copy_file_range(2) System Calls Manual copy_file_range(2) NAZWA copy_file_range - kopiuje zakres danych z jednego pliku do drugiego BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include ssize_t copy_file_range(int fd_in, off_t *_Nullable off_in, int fd_out, off_t *_Nullable off_out, size_t size, unsigned int flags); OPIS Wywolanie systemowe copy_file_range() przeprowadza kopiowanie wewnatrz jadra pomiedzy dwoma deskryptorami plikow, bez dodatkowego kosztu transferu danych z jadro do przestrzeni uzytkownika, a nastepnie z powrotem do jadra. Kopiuje maksymalnie size bajtow danych ze zrodlowego deskryptora pliku fd_in do docelowego deskryptora pliku fd_out, nadpisujac wszelkie dane, ktore istnialy w zadanym zakresie pliku docelowego. off_in jest objete nastepujaca semantyka i podobne stwierdzenia odnosza sie do off_out: o Jesli off_in wynosi NULL, to bajty sa odczytywane z fd_in poczawszy od przesuniecia pliku, a przesuniecie pliku jest dostosowywane o liczbe skopiowanych bajtow. o Jesli off_in nie wynosi NULL, to off_in musi wskazywac na bufor okreslajacy poczatkowe przesuniecie, od ktorego zostana odczytane bajty z fd_in. Przesuniecie pliku fd_in nie jest zmieniane, ale off_in jest odpowiednio dostosowywane. fd_in i fd_out moga odnosic sie do tego samego pliku. Jesli odnosza sie do tego samego pliku, to zakres zrodlowy i docelowy nie moga na siebie nachodzic. Argument flags jest przeznaczony na przyszle rozszerzenia i obecnie musi byc ustawiony na 0. WARTOSC ZWRACANA Po pomyslnym zakonczeniu, copy_file_range() zwroci liczbe bajtow skopiowanych pomiedzy dwoma plikami. Moze byc to rozmiar mniejszy od pierwotnie zadanego. Jesli przesuniecie pliku fd_in znajduje sie na koncu, lub za koncem, pliku, to nie sa kopiowane zadne bajty, a copy_file_range() zwraca zero. W razie wystapienia bledu copy_file_range zwraca -1 i ustawia errno, wskazujac blad. BLEDY EBADF Jeden lub wiecej deskryptorow plikow nie jest prawidlowych. EBADF fd_in nie jest otwarty do odczytu; albo fd_out nie jest otwarty do zapisu. EBADF Znacznik O_APPEND jest ustawiony na opis otwartego pliku (ODF, zob. open(2)), do ktorego odnosi sie deskryptor pliku fd_out. EFBIG Podjeto probe zapisu w pozycji poza maksymalnym przesunieciem pliku obslugiwanym przez jadro. EFBIG Podjeto probe zapisu zakresu, ktory przekracza maksymalny dopuszczalny rozmiar pliku. Maksymalny rozmiar pliku rozni sie pomiedzy implementacjami systemow plikow i moze byc inny niz maksymalne dopuszczalne przesuniecie pliku. EFBIG Podjeto probe zapisu poza limit zasobu procesu dotyczacy rozmiaru pliku. Moze to tez spowodowac otrzymanie przez proces sygnalu SIGXFSZ. EINVAL Argument flags nie wynosi 0. EINVAL fd_in i fd_out odnosza sie do tego samego pliku, a zrodlowy i docelowy zakres nachodza na siebie. EINVAL fd_in albo fd_out nie jest zwyklym plikiem. EIO Przy kopiowaniu wystapil niskopoziomowy blad wejscia/wyjscia. EISDIR fd_in albo fd_out odnosza sie do katalogu. ENOMEM Brak pamieci. ENOSPC Na docelowym systemie plikow nie ma wystarczajaco duzo miejsca, aby ukonczyc kopiowanie. EOPNOTSUPP (od Linuksa 5.19) System plikow nie obsluguje tej operacji. EOVERFLOW Zadany zakres zrodlowy lub docelowy jest zbyt duzy, aby dalo sie go przedstawic w podanych typach danych. EPERM fd_out odnosi sie do niezmiennego pliku (ang. immutable). ETXTBSY fd_in albo fd_out odnosza sie do aktywnego pliku wymiany. EXDEV (przed Linuksem 5.3) Pliki, do ktorych odnosza sie fd_in i fd_out nie sa polozone w tym samym systemie plikow. EXDEV (od Linuksa 5.19) Pliki, do ktorych odnosza sie fd_in i fd_out nie sa polozone w tym samym systemie plikow, a zrodlowy i docelowy system plikow nie jest tego samego typu lub nie obsluguje kopii pomiedzy systemami plikow. WERSJE W Linuksie 5.3 doszlo do znaczacej modyfikacji implementacji w jadrze. Jasno zdefiniowano miejsca w API, ktorym wczesniej tego brakowalo, a granice API sa znacznie scislej sprawdzane, niz we wczesniejszych jadrach. Od Linuksa 5.19, mozliwe jest kopiowanie pomiedzy systemami plikow, jesli oba sa tego samego typu i dany system plikow zaimplementowal wsparcie tej operacji. W USTERKACH opisano zachowanie przed Linuksem 5.19. Aplikacje powinny dostosowac sie do zachowania i wymogow Linuksa 5.19, ktore zostalo rowniez przeportowane na wczesniejsze stabilne jadra. STANDARDY Linux, GNU. HISTORIA Linux 4.5, lecz glibc 2.27 dostarcza emulacje w przestrzeni uzytkownika tam, gdzie wywolanie nie jest dostepne. UWAGI Jesli fd_in jest rzadkim (ang. sparse) plikiem, to copy_file_range() moze wykroczyc poza istniejace dziury w zadanym zakresie. Uzytkownicy moga zechciec wywolywac copy_file_range() w petli, korzystajac z operacji SEEK_DATA i SEEK_HOLE wywolania lseek(2), aby odnalezc polozenie segmentow danych. copy_file_range() daje systemom plikow sposobnosc na implementacje technik ,,przyspieszonego kopiowania", takich jak korzystanie z dowiazan lekkich (reflinkow tj. dwoch lub wiecej i-wezlow, ktore dziela wskazniki do tych samych blokow dyskowych kopii przy zapisie) lub kopiowania po stronie serwera (w przypadku NFS). _FILE_OFFSET_BITS powinno byc zdefiniowane jako 64 w kodzie, ktory uzywa wartosci off_in lub off_out innych niz null lub takim, ktory przyjmuje adres copy_file_range, jesli kod ma byc przenosny na tradycyjne, 32-bitowe platformy x86 i ARM, w ktorych szerokosc off_t domyslnie wynosi 32 bity. USTERKI W Linuksie 5.3 do Linuksa 5.18, kopie pomiedzy systemami plikow byly zaimplementowane w jadrze, jesli operacja nie byla obslugiwana przez poszczegolne systemy plikow. Jednak w niektorych wirtualnych systemach plikow, kopiowanie sie nie powodzilo, a mimo to wywolanie wciaz zglaszalo sukces. PRZYKLADY #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include int main(int argc, char *argv[]) { int fd_in, fd_out; off_t size, ret; struct stat stat; if (argc != 3) { fprintf(stderr, "Uzycie: %s \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); } size = 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, size, 0); if (ret == -1) { perror("copy_file_range"); exit(EXIT_FAILURE); } size -= ret; } while (size > 0 && ret > 0); close(fd_in); close(fd_out); exit(EXIT_SUCCESS); } ZOBACZ TAKZE lseek(2), sendfile(2), splice(2) TLUMACZENIE Tlumaczenie niniejszej strony podrecznika: Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.15 17 maja 2025 r. copy_file_range(2)