Разработка приложений в среде Linux. Второе издание
Шрифт:
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 | Файл является каталогом, полномочий на чтение которого у приложения нет (то есть его обход невозможен). |
FTW_SL | Файл является символической ссылкой. |
FTW_NS | Файл является объектом, к которому не удалось применить stat . Примером может служить файл в каталоге, права на чтение которого приложение имеет (приложение может получить список файлов этого каталога), но не имеет права на выполнение (что предотвращает успешный вызов stat применительно к файлам этого каталога). |
102
Функции
ftw
необходимо выполнять stat
для каждого файла для выяснения, является ли он каталогом, и передача этой информации обратному вызову во многих случаях избавляет последний от необходимости повторного выполнения stat
для файлов. Когда файл является символической ссылкой,
ftw
пытается последовать за этой ссылкой и вернуть информацию о файле, на который она указывает (ftw
проходит один и тот же каталог несколько раз, если на него имеется несколько символических ссылок). Однако для поврежденной ссылки не определено, вернется FTW_SL
или FTW_NS
. Это хорошая причина, чтобы использовать nftw
. Если функция обратного вызова возвращает ноль, обход каталога продолжается. Если возвращается ненулевое значение, обход дерева файлов завершается и эта величина возвращается функцией
ftw
. При удачном завершении обхода ftw
возвращает ноль, а в случае ошибки возвращается -1. 14.7.2. Обход дерева файлов с помощью
nft
Новая версия
ftw
— nftw
— решает неоднозначность символических ссылок, присущих ftw
, и содержит несколько дополнительных свойств. С целью правильного определения nftw
заголовочными файлами значение _XOPEN_SOURCE
в приложении должно быть определено 500 или больше. Ниже показан прототип nftw
. #define _XOPEN_SOURCE 600
#include <ftw.h>
int nftw(const char * dir, ftwFunctionPointer callback, int depth, int flags);
int nftwCallbackFunction(const char *file, const struct stat * sb,
int flag, struct FTW * ftwInfo);
Сравнивая
nftw
с ftw
, легко заметить новый параметр — flags
. Это может быть один или несколько следующих флагов, объединенных с помощью
логического "ИЛИ". FTW_CHDIR | Функция nftw обычно не меняет текущий каталог программы. Если определен флаг FTW_CHDIR функция nftw меняет текущий каталог на любой другой каталог, читаемый в данный момент. Иначе говоря, при активизации обратного вызова имя файла, передаваемое ему, всегда относится к текущему каталогу. |
FTW_DEPTH | По умолчанию nftw выводит имя каталога перед списком имен файлов в этом каталоге. Этот флаг вызывает изменение порядка на обратный, то есть содержимое каталога выводится перед его именем. (Примечание. Этот флаг заставляет nftw выполнять поиск в глубину. Подобного флага для поиска в ширину не существует.) |
FTW_MOUNT | Это флаг запрещает nftw переходить границу файловой системы во время обхода. Более подробно файловые системы описаны в [32]. |
FTW_PHYS | Вместо следования символическим ссылкам nftw сообщает о ссылках, но не следует по ним. Побочный эффект заключается в том, что обратный вызов получает результат вызова lstat , а не stat . |
Аргумент обратного вызова
flag
может принимать два новых значения для nftw
вдобавок к значениям, уже упомянутым для ftw
. FTW_DP | Этот элемент является каталогом, об оглавлении которого уже сообщили (это может произойти только в случае установки FTW_DEPTH ). |
FTW_SLN | Этот элемент является символической ссылкой, указывающей на несуществующий файл (поврежденная ссылка). Это происходит только в том случае, если FTW_PHYS не был установлен; если же он был установлен, передается FTW_SL . |
Эти дополнительные значения
flag
надлежащим образом определяют nftw
для символических ссылок. При использовании FTW_PHYS
все символические ссылки возвращают FTW_SL
. Без nftw
поврежденные ссылки выдают FTW_NS
, а другие символические ссылки дают тот же результат, что и цель ссылки. Обратный вызов для
nftw
принимает еще один аргумент, ftwInfо
. Это указатель на struct FTW
, которая определяется следующим образом. #define _XOPEN_SOURCE 600
#include <ftw.h>
struct FTW {
int base;
int level;
};
Элемент
base
— это смещение имени файла в полном пути, передаваемое обратному вызову. Например, если переданный полный путь выглядит как /usr/bin/ls
, base
будет равно 9, a file + ftwInfo->base
даст имя файла ls
. level
— это количество каталогов под текущим каталогом. Если ls
был найден в nftw
, начинающемся с /usr
, уровень будет равен 1. Если поиск начался с /usr/bin
, уровень будет равен 0. 14.7.3. Реализация
find
Команда
find
выполняет в одном или нескольких деревьях каталогов поиск файлов, соответствующих определенным характеристикам. Ниже приведена простая реализация find
, реализованная на основе nftw
. Она использует fnmatch
(см. главу 23) для реализации переключателя – name
и иллюстрирует многие флаги, воспринимаемые nftw
. 1: /* find.с */
2:
3: #define _XOPEN_SOURCE 600
4:
5: #include <fnmatch.h>
6: #include <ftw.h>
7: #include <limits.h>
8: #include <stdio.h>
9: #include <stdlib.h>
10: #include <string.h>
11:
12: const char * name = NULL;
13: int minDepth = 0, maxDepth = INT_MAX;
Поделиться с друзьями: