mirror of https://github.com/mkerrisk/man-pages
288 lines
7.1 KiB
Groff
288 lines
7.1 KiB
Groff
.\"This manpage is Copyright (C) 2015 Anna Schumaker <Anna.Schumaker@Netapp.com>
|
|
.\"
|
|
.\" %%%LICENSE_START(VERBATIM)
|
|
.\" Permission is granted to make and distribute verbatim copies of this
|
|
.\" manual provided the copyright notice and this permission notice are
|
|
.\" preserved on all copies.
|
|
.\"
|
|
.\" Permission is granted to copy and distribute modified versions of
|
|
.\" this manual under the conditions for verbatim copying, provided that
|
|
.\" the entire resulting derived work is distributed under the terms of
|
|
.\" a permission notice identical to this one.
|
|
.\"
|
|
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
.\" manual page may be incorrect or out-of-date. The author(s) assume
|
|
.\" no responsibility for errors or omissions, or for damages resulting
|
|
.\" from the use of the information contained herein. The author(s) may
|
|
.\" not have taken the same level of care in the production of this
|
|
.\" manual, which is licensed free of charge, as they might when working
|
|
.\" professionally.
|
|
.\"
|
|
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
.\" the source, must acknowledge the copyright and authors of this work.
|
|
.\" %%%LICENSE_END
|
|
.\"
|
|
.TH COPY_FILE_RANGE 2 2021-03-22 "Linux" "Linux Programmer's Manual"
|
|
.SH NAME
|
|
copy_file_range \- Copy a range of data from one file to another
|
|
.SH SYNOPSIS
|
|
.nf
|
|
.B #define _GNU_SOURCE
|
|
.B #include <unistd.h>
|
|
.PP
|
|
.BI "ssize_t copy_file_range(int " fd_in ", off64_t *" off_in ,
|
|
.BI " int " fd_out ", off64_t *" off_out ,
|
|
.BI " size_t " len ", unsigned int " flags );
|
|
.fi
|
|
.SH DESCRIPTION
|
|
The
|
|
.BR copy_file_range ()
|
|
system call performs an in-kernel copy between two file descriptors
|
|
without the additional cost of transferring data from the kernel to user space
|
|
and then back into the kernel.
|
|
It copies up to
|
|
.I len
|
|
bytes of data from the source file descriptor
|
|
.I fd_in
|
|
to the target file descriptor
|
|
.IR fd_out ,
|
|
overwriting any data that exists within the requested range of the target file.
|
|
.PP
|
|
The following semantics apply for
|
|
.IR off_in ,
|
|
and similar statements apply to
|
|
.IR off_out :
|
|
.IP * 3
|
|
If
|
|
.I off_in
|
|
is NULL, then bytes are read from
|
|
.I fd_in
|
|
starting from the file offset, and the file offset is
|
|
adjusted by the number of bytes copied.
|
|
.IP *
|
|
If
|
|
.I off_in
|
|
is not NULL, then
|
|
.I off_in
|
|
must point to a buffer that specifies the starting
|
|
offset where bytes from
|
|
.I fd_in
|
|
will be read.
|
|
The file offset of
|
|
.I fd_in
|
|
is not changed, but
|
|
.I off_in
|
|
is adjusted appropriately.
|
|
.PP
|
|
.I fd_in
|
|
and
|
|
.I fd_out
|
|
can refer to the same file.
|
|
If they refer to the same file, then the source and target ranges are not
|
|
allowed to overlap.
|
|
.PP
|
|
The
|
|
.I flags
|
|
argument is provided to allow for future extensions
|
|
and currently must be set to 0.
|
|
.SH RETURN VALUE
|
|
Upon successful completion,
|
|
.BR copy_file_range ()
|
|
will return the number of bytes copied between files.
|
|
This could be less than the length originally requested.
|
|
If the file offset of
|
|
.I fd_in
|
|
is at or past the end of file, no bytes are copied, and
|
|
.BR copy_file_range ()
|
|
returns zero.
|
|
.PP
|
|
On error,
|
|
.BR copy_file_range ()
|
|
returns \-1 and
|
|
.I errno
|
|
is set to indicate the error.
|
|
.SH ERRORS
|
|
.TP
|
|
.B EBADF
|
|
One or more file descriptors are not valid.
|
|
.TP
|
|
.B EBADF
|
|
.I fd_in
|
|
is not open for reading; or
|
|
.I fd_out
|
|
is not open for writing.
|
|
.TP
|
|
.B EBADF
|
|
The
|
|
.B O_APPEND
|
|
flag is set for the open file description (see
|
|
.BR open (2))
|
|
referred to by the file descriptor
|
|
.IR fd_out .
|
|
.TP
|
|
.B EFBIG
|
|
An attempt was made to write at a position past the maximum file offset the
|
|
kernel supports.
|
|
.TP
|
|
.B EFBIG
|
|
An attempt was made to write a range that exceeds the allowed maximum file size.
|
|
The maximum file size differs between filesystem implementations and can be
|
|
different from the maximum allowed file offset.
|
|
.TP
|
|
.B EFBIG
|
|
An attempt was made to write beyond the process's file size resource limit.
|
|
This may also result in the process receiving a
|
|
.B SIGXFSZ
|
|
signal.
|
|
.TP
|
|
.B EINVAL
|
|
The
|
|
.I flags
|
|
argument is not 0.
|
|
.TP
|
|
.B EINVAL
|
|
.I fd_in
|
|
and
|
|
.I fd_out
|
|
refer to the same file and the source and target ranges overlap.
|
|
.TP
|
|
.B EINVAL
|
|
Either
|
|
.I fd_in
|
|
or
|
|
.I fd_out
|
|
is not a regular file.
|
|
.TP
|
|
.B EIO
|
|
A low-level I/O error occurred while copying.
|
|
.TP
|
|
.B EISDIR
|
|
Either
|
|
.I fd_in
|
|
or
|
|
.I fd_out
|
|
refers to a directory.
|
|
.TP
|
|
.B ENOMEM
|
|
Out of memory.
|
|
.TP
|
|
.B ENOSPC
|
|
There is not enough space on the target filesystem to complete the copy.
|
|
.TP
|
|
.B EOVERFLOW
|
|
The requested source or destination range is too large to represent in the
|
|
specified data types.
|
|
.TP
|
|
.B EPERM
|
|
.I fd_out
|
|
refers to an immutable file.
|
|
.TP
|
|
.B ETXTBSY
|
|
Either
|
|
.I fd_in
|
|
or
|
|
.I fd_out
|
|
refers to an active swap file.
|
|
.TP
|
|
.B EXDEV
|
|
The files referred to by
|
|
.IR fd_in " and " fd_out
|
|
are not on the same mounted filesystem (pre Linux 5.3).
|
|
.SH VERSIONS
|
|
The
|
|
.BR copy_file_range ()
|
|
system call first appeared in Linux 4.5, but glibc 2.27 provides a user-space
|
|
emulation when it is not available.
|
|
.\" https://sourceware.org/git/?p=glibc.git;a=commit;f=posix/unistd.h;h=bad7a0c81f501fbbcc79af9eaa4b8254441c4a1f
|
|
.PP
|
|
A major rework of the kernel implementation occurred in 5.3.
|
|
Areas of the API that weren't clearly defined were clarified and the API bounds
|
|
are much more strictly checked than on earlier kernels.
|
|
Applications should target the behaviour and requirements of 5.3 kernels.
|
|
.PP
|
|
First support for cross-filesystem copies was introduced in Linux 5.3.
|
|
Older kernels will return -EXDEV when cross-filesystem copies are attempted.
|
|
.SH CONFORMING TO
|
|
The
|
|
.BR copy_file_range ()
|
|
system call is a nonstandard Linux and GNU extension.
|
|
.SH NOTES
|
|
If
|
|
.I fd_in
|
|
is a sparse file, then
|
|
.BR copy_file_range ()
|
|
may expand any holes existing in the requested range.
|
|
Users may benefit from calling
|
|
.BR copy_file_range ()
|
|
in a loop, and using the
|
|
.BR lseek (2)
|
|
.BR SEEK_DATA
|
|
and
|
|
.BR SEEK_HOLE
|
|
operations to find the locations of data segments.
|
|
.PP
|
|
.BR copy_file_range ()
|
|
gives filesystems an opportunity to implement "copy acceleration" techniques,
|
|
such as the use of reflinks (i.e., two or more inodes that share
|
|
pointers to the same copy-on-write disk blocks)
|
|
or server-side-copy (in the case of NFS).
|
|
.SH EXAMPLES
|
|
.EX
|
|
#define _GNU_SOURCE
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int fd_in, fd_out;
|
|
struct stat stat;
|
|
off64_t len, ret;
|
|
|
|
if (argc != 3) {
|
|
fprintf(stderr, "Usage: %s <source> <destination>\en", argv[0]);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
fd_in = open(argv[1], O_RDONLY);
|
|
if (fd_in == \-1) {
|
|
perror("open (argv[1])");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if (fstat(fd_in, &stat) == \-1) {
|
|
perror("fstat");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
len = stat.st_size;
|
|
|
|
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC, 0644);
|
|
if (fd_out == \-1) {
|
|
perror("open (argv[2])");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
do {
|
|
ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
|
|
if (ret == \-1) {
|
|
perror("copy_file_range");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
len \-= ret;
|
|
} while (len > 0 && ret > 0);
|
|
|
|
close(fd_in);
|
|
close(fd_out);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
.EE
|
|
.SH SEE ALSO
|
|
.BR lseek (2),
|
|
.BR sendfile (2),
|
|
.BR splice (2)
|