Blame lib/fseeko.c

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