changeset 16795:6a9ea5d7b466

Large File Support for native Windows platforms. * m4/largefile.m4 (gl_LARGEFILE): New macro. * modules/largefile (configure.ac): Require gl_LARGEFILE. * lib/sys_types.in.h (off_t) [WINDOWS_64_BIT_OFF_T]: Define to a 64-bit type. * m4/sys_types_h.m4 (gl_SYS_TYPES_H): Set WINDOWS_64_BIT_OFF_T. * modules/sys_types (Makefile.am): Substitute WINDOWS_64_BIT_OFF_T. * doc/posix-headers/sys_types.texi: Mention the effect of the 'largefile' module. * lib/fcntl.in.h: Add comments about off_t. * modules/fcntl-h (Depends-on): Add sys_types. * lib/unistd.in.h [WINDOWS_64_BIT_OFF_T]: Include <sys/types.h>. (ftruncate): Replace it if REPLACE_FTRUNCATE is 1. * m4/unistd_h.m4 (gl_UNISTD_H): Require gl_SYS_TYPES_H. (gl_UNISTD_H_DEFAULTS): Initialize REPLACE_FTRUNCATE. * modules/unistd (Depends-on): Add sys_types. (Makefile.am): Substitute WINDOWS_64_BIT_OFF_T, REPLACE_FTRUNCATE. * lib/lseek.c (rpl_lseek) [_GL_WINDOWS_64_BIT_OFF_T]: Use _lseeki64 instead of lseek. * m4/lseek.m4 (gl_FUNC_LSEEK): Require gl_SYS_TYPES_H. Set REPLACE_LSEEK if WINDOWS_64_BIT_OFF_T is 1. * modules/lseek (Depends-on): Add sys_types. * lib/ftruncate.c: Put under GPLv3+. Include <windows.h>, msvc-nothrow.h. (SetFileSize): New function. (ftruncate) [_GL_WINDOWS_64_BIT_OFF_T]: New implementation. * m4/ftruncate.m4 (gl_FUNC_FTRUNCATE): Set REPLACE_FTRUNCATE on Windows if Large File Support is requested. * modules/ftruncate (configure.ac): Consider REPLACE_FTRUNCATE. (Depends-on): Add sys_types, msvc-nothrow. Update conditions. * lib/stdio.in.h: Add comments about off_t. * modules/stdio (Depends-on): Add sys_types. * lib/ftello.c [_GL_WINDOWS_64_BIT_OFF_T]: Use _ftelli64 or ftello64 instead of ftello. * m4/ftello.m4 (gl_FUNC_FTELLO): Require gl_SYS_TYPES_H. Set REPLACE_FTELLO if WINDOWS_64_BIT_OFF_T is 1. (gl_PREREQ_FTELLO): New macro. * modules/ftello (Depends-on): Add sys_types. (configure.ac): Incoke gl_PREREQ_FTELLO. * lib/fseeko.c [_GL_WINDOWS_64_BIT_OFF_T]: Use _fseeki64 or fseeko64 instead of fseeko. * m4/fseeko.m4 (gl_FUNC_FSEEKO): Require gl_SYS_TYPES_H. Set REPLACE_FSEEKO if WINDOWS_64_BIT_OFF_T is 1. (gl_PREREQ_FSEEKO): New macro. * modules/fseeko (Depends-on): Add sys_types. (configure.ac): Invoke gl_PREREQ_FSEEKO. * lib/sys_stat.in.h: Add comments about off_t. (stat, fstat) [WINDOWS_64_BIT_ST_SIZE]: Define to variants that use a 64-bit integer for st_size in 'struct stat'. * m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Set WINDOWS_64_BIT_ST_SIZE. Define _GL_WINDOWS_64_BIT_ST_SIZE. * modules/sys_stat (Depends-on): Add sys_types. (Makefile.am): Substitute WINDOWS_64_BIT_ST_SIZE. * lib/stat.c (stat) [_GL_WINDOWS_64_BIT_ST_SIZE]: Define to _stati64 instead of stat or _stat. * lib/fstat.c [_GL_WINDOWS_64_BIT_ST_SIZE]: Use _fstati64 and 'struct _stati64' instead of fstat and 'struct stat'. * m4/fstat.m4 (gl_FUNC_FSTAT): Require gl_HEADER_SYS_STAT_H. Set REPLACE_FSTAT if WINDOWS_64_BIT_ST_SIZE is 1. Reported by Ray Satiro <raysatiro@yahoo.com>.
author Bruno Haible <bruno@clisp.org>
date Sat, 14 Apr 2012 23:27:45 +0200
parents 42a3333c10b6
children f15f29149749
files ChangeLog doc/posix-headers/sys_types.texi lib/fcntl.in.h lib/fseeko.c lib/fstat.c lib/ftello.c lib/ftruncate.c lib/lseek.c lib/stat.c lib/stdio.in.h lib/sys_stat.in.h lib/sys_types.in.h lib/unistd.in.h m4/fseeko.m4 m4/fstat.m4 m4/ftello.m4 m4/ftruncate.m4 m4/largefile.m4 m4/lseek.m4 m4/sys_stat_h.m4 m4/sys_types_h.m4 m4/unistd_h.m4 modules/fcntl-h modules/fseeko modules/ftello modules/ftruncate modules/largefile modules/lseek modules/stdio modules/sys_stat modules/sys_types modules/unistd
diffstat 32 files changed, 482 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,79 @@
+2012-04-21  Bruno Haible  <bruno@clisp.org>
+
+	Large File Support for native Windows platforms.
+
+	* m4/largefile.m4 (gl_LARGEFILE): New macro.
+	* modules/largefile (configure.ac): Require gl_LARGEFILE.
+
+	* lib/sys_types.in.h (off_t) [WINDOWS_64_BIT_OFF_T]: Define to a 64-bit
+	type.
+	* m4/sys_types_h.m4 (gl_SYS_TYPES_H): Set WINDOWS_64_BIT_OFF_T.
+	* modules/sys_types (Makefile.am): Substitute WINDOWS_64_BIT_OFF_T.
+	* doc/posix-headers/sys_types.texi: Mention the effect of the
+	'largefile' module.
+
+	* lib/fcntl.in.h: Add comments about off_t.
+	* modules/fcntl-h (Depends-on): Add sys_types.
+
+	* lib/unistd.in.h [WINDOWS_64_BIT_OFF_T]: Include <sys/types.h>.
+	(ftruncate): Replace it if REPLACE_FTRUNCATE is 1.
+	* m4/unistd_h.m4 (gl_UNISTD_H): Require gl_SYS_TYPES_H.
+	(gl_UNISTD_H_DEFAULTS): Initialize REPLACE_FTRUNCATE.
+	* modules/unistd (Depends-on): Add sys_types.
+	(Makefile.am): Substitute WINDOWS_64_BIT_OFF_T, REPLACE_FTRUNCATE.
+
+	* lib/lseek.c (rpl_lseek) [_GL_WINDOWS_64_BIT_OFF_T]: Use _lseeki64
+	instead of lseek.
+	* m4/lseek.m4 (gl_FUNC_LSEEK): Require gl_SYS_TYPES_H. Set
+	REPLACE_LSEEK if WINDOWS_64_BIT_OFF_T is 1.
+	* modules/lseek (Depends-on): Add sys_types.
+
+	* lib/ftruncate.c: Put under GPLv3+. Include <windows.h>,
+	msvc-nothrow.h.
+	(SetFileSize): New function.
+	(ftruncate) [_GL_WINDOWS_64_BIT_OFF_T]: New implementation.
+	* m4/ftruncate.m4 (gl_FUNC_FTRUNCATE): Set REPLACE_FTRUNCATE on Windows
+	if Large File Support is requested.
+	* modules/ftruncate (configure.ac): Consider REPLACE_FTRUNCATE.
+	(Depends-on): Add sys_types, msvc-nothrow. Update conditions.
+
+	* lib/stdio.in.h: Add comments about off_t.
+	* modules/stdio (Depends-on): Add sys_types.
+
+	* lib/ftello.c [_GL_WINDOWS_64_BIT_OFF_T]: Use _ftelli64 or ftello64
+	instead of ftello.
+	* m4/ftello.m4 (gl_FUNC_FTELLO): Require gl_SYS_TYPES_H. Set
+	REPLACE_FTELLO if WINDOWS_64_BIT_OFF_T is 1.
+	(gl_PREREQ_FTELLO): New macro.
+	* modules/ftello (Depends-on): Add sys_types.
+	(configure.ac): Incoke gl_PREREQ_FTELLO.
+
+	* lib/fseeko.c [_GL_WINDOWS_64_BIT_OFF_T]: Use _fseeki64 or fseeko64
+	instead of fseeko.
+	* m4/fseeko.m4 (gl_FUNC_FSEEKO): Require gl_SYS_TYPES_H. Set
+	REPLACE_FSEEKO if WINDOWS_64_BIT_OFF_T is 1.
+	(gl_PREREQ_FSEEKO): New macro.
+	* modules/fseeko (Depends-on): Add sys_types.
+	(configure.ac): Invoke gl_PREREQ_FSEEKO.
+
+	* lib/sys_stat.in.h: Add comments about off_t.
+	(stat, fstat) [WINDOWS_64_BIT_ST_SIZE]: Define to variants that use a
+	64-bit integer for st_size in 'struct stat'.
+	* m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Set WINDOWS_64_BIT_ST_SIZE.
+	Define _GL_WINDOWS_64_BIT_ST_SIZE.
+	* modules/sys_stat (Depends-on): Add sys_types.
+	(Makefile.am): Substitute WINDOWS_64_BIT_ST_SIZE.
+
+	* lib/stat.c (stat) [_GL_WINDOWS_64_BIT_ST_SIZE]: Define to _stati64
+	instead of stat or _stat.
+
+	* lib/fstat.c [_GL_WINDOWS_64_BIT_ST_SIZE]: Use _fstati64 and
+	'struct _stati64' instead of fstat and 'struct stat'.
+	* m4/fstat.m4 (gl_FUNC_FSTAT): Require gl_HEADER_SYS_STAT_H. Set
+	REPLACE_FSTAT if WINDOWS_64_BIT_ST_SIZE is 1.
+
+	Reported by Ray Satiro <raysatiro@yahoo.com>.
+
 2012-04-19  Eric Blake  <eblake@redhat.com>
 
 	bootstrap: accommodate older libtool
