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

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

Жанры

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
обернулся в ноль. (Это маловероятные условия, но странные вещи все же случаются.) Если одно из этих условий верно, программа завершается с сообщением об ошибке. В противном случае функция возвращается в начало цикла, чтобы сделать еще одну попытку выделить буфер и прочесть ссылку.

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

Мир повелителей смерти

Муравьёв Константин Николаевич
10. Живучий
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Мир повелителей смерти

Курсант: назад в СССР 2

Дамиров Рафаэль
2. Курсант
Фантастика:
попаданцы
альтернативная история
6.33
рейтинг книги
Курсант: назад в СССР 2

Разведчик. Заброшенный в 43-й

Корчевский Юрий Григорьевич
Героическая фантастика
Фантастика:
боевая фантастика
попаданцы
альтернативная история
5.93
рейтинг книги
Разведчик. Заброшенный в 43-й

Вернувшийся: Посол. Том IV

Vector
4. Вернувшийся
Фантастика:
космическая фантастика
киберпанк
5.00
рейтинг книги
Вернувшийся: Посол. Том IV

Древесный маг Орловского княжества

Павлов Игорь Васильевич
1. Орловское княжество
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Древесный маг Орловского княжества

Звездная Кровь. Экзарх III

Рокотов Алексей
3. Экзарх
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Экзарх III

Искатель 10

Шиленко Сергей
10. Валинор
Фантастика:
рпг
фэнтези
попаданцы
гаремник
5.00
рейтинг книги
Искатель 10

Надуй щеки! Том 2

Вишневский Сергей Викторович
2. Чеболь за партой
Фантастика:
попаданцы
дорама
фантастика: прочее
5.00
рейтинг книги
Надуй щеки! Том 2

«Колонист»

Поселягин Владимир Геннадьевич
2. Русич
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
«Колонист»

Царь царей

Билик Дмитрий Александрович
9. Бедовый
Фантастика:
фэнтези
мистика
5.00
рейтинг книги
Царь царей

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

"Новый Михаил-Империя Единства". Компиляцияя. Книги 1-17

Марков-Бабкин Владимир
Избранные циклы фантастических романов
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Новый Михаил-Империя Единства. Компиляцияя. Книги 1-17

Барон не играет по правилам

Ренгач Евгений
1. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон не играет по правилам

Мрак

Мартовский Кот
Фантастика:
постапокалипсис
5.00
рейтинг книги
Мрак