13 #define SPARE_FDS 5 /* fds для использования другими функциями, см. текст */
14
15 extern int process(const char *file, const struct stat *sb,
16 int flag, struct FTW *s);
17
18 /* usage --- print message and die */
19
20 void usage(const char *name)
21 {
22 fprintf(stderr, "usage: %s (-c) directory ...\n", name);
23 exit(1);
24 }
25
26 /* main --- вызвать nftw() для каждого аргумента командной строки */
27
28 int main(int argc, char **argv)
29 {
30 int i, c, nfds;
31 int errors = 0;
32 int flags = FTW_PHYS;
33 char start[PATH_MAX], finish[PATH_MAX];
34
35 while ((c = getopt(argc, argv, "с")) != -1) {
36 switch (c) {
37 case 'c':
38 flags |= FTW_CHDIR;
39 break;
40 default:
41 usage(argv[0]);
42 break;
43 }
44 }
45
46 if (optind == argc)
47 usage(argv[0]);
48
49 getcwd(start, sizeof start);
50
51 nfds = getdtablesize() - SPARE_FDS; /* оставить несколько запасных дескрипторов */
52 for (i = optind; i < argc; i++) {
53 if (nftw(argv[i], process, nfds, flags) != 0) {
54 fprintf(stderr, "%s: %s: stopped early\n",
55 argv[0], argv[i]);
56 errors++;
57 }
58 }
59
60 if ((flags & FTW_CHDIR) != 0) {
61 getcwd(finish, sizeof finish);
62 printf("Starting dir: %s\n", start);
63 printf("Finishing dir: %s\n", finish);
64 }
65
66 return (errors != 0);
67 }
Строки 3–11 включают заголовочные файлы. По крайней мере в GLIBC 2.3.2 перед включением
#define
для _XOPEN_SOURCE
и _XOPEN_SOURCE_EXTENDED
. Они дают возможность получить объявления и значения флагов, которые nftw()
предоставляет свыше предоставляемых ftw()
. Это специфично для GLIBC. Потребность в этом в конечном счете исчезнет, когда GLIBC станет полностью совместимой со стандартом POSIX 2001.Строки 35–44 обрабатывают опции. Опция -с
nftw() FTW_CHDIR
. Это эксперимент с целью увидеть, сможете ли вы оказаться где-то в другом месте от того, где начинали. Кажется, это возможно, если nftw()
завершается неудачей, в противном случае вы заканчиваете там же, где начинали. (POSIX не документирует это явным образом, но целью, похоже, было действительно заканчивать там же, где начинали. Стандарт не говорит, что функция обратного вызова не должна менять текущий каталог.)Строка 49 сохраняет начальный каталог для дальнейшего использования, пользуясь getcwd()
Строка 51 вычисляет число дескрипторов, которые может использовать nftw()
getdtablesize()
(см. раздел 4.4.1 «Понятие о дескрипторах файлов») для получения максимально возможного числа и вычета из него SPARE_FDS
, который был вычислен ранее в строке 13.Эта процедура служит основанием для больших объяснений. В обычном случае по крайней мере три дескриптора уже используются для стандартного ввода, стандартного вывода и стандартной ошибки. nftw()
opendir()
использует open()
при открытии каталогов для чтения. Если функции обратного вызова также нужно открывать файлы, мы должны предотвратить израсходование функцией nftw()
всех доступных дескрипторов файлов для открывания каталогов. Мы делаем это, вычитая некоторое число из максимально допустимого. Для данного примера мы выбрали пять, но если функции обратного вызова нужно открывать файлы, должно использоваться большее число, (nftw()
знает, как восстановиться при израсходовании дескрипторов файлов; мы не должны беспокоиться о таком случае.)