Blame lib/fseeko.c

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