99: } else {
100: prog->freeGlob = 1;
101: flags = 0;
102: i = 0;
103: }
104:
105: rc = glob(prog->argv[argc - 1], flags, NULL, &prog->globResult);
106: if (rc == GLOB_NOSPACE) {
107: fprintf (stderr, 'не хватает памяти для выполнения универсализации
');
108: return;
109: } else if (rc == GLOB_NOMATCH ||
110: (!rc && (prog->globResult.gl_path - i) == 1 &&
111: !strcmp(prog->argv[argc - 1],
112: prog->globResult.gl_pathv[i]))) {
113: /* необходимо удалить кавычки в , если они все еще присутствуют */
114: src = dst = prog->argv[argc - 1];
115: while (*src) {
116: if (*src ! = '\') *dst++ = *src;
117: src++;
118: }
119: *dst = ' ';
120: } else if (!rc) {
121: argcAlloced += (prog->globResult.gl_pathc - i);
122: prog->argv = realloc(prog->argv,
123: argcAlloced * sizeof(*prog->argv));
124: memcpy(prog->argv + (argc - 1),
125: prog->globResult.gl_pathv + i,
126: sizeof(*(prog->argv)) *
127: (prog->globResult.gl_pathc - i));
128: argc += (prog->globResult.gl_pathc - i - 1);
129: }
130:
131: *argcAllocedPtr = argcAlloced;
132: *argcPtr = argc;
133: }
Последними изменениями касаются вызовов globLastArgument(), которые должны совершаться после синтаксического разбора нового аргумента. Вызовы добавляются в двух местах: когда за пределами строки в кавычках найдены пробелы и когда вся командная строка разобрана. Оба вызова выглядят следующим образом:
globLastArgument(prog, &argc, &argvAlloced);
Полный код ladsh3.с доступен на Web-сайте издательства, а также на сайте, посвященном книге.
14.7. Обход деревьев файловых систем
Существуют две функции, которые облегчают приложениям просмотр всех файлов каталога, включая файлы в подкаталогах. Рекурсивный просмотр всех элементов древовидной структуры (например, файловой системы) часто называется обходом (walk) дерева и он реализуется функциями ftw() и nftw(). nftw() представляет собой усовершенствованную версию ftw.
14.7.1. Использование ftw()
#include <ftw.h>
int ftw(const char *dir, ftwFunctionPointer callback, int depth);
Функция ftw() начинает с каталога dir и вызывает указанную в callback функцию для каждого файла в этом каталоге и его подкаталогах. Функция вызывается для всех типов файлов, включая символические ссылки и каталоги. Реализация ftw() открывает каждый найденный каталог (с помощью файлового дескриптора) и для увеличения производительности не закрывает их, пока не закончит чтение всех элементов каталога. Это означает, что он использует количество файловых дескрипторов, равное количеству уровней подкаталогов. Чтобы предотвратить недостаток файловых дескрипторов в приложении, параметр depth ограничивает количество файловых дескрипторов ftw(), остающихся одновременно открытыми. Если этот предел достигается, производительность снижается, поскольку каталоги необходимо часто открывать и закрывать.
Функция, на которую указывает callback, определяется следующим образом:
int ftwCallbackFunction(const char * file, const struct stat * sb, int flag);
Эта функция вызывается один раз для каждого файла в дереве каталогов, а первый параметр, file, представляет собой имя файла, начинающееся с dir, которое передается ftw(). Например, если бы аргумент dir принимал значение ., одним из файловых имен было бы ./bashrc. Если бы вместо этого использовалось /etc, имя файла выглядело бы как /etc/hosts.
Следующий аргумент обратного вызова, sb, указывает на структуру struct stat как на результат применения stat() к файлу [102]. Аргумент flag предоставляет информацию о файле и принимает одно из следующих значений.
FTW_F | Файл не является символической ссылкой или каталогом. |
FTW_D | Файл является каталогом либо символической ссылкой, указывающей на каталог. |
FTW_DNR | Файл является каталогом, полномочий на чтение которого у приложения нет (то есть его обход невозможен). |
