Вывод должен представлять строку в 10 символов, идентичную первому полю вывода 'ls -l
'. Другими словами, первый символ обозначает тип файла, а остальные девять — права доступа.
Когда установлены биты S_ISUID
и S_IXUSR
, используйте s
вместо x
; если установлен лишь бит I_ISUID
, используйте S
. То же относится к битам S_ISGID
и S_IXGRP
. Если установлены оба бита S_ISVTX
и S_IXOTH
, используйте t
; для одного S_ISVTX
используйте T
.
Для простоты можете использовать статический (static
) буфер, содержимое которого перезаписывается при каждом вызове процедуры.
2. Доработайте ch05-catdir.c
, чтобы она вызывала stat()
для каждого найденного имени файла. Затем выведите номер индекса, результат вызова fmt_mode()
, число ссылок и имя файла.
3. Доработайте ch05-catdir.c
так, что если файл является символической ссылкой, программа будет также выводить имя указываемого файла.
4. Добавьте такую опцию, что если имя файла является именем подкаталога, программа рекурсивно входит в него и отображает сведения о файлах (и каталогах) этого подкаталога. Необходим лишь один уровень рекурсии.
5. Если вы не работаете на системе GNU/Linux, запустите ch05-trymkdir
(см. раздел 5.2 «Создание и удаление каталогов») на своей системе и сравните результаты с приведенными нами.
6. Напишите программу mkdir
. Посмотрите свою локальную справочную страницу для
7. В корневом каталоге, /
, как номер устройства, так и номер индекса для '.
' и '..
' совпадают. Используя эту информацию, напишите программу pwd
.
Вначале программа должна найти имя текущего каталога, прочитав содержимое родительского каталога. Затем она должна продолжить собирать сведения о иерархии файловой системы, пока не достигнет корневого каталога.
Отображение имени каталога в обратном порядке, от текущего каталога до корневого, легко. Как будет справляться ваша версия pwd
с выводом имени каталога правильным образом, от корневого каталога вниз?
8. Если вы написали pwd
, использовав рекурсию, напишите ее снова, использовав итерацию. Если вы использовали итерацию, напишите ее с использованием рекурсии. Что лучше? (Подсказка: рассмотрите очень глубоко вложенные деревья каталогов.)
9. Тщательно исследуйте функцию rpl_utime()
(см. раздел 5.5.3.1 «Подделка utime(file, NULL)
»). Какой ресурс не восстанавливается, если одна из проверок в середине if
не выполняется? (Спасибо Джеффу Колье (Geoff Collyer).)
10. (Трудное) Прочтите страницу справки для
Когда вы решите, что это работает, напишите свою собственную версию chmod
, которая применяет назначенные права доступа к каждому файлу или каталогу, указанному в командной строке. Какую функцию вы использовали, chmod()
— или open()
и fchmod()
— и почему?
Глава 6
Общие библиотечные интерфейсы — часть 1
В главе 5 «Каталоги и служебные данные файлов» мы видели, что непосредственное чтение каталога возвращает имена файлов в том порядке, в каком они хранятся в каталоге. Мы также видели, что struct stat
содержит всю информацию о файле за исключением его имени. Однако, некоторые компоненты этой структуры не могут использоваться непосредственно; они являются просто числовыми значениями.
В данной главе представлена оставшаяся часть API, необходимая для полного использования значений компонентов struct stat
. Мы по порядку рассматриваем следующие темы: значения time_t
для представления времени и функций форматирования времени; функции сортировки и поиска (для сортировки имен файлов или других данных); типы uid_t
и gid_t
для представления пользователей, групп и функций, которые сопоставляют их с соответствующими именами пользователей и групп; и наконец, функцию для проверки того, что дескриптор файла представляет терминал.
6.1. Времена и даты
Значения времени хранятся в типе, который известен как time_t
. Стандарт ISO С гарантирует, что это числовой тип, но во всем остальном никак не указывает, чем именно он является (целым или с плавающей точкой), как и не указывает степень точности хранящихся в нем значений.
На системах GNU/Linux и Unix значения time_t
представляют «секунды с начала Эпохи». Эпоха представляет собой начало записываемого времени, которое относится к полночи 1 января 1970 г. по UTC. На большинстве систем time_t
является long int
С. Для 32-разрядных систем это означает, что time_t
переполнится 19 января 2038 г. К тому времени, мы надеемся, тип time_t
будет переопределен как по меньшей мере 64-разрядное значение.