65 while (read(fd, (char*)&dir, sizeof dir) == sizeof dir) {
66 if (dir.d_ino == 0) continue;
67 if (!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, ".."))
68 continue;
69 fprintf(stderr, "rmdir: %s not empty\n", name);
70 ++Errors;
71 close(fd);
72 return;
73 }
74 close(fd);
В строке 60 каталог открывается для чтения (второй аргумент равен 0, что означает
O_RDONLY
). В строке 65 читается
struct direct
. В строке 66 проверяется, не является ли элемент каталога пустым, т. е. с номером индекса 0. Строки 67 и 68 проверяют на наличие '
.
' и '
..
'.
По достижении строки 69 мы знаем, что было встречено какое-то другое имя файла, следовательно, этот каталог не пустой.
(Тест '
!strcmp(s1, s2)
' является более короткой формой '
strcmp(s1, s2) == 0
', т.е. проверкой совпадения строк. Стоит заметить, что мы рассматриваем '
!strcmp(s1, s2)
' как плохой стиль. Как сказал однажды Генри Спенсер (Henry Spencer), «
strcmp
это не boolean!».)
Когда 4.2 BSD представило новый формат файловой системы, который допускал длинные имена файлов и обеспечивал лучшую производительность, были также представлены несколько новых функций для абстрагирования чтения каталогов. Этот набор функций можно использовать независимо от того, какова лежащая в основе файловая система и как организованы каталоги. Основная ее часть стандартизована POSIX, а программы, использующие ее, переносимы между системами GNU/Linux и Unix.
5.3.1. Базовое чтение каталогов
Элементы каталогов представлены
struct dirent
(не то же самое, что V7
struct direct
!):
struct dirent {
...
ino_t d_ino; /* расширение XSI --- см. текст */
char d_name[...]; /* О размере этого массива см. в тексте */
...
};
Для переносимости POSIX указывает лишь поле
d_name
, которое является завершающимся нулем массивом байтов, представляющим часть элемента каталога с именем файла. Размер
d_name
стандартом не указывается, кроме того, что там перед завершающим нулем может быть не более
NAME_MAX
байтов. (
NAME_MAX
определен в
<limits.h>
.) Расширение XSI POSIX предусматривает поле номера индекса
d_ino
.
На практике, поскольку имена файлов могут быть различной длины, a
NAME_MAX
обычно довольно велико (подобно 255),
struct dirent
содержит дополнительные члены, которые помогают вести на диске учет элементов каталогов с переменными длинами. Эти дополнительные члены не существенны для обычного кода.
Следующие функции предоставляют интерфейс чтения каталогов:
#include <sys/types.h> /* POSIX */
#include <dirent.h>
DIR *opendir(const char *name); /* Открыть каталог для чтения */
struct dirent *readdir(DIR *dir); /* Вернуть struct dirent за раз */
int closedir(DIR *dir); /* Закрыть открытый каталог */
void rewinddir(DIR *dirp); /* Вернуться в начало каталога */
Тип
DIR
является аналогом типа
FILE
в
<stdio.h>
. Это непрозрачный тип, что означает, что код приложения не должен знать, что находится внутри него; его содержимое предназначено для использования другими процедурами каталогов. Если
opendir
возвращает
NULL
, именованный каталог не может быть открыт для чтения, а errno содержит код ошибки.