Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
92 {93 n_alloc = info->level * 2; /* Удвоить сумму */94 sum_ent = XREALLOC(sum_ent, uintmax_t, realloc); /* И выделить повторно */95 sum_subdir = XREALLOC(sum_subdir, uintmax_t, n_alloc);96 }97 }9899 size_to_print = size;Строки 78–97 управляют динамической памятью, используемой для хранения статистики о размере файла,
first_callprocess_file()calloc()first_callrealloc()Строка 99 заносит значение
sizesize_to_printsize101 if (!first_call)102 {103 if ((size_t)info->level == prev_level)104 {105 /* Обычно самый частый случай. Ничего не делать. */106 }107 else if ((size_t)info->level > prev_level)108 {109 /* Нисхождение по иерархии.110 Очистить аккумуляторы для *всех* уровней между prev_level111 и текущим. Глубина может значительно меняться,112 например, от 1 до 10. */113 int i;114 for (i = prev_level +1; i <= info->level; i++)115 sum_ent[i] = sum_subdir[i] = 0;116 }117 else /* info->level < prev_level */118 {119 /* Восхождение по иерархии.120 nftw обрабатывает каталог лишь после всех элементов,121 в которых был обработан каталог. Когда глубина уменьшается,122 передать суммы от детей (prev_level) родителям.123 Здесь текущий уровень всегда меньше, чем124 предыдущий. */125 assert (<size_t) info->level == prev_level - 1);126 size_to_print += sum_ent[prev_level];127 if (!opt_separate_dirs)128 size_to_print += sum_subdir[prev_level];129 sum_subdir[info->level] += (sum_ent[prev_level]130 + sum_subdir[prev_level]);131 }132 }Строки 101–132 сравнивают текущий уровень с предыдущим. Возможны три случая.
Уровни те же самые
В этом случае нет необходимости беспокоиться о статистике дочерних элементов. (Строки 103–106.)
Текущий уровень выше предыдущего
В этом случае мы спустились по иерархии, и статистику нужно восстановить (строки 107–116). Термин «аккумулятор» в комментарии подходящий: каждый элемент аккумулирует общее дисковое пространство, использованное на этом уровне. (На заре вычислительной техники регистры центрального процессора часто назывались «аккумуляторами».)
Текущий уровень ниже предыдущего
В этом случае мы завершили обработку всех дочерних элементов каталога и только что вернулись обратно в родительский каталог (строки 117–131). Код обновляет суммы, включая
size_to_print134 prev_level = info->level; /* Установить статические переменные */135 first_call = 0;136137 /* Включить элемент каталога в общую сумму для содержащего138 каталога, если не указана --separate-dirs (-S). */139 if (!(opt_separate_dirs && IS_FTW_DIR_TYPE(file_type)))140 sum_ent[info->level] += size;141142 /* Даже если каталог нельзя прочесть или перейти в него,143 включить его размер в общую сумму, ... */144 tot_size += size;145146 /* ...но не выводить для него итог, поскольку без размера(-ов)147 потенциальных элементов, это может сильно запутывать. */148 if (file_type == FTW_DNR || file_type == FTW_DCH)149 return 0;150151 /* Если мы не считаем элемент, например, потому что это прямая152 ссылка на файл, который уже посчитан (и --count-links), не153 выводить для него строку. */154 if (!print)155 return 0;Строки 134–135 устанавливают статические переменные
prev_levelfirst_callprocess_file()Строки 137–144 выверяют статистику на основе опций и типа файла. Комментарии и код достаточно просты. Строки 146–155 сразу завершают функцию, если сведения не должны выводиться.
157 /* FIXME: Это выглядит подозрительно годным для упрощения. */158 if ((IS_FTW_DIR_TYPE(file_type) &&159 (info->level <= max_depth || info->level == 0))