Thanks for the quick report! I've just fixed it with the patch below. I will add a test, too, of course.
Matthias Andree <[EMAIL PROTECTED]> wrote: > URL: > <http://savannah.gnu.org/bugs/?func=detailitem&item_id=14848> ... > Details: > > As of coreutils 5.92, there is a regression over previous versions: > > $ rm -rf /tmp/test$$ > # this fails: > $ mkdir -p /tmp/test$$/new/. > mkdir: cannot create directory `/tmp/test12097/new/.': File exists > # it works however if the directory exists > $ mkdir -p /tmp/test$$/new/. # now works as new exists > > The first mkdir -p command shown used to work with older coreutils, and there > is no reason why it should fail today. 2005-10-24 Jim Meyering <[EMAIL PROTECTED]> * mkdir-p.c (make_dir_parents): Make the preceding fix a little more robust, e.g., when the final component is created as a non- directory by another process just before `mkdir -p's final mkdir. A command like `mkdir -p nonexistent/.' would create the directory but exit nonzero with a diagnostic. This could also be triggered with a non-`.' component, e.g., in a race with another process running the same `mkdir -p nonexistent/sub' command. * mkdir-p.c (make_dir_parents): Handle the case of an existing final component. Reported by Matthias Andree here: http://savannah.gnu.org/bugs/?func=detailitem&item_id=14848 Index: lib/mkdir-p.c =================================================================== RCS file: /fetish/cu/lib/mkdir-p.c,v retrieving revision 1.12 retrieving revision 1.14 diff -u -p -r1.12 -r1.14 --- lib/mkdir-p.c 13 Oct 2005 19:05:13 -0000 1.12 +++ lib/mkdir-p.c 24 Oct 2005 10:22:10 -0000 1.14 @@ -264,17 +264,42 @@ make_dir_parents (char const *arg, Create the final component of the file name. */ if (retval) { - if (mkdir (basename_dir, mode) != 0) - { - error (0, errno, _("cannot create directory %s"), quote (dir)); - retval = false; - } - else + bool just_created = (mkdir (basename_dir, mode) == 0); + if (just_created) { if (verbose_fmt_string) error (0, 0, verbose_fmt_string, quote (dir)); fixup_permissions_dir = basename_dir; } + else + { + if (errno != EEXIST) + { + error (0, errno, _("cannot create directory %s"), quote (dir)); + retval = false; + } + else + { + /* basename_dir exists. + This is highly unlikely, but not impossible in a race. + You can exercise this code by running a very slow + mkdir -p a/nonexistent/c process and e.g., running + touch a/nonexistent/c after a/nonexistent is created + but before mkdir attempts to create `c'. + + If it's a directory, we're done. + Otherwise, we must fail. */ + struct stat sbuf; + /* The stat may fail for a dangling link. */ + if (stat (basename_dir, &sbuf) != 0 + || ! S_ISDIR (sbuf.st_mode)) + { + error (0, 0, _("%s exists but is not a directory"), + quote (basename_dir)); + retval = false; + } + } + } } } _______________________________________________ Bug-coreutils mailing list [email protected] http://lists.gnu.org/mailman/listinfo/bug-coreutils
