readdir() 32/64 проблемы совместимости
Я пытаюсь заставить старый унаследованный код работать на новых 64-битных системах, и сейчас я застрял. Ниже приведен небольшой файл C, который я использую для тестирования функциональности, существующей в реальной программе, которая в данный момент ломается.
#define _POSIX_SOURCE
#include <dirent.h>
#include <sys/types.h>
#undef _POSIX_SOURCE
#include <stdio.h>
main(){
DIR *dirp;
struct dirent *dp;
char *const_dir;
const_dir = "/any/path/goes/here";
if(!(dirp = opendir(const_dir)))
perror("opendir() error");
else{
puts("contents of path:");
while(dp = readdir(dirp))
printf(" %s\n", dp->d_name);
closedir(dirp);
}
}
Эта проблема:
ОС Red Hat 7.0 Maipo x86_64. Устаревший код является 32-разрядным и должен храниться таким образом.
Я получил компиляцию для программы, работающей нормально, используя -m32
флаг с g++
, Проблема, которая возникает во время выполнения, readdir()
получает 64-битный инод, а затем выдает EOVERFLOW с ошибкой и, конечно, ничего не распечатывается.
Я пытался использовать readdir64()
на месте readdir()
к некоторому успеху. Я больше не получаю ошибку EOVERFLOW, и строки выходят на терминал, но сами файлы не печатаются. Я предполагаю, что это связано с тем, что буфер не dirent
надеется.
Я пытался использовать dirent64
чтобы попытаться облегчить эту проблему, но всякий раз, когда я пытаюсь это сделать, я получаю:
test.c:19:22 error: dereferencing pointer to incomplete type
printf(" %s\n", dp->d_name);
Мне интересно, есть ли способ вручную сдвинуть dp->d_name
буфер для dirent
использоваться с readdir()
, Я заметил в Gdb, что с помощью readdir()
а также dirent
результаты в dp->d_name
каталоги, перечисленные в dp->d_name[1]
, в то время как readdir64()
а также dirent
дает первый каталог в dp->d_name[8]
,
Это или как-то получить dirent64
на работу, или, может быть, я просто на неправильном пути полностью.
Наконец, стоит отметить, что программа прекрасно работает без -m32
флаг включен, поэтому я предполагаю, что это должна быть ошибка совместимости 32/64 где-то. Любая помощь приветствуется.
2 ответа
Для того, чтобы получить 64-битную ino_t
с GCC и Glibc вам нужно определить функции _XOPEN_SOURCE
а также _FILE_OFFSET_BITS=64
,
$ echo '#include <dirent.h>' | gcc -m32 -E -D_XOPEN_SOURCE -D_FILE_OFFSET_BITS=64 - | grep ino
__extension__ typedef unsigned long int __ino_t;
__extension__ typedef __u_quad_t __ino64_t;
typedef __ino64_t ino_t;
__ino64_t d_ino;
Я говорю это из чтения документации и проверки препроцессора, а не из глубокого опыта или тестирования с файловой системой с номерами инодов выше 2^32, поэтому я не гарантирую, что вы не столкнетесь с другими проблемами в будущем.
Благодаря @Martin в комментариях выше я был вынужден попытаться определить структуру dirent64 в моем коде. Это работает. Вероятно, есть #define, который можно использовать, чтобы обойти вставку кода libc.h в мой собственный код, но пока это работает.
Код, который мне нужен был найден в <bits/dirent.h
>
Я думаю, я должен также отметить, что это заставляет его работать как readdir64() и dirent64