This patch adds an override of 'struct stat' on native Windows platforms. It's a separate module so that other modules can depend on it. (Maybe a module is overkill and a .m4 file would be sufficient, but I think it's easier to use this way.)
2017-05-13 Bruno Haible <br...@clisp.org> windows-stat-override: New module. * lib/sys_stat.in.h (stat) [GNULIB_OVERRIDES_STRUCT_STAT]: Provide own definition. Define GNULIB_defined_struct_stat. (fstat, fstatat, lstat, stat) [GNULIB_OVERRIDES_STRUCT_STAT]: Provoke link error if this symbol is used and the corresponding module is not in use. (_stat64, _stat32i64, _stati64, _stat32, _stat64i32): Don't redefine if GNULIB_OVERRIDES_STRUCT_STAT. * m4/sys_stat_h.m4 (gl_SYS_STAT_H_DEFAULTS): Initialize GNULIB_OVERRIDES_STRUCT_STAT. * modules/sys_stat (Makefile.am): Substitute GNULIB_OVERRIDES_STRUCT_STAT. * modules/windows-stat-override: New file. diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index 189598d..ef689b9 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -1,4 +1,4 @@ -/* Provide a more complete sys/stat header file. +/* Provide a more complete sys/stat.h header file. Copyright (C) 2005-2017 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify @@ -72,6 +72,73 @@ # define stat _stati64 #endif +/* Optionally, override 'struct stat' on native Windows. */ +#if @GNULIB_OVERRIDES_STRUCT_STAT@ + +# undef stat +# if @GNULIB_STAT@ +# define stat rpl_stat +# else + /* Provoke a clear link error if stat() is used as a function and + module 'stat' is not in use. */ +# define stat stat_used_without_requesting_gnulib_module_stat +# endif + +# if !GNULIB_defined_struct_stat +struct stat +{ + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; +# if 0 + uid_t st_uid; +# else /* uid_t is not defined by default on native Windows. */ + short st_uid; +# endif +# if 0 + gid_t st_gid; +# else /* gid_t is not defined by default on native Windows. */ + short st_gid; +# endif + dev_t st_rdev; + off_t st_size; +# if 0 + blksize_t st_blksize; + blkcnt_t st_blocks; +# endif + +# if 0 + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +# else + time_t st_atime; + time_t st_mtime; + time_t st_ctime; +# endif +}; +# if 0 +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# endif +# define GNULIB_defined_struct_stat 1 +# endif + +/* Other possible values of st_mode. */ +# if 0 +# define _S_IFBLK 0x6000 +# endif +# if 0 +# define _S_IFLNK 0xA000 +# endif +# if 0 +# define _S_IFSOCK 0xC000 +# endif + +#endif + #ifndef S_IFIFO # ifdef _S_IFIFO # define S_IFIFO _S_IFIFO @@ -345,6 +412,9 @@ _GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); _GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); # endif _GL_CXXALIASWARN (fstat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstat +# define fstat fstat_used_without_requesting_gnulib_module_fstat #elif @WINDOWS_64_BIT_ST_SIZE@ /* Above, we define stat to _stati64. */ # define fstat _fstati64 @@ -378,6 +448,9 @@ _GL_CXXALIAS_SYS (fstatat, int, (int fd, char const *name, struct stat *st, int flags)); # endif _GL_CXXALIASWARN (fstatat); +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef fstatat +# define fstatat fstatat_used_without_requesting_gnulib_module_fstatat #elif defined GNULIB_POSIXCHECK # undef fstatat # if HAVE_RAW_DECL_FSTATAT @@ -476,6 +549,9 @@ _GL_CXXALIAS_SYS (lstat, int, (const char *name, struct stat *buf)); # if @HAVE_LSTAT@ _GL_CXXALIASWARN (lstat); # endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +# undef lstat +# define lstat lstat_used_without_requesting_gnulib_module_lstat #elif defined GNULIB_POSIXCHECK # undef lstat # if HAVE_RAW_DECL_LSTAT @@ -625,63 +701,69 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - " #if @GNULIB_STAT@ # if @REPLACE_STAT@ -/* We can't use the object-like #define stat rpl_stat, because of - struct stat. This means that rpl_stat will not be used if the user - does (stat)(a,b). Oh well. */ -# if defined _AIX && defined stat && defined _LARGE_FILES - /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, - 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) +# if !@GNULIB_OVERRIDES_STRUCT_STAT@ + /* We can't use the object-like #define stat rpl_stat, because of + struct stat. This means that rpl_stat will not be used if the user + does (stat)(a,b). Oh well. */ +# if defined _AIX && defined stat && defined _LARGE_FILES + /* With _LARGE_FILES defined, AIX (only) defines stat to stat64, + 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 _MSC_VER && defined _stati64 +# elif defined __MINGW32__ && defined stat # ifdef _USE_32BIT_TIME_T - /* The system headers define _stati64 to _stat32i64. */ + /* The system headers define stat to _stat32i64. */ # undef _stat32i64 # define _stat32i64(name, st) rpl_stat (name, st) # else - /* The system headers define _stati64 to _stat64. */ + /* The system headers define stat 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. */ -# undef _stat32i64 -# define _stat32i64(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64. */ -# undef _stat64 -# define _stat64(name, st) rpl_stat (name, st) -# endif -# elif defined _MSC_VER && defined stat -# ifdef _USE_32BIT_TIME_T - /* The system headers define stat to _stat32. */ -# undef _stat32 -# define _stat32(name, st) rpl_stat (name, st) -# else - /* The system headers define stat to _stat64i32. */ -# undef _stat64i32 -# define _stat64i32(name, st) rpl_stat (name, st) -# endif -# else /* !(_AIX ||__MINGW32__ || _MSC_VER) */ -# undef stat -# define stat(name, st) rpl_stat (name, st) -# endif /* !_LARGE_FILES */ +# elif defined _MSC_VER && defined stat +# ifdef _USE_32BIT_TIME_T + /* The system headers define stat to _stat32. */ +# undef _stat32 +# define _stat32(name, st) rpl_stat (name, st) +# else + /* The system headers define stat to _stat64i32. */ +# undef _stat64i32 +# define _stat64i32(name, st) rpl_stat (name, st) +# endif +# else /* !(_AIX || __MINGW32__ || _MSC_VER) */ +# undef stat +# define stat(name, st) rpl_stat (name, st) +# endif /* !_LARGE_FILES */ +# endif /* !@GNULIB_OVERRIDES_STRUCT_STAT@ */ _GL_EXTERN_C int stat (const char *name, struct stat *buf) _GL_ARG_NONNULL ((1, 2)); # endif +#elif @GNULIB_OVERRIDES_STRUCT_STAT@ +/* see above: + #define stat stat_used_without_requesting_gnulib_module_stat + */ #elif defined GNULIB_POSIXCHECK # undef stat # if HAVE_RAW_DECL_STAT diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4 index 1e34ac4..f0f443e 100644 --- a/m4/sys_stat_h.m4 +++ b/m4/sys_stat_h.m4 @@ -1,4 +1,4 @@ -# sys_stat_h.m4 serial 28 -*- Autoconf -*- +# sys_stat_h.m4 serial 29 -*- Autoconf -*- dnl Copyright (C) 2006-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, @@ -72,6 +72,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS], GNULIB_MKNODAT=0; AC_SUBST([GNULIB_MKNODAT]) GNULIB_STAT=0; AC_SUBST([GNULIB_STAT]) GNULIB_UTIMENSAT=0; AC_SUBST([GNULIB_UTIMENSAT]) + GNULIB_OVERRIDES_STRUCT_STAT=0; AC_SUBST([GNULIB_OVERRIDES_STRUCT_STAT]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_FCHMODAT=1; AC_SUBST([HAVE_FCHMODAT]) HAVE_FSTATAT=1; AC_SUBST([HAVE_FSTATAT]) diff --git a/modules/sys_stat b/modules/sys_stat index f8d8633..2e0aa75 100644 --- a/modules/sys_stat +++ b/modules/sys_stat @@ -46,6 +46,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's/@''GNULIB_MKNODAT''@/$(GNULIB_MKNODAT)/g' \ -e 's/@''GNULIB_STAT''@/$(GNULIB_STAT)/g' \ -e 's/@''GNULIB_UTIMENSAT''@/$(GNULIB_UTIMENSAT)/g' \ + -e 's/@''GNULIB_OVERRIDES_STRUCT_STAT''@/$(GNULIB_OVERRIDES_STRUCT_STAT)/g' \ -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \ -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \ -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \ diff --git a/modules/windows-stat-override b/modules/windows-stat-override new file mode 100644 index 0000000..027fa92 --- /dev/null +++ b/modules/windows-stat-override @@ -0,0 +1,30 @@ +Description: +On native Windows platforms, override 'struct stat'. + +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: + +Depends-on: +sys_stat + +configure.ac: +AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) +AC_REQUIRE([AC_CANONICAL_HOST]) +case "$host_os" in + mingw*) GNULIB_OVERRIDES_STRUCT_STAT=1 ;; +esac + +Makefile.am: + +Include: +<sys/stat.h> + +License: +LGPLv2+ + +Maintainer: +Bruno Haible