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

Другие вопросы по тегам