rename(2)

NAZWA
rename, renameat, renameat2 - zmienia nazwę lub położenie pliku

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#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);

    Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

renameat():
    Od glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    Przed glibc 2.10:
        _ATFILE_SOURCE

renameat2():
    _GNU_SOURCE

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

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

WARTOŚĆ ZWRACANA
Po pomyślnym zakończeniu zwracane jest zero. Po błędzie zwracane jest -1 i ustawiane errno, wskazując błąd.

BŁĘDY

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.

STANDARDY

rename()
    C11, POSIX.1-2008.

renameat()
    POSIX.1-2008.

renameat2()
    Linux.

HISTORIA

rename()
    4.3BSD, C89, POSIX.1-2001.

renameat()
    Linux 2.6.16, glibc 2.4.

renameat2()
    Linux 3.15, glibc 2.28.

  Uwagi dla glibc
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.

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

ZOBACZ TAKŻE
mv(1), rename(1), chmod(2), link(2), symlink(2), unlink(2), path_resolution(7), symlink(7)

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 (https://www.gnu.org/licenses/gpl-3.0.html) 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.