Linux программирование в примерах, стр. 59
•
S_ISLNK(sbuf.st_mode)true•
sbuf.st_sizeМы уже видели, что системный вызов
symlink()lsОткрывание ссылки с помощью
open()read()open()readlink()#include <unistd.h> /* POSIX */int readlink(const char *path, char *buf, size_t bufsiz);readlink()pathbufbufsizbufreadlink()Обратите внимание, что если буфер, переданный
readlink()readlink()1. Используйте
lstat()2. Убедитесь, что ваш буфер для содержимого символической ссылки составляет по крайней мере '
sbuf.st_size + 1+ 13. Вызовите
readlink()sbuf.st_size4. Добавьте '
\0/* Проверка ошибок для краткости опущена */int count;char linkfile[PATH_MAX], realfile[PATH_MAX]; /* PATH_MAX в <limits.h> */strut stat sbuf;/* ...поместить в linkfile путь к нужной символической ссылке... */lstat(linkfile, &sbuf); /* Получить сведения от stat */if (!S_ISLNK(sbuf.st_mode)) /* Проверить, что это ссылка */ /* не символическая ссылка, обработать это */if (sbuf.st_size + 1 > PATH_МАХ) /* Проверить размер буфера */ /* обработать проблемы с размером буфера */count = readlink(linkfile, realfile, PATH_MAX);/* Прочесть ссылку */if (count != sbuf.st_size) /* происходит что-то странное, обработать это */realfile(count) = '\0'; /* Составить строку С */Данный пример для простоты представления использует буферы фиксированного размера. Реальный код мог бы использовать для выделения буфера нужного размера
malloc()lib/xreadlink.cmalloc()55 /* Вызвать readlink для получения значения ссылки FILENAME.56 Вернуть указатель на завершенную NUL строку в выделенной malloc памяти.57 При ошибке readlink вернуть NULL (использовать errno для диагноза).58 При ошибке realloc или если значение ссылки больше SIZE_MAX,59 выдать диагностику и выйти. */6061 char*62 xreadlink(char const* filename)63 {64 /* Начальный размер буфера для ссылки. Степень 2 обнаруживает65 арифметическое переполнение раньше, но не рекомендуется. */66 size_t buf_size = 128;6768 while(1)69 {70 char *buffer = xmalloc(buf_size);71 ssize_t link_length = readlink(filename, buffer, buf_size);7273 if (link_length < 0)74 {75 int saved_errno = errno;76 free(buffer);77 errno = saved_errno;78 return NULL;79 }8081 if ((size_t)link_length < buf_size)82 {83 buffer[link_length] = 0;84 return buffer;85 }8687 free(buffer);88 buf_size *= 2;89 if (SSIZE_MAX < buf_size || (SIZE_MAX / 2 < SSIZE_MAX && buf_size == 0))90 xalloc_die();91 }92 }Тело функции состоит из бесконечного цикла (строки 68–91), разрываемого в строке 84, которая возвращает выделенный буфер. Цикл начинается выделением первоначального буфера (строка 70) и чтения ссылки (строка 71). Строки 73–79 обрабатывают случай ошибки, сохраняя и восстанавливая errno таким образом, что она может корректно использоваться вызывающим кодом.