* m4/windows-stat-inodes.m4: New file.
* m4/sys_types_h.m4 (gl_SYS_TYPES_H): Set WINDOWS_STAT_INODES.
* modules/sys_types (Makefile.am): Substitute WINDOWS_STAT_INODES.
* lib/sys_types.in.h [WINDOWS_STAT_INODES]: Override dev_t and ino_t.
(_GL_WINDOWS_STAT_INODES): New macro.
* lib/stat-w32.c: Set _WIN32_WINNT. Include <string.h>, verify.h.
(GetFileInformationByHandleExFunc): New variable.
(initialize): Initialize it.
(_gl_fstat_by_handle) [_GL_WINDOWS_STAT_INODES]: Initialize st_dev and
st_ino appropriately.
* lib/stat.c (rpl_stat): Use the directory entry based approach only as
a fallback, because it does not provide st_dev and st_ino values.
* modules/fstat (Depends-on): Add 'verify'.
* modules/windows-stat-inodes: New file.
* doc/windows-stat-inodes.texi: New file.
* doc/gnulib.texi: Include it.
* doc/posix-headers/sys_stat.texi: Mention the new module.
+2017-05-14 Bruno Haible <bruno@clisp.org>
+
+ windows-stat-inodes: New module.
+ * m4/windows-stat-inodes.m4: New file.
+ * m4/sys_types_h.m4 (gl_SYS_TYPES_H): Set WINDOWS_STAT_INODES.
+ * modules/sys_types (Makefile.am): Substitute WINDOWS_STAT_INODES.
+ * lib/sys_types.in.h [WINDOWS_STAT_INODES]: Override dev_t and ino_t.
+ (_GL_WINDOWS_STAT_INODES): New macro.
+ * lib/stat-w32.c: Set _WIN32_WINNT. Include <string.h>, verify.h.
+ (GetFileInformationByHandleExFunc): New variable.
+ (initialize): Initialize it.
+ (_gl_fstat_by_handle) [_GL_WINDOWS_STAT_INODES]: Initialize st_dev and
+ st_ino appropriately.
+ * lib/stat.c (rpl_stat): Use the directory entry based approach only as
+ a fallback, because it does not provide st_dev and st_ino values.
+ * modules/fstat (Depends-on): Add 'verify'.
+ * modules/windows-stat-inodes: New file.
+ * doc/windows-stat-inodes.texi: New file.
+ * doc/gnulib.texi: Include it.
+ * doc/posix-headers/sys_stat.texi: Mention the new module.
+
2017-05-14 Bruno Haible <bruno@clisp.org>
stat-time tests: Workaround for native Windows.
@menu
* Libtool and Windows::
* Large File Support::
+* Inode numbers on Windows::
* Precise file timestamps on Windows::
* Avoiding the year 2038 problem::
* Windows sockets::
@include largefile.texi
+@include windows-stat-inodes.texi
+
@include windows-stat-timespec.texi
@include year2038.texi
Gnulib module: sys_stat
-Portability problems fixed by Gnulib:
+Portability problems fixed by Gnulib module @code{sys_stat}:
@itemize
@item
The type @code{mode_t} is not defined on some platforms:
@samp{stat-time} for accessors to portably get at subsecond resolution.
@end itemize
+Portability problems fixed by Gnulib module @code{sys_stat}, together with module @code{windows-stat-inodes}:
+@itemize
+@item
+On Windows platforms (excluding Cygwin), @code{st_ino} is always 0.
+@end itemize
+
Portability problems not fixed by Gnulib:
@itemize
@item
The macro @code{S_IFBLK} is missing on some platforms:
MSVC 9.
@item
-On Windows platforms (excluding Cygwin), @code{st_ino} is always 0.
-@item
On OpenVMS, @code{st_ino} is an array of three @code{ino_t} values,
not a single value.
@item
--- /dev/null
+@node Inode numbers on Windows
+@section Inode numbers on Windows
+
+The module @samp{windows-stat-inodes} ensures that,
+on native Windows platforms, @code{struct stat} contains
+@code{st_dev}, @code{st_ino} fields that are able to distinguish
+different inodes.
+
+Note: Such values can only be provided for most files on the
+file system. For a few files (such as inaccessible files),
+@code{st_dev} and @code{st_ino} are set to 0. Therefore,
+you should test whether @code{st_dev != 0 && st_ino != 0},
+before going to make inferences based on the file identity
+based on @code{st_dev} and @code{st_ino}.
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+/* Ensure that <windows.h> defines FILE_ID_INFO. */
+#undef _WIN32_WINNT
+#define _WIN32_WINNT _WIN32_WINNT_WIN8
+
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
+#include <string.h>
#include <unistd.h>
#include <windows.h>
#include "stat-w32.h"
#include "pathmax.h"
+#include "verify.h"
+#if _GL_WINDOWS_STAT_INODES == 2
+/* GetFileInformationByHandleEx was introduced only in Windows Vista. */
+typedef DWORD (WINAPI * GetFileInformationByHandleExFuncType) (HANDLE hFile,
+ FILE_INFO_BY_HANDLE_CLASS fiClass,
+ LPVOID lpBuffer,
+ DWORD dwBufferSize);
+static GetFileInformationByHandleExFuncType GetFileInformationByHandleExFunc = NULL;
+#endif
/* GetFinalPathNameByHandle was introduced only in Windows Vista. */
typedef DWORD (WINAPI * GetFinalPathNameByHandleFuncType) (HANDLE hFile,
LPTSTR lpFilePath,
HMODULE kernel32 = LoadLibrary ("kernel32.dll");
if (kernel32 != NULL)
{
+#if _GL_WINDOWS_STAT_INODES == 2
+ GetFileInformationByHandleExFunc =
+ (GetFileInformationByHandleExFuncType) GetProcAddress (kernel32, "GetFileInformationByHandleEx");
+#endif
GetFinalPathNameByHandleFunc =
- (GetFinalPathNameByHandleFuncType) GetProcAddress (kernel32, "GetFinalPathNameByHandleA");
+ (GetFinalPathNameByHandleFuncType) GetProcAddress (kernel32, "GetFinalPathNameByHandleA");
}
initialized = TRUE;
}
return -1;
}
+#if _GL_WINDOWS_STAT_INODES
+ /* st_ino can be determined through
+ GetFileInformationByHandle
+ <https://msdn.microsoft.com/en-us/library/aa364952.aspx>
+ <https://msdn.microsoft.com/en-us/library/aa363788.aspx>
+ as 64 bits, or through
+ GetFileInformationByHandleEx with argument FileIdInfo
+ <https://msdn.microsoft.com/en-us/library/aa364953.aspx>
+ <https://msdn.microsoft.com/en-us/library/hh802691.aspx>
+ as 128 bits.
+ The latter requires -D_WIN32_WINNT=_WIN32_WINNT_WIN8 or higher. */
+ /* Experiments show that GetFileInformationByHandleEx does not provide
+ much more information than GetFileInformationByHandle:
+ * The dwVolumeSerialNumber from GetFileInformationByHandle is equal
+ to the low 32 bits of the 64-bit VolumeSerialNumber from
+ GetFileInformationByHandleEx, and is apparently sufficient for
+ identifying the device.
+ * The nFileIndex from GetFileInformationByHandle is equal to the low
+ 64 bits of the 128-bit FileId from GetFileInformationByHandleEx,
+ and the high 64 bits of this 128-bit FileId are zero.
+ * On a FAT file system, GetFileInformationByHandleEx fails with error
+ ERROR_INVALID_PARAMETER, whereas GetFileInformationByHandle
+ succeeds.
+ * On a CIFS/SMB file system, GetFileInformationByHandleEx fails with
+ error ERROR_INVALID_LEVEL, whereas GetFileInformationByHandle
+ succeeds. */
+# if _GL_WINDOWS_STAT_INODES == 2
+ if (GetFileInformationByHandleExFunc != NULL)
+ {
+ FILE_ID_INFO id;
+ if (GetFileInformationByHandleExFunc (h, FileIdInfo, &id, sizeof (id)))
+ {
+ buf->st_dev = id.VolumeSerialNumber;
+ verify (sizeof (ino_t) == sizeof (id.FileId));
+ memcpy (&buf->st_ino, &id.FileId, sizeof (ino_t));
+ goto ino_done;
+ }
+ else
+ {
+ switch (GetLastError ())
+ {
+ case ERROR_INVALID_PARAMETER: /* older Windows version, or FAT */
+ case ERROR_INVALID_LEVEL: /* CIFS/SMB file system */
+ goto fallback;
+ default:
+ goto failed;
+ }
+ }
+ }
+ fallback: ;
+ /* Fallback for older Windows versions. */
+ buf->st_dev = info.dwVolumeSerialNumber;
+ buf->st_ino._gl_ino[0] = ((ULONGLONG) info.nFileIndexHigh << 32) | (ULONGLONG) info.nFileIndexLow;
+ buf->st_ino._gl_ino[1] = 0;
+ ino_done: ;
+# else /* _GL_WINDOWS_STAT_INODES == 1 */
+ buf->st_dev = info.dwVolumeSerialNumber;
+ buf->st_ino = ((ULONGLONG) info.nFileIndexHigh << 32) | (ULONGLONG) info.nFileIndexLow;
+# endif
+#else
/* st_ino is not wide enough for identifying a file on a device.
Without st_ino, st_dev is pointless. */
buf->st_dev = 0;
buf->st_ino = 0;
+#endif
/* st_mode. */
unsigned int mode =
else if (type == FILE_TYPE_CHAR || type == FILE_TYPE_PIPE)
{
buf->st_dev = 0;
+#if _GL_WINDOWS_STAT_INODES == 2
+ buf->st_ino._gl_ino[0] = buf->st_ino._gl_ino[1] = 0;
+#else
buf->st_ino = 0;
+#endif
buf->st_mode = (type == FILE_TYPE_PIPE ? _S_IFIFO : _S_IFCHR);
buf->st_nlink = 1;
buf->st_uid = 0;
UNC root directories (e.g. '\\server\share').
The second approach fails for some system files (e.g. 'C:\pagefile.sys'
and 'C:\hiberfil.sys'): ERROR_SHARING_VIOLATION.
- So we use the first approach for nearly all files, and the second one
- only for root and UNC root directories. */
+ The second approach gives more information (in particular, correct
+ st_dev, st_ino, st_nlink fields).
+ So we use the second approach and, as a fallback except for root and
+ UNC root directories, also the first approach. */
{
int ret;
- if (!((rlen == drive_prefix_len + 1 && ISSLASH (rname[drive_prefix_len]))
- || is_unc_root (rname)))
- {
- /* Approach based on the directory entry. */
-
- if (strchr (rname, '?') != NULL || strchr (rname, '*') != NULL)
- {
- /* Other Windows API functions would fail with error
- ERROR_INVALID_NAME. */
- if (malloca_rname != NULL)
- freea (malloca_rname);
- errno = ENOENT;
- return -1;
- }
-
- /* Get the details about the directory entry. */
- WIN32_FIND_DATA info;
- HANDLE h = FindFirstFile (rname, &info);
- if (h == INVALID_HANDLE_VALUE)
- goto failed;
-
- /* Test for error conditions before starting to fill *buf. */
- if (sizeof (buf->st_size) <= 4 && info.nFileSizeHigh > 0)
- {
- FindClose (h);
- if (malloca_rname != NULL)
- freea (malloca_rname);
- errno = EOVERFLOW;
- return -1;
- }
-
- /* st_ino is not wide enough for identifying a file on a device.
- Without st_ino, st_dev is pointless. */
- buf->st_dev = 0;
- buf->st_ino = 0;
-
- /* st_mode. */
- unsigned int mode =
- /* XXX How to handle FILE_ATTRIBUTE_REPARSE_POINT ? */
- ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR | S_IEXEC_UGO : _S_IFREG)
- | S_IREAD_UGO
- | ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE_UGO);
- if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- /* Determine whether the file is executable by looking at the file
- name suffix. */
- if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0)
- {
- const char *last_dot = NULL;
- const char *p;
- for (p = info.cFileName; *p != '\0'; p++)
- if (*p == '.')
- last_dot = p;
- if (last_dot != NULL)
- {
- const char *suffix = last_dot + 1;
- if (_stricmp (suffix, "exe") == 0
- || _stricmp (suffix, "bat") == 0
- || _stricmp (suffix, "cmd") == 0
- || _stricmp (suffix, "com") == 0)
- mode |= S_IEXEC_UGO;
- }
- }
- }
- buf->st_mode = mode;
-
- /* st_nlink. Ignore hard links here. */
- buf->st_nlink = 1;
-
- /* There's no easy way to map the Windows SID concept to an integer. */
- buf->st_uid = 0;
- buf->st_gid = 0;
-
- /* st_rdev is irrelevant for normal files and directories. */
- buf->st_rdev = 0;
-
- /* st_size. */
- if (sizeof (buf->st_size) <= 4)
- /* Range check already done above. */
- buf->st_size = info.nFileSizeLow;
- else
- buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow;
-
- /* st_atime, st_mtime, st_ctime. */
+
+ {
+ /* Approach based on the file. */
+
+ /* Open a handle to the file.
+ CreateFile
+ <https://msdn.microsoft.com/en-us/library/aa363858.aspx>
+ <https://msdn.microsoft.com/en-us/library/aa363874.aspx> */
+ HANDLE h =
+ CreateFile (rname,
+ FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only
+ in case as different) makes sense only when applied to *all*
+ filesystem operations. */
+ FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */,
+ NULL);
+ if (h != INVALID_HANDLE_VALUE)
+ {
+ ret = _gl_fstat_by_handle (h, rname, buf);
+ CloseHandle (h);
+ goto done;
+ }
+ }
+
+ /* Test for root and UNC root directories. */
+ if ((rlen == drive_prefix_len + 1 && ISSLASH (rname[drive_prefix_len]))
+ || is_unc_root (rname))
+ goto failed;
+
+ /* Fallback. */
+ {
+ /* Approach based on the directory entry. */
+
+ if (strchr (rname, '?') != NULL || strchr (rname, '*') != NULL)
+ {
+ /* Other Windows API functions would fail with error
+ ERROR_INVALID_NAME. */
+ if (malloca_rname != NULL)
+ freea (malloca_rname);
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* Get the details about the directory entry. This can be done through
+ FindFirstFile
+ <https://msdn.microsoft.com/en-us/library/aa364418.aspx>
+ <https://msdn.microsoft.com/en-us/library/aa365740.aspx>
+ or through
+ FindFirstFileEx with argument FindExInfoBasic
+ <https://msdn.microsoft.com/en-us/library/aa364419.aspx>
+ <https://msdn.microsoft.com/en-us/library/aa364415.aspx>
+ <https://msdn.microsoft.com/en-us/library/aa365740.aspx> */
+ WIN32_FIND_DATA info;
+ HANDLE h = FindFirstFile (rname, &info);
+ if (h == INVALID_HANDLE_VALUE)
+ goto failed;
+
+ /* Test for error conditions before starting to fill *buf. */
+ if (sizeof (buf->st_size) <= 4 && info.nFileSizeHigh > 0)
+ {
+ FindClose (h);
+ if (malloca_rname != NULL)
+ freea (malloca_rname);
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+# if _GL_WINDOWS_STAT_INODES
+ buf->st_dev = 0;
+# if _GL_WINDOWS_STAT_INODES == 2
+ buf->st_ino._gl_ino[0] = buf->st_ino._gl_ino[1] = 0;
+# else /* _GL_WINDOWS_STAT_INODES == 1 */
+ buf->st_ino = 0;
+# endif
+# else
+ /* st_ino is not wide enough for identifying a file on a device.
+ Without st_ino, st_dev is pointless. */
+ buf->st_dev = 0;
+ buf->st_ino = 0;
+# endif
+
+ /* st_mode. */
+ unsigned int mode =
+ /* XXX How to handle FILE_ATTRIBUTE_REPARSE_POINT ? */
+ ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR | S_IEXEC_UGO : _S_IFREG)
+ | S_IREAD_UGO
+ | ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0 : S_IWRITE_UGO);
+ if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /* Determine whether the file is executable by looking at the file
+ name suffix. */
+ if (info.nFileSizeHigh > 0 || info.nFileSizeLow > 0)
+ {
+ const char *last_dot = NULL;
+ const char *p;
+ for (p = info.cFileName; *p != '\0'; p++)
+ if (*p == '.')
+ last_dot = p;
+ if (last_dot != NULL)
+ {
+ const char *suffix = last_dot + 1;
+ if (_stricmp (suffix, "exe") == 0
+ || _stricmp (suffix, "bat") == 0
+ || _stricmp (suffix, "cmd") == 0
+ || _stricmp (suffix, "com") == 0)
+ mode |= S_IEXEC_UGO;
+ }
+ }
+ }
+ buf->st_mode = mode;
+
+ /* st_nlink. Ignore hard links here. */
+ buf->st_nlink = 1;
+
+ /* There's no easy way to map the Windows SID concept to an integer. */
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+
+ /* st_rdev is irrelevant for normal files and directories. */
+ buf->st_rdev = 0;
+
+ /* st_size. */
+ if (sizeof (buf->st_size) <= 4)
+ /* Range check already done above. */
+ buf->st_size = info.nFileSizeLow;
+ else
+ buf->st_size = ((long long) info.nFileSizeHigh << 32) | (long long) info.nFileSizeLow;
+
+ /* st_atime, st_mtime, st_ctime. */
# if _GL_WINDOWS_STAT_TIMESPEC
- buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
- buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime);
- buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime);
+ buf->st_atim = _gl_convert_FILETIME_to_timespec (&info.ftLastAccessTime);
+ buf->st_mtim = _gl_convert_FILETIME_to_timespec (&info.ftLastWriteTime);
+ buf->st_ctim = _gl_convert_FILETIME_to_timespec (&info.ftCreationTime);
# else
- buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime);
- buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime);
- buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime);
+ buf->st_atime = _gl_convert_FILETIME_to_POSIX (&info.ftLastAccessTime);
+ buf->st_mtime = _gl_convert_FILETIME_to_POSIX (&info.ftLastWriteTime);
+ buf->st_ctime = _gl_convert_FILETIME_to_POSIX (&info.ftCreationTime);
# endif
- FindClose (h);
+ FindClose (h);
- ret = 0;
- }
- else
- {
- /* Approach based on the file. */
-
- /* Open a handle to the file.
- CreateFile
- <https://msdn.microsoft.com/en-us/library/aa363858.aspx>
- <https://msdn.microsoft.com/en-us/library/aa363874.aspx> */
- HANDLE h =
- CreateFile (rname,
- FILE_READ_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL,
- OPEN_EXISTING,
- /* FILE_FLAG_POSIX_SEMANTICS (treat file names that differ only
- in case as different) makes sense only when applied to *all*
- filesystem operations. */
- FILE_FLAG_BACKUP_SEMANTICS /* | FILE_FLAG_POSIX_SEMANTICS */,
- NULL);
- if (h == INVALID_HANDLE_VALUE)
- goto failed;
-
- ret = _gl_fstat_by_handle (h, rname, buf);
- CloseHandle (h);
- }
+ ret = 0;
+ }
+ done:
if (ret >= 0 && check_dir && !S_ISDIR (buf->st_mode))
{
errno = ENOTDIR;
# define _GL_WINDOWS_64_BIT_OFF_T 1
#endif
+/* Override dev_t and ino_t if distinguishable inodes support is requested
+ on native Windows. */
+#if @WINDOWS_STAT_INODES@
+
+# if @WINDOWS_STAT_INODES@ == 2
+/* Experimental, not useful in Windows 10. */
+
+/* Define dev_t to a 64-bit type. */
+# if !defined GNULIB_defined_dev_t
+typedef unsigned long long int rpl_dev_t;
+# undef dev_t
+# define dev_t rpl_dev_t
+# define GNULIB_defined_dev_t 1
+# endif
+
+/* Define ino_t to a 128-bit type. */
+# if !defined GNULIB_defined_ino_t
+/* MSVC does not have a 128-bit integer type.
+ GCC has a 128-bit integer type __int128, but only on 64-bit targets. */
+typedef struct { unsigned long long int _gl_ino[2]; } rpl_ino_t;
+# undef ino_t
+# define ino_t rpl_ino_t
+# define GNULIB_defined_ino_t 1
+# endif
+
+# else /* @WINDOWS_STAT_INODES@ == 1 */
+
+/* Define ino_t to a 64-bit type. */
+# if !defined GNULIB_defined_ino_t
+typedef unsigned long long int rpl_ino_t;
+# undef ino_t
+# define ino_t rpl_ino_t
+# define GNULIB_defined_ino_t 1
+# endif
+
+# endif
+
+/* Indicator, for gnulib internal purposes. */
+# define _GL_WINDOWS_STAT_INODES @WINDOWS_STAT_INODES@
+
+#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__) \
-# sys_types_h.m4 serial 6
+# sys_types_h.m4 serial 7
dnl Copyright (C) 2011-2017 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl Whether to override the 'off_t' type.
AC_REQUIRE([gl_TYPE_OFF_T])
+
+ dnl Whether to override the 'dev_t' and 'ino_t' types.
+ m4_ifdef([gl_WINDOWS_STAT_INODES], [
+ AC_REQUIRE([gl_WINDOWS_STAT_INODES])
+ ], [
+ WINDOWS_STAT_INODES=0
+ ])
+ AC_SUBST([WINDOWS_STAT_INODES])
])
AC_DEFUN([gl_SYS_TYPES_H_DEFAULTS],
--- /dev/null
+# windows-stat-inodes.m4 serial 1
+dnl Copyright (C) 2017 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Enable inode identification in 'struct stat' on native Windows platforms.
+dnl Set WINDOWS_STAT_INODES to
+dnl - 0 -> keep the default (dev_t = 32-bit, ino_t = 16-bit),
+dnl - 1 -> override types normally (dev_t = 32-bit, ino_t = 64-bit),
+dnl - 2 -> override types in an extended way (dev_t = 64-bit, ino_t = 128-bit).
+AC_DEFUN([gl_WINDOWS_STAT_INODES],
+[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ case "$host_os" in
+ mingw*) WINDOWS_STAT_INODES=1 ;;
+ *) WINDOWS_STAT_INODES=0 ;;
+ esac
+])
largefile
pathmax [test $REPLACE_FSTAT = 1]
unistd [test $REPLACE_FSTAT = 1]
+verify [test $REPLACE_FSTAT = 1]
msvc-nothrow [test $REPLACE_FSTAT = 1]
configure.ac:
-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' \
+ -e 's|@''WINDOWS_STAT_INODES''@|$(WINDOWS_STAT_INODES)|g' \
< $(srcdir)/sys_types.in.h; \
} > $@-t && \
mv $@-t $@
--- /dev/null
+Description:
+On native Windows platforms, ensure that 'struct stat' contains values
+in the st_dev, st_ino fields that are able to distinguish different inodes.
+
+Comment:
+This module should not be used as a dependency from a test module,
+otherwise when this module occurs as a tests-related module, it will
+have side effects on the compilation of the main modules in lib/.
+
+Files:
+m4/windows-stat-inodes.m4
+
+Depends-on:
+windows-stat-override
+
+configure.ac:
+AC_REQUIRE([gl_WINDOWS_STAT_INODES])
+
+Makefile.am:
+
+Include:
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible