| copy_file_range(2) | System Calls Manual | copy_file_range(2) |
copy_file_range - kopiuje zakres danych z jednego pliku do drugiego
Standardowa biblioteka C (libc, -lc)
#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include <unistd.h>
ssize_t copy_file_range(int fd_in, off_t *_Nullable off_in,
int fd_out, off_t *_Nullable off_out,
size_t len, unsigned int flags);
Wywołanie systemowe copy_file_range() przeprowadza kopiowanie wewnątrz jądra pomiędzy dwoma deskryptorami plików, bez dodatkowego kosztu transferu danych z jądro do przestrzeni użytkownika, a następnie z powrotem do jądra. Kopiuje maksymalnie len bajtów danych ze źródłowego deskryptora pliku fd_in do docelowego deskryptora pliku fd_out, nadpisując wszelkie dane, które istniały w żądanym zakresie pliku docelowego.
off_in jest objęte następującą semantyką i podobne stwierdzenia odnoszą się do off_out:
fd_in i fd_out mogą odnosić się do tego samego pliku. Jeśli odnoszą się do tego samego pliku, to zakres źródłowy i docelowy nie mogą na siebie nachodzić.
Argument flags jest przeznaczony na przyszłe rozszerzenia i obecnie musi być ustawiony na 0.
Po pomyślnym zakończeniu, copy_file_range() zwróci liczbę bajtów skopiowanych pomiędzy dwoma plikami. Może być to długość mniejsza od pierwotnie żądanej. Jeśli przesunięcie pliku fd_in znajduje się na końcu, lub za końcem, pliku, to nie są kopiowane żadne bajty, a copy_file_range() zwraca zero.
W razie wystąpienia błędu copy_file_range zwraca -1 i ustawia errno, wskazując błąd.
W Linuksie 5.3 doszło do znaczącej modyfikacji implementacji w jądrze. Jasno zdefiniowano miejsca w API, którym wcześniej tego brakowało, a granice API są znacznie ściślej sprawdzane, niż we wcześniejszych jądrach.
Od Linuksa 5.19, możliwe jest kopiowanie pomiędzy systemami plików, jeśli oba są tego samego typu i dany system plików zaimplementował wsparcie tej operacji. W USTERKACH opisano zachowanie przed Linuksem 5.19.
Aplikacje powinny dostosować się do zachowania i wymogów Linuksa 5.19, które zostało również przeportowane na wcześniejsze stabilne jądra.
Linux, GNU.
Linux 4.5, lecz glibc 2.27 dostarcza emulację w przestrzeni użytkownika tam, gdzie wywołanie nie jest dostępne.
Jeśli fd_in jest rzadkim (ang. sparse) plikiem, to copy_file_range() może wykroczyć poza istniejące dziury w żądanym zakresie. Użytkownicy mogą zechcieć wywoływać copy_file_range() w pętli, korzystając z operacji SEEK_DATA i SEEK_HOLE wywołania lseek(2), aby odnaleźć położenie segmentów danych.
copy_file_range() daje systemom plików sposobność na implementację technik „przyspieszonego kopiowania”, takich jak korzystanie z dowiązań lekkich (reflinków tj. dwóch lub więcej i-węzłów, które dzielą wskaźniki do tych samych bloków dyskowych kopii przy zapisie) lub kopiowania po stronie serwera (w przypadku NFS).
_FILE_OFFSET_BITS powinno być zdefiniowane jako 64 w kodzie, który używa wartości off_in lub off_out innych niż null lub takim, który przyjmuje adres copy_file_range, jeśli kod ma być przenośny na tradycyjne, 32-bitowe platformy x86 i ARM, w których szerokość off_t domyślnie wynosi 32 bity.
W Linuksie 5.3 do Linuksa 5.18, kopie pomiędzy systemami plików były zaimplementowane w jądrze, jeśli operacja nie była obsługiwana przez poszczególne systemy plików. Jednak w niektórych wirtualnych systemach plików, kopiowanie się nie powodziło, a mimo to wywołanie wciąż zgłaszało sukces.
#define _GNU_SOURCE
#define _FILE_OFFSET_BITS 64
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.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, "Użycie: %s <źródło> <cel>\n", 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);
}
Tłumaczenie niniejszej strony podręcznika: Michał Kułach <michal.kulach@gmail.com>
Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.
Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.
| 15 czerwca 2024 r. | Linux man-pages 6.9.1 |