5.4.4. Определение типа файла

5.4.4. Определение типа файла

Вспомните, что в поле st_mode закодированы как тип файла, так и права доступа к нему. <sys/stat.h> определяет ряд макросов, которые определяют тип файла. В частности, эти макросы возвращают true или false при использовании с полем st_mode. У каждого описанного ранее типа файла есть свой макрос. Предположим, выполняется следующий код:

struct stat stbuf;

char filename[PATH_МАХ]; /* PATH_MAX из <limits.h> */

/* ... поместить имя файла в filename ... */

if (stat(filename, &stbuf) < 0) {

 /* обработать ошибку */

}

Когда система заполнила stbuf, можно вызывать следующие макросы, причем в качестве аргумента передается stbuf.st_mode:

S_ISREG(stbuf.st_mode)

Возвращает true, если filename является обычным файлом.

S_ISDIR(stbuf.st_mode)

Возвращает true, если filename является каталогом.

S_ISCHR(stbuf.st_mode)

Возвращает true, если filename является символьным устройством. Устройства вскоре будут обсуждены более подробно.

S_ISBLK(stbuf.st_mode)

Возвращает true, если filename является блочным устройством.

S_ISFIFO(stbuf.st_mode)

Возвращает true, если filename является FIFO.

S_ISLNK(stbuf.st_mode)

Возвращает true, если filename является символической ссылкой. (Это может никогда не вернуть true, если вместо lstat() использовались stat() или fstat().)

S_ISSOCK(stbuf.st_mode)

Возвращает true, если filename является сокетом.

ЗАМЕЧАНИЕ. В GNU/Linux эти макросы возвращают 1 для true и 0 для false. Однако, на других системах возможно, что они будут возвращать для true вместо 1 произвольное неотрицательное число. (POSIX определяет лишь ненулевое значение в противоположность нулевому). Поэтому всегда следует использовать эти макросы как автономные тесты вместо проверки возвращаемого значения.

/* Корректное использование */

if (S_ISREG(stbuf.st_mode)) ...

/* Heкорректное использование */

if (S_ISREG(stbuf.st_mode) ==1) ...

Наряду с макросами <sys/stat.h> предоставляет два набора битовых масок. Один набор для проверки прав доступа, а другой - для проверки типа файла. Мы видели маски прав доступа в разделе 4.6 «Создание файлов», когда обсуждали тип mode_t и значения для open() и creat(). Битовые маски, их числовые значения для GNU/Linux и смысл приведены в табл. 5.2.

Таблица 5.2. Битовые маски POSIX для типов файлов и прав доступа в <sys/stat.h>

Маска Значение Комментарий S_IFMT 0170000 Маска для битовых полей типа файла S_IFSOCK 0140000 Сокет. S_IFLNK 0120000 Символическая ссылка S_IFREG 0100000 Обычный файл. S_IFBLK 0060000 Блочное устройство. S_IFDIR 0040000 Каталог. S_IFCHR 0020000 Символьное устройство. S_IFIFO 0010000 FIFO. S_ISUID 0004000 Бит setuid. S_ISGID 0002000 Бит setgid S_ISVTX 0001000 «Липкий» (sticky) бит. S_IRWXU 0000700 Маска для прав доступа владельца. S_IRUSR 0000400 Доступ на чтение для владельца. S_IWUSR 0000200 Доступ на запись для владельца. S_IXUSR 0000100 Доступ на исполнение для владельца. S_IRWXG 0000070 Маска для прав доступа группы. S_IRGRP 0000040 Доступ на чтение для группы. S_IWGRP 0000020 Доступ на запись для группы. S_IXGRP 0000010 Доступ на исполнение для группы. S_IRWXO 0000007 Маска для прав доступа остальных. S_IROTH 0000004 Доступ на чтение для остальных. S_IWOTH 0000002 Доступ на запись для остальных. S_IXOTH 0000001 Доступ на исполнение для остальных.

Некоторые из этих масок служат цели изолирования различных наборов битов, закодированных в поле st_mode:

• S_IFMT представляет биты 12–15, которыми закодированы различные типы файлов.

• S_IRWXU представляет биты 6–8, являющиеся правами доступа владельца (на чтение, запись, исполнение для User).

• S_IRWXG представляет биты 3–5, являющиеся правами доступа группы (на чтение, запись, исполнение для Group).

• S_IRWXO представляет биты 0–2, являющиеся правами доступа для «остальных» (на чтение, запись, исполнение для Other).

Биты прав доступа и типа файла графически изображены на рис. 5.3.

Рис. 5.3. Биты прав доступа и типа файлов

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

Стандарт POSIX явным образом констатирует; что в будущем не будут стандартизированы новые битовые маски и что тесты для любых дополнительных разновидностей типов файлов, которые могут быть добавлены, будут доступны лишь в виде макросов S_ISxxx().