Scroll to navigation

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)

SKŁADNIA

#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);

OPIS

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:

Jeśli off_in wynosi NULL, to bajty są odczytywane z fd_in począwszy od przesunięcia pliku, a przesunięcie pliku jest dostosowywane o liczbę skopiowanych bajtów.
Jeśli off_in nie wynosi NULL, to off_in musi wskazywać na bufor określający początkowe przesunięcie, od którego zostaną odczytane bajty z fd_in. Przesunięcie pliku fd_in nie jest zmieniane, ale off_in jest odpowiednio dostosowywane.

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.

WARTOŚĆ ZWRACANA

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.

BŁĘDY

Jeden lub więcej deskryptorów plików nie jest prawidłowych.
fd_in nie jest otwarty do odczytu; albo fd_out nie jest otwarty do zapisu.
Znacznik O_APPEND jest ustawiony na opis otwartego pliku (ODF, zob. open(2)), do którego odnosi się deskryptor pliku fd_out.
Podjęto próbę zapisu w pozycji poza maksymalnym przesunięciem pliku obsługiwanym przez jądro.
Podjęto próbę zapisu zakresu, który przekracza maksymalny dopuszczalny rozmiar pliku. Maksymalny rozmiar pliku różni się pomiędzy implementacjami systemów plików i może być inny niż maksymalne dopuszczalne przesunięcie pliku.
Podjęto próbę zapisu poza limit zasobu procesu dotyczący rozmiaru pliku. Może to też spowodować otrzymanie przez proces sygnału SIGXFSZ.
Argument flags nie wynosi 0.
fd_in i fd_out odnoszą się do tego samego pliku, a źródłowy i docelowy zakres nachodzą na siebie.
fd_in albo fd_out nie jest zwykłym plikiem.
Przy kopiowaniu wystąpił niskopoziomowy błąd wejścia/wyjścia.
fd_in albo fd_out odnoszą się do katalogu.
Brak pamięci.
Na docelowym systemie plików nie ma wystarczająco dużo miejsca, aby ukończyć kopiowanie.
System plików nie obsługuje tej operacji.
Żądany zakres źródłowy lub docelowy jest zbyt duży, aby dało się go przedstawić w podanych typach danych.
fd_out odnosi się do niezmiennego pliku (ang. immutable).
fd_in albo fd_out odnoszą się do aktywnego pliku wymiany.
Pliki, do których odnoszą się fd_in i fd_out nie są położone w tym samym systemie plików.
Pliki, do których odnoszą się fd_in i fd_out nie są położone w tym samym systemie plików, a źródłowy i docelowy system plików nie jest tego samego typu lub nie obsługuje kopii pomiędzy systemami plików.

WERSJE

Wywołanie systemowe copy_file_range() pojawiło się pierwotnie w Linuksie 4.5, lecz glibc 2.27 dostarcza emulację w przestrzeni użytkownika tam, gdzie wywołanie nie jest dostępne.

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.

STANDARDY

Wywołanie systemowe copy_file_range() jest niestandardowym rozszerzeniem Linuksa i GNU.

UWAGI

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).

USTERKI

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.

PRZYKŁADY

#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, "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); }

ZOBACZ TAKŻE

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

TŁUMACZENIE

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.

5 lutego 2023 r. Linux man-pages 6.03