|go text: || - index - problems - systems - libraries - converting - programming - old library - [ new library ] - links -
||topics: || - [ dual export ] - largefiles win32 - compat32 calls - compat32 library - long32 dualmode -

Dual Export

Dual 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.