ИМЯ

readlink, readlinkat - считывает значение символьной ссылки

LIBRARY

Standard C library ( libc, -lc)

СИНТАКСИС

#include <unistd.h>
ssize_t readlink(const char *restrict pathname, char *restrict buf,
                 size_t bufsiz);
#include <fcntl.h>            /* определения констант AT_* */
#include <unistd.h>
ssize_t readlinkat(int dirfd, const char *restrict pathname,
                 char *restrict buf, size_t bufsiz);

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):
readlink():
    _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L
        || /* glibc <= 2.19: */ _BSD_SOURCE
readlinkat():
    Since glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    Before glibc 2.10:
        _ATFILE_SOURCE

ОПИСАНИЕ

readlink() places the contents of the symbolic link pathname in the buffer buf, which has size bufsiz. readlink() does not append a terminating null byte to buf. It will (silently) truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents.

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 (если возвращаемое значение равно bufsiz, то возможно произошло обрезание). В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.

ОШИБКИ

EACCES
В одном из каталогов префикса пути не разрешён поиск (см. также path_resolution(7).
EBADF
(readlinkat()) pathname is relative but dirfd is neither AT_FDCWD nor a valid file descriptor.
EFAULT
buf выходит за пределы адресного пространства, выделенного процессу.
EINVAL
Аргумент bufsiz содержит отрицательное значение.
EINVAL
Указанный файл (т. е., последний компонент имени файла pathname) не является символьной ссылкой.
EIO
При чтении файловой системы произошла ошибка ввода-вывода.
ELOOP
Во время определения pathname встретилось слишком много символьных ссылок.
ENAMETOOLONG
Слишком длинное значение аргумента pathname или его части.
ENOENT
Указанный файл не существует.
ENOMEM
Недостаточное количество памяти ядра.
ENOTDIR
Компонент в префиксе пути не является каталогом.
ENOTDIR
(readlinkat()) Значение pathname содержит относительный путь и dirfd содержит файловый дескриптор, указывающий на файл, а не на каталог.

ВЕРСИИ

readlinkat() was added in Linux 2.6.16; library support was added in glibc 2.4.

СТАНДАРТЫ

readlink(): 4.4BSD (readlink() появился в 4.2BSD), POSIX.1-2001, POSIX.1-2008.
readlinkat(): POSIX.1-2008.

ЗАМЕЧАНИЯ

Up to and including glibc 2.4, the return type of readlink() was declared as int. Nowadays, the return type is declared as ssize_t, as (newly) required in 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(2), или использует буфер размером PATH_MAX, если lstat(2) вернул нулевой размер.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char *argv[]) { char *buf; ssize_t nbytes, bufsiz; struct stat sb;
if (argc != 2) { fprintf(stderr, "Использование: %s <путь>\n", argv[0]); exit(EXIT_FAILURE); }
if (lstat(argv[1], &sb) == -1) { perror("lstat"); exit(EXIT_FAILURE); }
/* Добавляем единицу к размеру ссылки, так чтобы можно было определить обрезанность буфера, возвращаемого readlink(). */
bufsiz = sb.st_size + 1;
/* Some magic symlinks under (for example) /proc and /sys report 'st_size' as zero. In that case, take PATH_MAX as a "good enough" estimate. */
if (sb.st_size == 0) bufsiz = PATH_MAX;
buf = malloc(bufsiz); if (buf == NULL) { perror("malloc"); exit(EXIT_FAILURE); }
nbytes = readlink(argv[1], buf, bufsiz); if (nbytes == -1) { perror("readlink"); exit(EXIT_FAILURE); }
/* Print only 'nbytes' of 'buf', as it doesn't contain a terminating null byte ('\0'). */ printf("'%s' points to '%.*s'\n", argv[1], (int) nbytes, buf);
/* Если возвращаемое значение равно размеру буфера, то ссылка назначения больше чем ожидалось (возможно, из-за того, что цель изменилась между вызовом lstat() и readlink()). Предупреждаем пользователя о том, что цель может быть обрезана. */
if (nbytes == bufsiz) printf("(Возвращённый буфер мог быть обрезан)\n");
free(buf); exit(EXIT_SUCCESS); }

СМ. ТАКЖЕ

readlink(1), lstat(2), stat(2), symlink(2), realpath(3), path_resolution(7), symlink(7)

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан aereiae <[email protected]>, Azamat Hackimov <[email protected]>, Dmitriy S. Seregin <[email protected]>, Katrin Kutepova <[email protected]>, Lockal <[email protected]>, Yuri Kozlov <[email protected]>, Баринов Владимир и Иван Павлов <[email protected]>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на [email protected]