Linux repositories inspector

copy_file_range(2) - Russkiy

Linux
2019-03-06

man-pages-ru

Russian man pages from the Linux Documentation Project

manpages-dev

Manual pages about using GNU/Linux for development

man-pages

Linux kernel and C library user-space interface documentation

ИМЯ

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

ОБЗОР

#define _GNU_SOURCE
#include <unistd.h>

ssize_t copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *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 Недостаточно места на файловой системе назначения для завершения копирования.
EOVERFLOW
Запрошенный диапазон источника и приёмника слишком большой для представления в указанном типе данных.
EPERM Значение fd_out ссылается на файл с постоянными данными (immutable).
TXTBSY Значение fd_in или fd_out указывает на активный файл подкачки.
EXDEV Файлы, на которые ссылаются file_in и file_out, находятся не в одной смонтированной файловой системе (до Linux 5.3).

ВЕРСИИ

Системный вызов copy_file_range() впервые появился в Linux 4.5, но если он недоступен, в glibc 2.27 предоставляется эмуляция в пользовательском пространстве.
В ядре версии 5.3 произошли значительные перемены. Уточнены области API, которые были нечётно определены, и границы API теперь строже проверяются, по сравнению с ранними ядрами. Приложения должны следовать поведению и требованиям ядер 5.3.
В Linux 5.3 появилась поддержка копирования между файловыми системами. В старых ядрах при попытках копирования между файловыми системами возвращается ошибка -EXDEV.

СООТВЕТСТВИЕ СТАНДАРТАМ

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

ЗАМЕЧАНИЯ

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

ПРИМЕР

#define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/syscall.h> #include <unistd.h>
/ * В версиях glibc до 2.27, мы должны ссылаться на copy_file_range ()
используя syscall(2) * /
static loff_t copy_file_range(int fd_in, loff_t *off_in, int fd_out,
loff_t *off_out, size_t len, unsigned int flags) {
return syscall(__NR_copy_file_range, fd_in, off_in, fd_out,
off_out, len, flags); }
int main(int argc, char **argv) {
int fd_in, fd_out;
struct stat stat;
loff_t len, ret;
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); }

СМОТРИТЕ ТАКЖЕ

⇧ Top