--- a/doc/posix-headers/sys_types.texi
+++ b/doc/posix-headers/sys_types.texi
@@ -27,5 +27,8 @@
 On some platforms the types @code{blksize_t} and @code{suseconds_t}
 are signed integer types that are wider than @code{long}:
 glibc x32
+@end itemize
 
-@end itemize
+This module, together with the module @code{largefile}, also defines the type
+@code{off_t} to a 64-bit integer type on some platforms:
+mingw (except mingw64), MSVC 9.
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -25,6 +25,8 @@
 #if defined __need_system_fcntl_h
 /* Special invocation convention.  */
 
+/* Needed before <sys/stat.h>.
+   May also define off_t to a 64-bit type on native Windows.  */
 #include <sys/types.h>
 /* On some systems other than glibc, <sys/stat.h> is a prerequisite of
    <fcntl.h>.  On glibc systems, we would like to avoid namespace pollution.
@@ -42,6 +44,8 @@
 
 #ifndef _@GUARD_PREFIX@_FCNTL_H
 
+/* Needed before <sys/stat.h>.
+   May also define off_t to a 64-bit type on native Windows.  */
 #include <sys/types.h>
 /* On some systems other than glibc, <sys/stat.h> is a prerequisite of
    <fcntl.h>.  On glibc systems, we would like to avoid namespace pollution.
--- a/lib/fseeko.c
+++ b/lib/fseeko.c
@@ -31,6 +31,14 @@
 # undef fseek
 # define fseeko fseek
 #endif
+#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.  */
--- a/lib/fstat.c
+++ b/lib/fstat.c
@@ -23,6 +23,10 @@
 /* Get the original definition of fstat.  It might be defined as a macro.  */
 #include <sys/types.h>
 #include <sys/stat.h>
