Blame src/gl/fseeko.c

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