Readdir () 32/64 compatibility issues

I am trying to get old old code working on new 64-bit systems, and I'm stuck right now. Below is a small C file that I use to test the functionality that exists in the current program, which is currently broken.

#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); } } 

Problem:

OS - Red Hat 7.0 Maipo x86_64. The legacy code is 32-bit and must be saved this way.

I got a compilation for the program to work using the -m32 flag with g++ . There is a problem at runtime, readdir() receives a 64-bit inode and then throws an EOVERFLOW error and, of course, nothing is printed.

I tried using readdir64() instead of readdir() for some success. I no longer get errno EOVERFLOW, and the lines are output to the terminal, but the files themselves are not printed. I assume this is because the buffer is not what dirent expects.

I tried using dirent64 to try to alleviate this problem, but whenever I try to do this, I get:

 test.c:19:22 error: dereferencing pointer to incomplete type printf(" %s\n", dp->d_name); 

I am wondering if there is a way to manually shift the dp->d_name for dirent , which will be used with readdir() . I noticed in Gdb that using readdir() and dirent results in dp->d_name having the directories listed in dp->d_name[1] , while readdir64() and dirent gives the first directory in dp->d_name[8] .

It is either somehow getting dirent64 to work, or maybe I'm completely wrong.

Finally, it is worth noting that the program works fine without the -m32 flag, so I assume that it should be a 32/64 compatibility error somewhere. Any help is appreciated.

+6
source share
2 answers

Thanks to @Martin in the comments above, I was asked to define the dirent64 structure in my code. It works. Probably #define, which can be used to bypass the insertion of libc.h code into my own code, but this works for now.

The code I need was found in <bits/dirent.h >

I think I should also note that this makes it work using both readdir64 () and dirent64

+1
source

To get the 64-bit ino_t with GCC and Glibc, you need to define the functions _XOPEN_SOURCE and _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; 

I say this from reading the documentation and checking the preprocessor, and not from deep experience or testing with a file system with inode numbers above 2 ^ 32, so I can not guarantee that you will not encounter other problems in the queue.

+1
source

Source: https://habr.com/ru/post/979880/


All Articles