Читаем Linux API. Исчерпывающее руководство полностью

При достижении конца каталога или при ошибке функция readdir() возвращает NULL; в последнем случае для указания на ошибку присваивается значение переменной errno. Для различения этих двух случаев можно написать такой код:

errno = 0;

direntp = readdir(dirp);


if (direntp == NULL) {

if (errno!= 0) {

/* Обработка ошибки */

} else {

/* Достижение конца каталога */

}

}

Если содержимое каталога меняется, пока программа сканирует его с помощью функции readdir(), то эта программа может не заметить изменений. Стандарт SUSv3 явным образом отмечает, что возникает неопределенность: возвратит ли функция readdir() имя файла, который был добавлен в данный каталог или был удален из него за время, прошедшее с момента последнего вызова функции opendir() или rewinddir()? Все имена файлов, которые не были добавлены или удалены с момента последнего вызова, гарантированно возвращаются.

Функция rewinddir() перемещает поток каталога обратно к началу, чтобы следующий вызов функции readdir() начинал работу с первого файла в данном каталоге.

#include


void rewinddir(DIR *dirp);

Функция closedir() закрывает открытый поток каталога, на который указывает аргумент dirp, высвобождая ресурсы, использованные этим потоком.

#include


int closedir(DIR *dirp);

Возвращает 0 при успешном завершении или –1 при ошибке

Следующие две функции, telldir() и seekdir(), которые также определены в стандарте SUSv3, разрешают произвольный доступ внутри потока каталога. Дополнительную информацию об этих функциях см. на страницах руководства.


Потоки каталогов и файловые дескрипторы

Поток каталога обладает связанным с ним файловым дескриптором. Функция dirfd() возвращает дескриптор, относящийся к потоку каталога, на который указывает аргумент dirp.

#include


int dirfd(DIR *dirp);

Возвращает файловый дескриптор при успешном завершении или –1 при ошибке

Можно было бы, например, передать файловый дескриптор, возвращенный функцией dirfd(), функции fchdir() (см. раздел 18.10), чтобы изменить текущий рабочий каталог процесса на соответствующий. В другом варианте можно было бы передать файловый дескриптор как аргумент dirfd в одной из функций, описанных в разделе 18.11.

Функция dirfd() появляется также в версиях BSD, однако присутствует в немногих других реализациях. Она не определена в стандарте SUSv3, но описана в стандарте SUSv4.

Здесь уместно отметить: функция opendir() автоматически устанавливает флаг close-on-exec (FD_CLOEXEC) для файлового дескриптора, связанного с потоком каталога. Это дает гарантию того, что данный файловый дескриптор будет автоматически закрыт после выполнения вызова exec(). (Стандарт SUSv3 требует такого поведения.) Мы рассмотрим флаг close-on-exec в разделе 27.4.


Пример программы

В листинге 18.2 применены функции opendir(), readdir() и closedir() для вывода содержимого каталогов, указанных в командной строке (или в рабочем каталоге, если аргументы не указаны). Ниже приведен пример использования этой программы:

$ mkdir sub Создаем тестовый каталог

$ touch sub/a sub/b Создаем несколько файлов в тестовом каталоге

$ ./list_files sub Выводим содержимое каталога

sub/a

sub/b


Листинг 18.2. Сканирование каталога

dirs_links/list_files.c

#include

#include "tlpi_hdr.h"


static void /* Перечисляет все файлы в каталоге 'dirPath' */

listFiles(const char *dirpath)

{

DIR *dirp;

struct dirent *dp;

Boolean isCurrent; /* Истина, если 'dirpath' равен"." */


isCurrent = strcmp(dirpath, ".") == 0;


dirp = opendir(dirpath);

if (dirp == NULL) {

errMsg("opendir failed on '%s'", dirpath);

return;

}


/* Для каждой записи в этом каталоге выводим имя каталога + имя файла */


for (;;) {

errno = 0; /* Чтобы отличить ошибку от достижения конца папки */

dp = readdir(dirp);

if (dp == NULL)

break;


if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)

continue; /* Пропускаем. и… */


if (!isCurrent)

printf("%s/", dirpath);

printf("%s\n", dp->d_name);

}


if (errno!= 0)

errExit("readdir");


if (closedir(dirp) == -1)

errMsg("closedir");

}


int

main(int argc, char *argv[])

{

if (argc > 1 && strcmp(argv[1], "-help") == 0)

usageErr("%s [dir-path…]\n", argv[0]);


if (argc == 1) /* Аргументов нет — используем текущий каталог */

listFiles(".");

else

for (argv++; *argv; argv++)

listFiles(*argv);


exit(EXIT_SUCCESS);

}

dirs_links/list_files.c


Функция readdir_r()

Функция readdir_r() является вариантом функции readdir(). Ключевым семантическим различием между этими функциями является то, что первая допускает многократный ввод, а вторая — нет. Это связано вот с чем: функция readdir_r() возвращает запись файла через аргумент entry, назначаемый вызывающим процессом, а функция readdir() возвращает информацию, задействуя указатель на статически выделенную структуру. Мы рассмотрим многократный ввод в подразделе 21.1.2 и разделе 31.1.

#include


Перейти на страницу:

Похожие книги

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных