Linux программирование в примерах
flagsНабор флагов, объединяемых побитовым ИЛИ, которые указывают, как
должна обрабатывать иерархию.nftw()Интерфейс
имеет два отдельных набора флагов. Одни набор контролирует самуnftw()(аргументnftw()функцииflags). Другой набор передается предоставленной пользователем функции, которую вызываетnftw()(аргументnftw()дляflags). Однако, интерфейс запутывает, поскольку имена обоих наборов флагов начинаются с префикса '(*fn)()'. Мы постараемся сделать все, чтобы это прояснить по ходу дела. В табл. 8.3 представлены флаги, которые контролируютFTW_.nftw()Таблица 8.3. Управляющие флаги для
nftw()
Флаг Значение FTW_CHDIRПри установке перед открытием каждого из каталогов сначала осуществляется переход в него. Это действие более эффективно, но вызывающее приложение должно быть готово оказаться в другом каталоге, когда завершитсяnftw()FTW_DEPTHПри установке осуществляется «сначала глубокий поиск». Это означает, что все файлы и подкаталоги обрабатываются до того, как будет обработан сам каталог FTW_MOUNTПри установке остается в той же самой смонтированной файловой системе. Это более специализированная опция FTW_PHYSПри установке не следует по символическим ссылкам предоставляет большую эффективность; при обработке глубоких иерархий файлов ядру не приходится обрабатывать снова и снова полные пути имен при осуществленииFTW_CHDIRили открытии каталога. Экономия времени для больших иерархий может быть вполне ощутимой. [85]stat()может быть, а может и не быть тем, что вам нужно; для некоторых приложений это безусловно справедливо. Рассмотрите 'FTW_DEPTH'. Эта команда удаляет права чтения и исполнения для владельца для всех файлов и подкаталогов в текущем каталоге. Если это изменение прав доступа применено к каталогу до того, как оно применено к содержимому каталога, любые последующие попытки обработки содержимого потерпят неудачу! Поэтому команда должна применяться к каталогу после обработки его содержимого. [86] Справочная страница GNU/Linux nftw(3) отмечает дляchmod -R u-rx ., что «это то, что вам нужно». Это позволяет вам обрабатывать сами символические ссылки, что обычно бывает нужно (РассмотритеFTW_PHYS, она должна подсчитывать занимаемое ссылками пространство отдельно от связанных с ними файлов.)du8.4.3.2. Функция обратного вызова
nftw()После запуска
она вызывает функцию, указатель для которой предоставляете вы. (Такие функции называются функциями обратного вызова (callback functions), поскольку они «вызываются обратно» из библиотечного кода.) Функция обратного вызова получает четыре аргумента:nftw()const char *fileИмя текущего обрабатываемого файла (каталога, символической ссылки и т.д.).
const struct stat *sbУказатель на
для файла.struct statint flagОдно из нескольких значений флагов (описанных ниже), указывающих, какой это вид файла или была ли ошибка для объекта.
struct FTW *sЭта структура предоставляет две отдельные части информации:
struct FTW {int base; /* Индекс в файле базовой части имени файла */int level; /* Глубина этого элемента относительно точки отсчета */};Параметр
имеет одно из перечисленных в табл. 8.4 значений.flagТаблица 8.4. Значения флагов для функции обратного вызова
nftw()
Флаг Значение FTW_FОбъект является обычным файлом FTW_DОбъект является каталогом FTW_DNRОбъект является каталогом, который нельзя прочесть FTW_SLОбъект является символической ссылкой FTW_NSОбъект не является символической ссылкой, а потерпела неудачуstat()FTW_DPОбъект является каталогом, элементы которого были уже обработаны. Это может случиться, лишь когда в вызове использовалсяnftw()FTW_DEPTHFTW_SLNОбъект является символической ссылкой, указывающей на несуществующий файл. Это может случиться, лишь когда в вызове не используетсяnftw()FTW_PHYSпредоставляет дополнительную информацию, которая может быть полезной.struct FTW* se действует в качестве индекса вs->bas;fileявляется полным путем обрабатываемого объекта (относительно точки отсчета), 'file' указывает на первый символ компонента имени файла.file + s->baseуказывает текущую глубину иерархии; считается, что первоначальная точка отсчета находится на уровне 0.s->levelФункция обратного вызова должна вернуть 0, если все нормально. Любое ненулевое возвращенное значение заставляет
прекратить свою обработку и вернуть то самое ненулевое значение. Справочная страница отмечает, что функция обратного вызова должна останавливать обработку только путем возвращаемого значения, чтобы уnftw()был шанс произвести очистку: т.е. освободить динамически выделенную память, закрыть открытые дескрипторы файлов и т.д. Функции обратного вызова не следует использоватьnftw(), если только программа не завершается немедленно, (longjmp()является продвинутой функцией, которую мы опишем в разделе 12.5 «Нелокальные goto».) Рекомендуемой методикой обработки ошибок является установка глобальной переменной, указывающей на наличие проблем, возвращение 0 из функции обратного вызова и обработка ошибок после завершения перемещенияlongjmp()по иерархии файлов. (GNUnftw()это делает, как мы вскоре увидим.)du