changeset 12131:3e62859ad66f

mkdir, mkdirat: fix cygwin 1.5.x bug 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>
author Eric Blake <ebb9@byu.net>
date Tue, 06 Oct 2009 16:08:46 -0600
parents 885b12200361
children 8e0dac113023
files ChangeLog doc/posix-functions/mkdir.texi lib/mkdir.c m4/mkdir-slash.m4 m4/mkdir.m4 modules/mkdir modules/openat
diffstat 7 files changed, 86 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/doc/posix-functions/mkdir.texi
+++ b/doc/posix-functions/mkdir.texi
@@ -11,6 +11,10 @@
 @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:
--- a/lib/mkdir.c
+++ b/lib/mkdir.c
@@ -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 @@
     {
       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);
 
deleted file mode 100644
--- a/m4/mkdir-slash.m4
+++ /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], [:])
new file mode 100644
--- /dev/null
+++ b/m4/mkdir.m4
@@ -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
+])
--- a/modules/mkdir
+++ b/modules/mkdir
@@ -3,7 +3,7 @@
 
 Files:
 lib/mkdir.c
-m4/mkdir-slash.m4
+m4/mkdir.m4
 
 Depends-on:
 sys_stat
@@ -11,7 +11,7 @@
 dirname
 
 configure.ac:
-gl_FUNC_MKDIR_TRAILING_SLASH
+gl_FUNC_MKDIR
 
 Makefile.am:
 
--- a/modules/openat
+++ b/modules/openat
@@ -27,6 +27,7 @@
 intprops
 lchown
 lstat
+mkdir
 open
 openat-die
 rmdir