Linux программирование в примерах - Арнольд Роббинс
Шрифт:
Интервал:
Закладка:
glob_t *pglob
Указатель на структуру glob_t, использующуюся для хранения результатов. Структура glob_t содержит список путей, которые выдает glob():
typedef struct { /* POSIX */
size_t gl_pathc; /* Число найденных подходящих путей */
char **gl_pathv; /* Список подходящих путей */
size_t gl_offs; /* Слоты для резервирования в gl_pathv */
} glob_t;
size_t gl_pathc
Число путей, которые подошли.
char **gl_pathv
Массив подходящих путей. gl_pathv[gl_pathc] всегда равен NULL.
size_t gl_offs
«Зарезервированные слоты» в gl_pathv. Идея заключается в резервировании слотов спереди от gl_pathv для заполнения их приложением впоследствии, как в случае с именем команды и опциями. Список затем может быть передан непосредственно execv() или execvp() (см. раздел 9.1.4 «Запуск новой программы: семейство exec()»). Зарезервированные слоты устанавливаются в NULL. Чтобы все это работало, в flags должен быть установлен GLOB_DOOFFS.
В табл. 12.2 перечислены стандартные флаги для glob().
Таблица 12.2. Флаги для glob()
Флаг Значение GLOB_APPEND Добавить результаты текущего вызова к предыдущим GLOB_DOOFFS Зарезервировать места gl_offs спереди в gl_pathv GLOB_MARK Добавлять символ / в конец каждого имени, которое обозначает каталог GLOB_NOCHECK Если шаблон не соответствует имени какого-нибудь файла, вернуть его без изменений GLOB_NOESCAPE Рассматривать обратный слеш как обычный символ. Это делает невозможным обозначать метасимволы подстановок GLOB_NOSORT Не сортировать результаты, по умолчанию они сортируютсяGLIBC версия структуры glob_t содержит дополнительные члены:
typedef struct { /* GLIBC */
/* Компоненты POSIX: */
size_t gl_pathc; /* Число подходящих путей */
char **gl_pathv; /* Список подходящих путей */
size_t gl_offs; /* Резервируемые в gl_pathv слоты */
/* Компоненты GLIBC: */
int gl_flags; /* Копия флагов, дополнительные флаги GLIBC */
void (*gl_closedir)(DIR *); /* Частная версия closedir() */
struct dirent *(*gl_readdir)(DIR *); /* Частная версия readdir)) */
DIR *(*gl_opendir)(const char *); /* Частная версия opendir)) */
int (*gl_lstat)(const char *, struct stat *);
/* Частная версия lstat() */
int (*gl_stat)(const char *, struct stat *); /* Частная версия stat() */
} glob_t;
Члены структуры следующие:
int gl_flags
Копия флагов. Включает также GLOB_MAGCHAR, если pattern включал какие-либо метасимволы.
void (*gl_closedir)(DIR *)
Указатель на альтернативную версию closedir().
struct dirent *(*gl_readdir)(DIR *)
Указатель на альтернативную версию readdir().
DIR *(*gl_opendir)(const char *)
Указатель на альтернативную версию opendir().
int (*gl_lstat)(const char *, struct stat*)
Указатель на альтернативную версию lstat().
int (*gl_stat)(const char*, struct stat*)
Указатель на альтернативную версию stat().
Указатели на альтернативные версии стандартных функций предназначены главным образом для использования в реализации GLIBC; крайне маловероятно, что вы когда-нибудь их используете. Поскольку GLIBC предусматривает поле gl_flags и дополнительные значения флагов, справочная страница и руководство Info документируют оставшуюся часть структуры GLIBC glob_t. В табл. 12.3 перечислены дополнительные флаги.
Таблица 12.3. Дополнительные флаги GLIBC для glob()
Флаг Значение GLOB_ALTDIRFUNC Использовать для доступа к каталогам альтернативные функции (см. текст) GLOB_BRACE Выполнить раскрытие фигурных скобок в стиле csh и Bash. GLOB_MAGCHAR Вставить gl_flags, если были найдены метасимволы. GLOB_NOMAGIC Вернуть шаблон, если он не содержит метасимволов GLOB_ONLYDIR По возможности сопоставлять лишь каталоги. См. текст. GLOB_PERIOD Разрешить соответствие метасимволов наподобие * и ? начальной точке GLOB_TILDE Выполнить раскрывание тильды в стиле оболочки. GLOB_TILDE_CHECK Подобно GLOB_TILDE, но если есть проблемы с указанным домашним каталогом, вернуть GLOB_NOMATCH вместо помещения pattern в список.Флаг GLOB_ONLYDIR действует в качестве подсказки реализации, потому что вызывающий интересуется лишь каталогами. Главным его предназначением является использование другими функциями в GLIBC, а вызывающий по-прежнему должен быть готов обрабатывать файлы, не являющиеся каталогами. Вам не следует использовать этот флаг в своих программах.
glob() может быть вызвана более одного раза: при первом вызове флаг GLOB_APPEND не должен быть указан, при всех последующих вызовах он должен быть указан. Вы не можете между вызовами изменять gl_offs, а если вы изменили какие-нибудь значения в gl_pathv или gl_pathc, нужно их восстановить перед последующим вызовом glob().
Возможность многократного вызова glob() позволяет накапливать результаты в одном списке. Это довольно практично, приближается к мощным возможностям раскрывания групповых символов оболочки, но на уровне языка программирования С.
glob() возвращает 0, если не было проблем, или одно из значений из табл. 12.4, если были.
Таблица 12.4. Возвращаемые glob() значения
Флаг Значение GLOB_ABORTED Просмотр остановлен раньше времени, поскольку был установлен GLOB_ERR или функция (*errfunc)() возвратила ненулевой результат GLOB_NOMATCH Ни одно имя файла не соответствовало pattern, а флаг GLOB_NOCHECK не был установлен GLOB_NOSPACE Была проблема с выделением динамической памятиglobfree() освобождает всю память, которую динамически выделила glob() Следующая программа, ch12-glob.с, демонстрирует glob():
1 /* ch12-glob.c --- демонстрирует glob(). */
2
3 #include <stdio.h>
4 #include <errno.h>
5 #include <glob.h>
6
7 char *myname;
8
9 /* globerr --- выводит сообщение об ошибке для glob() */
10
11 int globerr(const char *path, int eerrno)
12 {
13 fprintf(stderr, "%s: %s: %sn", myname, path, strerror(eerrno));
14 return 0; /* let glob() keep going */
15 }
16
17 /* main() --- раскрывает символы подстановки в командной строке и выводит результаты */
18
19 int main(int argc, char **argv)
20 {
21 int i;
22 int flags = 0;
23 glob_t results;
24 int ret;
25
26 if (argc == 1) {
27 fprintf(stderr, "usage: %s wildcard ...n", argv[0]);
28 exit(1);
29 }
30
31 myname = argv[0]; /* для globerr() */
32
33 for (i = 1; i < argc; i++) {
34 flags |= (i > 1 ? GLOB_APPEND : 0);
35 ret = glob(argv[i], flags, globerr, &results);
36 if (ret != 0) {
37 fprintf(stderr, "%s: problem with %s (%s),
38 stopping earlyn", myname, argv[i],
39 /* опасно: */ (ret == GLOB_ABORTED ? "filesystem problem" :
40 ret == GLOB_NOMATCH ? "no match of pattern" :
41 ret == GLOB_NOSPACE ? "no dynamic memory" :
42 "unknown problem"));
43 break;
44 }
45 }
46
47 for (i = 0; i < results.gl_pathc; i++)