Для успешного выполнения rmdir()
каталог должен быть пустым (он не должен содержать ничего, кроме вездесущих .
и ..
); в противном случае возвращается ENOTEMPTY
.
14.4. Чтение содержимого каталога
Обычно программам требуется получать список файлов, содержащихся в каталоге. Linux предоставляет ряд функций, позволяющих обрабатывать каталог как абстрактный объект, что дает возможность избежать зависимости программ от точного формата каталогов, реализуемого файловой системой. Открытие и закрытие каталогов осуществляется очень просто.
#include
DIR * opendir(const char * pathname);
int closedir(DIR * dir);
Системный вызов opendir()
возвращает указатель на тип данных DIR
, который является абстрактным (как и структура stdio
по имени FILE
) и которым не следует манипулировать вне библиотеки С. Поскольку каталоги можно открывать только для чтения, нет необходимости определять, в каком режиме открывается каталог, opendir()
срабатывает только в случае существования каталога — этот вызов нельзя использовать для создания новых каталогов (для этого служит mkdir()
). Закрытие каталога может не сработать только в случае некорректного значения аргумента dir
.
После открытия каталога его элементы читаются последовательно до конца каталога.
Системный вызов readdir()
возвращает имя следующего файла в каталоге. Каталоги не упорядочены каким-либо образом, поэтому не стоит предполагать, что оглавление каталога отсортировано. Если необходим упорядоченный список файлов, сортировку придется выполнять самостоятельно. Функция readdir()
определяется, как показано ниже.
#include
struct dirent * readdir (DIR * dir);
Вызывающему коду возвращается указатель на структуру struct dirent
. Несмотря на то что struct dirent
содержит несколько элементов, единственным переносимым элементом является d_name
, содержащий имя файла элемента каталога. Остальные элементы struct dirent
зависят от системы. Однако интересным является элемент d_ino
, содержащий inode-номер файла.
Самой сложной частью этого процесса является определение ошибки. К сожалению, readdir()
возвращает NULL
, и когда происходит ошибка, и когда в каталоге больше нет элементов. Чтобы различать эти две ситуации, необходимо проверять errno
. Эта задача усложняется тем, что readdir()
не меняет errno
, пока не произойдет ошибка. Это означает, что для корректной проверки ошибок errno
необходимо установить перед вызовом readdir()
в заранее известное значение (обычно 0). Ниже показана простая программа, записывающая имена файлов текущего каталога в stdout.
1: /* dircontents.с */
2:
3: #include
4: #include
5: #include
6:
7: int main(void) {
8: DIR * dir;
9: struct dirent * ent;
10:
11: /* "." - текущий каталог */
12: if (!(dir = opendir("."))) {
13: perror("opendir");
14: return 1;
15: }
16:
17: /* установить errno в 0, чтобы можно было выяснить, когда readdir() даст сбой*/
18: errno = 0;
19: while ((ent = readdir(dir))) {
20: puts (ent->d_name);
21: /* сбросить errno, поскольку puts() может модифицировать ее */
22: errno = 0;
23: }
24:
25: if (errno) {
26: perror("readdir");
27: return 1;
28: }
29:
30: closedir(dir);
31:
32: return 0;
33: }
14.4.1. Прохождение по каталогу
Если требуется перечитать содержимое каталога, уже открытого opendir()
, с помощью rewinddir()
структура DIR
сбрасывается, чтобы следующий вызов readdir()
мог вернуть первый файл в каталоге.
#include
int rewinddir(DIR * dir);
14.5. Универсализация файловых имен