+#if _GL_WINDOWS_64_BIT_ST_SIZE
+# define stat _stati64
+# define fstat _fstati64
+#endif
 #undef __need_system_sys_stat_h
 
 static inline int
--- a/lib/ftello.c
+++ b/lib/ftello.c
@@ -31,6 +31,14 @@
 # undef ftell
 # define ftello ftell
 #endif
+#if _GL_WINDOWS_64_BIT_OFF_T
+# undef ftello
+# if HAVE__FTELLI64 /* msvc, mingw64 */
+#  define ftello _ftelli64
+# else /* mingw */
+#  define ftello ftello64
+# endif
+#endif
 {
 #if LSEEK_PIPE_BROKEN
   /* mingw gives bogus answers rather than failure on non-seekable files.  */
--- a/lib/ftruncate.c
+++ b/lib/ftruncate.c
@@ -1,5 +1,18 @@
 /* ftruncate emulations for native Windows.
-   This file is in the public domain.  */
+   Copyright (C) 1992-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
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   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, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
@@ -7,12 +20,143 @@
 #include <unistd.h>
 
 #if HAVE_CHSIZE
+/* A native Windows platform.  */
 
 # include <errno.h>
-# include <io.h>
+
+# if _GL_WINDOWS_64_BIT_OFF_T
+
+/* Large File Support: off_t is 64-bit, but chsize() takes only a 32-bit
+   argument.  So, define a 64-bit safe SetFileSize function ourselves.  */
+
+/* Ensure that <windows.h> declares GetFileSizeEx.  */
+#  undef _WIN32_WINNT
+#  define _WIN32_WINNT 0x500
+
+/* Get declarations of the native Windows API functions.  */
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+
+/* Get _get_osfhandle.  */
+#  include "msvc-nothrow.h"
+
+static BOOL
+SetFileSize (HANDLE h, LONGLONG size)
+{
+  LARGE_INTEGER old_size;
+
+  if (!GetFileSizeEx (h, &old_size))
+    return FALSE;
+
+  if (size != old_size.QuadPart)
+    {
+      /* Duplicate the handle, so we are free to modify its file position.  */
+      HANDLE curr_process = GetCurrentProcess ();
+      HANDLE tmph;
+
+      if (!DuplicateHandle (curr_process,           /* SourceProcessHandle */
+                            h,                      /* SourceHandle */
+                            curr_process,           /* TargetProcessHandle */
+                            (PHANDLE) &tmph,        /* TargetHandle */
+                            (DWORD) 0,              /* DesiredAccess */
+                            FALSE,                  /* InheritHandle */
+                            DUPLICATE_SAME_ACCESS)) /* Options */
+        return FALSE;
 
-# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
-#  include "msvc-inval.h"
+      if (size < old_size.QuadPart)
+        {
+          /* Reduce the size.  */
+          LONG size_hi = (LONG) (size >> 32);
+          if (SetFilePointer (tmph, (LONG) size, &size_hi, FILE_BEGIN)
+              == INVALID_SET_FILE_POINTER
+              && GetLastError() != NO_ERROR)
+            {
+              CloseHandle (tmph);
+              return FALSE;
+            }
+          if (!SetEndOfFile (tmph))
+            {
+              CloseHandle (tmph);
+              return FALSE;
+            }
+        }
+      else
+        {
+          /* Increase the size by adding zero bytes at the end.  */
+          static char zero_bytes[1024];
+          LONG pos_hi = 0;
+          LONG pos_lo = SetFilePointer (tmph, (LONG) 0, &pos_hi, FILE_END);
+          LONGLONG pos;
+          if (pos_lo == INVALID_SET_FILE_POINTER
+              && GetLastError() != NO_ERROR)
+            {
+              CloseHandle (tmph);
+              return FALSE;
+            }
+          pos = ((LONGLONG) pos_hi << 32) | (ULONGLONG) (ULONG) pos_lo;
+          while (pos < size)
+            {
+              DWORD written;
+              LONGLONG count = size - pos;
+              if (count > sizeof (zero_bytes))
+                count = sizeof (zero_bytes);
+              if (!WriteFile (tmph, zero_bytes, (DWORD) count, &written, NULL)
+                  || written == 0)
+                {
+                  CloseHandle (tmph);
+                  return FALSE;
+                }
+              pos += (ULONGLONG) (ULONG) written;
+            }
+        }
+      /* Close the handle.  */
+      CloseHandle (tmph);
+    }
+  return TRUE;
+}
+
+int
+ftruncate (int fd, off_t length)
+{
+  HANDLE handle = (HANDLE) _get_osfhandle (fd);
+
+  if (handle == INVALID_HANDLE_VALUE)
+    {
+      errno = EBADF;
+      return -1;
+    }
+  if (length < 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+  if (!SetFileSize (handle, length))
+    {
+      switch (GetLastError ())
+        {
+        case ERROR_ACCESS_DENIED:
+          errno = EACCES;
+          break;
+        case ERROR_HANDLE_DISK_FULL:
+        case ERROR_DISK_FULL:
+        case ERROR_DISK_TOO_FRAGMENTED:
+          errno = ENOSPC;
+          break;
+        default:
+          errno = EIO;
+          break;
+        }
+      return -1;
+    }
+  return 0;
+}
+
+# else
+
+#  include <io.h>
+
+#  if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+#   include "msvc-inval.h"
 static inline int
 chsize_nothrow (int fd, long length)
 {
@@ -31,8 +175,8 @@
 
   return result;
 }
-#  define chsize chsize_nothrow
-# endif
+#   define chsize chsize_nothrow
+#  endif
 
 int
 ftruncate (int fd, off_t length)
@@ -40,4 +184,5 @@
   return chsize (fd, length);
 }
 
+# endif
 #endif
--- a/lib/lseek.c
+++ b/lib/lseek.c
@@ -59,5 +59,9 @@
       return -1;
     }
 #endif
