Linux Man на русском

  User    Syst    Libr    Device    Files    Other    Admin  



   rename - изменяет имя или расположение файла

rename(2) изменяет имя или расположение файла

Other Alias

renameat, renameat2


ОБЗОР

#include <stdio.h>


int rename(const char *oldpath, const char *newpath);

#include <fcntl.h> /* определения констант 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);

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

renameat():


Начиная с glibc 2.10: _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
До glibc 2.10: _ATFILE_SOURCE


ОПИСАНИЕ

Вызов rename() переименовывает файл и, если требуется, перемещает его из одного каталога в другой. Все прочие жёсткие ссылки на файл (созданные с помощью link(2)), не изменяются. Открытые файловые дескрипторы на oldpath также не изменяются.

Если newpath уже существует, то он будет атомарно перезаписан (при определённых условиях, смотрите


ОШИБКИ ниже) так, что другой процесс, пытающийся обратиться к newpath, не сможет определить его временное отсутствие.

Если oldpath и newpath являются жёсткими ссылками на один и тот же файл, то rename() ничего не делает и возвращает код успешного выполнения.

Если newpath существует, но операция завершается ошибкой, то rename() гарантирует, что newpath останется нетронутым.

В oldpath может быть указан каталог. В этом случае каталог в newpath должен или не существовать, или должен быть пуст.

Однако, при перезаписи, вероятно, будет временной промежуток, в котором оба значения, oldpath и newpath, ссылаются на переименовываемый файл.

Если oldpath является символьной ссылкой, то она переименовывается; если newpath является символьной ссылкой, то будет вновь записан файл, на который она указывает.

renameat()

Системный вызов renameat() работает также как системный вызов rename(), за исключением случаев, описанных далее.

Если в oldpath указан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор olddirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в rename()).

Если в oldpath указан относительный путь и olddirfd равно специальному значению AT_FDCWD, то oldpath рассматривается относительно текущего рабочего каталога вызывающего процесса (как rename()).

Если в oldpath указан абсолютный путь, то olddirfd игнорируется.

Значение newpath интерпретируется как oldpath, за исключением того, что относительный путь интерпретируется относительно каталога, на который ссылается файловый дескриптор newdirfd.

Смотрите в openat(2) объяснение необходимости renameat().

renameat2()

Вызов renameat2() имеет дополнительный аргумент flags. Если значение flags равно нулю, то renameat2() эквивалентен renameat().

Аргумент flags является битовой маской, состоящей из нуля или более следующих флагов:

RENAME_EXCHANGE Атомарно обменять oldpath и newpath. Оба пути должны существовать, но могут быть различных типов (например, один может быть непустым каталогом, а другой символической ссылкой).

RENAME_NOREPLACE Не перезаписывать newpath. Возвращать ошибку, если newpath уже существует.

RENAME_NOREPLACE не может быть применен вместе с RENAME_EXCHANGE.

RENAME_WHITEOUT (начиная с Linux 3.18) Эта операция применима только для реализаций оверлейных/объединённых файловых систем.

При указании RENAME_WHITEOUT для источника переименования одновременно с выполнением переименования создаётся «замазанный» объект (whiteout object). Вся операция атомарна, и при успешном выполнении переименования создаётся и замазка.

«Замазка» — это объект, имеющий специальное предназначение в оверлейных/объединённых файловых системах. В них существует несколько слоёв, и для изменения доступен только верхний. Замазка на верхнем слое эффективно скрывает файл из нижнего слоя, и кажется, что файл не существует.

Когда переименовывается файл, существующий в нижнем слое, то первым действием он переписывается (если его уже нет в верхнем слое) и переименовывается в верхнем, доступном на чтение-запись слое. Одновременно с этим, исходный файл требуется «замазать» (что исходный файл в нижнем слое отражался невидимым). Вся операция должна выполняться атомарно.

При отсутствии объединения/оверлея замазка появляется в виде символьного устройства с номером устройства {0,0}.

Для RENAME_WHITEOUT требуются те же права, что и для создания узла устройства (т. е., мандата CAP_MKNOD).

RENAME_WHITEOUT не может быть применён вместе с RENAME_EXCHANGE.

Для RENAME_WHITEOUT требуется поддержка в файловой системе. Такая поддержка имеется в shmem (начиная с Linux 3.18), ext4 (начиная с Linux 3.18) и XFS (начиная с Linux 4.1).


ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.


ОШИБКИ

EACCES Запись в каталог, содержащий oldpath или newpath, запрещена, или в одном из каталогов пути oldpath или newpath нельзя производить поиск, или oldpath является каталогом, в который запрещена запись (требует обновления элемента ..); смотрите также path_resolution(7)).

EBUSY Переименование завершилось неудачно, так как oldpath или newpath является каталогом, который используется другим процессом (возможно в качестве текущего рабочего каталога или в качестве корневого каталога, или он открыт на чтение), или используется системой (например, в качестве точки монтирования), и система считает это ошибкой (заметим, что нет требования возвращать EBUSY в таких случаях — нет ничего неправильного в таком переименовании — но разрешается возвращать EBUSY, если система не может иначе обработать такие ситуации).

EDQUOT Исчерпана пользовательская квота на дисковые блоки файловой системы.

EFAULT Значения oldpath и newpath указывают за пределы доступного адресного пространства.

EINVAL Новый путь содержит префикс старого пути или, в более общем смысле, выполняется попытка сделать каталог подкаталогом самого себя.

EISDIR Каталог newpath уже существует, но oldpath не является каталогом.

ELOOP Во время определения oldpath или newpath встретилось слишком много символьных ссылок.

EMLINK В oldpath уже имеется максимальное количество ссылок, или каталог, содержащий newpath, уже имеет максимальное количество ссылок.

ENAMETOOLONG Слишком длинное значение аргумента oldpath или newpath.

ENOENT Ссылка, на которую ссылается oldpath, не существует; компонент каталога в newpath не существует; в oldpath или newpath указана пустая строка.

ENOMEM Недостаточное количество памяти ядра.

ENOSPC На устройстве, содержащем файл, нет места для создания нового элемента каталога.

ENOTDIR Компонент, используемый как каталог в oldpath или newpath, в действительности не является каталогом. Или oldpath является каталогом и существует newpath, который не является каталогом.

ENOTEMPTY или EEXIST Значение newpath является непустым каталогом, то есть содержит элементы, отличные от «.» и «..».

EPERM или EACCES Каталог, содержащийся в oldpath, имеет закрепляющий бит (S_ISVTX) и эффективный идентификатор процесса не совпадает с идентификатором пользователя удаляемого файла или каталога, его содержащего, и процесс не имеет прав (Linux: нет мандата CAP_FOWNER); или newpath является существующим файлом и каталог, содержащий его, имеет закрепляющий бит и эффективный идентификатор процесса не совпадает с идентификатором пользователя замещаемого файла или каталога, его содержащего, и процесс не имеет прав (Linux: нет мандата CAP_FOWNER); или файловая система, содержащая pathname, не поддерживает переименования запрашиваемого типа.

EROFS Файл расположен в файловой системе, доступной только для чтения.

EXDEV Элементы oldpath и newpath находятся не в одной смонтированной файловой системе (Linux позволяет монтировать файловую систему в несколько точек, но rename() не работает с различающимися точками монтирования, даже если в них смонтирована идентичная файловая система).

В renameat() и renameat2() дополнительно могут возникнуть следующие ошибки:

EBADF Значение olddirfd или newdirfd не является правильным файловым дескриптором.

ENOTDIR Значение oldpath содержит относительный путь и olddirfd содержит файловый дескриптор, указывающий на файл, а не на каталог; или произошло тоже самое с newpath и newdirfd.

В renameat2() дополнительно могут возникнуть следующие ошибки:

EEXIST Значение flags содержит RENAME_NOREPLACE, а newpath уже существует.

EINVAL В flags указан неверный флаг.

EINVAL В flags указаны оба флага, RENAME_NOREPLACE и RENAME_EXCHANGE.

EINVAL В flags указаны оба флага, RENAME_WHITEOUT и RENAME_EXCHANGE.

EINVAL Файловая система не поддерживает один из флагов в flags.

ENOENT В flags содержится RENAME_EXCHANGE, но newpath не существует.

EPERM В flags указан флаг RENAME_WHITEOUT , но вызывающий не имеет мандата CAP_MKNOD.

ВЕРСИИ

Системный вызов renameat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.

Вызов renameat2() был добавлен в ядро Linux 3.15.


СООТВЕТСТВИЕ СТАНДАРТАМ

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

renameat(): POSIX.1-2008.

Вызов renameat2() есть только в Linux.


ЗАМЕЧАНИЯ

Замечания по glibc

В старых ядрах, где renameat() отсутствует, обёрточная функция glibc использует rename(). Если oldpath и newpath являются относительными путями, то glibc собирает пути относительно символической ссылки в /proc/self/fd, которая соответствует аргументам olddirfd и newdirfd.

ДЕФЕКТЫ

При работе с файловыми системами NFS нельзя считать, что если операция завершилась неудачно, то имя файла не изменилось. Если сервер производит операцию переименования, а затем аварийно останавливает свою работу, то перепосланный пакет RPC будет вновь обработан при восстановлении работы сервера, что вызовет сообщение об ошибке. Приложение в этой ситуации должно работать корректно. Смотрите link(2), где описывается подобная проблема.