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

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

Жанры

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

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

Мессия

Старлинг Борис
121. Книга-загадка, книга-бестселлер
Детективы:
триллеры
маньяки
7.23
рейтинг книги
Мессия

Граф

Ланцов Михаил Алексеевич
6. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Граф

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

Рокотов Алексей
2. Экзарх
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
Звездная Кровь. Экзарх II

Хозяин Теней 6

Петров Максим Николаевич
6. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 6

На границе империй. Том 10. Часть 10

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 10

Наследник

Назимов Константин Геннадьевич
3. Травник
Фантастика:
фэнтези
6.80
рейтинг книги
Наследник

Практик

Листратов Валерий
5. Ушедший Род
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Практик

Бастард Императора. Том 5

Орлов Андрей Юрьевич
5. Бастард Императора
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 5

Эволюционер из трущоб

Панарин Антон
1. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб

Сталин

Радзинский Эдвард Станиславович
3. Загадки жизни и смерти
Проза:
историческая проза
7.36
рейтинг книги
Сталин

Вернуть невесту. Ловушка для попаданки

Ардова Алиса
1. Вернуть невесту
Любовные романы:
любовно-фантастические романы
8.49
рейтинг книги
Вернуть невесту. Ловушка для попаданки

Тринадцатый V

NikL
5. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Тринадцатый V

Начало

Харенко Алина Александровна
1. Второй шанс
Фантастика:
фэнтези
5.00
рейтинг книги
Начало

Цикл "Отмороженный". Компиляция. Книги 1-14

Гарцевич Евгений Александрович
Отмороженный
Фантастика:
боевая фантастика
рпг
постапокалипсис
5.00
рейтинг книги
Цикл Отмороженный. Компиляция. Книги 1-14