+#if _GL_WINDOWS_64_BIT_OFF_T
+  return _lseeki64 (fd, offset, whence);
+#else
   return lseek (fd, offset, whence);
+#endif
 }
--- a/lib/stat.c
+++ b/lib/stat.c
@@ -27,13 +27,18 @@
 #include <sys/stat.h>
 #undef __need_system_sys_stat_h
 
-#if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
-    && REPLACE_FUNC_STAT_FILE
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if _GL_WINDOWS_64_BIT_ST_SIZE
+#  define stat _stati64
+#  define REPLACE_FUNC_STAT_DIR 1
+#  undef REPLACE_FUNC_STAT_FILE
+# elif REPLACE_FUNC_STAT_FILE
 /* mingw64 has a broken stat() function, based on _stat(), in libmingwex.a.
    Bypass it.  */
-# define stat _stat
-# define REPLACE_FUNC_STAT_DIR 1
-# undef REPLACE_FUNC_STAT_FILE
+#  define stat _stat
+#  define REPLACE_FUNC_STAT_DIR 1
+#  undef REPLACE_FUNC_STAT_FILE
+# endif
 #endif
 
 static inline int
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -52,7 +52,8 @@
 #include <stddef.h>
 
 /* Get off_t and ssize_t.  Needed on many systems, including glibc 2.8
-   and eglibc 2.11.2.  */
+   and eglibc 2.11.2.
+   May also define off_t to a 64-bit type on native Windows.  */
 #include <sys/types.h>
 
 /* The __attribute__ feature is available in gcc versions 2.5 and later.
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -35,7 +35,8 @@
 
 #ifndef _@GUARD_PREFIX@_SYS_STAT_H
 
-/* Get nlink_t.  */
+/* Get nlink_t.
+   May also define off_t to a 64-bit type on native Windows.  */
 #include <sys/types.h>
 
 /* Get struct timespec.  */
@@ -66,6 +67,11 @@
 # include <io.h>
 #endif
 
+/* Large File Support on native Windows.  */
+#if @WINDOWS_64_BIT_ST_SIZE@
+# define stat _stati64
+#endif
+
 #ifndef S_IFIFO
 # ifdef _S_IFIFO
 #  define S_IFIFO _S_IFIFO
@@ -335,6 +341,9 @@
 _GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf));
 # endif
 _GL_CXXALIASWARN (fstat);
