stat: fix Solaris 9 bug
authorEric Blake <ebb9@byu.net>
Tue, 15 Sep 2009 23:08:39 +0000 (17:08 -0600)
committerEric Blake <ebb9@byu.net>
Sat, 19 Sep 2009 19:17:22 +0000 (13:17 -0600)
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 <ebb9@byu.net>
ChangeLog
doc/posix-functions/stat.texi
lib/stat.c
m4/stat.m4

index fde8d07..d0aa2c4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2009-09-19  Eric Blake  <ebb9@byu.net>
 
+       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.
index a7011ed..5fdb683 100644 (file)
@@ -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.
index c3400d5..8aa7709 100644 (file)
 
 #include <config.h>
 
+/* Get the original definition of stat.  It might be defined as a macro.  */
+#define __need_system_sys_stat_h
+#include <sys/types.h>
+#include <sys/stat.h>
+#undef __need_system_sys_stat_h
+
+static inline int
+orig_stat (const char *filename, struct stat *buf)
+{
+  return stat (filename, buf);
+}
+
+/* Specification.  */
 #include <sys/stat.h>
 
 #include <errno.h>
 #include <stdbool.h>
 #include <string.h>
 
-#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;
 }
index 9cc0b4a..0a10de1 100644 (file)
@@ -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 <sys/stat.h>
 ]], [[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 <sys/stat.h>
+]], [[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
 ])