[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [bug #14848] [5.92 regression] "mkdir -p nonexistent/." fails
From: |
Jim Meyering |
Subject: |
Re: [bug #14848] [5.92 regression] "mkdir -p nonexistent/." fails |
Date: |
Mon, 24 Oct 2005 12:31:54 +0200 |
Thanks for the quick report!
I've just fixed it with the patch below.
I will add a test, too, of course.
Matthias Andree <address@hidden> 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 <address@hidden>
* 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;
+ }
+ }
+ }
}
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [bug #14848] [5.92 regression] "mkdir -p nonexistent/." fails,
Jim Meyering <=