ИМЯ
rename, 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:
- _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _ATFILE_SOURCE
 
renameat2():
ОПИСАНИЕ
Вызов rename()
    переименовывает
    файл и, если
    требуется,
    перемещает
    его из
    одного
    каталога в
    другой. Все
    прочие
    жёсткие
    ссылки на
    файл
    (созданные
    с помощью
    link(2)), не
    изменяются.
    Открытые
    файловые
    дескрипторы
    на oldpath также
    не
    изменяются.
На
    успешность
    выполнения
    операции
    переименования
    влияют
    различные
    ограничения:
    смотрите
    ОШИБКИ
    далее.
Если newpath
    уже
    существует,
    то он будет
    атомарно
    перезаписан
    так, что
    другой
    процесс,
    пытающийся
    в этот
    момент
    обратиться
    к newpath, не
    сможет
    определить
    его
    временное
    отсутствие.
    Однако
    будет
    промежуток
    времени,
    когда oldpath и
    newpath
    указывают
    на один
    файл.
Если oldpath и
    newpath
    являются
    жёсткими
    ссылками
    на один и
    тот же файл,
    то rename()
    ничего не
    делает и
    возвращает
    код
    успешного
    выполнения.
Если newpath
    существует,
    но
    операция
    завершается
    ошибкой, то
    rename()
    гарантирует,
    что newpath
    останется
    нетронутым.
В oldpath может
    быть
    указан
    каталог. В
    этом
    случае
    каталог в
    newpath должен
    или не
    существовать,
    или должен
    быть пуст.
Если oldpath
    является
    символьной
    ссылкой, то
    она
    переименовывается;
    если newpath
    является
    символьной
    ссылкой, то
    будет
    вновь
    записан
    файл, на
    который
    она
    указывает.
Системный
    вызов renameat()
    работает
    также как
    системный
    вызов rename(), за
    исключением
    случаев,
    описанных
    далее.
Если в oldpath
    указан
    относительный
    путь, то он
    считается
    относительно
    каталога,
    на который
    ссылается
    файловый
    дескриптор
    olddirfd (а не
    относительно
    текущего
    рабочего
    каталога
    вызывающего
    процесса,
    как это
    делается в
    rename()).
Если в oldpath
    указан
    относительный
    путь и olddirfd
    равно
    специальному
    значению
    AT_FDCWD, то oldpath
    рассматривается
    относительно
    текущего
    рабочего
    каталога
    вызывающего
    процесса
    (как rename()).
Если в oldpath
    указан
    абсолютный
    путь, то olddirfd
    игнорируется.
Значение
    newpath
    интерпретируется
    как oldpath, за
    исключением
    того, что
    относительный
    путь
    интерпретируется
    относительно
    каталога,
    на который
    ссылается
    файловый
    дескриптор
    newdirfd.
Смотрите
    в openat(2)
    объяснение
    необходимости
    renameat().
Вызов renameat2()
    имеет
    дополнительный
    аргумент
    flags. Если
    значение
    flags равно
    нулю, то renameat2()
    эквивалентен
    renameat().
Аргумент
    flags
    является
    битовой
    маской,
    состоящей
    из нуля или
    более
    следующих
    флагов:
  - RENAME_EXCHANGE
- Атомарно
      обменять
      oldpath и newpath. Оба
      пути
      должны
      существовать,
      но могут
      быть
      различных
      типов
      (например,
      один может
      быть
      непустым
      каталогом,
      а другой
      символической
      ссылкой).
- RENAME_NOREPLACE
- Не
      перезаписывать
      newpath.
      Возвращать
      ошибку,
      если newpath уже
      существует.
  
  - RENAME_NOREPLACE не
      может быть
      применен
      вместе с
      RENAME_EXCHANGE.
- Для RENAME_NOREPLACE
      требуется
      поддержка
      в файловой
      системе;
      она есть
      только у
      нескольких
      файловых
      систем:
  - ext4 (начиная
      с Linux 3.15);
- btrfs, shmem, и cifs
      (начиная
      с Linux 3.17);
- xfs (начиная
      с Linux 4.0);
- Поддержка
      для других
      файловых
      систем
      была
      добавлена
      в Linux 4.9: etx2, minix, reiserfs, jfs, vfat и bpf.
 
  - RENAME_WHITEOUT
    (начиная с Linux
    3.18)
- Эта
      операция
      применима
      только для
      реализаций
      оверлейных/объединённых
      файловых
      систем.
  
  - При
      указании
      RENAME_WHITEOUT для
      источника
      переименования
      одновременно
      с
      выполнением
      переименования
      создаётся
      «замазанный»
      объект (whiteout object).
      Вся
      операция
      атомарна, и
      при
      успешном
      выполнении
      переименования
      создаётся
      и замазка.
- «Замазка»
      — это
      объект,
      имеющий
      специальное
      предназначение
      в
      оверлейных/объединённых
      файловых
      системах. В
      них
      существует
      несколько
      слоёв, и
      для
      изменения
      доступен
      только
      верхний.
      Замазка на
      верхнем
      слое
      эффективно
      скрывает
      файл из
      нижнего
      слоя, и
      кажется,
      что файл не
      существует.
- Когда
      переименовывается
      файл,
      существующий
      в нижнем
      слое, то
      первым
      действием
      он
      переписывается
      (если его
      уже нет в
      верхнем
      слое) и
      переименовывается
      в верхнем,
      доступном
      на
      чтение-запись
      слое.
      Одновременно
      с этим,
      исходный
      файл
      требуется
      «замазать»
      (что
      исходный
      файл в
      нижнем
      слое
      отражался
      невидимым).
      Вся
      операция
      должна
      выполняться
      атомарно.
- При
      отсутствии
      объединения/оверлея
      замазка
      появляется
      в виде
      символьного
      устройства
      с номером
      устройства
      {0,0} (заметим,
      что в
      других
      реализациях
      объединения/оверлея
      могут
      использоваться
      другие
      методы
      хранения
      элементов
      замазки; в
      частности,
      в BSD для
      объединения
      монтирования
      используется
      специальный
      тип иноды,
      DT_WHT, который,
      хотя и
      поддерживается
      некоторыми
      файловыми
      системами,
      доступными
      в Linux,
      например CODA
      и XFS, но
      игнорируется
      кодом
      поддержки
      замазки в
      ядре, по
      крайней
      мере, в Linux 4.19).
- Для RENAME_WHITEOUT
      требуются
      те же
      права, что
      и для
      создания
      узла
      устройства
      (т. е.,
      мандата
      CAP_MKNOD).
- RENAME_WHITEOUT не
      может быть
      применён
      вместе с
      RENAME_EXCHANGE.
- Для RENAME_WHITEOUT
      требуется
      поддержка
      в файловой
      системе.
      Такая
      поддержка
      имеется в tmpfs
      (начиная с Linux
      3.18), ext4 (начиная
      с Linux 3.18), XFS
      (начиная с Linux
      4.1), f2fs (начиная
      с Linux 4.2), btrfs
      (начиная с Linux
      4.7) и ubifs
      (начиная с Linux
      4.9).
ВОЗВРАЩАЕМОЕ
  ЗНАЧЕНИЕ
При
    успешном
    выполнении
    возвращается
    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;
    поддержка
    в glibc
    доступна с
    версии 2.28.
СООТВЕТСТВИЕ
  СТАНДАРТАМ
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), где
    описывается
    подобная
    проблема.