summaryrefslogtreecommitdiffstats
path: root/man/man2/copy_file_range.2
diff options
context:
space:
mode:
Diffstat (limited to 'man/man2/copy_file_range.2')
-rw-r--r--man/man2/copy_file_range.2307
1 files changed, 307 insertions, 0 deletions
diff --git a/man/man2/copy_file_range.2 b/man/man2/copy_file_range.2
new file mode 100644
index 000000000..913d94345
--- /dev/null
+++ b/man/man2/copy_file_range.2
@@ -0,0 +1,307 @@
+.\"This manpage is Copyright (C) 2015 Anna Schumaker <Anna.Schumaker@Netapp.com>
+.\"
+.\" SPDX-License-Identifier: Linux-man-pages-copyleft
+.\"
+.TH copy_file_range 2 (date) "Linux man-pages (unreleased)"
+.SH NAME
+copy_file_range \- Copy a range of data from one file to another
+.SH LIBRARY
+Standard C library
+.RI ( libc ", " \-lc )
+.SH SYNOPSIS
+.nf
+.B #define _GNU_SOURCE
+.B #define _FILE_OFFSET_BITS 64
+.B #include <unistd.h>
+.P
+.BI "ssize_t copy_file_range(int " fd_in ", off_t *_Nullable " off_in ,
+.BI " int " fd_out ", off_t *_Nullable " 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.
+.P
+The following semantics apply for
+.IR off_in ,
+and similar statements apply to
+.IR off_out :
+.IP \[bu] 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 \[bu]
+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.
+.P
+.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.
+.P
+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.
+.P
+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
+.BR EOPNOTSUPP " (since Linux 5.19)"
+.\" commit 868f9f2f8e004bfe0d3935b1976f625b2924893b
+The filesystem does not support this operation.
+.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
+.BR EXDEV " (before Linux 5.3)"
+.\" commit 5dae222a5ff0c269730393018a5539cc970a4726
+The files referred to by
+.IR fd_in " and " fd_out
+are not on the same filesystem.
+.TP
+.BR EXDEV " (since Linux 5.19)"
+.\" commit 868f9f2f8e004bfe0d3935b1976f625b2924893b
+The files referred to by
+.IR fd_in " and " fd_out
+are not on the same filesystem,
+and the source and target filesystems are not of the same type,
+or do not support cross-filesystem copy.
+.SH VERSIONS
+A major rework of the kernel implementation occurred in Linux 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.
+.P
+Since Linux 5.19,
+cross-filesystem copies can be achieved
+when both filesystems are of the same type,
+and that filesystem implements support for it.
+See BUGS for behavior prior to Linux 5.19.
+.P
+Applications should target the behaviour and requirements of Linux 5.19,
+that was also backported to earlier stable kernels.
+.SH STANDARDS
+Linux, GNU.
+.SH HISTORY
+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
+.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)
+.B SEEK_DATA
+and
+.B SEEK_HOLE
+operations to find the locations of data segments.
+.P
+.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).
+.P
+.B _FILE_OFFSET_BITS
+should be defined to be 64 in code that uses non-null
+.I off_in
+or
+.I off_out
+or that takes the address of
+.BR copy_file_range ,
+if the code is intended to be portable
+to traditional 32-bit x86 and ARM platforms where
+.BR off_t 's
+width defaults to 32 bits.
+.SH BUGS
+In Linux 5.3 to Linux 5.18,
+cross-filesystem copies were implemented by the kernel,
+if the operation was not supported by individual filesystems.
+However, on some virtual filesystems,
+the call failed to copy, while still reporting success.
+.SH EXAMPLES
+.\" SRC BEGIN (copy_file_range.c)
+.EX
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+#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;
+ off_t len, ret;
+ struct stat stat;
+\&
+ 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
+.\" SRC END
+.SH SEE ALSO
+.BR lseek (2),
+.BR sendfile (2),
+.BR splice (2)