+#elif @WINDOWS_64_BIT_ST_SIZE@
+/* Above, we define stat to _stati64.  */
+# define fstat _fstati64
 #elif defined GNULIB_POSIXCHECK
 # undef fstat
 # if HAVE_RAW_DECL_FSTAT
@@ -620,6 +629,28 @@
        so we have to replace stat64() instead of stat(). */
 #   undef stat64
 #   define stat64(name, st) rpl_stat (name, st)
+#  elif @WINDOWS_64_BIT_ST_SIZE@
+    /* Above, we define stat to _stati64.  */
+#   if defined __MINGW32__ && defined _stati64
+#    ifndef _USE_32BIT_TIME_T
+      /* The system headers define _stati64 to _stat64.  */
+#     undef _stat64
+#     define _stat64(name, st) rpl_stat (name, st)
+#    endif
+#   elif defined _MSC_VER && defined _stati64
+#    ifdef _USE_32BIT_TIME_T
+      /* The system headers define _stati64 to _stat32i64.  */
+#     undef _stat32i64
+#     define _stat32i64(name, st) rpl_stat (name, st)
+#    else
+      /* The system headers define _stati64 to _stat64.  */
+#     undef _stat64
+#     define _stat64(name, st) rpl_stat (name, st)
+#    endif
+#   else
+#    undef _stati64
+#    define _stati64(name, st) rpl_stat (name, st)
+#   endif
 #  elif defined __MINGW32__ && defined stat
 #   ifdef _USE_32BIT_TIME_T
      /* The system headers define stat to _stat32i64.  */
--- a/lib/sys_types.in.h
+++ b/lib/sys_types.in.h
@@ -28,6 +28,18 @@
 #ifndef _@GUARD_PREFIX@_SYS_TYPES_H
 #define _@GUARD_PREFIX@_SYS_TYPES_H
 
+/* Override off_t if Large File Support is requested on native Windows.  */
+#if @WINDOWS_64_BIT_OFF_T@
+/* Same as int64_t in <stdint.h>.  */
+# if defined _MSC_VER
+#  define off_t __int64
+# else
+#  define off_t long long int
+# endif
+/* Indicator, for gnulib internal purposes.  */
+# define _GL_WINDOWS_64_BIT_OFF_T 1
+#endif
+
 /* MSVC 9 defines size_t in <stddef.h>, not in <sys/types.h>.  */
 /* But avoid namespace pollution on glibc systems.  */
 #if ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) \
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -107,8 +107,9 @@
 # include <netdb.h>
 #endif
 
-/* MSVC defines off_t in <sys/types.h>.  */
-#if !@HAVE_UNISTD_H@
+/* MSVC defines off_t in <sys/types.h>.
+   May also define off_t to a 64-bit type on native Windows.  */
+#if !@HAVE_UNISTD_H@ || @WINDOWS_64_BIT_OFF_T@
 /* Get off_t.  */
 # include <sys/types.h>
 #endif
@@ -562,10 +563,19 @@
    Return 0 if successful, otherwise -1 and errno set.
    See the POSIX:2008 specification
    <http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html>.  */
-# if !@HAVE_FTRUNCATE@
+# if @REPLACE_FTRUNCATE@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef ftruncate
+#   define ftruncate rpl_ftruncate
+#  endif
+_GL_FUNCDECL_RPL (ftruncate, int, (int fd, off_t length));
+_GL_CXXALIAS_RPL (ftruncate, int, (int fd, off_t length));
+# else
+#  if !@HAVE_FTRUNCATE@
 _GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length));
+#  endif
+_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length));
 # endif
-_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length));
 _GL_CXXALIASWARN (ftruncate);
 #elif defined GNULIB_POSIXCHECK
 # undef ftruncate
--- a/m4/fseeko.m4
+++ b/m4/fseeko.m4
@@ -1,4 +1,4 @@
-# fseeko.m4 serial 15
+# fseeko.m4 serial 16
 dnl Copyright (C) 2007-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,6 +8,7 @@
 [
   AC_REQUIRE([gl_STDIO_H_DEFAULTS])
   AC_REQUIRE([gl_STDIN_LARGE_OFFSET])
+  AC_REQUIRE([gl_SYS_TYPES_H])
   AC_REQUIRE([AC_PROG_CC])
 
   dnl Persuade glibc <stdio.h> to declare fseeko().
@@ -28,6 +29,9 @@
   if test $gl_cv_func_fseeko = no; then
     HAVE_FSEEKO=0
   else
+    if test $WINDOWS_64_BIT_OFF_T = 1; then
+      REPLACE_FSEEKO=1
+    fi
     if test $gl_cv_var_stdin_large_offset = no; then
       REPLACE_FSEEKO=1
     fi
@@ -59,3 +63,11 @@
         [gl_cv_var_stdin_large_offset=yes],
         [gl_cv_var_stdin_large_offset=no])])
 ])
+
+# Prerequisites of lib/fseeko.c.
+AC_DEFUN([gl_PREREQ_FSEEKO],
+[
+  dnl Native Windows has the function _fseeki64. mingw hides it, but mingw64
+  dnl makes it usable again.
+  AC_CHECK_FUNCS([_fseeki64])
+])
--- a/m4/fstat.m4
+++ b/m4/fstat.m4
@@ -1,4 +1,4 @@
-# fstat.m4 serial 1
+# fstat.m4 serial 2
 dnl Copyright (C) 2011-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,10 +7,17 @@
 AC_DEFUN([gl_FUNC_FSTAT],
 [
   AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+
   AC_REQUIRE([gl_MSVC_INVAL])
   if test $HAVE_MSVC_INVALID_PARAMETER_HANDLER = 1; then
     REPLACE_FSTAT=1
   fi
+
+  AC_REQUIRE([gl_HEADER_SYS_STAT_H])
+  if test $WINDOWS_64_BIT_ST_SIZE = 1; then
+    REPLACE_FSTAT=1
+  fi
+
   dnl Replace fstat() for supporting the gnulib-defined open() on directories.
   m4_ifdef([gl_FUNC_FCHDIR], [
     gl_TEST_FCHDIR
--- a/m4/ftello.m4
+++ b/m4/ftello.m4
@@ -1,4 +1,4 @@
-# ftello.m4 serial 10
+# ftello.m4 serial 11
 dnl Copyright (C) 2007-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -9,6 +9,7 @@
   AC_REQUIRE([gl_STDIO_H_DEFAULTS])
   AC_REQUIRE([AC_PROG_CC])
   AC_REQUIRE([gl_STDIN_LARGE_OFFSET])
+  AC_REQUIRE([gl_SYS_TYPES_H])
 
   dnl Persuade glibc <stdio.h> to declare ftello().
   AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
@@ -30,9 +31,13 @@
   if test $gl_cv_func_ftello = no; then
     HAVE_FTELLO=0
   else
+    if test $WINDOWS_64_BIT_OFF_T = 1; then
+      REPLACE_FTELLO=1
+    fi
     if test $gl_cv_var_stdin_large_offset = no; then
       REPLACE_FTELLO=1
-    else
+    fi
+    if test $REPLACE_FTELLO = 0; then
       dnl Detect bug on Solaris.
       dnl ftell and ftello produce incorrect results after putc that followed a
       dnl getc call that reached EOF on Solaris. This is because the _IOREAD
@@ -125,3 +130,11 @@
     fi
   fi
 ])
+
+# Prerequisites of lib/ftello.c.
+AC_DEFUN([gl_PREREQ_FTELLO],
+[
+  dnl Native Windows has the function _ftelli64. mingw hides it, but mingw64
+  dnl makes it usable again.
+  AC_CHECK_FUNCS([_ftelli64])
+])
--- a/m4/ftruncate.m4
+++ b/m4/ftruncate.m4
@@ -1,4 +1,4 @@
-# serial 18
+# serial 19
 
 # See if we need to emulate a missing ftruncate function using chsize.
 
@@ -11,7 +11,24 @@
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
   AC_CHECK_FUNCS_ONCE([ftruncate])
-  if test $ac_cv_func_ftruncate = no; then
+  if test $ac_cv_func_ftruncate = yes; then
+    m4_ifdef([gl_LARGEFILE], [
+      AC_REQUIRE([AC_CANONICAL_HOST])
+      case "$host_os" in
+        mingw*)
+          dnl Native Windows, and Large File Support is requested.
+          dnl The MSVCRT _chsize() function only accepts a 32-bit file size,
+          dnl and the mingw64 ftruncate64() function is unreliable (it may
+          dnl delete the file, see
+          dnl <http://mingw-w64.sourcearchive.com/documentation/2.0-1/ftruncate64_8c_source.html>).
+          dnl Use gnulib's ftruncate() implementation instead.
+          REPLACE_FTRUNCATE=1
+          ;;
+      esac
+    ], [
+      :
+    ])
+  else
     HAVE_FTRUNCATE=0
   fi
 ])
--- a/m4/largefile.m4
+++ b/m4/largefile.m4
@@ -102,3 +102,48 @@
 ])# AC_SYS_LARGEFILE
 
 ])# m4_version_prereq 2.69
+
+# Enable large files on systems where this is implemented by Gnulib, not by the
+# system headers.
+# Set the variables WINDOWS_64_BIT_OFF_T, WINDOWS_64_BIT_ST_SIZE if Gnulib
+# overrides ensure that off_t or 'struct size.st_size' are 64-bit, respectively.
+AC_DEFUN([gl_LARGEFILE],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  case "$host_os" in
+    mingw*)
+      dnl Native Windows.
+      dnl mingw64 defines off_t to a 64-bit type already, if
+      dnl _FILE_OFFSET_BITS=64, which is ensured by AC_SYS_LARGEFILE.
+      AC_CACHE_CHECK([for 64-bit off_t], [gl_cv_type_off_t_64],
+        [AC_COMPILE_IFELSE(
+           [AC_LANG_PROGRAM(
+              [[#include <sys/types.h>
+                int verify_off_t_size[sizeof (off_t) >= 8 ? 1 : -1];
+              ]],
+              [[]])],
+           [gl_cv_type_off_t_64=yes], [gl_cv_type_off_t_64=no])
+        ])
+      if test $gl_cv_type_off_t_64 = no; then
+        WINDOWS_64_BIT_OFF_T=1
+      else
+        WINDOWS_64_BIT_OFF_T=0
+      fi
+      dnl But all native Windows platforms (including mingw64) have a 32-bit
+      dnl st_size member in 'struct stat'.
+      WINDOWS_64_BIT_ST_SIZE=1
+      ;;
+    *)
+      dnl Nothing to do on gnulib's side.
+      dnl A 64-bit off_t is
+      dnl   - already the default on MacOS X, FreeBSD, NetBSD, OpenBSD, IRIX,
+      dnl     OSF/1, Cygwin,
+      dnl   - enabled by _FILE_OFFSET_BITS=64 (ensured by AC_SYS_LARGEFILE) on
+      dnl     glibc, HP-UX, Solaris,
+      dnl   - enabled by _LARGE_FILES=1 (ensured by AC_SYS_LARGEFILE) on AIX,
+      dnl   - impossible to achieve on Minix 3.1.8.
+      WINDOWS_64_BIT_OFF_T=0
+      WINDOWS_64_BIT_ST_SIZE=0
+      ;;
+  esac
+])
--- a/m4/lseek.m4
+++ b/m4/lseek.m4
@@ -1,4 +1,4 @@
-# lseek.m4 serial 9
+# lseek.m4 serial 10
 dnl Copyright (C) 2007, 2009-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,6 +7,7 @@
 AC_DEFUN([gl_FUNC_LSEEK],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+
   AC_REQUIRE([AC_CANONICAL_HOST])
   AC_REQUIRE([AC_PROG_CC])
   AC_CHECK_HEADERS_ONCE([unistd.h])
@@ -62,4 +63,9 @@
     AC_DEFINE([LSEEK_PIPE_BROKEN], [1],
       [Define to 1 if lseek does not detect pipes.])
   fi
+
+  AC_REQUIRE([gl_SYS_TYPES_H])
+  if test $WINDOWS_64_BIT_OFF_T = 1; then
+    REPLACE_LSEEK=1
+  fi
 ])
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,4 +1,4 @@
-# sys_stat_h.m4 serial 26   -*- Autoconf -*-
+# sys_stat_h.m4 serial 27   -*- Autoconf -*-
 dnl Copyright (C) 2006-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -22,6 +22,19 @@
   dnl Ensure the type mode_t gets defined.
   AC_REQUIRE([AC_TYPE_MODE_T])
 
+  dnl Whether to override 'struct stat'.
+  m4_ifdef([gl_LARGEFILE], [
+    AC_REQUIRE([gl_LARGEFILE])
+  ], [
+    WINDOWS_64_BIT_ST_SIZE=0
+  ])
+  AC_SUBST([WINDOWS_64_BIT_ST_SIZE])
+  if test $WINDOWS_64_BIT_ST_SIZE = 1; then
+    AC_DEFINE([_GL_WINDOWS_64_BIT_ST_SIZE], [1],
+      [Define to 1 if Gnulib overrides 'struct stat' on Windows so that
+       struct stat.st_size becomes 64-bit.])
+  fi
+
   dnl Define types that are supposed to be defined in <sys/types.h> or
   dnl <sys/stat.h>.
   AC_CHECK_TYPE([nlink_t], [],
--- a/m4/sys_types_h.m4
+++ b/m4/sys_types_h.m4
@@ -1,4 +1,4 @@
-# sys_types_h.m4 serial 2
+# sys_types_h.m4 serial 3
 dnl Copyright (C) 2011-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -14,6 +14,14 @@
 
   dnl Ensure the type mode_t gets defined.
   AC_REQUIRE([AC_TYPE_MODE_T])
+
+  dnl Whether to override the 'off_t' type.
+  m4_ifdef([gl_LARGEFILE], [
+    AC_REQUIRE([gl_LARGEFILE])
+  ], [
+    WINDOWS_64_BIT_OFF_T=0
+  ])
+  AC_SUBST([WINDOWS_64_BIT_OFF_T])
 ])
 
 AC_DEFUN([gl_SYS_TYPES_H_DEFAULTS],
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 63
+# unistd_h.m4 serial 64
 dnl Copyright (C) 2006-2012 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,6 +24,9 @@
   dnl Ensure the type pid_t gets defined.
   AC_REQUIRE([AC_TYPE_PID_T])
 
+  dnl Determine WINDOWS_64_BIT_OFF_T.
+  AC_REQUIRE([gl_SYS_TYPES_H])
+
   dnl Check for declarations of anything we want to poison if the
   dnl corresponding gnulib module is not in use.
   gl_WARN_ON_USE_PREPARE([[
@@ -155,6 +158,7 @@
   REPLACE_DUP=0;          AC_SUBST([REPLACE_DUP])
   REPLACE_DUP2=0;         AC_SUBST([REPLACE_DUP2])
   REPLACE_FCHOWNAT=0;     AC_SUBST([REPLACE_FCHOWNAT])
+  REPLACE_FTRUNCATE=0;    AC_SUBST([REPLACE_FTRUNCATE])
   REPLACE_GETCWD=0;       AC_SUBST([REPLACE_GETCWD])
   REPLACE_GETDOMAINNAME=0; AC_SUBST([REPLACE_GETDOMAINNAME])
   REPLACE_GETLOGIN_R=0;   AC_SUBST([REPLACE_GETLOGIN_R])
--- a/modules/fcntl-h
+++ b/modules/fcntl-h
@@ -12,6 +12,7 @@
 snippet/arg-nonnull
 snippet/c++defs
 snippet/warn-on-use
+sys_types
 unistd
 
 configure.ac:
--- a/modules/fseeko
+++ b/modules/fseeko
@@ -11,6 +11,7 @@
 largefile
 lseek
 stdio
+sys_types
 # Just to guarantee consistency between fseek() and fseeko().
 fseek
 
@@ -21,6 +22,7 @@
 gl_FUNC_FSEEKO
 if test $HAVE_FSEEKO = 0 || test $REPLACE_FSEEKO = 1; then
   AC_LIBOBJ([fseeko])
+  gl_PREREQ_FSEEKO
 fi
 gl_STDIO_MODULE_INDICATOR([fseeko])
 
--- a/modules/ftello
+++ b/modules/ftello
@@ -11,6 +11,7 @@
 stdio
 extensions
 largefile
+sys_types
 lseek           [test $HAVE_FTELLO = 0 || test $REPLACE_FTELLO = 1]
 # Just to guarantee consistency between ftell() and ftello().
 ftell
@@ -22,6 +23,7 @@
 gl_FUNC_FTELLO
 if test $HAVE_FTELLO = 0 || test $REPLACE_FTELLO = 1; then
   AC_LIBOBJ([ftello])
+  gl_PREREQ_FTELLO
 fi
 gl_STDIO_MODULE_INDICATOR([ftello])
 
--- a/modules/ftruncate
+++ b/modules/ftruncate
@@ -7,12 +7,14 @@
 
 Depends-on:
 unistd
+sys_types
 largefile
-msvc-inval      [test $HAVE_FTRUNCATE = 0]
+msvc-nothrow    [test $HAVE_FTRUNCATE = 0 || test $REPLACE_FTRUNCATE = 1]
+msvc-inval      [test $HAVE_FTRUNCATE = 0 || test $REPLACE_FTRUNCATE = 1]
 
 configure.ac:
 gl_FUNC_FTRUNCATE
-if test $HAVE_FTRUNCATE = 0; then
+if test $HAVE_FTRUNCATE = 0 || test $REPLACE_FTRUNCATE = 1; then
   AC_LIBOBJ([ftruncate])
   gl_PREREQ_FTRUNCATE
 fi
--- a/modules/largefile
+++ b/modules/largefile
@@ -10,6 +10,7 @@
 AC_REQUIRE([AC_SYS_LARGEFILE])
 
 configure.ac:
+AC_REQUIRE([gl_LARGEFILE])
 
 Makefile.am:
 
--- a/modules/lseek
+++ b/modules/lseek
@@ -7,6 +7,7 @@
 
 Depends-on:
 unistd
+sys_types
 largefile
 msvc-nothrow    [test $REPLACE_LSEEK = 1]
 fstat           [test $REPLACE_LSEEK = 1]
--- a/modules/stdio
+++ b/modules/stdio
@@ -12,6 +12,7 @@
 snippet/warn-on-use
 ssize_t
 stddef
+sys_types
 
 configure.ac:
 gl_STDIO_H
--- a/modules/sys_stat
+++ b/modules/sys_stat
@@ -11,6 +11,7 @@
 snippet/arg-nonnull
 snippet/c++defs
 snippet/warn-on-use
+sys_types
 time
 
 configure.ac:
@@ -31,6 +32,7 @@
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \
 	      -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \
 	      -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
 	      -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
--- a/modules/sys_types
+++ b/modules/sys_types
@@ -27,6 +27,7 @@
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_SYS_TYPES_H''@|$(NEXT_SYS_TYPES_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
 	      < $(srcdir)/sys_types.in.h; \
 	} > $@-t && \
 	mv $@-t $@
--- a/modules/unistd
+++ b/modules/unistd
@@ -12,6 +12,7 @@
 snippet/warn-on-use
 ssize_t
 stddef
+sys_types
 
 configure.ac:
 gl_UNISTD_H
@@ -30,6 +31,7 @@
 	      -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \
+	      -e 's|@''WINDOWS_64_BIT_OFF_T''@|$(WINDOWS_64_BIT_OFF_T)|g' \
 	      -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \
 	      -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \
 	      -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \
@@ -128,6 +130,7 @@
 	      -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \
 	      -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \
 	      -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \
+	      -e 's|@''REPLACE_FTRUNCATE''@|$(REPLACE_FTRUNCATE)|g' \
 	      -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \
 	      -e 's|@''REPLACE_GETDOMAINNAME''@|$(REPLACE_GETDOMAINNAME)|g' \
 	      -e 's|@''REPLACE_GETLOGIN_R''@|$(REPLACE_GETLOGIN_R)|g' \