int readdir_r(DIR *
Возвращает 0 при успешном завершении или положительное значение при ошибке
При заданном аргументе dirp, являющемся потоком каталога, открытым ранее с помощью функции opendir(), функция readdir_r() помещает информацию о следующей записи каталога в структуру dirent, на которую указывает аргумент entry. Кроме того, в аргумент result помещается указатель на эту структуру. Если достигнут конец потока каталога, в аргумент result помещается значение NULL (и функция readdir_r() возвращает 0). В случае ошибки функция readdir_r() возвращает не –1, а положительное число, соответствующее одному из значений кода errno.
В Linux поле d_name структуры dirent определено как массив из 256 байт, длины которого достаточно для хранения самого длинного возможного имени файла. Несмотря на то что в ряде реализаций UNIX для размера поля d_name определено такое же значение, стандарт SUSv3 не оговаривает этот момент, в связи с чем в некоторых реализациях UNUX данное поле определено как однобайтный массив, а на вызывающую программу ложится задача по выделению структуры с корректным размером. При ее осуществлении следует задавать размер поля d_name на единицу больше (для завершающего нулевого байта), чем значение константы NAME_MAX. Таким образом, в портируемых приложениях структуру dirent следует выделять так:
struct dirent *entryp;
size_t len;
len = offsetof(struct dirent, d_name) + NAME_MAX + 1;
entryp = malloc(len);
if (entryp == NULL)
errExit("malloc");
За счет использования макроопределения offsetof() (приводимого в файле
Макроопределение offsetof() принимает два аргумента — тип структуры и имя поля внутри нее — и возвращает значение типа size_t, которое является смещением (в байтах) данного поля относительно начала структуры. Это макроопределение необходимо, поскольку компилятор может вставить заполняющие байты в структуру, чтобы удовлетворить требованиям выравнивания для таких типов, как int, в результате чего смещение поля в структуре может оказаться больше, чем сумма размеров полей, которые ей предшествуют.
Функция nftw() позволяет программе рекурсивно перемещаться по всему поддереву каталога, выполняя некую операцию (например, вызов некоторой функции, указанной программистом) для каждого файла в этом поддереве.
Функция nftw() является улучшением старой функции ftw(), выполняющей похожую задачу. В новых приложениях следует использовать функцию nftw() (new ftw), поскольку она обеспечивает бульшую функциональность и предсказуемую обработку символических ссылок (стандарт SUSv3 разрешает функции ftw() либо следовать по символическим ссылкам, либо нет). Стандарт SUSv3 определяет обе функции, nftw() и ftw(), однако последняя считается устаревшей в стандарте SUSv4.
GNU-библиотека C также обеспечивает API на основе BSD в виде функций fts (fts_open(), fts_read(), fts_children(), fts_set() и fts_close()). Они выполняют задачи подобно функциям ftw() и nftw(), но обеспечивают повышенную гибкость для приложения, просматривающего дерево. Тем не менее данный интерфейс не стандартизирован и присутствует лишь в ряде реализаций UNIX, которые не являются ветками BSD, и поэтому мы не рассматриваем его здесь.
Функция nftw() выполняет обход дерева каталога, указанного в аргументе dirpath и вызывает указанную программистом функцию func для каждого файла в дереве каталога.
#define _XOPEN_SOURCE 500
#include
int nftw(const char
int (*
int
int
Возвращает 0 после успешного обхода всего дерева, –1 при ошибке или первое ненулевое значение, возвращенное вызовом функции func
По умолчанию функция nftw() выполняет несортированный обход указанного дерева в прямом порядке, обрабатывая каждый каталог, прежде чем перейти к обработке файлов и подкаталогов внутри данного каталога.