bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 'fflush' test failure on Cygwin


From: Bruno Haible
Subject: Re: 'fflush' test failure on Cygwin
Date: Wed, 25 Apr 2007 11:17:26 +0200
User-agent: KMail/1.5.4

On 2007-04-13, I wrote:
> 2) fseek() is heavily optimized: fseeko (fp, pos, SEEK_SET) will position
>    the file descriptor to   pos & ~fp->_blksize  and then read one buffer,
>    [or if   pos   is inside the current buffer, optimize even more: just
>    change some pointers and counters, without accessing the file descriptor],
>    unless
>      - fp is not seekable, or
>      - fp is open for writing (__SWR | __SRW), or
>      - fp is unbuffered (__SNBF), or
>      - fp has an unusual block size set through setvbuf (__SNPT).
>    If your fflush or fseek was to invoke setvbuf, it's hard to keep programs
>    working that use setvbuf as well.
> 
>    A solution might be to make a wrapper around fseek() roughly like this:
> 
>      rpl_fseek (...)
>      {
>        if (fp is not open for writing
>            && fp's buffer is empty, like after fpurge)
>          perform just an lseek
>        else
>          fseek (...);
>      }

This implements it.

2007-04-25  Bruno Haible  <address@hidden>

        Make fflush+fseek POSIX-compliant on FreeBSD and MacOS X.
        * lib/fseeko.c: New file.
        * lib/stdio_.h: Include <sys/types.h> when off_t is needed.
        (fseeko, fseek): Define to replacements if REPLACE_FFLUSH.
        * m4/fseeko.m4 (gl_CHECK_FSEEKO): New macro, extracted from
        gl_FUNC_FSEEKO.
        (gl_FUNC_FSEEKO): Invoke it.
        * m4/fflush.m4 (gl_REPLACE_FFLUSH): Arrange to compile fseeko.c. Invoke
        gl_CHECK_FSEEKO. Define HAVE_FSEEKO.
        * modules/fflush (Files): Add lib/fseeko.c, m4/fseeko.m4.

======================== lib/fseeko.c ====================================
/* An fseek() function that, together with fflush(), is POSIX compliant.
   Copyright (C) 2007 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#include <config.h>

/* Specification.  */
#include <stdio.h>

/* Get off_t and lseek.  */
#include <unistd.h>

#undef fseeko
#if !HAVE_FSEEKO
# define fseeko fseek
#endif

int
rpl_fseeko (FILE *fp, off_t offset, int whence)
{
  /* These tests are based on fpurge.c.  */
#if defined _IO_ferror_unlocked     /* GNU libc, BeOS */
  if (fp->_IO_read_end == fp->_IO_read_ptr
      && fp->_IO_write_ptr == fp->_IO_write_base
      && fp->_IO_save_base == NULL)
#elif defined __sferror             /* FreeBSD, NetBSD, OpenBSD, MacOS X, 
Cygwin */
# if defined __NetBSD__ || defined __OpenBSD__ /* NetBSD, OpenBSD */
   /* See 
<http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
      and 
<http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fileext.h?rev=HEAD&content-type=text/x-cvsweb-markup>
 */
#  define fp_ub ((struct { struct __sbuf _ub; } *) fp->_ext._base)->_ub
# else                                         /* FreeBSD, MacOS X, Cygwin */
#  define fp_ub fp->_ub
# endif
  if (fp->_p == fp->_bf._base
      && fp->_r == 0
      && fp->_w == ((fp->_flags & (__SLBF | __SNBF)) == 0 /* fully buffered? */
                    ? fp->_bf._size
                    : 0)
      && fp_ub._base == NULL)
#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, mingw 
*/
# if defined __sun && defined __sparc && defined _LP64 /* Solaris/SPARC 64-bit 
*/
#  define fp_ ((struct { unsigned char *_ptr; \
                         unsigned char *_base; \
                         unsigned char *_end; \
                         long _cnt; \
                       } *) fp)
  if (fp_->_ptr == fp_->_base
      && (fp_->_ptr == NULL || fp_->_cnt == 0))
# else
  if (fp->_ptr == fp->_base
      && (fp->_ptr == NULL || fp->_cnt == 0))
# endif
#else
  #error "Please port gnulib fseeko.c to your platform! Look at the code in 
