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 |
Dualmode SourcesIn the case of a 64on32 system with two largefile-sensitive off_t variations you have gone to rename symbols as they are exported from the library when the library is compiled in largefile64 mode. To allow non-largefile code to link to your library requires a second symbol being exported from your library and it should be under the old name - i.e. not renamed. The implementation can take advantage of the fact that before the introduction of "off_t" all seek-values where using "long". So in the case of 64on32 one can assume that sizeof(off_t) is 64bit and sizeof(long) is 32bit. Nothing needs to be told about that in headers - in your *.c implementation files you would add the following code to export both symbols. off_t my_seek(MYHANDLE fp) { /* this is the largefile64 variant that creates a symbol "my_seek64" if _FILE_OFFSET_BITS == 64 was seen in the precompiler environment */ } #ifndef EOVERFLOW #define EOVERFLOW EFBIG #endif #ifdef MYLIB_LARGEFILE_RENAME #undef my_seek long my_seek(MYHANDLE * fp, long offset, int whence) { if (sizeof(off_t) == sizeof(long)) { return my_seek64(fp, offset, whence); } else { off_t off = my_seek64(fp, offset, whence); if (off >= 0) { register long off32 = off; if (off32 == off) return off32; errno = EOVERFLOW; } return -1L; } } The usage of EOVERFLOW is what the Unix-LFS largefile standard recommends. However this has two problems - first all there is the WIN32 API which does have neither "off_t" nor "EOVERFLOW". In that case one should define "off_t" to "long" and "EOVERFLOW" to "EFBIG". Of course one could simplify the code by using EFBIG in the first place. Using EFBIG as the return code for the "largefile case" is easier for the application code which will usually not care really if the EFBIG error is based on the 32bit-off_t restricted function call -or- because the file lives on a filesystem that can not create files beyond a certain limit (e.g. on good old FAT windows paritions). In both case it is best to bail out for the application. Another simplification could live under the assumption the the "#define my_seek" does only exist in the largefile64 case. So the simplified implementation code could look like: off_t my_seek(MYHANDLE fp) { /* this is the largefile64 variant that creates a symbol "my_seek64" */ } #ifdef my_seek #undef my_seek long my_seek(MYHANDLE * fp, long offset, int whence) { if (sizeof(off_t) == sizeof(long)) { return my_seek64(fp, offset, whence); } else { off_t off = my_seek64(fp, offset, whence); if (off >= 0) { register long off32 = off; if (off32 == off) return off32; errno = EFBIG; } return -1; } } |