14.5.2. Внутренняя универсализация

14.5.2. Внутренняя универсализация

Если необходимо универсализировать несколько файловых имен, запуск нескольких подоболочек с помощью popen() будет неэффективным. Функция glob() позволяет универсализировать имена файлов без запуска каких-либо подпроцессов, однако за счет увеличения сложности и снижения переносимости. Несмотря на то что вызов glob() описан в стандарте POSIX.2, многие варианты Unix до сих пор его не поддерживают.

#include <glob.h>

int glob(const char * pattern, int flags,

int (*errfunc)(const char * epath, int eerrno), glob_t* pglob);

Первый параметр, pattern, определяет шаблон, которому должны соответствовать имена файлов. В нем допускается применение операций универсализации *, ? и [], а также необязательно {, } и ~ которые трактуются так же, как в стандартных оболочках. Последний параметр указывает на структуру, которая заполняется результатами универсализации. Эта структура определена следующим образом.

#include <glob.h>

typedef struct {

 int gl_pathc; /* количество путей в gl_pathv */

 char **gl_pathv; /* список gl_pathc, соответствующих именам путей */

 int gl_offs; /* пространство, зарезервированное в gl_pathv для GLOB_DOOFFS*/

} glob_t;

flags — это одно или несколько перечисленных ниже значений, объединенных с помощью битового "ИЛИ".

GLOB_ERR Возвращается в случае ошибки (если функция не может прочесть оглавление каталога, например, из-за проблем с доступом).
GLOB_MARK Если шаблон соответствует имени каталога, при возврате к этому имени будет добавлен символ /.
GLOB_NOSORT Обычно возвращаемые имена путей сортируются в алфавитном порядке. Если этот флаг установлен, они не сортируются.
GLOB_DOOFFS При установке первые строки pglob->gl_offs в возвращаемом списке имен путей оставляются пустыми. Это позволяет использовать glob() во время выстраивания ряда аргументов, которые будут переданы прямо в execv().
GLOB_NOCHECK Если ни одно из файловых имен не соответствует шаблону, в качестве единственного совпадения возвращается сам шаблон (обычно не возвращается ни одного совпадения). В обоих случаях шаблон возвращается, если он не содержит операций универсализации.
GLOB_APPEND pglob предположительно является действительным результатом предыдущего вызова glob(), и любые результаты этого вызова добавляются к результатам предыдущего вызова. Это облегчает универсализацию множества шаблонов.
GLOB_NOESCAPE Обычно если операции универсализации предшествует символ , она воспринимается как обычный символ. Например, шаблон а* обычно соответствует только файлу по имени а*. Если устанавливается GLOB_NOESCAPE, символ теряет свое особое значение, aa* соответствует любому имени файла, начинающемуся с символов а. В таком случае имена а. и acd будут соответствовать, но arachnid — нет, поскольку оно не содержит .
GLOB_PERIOD Большинство оболочек не позволяют применять операции универсализации для файловых имен, начинающихся с . (запустите ls * в своем домашнем каталоге и сравните полученное с результатом ls - а .). Функция glob() обычно ведет себя подобным образом, но GLOB_PERIOD позволяет операциям универсализации работать с ведущим символом. Значение GLOB_PERIOD в POSIX не определено.
GLOB_BRACE Многие оболочки (следуя примеру csh) разворачивают последовательности с фигурными скобками как альтернативы; например, шаблон {a, b} разворачивается до a b, а шаблон a {, b, c} — до a ab ас. GLOB_BRACE делает возможным такое поведение. Значение GLOB_BRACE в POSIX не определено.
GLOB_NOMAGIС Действует подобно GLOB_NOCHECK за исключением того, что он добавляет шаблон к списку результатов только в том случае, если она не содержит специальных знаков. Значение GLOB_NOMAGIC в POSIX не определено.
GLOB_TILDE Включает расширение с тильдой, в котором ~ или подстрока ~/ разворачиваются до пути к домашнему каталогу текущего пользователя, а ~user — до пути к домашнему каталогу пользователя user. Значение GLOB_TILDE в POSIX не определено.
GLOB_ONLYDIR Совпадает только с каталогами, а не с другими типами файлов. Значение GLOB_ONLYDIR в POSIX не определено.

Часто glob() наталкивается на каталоги, к которым у процесса нет доступа, что вызывает ошибки. Хотя ошибку можно каким-то образом обработать, однако если glob() возвращает ошибку (GLOB_ERR), операцию универсализации нельзя перезапустить там, где предыдущая операция универсализации столкнулась с ошибкой. Поскольку сложно одновременно устранять ошибки, происходящие во время выполнения glob(), и завершать универсализацию, glob() позволяет передать ошибку в специально предусмотренную для этого функцию, которая определяется в третьем параметре glob().

