5.5.3.1. Подделка utime(file, NULL)

5.5.3.1. Подделка utime(file, NULL)

Некоторые более старые системы не устанавливают значения времени доступа и изменения равным текущему времени, когда второй аргумент utime() равен NULL. Однако код более высокого уровня (такой, как GNU touch) проще, если он может полагаться на один стандартизованный интерфейс.

Поэтому библиотека GNU Coreutils содержит замещающую функцию для utime(), которая обрабатывает этот случай, которую потом может вызвать код более высокого уровня. Это отражает принцип проектирования «выбор лучшего интерфейса для работы», который мы описали в разделе 1.5 «Возвращаясь к переносимости».

Замещающая функция находится в файле lib/utime.c в дистрибутиве Coreutils Следующий код является версией из Coreutils 5.0. Номера строк относятся к началу файла:

24 #include <sys/types.h>

25

26 #ifdef HAVE_UTIME_H

27 # include <utime.h>

28 #endif

39

30 #include "full-write.h"

31 #include "safe-read.h"

32

33 /* Некоторые системы (даже имеющие <utime.h>) нигде не объявляют

34    эту структуру. */

35 #ifndef HAVE_STRUCT_UTIMBUF

36 struct utimbuf

37 {

38  long actime;

39  long modtime;

40 };

41 #endif

42

43 /* Эмулировать utime(file, NULL) для систем (подобных 4.3BSD),

44    которые не устанавливают в этом случае текущее время для времени

45    доступа и изменения file. Вернуть 0, если успешно, -1 если нет. */

46

47 static int

48 utime_null(const char *file)

49 {

50 #if HAVE_UTIMES_NULL

51  return utimes(file, 0);

52 #else

53  int fd;

54  char c;

55  int status = 0;

56  struct stat sb;

57

58  fd = open(file, O_RDWR);

59  if (fd < 0

60   || fstat(fd, &sb) < 0

61   || safe_read(fd, &c, sizeof c) == SAFE_READ_ERROR

62   || lseek(fd, (off_t)0, SEEK_SET) < 0

63   || full_write(fd, &c, sizeof c) != sizeof с

64 /* Можно сделать - это необходимо на SunOS4.1.3 с некоторой комбинацией

65    заплат, но та система не использует этот код: у нее есть utimes.

66   || fsync(fd) < 0

67    */

68   || (st.st_size == 0 && ftruncate(fd, st.st_size) < 0)

69   || close(fd) < 0)

70   status = -1;

71  return status;

72 #endif

73 }

74

75 int

76 rpl_utime(const char *file, const struct utimbuf *times)

77 {

78  if (times)

79   return utime(file, times);

80

81  return utime_null(file);

82 }

Строки 33–41 определяют структуру struct utimbuf; как сказано в комментарии, некоторые системы не объявляют эту структуру. Работу осуществляет функция utime_null(). Используется системный вызов utimes(), если он доступен (utimes() является сходным, но более развитым системным вызовом, который рассматривается в разделе 14.3.2 «Файловое время в микросекундах: utimes().» Он допускает также в качестве второго аргумента NULL, что означает использование текущего времени.)

В случае, когда время должно обновляться вручную, код осуществляет обновление, прочитав сначала из файла байт, а затем записав его обратно. (Первоначальный touch Unix работал таким способом.) Операции следующие:

1. Открыть файл, строка 58.

2. Вызвать для файла stat(), строка 60.

3. Прочесть один байт, строка 61 Для наших целей safe_read() действует подобно read(); это объясняется в разделе 10.4.4 «Повторно запускаемые системные вызовы»).

4. Переместиться обратно на начало файла с помощью lseek(), строка 62. Это сделано для записи только что прочитанного байта обратно поверх себя.

5. Записать байт обратно, строка 63. full_write() действует подобно write(); это также рассматривается в разделе 10.4.4 «Повторно запускаемые системные вызовы»).

6. Если файл имеет нулевой размер, использовать ftruncate() для установки его размера в ноль (строка 68). Это не изменяет файл, но имеет побочный эффект обновления времени доступа и изменения (ftruncate() была описана в разделе 4 8 «Установка длины файла».)

7. Закрыть файл, строка 69.

Все эти шаги осуществляются в одной длинной последовательной цепи проверок внутри if. Проверки сделаны так, что если любое сравнение неверно, utime_null() возвращает -1, как обычный системный вызов, errno автоматически устанавливается системой для использования кодом более высокого уровня.

Функция rpl_utime() (строки 75–82) является «заместителем utime()». Если второй аргумент не равен NULL, она вызывает настоящую utime(). В противном случае она вызывает utime_null().

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг:

