Системным вызовам stat() и lstat() не требуются права на доступ к самому файлу. Однако необходимо, чтобы у всех родительских каталогов, указанных в переменной pathname, было право на выполнение (поиск). Системный вызов fstat() всегда завершается успешно, если ему передан корректный дескриптор файла.

Все эти вызовы возвращают в буфер структуру stat, на которую указывает переменная statbuf. Форма данной структуры такова:

struct stat {

dev_t st_dev; /* Идентификатор устройства,

на котором находится файл */

ino_t st_ino; /* Номер индексного дескриптора файла */

mode_t st_mode; /* Тип файла и права доступа */

nlink_t st_nlink; /* Количество (жестких) ссылок на файл */

uid_t st_uid; /* Пользовательский ID владельца файла */

gid_t st_gid; /* Групповой ID владельца файла */

dev_t st_rdev; /* Идентификаторы файлов устройств */

off_t st_size; /* Общий размер файла (в байтах) */

blksize_t st_blksize; /* Оптимальный размер блока

для ввода-вывода (в байтах) */

blkcnt_t st_blocks; /* Количество отведенных блоков (по 512 байт) */

time_t st_atime; /* Время последнего доступа к файлу */

time_t st_mtime; /* Время последнего изменения файла */

time_t st_ctime; /* Время последнего изменения статуса */

};

Различные типы данных, которые используются для представления полей в структуре stat, определены в стандарте SUSv3. Дополнительную информацию об этих типах см. в подразделе 3.6.2.

Согласно стандарту SUSv3 если системный вызов lstat() применяется к символической ссылке, то он в обязательном порядке возвращает корректную информацию только в поле st_size, а также в компонент типа файла (записанный в краткой форме) поля st_mode. Остальные поля (например, поля с метками времени) не обязаны содержать корректную информацию. Это позволяет отказаться от их поддержки, чтобы повысить эффективность. В частности, целью ранних стандартов UNIX являлась возможность реализации символической ссылки либо как индексного дескриптора, либо как элемента в каталоге. В более поздних версиях невозможно реализовать все поля, которые необходимы структуре stat. (Во всех главных современных реализациях UNIX символические ссылки представлены как индексные дескрипторы.) В Linux системный вызов lstat() возвращает информацию во все поля структуры stat, когда применен к символической ссылке.

Ниже мы рассмотрим более подробно некоторые поля структуры stat и в завершение — пример программы, отображающей всю структуру stat.

Идентификаторы устройств и индексный дескриптор

Поле st_dev идентифицирует устройство, на котором находится файл. Поле st_ino содержит индексный дескриптор этого файла. Комбинация значений st_dev и st_ino уникальным образом идентифицирует файл во всех файловых системах. В типе dev_t записаны старший и младший номера устройства (см. раздел 14.1).

Если это индексный дескриптор устройства, то поле st_rdev содержит старший и младший номера данного устройства.

Старший и младший номера, содержащиеся в значении dev_t, можно извлечь с помощью двух макросов: major() и minor(). Заголовочный файл, который необходим для объявления этих макросов, отличается для разных реализаций UNIX. В Linux они объявляются с помощью файла , если определен макрос _BSD_SOURCE.

Величина целочисленных значений, возвращаемых макросами major() и minor(), различна для разных реализаций UNIX. Для совместимости мы всегда приводим возвращаемые значения к типу long при их выводе на печать (см. подраздел 3.6.2).

Принадлежность файла

Поля st_uid и st_gid идентифицируют соответственно владельца (пользовательский ID) и группу (групповой ID), которым принадлежит файл.

Счетчик ссылок

Поле st_nlink — это количество (жестких) ссылок на файл. Они подробно описаны в главе 13.

Тип файла и права доступа

Поле st_mode является битовой маской, которая служит двум целям: идентификации типа файла и указанием прав доступа к нему. Биты этого поля располагаются так, как показано на рис. 15.1.

Рис. 15.1.Битовая маска поля st_mode

Тип файла можно извлечь из данного поля с помощью операции И, задействуя константу S_IFMT. (В Linux для обозначения типа файла использованы четыре бита поля st_mode. Но, поскольку в стандарте SUSv3 не оговорено, каким образом представлять тип файла, детали могут быть различными в разных реализациях.) Затем результат можно сравнить с набором констант, чтобы определить тип файла. Например, так:

if ((statbuf.st_mode & S_IFMT) == S_IFREG)

printf("regular file\n");

Поскольку данная операция довольно обычная, для упрощения написанного выше применяется стандартный макрос:

if (S_ISREG(statbuf.st_mode))

printf("regular file\n");

Перейти на страницу:

Похожие книги