66     Нам все еще нужно обновить prev_level и, возможно, передать

67     некоторые суммы выше по иерархии. */

68  size = 0;

69  print = 0;

70 }

71 else

72 {

73  size = (apparent_size

74    ? sb->st_size

75    : ST_NBLOCKS (*sb) * ST_NBLOCKSIZE);

76  }

Теперь становится интересно. По умолчанию du подсчитывает пространство, занимаемое прямыми ссылками, лишь одни раз. Опция --count-links заставляет ее подсчитывать пространство для каждой ссылки; переменная opt_count_all равна true, когда указана --count-links. Для отслеживания ссылок du содержит хэш-таблицу[87] уже встречавшихся пар (устройство, индекс).

Строки 60–63 проверяют, следует ли не включать файл в подсчет, либо из-за того, что он был исключен (info->skip равно true, строка 60), либо потому что не была указана --count-links (строка 61) и у файла несколько ссылок (строка 62) и файл уже находится в хеш-таблице (строка 63). В этом случае размер устанавливается в 0, поэтому он не входит в конечную сумму, a print также устанавливается в false (строки 68–69).

Если ни одно из этих условий не отмечается, размер вычисляется либо в соответствии с размером в struct stat, либо в соответствии с числом блоков диска (строки 73–75) Это решение основывается на переменной apparent_size, которая установлена при использовании опции --apparent-size.

78 if (first_call)

79 {

80  n_alloc = info->level + 10; /* Allocate arrays */

81  sum_ent = XCALLOC(uintmax_t, n_alloc); /* to hold sums */

82  sum_subdir = XCALLOC(uintmax_t, n_alloc);

83 }

84 else

85 {

86  /* FIXME: Стыдно, что нам нужно приводить к типу size_t для избежания

87     предупреждений gcc о 'сравнении между знаковым и беззнаковым'.

88     Возможно, неизбежно, при условии, что члены структуры FTW

89     имеют тип 'int' (исторически), так как мне нужно, чтобы переменные

90     вроде n_alloc и prev_level имели осмысленные типы. */

91  if (n_alloc <= (size_t)info->level)

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 }

98

99 size_to_print = size;

Строки 78–97 управляют динамической памятью, используемой для хранения статистики о размере файла, first_call является статической переменной (строка 12), которая равна true при первом вызове process_file(). В этом случае вызывается calloc() (через упаковывающий макрос в строках 81–82; это обсуждалось в разделе 3.2.1.8 «Пример чтение строк произвольной длины»). Остальную часть времени first_call равно false, и используется realloc() (снова через упаковывающий макрос, строки 91–96).

Строка 99 заносит значение size в size_to_print; эта переменная может обновляться в зависимости от того, должна ли она включать размеры дочерних элементов. Хотя size могла бы использоваться повторно, отдельная переменная упрощает чтение кода.

101 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_level

111      и текущим. Глубина может значительно меняться,

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  }

Перейти на страницу:

Похожие книги