Объект file

Из книги автора

Объект file Последним из основных объектов подсистемы VFS рассмотрим объект файла. Объект File используется для представления файлов, которые открыты процессом. Когда мы думаем о подсистеме VFS с точки зрения пространства пользователя, то объект файла — это то, что первое


(8.11) После подключения дополнительного жесткого диска W2k перестал загружаться. После ввода пароля говорит, что "your system has no paging file, or the paging file is too small" и снова выдает окно логона. Что делать?

Из книги автора

(8.11) После подключения дополнительного жесткого диска W2k перестал загружаться. После ввода пароля говорит, что "your system has no paging file, or the paging file is too small" и снова выдает окно логона. Что делать? Данная проблема появляется, если буква загрузочного раздела не совпадает с буквой,


File

Из книги автора

File Официальная ссылкаFile (3.39): ftp://ftp.gw.com/mirrors/pub/unix/file/Содержимое FileПоследняя проверка: версия 3.39.ПрограммыfileОписанияfilefile проверяет указанные файлы с целью их классификации. Есть 3 набора тестов, запускаемых в данном порядке: тесты файловой системы, тесты magic number и тесты


Урок 37. Подделка фотографий

Из книги автора

Урок 37. Подделка фотографий С развитием цифровых технологий появилась возможность гибкого и удобного монтажа. Помимо практического применения данной технологии в производственных целях, подделка фотографии также служит хорошим развлечением, которым вы сможете в


WWW File Share Pro

Из книги автора

WWW File Share Pro Производитель: LionMax Software (http://www.wfshome.com).Статус: коммерческая.Страница для скачивания: http://www.wfshome.com/download.htm.Размер: 2,7 Мбайт.Эта программа предназначена для открытия и настройки на компьютере простого HTTP-сервера, который можно применять для обмена файлами с


6.5.1. /dev/null

Из книги автора

6.5.1. /dev/null Устройство /dev/null служит двум целям.? Linux удаляет любые данные, направляемые в устройство /dev/null. В тех случаях, когда выводные данные программы не нужны, в качестве выходного файла назначают устройство /dev/null, например:% verbose_command > /dev/null? При чтении из устройства


Атрибут NOT NULL

Из книги автора

Атрибут NOT NULL Включите этот атрибут в описание домена, если вы хотите, чтобы все столбцы, создаваемые на основе этого домена, имели непустое значение.NULL - который является не значением, а состоянием, - всегда будет недопустимым для любого столбца, имеющего атрибут NOT NULL.


Ограничение NOT NULL

Из книги автора

Ограничение NOT NULL Firebird не поддерживает атрибут указания допустимости пустого значения, как это делают некоторые нестандартные СУБД. В соответствии со стандартами все столбцы в Firebird могут содержать пустое значение, если не будет явно указано ограничение NOT NULL.


Предикат IS [NOT] NULL

Из книги автора

Предикат IS [NOT] NULL IS NULL и его противоположность IS NOT NULL являются парой предикатов, которые не используют группирование. Поскольку NULL не является значением, эти операторы не являются операторами сравнения. Они проверяют утверждение, что объект в левой части имеет значение (IS


Обсуждение NULL

Из книги автора

Обсуждение NULL NULL может оказаться довольно сложным для людей, ранее работавших с настольными базами данных, которые просто использовали NULL для хранения "нулевых значений": пустая строка, ноль для чисел, ложь для логических столбцов и т.д. В SQL любой элемент данных в столбце,


NULL в выражениях

Из книги автора

NULL в выражениях NULL не является значением, следовательно, он не может быть "равным" какому-либо значению. Например, воз такой предикатWHERE (COL1 = NULL)вернет ошибку, потому что оператор равенства не является действительным для NULL, NULL является состоянием, и правильным предикатом


NULL в вычислениях

Из книги автора

NULL в вычислениях В выражении пустой операнд даст результат вычисления NULL. Например, следующий операторUPDATE TABLEASET COL4 = COL4 + C0L5;присвоит столбцу COL4 значение NULL, если значением COL5 является NULL.В агрегатном (обобщающем) выражении, использующем операторы типа SUMO, AVG() или COUNT (<ИМЯ


Глава 28. /dev/zero и /dev/null

Из книги автора

Глава 28. /dev/zero и /dev/null /dev/nullПсевдоустройство /dev/null -- это, своего рода, "черная дыра" в системе. Это, пожалуй, самый близкий смысловой эквивалент. Все, что записывается в этот файл, "исчезает" навсегда. Попытки записи или чтения из этого файла не дают, ровным счетом, никакого