Linux программирование в примерах
Часть 104 из 253 Информация о книге
Давайте свяжем все это воедино в примере программы.
обрабатывает каждый файл или каталог, указанный в командной строке, запуская для нихch08-nftw.c. Функция, обрабатывающая каждый файл, выводите отступом имя и тип файла, показывая иерархическое положение каждого файла. Для разнообразия мы сначала покажем результаты, а затем покажем и обсудим программу:nftw()$ <b>pwd</b> /* Где мы находимся *// home/аrnold/work/prenhall/progex$ <b>code/ch08/ch08-nftw code</b> /* Обойти каталог 'code' */code (directory) /* Каталог верхнего уровня */ch02 (directory) /* Подкаталоги с отступом на один уровень */ch02-printenv.c (file) /* Файлы в подкаталоге с отступомна два уровня */ch03 (directory)ch03-memaddr.c (file)ch04 (directory)ch04-holes.c (file)ch04-cat.с (file)ch04-maxfds.c (file)v7cat.c (file)...Вот сама программа:
1 /* ch08-nftw.c --- демонстрирует nftw() */23 #define _XOPEN_SOURCE 1 /* Требуется под GLIBC для nftw() */4 #define _XOPEN_SOURCE_EXTENDED 1 /* To же */56 #include <stdio.h>7 #include <errno.h>8 #include <getopt.h>9 #include <ftw.h> /* получает для нас <sys/types.h> и <sys/stat.h> */10 #include <limits.h> /* для PATH_MAX */11 #include <unistd.h> /* для объявлений getdtablesize(), getcwd() */1213 #define SPARE_FDS 5 /* fds для использования другими функциями, см. текст */1415 extern int process(const char *file, const struct stat *sb,16 int flag, struct FTW *s);1718 /* usage --- print message and die */1920 void usage(const char *name)21 {22 fprintf(stderr, "usage: %s (-c) directory ...\n", name);23 exit(1);24 }2526 /* main --- вызвать nftw() для каждого аргумента командной строки */2728 int main(int argc, char **argv)29 {30 int i, c, nfds;31 int errors = 0;32 int flags = FTW_PHYS;33 char start[PATH_MAX], finish[PATH_MAX];3435 while ((c = getopt(argc, argv, "с")) != -1) {36 switch (c) {37 case 'c':38 flags |= FTW_CHDIR;39 break;40 default:41 usage(argv[0]);42 break;43 }44 }4546 if (optind == argc)47 usage(argv[0]);4849 getcwd(start, sizeof start);5051 nfds = getdtablesize() - SPARE_FDS; /* оставить несколько запасных дескрипторов */52 for (i = optind; i < argc; i++) {53 if (nftw(argv[i], process, nfds, flags) != 0) {54 fprintf(stderr, "%s: %s: stopped early\n",55 argv[0], argv[i]);56 errors++;57 }58 }5960 if ((flags & FTW_CHDIR) != 0) {61 getcwd(finish, sizeof finish);62 printf("Starting dir: %s\n", start);63 printf("Finishing dir: %s\n", finish);64 }6566 return (errors != 0);67 }Строки 3–11 включают заголовочные файлы. По крайней мере в GLIBC 2.3.2 перед включением любого заголовочного файла необходимы
для#defineи_XOPEN_SOURCE. Они дают возможность получить объявления и значения флагов, которые_XOPEN_SOURCE_EXTENDEDпредоставляет свыше предоставляемыхnftw(). Это специфично для GLIBC. Потребность в этом в конечном счете исчезнет, когда GLIBC станет полностью совместимой со стандартом POSIX 2001.ftw()Строки 35–44 обрабатывают опции. Опция
добавляет к флагам-с. Это эксперимент с целью увидеть, сможете ли вы оказаться где-то в другом месте от того, где начинали. Кажется, это возможно, еслиnftw() FTW_CHDIRзавершается неудачей, в противном случае вы заканчиваете там же, где начинали. (POSIX не документирует это явным образом, но целью, похоже, было действительно заканчивать там же, где начинали. Стандарт не говорит, что функция обратного вызова не должна менять текущий каталог.)nftw()