По этой причине существует системный вызов lstat()
stat(), но если проверяемый файл окажется символической ссылкой, возвращаемые сведения относятся к символической ссылке, а не к указываемому файлу. А именно:• S_ISLNK(sbuf.st_mode)
true.• sbuf.st_size
Мы уже видели, что системный вызов symlink()
ls может получить это имя; поэтому мы должны быть способны это сделать.)Открывание ссылки с помощью open()
read() не будет работать, open() следует по ссылке на указываемый файл. Таким образом, символические ссылки сделали необходимым дополнительный системный вызов, который называется readlink():#include
int readlink(const char *path, char *buf, size_t bufsiz);
readlink()
path, в буфер, на который указывает buf. Копируется не более bufsiz символов. Возвращаемое значение равно числу символов, помещенных в buf, либо -1, если возникла ошибка, readlink() Обратите внимание, что если буфер, переданный readlink()
readlink() должным образом, вы должны делать следующее:1. Используйте lstat()
2. Убедитесь, что ваш буфер для содержимого символической ссылки составляет по крайней мере 'sbuf.st_size + 1
+ 1' нужно для завершающего нулевого байта, чтобы сделать буфер годной к употреблению строкой С.3. Вызовите readlink()
sbuf.st_size.4. Добавьте '\0
/* Проверка ошибок для краткости опущена */
int count;
char linkfile[PATH_MAX], realfile[PATH_MAX]; /* PATH_MAX в
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.c в GNU Coreutils делает именно это. Он читает содержимое символической ссылки в память, выделенную malloc(). Мы покажем здесь саму функцию, большая часть файла представляет собой стереотипные определения. Номера строк относятся к началу файла:55 /* Вызвать readlink для получения значения ссылки FILENAME.
56 Вернуть указатель на завершенную NUL строку в выделенной malloc памяти.
57 При ошибке readlink вернуть NULL (использовать errno для диагноза).
58 При ошибке realloc или если значение ссылки больше SIZE_MAX,
59 выдать диагностику и выйти. */
60
61 char*
62 xreadlink(char const* filename)
63 {
64 /* Начальный размер буфера для ссылки. Степень 2 обнаруживает
Бьёрн Страуструп , Ирина Сергеевна Козлова , Бьерн Страуструп , Валерий Федорович Альмухаметов
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT