Large File Support for native Windows platforms.
[gnulib.git] / lib / fseeko.c
index 91b853d..7446560 100644 (file)
@@ -1,5 +1,5 @@
 /* An fseeko() function that, together with fflush(), is POSIX compliant.
-   Copyright (C) 2007-2009 Free Software Foundation, Inc.
+   Copyright (C) 2007-2012 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -12,8 +12,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+   with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
 
 #include "stdio-impl.h"
 
+int
+fseeko (FILE *fp, off_t offset, int whence)
 #undef fseeko
 #if !HAVE_FSEEKO
 # undef fseek
 # define fseeko fseek
 #endif
-
-int
-rpl_fseeko (FILE *fp, off_t offset, int whence)
+#if _GL_WINDOWS_64_BIT_OFF_T
+# undef fseeko
+# if HAVE__FSEEKI64 /* msvc, mingw64 */
+#  define fseeko _fseeki64
+# else /* mingw */
+#  define fseeko fseeko64
+# endif
+#endif
 {
 #if LSEEK_PIPE_BROKEN
   /* mingw gives bogus answers rather than failure on non-seekable files.  */
@@ -70,7 +76,10 @@ rpl_fseeko (FILE *fp, off_t offset, int whence)
       && fp->_rcount == 0
       && fp->_wcount == 0
       && fp->_ungetc_count == 0)
-#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
+#elif defined __minix               /* Minix */
+  if (fp_->_ptr == fp_->_buf
+      && (fp_->_ptr == NULL || fp_->_count == 0))
+#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
   if (fp_->_ptr == fp_->_base
       && (fp_->_ptr == NULL || fp_->_cnt == 0))
 #elif defined __UCLIBC__            /* uClibc */
@@ -87,18 +96,17 @@ rpl_fseeko (FILE *fp, off_t offset, int whence)
       && fp->__get_limit == fp->__bufp
       && fp->__put_limit == fp->__bufp
       && !fp->__pushed_back)
+#elif defined EPLAN9                /* Plan9 */
+  if (fp->rp == fp->buf
+      && fp->wp == fp->buf)
 #else
   #error "Please port gnulib fseeko.c to your platform! Look at the code in fpurge.c, then report this to bug-gnulib."
 #endif
     {
-      /* We get here when an fflush() call immediately preceded this one.  We
-         know there are no buffers.
-         POSIX requires us to modify the file descriptor's position.
-         But we cannot position beyond end of file here.  */
-      off_t pos =
-        lseek (fileno (fp),
-               whence == SEEK_END && offset > 0 ? 0 : offset,
-               whence);
+      /* We get here when an fflush() call immediately preceded this one (or
+         if ftell() has created buffers but no I/O has occurred on a
+         newly-opened stream).  We know there are no buffers.  */
+      off_t pos = lseek (fileno (fp), offset, whence);
       if (pos == -1)
         {
 #if defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
@@ -109,7 +117,13 @@ rpl_fseeko (FILE *fp, off_t offset, int whence)
 
 #if defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1 /* GNU libc, BeOS, Haiku, Linux libc5 */
       fp->_flags &= ~_IO_EOF_SEEN;
+      fp->_offset = pos;
 #elif defined __sferror || defined __DragonFly__ /* FreeBSD, NetBSD, OpenBSD, DragonFly, MacOS X, Cygwin */
+# if defined __CYGWIN__
+      /* fp_->_offset is typed as an integer.  */
+      fp_->_offset = pos;
+# else
+      /* fp_->_offset is an fpos_t.  */
       {
         /* Use a union, since on NetBSD, the compilation flags
            determine whether fpos_t is typedef'd to off_t or a struct
@@ -122,20 +136,18 @@ rpl_fseeko (FILE *fp, off_t offset, int whence)
         u.o = pos;
         fp_->_offset = u.f;
       }
+# endif
       fp_->_flags |= __SOFF;
       fp_->_flags &= ~__SEOF;
 #elif defined __EMX__               /* emx+gcc */
       fp->_flags &= ~_IOEOF;
-#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw */
+#elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, NonStop Kernel */
       fp->_flag &= ~_IOEOF;
 #elif defined __MINT__              /* Atari FreeMiNT */
       fp->__offset = pos;
       fp->__eof = 0;
 #endif
-      /* If we were not requested to position beyond end of file, we're
-         done.  */
-      if (!(whence == SEEK_END && offset > 0))
-        return 0;
+      return 0;
     }
   return fseeko (fp, offset, whence);
 }