Blame src/gl/fseeko.c

Packit 549fdc
/* An fseeko() function that, together with fflush(), is POSIX compliant.
Packit 549fdc
   Copyright (C) 2007-2016 Free Software Foundation, Inc.
Packit 549fdc
Packit 549fdc
   This program is free software; you can redistribute it and/or modify
Packit 549fdc
   it under the terms of the GNU General Public License as published by
Packit 549fdc
   the Free Software Foundation; either version 3, or (at your option)
Packit 549fdc
   any later version.
Packit 549fdc
Packit 549fdc
   This program is distributed in the hope that it will be useful,
Packit 549fdc
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 549fdc
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 549fdc
   GNU General Public License for more details.
Packit 549fdc
Packit 549fdc
   You should have received a copy of the GNU General Public License along
Packit 549fdc
   with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit 549fdc
Packit 549fdc
#include <config.h>
Packit 549fdc
Packit 549fdc
/* Specification.  */
Packit 549fdc
#include <stdio.h>
Packit 549fdc
Packit 549fdc
/* Get off_t, lseek, _POSIX_VERSION.  */
Packit 549fdc
#include <unistd.h>
Packit 549fdc
Packit 549fdc
#include "stdio-impl.h"
Packit 549fdc
Packit 549fdc
int
Packit 549fdc
fseeko (FILE *fp, off_t offset, int whence)
Packit 549fdc
#undef fseeko
Packit 549fdc
#if !HAVE_FSEEKO
Packit 549fdc
# undef fseek
Packit 549fdc
# define fseeko fseek
Packit 549fdc
#endif
Packit 549fdc
#if _GL_WINDOWS_64_BIT_OFF_T
Packit 549fdc
# undef fseeko
Packit 549fdc
# if HAVE__FSEEKI64 /* msvc, mingw64 */
Packit 549fdc
#  define fseeko _fseeki64
Packit 549fdc
# else /* mingw */
Packit 549fdc
#  define fseeko fseeko64
Packit 549fdc
# endif
Packit 549fdc
#endif
Packit 549fdc
{
Packit 549fdc
#if LSEEK_PIPE_BROKEN
Packit 549fdc
  /* mingw gives bogus answers rather than failure on non-seekable files.  */
Packit 549fdc
  if (lseek (fileno (fp), 0, SEEK_CUR) == -1)
Packit 549fdc
    return EOF;
Packit 549fdc
#endif
Packit 549fdc
Packit 549fdc
  /* These tests are based on fpurge.c.  */
Packit 549fdc
#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
Packit 549fdc
  if (fp->_IO_read_end == fp->_IO_read_ptr
Packit 549fdc
      && fp->_IO_write_ptr == fp->_IO_write_base
Packit 549fdc
      && fp->_IO_save_base == NULL)
Packit 549fdc
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
Packit 549fdc
  /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
Packit 549fdc
# if defined __SL64 && defined __SCLE /* Cygwin */
Packit 549fdc
  if ((fp->_flags & __SL64) == 0)
Packit 549fdc
    {
Packit 549fdc
      /* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit
Packit 549fdc
         mode; but has an fseeko that requires 64-bit mode.  */
Packit 549fdc
      FILE *tmp = fopen ("/dev/null", "r");
Packit 549fdc
      if (!tmp)
Packit 549fdc
        return -1;
Packit 549fdc
      fp->_flags |= __SL64;
Packit 549fdc
      fp->_seek64 = tmp->_seek64;
Packit 549fdc
      fclose (tmp);
Packit 549fdc
    }
Packit 549fdc
# endif
Packit 549fdc
  if (fp_->_p == fp_->_bf._base
Packit 549fdc
      && fp_->_r == 0
Packit 549fdc
      && fp_->_w == ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */
Packit 549fdc
                     ? fp_->_bf._size
Packit 549fdc
                     : 0)
Packit 549fdc
      && fp_ub._base == NULL)
Packit 549fdc
#elif defined __EMX__               /* emx+gcc */
Packit 549fdc
  if (fp->_ptr == fp->_buffer
Packit 549fdc
      && fp->_rcount == 0
Packit 549fdc
      && fp->_wcount == 0
Packit 549fdc
      && fp->_ungetc_count == 0)
Packit 549fdc
#elif defined __minix               /* Minix */
Packit 549fdc
  if (fp_->_ptr == fp_->_buf
Packit 549fdc
      && (fp_->_ptr == NULL || fp_->_count == 0))
Packit 549fdc
#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
Packit 549fdc
  if (fp_->_ptr == fp_->_base
Packit 549fdc
      && (fp_->_ptr == NULL || fp_->_cnt == 0))
