Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Программное обеспечение » Linux программирование в примерах - Арнольд Роббинс

Linux программирование в примерах - Арнольд Роббинс

Читать онлайн Linux программирование в примерах - Арнольд Роббинс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 63 64 65 66 67 68 69 70 71 ... 165
Перейти на страницу:

8.5. Обход дерева файлов: GNU du

GNU версия du в GNU Coreutils использует nftw() для обхода одной или более иерархии файлов, собирая и выводя сведения, касающиеся количества используемого дискового пространства. У нее большое число опций, которые управляют ее поведением но отношению к символическим ссылкам, форматом вывода чисел и т.д. Это делает разбор кода труднее, чем могло бы быть при более простой версии. (Однако, мы не собираемся позволить этому остановить нас.) Вот сводка опций du, которые вскоре будут полезны, когда мы рассмотрим код.

$ du --help

Usage: du [OPTION]... [FILE]...

  Дает сводку использования диска для каждого FILE,

  рекурсивно для каталогов.

  Обязательные для длинных опций аргументы являются обязательными

  также и для коротких опций.

-a,  --all              записать число всех файлов, а не только

                        каталогов

     --apparent-size    вывести видимые размеры, а не использование

                        диска; хотя видимый размер обычно меньше, он

                        может быть и больше из-за дыр в файлах,

                        внутренней фрагментации, косвенных блоков и т.п.

-В,  --block-size=SIZE  использовать блоки размером SIZE байтов

-b,  --bytes            эквивалентно '--apparent-size --block-size=1'

-с,  --total            выводит итоговую сумму

-D,  --dereference-args разыменовывать FILE, которые являются

                        символическими ссылками

-h,  --human-readable   вывести размеры в удобном для восприятия

                        формате (например, 1K 234М 2G)

-Н,  --si               так же, но использовать степени 1000, не 1024

-k                      подобно --block-size=1K

-l,  --count-links      считать размеры несколько раз при прямых

                        ссылках

-L,  --dereference      разыменовывать все символические ссылки

-S,  --separate-dirs    не включать размер подкаталогов

-s,  --summarize        отобразить для каждого аргумента лишь итоги

-х,  --one-file-system  пропускать каталоги на различных файловых

                        системах

-X   --exclude-         исключить файлы, подходящие под любой

FILE from=FILE          образец в FILE

     --exclude=PATTERN  исключить файлы, соответствующие PATTERN

     --max-depth=N      вывести итог для каталога (или файла, с --all)

                        только если он находится на N или менее уровней

                        глубже аргумента командной строки;

     --max-depth=0      то же самое, что и --summarize

     --help             отобразить экран справки и выйти

     --version          вывести сведения о версии и выйти

SIZE может быть (или может быть целым, за которым

может следовать это) одним из

следующих: kB 1000, K 1024, MB 1 000 000, M 1 048 576 и т.д.

для G, T, Р, E, Z, Y.

Чтобы еще больше усложнить дело, du использует частную версию nftw(), у которой есть несколько расширений. Сначала имеются дополнительные значения флагов для функции обратного вызова:

FTW_DCHP

Это значение означает, что nftw() не может выполнять 'chdir("..")'.

FTW_DCH

Это значение означает, что nftw() не может использовать chdir() для перехода в сам каталог.

FTW_DPRE

Частная nftw() вызывает для каталогов функцию обратного вызова дважды. Это значение используется при первой встрече с каталогом. После обработки всех нижележащих объектов каталога используется стандартное значение FTW_DP.

Частная nftw() добавляет также в struct FTW новый член, int skip. Если текущий объект является каталогом и функция обратного вызова устанавливает в поле skip ненулевое значение, nftw() не будет больше обрабатывать этот каталог. (Функция обратного вызова должна установить skip таким образом, когда flag равен FTW_DPRE; делать это для FTW_DP слишком поздно.)

С этим объяснением за поясом, вот функция process_file() из du.c. Номера строк приведены относительно начала функции:

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  /* Заметьте, мы не должны здесь просто возвращаться.

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).

1 ... 63 64 65 66 67 68 69 70 71 ... 165
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Арнольд Роббинс.
Комментарии