Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

Открывание ссылки с помощью

open
для чтения ее с использованием
read
не будет работать,
open
следует по ссылке на указываемый файл. Таким образом, символические ссылки сделали необходимым дополнительный системный вызов, который называется
readlink
:

#include <unistd.h> /* POSIX */

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 в <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.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 обнаруживает

65 арифметическое переполнение раньше, но не рекомендуется. */

66 size_t buf_size = 128;

67

68 while(1)

69 {

70 char *buffer = xmalloc(buf_size);

71 ssize_t link_length = readlink(filename, buffer, buf_size);

72

73 if (link_length < 0)

74 {

75 int saved_errno = errno;

76 free(buffer);

77 errno = saved_errno;

78 return NULL;

79 }

80

81 if ((size_t)link_length < buf_size)

82 {

83 buffer[link_length] = 0;

84 return buffer;

85 }

86

87 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 таким образом, что она может корректно использоваться вызывающим кодом.

Строки 81–85 обрабатывают случай «успеха», при котором размер содержимого ссылки меньше размера буфера. В этом случае добавляется завершающий ноль (строка 83), а затем буфер возвращается, прерывая бесконечный цикл. Это гарантирует, что в буфер помещено все содержимое ссылки, поскольку у

readlink
нет возможности сообщить о «недостаточном размере буфера».

Строки 87–88 освобождают буфер и удваивают размер буфера для следующей попытки в начале цикла. Строки 89–90 обрабатывают случай, при котором размер ссылки слишком велик:

buf_size
больше, чем
SSIZE_MAX
, или
SSIZE_MAX
больше, чем значение, которое может быть представлено в знаковом целом того же размера, который использовался для хранения
SIZE_MAX
, и
buf_size
обернулся в ноль. (Это маловероятные условия, но странные вещи все же случаются.) Если одно из этих условий верно, программа завершается с сообщением об ошибке. В противном случае функция возвращается в начало цикла, чтобы сделать еще одну попытку выделить буфер и прочесть ссылку.

Поделиться:
Популярные книги

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Турнир

Скиба Николай
7. Зверолов
Фантастика:
фэнтези
рпг
уся
фантастика: прочее
попаданцы
6.00
рейтинг книги
Турнир

Чай и водка в истории России

Похлебкин Вильям Васильевич
Дом и Семья:
кулинария
6.25
рейтинг книги
Чай и водка в истории России

Деспот

Арская Арина
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Деспот

Странники

Измайлова Кира Алиевна
Фантастика:
фэнтези
юмористическая фантастика
8.77
рейтинг книги
Странники

Боярышня Евдокия

Меллер Юлия Викторовна
3. Боярышня
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Боярышня Евдокия

За миллиард лет до конца света (сборник)

Стругацкие Аркадий и Борис
Фантастика:
научная фантастика
8.45
рейтинг книги
За миллиард лет до конца света (сборник)

Достоевский

Гроссман Леонид Петрович
357. Жизнь замечательных людей
Документальная литература:
биографии и мемуары
5.00
рейтинг книги
Достоевский

Законник Российской Империи

Ткачев Андрей Юрьевич
1. Словом и делом
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Законник Российской Империи

Первый среди равных. Книга IX

Бор Жорж
9. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга IX

Наша навсегда

Зайцева Мария
2. Наша
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
Наша навсегда

Большая Советская Энциклопедия (РЫ)

Большая Советская Энциклопедия
Справочная литература:
энциклопедии
5.00
рейтинг книги
Большая Советская Энциклопедия (РЫ)

Гуманитарное знание и вызовы времени

Коллектив авторов
Humanitas
Научно-образовательная:
культурология
5.00
рейтинг книги
Гуманитарное знание и вызовы времени

Кодекс Охотника. Книга X

Винокуров Юрий
10. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
6.25
рейтинг книги
Кодекс Охотника. Книга X