struct dirent не имеет de_type в заголовочном файле

Итак, у меня есть проект, в котором мне нужно создать небольшую простую текстовую оболочку, которая может запускать, редактировать и читать файлы из каталога. У меня есть небольшой прототип, который должен работать, за исключением того, что при компиляции я получаю сообщение об ошибке о том, что d_type не найден в структуре dirent, используемой в заголовочном файле dirent.h.

d = opendir( "." );
c = 0;
while ((de = readdir(d))){
    if ((de->de_type) & DT_DIR)
    printf( " ( %d Directory: %s ) \n", c++, de->de_name);
}

переменная "de" имеет тип struct dirent* и проверяется на ее тип, и я получаю сообщение об ошибке: "struct dirent" не имеет члена с именем "de_type"

Вот где я действительно озадачен и сбит с толку: я скомпилировал этот код как в Windows (используя dev C++), так и в Ubuntu (используя gcc). Я получил одну и ту же ошибку в обеих ОС, и когда я проверил используемую библиотеку, которая, как я полагаю, является обычной библиотекой gnu C, там есть переменная с именем d_type:

https://www.gnu.org/software/libc/manual/html_node/Directory-Entries.html

Я нашел другие ссылки на файл dirent.h, которого нет, потому что он находится в другой библиотеке, и если это так, как мне загрузить эту библиотеку, чтобы я мог скомпилировать код?

Извините за длинный пост и большое спасибо всем, кто ответит!


person JustaRedShirt    schedule 05.02.2016    source источник
comment
Какой тип файловой системы вы используете?   -  person e0k    schedule 05.02.2016
comment
Итак, теперь вопрос вообще не имеет смысла, так как в заголовке написано d_type, а везде у вас de_type.   -  person user3386109    schedule 05.02.2016


Ответы (1)


Из man readdir(3):

Единственными полями в структуре dirent, требуемыми POSIX.1, являются: d_name[] неопределенного размера с не более чем NAME_MAX символами, предшествующими завершающему нулевому байту; и (как расширение XSI) d_ino. Остальные поля нестандартизированы и присутствуют не во всех системах; дополнительные сведения см. в ПРИМЕЧАНИЯХ ниже.

затем продолжается

В POSIX.1-2001 указаны только поля d_name и d_ino. Остальные поля доступны во многих, но не во всех системах. В glibc программы могут проверять наличие полей, не определенных в POSIX.1, проверяя, определены ли макросы _DIRENT_HAVE_D_NAMLEN, _DIRENT_HAVE_D_RECLEN, _DIRENT_HAVE_D_OFF или _DIRENT_HAVE_D_TYPE.

В отличие от Linux поле d_type доступно в основном только в системах BSD. Это поле позволяет избежать затрат на вызов lstat(2), если дальнейшие действия зависят от типа файла. Если определен макрос тестирования функций _BSD_SOURCE, то glibc определяет следующие константы макроса для значения, возвращаемого в d_type:

Поэтому я предлагаю просто использовать stat() для проверки типа записи. (Или lstat(), чтобы не переходить по символическим ссылкам.) struct stat содержит поле st_mode, которое может быть проверяется с помощью макроса POSIX S_ISDIR(m), чтобы проверить, является ли это каталогом.


Приложение: см. комментарии @R.. ниже и этот ответ. В итоге:

  1. Используйте правильную вещь. Добавьте -D_FILE_OFFSET_BITS=64 к флагам вашего компилятора и создайте с 64-битными смещениями файлов.
  2. Проверьте, есть ли у вас d_type с помощью макроса препроцессора _DIRENT_HAVE_D_TYPE. Если да, используйте d_type. Получение нужной информации из таблицы каталогов (если она доступна) будет более эффективным, чем поиск и чтение всех инодов для файлов.
  3. В качестве запасной меры (сделайте, как указано выше) используйте stat для чтения инодов и проверьте st_mode с помощью макроса S_ISDIR() (или аналогичной проверки).
person e0k    schedule 05.02.2016
comment
Есть одна деталь, которую вы упустили: причина, по которой d_type отсутствует в OP, заключается в том, что она отсутствует в устаревшей 32-разрядной-off_t версии dirent, которую вы никогда не должны использовать. Соберите с -D_FILE_OFFSET_BITS=64 и все будет хорошо. - person R.. GitHub STOP HELPING ICE; 05.02.2016
comment
@R.. Для совместимости было бы лучше просто stat записи? - person e0k; 05.02.2016
comment
Использование stat будет на порядок медленнее или хуже, потому что время выполнения такого кода примерно пропорционально количеству сделанных системных вызовов, а stat вдобавок является довольно тяжелым системным вызовом. Это еще до того, как вы доберетесь до бремени ввода-вывода: с помощью stat вы выполняете ввод-вывод на инодах для каждой записи каталога (интенсивный произвольный доступ), а не просто читаете таблицу каталогов (компактное линейное чтение). Вы должны предоставить переносимый резервный вариант stat, если _DIRENT_HAVE_D_TYPE не определен, но в противном случае определенно используйте d_type, если он у вас есть. - person R.. GitHub STOP HELPING ICE; 05.02.2016