rename, renameat, renameat2 - zmienia nazwę lub
położenie pliku
Standardowa biblioteka C (libc, -lc)
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
#include <fcntl.h> /* Definicja stałych AT_* */
#include <stdio.h>
int renameat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath);
int renameat2(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, unsigned int flags);
renameat():
Od glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Przed glibc 2.10:
_ATFILE_SOURCE
renameat2():
_GNU_SOURCE
rename() zmienia nazwę pliku, przenosząc go
pomiędzy katalogami, jeśli to konieczne. Nie wpływa to
na wszelkie inne zwykłe (twarde) dowiązania do pliku (jak
utworzone przez link(2)). Nie ma wpływu również
na deskryptory pliku otwartego na oldpath.
Na to, czy operacja zmiany nazwy się powiedzie,
wpływa wiele ograniczeń: zob. BŁĘDY
niżej.
Jeśli newpath już istnieje, zostanie
zastąpiona w sposób niepodzielny tak, że w
żadnym momencie, gdy inny proces spróbuje uzyskać
dostęp do newpath, nie zastanie jej nieistniejącej.
Jednak prawdopodobnie wystąpi okno czasowe, w którym
oldpath i newpath będą odnosić się
do przemianowywanego pliku.
Jeśli oldpath i newpath są
istniejącymi dowiązaniami zwykłymi (twardymi),
odnoszącymi się do tego pliku, to rename() nic nie robi
i zwraca status powodzenia.
Jeśli newpath istnieje, lecz operacja z
jakiegoś powodu się nie powiedzie, rename() daje
gwarancję pozostawienia wystąpienia newpath bez
zmian.
oldpath może określać katalog. W tym
przypadku, newpath musi albo nie istnieć, albo musi
określać pusty katalog.
Jeśli oldpath odnosi się do dowiązania
symbolicznego, dowiązaniu temu zostanie zmieniona nazwa; jeśli
newpath odnosi się do dowiązania symbolicznego,
dowiązanie zostanie nadpisane.
Wywołanie systemowe renameat() operuje w
dokładnie taki sam sposób jak rename(), z
wyjątkiem różnic opisanych tutaj.
Jeśli ścieżka podana w oldpath jest
względna, jest to interpretowane w odniesieniu do katalogu do
którego odnosi się deskryptor pliku olddirfd (zamiast w
odniesieniu do bieżącego katalogu roboczego procesu
wywołującego, jak w stosunku do ścieżek
względnych robi to rename()).
Jeśli oldpath jest względna a olddirfd
ma wartość specjalną AT_FDCWD, to oldpath
jest interpretowana w odniesieniu do bieżącego katalogu
roboczego procesu wywołującego (jak rename()).
Jeśli oldpath jest bezwzględna, to
olddirfd jest ignorowane.
Interpretacja newpath jest taka sama jak oldpath, z
tym wyjątkiem, że ścieżka względna jest
interpretowana względem katalogu, do którego odnosi się
deskryptor pliku newdirfd.
Więcej informacji o potrzebie wprowadzenia
renameat() można znaleźć w podręczniku
openat(2).
renameat2() ma dodatkowy argument flags.
Wywołanie renameat2() z zerowym argumentem flags jest
równoważne renameat().
Argument flags jest maską bitową
składającą się z zera lub więcej
następujących znaczników:
- RENAME_EXCHANGE
- Niepodzielnie wymienia oldpath i newpath. Obie
ścieżki muszą istnieć, lecz mogą
być różnego typu (np. jedna może być
niepustym katalogiem, a druga dowiązaniem symbolicznym).
- RENAME_NOREPLACE
- Nie nadpisuje newpath przy zmianie nazwy. Zwraca
błąd, gdy newpath już istnieje.
- RENAME_NOREPLACE nie można łączyć z
RENAME_EXCHANGE.
- RENAME_NOREPLACE wymaga obsługi w systemie plików.
Pojawiała się ona zgodnie z poniższym wykazem:
- •
- ext4 (Linux 3.15);
- •
- btrfs, tmpfs i cifs (Linux 3.17);
- •
- xfs (Linux 4.0);
- •
- Obsługę wielu innych systemów plików dodano w
Linuksie 4.9, w tym ext2, minix, reiserfs, jfs, vfat i bpf.
- RENAME_WHITEOUT
(od Linuksa 3.18)
- Operacja ta ma sens tylko w implementacjach systemu plików typu
nakładka/unia (overlay/union).
- Podanie RENAME_WHITEOUT tworzy obiekt
„zaciemniający” w miejscu źródła
zmiany nazwy w momencie dokonywania zmiany nazwy. Cała operacja
jest niepodzielna, tak więc jeśli zmiana nazwy się
powiedzie, to utworzone zostanie również zaciemnienie.
- Obiekt „zaciemniający” ma specjalne znaczenie w
systemach plików typu nakładka/unia. Istnieje tam wiele
warstw i jedyną, która jest kiedykolwiek modyfikowana, jest
najwyższa. Zaciemnienie na wyższej warstwie, efektywnie
ukrywa odpowiedni plik w niższej warstwie, dając
wrażenie, że plik nie istnieje.
- Jeśli plikowi istniejącemu w niższej warstwie
zmieniana jest nazwa, plik jest najpierw kopiowany w górę
(jeśli nie jest jeszcze na wyższej warstwie), a
następnie zmieniana jest mu nazwa na wyższej warstwie,
będącej do odczytu i zapisu. W tym samym czasie plik
źródłowy musi być „zaciemniony”
(dzięki czemu wersja pliku źródłowego w
niższej warstwie staje się niewidoczna). Cała
operacja musi być niepodzielna.
- Gdy nie jest częścią nakładki/unii,
zaciemnienie jest widoczne jako urządzenie znakowe z numerem
urządzenia {0,0} (proszę zauważyć, że
inne implementacje nakładki/unii mogą używać
odmiennych metod do przechowywania zaciemnionych wpisów; w
szczególności, unie BSD korzystają z oddzielnego typu
i-węzła, który, choć obsługiwany przez
niektóre systemy plików dostępne w Linuksie, takie
jak CODA i XFS, jest ignorowany przez zaciemniający kod
jądra, przynajmniej według stanu na Linuksa 4.19).
- RENAME_WHITEOUT wymaga tych samym przywilejów, co utworzenie
węzła urządzenia (tj. przywileju
CAP_MKNOD).
- RENAME_WHITEOUT nie można łączyć z
RENAME_EXCHANGE.
- RENAME_WHITEOUT musi być obsługiwane przez
przedmiotowy system plików. Pośród
obsługujących systemów plików są: tmpfs
(od Linuksa 3.18), ext4 (od Linuksa 3.18), XFS (od Linuksa 4.1), f2fs (od
Linuksa 4.2), btrfs (od Linuksa 4.7) oraz ubifs (od Linuksa 4.9).
Po pomyślnym zakończeniu zwracane jest zero. Po
błędzie zwracane jest -1 i ustawiane errno,
wskazując błąd.
- EACCES
- Odmówiono uprawnienia zapisu dla katalogu zawierającego
oldpath lub newpath; albo odmówiono uprawnienia
przeszukiwania dla jednego z katalogów w przedrostku
ścieżki oldpath lub newpath; albo
oldpath jest katalogiem i nie zezwala na uprawnienie zapisu
(potrzebne do zaktualizowania wpisu ..). Zob. też
path_resolution(7).
- EBUSY
- Zmiana nazwy nie powiodła się, ponieważ
oldpath lub newpath jest katalogiem, który jest
używany przez jakiś proces (być może jako
bieżący katalog roboczy albo katalog główny,
albo ponieważ był otwarty do odczytu) lub jest
używany przez system (np. jako punkt montowania), a system
uważa to za błąd (proszę
zauważyć, że nie ma obowiązku zwracania w
takim przypadku EBUSY — nie ma niczego złego w
dokonaniu wówczas zmiany nazwy — lecz można
zwrócić EBUSY, jeśli system nie może
jednak obsłużyć takich sytuacji).
- EDQUOT
- Przydział bloków dyskowych użytkownika
dotyczący systemu plików został wyczerpany.
- EFAULT
- oldpath lub newpath wskazuje poza dostępną dla
użytkownika przestrzeń adresową.
- EINVAL
- Nowa ścieżka zawierała przedrostek
ścieżki starej lub, ogólniej, próbowano
utworzyć katalog lub podkatalog siebie samego.
- EISDIR
- newpath jest istniejącym katalogiem, lecz oldpath nie
jest katalogiem.
- ELOOP
- Podczas rozwiązywania oldpath lub newpath napotkano
zbyt wiele dowiązań symbolicznych.
- EMLINK
- Do oldpath osiągnięto już maksymalną
dowiązań lub był to katalog, a katalog
zawierający newpath ma maksymalną liczbę
dowiązań.
- ENAMETOOLONG
- oldpath lub newpath było zbyt długie.
- ENOENT
- Dowiązanie o nazwie oldpath nie istnieje; lub
składowa katalogu w newpath nie istnieje; lub oldpath
albo newpath jest łańcuchem pustym.
- ENOMEM
- Brak pamięci jądra.
- ENOSPC
- Na urządzeniu zawierającym plik nie ma miejsca na kolejny
wpis w katalogu.
- ENOTDIR
- Składowa używana jako katalog w oldpath lub
newpath nie jest faktycznie katalogiem; lub oldpath jest
katalogiem, a newpath istnieje, lecz nie jest katalogiem.
- ENOTEMPTY lub
EEXIST
- newpath jest niepustym katalogiem tj. zawiera wpisy inne niż
„.” oraz „..”.
- EPERM lub
EACCES
- Katalog zawierający oldpath ma ustawiony bit lepkości
(S_ISVTX), a efektywny identyfikator użytkownika procesu nie
jest ani identyfikatorem użytkownika usuwanego pliku, ani katalogu
go zawierającego oraz proces nie jest uprzywilejowany (Linux: nie
ma przywileju CAP_FOWNER); albo: newpath jest
istniejącym plikiem, katalog go zawierający ma ustawiony bit
lepkości, a efektywny identyfikator użytkownika procesu nie
jest ani identyfikatorem użytkownika usuwanego pliku, ani katalogu
go zawierającego oraz proces nie jest uprzywilejowany (Linux: nie
ma przywileju CAP_FOWNER); albo: system plików
zawierający oldpath nie obsługuje zmiany nazwy
żądanego typu.
- EROFS
- Plik leży w systemie plików tylko do odczytu.
- EXDEV
- oldpath i newpath nie są położone w
zamontowanym tak samo systemie plików (Linux zezwala na
zamontowanie systemu plików w wielu punktach, ale rename()
nie działa poprzez różne punkty montowania, nawet
jeśli w obu zamontowany jest ten sam system plików).
W przypadku renameat() i renameat2() mogą
wystąpić następujące, dodatkowe
błędy:
- EBADF
- oldpath (newpath) jest względna, lecz olddirfd
(newdirfd) nie jest prawidłowym deskryptorem pliku.
- ENOTDIR
- oldpath jest względna, a olddirfd jest deskryptorem
pliku odnoszącym się do pliku innego niż katalog; lub
analogicznie dla newpath i newdirfd
Następujące dodatkowe błędy
mogą wystąpić w przypadku renameat2():
- EEXIST
- flags zawiera RENAME_NOREPLACE, a newpath już
istnieje.
- EINVAL
- We flags podano nieprawidłowy znacznik.
- EINVAL
- We flags podano równocześnie RENAME_NOREPLACE
i RENAME_EXCHANGE.
- EINVAL
- We flags podano równocześnie RENAME_WHITEOUT i
RENAME_EXCHANGE.
- EINVAL
- System plików nie obsługuje jednego ze znaczników z
flags.
- ENOENT
- flags zawiera RENAME_EXCHANGE, a newpath nie
istnieje.
- EPERM
- We flags podano RENAME_WHITEOUT, lecz
wywołujący nie ma przywileju CAP_MKNOD.
- rename()
- 4.3BSD, C89, POSIX.1-2001.
- renameat()
- Linux 2.6.16, glibc 2.4.
- renameat2()
- Linux 3.15, glibc 2.28.
W starszych jądrach, gdzie renameat() jest
niedostępne, funkcja opakowująca korzysta zapasowo z
rename(). Gdy oldpath i newpath są
ścieżkami względnymi, glibc tworzy
ścieżki w oparciu o dowiązania symboliczne w
/proc/self/fd, które są związane z argumentami
olddirfd i newdirfd.
W systemach plików NFS nie można
zakładać, że przy niepowodzeniu operacji, nazwa pliku
nie uległa zmianie. Jeśli serwer dokonuje operacji zmiany
nazwy, a następnie się załamie, ponowna transmisja RPC,
która nastąpi po podniesieniu się serwera, spowoduje
błąd. Oczekuje się, że aplikacje mają
sobie z tym radzić. Podobny problem występuje w
link(2).
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.