Язык Си



Глава 8. Интерфейс с системой UNIX - часть 13


void fsize(char *);

/* печатает размер файлов */ main(int argc, char **argv) { if (argc == 1)/* по умолчанию берется текущий каталог */ fsize("."); else while (--argc > 0) fsize(*++argv); return 0; }

Функция fsize печатает размер файла. Однако, если файл - каталог, она сначала вызывает dirwalk, чтобы обработать все его файлы. Обратите внимание на то, как используются имена флажков S_IFMT и S_IFDIR из <sys/stat.h> при проверке, является ли файл каталогом. Здесь нужны скобки, поскольку приоритет оператора & ниже приоритета оператора ==.

int stat(char *, struct stat *); void dirwalk(char *, void (*fcn)(char *));

/* fsize: печатает размер файла "name" */ void fsize(char *name) { struct stat stbuf;

if (stat(name, &stbuf) == -1) { fprintf(stderr, "fsize: нет доступа к %s\n", name); return; } if ((stbuf.st_mode & S_IFMT) == S_IFDIR) dirwalk(name, fsize); printf("%8ld%s\n", stbuf.st_size, name); }

Функция dirwalk - это универсальная программа, применяющая некоторую функцию к каждому файлу каталога. Она открывает каталог, с помощью цикла перебирает содержащиеся в нем файлы, применяя к каждому из них указанную функцию, затем закрывает каталог и осуществляет возврат. Так как fsize вызывает dirwalk на каждом каталоге, в этих двух функциях заложена косвенная рекурсия.

#define MAX_PATH 1024

/* dirwalk: применяет fcn ко всем файлам из dir */ void dirwalk(char *dir, void (*fcn)(char *)) { char name[MAX_PATH]; Dirent *dp; DIR *dfd;

if ((dfd = opendir(dir)) == NULL) { fprintf(stderr, "dirwalk: не могу открыть %s\n", dir); return; } while ((dp = readdir(dfd)) != NULL) { if (strcmp(dp->name, ".") == 0 strcmp(dp->name, "..") == 0) continue; /* пропустить себя и родителя */ if (strlen(dir)+strlen(dp->name) + 2 > sizeof(name)) fprintf(stderr, "dirwalk: слишком длинное имя %s/%s\n", dir, dp->name); else { sprintf(name, "%s/%s", dir, dp->name); (*fcn) (name); } } closedir(dfd); }




Содержание  Назад  Вперед