Other Alias
readlinkОБЗОР
#include <unistd.h>
ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
#include <fcntl.h> /* определения констант of AT_* */
#include <unistd.h>
ssize_t readlinkat(int dirfd, const char *pathname,
char *buf, size_t bufsiz);
Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):
readlink():
- _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || _POSIX_C_SOURCE >= 200112L
readlinkat():
-
- Начиная с glibc 2.10:
- _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
- До glibc 2.10:
- _ATFILE_SOURCE
ОПИСАНИЕ
Вызов readlink() помещает содержимое символьной ссылки pathname в буфер buf размером bufsiz. readlink() не добавляет в buf байт null. Если буфер слишком мал для хранения всего содержимого, то содержимое будет урезано (до длины в bufsiz символов).readlinkat()
Системный вызов readlinkat() работает также как системный вызов readlink(), за исключением случаев, описанных здесь.Если в pathname задан относительный путь, то он считается относительно каталога, на который ссылается файловый дескриптор dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делается в readlink()).
Если в pathname задан относительный путь и dirfd равно специальному значению AT_FDCWD, то pathname рассматривается относительно текущего рабочего каталога вызывающего процесса (как readlink()).
Если в pathname задан абсолютный путь, то dirfd игнорируется.
Начиная с Linux .6.39, pathname может быть пустой строкой; при этом вызов выполняет действие с символьной ссылкой, на которую ссылается dirfd (должна получаться с помощью вызова open(2) с флагами O_PATH и O_NOFOLLOW).
Смотрите в openat(2) объяснение необходимости readlinkat().
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти вызовы возвращают количество байт, помещённых в buf. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.ОШИБКИ
- EACCES
- В одном из каталогов префикса пути не разрешён поиск (см. также path_resolution(7).
- EFAULT
- buf выходит за пределы адресного пространства, выделенного процессу.
- EINVAL
- Аргумент bufsiz содержит отрицательное значение.
- EINVAL
- Указанный файл не является символьной ссылкой.
- EIO
- При чтении файловой системы произошла ошибка ввода-вывода.
- ELOOP
- Во время определения pathname встретилось слишком много символьных ссылок.
- ENAMETOOLONG
- Слишком длинное значение аргумента pathname или его части.
- ENOENT
- Указанный файл не существует.
- ENOMEM
- Недостаточное количество памяти ядра.
- ENOTDIR
- Компонент в префиксе пути не является каталогом.
В readlinkat() дополнительно могут возникнуть следующие ошибки:
- EBADF
- dirfd не является правильным файловым дескриптором.
- ENOTDIR
- Значение pathname содержит относительный путь и dirfd содержит файловый дескриптор, указывающий на файл, а не на каталог.
ВЕРСИИ
Системный вызов readlinkat() был добавлен в ядро Linux версии 2.6.16; поддержка в glibc доступна с версии 2.4.СООТВЕТСТВИЕ СТАНДАРТАМ
readlink(): 4.4BSD (readlink() появился в 4.2BSD), POSIX.1-2001, POSIX.1-2008.readlinkat(): POSIX.1-2008.
ЗАМЕЧАНИЯ
В версиях glibc до glibc 2.4 включительно, тип результата readlink() был объявлен как int. В настоящее время типом возвращаемого результата является ssize_t, как (теперь) это требуется по POSIX.1-2001.Буфера с фиксированным размером может не хватить для хранения содержимого символьной ссылки. Требуемый размер буфера можно получить как значение stat.st_size, возвращаемое на ссылку вызовом lstat(2). Однако, количество байт, записанное readlink() и readlinkat(), должно быть проверено, так как требуется убедиться, что размер символьной ссылки не увеличился между вызовами. Динамическое выделение буфера для readlink() и readlinkat() также поможет решить проблему с переносимостью, которая возникает, когда для размера буфера используется PATH_MAX, но согласно POSIX для этой константы не гарантируется, что она определена , если система не имеет такого ограничения.
Замечания по glibc
В старых ядрах, где readlinkat() отсутствует, обёрточная функция glibc использует readlink(). Если pathname является относительным путём, то glibc собирает путь относительно символической ссылки в /proc/self/fd, которая соответствует аргументу dirfd.ПРИМЕР
Следующая программа динамически выделяет буфер, необходимый readlink(), из информации, предоставленной lstat() и проверяет, что при работы вызовов не возникло состязательности.#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { struct stat sb; char *linkname; ssize_t r; if (argc != 2) { fprintf(stderr, "Использование: %s <путь>\n", argv[0]); exit(EXIT_FAILURE); } if (lstat(argv[1], &sb) == -1) { perror("lstat"); exit(EXIT_FAILURE); } linkname = malloc(sb.st_size + 1); if (linkname == NULL) { fprintf(stderr, "недостаточно памяти\n"); exit(EXIT_FAILURE); } r = readlink(argv[1], linkname, sb.st_size + 1); if (r == -1) { perror("readlink"); exit(EXIT_FAILURE); } if (r > sb.st_size) { fprintf(stderr, "ссылка увеличилась в размере " "между lstat() и readlink()\n"); exit(EXIT_FAILURE); } linkname[r] = '\0'; printf("'%s' указывает на '%s'\n", argv[1], linkname); free(linkname); exit(EXIT_SUCCESS); }