ИМЯ
link, linkat -
создаёт
новое имя
файла
ОБЗОР
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
#include <fcntl.h> /* определения констант of AT_* */
#include <unistd.h>
int linkat(int olddirfd, const char *oldpath,
int newdirfd, const char *newpath, int flags);
Требования
макроса
тестирования
свойств
для glibc (см.
feature_test_macros(7)):
linkat():
- Начиная с glibc
2.10:
- _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _ATFILE_SOURCE
ОПИСАНИЕ
link()
создаёт
новую
ссылку
(также
называемую
жёсткую
ссылку) на
существующий
файл.
Если newpath
существует,
то он не
будет
перезаписан.
Это новое
имя может
использоваться
как и
старое для
любых
операций;
оба имени
ссылаются
на один
файл (и
имеют
одинаковые
права и
владельцев)
и
невозможно
сказать
какое имя
считать
"изначальным".
Системный
вызов linkat()
работает
также как
системный
вызов link(), за
исключением
случаев,
описанных
здесь.
Если в oldpath
задан
относительный
путь, то он
считается
относительно
каталога,
на который
ссылается
файловый
дескриптор
olddirfd (а не
относительно
текущего
рабочего
каталога
вызывающего
процесса,
как это
делается в
link()).
Если в oldpath
задан
относительный
путь и olddirfd
равно
специальному
значению
AT_FDCWD, то oldpath
рассматривается
относительно
текущего
рабочего
каталога
вызывающего
процесса
(как link()).
Если в oldpath
задан
абсолютный
путь, то olddirfd
игнорируется.
Значение
newpath
интерпретируется
как oldpath, за
исключением
того, что
относительный
путь
интерпретируется
относительно
каталога,
на который
ссылается
файловый
дескриптор
newdirfd.
Следующие
значения
можно
побитово (OR)
объединять
в flags:
- AT_EMPTY_PATH
(начиная с Linux
2.6.39)
- Если
значение
oldpath равно
пустой
строке, то
создаётся
ссылка на
файл, на
который
указывает
olddirfd (который
может быть
получен с
помощью open(2)
с флагом O_PATH).
В этом
случае olddirfd
может
указывать
на файл
любого
типа кроме
каталога.
Это,
обычно, не
работает,
если файл
имеет
счётчик
ссылок
равный
нулю
(исключение
— файлы,
созданные
с флагом O_TMPFILE
и без O_EXCL).
Вызывающий
должен
иметь
мандат
CAP_DAC_READ_SEARCH, чтобы
использовать
этот флаг.
Данный
флаг есть
только в Linux;
для
получения
его
определения
определите
_GNU_SOURCE.
- AT_SYMLINK_FOLLOW
(начиная с Linux
2.6.18)
- По
умолчанию,
linkat() не
разыменовывает
oldpath, если это
символьная
ссылка
(подобно link()).
В flags можно
указать
флаг AT_SYMLINK_FOLLOW, и
тогда
значение
oldpath будет
разыменовано,
если это
символьная
ссылка.
Если
смонтирована
procfs, то это
может быть
использовано
как
альтернатива
AT_EMPTY_PATH,
например:
-
linkat(AT_FDCWD, "/proc/self/fd/<fd>", newdirfd,
newname, AT_SYMLINK_FOLLOW);
До версии
ядра 2.6.18
аргумент
flags не
использовался
и должен
был быть
равен 0.
Смотрите
в openat(2)
объяснение
необходимости
linkat().
ВОЗВРАЩАЕМОЕ
ЗНАЧЕНИЕ
При
успешном
выполнении
возвращается
0. В случае
ошибки
возвращается
-1, а errno
устанавливается
в
соответствующее
значение.
ОШИБКИ
- EACCES
- Нет прав на
запись в
каталог,
содержащий
newpath, или в
одном из
каталогов
пути до oldpath
или newpath не
разрешён
поиск (см.
также path_resolution(7)).
- EDQUOT
- Исчерпана
пользовательская
квота на
дисковые
блоки
файловой
системы.
- EEXIST
- newpath уже
существует.
- EFAULT
- Значения
oldpath и newpath
указывают
за пределы
доступного
адресного
пространства.
- EIO
- Произошла
ошибка
ввода-вывода.
- ELOOP
- Во время
определения
oldpath или newpath
встретилось
слишком
много
символьных
ссылок.
- EMLINK
- На файл, на
который
указывает
oldpath, уже
создано
максимальное
количество
ссылок.
Например,
для
файловой
системы ext4(5),
в которой
не
используется
свойство
dir_index,
ограничение
по
количеству
жёстких
ссылок на
файл равно
65000; в btrfs(5) — 65535
ссылок.
- ENAMETOOLONG
- Слишком
длинное
значение
аргумента
oldpath или newpath.
- ENOENT
- Компонент
каталога в
oldpath или newpath не
существует
или
является
повисшей
ссылкой.
- ENOMEM
- Недостаточное
количество
памяти
ядра.
- ENOSPC
- На
устройстве,
содержащем
файл, нет
места для
создания
нового
элемента
каталога.
- ENOTDIR
- Компонент,
используемый
как
каталог в
oldpath или newpath, на
самом деле
не
является
каталогом.
- EPERM
- oldpath
является
каталогом.
- EPERM
- Файловая
система,
содержащая
oldpath и newpath, не
поддерживает
создание
жёстких
ссылок.
- EPERM
(начиная с Linux
3.6)
- Вызывающий
не имеет
прав для
создания
жёстких
ссылок на
этот файл
(смотрите
описание
/proc/sys/fs/protected_hardlinks в proc(5)).
- EPERM
- Файл oldpath
помечен
как
неизменяемый
(immutable) или
только для
добавления
(смотрите
ioctl_iflags(2)).
- EROFS
- Файл
расположен
в файловой
системе,
доступной
только для
чтения.
- EXDEV
- oldpath и newpath
находятся
не в одной
смонтированной
файловой
системе (Linux
позволяет
монтировать
файловую
систему в
несколько
точек, но link()
не
работает с
отличающими
точками
монтирования,
даже если в
них
смонтирована
идентичная
файловая
система).
В linkat()
дополнительно
могут
возникнуть
следующие
ошибки:
- EBADF
- В olddirfd или newdirfd
указаны
неправильные
файловые
дескрипторы.
- EINVAL
- В flags
указано
неверное
значение
флага.
- ENOENT
- Флаг AT_EMPTY_PATH
указан в flags,
но
вызывающий
не имеет
мандата
CAP_DAC_READ_SEARCH.
- ENOENT
- Предпринята
попытка
сделать
ссылку на
файл /proc/self/fd/NN,
который
соответствует
файловому
дескриптору,
созданному
с помощью
-
open(path, O_TMPFILE | O_EXCL, mode);
- Смотрите
open(2).
- ENOENT
- Значение
oldpath
является
относительным
путём и olddirfd
ссылается
на каталог,
который
был удалён,
или newpath
является
относительным
путём и newdirfd
ссылается
на каталог,
который
был
удалён.
- ENOTDIR
- Значение
oldpath
содержит
относительный
путь и olddirfd
содержит
файловый
дескриптор,
указывающий
на файл, а
не на
каталог;
или
произошло
тоже самое
с newpath и newdirfd.
- EPERM
- Значение
AT_EMPTY_PATH было
указано в
flags,
значение
oldpath равно
пустой
строке и olddirfd
указывает
на
каталог.
ВЕРСИИ
Вызов linkat()
был
добавлен в
ядро Linux
версии 2.6.16;
поддержка
в glibc
доступна с
версии 2.4.
СООТВЕТСТВИЕ
СТАНДАРТАМ
link(): SVr4, 4.3BSD, POSIX.1-2001 (но
смотрите
ЗАМЕЧАНИЯ),
POSIX.1-2008.
linkat(): POSIX.1-2008.
ЗАМЕЧАНИЯ
Жёсткие
ссылки,
создаваемые
link(), не могут
располагаться
в разных
файловых
системах.
Если это
необходимо,
используйте
symlink(2).
В POSIX.1-001
сказано,
что link()
должен
разыменовывать
oldpath, если он
является
символьной
ссылкой.
Однако,
начиная с
ядра
версии 2.0, Linux
также не
поступает:
если oldpath
является
символьной
ссылкой, то
newpath
создаётся
как
(жёсткая)
ссылка на
файл этой
символьной
ссылки (т.е.,
newpath
становится
символьной
ссылкой на
файл,
содержащий
ссылку на
oldpath).
Некоторые
другие
реализации
поступают
также как Linux.
В POSIX.1-2008
изменено
описание
link(), теперь
разыменование
символьной
ссылки oldpath
зависит от
реализации.
Для
точного
управления
по
обработке
символьных
ссылок при
создании
используйте
linkat().
Замечания
по glibc
В старых
ядрах, где
linkat()
отсутствует
(и если не
указан
флаг AT_SYMLINK_NOFOLLOW),
обёрточная
функция glibc
использует
link(). Если oldpath и
newpath
являются
относительными
путями, то glibc
собирает
пути
относительно
символической
ссылки в
/proc/self/fd,
которая
соответствует
аргументам
olddirfd и newdirfd.
ДЕФЕКТЫ
В
файловых
системах NFS
возвращаемый
код может
быть
неправильным,
если
сервер NFS
выполнит
создание
ссылки и
завершит
работу до
возврата
результата
операции.
Используйте
stat(2), чтобы
выяснить
была ли
создана
ссылка.