13:
14: #include <errno.h>
15: #include <fcntl.h>
16: #include <linux/ext3_fs.h>
17: #include <stdio.h>
18: #include <string.h>
19: #include <sys/ioctl.h>
20: #include <unistd.h>
21:
22: int main(int argc, const char **argv) {
23: const char **filename = argv + 1;
24: int fd;
25: int flags = 0;
26:
27: /* Убедиться, что указаны устанавливаемые флаги, вместе
28: с именами файлов. Позволить установить '0', как признак
29: того, что все флаги должны быть сброшены. */
30: if (argc<3){
31: fprintf(stderr, 'Использование setflags: [0][I][A][S][N]'
32: '<filenames>
');
33: return 1;
34: }
35:
36: /* каждая буква представляет флаг; установить
37: флаг, которые указаны */
38: if (strchr(argv[1], 'I') ) flags |= EXT3_IMMUTABLE_FL;
39: if (strchr(argv[1], 'A') ) flags |= EXT3_APPEND_FL;
40: if (strchr(argv[1], 'S') ) flags |= EXT3_SYNC_FL;
41: if (strchr(argv[1], 'N') ) flags |= EXT3_NODUMP_FL;
42:
43: /* пройти по всем именам в argv[] */
44: while (*(++filename)) {
45: /* В отличие от нормальных атрибутов, атрибута ext3 можно опрашивать,
46: только если есть файловый дескриптор (имя файла не годится).
47: Для выполнения запроса атрибутов ext3 нам не нужен доступ на запись,
48: поэтому O_RDONLY подойдет. */
49: fd = open(*filename, O_RDONLY);
50: if (fd < 0) {
51: fprintf(stderr, 'невозможно открыть %s:%s
', *filename,
52: strerror(errno));
53: return 1;
54: }
55:
56: /* Установить атрибуты в соответствии с переданными
57: флагами. */
58: if (ioctl(fd, EXT3_IOC_SETFLAGS, &flags)) {
59: fprintf(stderr, 'Сбой ioctl в %s:%s
', *filename,
60: strerror(errno));
61: return 1;
62: }
63: close(fd);
64: }
65:
66: return 0;
67: }
11.4. Манипулирование содержимым каталогов
Вспомните, что компоненты каталогов (имена файлов) — это ни что иное, как указатели на дисковые информационные узлы (on-disk inodes); почти вся важная информация, касающаяся файла, хранится в его inode. Вызов open()
позволяет процессу создавать компоненты каталогов, которые являются обычными файлами, но для создания файлов других типов и для манипулирования компонентами каталогов могут понадобиться другие функции. Функции, которые позволяют создавать, удалять и выполнять поиск каталогов, описаны в главе 14; файлы сокетов — в главе 17. В настоящем разделе раскрываются символические ссылки, файлы устройств и FIFO.
11.4.1. Создание входных точек устройств и именованных каналов
Процессы создают файлы устройств и именованных каналов в файловой системе с помощью вызова mknod()
.
#include <fcntl.h>
#include <unistd.h>
int mknod(const char *pathname, mode_t mode, dev_t dev);
pathname
— это имя файла, который нужно создать, mode
— это и режим доступа (который модифицируется текущим umask
), и тип нового файла (S_IFIFO
, S_IFBLK
, S_IFCHR
). Последний параметр, dev
, содержит старший (major) и младший (minor) номера создаваемого устройства. Тип устройства (символьное или блочное) и старший номер устройства сообщают ядру, какой драйвер устройств отвечает за операции с этим файлом устройства. Младший номер используется внутри драйвером устройства, чтобы различать отдельные устройства среди многих, которыми он управляет. Только пользователю root разрешено создавать файлы устройств; именованные же каналы могут создавать все пользователи.
Заголовочный файл <sys/sysmacros.h>
представляет три макроса для манипулирования значениями типа dev_t
. Макрос makedev()
принимает старшие номера в первом аргументе, младшие — во втором и возвращает значение dev_t
, ожидаемое mknod()
. Макросы major()
и minor()
принимают значение типа dev_t
в качестве единственного аргумента и возвращают, соответственно, старший и младший номер устройства.
Программа mknod
, доступная в Linux, предоставляет пользовательский интерфейс к системному вызову mknod()
(подробности см. в man 1 mknod
). Ниже приведена упрощенная реализация mknod
для иллюстрации системного вызова mknod()
. Следует отметить, что программа создает файл с режимом доступа 0666