ftw(3) | Library Functions Manual | ftw(3) |
ftw, nftw - обход файлового дерева
Standard C library (libc, -lc)
#include <ftw.h>
int nftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf), int nopenfd, int flags);
[[deprecated]] int ftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag), int nopenfd);
nftw():
_XOPEN_SOURCE >= 500
Функция nftw() обходит дерево каталогов, начиная с указанного в dirpath, и для каждого элемента дерева однократно вызывает fn(). По умолчанию каталоги обрабатываются раньше файлов и подкаталогов, которые в них содержатся (предварительный обход).
Чтобы избежать использования всех файловых дескрипторов вызывающего процесса, в nopenfd задаётся максимальное количество одновременно открываемых nftw() каталогов. Когда это количество превышается, работа nftw() немного замедляется, так как каталоги будут закрываться и снова открываться. Функция nftw() использует не более одного файлового дескриптора для работы с каждым уровнем дерева каталогов.
Для каждого найденного элемента дерева nftw() вызывает функцию fn() с четырьмя аргументами: fpath, sb, fpath и ftwbuf. В fpath указывается полное имя элемента в виде, или пути относительно рабочего каталога вызывающего процесса на момент вызова nftw() (если dirpath указан в виде относительного пути), или абсолютного пути (если dirpath указан в виде абсолютного пути). В sb задаётся указатель на структуру stat, возвращаемую вызовом stat(2) для fpath.
Аргумент typeflag, передаваемый в fn(), представляет собой целое число, которое может быть одним из следующих значений:
Четвёртый аргумент (ftwbuf), передаваемый nftw() при вызове fn(), является структурой типа FTW:
struct FTW {
int base;
int level; };
base — смещение на имя файла (т.е. базовая часть) в пути, заданном в fpath. level — глубина fpath в дереве каталогов относительно корня дерева (dirpath имеет глубину 0).
Для остановки обхода дерева fn() возвращает ненулевое значение; оно станет возвращаемым значением для nftw(). Пока fn() возвращает 0, nftw() будет продолжать свой поиск до полного обхода дерева (в этом случае она возвратит ноль), или пока не возникнет ошибка (например, из-за malloc(3)). В этом случае функция возвратит значение -1.
Так как nftw() использует динамические структуры данных, то единственным безопасным способом для выхода из процесса обхода дерева будет возврат ненулевого значения из fn(). Для завершения обхода по сигналу без утечек памяти в обработчике нужно устанавливать глобальный флаг, проверяемый fn(). Не используйте longjmp(3) кроме как для завершения программы.
Значение аргумента flags в nftw() составляется логическим сложением 0 или нескольких следующих флагов:
В будущем могут появиться другие возвращаемые значения для новых действий; fn() не должна возвращать значений, отличных от перечисленных выше.
Чтобы получить определение FTW_ACTIONRETVAL из <ftw.h>, должен быть определён макрос тестирования свойств _GNU_SOURCE.
Функция ftw() является устаревшей и предоставляет только часть возможностей nftw(). Основные отличия:
При успешном выполнении эти функции возвращают 0 и -1 при ошибке.
Если fn() возвращает ненулевое значение, то обход дерева прекращается и значение, полученное от fn(), возвращается в качестве результата ftw() или nftw().
Если nftw() вызывается с флагом FTW_ACTIONRETVAL, то для прекращения обхода дерева fn() должна вернуть ненулевое значение FTW_STOP, и это значение возвращается в качестве результата nftw().
nftw() is available since glibc 2.1.
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
nftw() | Безвредность в нитях | MT-Safe cwd |
ftw() | Безвредность в нитях | MT-Safe |
POSIX.1-2001, POSIX.1-2008, SVr4, SUSv1. В POSIX.1-2008 функция ftw() помечена как устаревшая.
В POSIX.1-2008 отмечено, что результат непредсказуем, если fn не сохраняет текущий рабочий каталог.
Функция nftw() и использование FTW_SL с ftw() впервые появились в SUSv1.
В некоторых реализациях (например, glibc), ftw() никогда не использует FTW_SL, в других системах FTW_SL возникает только для символьных ссылок, которые не указывают на существующий файл, или даже ftw() будет использовать FTW_SL для каждой символьной ссылки. Если fpath — символьная ссылка и stat(2) завершается с ошибкой, то следуя POSIX.1-2008 нельзя понять что передаётся в typeflag: FTW_NS или FTW_SL. Для предсказуемости результатов используйте nftw().
According to POSIX.1-2008, when the typeflag argument passed to fn() contains FTW_SLN, the buffer pointed to by sb should contain information about the dangling symbolic link (obtained by calling lstat(2) on the link). Early glibc versions correctly followed the POSIX specification on this point. However, as a result of a regression introduced in glibc 2.4, the contents of the buffer pointed to by sb were undefined when FTW_SLN is passed in typeflag. (More precisely, the contents of the buffer were left unchanged in this case.) This regression was eventually fixed in glibc 2.30, so that the glibc implementation (once more) follows the POSIX specification.
Следующая программа обходит дерево каталогов начиная с пути, указанном в первом аргументе командой строки или начиная с текущего каталога, если аргумент не указан. Она отображает различную информацию о каждом файле. Во втором параметре можно указать символы, которые управляют содержимым аргумента flags у nftw().
#define _XOPEN_SOURCE 500 #include <ftw.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> static int display_info(const char *fpath, const struct stat *sb,
int tflag, struct FTW *ftwbuf) {
printf("%-3s %2d ",
(tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" :
(tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" :
(tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" :
(tflag == FTW_SLN) ? "sln" : "???",
ftwbuf->level);
if (tflag == FTW_NS)
printf("-------");
else
printf("%7jd", (intmax_t) sb->st_size);
printf(" %-40s %d %s\n",
fpath, ftwbuf->base, fpath + ftwbuf->base);
return 0; /* говорит nftw() продолжать */ } int main(int argc, char *argv[]) {
int flags = 0;
if (argc > 2 && strchr(argv[2], 'd') != NULL)
flags |= FTW_DEPTH;
if (argc > 2 && strchr(argv[2], 'p') != NULL)
flags |= FTW_PHYS;
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags)
== -1)
{
perror("nftw");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS); }
Русский перевод этой страницы руководства был сделан Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
5 февраля 2023 г. | Linux man-pages 6.03 |