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

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

Жанры

Linux программирование в примерах
Шрифт:

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

Некоторое дополнительное разъяснение: условие '

SIZE_MAX / 2 < SSIZE_MAX
' верно лишь на системах, в которых '
SIZE_MAX < 2 * SSIZE_MAX
'; мы не знаем таких, но лишь на таких системах
buf_size
может обернуться в ноль. Поскольку на практике это условие не может быть истинным, компилятор может оптимизировать все выражение, включив следующую проверку '
buf_size == 0
'. После прочтения этого кода вы можете спросить: «Почему не использовать
lstat
для получения размера символической ссылки, не выделить буфер нужного размера с помощью
malloc
, и все?» На это есть несколько причин. [61]

61

Спасибо Джиму Мейерингу (Jim Meyering) за объяснение проблем — Примеч. автора.

• 

lstat
является системным вызовом — лучше избежать накладных расходов по его вызову, поскольку содержимое большинства символических ссылок поместится в первоначальный размер буфера в 128.

• Вызов

lstat
создает условие состязания: ссылка может измениться между исполнением
lstat
и
readlink
, в любом случае вынуждая повторение.

• Некоторые системы не заполняют должным образом член

st_size
для символической ссылки. (Печально, но верно.) Сходным образом, как мы увидим в разделе 8.4.2 «Получение текущего каталога:
getcwd
», Linux в
/proc
предоставляет специальные символические ссылки, у которых
st_size
равен нулю, но для которых
readlink
возвращает действительное содержимое.

Наконец, буфер не слишком большой,

xreadlink
использует
free
и
malloc
с большим размером вместо
realloc
, чтобы избежать бесполезного копирования, которое делает
realloc
. (Поэтому комментарий в строке 58 устарел, поскольку
realloc
не используется; это исправлено в версии Coreutils после 5.0.)

5.5. Смена владельца, прав доступа и времени изменения

Несколько других системных вызовов дают вам возможность изменять другие относящиеся к файлу сведения: в частности, владельца и группу файла, права доступа к файлу и времена доступа и изменения файла.

5.5.1. Смена владельца файла:

chown
,
fchown
и
lchown

Владелец и группа файла изменяются с помощью трех сходных системных вызовов.

#include <sys/types.h> /* POSIX */

#include <unistd.h>

int chown(const char *path, uid_t owner, gid_t group);

int fchown(int fd, uid_t owner, gid_t group);

int lchown(const char *path, uid_t owner, gid_t group);

chown
работает с аргументом имени файла,
fchown
работает с открытым файлом, а
lchown
работает с символической ссылкой вместо файла, на который эта ссылка указывает. Во всех других отношениях эти три вызова работают идентично, возвращая 0 в случае успеха и -1 при ошибке.

Стоит заметить, что один системный вызов изменяет как владельца, так и группу файла. Чтобы изменить лишь владельца или лишь группу, передайте (-1) в качестве того идентификационного номера, который должен остаться без изменений.

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

Я снова граф. Книга XI

Дрейк Сириус
11. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я снова граф. Книга XI

Третий Генерал: Том VI

Зот Бакалавр
5. Третий Генерал
Фантастика:
городское фэнтези
аниме
сказочная фантастика
попаданцы
гаремник
5.00
рейтинг книги
Третий Генерал: Том VI

Ученик. Книга 4

Первухин Андрей Евгеньевич
4. Ученик
Фантастика:
фэнтези
5.67
рейтинг книги
Ученик. Книга 4

Герой

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

Вперед в прошлое 7

Ратманов Денис
7. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 7

Печать Пожирателя 3

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

Законы Рода. Том 6

Андрей Мельник
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4

Я не князь. Книга XIII

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

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

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

Я не царь. Книга XXIV

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

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

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

Третий Генерал: Том VIII

Зот Бакалавр
7. Третий Генерал
Фантастика:
городское фэнтези
аниме
сказочная фантастика
попаданцы
5.00
рейтинг книги
Третий Генерал: Том VIII

Запечатанный во тьме. Том 2

NikL
2. Хроники Арнея
Фантастика:
уся
эпическая фантастика
фэнтези
5.00
рейтинг книги
Запечатанный во тьме. Том 2