61: if (i == argc)
62: problem = 1;
63: else {
64: tmp = strtoul(argv[i++], &chptr, 10);
65: if (*chptr)
66: problem = 1;
67: else if (!strcmp(argv[i - 2], "-mindepth"))
68: minDepth = tmp;
69: else
70: maxDepth = tmp;
71: }
72: }
73: }
74:
75: if (problem) {
76: fprintf(stderr, "использование: find <пути> [-name <строка>]"
77: "[-mindepth <целое>] [-maxdepth <целое>]\n");
78: fprintf(stderr, " [-xdev] [-depth]\n");
79: return 1;
80: }
81:
82: if (argc == 1 || *argv[1] == '-') {
83: argv[1] = ".";
84: argc = 2;
85: }
86:
87: rc = 0;
88: i = 1;
89: flags = 0;
90: while (i < argc && *argv[i] != '-')
91: rc |= nftw (argv [i++], find, 100, flags);
92:
93: return rc;
94: }
14.8. Уведомление о смене каталога
Иногда приложения желают получать уведомления об изменении оглавления каталога. Например, диспетчеры файлов могут выводить оглавление каталога в окне и обновлять это окно каждый раз при изменении каталога другими программами. В то время как приложение регулярно перепроверяет каталог, Linux может послать программе сигнал о модификации каталога, позволяя своевременные обновления без накладных расходов и задержек на страничный обмен.
Системный вызов fcntl()
используется для регистрации уведомлений об обновлениях каталога. В главе 11 уже говорилось о том, что этот системный вызов принимает три аргумента. Первый аргумент — это интересующий файловый дескриптор, второй — это команда, которую необходимо выполнить fcntl()
, а последний — это целое число, специфическое для этой команды. Для уведомлений каталогов первый аргумент является файловым дескриптором, относящимся к интересующему каталогу. Это единственный случай, при котором каталог следует открывать с помощью нормального системного вызова open()
вместо opendir()
. Командой регистрации уведомлений является F_NOTIFY
, а последний аргумент определяет, какие типы событий вызывают отправку сигнала. Это должен быть один или несколько перечисленных ниже флагов, объединенных по логическому "ИЛИ".
DN_ACCESS | Файл в каталоге, который читается. |
DN_ATTRIB | Права владения или доступа к файлу в каталоге были изменены. |
DN_CREATE | В каталоге создан новый файл (включая новые жесткие ссылки на уже существующие файлы). |
DN_DELETE | Файл удален из каталога. |
DN_MODIFY | Файл в каталоге был модифицирован (тип модификации — усечение). |
DN_RENAME | Файл в каталоге был переименован. |
Для отмены уведомления о событии вызовите fcntl()
с командой F_NOTIFY
и последним аргументом, равным нулю.
Обычно уведомление каталога автоматически отменяется после передачи одного сигнала. Для эффективного уведомления каталога окончательный аргумент для fcntl()
должен быть объединен операцией "ИЛИ" с DN_MULTISHOT
, что вызывает отправку сигналов для всех подходящих событий до отмены уведомления.
По умолчанию для уведомления каталога передается SIGIO
. Если приложение желает использовать для этого другой сигнал (например, для разных каталогов могут понадобиться разные сигналы), можно применить команду F_SETSIG
в fcntl()
, а в качестве последнего аргумента определить нужный сигнал. Если используется F_SETSIG
(даже если установлен сигнал SIGIO
), ядро также помещает файловый дескриптор на каталог в элементе si_fd
аргумента обработчика сигналов siginfo_t
[103], позволяя приложению узнать, какие из контролируемых каталогов обновились[104].
Если контролируется несколько каталогов и для всех каталогов выбран один сигнал, крайне необходимо использовать сигнал реального времени, чтобы убедиться, что ни одно из событий не затерялось.