В случае неудачи функция opendir возвращает пустой указатель. Имейте в виду, что для доступа к самому каталогу поток каталога использует низкоуровневый дескриптор файла, поэтому opendir может дать сбой, если открыто слишком много файлов.
Функция readdir
dirp. Успешные вызовы readdir возвращают следующие элементы каталогов. При возникновении ошибки и в конце каталога readdir возвращает NULL. Системы, удовлетворяющие стандарту POSIX, возвращая NULL, не меняют переменную errno в случае достижения конца каталога и устанавливают ее значение, если обнаружена ошибка.#include
#include
struct dirent *readdir(DIR *dirp);
Просмотр каталога с помощью функции readdir
В состав структуры dirent
ino_t d_ino
char d_name[]
Для выяснения других реквизитов файла в каталоге вам необходимо вызвать stat
Функция telldir
seekdir для переустановки просмотра каталога, начиная с текущей позиции.#include
#include
long int telldir(DIR *dirp);
Функция seekdir
dirp. Значение параметра loc, применяемого для установки позиции, следует получить из предшествующего вызова функции telldir.#include
#include
void seekdir (DIR *dirp, long int loc);
Функция closedir
#include
#include
int closedir(DIR *dirp);
В приведенной далее программе printdir.c (упражнение 3.4) вы соберете вместе множество функций обработки файлов для создания простого перечня содержимого каталога. Каждый файл представлен отдельной строкой. У каждого подкаталога есть имя, за которым следует слэш, и файлы, содержащиеся в подкаталоге, выводятся с отступом шириной в четыре пробела.
Программа превращает каталог в подкаталоги, чтобы у найденных файлов были пригодные для использования имена, т.е. они могут передаваться непосредственно в функцию opendir. Программа будет давать сбои при просмотре структур с большим числом уровней вложенности, поскольку есть ограничение на разрешенное число открытых потоков каталогов.
Мы могли бы сделать программу более универсальной, принимая в качестве аргумента командной строки начальную точку просмотра.
Для того чтобы познакомиться с методами повышения универсальности программ, посмотрите исходный код таких утилит Linux, как ls
find.1. Начните с соответствующих заголовочных файлов и функции printdir
depth для задания отступа.#include
#include
#include
#include
#include
#include
void printdir(char *dir, int depth) {
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if ((dp = opendir(dir)) == NULL) {
fprintf(stderr, "cannot open directory: %s\n", dir);
return;
}
chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry->d_name, &statbuf);
if (S_ISDIR(statbuf.st_mode)) {
/* Находит каталог, но игнорирует . и .. */
if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0)
continue;
printf("%*s%s/\n", depth, "", entry->d_name);
/* Рекурсивный вызов с новый отступом */
printdir(entry->d_name, depth+4);
} else printf("%*s%s\n", depth, " ", entry->d_name);
}
chdir("..");
closedir(dp);
}
2. Теперь переходите к функции main
int main {
/* Обзор каталога /home */
printf("Directory scan of /home:\n");
printdir("/home", 0);