Чтение онлайн

на главную

Жанры

Язык программирования Си. Издание 3-е, исправленное

Ритчи Деннис М.

Шрифт:

#define S_IFMT 0160000 /* тип файла */

#define S_IFDIR 0040000 /* каталог */

#define S_IFCHR 0020000 /* символьно-ориентированный */

#define S_IFBLK 0060000 /* блочно-ориентированный */

#define S_IFREG 0100000 /* обычный */

Теперь мы готовы приступить к написанию программы fsize. Если режимные биты (st_mode), полученные от stat, указывают, что файл не является каталогом, то можно взять его размер (st_size) и напечатать.

Однако если файл - каталог, то мы должны обработать все его файлы, каждый из которых в свою очередь может быть каталогом. Обработка каталога - процесс рекурсивный.

Программа main просматривает параметры командной строки, передавая каждый аргумент функции fsize.

#include ‹stdio.h›

#include ‹string.h›

#include "syscalls.h"

#include ‹fcntl.h› /* флажки чтения и записи */

#include ‹sys/types.h› /* определения типов */

#include ‹sys/stat.h› /* структура, возвращаемая stat */

#include "dirent.h"

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);

}

Каждый вызов readdir возвращает указатель на информацию о следующем файле или NULL, если все файлы обработаны. Любой каталог всегда хранит в себе информацию о себе самом в файле под именем "." и о своем родителе в файле под именем "…": их нужно пропустить, иначе программа зациклится. Обратите внимание: код программы этого уровня не зависит от того, как форматированы каталоги. Следующий шаг - представить минимальные версии opendir, readdir и closedir для некоторой конкретной системы. Здесь приведены программы для систем Version 7 и System V UNIX. Они используют информацию о каталоге, хранящуюся в заголовочном файле ‹sys/dir.h›, который выглядит следующим образом:

#ifndef DIRSIZ

#define DIRSIZ 14

#endif

struct direct /* элемент каталога */

{

 ino_t d_ino; /* номер inode */

 char d_name[DIRSIZ]; /* длинное имя не имеет '\0' */

};

Некоторые версии системы допускают более длинные имена и имеют более сложную структуру каталога.

Тип ino_t задан с помощью typedef и описывает индекс списка узлов node. В системе, которой пользуемся мы, этот тип есть unsigned short, но в других системах он может быть иным, поэтому его лучше определять через typedef. Полный набор "системных" типов находится в ‹sys/types.h›.

Функция opendir открывает каталог, проверяет, является ли он действительно каталогом (в данном случае это делается с помощью системного вызова fstat, который аналогичен stat, но применяется к дескриптору файла), запрашивает пространство для структуры каталога и записывает информацию.

int fstat(int fd, struct stat *);

/* opendir: открывает каталог для вызовов readdir */

DIR *opendir(char *dirname)

Поделиться:
Популярные книги

На границе тучи ходят хмуро...

Кулаков Алексей Иванович
1. Александр Агренев
Фантастика:
альтернативная история
9.28
рейтинг книги
На границе тучи ходят хмуро...

Кодекс Охотника. Книга III

Винокуров Юрий
3. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Кодекс Охотника. Книга III

Последний попаданец 11. Финал. Часть 1

Зубов Константин
11. Последний попаданец
Фантастика:
фэнтези
юмористическое фэнтези
рпг
5.00
рейтинг книги
Последний попаданец 11. Финал. Часть 1

Книга пяти колец

Зайцев Константин
1. Книга пяти колец
Фантастика:
фэнтези
6.00
рейтинг книги
Книга пяти колец

Поступь Империи

Ланцов Михаил Алексеевич
7. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Поступь Империи

Купидон с топором

Юнина Наталья
Любовные романы:
современные любовные романы
7.67
рейтинг книги
Купидон с топором

Наследник в Зеркальной Маске

Тарс Элиан
8. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник в Зеркальной Маске

Совок 5

Агарев Вадим
5. Совок
Фантастика:
детективная фантастика
попаданцы
альтернативная история
6.20
рейтинг книги
Совок 5

Аномальный наследник. Том 1 и Том 2

Тарс Элиан
1. Аномальный наследник
Фантастика:
боевая фантастика
альтернативная история
8.50
рейтинг книги
Аномальный наследник. Том 1 и Том 2

Теневой путь. Шаг в тень

Мазуров Дмитрий
1. Теневой путь
Фантастика:
фэнтези
6.71
рейтинг книги
Теневой путь. Шаг в тень

Попаданка в академии драконов 2

Свадьбина Любовь
2. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
6.95
рейтинг книги
Попаданка в академии драконов 2

Гром над Империей. Часть 2

Машуков Тимур
6. Гром над миром
Фантастика:
фэнтези
попаданцы
5.25
рейтинг книги
Гром над Империей. Часть 2

Ритуал для призыва профессора

Лунёва Мария
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Ритуал для призыва профессора

Измена. Осколки чувств

Верди Алиса
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Осколки чувств