diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:40:15 +0000 |
commit | 399644e47874bff147afb19c89228901ac39340e (patch) | |
tree | 1c4c0b733f4c16b5783b41bebb19194a9ef62ad1 /man2/copy_file_range.2 | |
parent | Initial commit. (diff) | |
download | manpages-399644e47874bff147afb19c89228901ac39340e.tar.xz manpages-399644e47874bff147afb19c89228901ac39340e.zip |
Adding upstream version 6.05.01.upstream/6.05.01
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'man2/copy_file_range.2')
-rw-r--r-- | man2/copy_file_range.2 | 307 |
1 files changed, 307 insertions, 0 deletions
diff --git a/man2/copy_file_range.2 b/man2/copy_file_range.2 new file mode 100644 index 0000000..8bea2e8 --- /dev/null +++ b/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 2023-07-15 "Linux man-pages 6.05.01" +.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> +.PP +.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. +.PP +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. +.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 +.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. +.PP +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. +.PP +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. +.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). +.PP +.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) |