summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2005-10-24 10:22:10 +0000
committerJim Meyering <jim@meyering.net>2005-10-24 10:22:10 +0000
commitb8cedd257ad21e739caaaf77cb5d26514686d942 (patch)
tree5c6cd8e25a1fe85931ddd4c67a7d7a47dee9f2fc
parent946e7dc9300fa9833db8310932bfe1af69e1f5ff (diff)
downloadcoreutils-b8cedd257ad21e739caaaf77cb5d26514686d942.tar.xz
(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.
-rw-r--r--lib/mkdir-p.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/lib/mkdir-p.c b/lib/mkdir-p.c
index ac2e28749..0206cba9b 100644
--- a/lib/mkdir-p.c
+++ b/lib/mkdir-p.c
@@ -280,7 +280,24 @@ make_dir_parents (char const *arg,
}
else
{
- /* The directory already exists. Do nothing. */
+ /* 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;
+ }
}
}
}