2016-02-05 2 views
1

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

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

переменное «де» не имеет структуры Dirent типа * и проверяются на его тип, и я получаю сообщение об ошибке: «STRUCT Dirent» уже не член с именем «de_type»

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

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

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

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

+0

Какой тип файловой системы вы используете? – e0k

+0

Итак, теперь вопрос не имеет смысла, так как название говорит 'd_type' и везде, где есть' de_type'. – user3386109

ответ

5

От man readdir(3):

The only fields in the dirent structure that are mandated by POSIX.1 are: d_name[], of unspecified size, with at most NAME_MAX characters preceding the terminating null byte; and (as an XSI extension) d_ino. The other fields are unstandardized, and not present on all systems; see NOTES below for some further details.

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

Only the fields d_name and d_ino are specified in POSIX.1-2001. The remaining fields are available on many, but not all systems. Under glibc, programs can check for the availability of the fields not defined in POSIX.1 by testing whether the macros _DIRENT_HAVE_D_NAMLEN, _DIRENT_HAVE_D_RECLEN, _DIRENT_HAVE_D_OFF, or _DIRENT_HAVE_D_TYPE are defined.

Other than Linux, the d_type field is available mainly only on BSD systems. This field makes it possible to avoid the expense of calling lstat(2) if further actions depend on the type of the file. If the _BSD_SOURCE feature test macro is defined, then glibc defines the following macro constants for the value returned in d_type:

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


Добавление: См @R .. 's комментарии ниже и this answer. В резюме:

  1. Правильное использование. Добавьте -D_FILE_OFFSET_BITS=64 в свои флагов компилятора и создайте с 64-битными смещениями файлов.
  2. Проверьте, есть ли у вас d_type с макросом препроцессора _DIRENT_HAVE_D_TYPE. Если да, используйте d_type. Получение необходимой информации из таблицы каталогов (если доступно) будет более эффективным, чем поиск &, считывающий все inodes для файлов.
  3. В качестве меры снижения, (как описано выше) используйте stat для чтения inodes и проверьте st_mode с помощью макроса S_ISDIR() (или аналогичная проверка).
+1

Есть недостаток, который вы пропустили - причина, по которой «d_type» отсутствует для OP, заключается в том, что в устаревшей 32-битной версии '' '' 'dirent' версии' dirent' отсутствует **, которую вы никогда не должны использовать **. Создайте с '-D_FILE_OFFSET_BITS = 64', и все будет хорошо. –

+0

@R .. Для совместимости было бы лучше просто «статизировать» записи? – e0k

+1

Использование 'stat' будет на порядок медленнее или хуже, потому что время выполнения для такого кода примерно пропорционально количеству сделанных syscalls, а' stat' - довольно тяжелый syscall поверх этого. Это до того, как вы доберетесь до нагрузки IO: с помощью 'stat' вы выполняете IO на inodes для каждой записи dir (тяжелый случайный доступ), а не просто читаете таблицу каталогов (компактное линейное чтение). Вы должны предоставить переносимый ответ на 'stat', если' _DIRENT_HAVE_D_TYPE' не определен, но в противном случае ** определенно используйте 'd_type' **, если он у вас есть. –