fstat() also crashes on MSVC 9 for an invalid fd argument. This, together with the need to use 'largefile' whenever there is an fstat() call of a file that could be large than 2 GB, is enough justification for a new module 'fstat'.
2011-09-25 Bruno Haible <[email protected]> New module 'fstat'. * lib/sys_stat.in.h (fstat): Declare only if GNULIB_FSTAT is set. * lib/fstat.c: New file, based on a piece of lib/fchdir.c. * lib/fchdir.c (rpl_fstat): Remove function. * m4/fstat.m4: New file. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_FSTAT. * m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Test whether fstat is declared. (gl_SYS_STAT_H_DEFAULTS): Initialize GNULIB_FSTAT. * modules/sys_stat (Makefile.am): Substitute GNULIB_FSTAT. * modules/fstat: New file. * modules/sys_stat-tests (Depends-on): Remove fstat-tests. * tests/test-sys_stat-c++.cc (fstat): Check only if GNULIB_TEST_FSTAT is set. * doc/posix-functions/fstat.texi: Mention the new module and the problem on MSVC. * NEWS: Mention the change. * modules/acl (Depends-on): Add fstat. * modules/chdir-safer (Depends-on): Likewise. * modules/chown (Depends-on): Likewise. * modules/copy-file (Depends-on): Likewise. * modules/fchdir (Depends-on): Likewise. * modules/fdopendir (Depends-on): Likewise. * modules/fopen (Depends-on): Likewise. * modules/fts (Depends-on): Likewise. * modules/getcwd (Depends-on): Likewise. * modules/isapipe (Depends-on): Likewise. * modules/linkat (Depends-on): Likewise. * modules/lseek (Depends-on): Likewise. * modules/mkdir-p (Depends-on): Likewise. * modules/open (Depends-on): Likewise. * modules/openat (Depends-on): Likewise. * modules/read-file (Depends-on): Likewise. * modules/renameat (Depends-on): Likewise. * modules/utimens (Depends-on): Likewise. ================================= lib/fstat.c ================================= /* fstat() replacement. Copyright (C) 2011 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 of the License, 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/>. */ /* If the user's config.h happens to include <sys/stat.h>, let it include only the system's <sys/stat.h> here, so that orig_fstat doesn't recurse to rpl_fstat. */ #define __need_system_sys_stat_h #include <config.h> /* Get the original definition of fstat. It might be defined as a macro. */ #include <sys/types.h> #include <sys/stat.h> #undef __need_system_sys_stat_h static inline int orig_fstat (int fd, struct stat *buf) { return fstat (fd, buf); } /* Specification. */ /* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc eliminates this include because of the preliminary #include <sys/stat.h> above. */ #include "sys/stat.h" #include <errno.h> #include <unistd.h> #if HAVE_MSVC_INVALID_PARAMETER_HANDLER # include "msvc-inval.h" #endif #if HAVE_MSVC_INVALID_PARAMETER_HANDLER static inline int fstat_nothrow (int fd, struct stat *buf) { int result; TRY_MSVC_INVAL { result = orig_fstat (fd, buf); } CATCH_MSVC_INVAL { result = -1; errno = EBADF; } DONE_MSVC_INVAL; return result; } #else # define fstat_nothrow orig_fstat #endif int rpl_fstat (int fd, struct stat *buf) { #if REPLACE_FCHDIR && REPLACE_OPEN_DIRECTORY /* Handle the case when rpl_open() used a dummy file descriptor to work around an open() that can't normally visit directories. */ const char *name = _gl_directory_name (fd); if (name != NULL) return stat (name, buf); #endif return fstat_nothrow (fd, buf); } ================================= m4/fstat.m4 ================================= # fstat.m4 serial 1 dnl Copyright (C) 2011 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. 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 dnl Replace fstat() for supporting the gnulib-defined open() on directories. m4_ifdef([gl_FUNC_FCHDIR], [ gl_TEST_FCHDIR if test $HAVE_FCHDIR = 0 \ && test "$gl_cv_func_open_directory_works" != yes; then REPLACE_FSTAT=1 fi ]) ]) # Prerequisites of lib/fstat.c. AC_DEFUN([gl_PREREQ_FSTAT], [ AC_REQUIRE([AC_C_INLINE]) ]) ================================ modules/fstat ================================ Description: fstat() function: query file information Files: lib/fstat.c m4/fstat.m4 Depends-on: sys_stat largefile unistd [test $REPLACE_STAT = 1] msvc-inval [test $REPLACE_STAT = 1] configure.ac: gl_FUNC_FSTAT if test $REPLACE_FSTAT = 1; then AC_LIBOBJ([fstat]) gl_PREREQ_FSTAT fi gl_SYS_STAT_MODULE_INDICATOR([fstat]) Makefile.am: Include: <sys/stat.h> License: LGPLv2+ Maintainer: Bruno Haible =============================================================================== --- NEWS.orig Sun Sep 25 13:41:48 2011 +++ NEWS Sun Sep 25 12:32:21 2011 @@ -12,6 +12,10 @@ Date Modules Changes +2011-09-25 sys_stat This module no longer provides the fstat() + function. If you need this function, you now need + to request the 'fstat' module. + 2011-09-23 signal This module is renamed to 'signal-h'. 2011-09-22 select The link requirements of this module are changed --- doc/posix-functions/fstat.texi.orig Sun Sep 25 13:41:48 2011 +++ doc/posix-functions/fstat.texi Sun Sep 25 12:28:40 2011 @@ -4,18 +4,21 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/fstat.html} -Gnulib module: --- +Gnulib module: fstat Portability problems fixed by Gnulib: @itemize -@end itemize - -Portability problems not fixed by Gnulib: -@itemize +@item +This function crashes when invoked with invalid arguments on some platforms: +MSVC 9. @item On platforms where @code{off_t} is a 32-bit type, @code{fstat} may not correctly report the size of files or block devices larger than 2 GB. The fix is to use the @code{AC_SYS_LARGEFILE} macro. +@end itemize + +Portability problems not fixed by Gnulib: +@itemize @item On Cygwin, @code{fstat} applied to the file descriptors 0 and 1, returns different @code{st_ino} values, even if standard input and standard output --- lib/fchdir.c.orig Sun Sep 25 13:41:48 2011 +++ lib/fchdir.c Sun Sep 25 12:45:53 2011 @@ -197,20 +197,6 @@ return NULL; } -#if REPLACE_OPEN_DIRECTORY -/* Return stat information about FD in STATBUF. Needed when - rpl_open() used a dummy file to work around an open() that can't - normally visit directories. */ -# undef fstat -int -rpl_fstat (int fd, struct stat *statbuf) -{ - if (0 <= fd && fd < dirs_allocated && dirs[fd].name != NULL) - return stat (dirs[fd].name, statbuf); - return fstat (fd, statbuf); -} -#endif - /* Implement fchdir() in terms of chdir(). */ --- lib/sys_stat.in.h.orig Sun Sep 25 13:41:48 2011 +++ lib/sys_stat.in.h Sun Sep 25 12:25:13 2011 @@ -319,16 +319,25 @@ #endif -#if @REPLACE_FSTAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define fstat rpl_fstat -# endif +#if @GNULIB_FSTAT@ +# if @REPLACE_FSTAT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef fstat +# define fstat rpl_fstat +# endif _GL_FUNCDECL_RPL (fstat, int, (int fd, struct stat *buf) _GL_ARG_NONNULL ((2))); _GL_CXXALIAS_RPL (fstat, int, (int fd, struct stat *buf)); -#else +# else _GL_CXXALIAS_SYS (fstat, int, (int fd, struct stat *buf)); -#endif +# endif _GL_CXXALIASWARN (fstat); +#elif defined GNULIB_POSIXCHECK +# undef fstat +# if HAVE_RAW_DECL_FSTAT +_GL_WARN_ON_USE (fstat, "fstat has portability problems - " + "use gnulib module fstat for portability"); +# endif +#endif #if @GNULIB_FSTATAT@ --- m4/fchdir.m4.orig Sun Sep 25 13:41:48 2011 +++ m4/fchdir.m4 Sun Sep 25 13:34:10 2011 @@ -1,4 +1,4 @@ -# fchdir.m4 serial 19 +# fchdir.m4 serial 20 dnl Copyright (C) 2006-2011 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,7 +8,6 @@ [ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_REQUIRE([gl_DIRENT_H_DEFAULTS]) - AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) AC_CHECK_DECLS_ONCE([fchdir]) if test $ac_cv_have_decl_fchdir = no; then @@ -34,7 +33,6 @@ if test "$gl_cv_func_open_directory_works" != yes; then AC_DEFINE([REPLACE_OPEN_DIRECTORY], [1], [Define to 1 if open() should work around the inability to open a directory.]) - REPLACE_FSTAT=1 fi fi ]) --- m4/sys_stat_h.m4.orig Sun Sep 25 13:41:48 2011 +++ m4/sys_stat_h.m4 Sun Sep 25 12:25:48 2011 @@ -1,4 +1,4 @@ -# sys_stat_h.m4 serial 25 -*- Autoconf -*- +# sys_stat_h.m4 serial 26 -*- Autoconf -*- dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -33,7 +33,7 @@ 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([[#include <sys/stat.h> - ]], [fchmodat fstatat futimens lchmod lstat mkdirat mkfifo mkfifoat + ]], [fchmodat fstat fstatat futimens lchmod lstat mkdirat mkfifo mkfifoat mknod mknodat stat utimensat]) ]) # gl_HEADER_SYS_STAT_H @@ -50,6 +50,7 @@ [ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) dnl for REPLACE_FCHDIR GNULIB_FCHMODAT=0; AC_SUBST([GNULIB_FCHMODAT]) + GNULIB_FSTAT=0; AC_SUBST([GNULIB_FSTAT]) GNULIB_FSTATAT=0; AC_SUBST([GNULIB_FSTATAT]) GNULIB_FUTIMENS=0; AC_SUBST([GNULIB_FUTIMENS]) GNULIB_LCHMOD=0; AC_SUBST([GNULIB_LCHMOD]) --- modules/acl.orig Sun Sep 25 13:41:48 2011 +++ modules/acl Sun Sep 25 12:52:10 2011 @@ -12,6 +12,7 @@ Depends-on: error +fstat gettext-h quote sys_stat --- modules/chdir-safer.orig Sun Sep 25 13:41:48 2011 +++ modules/chdir-safer Sun Sep 25 12:51:35 2011 @@ -10,6 +10,7 @@ errno fchdir fcntl-h +fstat open same-inode stdbool --- modules/chown.orig Sun Sep 25 13:41:48 2011 +++ modules/chown Sun Sep 25 12:51:53 2011 @@ -8,6 +8,7 @@ Depends-on: unistd +fstat [test $HAVE_CHOWN = 0 || test $REPLACE_CHOWN = 1] open [test $HAVE_CHOWN = 0 || test $REPLACE_CHOWN = 1] stat [test $HAVE_CHOWN = 0 || test $REPLACE_CHOWN = 1] stdbool [test $HAVE_CHOWN = 0 || test $REPLACE_CHOWN = 1] --- modules/copy-file.orig Sun Sep 25 13:41:48 2011 +++ modules/copy-file Sun Sep 25 12:52:23 2011 @@ -10,6 +10,7 @@ acl binary-io error +fstat full-write gettext-h open --- modules/fchdir.orig Sun Sep 25 13:41:48 2011 +++ modules/fchdir Sun Sep 25 12:53:31 2011 @@ -16,6 +16,7 @@ fcntl [test $HAVE_FCHDIR = 0] fcntl-h [test $HAVE_FCHDIR = 0] filenamecat-lgpl [test $HAVE_FCHDIR = 0] +fstat [test $HAVE_FCHDIR = 0] getcwd-lgpl [test $HAVE_FCHDIR = 0] malloc-posix [test $HAVE_FCHDIR = 0] open [test $HAVE_FCHDIR = 0] --- modules/fdopendir.orig Sun Sep 25 13:41:48 2011 +++ modules/fdopendir Sun Sep 25 12:53:53 2011 @@ -13,6 +13,7 @@ dup [test $HAVE_FDOPENDIR = 0] errno [test $HAVE_FDOPENDIR = 0] fchdir [test $HAVE_FDOPENDIR = 0] +fstat [test $HAVE_FDOPENDIR = 0] openat-die [test $HAVE_FDOPENDIR = 0] opendir [test $HAVE_FDOPENDIR = 0] save-cwd [test $HAVE_FDOPENDIR = 0] --- modules/fopen.orig Sun Sep 25 13:41:48 2011 +++ modules/fopen Sun Sep 25 12:54:11 2011 @@ -9,6 +9,7 @@ stdio largefile unistd [test $REPLACE_FOPEN = 1] +fstat [test $REPLACE_FOPEN = 1] configure.ac: gl_FUNC_FOPEN --- modules/fts.orig Sun Sep 25 13:41:48 2011 +++ modules/fts Sun Sep 25 12:54:27 2011 @@ -18,6 +18,7 @@ fchdir fcntl-h fcntl-safer +fstat hash i-ring lstat --- modules/getcwd.orig Sun Sep 25 13:41:48 2011 +++ modules/getcwd Sun Sep 25 12:55:26 2011 @@ -16,6 +16,7 @@ d-ino [test $REPLACE_GETCWD = 1] memmove [test $REPLACE_GETCWD = 1] openat [test $REPLACE_GETCWD = 1] +fstat [test $REPLACE_GETCWD = 1] opendir [test $REPLACE_GETCWD = 1] closedir [test $REPLACE_GETCWD = 1] stdbool [test $REPLACE_GETCWD = 1] --- modules/isapipe.orig Sun Sep 25 13:41:48 2011 +++ modules/isapipe Sun Sep 25 12:55:52 2011 @@ -11,6 +11,7 @@ sys_stat [test $HAVE_ISAPIPE = 0] unistd [test $HAVE_ISAPIPE = 0] msvc-nothrow [test $HAVE_ISAPIPE = 0] +fstat [test $HAVE_ISAPIPE = 0] configure.ac: gl_ISAPIPE --- modules/linkat.orig Sun Sep 25 13:41:48 2011 +++ modules/linkat Sun Sep 25 12:50:55 2011 @@ -16,6 +16,7 @@ errno [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] fcntl-h [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] filenamecat-lgpl [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] +fstat [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] getcwd-lgpl [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] openat [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] link [test $HAVE_LINKAT = 0 || test $REPLACE_LINKAT = 1] --- modules/lseek.orig Sun Sep 25 13:41:48 2011 +++ modules/lseek Sun Sep 25 12:56:08 2011 @@ -9,6 +9,7 @@ unistd largefile msvc-nothrow [test $REPLACE_LSEEK = 1] +fstat [test $REPLACE_LSEEK = 1] configure.ac: gl_FUNC_LSEEK --- modules/mkdir-p.orig Sun Sep 25 13:41:48 2011 +++ modules/mkdir-p Sun Sep 25 12:52:56 2011 @@ -11,6 +11,7 @@ Depends-on: error fcntl-h +fstat gettext-h lchmod lchown --- modules/open.orig Sun Sep 25 13:41:48 2011 +++ modules/open Sun Sep 25 12:56:25 2011 @@ -9,6 +9,7 @@ Depends-on: fcntl-h largefile +fstat [test $REPLACE_OPEN = 1] stat [test $REPLACE_OPEN = 1] configure.ac: --- modules/openat.orig Sun Sep 25 13:41:48 2011 +++ modules/openat Sun Sep 25 12:57:04 2011 @@ -22,6 +22,7 @@ fchdir fcntl-h fdopendir +fstat gettext-h intprops largefile --- modules/read-file.orig Sun Sep 25 13:41:48 2011 +++ modules/read-file Sun Sep 25 12:57:23 2011 @@ -7,6 +7,7 @@ m4/read-file.m4 Depends-on: +fstat ftello malloc-posix realloc-posix --- modules/renameat.orig Sun Sep 25 13:41:48 2011 +++ modules/renameat Sun Sep 25 12:51:12 2011 @@ -12,6 +12,7 @@ fcntl-h dosname [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] filenamecat-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] +fstat [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] getcwd-lgpl [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] openat [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] rename [test $HAVE_RENAMEAT = 0 || test $REPLACE_RENAMEAT = 1] --- modules/sys_stat.orig Sun Sep 25 13:41:48 2011 +++ modules/sys_stat Sun Sep 25 12:26:11 2011 @@ -32,6 +32,7 @@ -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \ -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ -e 's/@''GNULIB_FCHMODAT''@/$(GNULIB_FCHMODAT)/g' \ + -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \ -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \ -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \ --- modules/sys_stat-tests.orig Sun Sep 25 13:41:48 2011 +++ modules/sys_stat-tests Sun Sep 25 13:30:54 2011 @@ -4,7 +4,6 @@ Depends-on: verify sys_stat-c++-tests -fstat-tests configure.ac: --- modules/utimens.orig Sun Sep 25 13:41:48 2011 +++ modules/utimens Sun Sep 25 12:57:58 2011 @@ -10,6 +10,7 @@ Depends-on: errno +fstat lstat gettime stat-time --- tests/test-sys_stat-c++.cc.orig Sun Sep 25 13:41:48 2011 +++ tests/test-sys_stat-c++.cc Sun Sep 25 12:26:35 2011 @@ -29,7 +29,9 @@ (int, char const *, mode_t, int)); #endif +#if GNULIB_TEST_FSTAT SIGNATURE_CHECK (GNULIB_NAMESPACE::fstat, int, (int, struct stat *)); +#endif #if GNULIB_TEST_FSTATAT SIGNATURE_CHECK (GNULIB_NAMESPACE::fstatat, int, -- In memoriam Safia Ahmed-jan <http://en.wikipedia.org/wiki/Safia_Ahmed-jan>
