Provided by: manpages-ru-dev_4.21.0-2_all bug

ИМЯ

       copy_file_range - копирует часть данных из одного файла в другой

LIBRARY

       Standard C library (libc, -lc)

СИНТАКСИС

       #define _GNU_SOURCE
       #include <unistd.h>

       ssize_t copy_file_range(int fd_in, off64_t *_Nullable off_in,
                               int fd_out, off64_t *_Nullable off_out,
                               size_t len, unsigned int flags);

ОПИСАНИЕ

       Системный   вызов  copy_file_range()   выполняет  внутриядерное  копирование  между  двумя
       файловыми дескрипторами без дополнительных накладных расходов по передаче данных из ядра в
       пользовательское  пространство  и  затем обратно в ядро. Он копирует до len байт данных из
       файлового  дескриптора  fd_in  источника   в   файловый   дескриптор   fd_out   приёмника,
       перезаписывая существующие данные внутри запрашиваемой области файла назначения.

       Следующая семантика применяется к off_in и подобная ей к off_out:

       •  Если  off_in  равно  NULL,  то  байты читаются из fd_in начиная с файлового смещения, а
          файловое смещение корректируется на количество скопированных байт.

       •  Если off_in не равно NULL, то off_in должно  указывать  на  буфер,  задающий  начальное
          смещение  в  fd_in,  из  которого  будут  читаться  байты.  Файловое  смещение fd_in не
          изменяется, но off_in изменяется соответствующим образом.

       Значения fd_in и fd_out могут ссылаться на один и тот же файл. Если это так, то диапазонам
       источника и приёмника нельзя перекрываться.

       Аргумент  flags предназначен для будущих расширений, а пока его значение должно быть равно
       0.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

       При  успешном  выполнении  copy_file_range()  возвращает  количество  скопированных  между
       файлами  байт.  Оно  может быть меньше запрашиваемой длины. Если файловое смещение fd_in в
       конце или за концом файла, то байты не копирются и copy_file_range() возвращает ноль.

       В случае ошибки copy_file_range() возвращает -1, а errno устанавливается в соответствующее
       значение.

ОШИБКИ

       EBADF  Один или оба файловых дескриптора недействительны.

       EBADF  Дескриптор fd_in не открыт на чтение или дескриптор fd_out не открыт на запись.

       EBADF  В  открытом  файловом  описании,  на  которое ссылается файловый дескриптор fd_out,
              установлен флаг O_APPEND (смотрите open(2)).

       EFBIG  Попытка  записать  в  позицию  вне  максимально  поддерживаемого  ядром   файлового
              смещения.

       EFBIG  Попытка  записи диапазона, который превышает разрешённый максимальный размер файла.
              Максимальный размер  файла  различается  в  реализациях  файловых  систем  и  может
              отличаться от разрешённого максимального файлового смещения.

       EFBIG  Попытка  записи,  выходящее  за ограничение ресурса процесса на размер файла. Также
              это может вызвать получение процессом сигнала SIGXFSZ.

       EINVAL Аргумент flags не равен 0.

       EINVAL Значения fd_in и fd_out ссылаются на один и тот же файл  и  диапазоны  источника  и
              приёмника перекрываются.

       EINVAL Значение fd_in или fd_out указывает на необычный файл.

       EIO    Во время копирования возникла низкоуровневая ошибка ввода-вывода.

       EISDIR Значение fd_in или fd_out указывает на каталог.

       ENOMEM Не хватает памяти.

       ENOSPC Недостаточно места на файловой системе назначения для завершения копирования.

       EOPNOTSUPP (since Linux 5.19)
              The filesystem does not support this operation.

       EOVERFLOW
              Запрошенный  диапазон  источника  и  приёмника  слишком большой для представления в
              указанном типе данных.

       EPERM  Значение fd_out ссылается на файл с постоянными данными (immutable).

       ETXTBSY
              Значение fd_in или fd_out указывает на активный файл подкачки.

       EXDEV (before Linux 5.3)
              The files referred to by fd_in and fd_out are not on the same filesystem.

       EXDEV (since Linux 5.19)
              The files referred to by 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.

ВЕРСИИ

       Системный вызов copy_file_range() впервые появился в Linux 4.5, но если он  недоступен,  в
       glibc 2.27 предоставляется эмуляция в пользовательском пространстве.

       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.

       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.

       Applications  should  target  the  behaviour and requirements of Linux 5.19, that was also
       backported to earlier stable kernels.

СТАНДАРТЫ

       Системный вызов copy_file_range() является нестандартным расширением Linux и GNU.

ЗАМЕЧАНИЯ

       Если файл fd_in является разреженным (sparse), то copy_file_range() может расширить  дыры,
       существующие  в  запрашиваемой области. Пользователи могут получить преимущество от вызова
       copy_file_range() в цикле, и используя операции lseek(2) SEEK_DATA и SEEK_HOLE для  поиска
       расположений сегментов данных.

       Вызов   copy_file_range()   даёт  файловым  системам  возможность  реализовать  «ускорение
       копирования»,  например,  использовать  ссылочные  связи  (т.  е.,  две  или  более  инод,
       использующих  общие  указатели  для  одного  копирования-при-записи  дисковых  блоков) или
       копирование-на-сервере (server-side-copy, в случае использования NFS).

ДЕФЕКТЫ

       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.

ПРИМЕРЫ

       #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;
           off64_t      len, ret;
           struct stat  stat;

           if (argc != 3) {
               fprintf(stderr, "Использование: %s <источник> <приёмник>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           fd_in = open(argv[1], O_RDONLY);
           if (fd_in == -1) {
               perror("открытие (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("открытие (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);
       }

СМ. ТАКЖЕ

       lseek(2), sendfile(2), splice(2)

ПЕРЕВОД

       Русский   перевод   этой    страницы    руководства    был    сделан    Azamat    Hackimov
       <azamat.hackimov@gmail.com>,  Dmitriy  S.  Seregin  <dseregin@59.ru>,  Dmitry Bolkhovskikh
       <d20052005@yandex.ru>,    Katrin    Kutepova    <blackkatelv@gmail.com>,    Yuri    Kozlov
       <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы  обнаружите  ошибки  в  переводе этой страницы руководства, пожалуйста, отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.