Язык Си




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


Каждый вызов 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) { int fd; struct stat stbuf; DIR *dp;

if ((fd = open(dirname. O_RDONLY, 0)) == -1 fstat(fd, &stbuf) == -1 (stbuf.st_mode & S_IFMT) != S_IFDIR (dp = (DIR *) malloc(sizeof(DIR))) == NULL) return NULL; dp->fd = fd; return dp; }

Функция closedir закрывает каталог и освобождает пространство.

/* closedir: закрывает каталог, открытый opendir */ void closedir(DIR *dp) { if (dp) { close(dp->fd); free(dp); } }




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