Шрифт:
1 /* Эта функция вызывается один раз для каждого объекта файловой
2 системы, с которой сталкивается nftw. nftw осуществляет сначала
3 поиск вглубь. Эта функция знает это и собирает итоги для каталогов
4 на основе изменений в глубине текущего элемента. */
5
6 static int
7 process_file(const char *file, const struct stat *sb,
8 int file_type, struct FTW *info)
9 {
10 uintmax_t size;
11 uintmax_t size_to_print;
12 static int first_call = 1;
13 static size_t prev_level;
14 static size_t n_alloc;
15 static uintmax_t *sum_ent;
16 static uintmax_t *sum_subdir;
17 int print = 1;
18
19 /* Всегда определяйте info->skip перед возвратом. */
20 info->skip = excluded_filename(exclude, file + info->base);
/* Для --exclude */
Эта функция делает многое, поскольку ей приходится реализовать все опции
du
. Строка 17 устанавливает print
в true (1); по умолчанию выводятся сведения о каждом файле. Дальнейший код устанавливает ее при необходимости в false (0). Строка 20 устанавливает
info->skip
на основе опции – -exclude
. Обратите внимание, что это исключает подкаталоги, если каталог совпадает с шаблоном для – -exclude
.
22 switch (file_type)
23 {
24 case FTW_NS:
25 error (0, errno, _("cannot access %s"), quote(file));
26 G_fail = 1; /* Установить глобальную переменную для дальнейшего */
27 return 0; /* Вернуть 0 для продолжения */
28
29 case FTW_DCHP:
30 error(0, errno, _("cannot change to parent of directory %s"),
31 quote(file));
32 G_fail = 1;
33 return 0;
34
35 case FTW_DCH:
36 /* Нельзя просто вернуться, поскольку, хотя nftw не может войти в
37 каталог, она может использовать stat, постольку у нас есть размер */
38 error(0, errno, _("cannot change to directory %s"), quote(file));
39 G_fail = 1;
40 break;
41
42 case FTW_DNR:
43 /* Нельзя просто вернуться, поскольку, хотя nftw не может прочесть
44 каталог, она может вызвать stat, постольку у нас есть размер. */
45 error(0, errno, _("cannot read directory %s"), quote(file));
46 G_fail = 1;
47 break;
48
49 default:
50 break;
51 }
52
53 /* Если это первая (предварительная) встреча с каталогом,
54 сразу вернуться. */
55 if (file_type == FTW_DPRE)
56 return 0;
Строки 22–51 являются стандартным оператором
switch
. Ошибки, для которых нет информации о размере, устанавливают глобальную переменную G_fail
в 1 и возвращают 0, чтобы продолжить обработку (см строки 24–27 и 29–33). Ошибки, для которых есть размер, также устанавливают G_fail
, но затем прерывают switch
для того, чтобы обработать статистику (см. строки 35–40 и 42–47). Строки 55–56 сразу завершают функцию, если это первая встреча с каталогом
58 /* Если файл исключается или если он уже учитывался
59 через прямую ссылку, не включать его в сумму. */
60 if (info->skip,
61 || (!opt_count_all
62 && 1 < sb->st_nlink
63 && hash_ins(sb->st_ino, sb->st_dev)))
64 {
65 /* Заметьте, мы не должны здесь просто возвращаться.