Строки 52–58 являются главным циклом над нашими аргументами; строки 53–57 проверяют ошибки; когда они появляются, код выводит диагностическое сообщение и увеличивает значение переменной errors
Строки 60–64 являются частью эксперимента с FTW_CHDIR
-с
.По-настоящему интересной функцией является process()
nftw()
, который является оператором switch
для значения flag
.69 /* process --- выводит каждый файл на нужном уровне */
70
71 int process(const char "file, const struct stat *sb,
72 int flag, struct FTW *s)
73 {
74 int retval = 0;
75 const char *name = file + s->base;
76
77 printf("%*s", s->level * 4, ""); /* сделать отступ */
78
79 switch (flag) {
80 case FTW_F:
81 printf("%s (file)\n", name);
82 break;
83 case FTW_D:
84 printf("%s (directory)\n", name);
85 break;
86 case FTW_DNR:
87 printf("%s (unreadable directory)\n", name);
88 break;
89 case FTW_SL:
90 printf("%s (symbolic link)\n", name);
91 break;
92 case FTW_NS:
93 printf("%s (stat failed): %s\n", name, strerror(errno));
94 break;
95 case FTW_DP:
96 case FTW_SLN:
97 printf("%s: FTW_DP or FTW_SLN: can't happen'\n", name);
98 retval = 1;
99 break;
100 default:
101 printf("%s: unknown flag %d: can't happen'\n", name, flag);
102 retval = 1;
103 break;
104 }
105
106 return retval;
107 }
Строка 75 использует 'file + s->base
name
для повторного использования в функции.Строка 77 делает отступ нужного размера, используя красивый трюк. Используя %*s
printf()
получает от первого аргумента ширину поля. Это вычисляется динамически как 'level * 4
'. Строка, которая должна быть выведена — «», пустая строка. Конечным результатом является то, что printf()
создает для нас отступ нужного размера без необходимости запуска цикла.Строки 79–104 являются оператором switch
Хотя эта программа не использует struct stat
ЗАМЕЧАНИЕ
. Джим Мейеринг (Jim Meyering), сопроводитель GNU Coreutils, замечает, что дизайнnftw()
несовершенен из-за ее рекурсивной природы. (Она рекурсивно вызывает себя при обработке подкаталогов.) Если иерархия каталогов становится действительно глубокой, в диапазоне уровней 20 000–40 000 (!), nftw()
может выйти за пределы размера стека, уничтожив программу. Есть также и другие проблемы, связанные с дизайном nftw()
. Версия GNU Coreutils после 5.0 исправляет это путем использования набора процедур fts()
(см. 8.5. Обход дерева файлов: GNU du
GNU версия du
nftw()
для обхода одной или более иерархии файлов, собирая и выводя сведения, касающиеся количества используемого дискового пространства. У нее большое число опций, которые управляют ее поведением но отношению к символическим ссылкам, форматом вывода чисел и т.д. Это делает разбор кода труднее, чем могло бы быть при более простой версии. (Однако, мы не собираемся позволить этому остановить нас.) Вот сводка опций du
, которые вскоре будут полезны, когда мы рассмотрим код.$ du --help
Usage: du [OPTION]... [FILE]...