READDIR(3) | Руководство программиста Linux | READDIR(3) |
readdir - чтение содержимого каталога
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
Функция readdir() возвращает указатель на структуру dirent, представляющую следующую запись каталога в потоке каталога, указанного в dirp. Функция возвращает NULL по достижении последней записи в потоке каталога или если произошла ошибка.
В реализации glibc структура dirent определена следующим образом:
struct dirent { ino_t d_ino; /* номер иноды */ off_t d_off; /* не смещение, смотрите ниже */ unsigned short d_reclen; /* длина этой записи */ unsigned char d_type; /* тип файла; поддерживается не во всех файловых системах */ char d_name[256]; /* имя файла с null в конце */ };
В соответствие с POSIX.1, структура dirent обязательно должна содержать поле d_name[] и d_ino. Другие поля не стандартизованы и имеются не во всех системах; подробней смотрите ЗАМЕЧАНИЯ далее.
Поля структуры dirent:
Данные, возвращаемые readdir(), могут быть переписаны последующими вызовами readdir() для того же потока каталога.
При успешном выполнении readdir() возвращает указатель на структуру dirent (эта структура может выделяться статически; не пытайтесь освободить её с помощью free(3)).
При достижении конца потока каталога возвращается NULL и errno не изменяется. При возникновении ошибки возвращается NULL, а errno изменяется соответствующим образом. Чтобы отличить конец потока от ошибки присваивайте errno значение нуля перед вызовом readdir(), а после проверяйте значение errno, если возвращается NULL.
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
readdir() | Безвредность в нитях | MT-Unsafe race:dirstream |
В текущей спецификации POSIX.1 (POSIX.1-2008), от readdir() не требуется быть нитебезопасной. Однако в современных реализациях (включая glibc) параллельные вызовы readdir() для различных потоков каталога являются нитебезопасными. В случаях, когда несколько нитей должны читать один поток каталога, всё равно предпочтительней использовать readdir() с внешней синхронизацией, а не устаревшей readdir_r(3). Ожидается, что в будущей версии POSIX.1 для readdir() будет требоваться нитебезопасность при одновременной работе с разными потоками каталога.
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD.
Поток каталога открывается с помощью opendir(3).
Порядок последовательно читаемых имён файлов вызовом readdir() зависит от реализации файловой системы; не очень здорово, что имена будут отсортированы в непредсказуемом порядке.
В POSIX.1 определены только поля d_name и d_ino (расширение XSI). Кроме Linux, поле d_type доступно, преимущественно только в системах BSD. Остальные поля доступны во многих, но не во всех системах. В glibc программы могут определить доступность полей, не определённых в POSIX.1, по наличию макросов _DIRENT_HAVE_D_NAMLEN, _DIRENT_HAVE_D_RECLEN, _DIRENT_HAVE_D_OFF или _DIRENT_HAVE_D_TYPE.
Определение структуры dirent, показанное выше, взято из заголовочных файлов glibc и отражает поле d_name с постоянным размером.
Предупреждение: приложения не должны зависеть от размера поля d_name. В POSIX оно определено как char d_name[], массив символов неопределённого размера, не более NAME_MAX символов с конечным байтом null ('\0').
В POSIX.1 явно сказано, что это поле не должно использоваться как lvalue. В стандарте также отмечено, что использование sizeof(d_name) некорректно; вместо него используйте strlen(d_name) (в некоторых системах это поле определено как char d_name[1]!). Как следствие, использовать sizeof(struct dirent) для получения размера записи, включающей размер d_name также неправильно.
Заметим, что хотя вызов
fpathconf(fd, _PC_NAME_MAX)
и возвращает значение 255 в большинстве файловых систем, но в некоторых файловых системах (например, CIFS, серверы Windows SMB) имя файла с null конце, возвращаемое (правильно) в d_name, может превышать этот размер. В таких случаях поле d_reclen будет содержать значение, превышающее размер структуры glibc dirent, показанной выше.
getdents(2), read(2), closedir(3), dirfd(3), ftw(3), offsetof(3), opendir(3), readdir_r(3), rewinddir(3), scandir(3), seekdir(3), telldir(3)
2019-03-06 |