when __USE_FILE_OFFSET64 is defined fstat() should behave the same as fstat64(), and struct stat should be compatible with struct stat64. This is not the case on my ubuntu edgy system with glibc 2.4-1ubuntu12, but the same seems to be true for glibc 2.5 as well. The problem is best described with this gdb session snippet: (gdb) p (char *)&st.st_size - (char *) &st $11 = 48 (gdb) p (char *)&st64.st_size - (char *) &st64 $12 = 44 As you can guess, the st_size field contains a bogus value. I'm using this set of CPPFLAGS: -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 The problem is that bits/stat.h contains short int sized padN fields while struct stat64 contains int sized padding fields: struct stat { __dev_t st_dev; /* Device. */ unsigned short int __pad1; ... } struct stat64 { __dev_t st_dev; /* Device. */ unsigned int __pad1; }
Then the bug is Ubuntu specific. (gdb) p (char *)&st64.st_size - (char *)&st64 $1 = 44 (gdb) p (char *)&st.st_size - (char *)&st $2 = 44 and #define _GNU_SOURCE #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 #include <sys/stat.h> #include <stddef.h> #include <stdio.h> int main (void) { printf ("%zd\n", (size_t) offsetof (struct stat, st_size)); printf ("%zd\n", (size_t) offsetof (struct stat64, st_size)); return 0; } prints 44 twice for 32-bit binaries (both on x86_64 -m32 and on i?86 only), 48 for 64-bit binaries.
hmm... it prints 44 for me as well, it seems to be somewhat more involved, then. I can clearly reproduce this problem when syslog-ng is run, but prints a proper value when it is your testprogram. I'm rechecking now, sorry for bothering you.
Just for the curious, this is not a glibc bug. gdb uses invalid offsets, probably because it sees two declarations of struct stat, one is in syslog-ng, the other is a statically linked library (libnet). The two differs, and I was unlucky. while gdb reports invalid values, the program sees them perfectly. I mark the bug VERIFIED.