Прототип этой функции показан ниже.

int globerr(const char * pathname, int globerrno);

Функции передается путевое имя, вызвавшее ошибку, и значение errno, возвращенное одним из системных вызовов opendir(), readdir() или stat(). Если функция ошибки возвращает величину больше нуля, glob() возвращается с ошибкой. В противном случае операция универсализации продолжается.

Результаты универсализации хранятся в структуре glob_t, на которую ссылается pglob. Она включает описанные ниже элементы, позволяющие абоненту найти согласованные имена файлов.

gl_pathc Количество путевых имен, соответствующих шаблону.
gl_pathv Массив путевых имен, соответствующих шаблону.

После использования возвращенного результата glob_t занимаемую им память следует освободить, передав его в globfree().

void globfree(glob_t * pglob);

Системный вызов glob() возвращает GLOB_NOSPACE в случае нехватки памяти, GLOB_ABEND, если ошибка чтения привела к неудачному выполнению функции, GLOB_NOMATCH, если соответствия не были найдены, или 0, если функция выполнилась удачно и нашла соответствия.

Для иллюстрации работы glob() ниже приведена программа globit, которая принимает множество шаблонов в качестве аргументов, универсализирует их и отображает результат. В случае ошибки отображается сообщение, описывающее ошибку, а операция универсализации продолжается.

 1: /* globit.с */

 2:

 3: #include <errno.h>

 4: #include <glob.h>

 5: #include <stdio.h>

 6: #include <string.h>

 7: #include <unistd.h>

 8:

 9: /* Это функция ошибки, которая передается в glob(). Она просто отображает

10:    сообщение об ошибке и возвращает состояние успеха, что позволяет glob()

11:    продолжить работу. */

12: int errfn(const char * pathname, int theerr) {

13:  fprintf(stderr, "ошибка при доступе к %s: %s ", pathname,

14:  strerror(theerr));

15:

16:  /* Операция универсализации должна продолжаться, поэтому вернуть 0 */

17:  return 0;

18: }

19:

20: int main(int argc, const char ** argv) {

21:  glob_t result;

22:  int i, rc, flags;

23:

24:  if (argc < 2) {

25:   printf("необходимо передать хотя бы один аргумент ") ;

26:   return 1;

27:  }

28:

29:  /* установить flags в 0; позже он будет изменен на GLOB_APPEND */

30:  flags = 0;

31:

32:  /* совершить проход по всем аргументам командной строки */

33:  for (i = 1; i < argc; i++) {

34:   rc = glob(argv[i], flags, errfn, &result);

35:

36:   /* благодаря errfn, GLOB_ABEND не происходит */

37:   if (rc == GLOB_NOSPACE) {

38:    fprintf(stderr, "не хватает памяти для выполнения универсализации ");

39:    return 1;

40:   }

41:

42:   flags |= GLOB_APPEND;

43:  }

44:

45:  if (!result.gl_pathc) {

46:   fprintf(stderr, "соответствий нет ");

47:   rc = 1;

48:  } else {

49:   for (i = 0; i < result.gl_pathc; i++)

50:    puts(result.gl_pathv[i]);

51:   rc = 0;

52:  }

53:

54:  /* структура glob_t занимает память из пула malloc(),

55:     которая должна быть освобождена */

56:  globfree(&result);

57:

58:  return rc;

59: }

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

ПАРАЛЛЕЛИ: Внутренняя Пустота

Из книги Журнал «Компьютерра» № 42 от 14 ноября 2006 года автора Журнал «Компьютерра»

ПАРАЛЛЕЛИ: Внутренняя Пустота Автор: Георгий ПачиковВ наше время любой мало-мальски образованный человек постоянно пользуется Интернетом. С его помощью мы решаем множество вопросов. Даже правописание можно проверить — залезаешь в Интернет и смотришь, как то или иное


3.1. Внутренняя структура описания уровней зрелости

Из книги Модель зрелости процессов разработки программного обеспечения автора Паулк Марк

3.1. Внутренняя структура описания уровней зрелости Каждое описание уровней зрелости разбивается на составные части. Разбиение каждого уровня зрелости, кроме первого, варьируется от кратких обзоров уровня до его рабочего определения в ключевых практиках, как показано на


Внутренняя организация дерева с двоичным основанием

Из книги Основы AS/400 автора Солтис Фрэнк

Внутренняя организация дерева с двоичным основанием Внутренняя форма хранения дерева с двоичным основанием оптимизирована как с точки зрения производительности, так и занимаемого пространства. Первая базовая структура для дерева с двоичным основанием была создана


5.1.3. Внешняя и внутренняя чистка компьютера

Из книги Самоучитель работы на компьютере автора Колисниченко Денис Николаевич

5.1.3. Внешняя и внутренняя чистка компьютера Регулярно, несколько раз в неделю нужно протирать пыль (это назовем внешней чисткой). Делать это следует сухой тряпкой, а для большего эффекта лучше купить специальные чистящие салфетки, чтобы протирать монитор, системный блок,


Inner Shadow (Внутренняя тень)

Из книги Photoshop CS3: Обучающий курс автора Тимофеев Сергей Михайлович

Inner Shadow (Внутренняя тень) Следующий эффект – Inner Shadow (Внутренняя тень) – создает иллюзию того, что объект вогнутый и его края отбрасывают тень внутрь. Перед применением данного эффекта мы также настраиваем все необходимые параметры. Изменения значений параметров можно


Универсализация (Genericity)

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Универсализация (Genericity) В описании STACK[G] именем G обозначен произвольный, не определяемый тип. G называется формальным родовым параметром для типов элементов АТД STACK, а сам STACK называется родовым или универсальным АТД. Механизм, допускающий такие параметризованные


Лекция 10. Универсализация

Из книги Разработка приложений в среде Linux. Второе издание автора Джонсон Майкл К.

Лекция 10. Универсализация Слияние двух концепций - модуля и типа - позволило разработать мощное понятие класса, послужившее основой ОО-метода. Уже в таком виде оно позволяет делать многое. Однако для достижения наших целей - расширяемости, возможности повторного


У10.1 Ограниченная универсализация

Из книги Инфобизнес на полную мощность [Удвоение продаж] автора Парабеллум Андрей Алексеевич

У10.1 Ограниченная универсализация Это упражнение немного специфично - оно ставит вопрос, детальный ответ на который будет дан позднее в этой книге. Его цель - дать возможность сравнить ваше решение с решением, предложенным в книге. Оно особенно полезно, если вы не знакомы с


14.5. Универсализация файловых имен

Из книги Раскрутка: секреты эффективного продвижения сайтов автора Евдокимов Николай Семенович

14.5. Универсализация файловых имен Большинство пользователей Linux принимают как должное то, что запуск ls *.с не сообщает сведения о файле в текущем каталоге, именем которого является *.с. Вместо этого они ожидают увидеть список всех файлов в текущем каталоге, имена которых


23.1. Универсализация произвольных строк

Из книги Операционная система UNIX автора Робачевский Андрей М.

23.1. Универсализация произвольных строк В главе 14 мы говорили о том, как с помощью функции glob() производится универсализация имен файлов, однако пользователи, знакомые с возможностями универсализации, нередко пытаются применить их и к другим разновидностям строк. Функция


Внутренняя оптимизация

Из книги автора

Внутренняя оптимизация Работа с внутренними факторами – хронологически приоритетная и чрезвычайно важная часть поискового продвижения. Перед тем как начать покупать ссылки, необходимо провести скрупулезный аудит сайта на предмет его корректности с точки зрения SEO.


Внутренняя оптимизация

Из книги автора

Внутренняя оптимизация Поисковой системе «приятнее» такая страница интернет-магазина, которая структурирована и сверстана по блочному типу. Предпочтительно делить контентную область страницы на несколько составляющих: заголовок, краткое описание, полное описание,


Внутренняя структура буферного кэша

Из книги автора

Внутренняя структура буферного кэша Буферный кэш состоит из буферов данных, размер которых достаточен для размещения одного дискового блока. С каждым блоком данных связан заголовок буфера, представленный структурой buf, с помощью которого ядро производит управление


Внутренняя архитектура

Из книги автора

Внутренняя архитектура Как уже говорилось, драйвер, реализующий поставщика услуг уровня канала данных, состоит из двух частей: аппаратно-зависимой и аппаратно-независимой. Соответственно драйвер хранит отдельные структуры данных, необходимые для работы этих частей.


Глава 4 Внутренняя оптимизация

Из книги автора

Глава 4 Внутренняя оптимизация При работе с крупными проектами внутренние факторы приобретают приоритетное значение. Даже небольшие изменения в шаблонах сайта могут существенно увеличить трафик из поисковых