Packit 549fdc
#elif defined __UCLIBC__            /* uClibc */
Packit 549fdc
  if (((fp->__modeflags & __FLAG_WRITING) == 0
Packit 549fdc
       || fp->__bufpos == fp->__bufstart)
Packit 549fdc
      && ((fp->__modeflags & (__FLAG_READONLY | __FLAG_READING)) == 0
Packit 549fdc
          || fp->__bufpos == fp->__bufread))
Packit 549fdc
#elif defined __QNX__               /* QNX */
Packit 549fdc
  if ((fp->_Mode & 0x2000 /* _MWRITE */ ? fp->_Next == fp->_Buf : fp->_Next == fp->_Rend)
Packit 549fdc
      && fp->_Rback == fp->_Back + sizeof (fp->_Back)
Packit 549fdc
      && fp->_Rsave == NULL)
Packit 549fdc
#elif defined __MINT__              /* Atari FreeMiNT */
Packit 549fdc
  if (fp->__bufp == fp->__buffer
Packit 549fdc
      && fp->__get_limit == fp->__bufp
Packit 549fdc
      && fp->__put_limit == fp->__bufp
Packit 549fdc
      && !fp->__pushed_back)
Packit 549fdc
#elif defined EPLAN9                /* Plan9 */
Packit 549fdc
  if (fp->rp == fp->buf
Packit 549fdc
      && fp->wp == fp->buf)
Packit 549fdc
#elif FUNC_FFLUSH_STDIN < 0 && 200809 <= _POSIX_VERSION
Packit 549fdc
  /* Cross-compiling to some other system advertising conformance to
Packit 549fdc
     POSIX.1-2008 or later.  Assume fseeko and fflush work as advertised.
Packit 549fdc
     If this assumption is incorrect, please report the bug to
Packit 549fdc
     bug-gnulib.  */
Packit 549fdc
  if (0)
Packit 549fdc
#else
Packit 549fdc
  #error "Please port gnulib fseeko.c to your platform! Look at the code in fseeko.c, then report this to bug-gnulib."
Packit 549fdc
#endif
Packit 549fdc
    {
Packit 549fdc
      /* We get here when an fflush() call immediately preceded this one (or
Packit 549fdc
         if ftell() has created buffers but no I/O has occurred on a
Packit 549fdc
         newly-opened stream).  We know there are no buffers.  */
Packit 549fdc
      off_t pos = lseek (fileno (fp), offset, whence);
Packit 549fdc
      if (pos == -1)
Packit 549fdc
        {
Packit 549fdc
#if defined __sferror || defined __DragonFly__ || defined __ANDROID__
Packit 549fdc
          /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
Packit 549fdc
          fp_->_flags &= ~__SOFF;
Packit 549fdc
#endif
Packit 549fdc
          return -1;
Packit 549fdc
        }
Packit 549fdc
Packit 549fdc
#if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
Packit 549fdc
      fp->_flags &= ~_IO_EOF_SEEN;
Packit 549fdc
      fp->_offset = pos;
Packit 549fdc
#elif defined __sferror || defined __DragonFly__ || defined __ANDROID__
Packit 549fdc
      /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Android */
Packit 549fdc
# if defined __CYGWIN__ || (defined __NetBSD__ && __NetBSD_Version__ >= 600000000)
Packit 549fdc
      /* fp_->_offset is typed as an integer.  */
Packit 549fdc
      fp_->_offset = pos;
Packit 549fdc
# else
Packit 549fdc
      /* fp_->_offset is an fpos_t.  */
Packit 549fdc
      {
Packit 549fdc
        /* Use a union, since on NetBSD, the compilation flags
Packit 549fdc
           determine whether fpos_t is typedef'd to off_t or a struct
Packit 549fdc
           containing a single off_t member.  */
Packit 549fdc
        union
Packit 549fdc
          {
Packit 549fdc
            fpos_t f;
Packit 549fdc
            off_t o;
Packit 549fdc
          } u;
Packit 549fdc
        u.o = pos;
Packit 549fdc
        fp_->_offset = u.f;
Packit 549fdc
      }
Packit 549fdc
# endif
Packit 549fdc
      fp_->_flags |= __SOFF;
Packit 549fdc
      fp_->_flags &= ~__SEOF;
Packit 549fdc
#elif defined __EMX__               /* emx+gcc */
Packit 549fdc
      fp->_flags &= ~_IOEOF;
Packit 549fdc
#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
Packit 549fdc
      fp->_flag &= ~_IOEOF;
Packit 549fdc
#elif defined __MINT__              /* Atari FreeMiNT */
Packit 549fdc
      fp->__offset = pos;
Packit 549fdc
      fp->__eof = 0;
Packit 549fdc
#endif
Packit 549fdc
      return 0;
Packit 549fdc
    }
Packit 549fdc
  return fseeko (fp, offset, whence);
Packit 549fdc
}