From cb7317d75af2de40fecdd949e3fb11a85b09e10a Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 6 Oct 2009 16:08:46 -0600 Subject: [PATCH] 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 --- ChangeLog | 11 +++++++ doc/posix-functions/mkdir.texi | 4 +++ lib/mkdir.c | 18 ++++++++++-- m4/mkdir-slash.m4 | 48 ------------------------------- m4/mkdir.m4 | 52 ++++++++++++++++++++++++++++++++++ modules/mkdir | 4 +-- modules/openat | 1 + 7 files changed, 86 insertions(+), 52 deletions(-) delete mode 100644 m4/mkdir-slash.m4 create mode 100644 m4/mkdir.m4 diff --git a/ChangeLog b/ChangeLog index 3ce4f945b2..96296efdd9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2009-10-07 Eric Blake + 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. diff --git a/doc/posix-functions/mkdir.texi b/doc/posix-functions/mkdir.texi index 20d13bb83c..69b67a5289 100644 --- a/doc/posix-functions/mkdir.texi +++ b/doc/posix-functions/mkdir.texi @@ -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: diff --git a/lib/mkdir.c b/lib/mkdir.c index 5f4d235e3b..3d9f043802 100644 --- 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 /* Specification. */ -#include #include +#include #include #include #include @@ -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 index a0bc12e559..0000000000 --- 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 -# include -# include -# ifdef HAVE_UNISTD_H -# include -# 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 index 0000000000..372718a2a9 --- /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 +# include +]], [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 +# include +]], [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 +]) diff --git a/modules/mkdir b/modules/mkdir index 0a80f592aa..59d60fb4ae 100644 --- a/modules/mkdir +++ b/modules/mkdir @@ -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: diff --git a/modules/openat b/modules/openat index 150853f4cc..77a7870ef1 100644 --- a/modules/openat +++ b/modules/openat @@ -27,6 +27,7 @@ inline intprops lchown lstat +mkdir open openat-die rmdir -- 2.30.2