table of contents
- bookworm-backports 1:4.27.0-1~bpo12+1
- testing 1:4.27.0-1
- unstable 1:4.27.0-1
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¶
- EBADF
- Jeden lub więcej deskryptorów plików nie jest prawidłowych.
- 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 którego odnosi się deskryptor pliku fd_out.
- EFBIG
- Podjęto próbę zapisu w pozycji poza maksymalnym przesunięciem pliku obsługiwanym przez jądro.
- EFBIG
- 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.
- EFBIG
- Podjęto próbę zapisu poza limit zasobu procesu dotyczący rozmiaru pliku. Może to też spowodować otrzymanie przez proces sygnału SIGXFSZ.
- EINVAL
- Argument flags nie wynosi 0.
- EINVAL
- fd_in i fd_out odnoszą się do tego samego pliku, a źródłowy i docelowy zakres nachodzą na siebie.
- EINVAL
- fd_in albo fd_out nie jest zwykłym plikiem.
- EIO
- Przy kopiowaniu wystąpił niskopoziomowy błąd wejścia/wyjścia.
- EISDIR
- fd_in albo fd_out odnoszą się do katalogu.
- ENOMEM
- Brak pamięci.
- ENOSPC
- Na docelowym systemie plików nie ma wystarczająco dużo miejsca, aby ukończyć kopiowanie.
- EOPNOTSUPP (od Linuksa 5.19)
- System plików nie obsługuje tej operacji.
- EOVERFLOW
- Żądany zakres źródłowy lub docelowy jest zbyt duży, aby dało się go przedstawić w podanych typach danych.
- EPERM
- fd_out odnosi się do niezmiennego pliku (ang. immutable).
- ETXTBSY
- fd_in albo fd_out odnoszą się do aktywnego pliku wymiany.
- EXDEV (przed Linuksem 5.3)
- Pliki, do których odnoszą się fd_in i fd_out nie są położone w tym samym systemie plików.
- EXDEV (od Linuksa 5.19)
- 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¶
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 |