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

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

Жанры

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

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

Шрифт:

8. Если вы написали

pwd
, использовав рекурсию, напишите ее снова, использовав итерацию. Если вы использовали итерацию, напишите ее с использованием рекурсии. Что лучше? (Подсказка: рассмотрите очень глубоко вложенные деревья каталогов.)

9. Тщательно исследуйте функцию

rpl_utime
(см. раздел 5.5.3.1 «Подделка
utime(file, NULL)
»). Какой ресурс не восстанавливается, если одна из проверок в середине
if
не выполняется? (Спасибо Джеффу Колье (Geoff Collyer).)

10. (Трудное) Прочтите страницу справки для chmod(1). Напишите код для анализа аргумента символических опций, который позволяет

добавлять, удалять и устанавливать права доступа на основе владельца, группы, других и «всех».

Когда вы решите, что это работает, напишите свою собственную версию

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-разрядное значение.

Для получения текущего времени, вычисления разницы между двумя значениями

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

Отдельный набор функций предоставляет доступ к текущему времени с разрешением, большим чем одна секунда. Функции работают с предоставлением двух различных значений, времени в виде секунд с начала Эпохи и числа микросекунд в текущей секунде. Эти функции описаны далее в разделе 14.3.1 «Время в микросекундах:

gettimeofday
».

6.1.1. Получение текущего времени:

time
и
difftime

Системный

вызов
time
получает текущие дату и время;
difftime
вычисляет разницу между двумя значениями
time_t
:

#include <time.h> /* ISO С */

time_t time(time_t *t);

double difftime(time_t time1, time_t time0);

time
возвращает текущее время. Если параметр
t
не равен
NULL
, переменная, на которую указывает
t
, также заполняется значением текущего времени. Функция возвращает
(time_t)(-1)
, если была ошибка, устанавливая
errno
.

Хотя ISO С не указывает, чем является значение

time_t
, POSIX определяет, что оно представляет время в секундах. Поэтому это предположение является обычным и переносимым. Например, чтобы посмотреть, что значение времени представляет отметку в прошлом шесть месяцев назад или позже, можно использовать код, подобный этому:

/* Для краткости проверка ошибок опущена */

time_t now, then, some_time;

time(&now); /* Получить текущее время */

then = now - (6L * 31 * 24 * 60 * 60); /* Примерно 6 месяцев назад */

/* ...установить какое-нибудь время, например, через stat... */

if (some_time < then)

 /* более 6 месяцев назад */

else

 /* менее 6 месяцев назад */

Однако, поскольку переносимый код может потребоваться запустить на не-POSIX системах, существует функция

difftime
для вычисления разницы между двумя значениями времени. Тот же самый тест с использованием
difftime
можно было бы написать таким способом:

time_t now, some_value;

const double six_months = 6.0 * 31 * 24 * 60 * 60;

time(&now); /* Получить текущее время */

/* ...установить какое-нибудь время, например, через stat... */

if (difftime(now, some_time) >= six_months)

 /* более 6 месяцев назад */

else

 /* менее 6 месяцев назад */

Возвращаемым типом

difftime
является
double
, поскольку
time_t
может также содержать доли секунд. На системах POSIX он всегда представляет целые секунды.

В обоих предыдущих примерах обратите внимание на использование типизированных констант, чтобы форсировать выполнение вычислений с нужным математическим типом:

6L
в первом случае для целых
long
, 6.0 во втором случае для чисел с плавающей точкой

6.1.2. Разложение времени:

gmtime
и
localtime

На практике форма представления даты и времени в виде «секунд с начала эпохи» не является очень удобной, кроме очень простых сравнений. Самостоятельное вычисление компонентов времени, таких, как месяц, день, год и т.д., подвержено ошибкам, поскольку необходимо принять во внимание местный часовой пояс (возможно, с учетом перехода на летнее время), правильно вычислить високосные годы и пр. К счастью, две стандартные процедуры делают за вас эту работу:

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

Последний реанорец. Том I и Том II

Павлов Вел
1. Высшая Речь
Фантастика:
фэнтези
7.62
рейтинг книги
Последний реанорец. Том I и Том II

Хозяин Теней

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

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

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

Мастер Трав III

Мордорский Ваня
3. Мастер Трав
Фантастика:
фэнтези
рпг
фантастика: прочее
попаданцы
5.75
рейтинг книги
Мастер Трав III

Лекарь Империи 7

Карелин Сергей Витальевич
7. Лекарь Империи
Фантастика:
городское фэнтези
аниме
боевая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 7

Чехов книга 3

Гоблин (MeXXanik)
3. Адвокат Чехов
Фантастика:
попаданцы
альтернативная история
аниме
6.00
рейтинг книги
Чехов книга 3

Газлайтер. Том 6

Володин Григорий
6. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 6

Третий. Том 3

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

Страж Кодекса. Книга VI

Романов Илья Николаевич
6. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса. Книга VI

Перешагнуть пропасть

Муравьёв Константин Николаевич
1. Перешагнуть пропасть
Фантастика:
боевая фантастика
космическая фантастика
8.38
рейтинг книги
Перешагнуть пропасть

Наномашины, Кошмар Академии! Том 10

Новиков Николай Васильевич
10. Первый среди карапузов
Фантастика:
аниме
попаданцы
5.00
рейтинг книги
Наномашины, Кошмар Академии! Том 10

Ким

Киплинг Редьярд Джозеф
Приключения:
исторические приключения
7.62
рейтинг книги
Ким

Его звали Тони. Книга 5

Кронос Александр
5. Щенки косуль
Фантастика:
городское фэнтези
технофэнтези
попаданцы
7.00
рейтинг книги
Его звали Тони. Книга 5

Эпоха Опустошителя. Том V

Павлов Вел
5. Вечное Ристалище
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Эпоха Опустошителя. Том V