mkdir, mkdirat: fix cygwin 1.5.x bug
authorEric Blake <ebb9@byu.net>
Tue, 6 Oct 2009 22:08:46 +0000 (16:08 -0600)
committerEric Blake <ebb9@byu.net>
Wed, 7 Oct 2009 13:13:52 +0000 (07:13 -0600)
mkdir("dir/./",mode) mistakenly succeeded.

* lib/mkdir.c (rpl_mkdir) [FUNC_MKDIR_DOT_BUG]: Work around bug.
* m4/mkdir-slash.m4 (gl_FUNC_MKDIR_TRAILING_SLASH): Move...
* m4/mkdir.m4 (gl_FUNC_MKDIR): ...here, and add check for cygwin
bug.
(gl_PREREQ_MKDIR): Delete unused macro.
* modules/mkdir (Files): Track file rename.
(configure.ac): Update macro name.
* modules/openat (Depends-on): Add mkdir.
* doc/posix-functions/mkdir.texi (mkdir): Document the bug.

Signed-off-by: Eric Blake <ebb9@byu.net>
ChangeLog
doc/posix-functions/mkdir.texi
lib/mkdir.c
m4/mkdir-slash.m4 [deleted file]
m4/mkdir.m4 [new file with mode: 0644]
modules/mkdir
modules/openat

index 3ce4f94..96296ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-10-07  Eric Blake  <ebb9@byu.net>
 
+       mkdir, mkdirat: fix cygwin 1.5.x bug
+       * lib/mkdir.c (rpl_mkdir) [FUNC_MKDIR_DOT_BUG]: Work around bug.
+       * m4/mkdir-slash.m4 (gl_FUNC_MKDIR_TRAILING_SLASH): Move...
+       * m4/mkdir.m4 (gl_FUNC_MKDIR): ...here, and add check for cygwin
+       bug.
+       (gl_PREREQ_MKDIR): Delete unused macro.
+       * modules/mkdir (Files): Track file rename.
+       (configure.ac): Update macro name.
+       * modules/openat (Depends-on): Add mkdir.
+       * doc/posix-functions/mkdir.texi (mkdir): Document the bug.
+
        mkdir, mkdirat: add tests
        * modules/mkdir-tests: New test.
        * tests/test-mkdir.h: New file.
index 20d13bb..69b67a5 100644 (file)
@@ -11,6 +11,10 @@ Portability problems fixed by Gnulib:
 @item
 When the argument ends in a slash, the function call fails on some platforms.
 @item
+This function mistakenly succeeds on @samp{mkdir("d/./",mode)} on
+some platforms:
+Cygwin 1.5.x, mingw.
+@item
 On Windows platforms (excluding Cygwin), this function is called @code{_mkdir}
 and takes only one argument.  The fix (without Gnulib) is to define a macro
 like this:
index 5f4d235..3d9f043 100644 (file)
@@ -1,7 +1,7 @@
 /* On some systems, mkdir ("foo/", 0700) fails because of the trailing
    slash.  On those systems, this wrapper removes the trailing slash.
 
-   Copyright (C) 2001, 2003, 2006, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2006, 2008, 2009 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
@@ -21,9 +21,9 @@
 #include <config.h>
 
 /* Specification.  */
-#include <sys/types.h>
 #include <sys/stat.h>
 
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -63,6 +63,20 @@ rpl_mkdir (char const *dir, mode_t mode maybe_unused)
     {
       tmp_dir = (char *) dir;
     }
+#if FUNC_MKDIR_DOT_BUG
+  /* Additionally, cygwin 1.5 mistakenly creates a directory "d/./".  */
+  {
+    char *last = last_component (tmp_dir);
+    if (*last == '.' && (last[1] == '\0'
+                         || (last[1] == '.' && last[2] == '\0')))
+      {
+        struct stat st;
+        if (stat (tmp_dir, &st) == 0)
+          errno = EEXIST;
+        return -1;
+      }
+  }
+#endif /* FUNC_MKDIR_DOT_BUG */
 
   ret_val = mkdir (tmp_dir, mode);
 