fpurge.c, then report this to bug-gnulib."
#endif
    return (lseek (fileno (fp), offset, whence) == (off_t)(-1) ? -1 : 0);
  else
    return fseeko (fp, offset, whence);
}
==========================================================================
*** lib/stdio_.h        25 Apr 2007 07:51:53 -0000      1.19
--- lib/stdio_.h        25 Apr 2007 09:10:07 -0000
***************
*** 38,43 ****
--- 38,48 ----
  #include <stdarg.h>
  #include <stddef.h>
  
+ #if @GNULIB_FFLUSH@ && @REPLACE_FFLUSH@
+ /* Get off_t.  */
+ # include <sys/types.h>
+ #endif
+ 
  #ifndef __attribute__
  /* This feature is available in gcc versions 2.5 and later.  */
  # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
***************
*** 207,213 ****
  # endif
  #endif
  
! #if @GNULIB_FSEEKO@
  # if address@hidden@
  /* Assume 'off_t' is the same type as 'long'.  */
  #  define fseeko fseek
--- 212,223 ----
  # endif
  #endif
  
! #if @GNULIB_FFLUSH@ && @REPLACE_FFLUSH@
! /* Provide fseek, fseeko functions that are aware of a preceding fflush().  */
! # define fseeko rpl_fseeko
! extern int fseeko (FILE *fp, off_t offset, int whence);
! # define fseek(fp, offset, whence) fseeko (fp, (off_t)(offset), whence)
! #elif @GNULIB_FSEEKO@
  # if address@hidden@
  /* Assume 'off_t' is the same type as 'long'.  */
  #  define fseeko fseek
*** m4/fseeko.m4        25 Apr 2007 07:39:56 -0000      1.1
--- m4/fseeko.m4        25 Apr 2007 09:10:07 -0000
***************
*** 7,19 ****
  AC_DEFUN([gl_FUNC_FSEEKO],
  [
    AC_REQUIRE([gl_STDIO_H_DEFAULTS])
    AC_REQUIRE([AC_PROG_CC])
    AC_CACHE_CHECK([for fseeko], [gl_cv_func_fseeko],
      [
        AC_TRY_LINK([#include <stdio.h>], [fseeko (stdin, 0, 0);],
          [gl_cv_func_fseeko=yes], [gl_cv_func_fseeko=no])
      ])
-   if test $gl_cv_func_fseeko = no; then
-     HAVE_FSEEKO=0
-   fi
  ])
--- 7,24 ----
  AC_DEFUN([gl_FUNC_FSEEKO],
  [
    AC_REQUIRE([gl_STDIO_H_DEFAULTS])
+   gl_CHECK_FSEEKO
+   if test $gl_cv_func_fseeko = no; then
+     HAVE_FSEEKO=0
+   fi
+ ])
+ 
+ AC_DEFUN([gl_CHECK_FSEEKO],
+ [
    AC_REQUIRE([AC_PROG_CC])
    AC_CACHE_CHECK([for fseeko], [gl_cv_func_fseeko],
      [
        AC_TRY_LINK([#include <stdio.h>], [fseeko (stdin, 0, 0);],
          [gl_cv_func_fseeko=yes], [gl_cv_func_fseeko=no])
      ])
  ])
*** m4/fflush.m4        17 Apr 2007 03:40:30 -0000      1.3
--- m4/fflush.m4        25 Apr 2007 09:10:07 -0000
***************
*** 1,4 ****
! #serial 2
  
  # Copyright (C) 2007 Free Software Foundation, Inc.
  # This file is free software; the Free Software Foundation
--- 1,4 ----
! #serial 3
  
  # Copyright (C) 2007 Free Software Foundation, Inc.
  # This file is free software; the Free Software Foundation
***************
*** 45,50 ****
--- 45,56 ----
  AC_DEFUN([gl_REPLACE_FFLUSH],
  [
    AC_LIBOBJ([fflush])
+   AC_LIBOBJ([fseeko])
    AC_REQUIRE([gl_STDIO_H_DEFAULTS])
    REPLACE_FFLUSH=1
+   gl_CHECK_FSEEKO
+   if test $gl_cv_func_fseeko = yes; then
+     AC_DEFINE([HAVE_FSEEKO], 1,
+       [Define to 1 if you have the fseeko() function or macro.])
+   fi
  ])
*** modules/fflush      25 Apr 2007 07:56:32 -0000      1.4
--- modules/fflush      25 Apr 2007 09:10:07 -0000
***************
*** 3,9 ****
--- 3,11 ----
  
  Files:
  lib/fflush.c
+ lib/fseeko.c
  m4/fflush.m4
+ m4/fseeko.m4
  
  Depends-on:
  fpurge





reply via email to

[Prev in Thread] Current Thread [Next in Thread]