Joerg Sonnenberger wrote: > Attached is a replacement version of fflush that is the least intrusive > version I can think of. No further replacements for ftello/fseeko are > needed. It should work with all BSD derived stdio implementations, > directly tested are NetBSD and DragonFly.
Thanks for this idea. Eric, here is a proposed patch for gnulib, that additionally: - uses the #ifdef for BSD systems, - not only sets __SNPT but also resets __SOPT. __SOPT tells fseek that it can use block-alignment as for regular files, __SNPT tells fseek that it must not do so. Since it is undocumented which of the two flags is tested first by fseek(), it is safer to reset __SOPT. - restores the previous flags after calling fseeko. Setting __SNPT means to disable block-aligned reading for *all* future fseek calls, but we need it only for the next one. Tested on MacOS X. If someone wants to submit a patch handling the __FILE_public, please do "gnulib-tool --create-testdir --dir=... fbufmode fflush fpurge freadable \ freading fseeko fseterr ftello fwritable fwriting" to see which files need to be adjusted for this special situation. Bruno 2007-07-27 Bruno Haible <[EMAIL PROTECTED]> * lib/fflush.c (rpl_fflush): On BSD systems, use the __SNPT flag. Suggested by Joerg Sonnenberger <[EMAIL PROTECTED]>. *** lib/fflush.c 27 Apr 2007 18:05:08 -0000 1.8 --- lib/fflush.c 27 Jul 2007 21:54:28 -0000 *************** *** 77,91 **** if (result != 0) return result; pos = lseek (fileno (stream), pos, SEEK_SET); if (pos == -1) return EOF; /* After a successful lseek, update the file descriptor's position cache in the stream. */ ! #if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */ stream->_offset = pos; stream->_flags |= __SOFF; ! #endif return 0; } --- 77,111 ---- if (result != 0) return result; + #if defined __sferror && defined __SNPT /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */ + + { + /* Disable seek optimization for the next fseeko call. This tells the + following fseeko call to seek to the desired position directly, rather + than to seek to a block-aligned boundary. */ + int saved_flags = stream->_flags & (__SOPT | __SNPT); + stream->_flags &= ~__SOPT; + stream->_flags |= __SNPT; + + result = fseeko (stream, pos, SEEK_SET); + + stream->_flags = (stream->_flags & ~(__SOPT | __SNPT)) | saved_flags; + } + return result; + + #else + pos = lseek (fileno (stream), pos, SEEK_SET); if (pos == -1) return EOF; /* After a successful lseek, update the file descriptor's position cache in the stream. */ ! # if defined __sferror /* FreeBSD, NetBSD, OpenBSD, MacOS X, Cygwin */ stream->_offset = pos; stream->_flags |= __SOFF; ! # endif return 0; + + #endif }