Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

14:

15: int find (const char * file, const struct stat * sb, int flags,

16: struct FTW * f) {

17: if (f->level < minDepth) return 0;

18: if (f->level > maxDepth) return 0;

19: if (name && fnmatch(name, file + f->base, FNM_PERIOD)) return 0;

20:

21: if (flags == FTW_DNR) {

22: fprintf(stderr, "find: %s: недопустимые полномочия\n", file);

23: } else {

24: printf("%s\n", file);

25: }

26:

27: return 0;

28: }

29:

30: int main(int argc, const char ** argv) {

31: int flags = FTW_PHYS;

32: int i;

33: int problem = 0;

34: int tmp;

35: int rc;

36: char * chptr;

37:

38: /*
поиск первого параметры командной строки (который должен

39: находиться после списка путей */

40: i = 1;

41: while (i < argc && *argv[i] != '-') i++;

42:

43: /* обработать опции командной строки */

44: while (i < argc && !problem) {

45: if (!strcmp(argv[i], "-name")) {

46: i++;

47: if (i == argc)

48: problem = 1;

49: else

50: name = argv[i++];

51: } else if (!strcmp(argv[i], "-depth")) {

52: i++;

53: flags |= FTW_DEPTH;

54: } else if (!strcmp (argv[i], "-mount") ||

55: !strcmp(argv[i], "-xdev")) {

56: i++;

57: flags |= FTW_MOUNT;

58: } else if (!strcmp (argv[i], "-mindepth") ||

59: !strcmp (argv[i], "-maxdepth")) {

60: i++;

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] .

103

Это то же, что и метод, используемый для владения файлами (глава 13).

104

Обработчик сигналов все еще следует регистрировать с помощью флага

SA_SIGINFO
, чтобы файловый дескриптор надлежащим образом получил доступ к сигналу.

Поделиться с друзьями: