Листинг 18.3. Использование функции для обхода дерева каталога

dirs_links/nftw_dir_tree.c

#define _XOPEN_SOURCE 600

/* Получаем объявление функции nftw() и макроопределение S_IFSOCK */

#include

#include "tlpi_hdr.h"

static void

usageError(const char *progName, const char *msg)

{

if (msg!= NULL)

fprintf(stderr, "%s\n", msg);

fprintf(stderr, "Usage: %s [-d] [-m] [-p]

[directory-path]\n", progName);

fprintf(stderr, "\t-d Use FTW_DEPTH flag\n");

fprintf(stderr, "\t-m Use FTW_MOUNT flag\n");

fprintf(stderr, "\t-p Use FTW_PHYS flag\n");

exit(EXIT_FAILURE);

}

static int /* Функция, вызываемая функцией nftw() */

dirTree(const char *pathname, const struct stat *sbuf, int type,

struct FTW *ftwb)

{

switch (sbuf->st_mode & S_IFMT) { /* Выводим тип файла */

case S_IFREG: printf("-"); break;

case S_IFDIR: printf("d"); break;

case S_IFCHR: printf("c"); break;

case S_IFBLK: printf("b"); break;

case S_IFLNK: printf("l"); break;

case S_IFIFO: printf("p"); break;

case S_IFSOCK: printf("s"); break;

default: printf("?"); break;

/* Такое не должно произойти (в Linux) */

}

printf(" %s",

(type == FTW_D)? "D": (type == FTW_DNR)? "DNR":

(type == FTW_DP)? "DP": (type == FTW_F)? "F":

(type == FTW_SL)? "SL": (type == FTW_SLN)? "SLN":

(type == FTW_NS)? "NS": " ");

if (type!= FTW_NS)

printf("%7ld", (long) sbuf->st_ino);

else

printf(" ");

printf(" %*s", 4 * ftwb->level, ""); /* Добавляем подходящий отступ */

printf("%s\n", &pathname[ftwb->base]); /* Выводим базовое имя */

return 0;

/* Даем команду на продолжение работы функции nftw() */

}

int

main(int argc, char *argv[])

{

int flags, opt;

flags = 0;

while ((opt = getopt(argc, argv, "dmp"))!= -1) {

switch (opt) {

case 'd': flags |= FTW_DEPTH; break;

case 'm': flags |= FTW_MOUNT; break;

case 'p': flags |= FTW_PHYS; break;

default: usageError(argv[0], NULL);

}

}

if (argc > optind + 1)

usageError(argv[0], NULL);

if (nftw((argc > optind)? argv[optind]: ".", dirTree, 10, flags)

== -1) {

perror("nftw");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

dirs_links/nftw_dir_tree.c

Программа в листинге 18.3 отображает снабженную отступами иерархию имен файлов в дереве каталога, по одному имени файла на строку, а также тип файла и номер индексного дескриптора. Можно использовать параметры командной строки, чтобы указать параметры аргумента flags, примененного для вызова функции nftw(). Следующий сеанс работы в оболочке демонстрирует примеры того, что мы увидим при запуске данной программы. Создадим сначала пустой подкаталог, который заполним файлами разных типов:

$ mkdir dir

$ touch dir/a dir/b Создаем несколько обычных файлов

$ ln — s a dir/sl и символическую ссылку,

$ ln — s x dir/dsl а также зависшую символическую ссылку

$ mkdir dir/sub и подкаталог

$ touch dir/sub/x с собственным файлом,

$ mkdir dir/sub2 и еще один подкаталог,

$ chmod 0 dir/sub2 который нельзя прочесть

Используем теперь нашу программу для вызова функции nftw() с нулевым аргументом flags:

$ ./nftw_dir_tree dir

d D 2327983 dir

— F 2327984 a

— F 2327985 b

— F 2327984 sl Символическая ссылка sl была представлена как a

l SLN 2327987 dsl

d D 2327988 sub

— F 2327989 x

d DNR 2327994 sub2

Из приведенного выше фрагмента видно, что для символической ссылки sl был выполнен разбор.

Применим теперь нашу программу для вызова функции nftw() с аргументом flags, который содержит значения FTW_PHYS и FTW_DEPTH:

$ ./nftw_dir_tree — p — d dir

— F 2327984 a

— F 2327985 b

l SL 2327986 sl Символическая ссылка sl не была проанализирована

l SL 2327987 dsl

— F 2327989 x

d DP 2327988 sub

d DNR 2327994 sub2

d DP 2327983 dir

Из приведенного выше фрагмента видно, что разбор символической ссылки sl не был выполнен.

Флаг FTW_ACTIONRETVAL функции nftw()

Начиная с версии 2.3.3, библиотека glibc позволяет использовать дополнительный нестандартный флаг flags. Этот флаг, FTW_ACTIONRETVAL, изменяет способ интерпретации функцией nftw() значения, которое возвращено после вызова функции func(). Если указан данный флаг, функция func() должна возвращать одно из следующих значений:

• FTW_CONTINUE — продолжить обработку записей в дереве каталога, как при обычном возврате нулевого значения от функции func();

• FTW_SKIP_SIBLINGS — не обрабатывать остальные записи в данном каталоге; возобновить обработку родительского каталога;

• FTW_SKIP_SUBTREE — если аргумент pathname является каталогом (то есть значение typeflag равно FTW_D), то не вызывать функцию func() для записей в этом каталоге. Обработка возобновляется в следующем каталоге, родительский каталог которого такой же, как у текущего;

Перейти на страницу:

Похожие книги