- bullseye-backports 4.18.1-1~bpo11+1
- testing 4.18.1-1
- unstable 4.18.1-1
READLINK(2) | Руководство программиста Linux | READLINK(2) |
ИМЯ¶
readlink, readlinkat - считывает значение символьной ссылки
СИНТАКСИС¶
#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);
readlink():
|| /* в версии glibc <= 2.19: */ _BSD_SOURCE
readlinkat():
- Начиная с glibc 2.10:
- _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 (если возвращаемое значение равно bufsiz, то возможно произошло обрезание). В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
ОШИБКИ¶
- EACCES
- В одном из каталогов префикса пути не разрешён поиск (см. также path_resolution(7).
- EFAULT
- buf выходит за пределы адресного пространства, выделенного процессу.
- EINVAL
- Аргумент bufsiz содержит отрицательное значение.
- EINVAL
- Указанный файл (т. е., последний компонент имени файла pathname) не является символьной ссылкой.
- EIO
- При чтении файловой системы произошла ошибка ввода-вывода.
- ELOOP
- Во время определения pathname встретилось слишком много символьных ссылок.
- ENAMETOOLONG
- Слишком длинное значение аргумента pathname или его части.
- ENOENT
- Указанный файл не существует.
- ENOMEM
- Недостаточное количество памяти ядра.
- ENOTDIR
- Компонент в префиксе пути не является каталогом.
В readlinkat() дополнительно могут возникнуть следующие ошибки:
ВЕРСИИ¶
Системный вызов 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(2), или использует буфер размером PATH_MAX, если lstat(2) вернул нулевой размер.
#include <sys/types.h> #include <sys/stat.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) {
struct stat sb;
char *buf;
ssize_t nbytes, bufsiz;
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;
/* У некоторых символьных ссылок в (например) /proc и /sys
значение 'st_size' равно нулю. В этом случае используется
PATH_MAX как «достаточный» размер. */
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);
}
printf("'%s' указывает на '%.*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)
ЗАМЕЧАНИЯ¶
Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.
ПЕРЕВОД¶
Русский перевод этой страницы руководства был сделан aereiae <aereiae@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Katrin Kutepova <blackkatelv@gmail.com>, Lockal <lockalsash@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Баринов Владимир и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
9 июня 2020 г. | Linux |