bug-gnulib
[Top][All Lists]
Advanced

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

Re: workaround ftello/fseeko on cygwin 1.5.x


From: Bruno Haible
Subject: Re: workaround ftello/fseeko on cygwin 1.5.x
Date: Thu, 24 May 2007 00:36:02 +0200
User-agent: KMail/1.5.4

Eric Blake wrote:
> It overcomes the
> fact that cygwin was creating the three std streams in 32-bit mode instead
> of 64-bit mode, such that fseeko/ftello failed because they expected the
> stream to be in 64-bit mode.

Glad to see that you found a workaround!

> Index: lib/fseeko.c
> ===================================================================
> RCS file: /sources/gnulib/gnulib/lib/fseeko.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 fseeko.c
> --- lib/fseeko.c      29 Apr 2007 12:16:55 -0000      1.3
> +++ lib/fseeko.c      23 May 2007 16:44:57 -0000
> @@ -44,6 +44,19 @@ rpl_fseeko (FILE *fp, off_t offset, int 
>  # else                                         /* FreeBSD, MacOS X, Cygwin */
>  #  define fp_ub fp->_ub
>  # endif
> +# if defined __SL64 && defined __SCLE /* Cygwin */
> +  if ((fp->_flags & __SL64) == 0)
> +    {
> +      /* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit
> +      mode; but has an fseeko that requires 64-bit mode.  */
> +      FILE *tmp = fopen ("/dev/null", "r");
> +      if (!tmp)
> +     return -1;
> +      fp->_flags |= __SL64;
> +      fp->_seek64 = tmp->_seek64;
> +      fclose (tmp);
> +    }
> +# endif

Every time fseeko or ftello is applied for the first time to a stream, this
code will fopen /dev/null. Sounds a bit expensive. Can't you cache the
_seek64 pointer that you found? Something like this:

  /* Ensures that the given stream is open in 64-bit mode.  */
  void
  cygfreopen64 (FILE *fp)
  {
    static _fpos64_t (*seek64_func) (void *_cookie, _fpos64_t _offset, int 
_whence);
    if (seek64_func == NULL)
      {
        FILE *tmp = fopen ("/dev/null", "r");
        if (tmp != NULL)
          {
            seek64_func = tmp->_seek64;
            fclose (tmp);
          }
        else
          seek64_func = (void *) (-1);
      }
    if (seek64_func != (void *) (-1))
      {
        fp->_flags |= __SL64;
        fp->_seek64 = seek64_func;
      }
  }

Put this into a separate compilation unit, so that fseeko and ftello can
share the same cache.

> @@ -233,6 +235,11 @@ typedef int verify_fseeko_types[2 * (siz
>     (GL_LINK_WARNING ("fseeko is unportable - " \
>                       "use gnulib module fseeko for portability"), \
>      fseeko (f, o, w))
> +# undef fseek
> +# define fseek(f,o,w) \
> +   (GL_LINK_WARNING ("fseek is artificially limited - " \
> +                     "use gnulib module fseeko for portability"), \
> +    fseek (f, o, w))
>  #endif

You don't need this: The warning about fseek is already contained in
stdio_.h lines 238..246, and the one for tell is already at stdio_.h lines
262..270.

> @@ -257,6 +267,11 @@ typedef int verify_ftello_types[2 * (siz
>     (GL_LINK_WARNING ("ftello is unportable - " \
>                       "use gnulib module ftello for portability"), \
>      ftello (f))
> +# undef ftell
> +# define ftell(f) \
> +   (GL_LINK_WARNING ("ftell is artificially limited - " \
> +                     "use gnulib module ftello for portability"), \
> +    ftell (f))
>  #endif

Likewise.

> Index: m4/fseeko.m4
> ===================================================================
> RCS file: /sources/gnulib/gnulib/m4/fseeko.m4,v
> retrieving revision 1.3
> diff -u -p -r1.3 fseeko.m4
> --- m4/fseeko.m4      26 Apr 2007 09:33:12 -0000      1.3
> +++ m4/fseeko.m4      23 May 2007 16:44:57 -0000
> @@ -1,4 +1,4 @@
> -# fseeko.m4 serial 1
> +# fseeko.m4 serial 2
>  dnl Copyright (C) 2007 Free Software Foundation, Inc.
>  dnl This file is free software; the Free Software Foundation
>  dnl gives unlimited permission to copy and/or distribute it,
> @@ -8,6 +8,7 @@ AC_DEFUN([gl_FUNC_FSEEKO],
>  [
>    AC_REQUIRE([gl_STDIO_H_DEFAULTS])
>    AC_REQUIRE([AC_PROG_CC])
> +  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
>    AC_CACHE_CHECK([for fseeko], [gl_cv_func_fseeko],
>      [
>        AC_TRY_LINK([#include <stdio.h>], [fseeko (stdin, 0, 0);],
> @@ -15,5 +16,32 @@ AC_DEFUN([gl_FUNC_FSEEKO],
>      ])
>    if test $gl_cv_func_fseeko = no; then
>      HAVE_FSEEKO=0
> +  else
> +    AC_CACHE_CHECK([if fseeko(stdin) works], [gl_cv_func_fseeko_stdin],
> +      [
> +        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>],
> +          [
> +#if defined __SL64 && defined __SCLE /* cygwin */
> +   /* Cygwin 1.5.24 and earlier fail to put stdin in 64-bit mode, making
> +      fseeko/ftello needlessly fail.  This bug was fixed at the same time
> +      that cygwin started exporting asnprintf (cygwin 1.7.0), so we use
> +      that as a link-time test for cross-compiles rather than building
> +      a runtime test.  */
> +   size_t s;
> +   if (asnprintf (NULL, &s, ""))
> +     return 0;
> +#endif
> +            ])],
> +          [gl_cv_func_fseeko_stdin=yes], [gl_cv_func_fseeko_stdin=no])])
> +    if test $gl_cv_func_fseeko_stdin = no; then
> +      gl_REPLACE_FSEEKO
> +    fi

This test is duplicated between fseeko.m4 and ftello.m4. Since you use
two different cache variables, it will even be executed twice per 'configure'
run. I would put it into a separate macro, say, in stdio_h.m4.

Bruno





reply via email to

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