index -summary -history -testscript perl / python problems -with callframes -with structures -largefile seeks -broken builds systems -freeBSD/darwin -linux/solaris -64on32 mix -distro makers -win32/other (2) libraries - libc ..(3264)
- zlib ..(-32-)
- gtk2 ..(-64-)
converting -old non-off_t code -going largefile -longlong default -face dualmode -make twinlibs -and defend (it) programming -largefile default -off_t in headers -make export64 -find mismatch -the autowrappers -environ changes -best practice? old library -dualmode renames -the extra function -largefile64_source -glibc headers -libgz example *** new library -dual export -largefiles win32 -compat32 calls -compat32 library -long32 dualmode links -some quotes -sitemap / mpl -large.file Group* -ac-archive Site*
(C) 2010-03-27 Guido U. Draheim |
Dual ExportDual Export is basically a simplication of the dualmode library appraoch. Instead of renaming largefile64 functions into a new call with a "64" suffix in the largefile64 case and a conditional implementation with "long" one would simply expose both an "off_t" variant as "64" and a "long" variant with the extension "32". Both implementations are visible - no _LARGEFILE_SOURCE or _LARGEFILE64_SOURCE is required here. In order to let application code to not care about which to take, we pick up the usual LARGEFILES redirect - the library binary however will only have explicit symbols in its export table. extern off_t myseek64(int fd, off_t seek, int whence); extern long myseek32(int fd, long seek, int whence); #if _FILE_OFFSET_BITS+0 == 64 || defined _LARGE_FILES #define myseek myseek64 #else #define myseek myseek32 #endif The standard implementation of the myseek32 would be a wrapper around the largefile64 variant. Note that no #ifdef/#undef is needed anymore. On a system that is not 64on32 it happens that both "long" and "off_t" are the same type, so we try to ask the compiler to detect the situation and "remove unreachable code" (which modern C compilers can actually do). As a consequence the code template looks like this... #ifndef EOVERFLOW #define EOVERFLOW EFBIG #endif off_t myseek64(MYFILE * fp, off_t offset, int whence) { /* implement your code under the assumption that your library is always compiled with AC_SYS_LARGFILE enabled. */ } long myseek32(MYFILE * fp, long offset, int whence) { if (sizeof(off_t) == sizeof(long)) { return myseek64(fp, offset, whence); } else { off_t off = myseek(fp, offset, whence); if (off >= 0) { register long off32 = off; if (off32 == off) return off32; errno = EOVERFLOW; } return -1; } } Note that in the case that someone has disabled the largefile-compilation (e.g. "--disable-largefile" for the autoconf AC_SYS_LARGEFILE case) the myseek64 could possibly be compiled with a "long32" which again makes the second myseek32 implementation collapse into calling it as the master implementation. Same thing happens on a system with "long" being 64bit from the start. In any case the re-call from myseek32 to myseek64 should be fast enough for most cases - and if anyone cares for speed then the application writer should compile in largefile64 mode. This is also good reasoning because the C library does the same and the Unix kernel calls (e.g. on Linux) will take 64bit offset values anyway - somewhere someone needs to convert values between 32bit values and the real 64bit values which should best be avoided at best. As soon as the application writer switches to AC_SYS_LARGEFILES then the call "myseek64" is being called directly. |