diff --git a/m4/mkdir-slash.m4 b/m4/mkdir-slash.m4
deleted file mode 100644 (file)
index a0bc12e..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# serial 8
-
-# Copyright (C) 2001, 2003-2004, 2006, 2008-2009 Free Software Foundation, Inc.
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# On some systems, mkdir ("foo/", 0700) fails because of the trailing slash.
-# On such systems, arrange to use a wrapper function that removes any
-# trailing slashes.
-AC_DEFUN([gl_FUNC_MKDIR_TRAILING_SLASH],
-[dnl
-  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
-  AC_CHECK_HEADERS_ONCE([unistd.h])
-  AC_CACHE_CHECK([whether mkdir fails due to a trailing slash],
-    gl_cv_func_mkdir_trailing_slash_bug,
-    [
-      # Arrange for deletion of the temporary directory this test might create.
-      ac_clean_files="$ac_clean_files confdir-slash"
-      AC_RUN_IFELSE([AC_LANG_SOURCE([[
-#       include <sys/types.h>
-#       include <sys/stat.h>
-#       include <stdlib.h>
-#       ifdef HAVE_UNISTD_H
-#         include <unistd.h>
-#       endif
-       int main ()
-       {
-         rmdir ("confdir-slash");
-         exit (mkdir ("confdir-slash/", 0700));
-       }
-       ]])],
-      [gl_cv_func_mkdir_trailing_slash_bug=no],
-      [gl_cv_func_mkdir_trailing_slash_bug=yes],
-      [gl_cv_func_mkdir_trailing_slash_bug=yes]
-      )
-    ]
-  )
-
-  if test $gl_cv_func_mkdir_trailing_slash_bug = yes; then
-    REPLACE_MKDIR=1
-    AC_LIBOBJ([mkdir])
-    gl_PREREQ_MKDIR
-  fi
-])
-
-# Prerequisites of lib/mkdir.c.
-AC_DEFUN([gl_PREREQ_MKDIR], [:])
diff --git a/m4/mkdir.m4 b/m4/mkdir.m4
new file mode 100644 (file)
index 0000000..372718a
--- /dev/null
@@ -0,0 +1,52 @@
+# serial 9
+
+# Copyright (C) 2001, 2003-2004, 2006, 2008-2009 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# On some systems, mkdir ("foo/", 0700) fails because of the trailing slash.
+# On others, mkdir ("foo/./", 0700) mistakenly succeeds.
+# On such systems, arrange to use a wrapper function.
+AC_DEFUN([gl_FUNC_MKDIR],
+[dnl
+  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+  AC_CHECK_HEADERS_ONCE([unistd.h])
+  AC_CACHE_CHECK([whether mkdir handles trailing slash],
+    [gl_cv_func_mkdir_trailing_slash_works],
+    [rm -rf conftest.dir
+      AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#       include <sys/types.h>
+#       include <sys/stat.h>
+]], [return mkdir ("conftest.dir/", 0700);])],
+      [gl_cv_func_mkdir_trailing_slash_works=yes],
+      [gl_cv_func_mkdir_trailing_slash_works=no],
+      [gl_cv_func_mkdir_trailing_slash_works="guessing no"])
+    rm -rf conftest.dir
+    ]
+  )
+  if test "$gl_cv_func_mkdir_trailing_slash_works" != yes; then
+    REPLACE_MKDIR=1
+    AC_LIBOBJ([mkdir])
+  fi
+
+  AC_CACHE_CHECK([whether mkdir handles trailing dot],
+    [gl_cv_func_mkdir_trailing_dot_works],
+    [rm -rf conftest.dir
+      AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#       include <sys/types.h>
+#       include <sys/stat.h>
+]], [return !mkdir ("conftest.dir/./", 0700);])],
+      [gl_cv_func_mkdir_trailing_dot_works=yes],
+      [gl_cv_func_mkdir_trailing_dot_works=no],
+      [gl_cv_func_mkdir_trailing_dot_works="guessing no"])
+    rm -rf conftest.dir
+    ]
+  )
+  if test "$gl_cv_func_mkdir_trailing_dot_works" != yes; then
+    REPLACE_MKDIR=1
+    AC_LIBOBJ([mkdir])
+    AC_DEFINE([FUNC_MKDIR_DOT_BUG], [1], [Define to 1 if mkdir mistakenly
+      creates a directory given with a trailing dot component.])
+  fi
+])
index 0a80f59..59d60fb 100644 (file)
@@ -3,7 +3,7 @@ mkdir() function: create a directory.
 
 Files:
 lib/mkdir.c
-m4/mkdir-slash.m4
+m4/mkdir.m4
 
 Depends-on:
 sys_stat
@@ -11,7 +11,7 @@ xalloc
 dirname
 
 configure.ac:
-gl_FUNC_MKDIR_TRAILING_SLASH
+gl_FUNC_MKDIR
 
 Makefile.am:
 
index 150853f..77a7870 100644 (file)
@@ -27,6 +27,7 @@ inline
 intprops
 lchown
 lstat
+mkdir
 open
 openat-die
 rmdir