From c9d72f69bd201a1ab31464d91f234ea1817fe0e1 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 15 Sep 2009 17:08:39 -0600 Subject: [PATCH] stat: fix Solaris 9 bug stat("file/",buf) mistakenly succeeded. * m4/stat.m4 (gl_FUNC_STAT): Detect Solaris 9 bug with trailing slash. * lib/stat.c (rpl_stat): Work around it. * doc/posix-functions/stat.texi (stat): Update documentation. Signed-off-by: Eric Blake --- ChangeLog | 6 ++++++ doc/posix-functions/stat.texi | 4 ++++ lib/stat.c | 44 ++++++++++++++++++++++++++++++++++--------- m4/stat.m4 | 38 +++++++++++++++++++++++++++---------- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index fde8d07f2..d0aa2c455 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2009-09-19 Eric Blake + stat: fix Solaris 9 bug + * m4/stat.m4 (gl_FUNC_STAT): Detect Solaris 9 bug with trailing + slash. + * lib/stat.c (rpl_stat): Work around it. + * doc/posix-functions/stat.texi (stat): Update documentation. + stat: new module, for mingw bug * modules/stat: New file. * lib/stat.c: Likewise. diff --git a/doc/posix-functions/stat.texi b/doc/posix-functions/stat.texi index a7011ed4e..5fdb683af 100644 --- a/doc/posix-functions/stat.texi +++ b/doc/posix-functions/stat.texi @@ -9,6 +9,10 @@ Gnulib module: stat Portability problems fixed by Gnulib: @itemize @item +On some platforms, @code{stat("file/",buf)} succeeds instead of +failing with @code{ENOTDIR}. +Solaris 9. +@item On some platforms, @code{stat(".",buf)} and @code{stat("./",buf)} give different results: mingw. diff --git a/lib/stat.c b/lib/stat.c index c3400d5b2..8aa770940 100644 --- a/lib/stat.c +++ b/lib/stat.c @@ -18,6 +18,19 @@ #include +/* Get the original definition of stat. It might be defined as a macro. */ +#define __need_system_sys_stat_h +#include +#include +#undef __need_system_sys_stat_h + +static inline int +orig_stat (const char *filename, struct stat *buf) +{ + return stat (filename, buf); +} + +/* Specification. */ #include #include @@ -25,18 +38,30 @@ #include #include -#undef stat - -/* For now, mingw is the only known platform where stat(".") and - stat("./") give different results. Mingw stat has other bugs (such - as st_ino always being 0 on success) which this wrapper does not - work around. But at least this implementation provides the ability - to emulate fchdir correctly. */ +/* Store information about NAME into ST. Work around bugs with + trailing slashes. Mingw has other bugs (such as st_ino always + being 0 on success) which this wrapper does not work around. But + at least this implementation provides the ability to emulate fchdir + correctly. */ int rpl_stat (char const *name, struct stat *st) { - int result = stat (name, st); + int result = orig_stat (name, st); +#if REPLACE_FUNC_STAT_FILE + /* Solaris 9 mistakenly succeeds when given a non-directory with a + trailing slash. */ + if (result == 0 && !S_ISDIR (st->st_mode)) + { + size_t len = strlen (name); + if (ISSLASH (name[len - 1])) + { + errno = ENOTDIR; + return -1; + } + } +#endif /* REPLACE_FUNC_STAT_FILE */ +#if REPLACE_FUNC_STAT_DIR if (result == -1 && errno == ENOENT) { /* Due to mingw's oddities, there are some directories (like @@ -66,7 +91,7 @@ rpl_stat (char const *name, struct stat *st) } else fixed_name[len++] = '/'; - result = stat (fixed_name, st); + result = orig_stat (fixed_name, st); if (result == 0 && check_dir && !S_ISDIR (st->st_mode)) { result = -1; @@ -74,5 +99,6 @@ rpl_stat (char const *name, struct stat *st) } } } +#endif /* REPLACE_FUNC_STAT_DIR */ return result; } diff --git a/m4/stat.m4 b/m4/stat.m4 index 9cc0b4a0a..0a10de14f 100644 --- a/m4/stat.m4 +++ b/m4/stat.m4 @@ -1,4 +1,4 @@ -# serial 1 +# serial 2 # Copyright (C) 2009 Free Software Foundation, Inc. # @@ -12,20 +12,38 @@ AC_DEFUN([gl_FUNC_STAT], AC_REQUIRE([gl_AC_DOS]) AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS]) dnl mingw is the only known platform where stat(".") and stat("./") differ - AC_CACHE_CHECK([whether stat handles trailing slashes], - [gl_cv_func_stat_works], + AC_CACHE_CHECK([whether stat handles trailing slashes on directories], + [gl_cv_func_stat_dir_slash], [AC_RUN_IFELSE( [AC_LANG_PROGRAM( [[#include ]], [[struct stat st; return stat (".", &st) != stat ("./", &st);]])], - [gl_cv_func_stat_works=yes], [gl_cv_func_stat_works=no], + [gl_cv_func_stat_dir_slash=yes], [gl_cv_func_stat_dir_slash=no], [case $host_os in - mingw*) gl_cv_func_stat_works="guessing no";; - *) gl_cv_func_stat_works="guessing yes";; + mingw*) gl_cv_func_stat_dir_slash="guessing no";; + *) gl_cv_func_stat_dir_slash="guessing yes";; esac])]) - case $gl_cv_func_stat_works in - *yes) ;; - *) REPLACE_STAT=1 - AC_LIBOBJ([stat]);; + dnl Solaris 9 mistakenly succeeds on stat("file/") + AC_CACHE_CHECK([whether stat handles trailing slashes on files], + [gl_cv_func_stat_file_slash], + [touch conftest.tmp + AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include +]], [[struct stat st; return !stat ("conftest.tmp/", &st);]])], + [gl_cv_func_stat_file_slash=yes], [gl_cv_func_stat_file_slash=no], + [gl_cv_func_stat_file_slash="guessing no"])]) + case $gl_cv_func_stat_dir_slash in + *no) REPLACE_STAT=1 + AC_DEFINE([REPLACE_FUNC_STAT_DIR], [1], [Define to 1 if stat needs + help when passed a directory name with a trailing slash]);; + esac + case $gl_cv_func_stat_file_slash in + *no) REPLACE_STAT=1 + AC_DEFINE([REPLACE_FUNC_STAT_FILE], [1], [Define to 1 if stat needs + help when passed a file name with a trailing slash]);; esac + if test $REPLACE_STAT = 1; then + AC_LIBOBJ([stat]) + fi ]) -- 2.11.0