diff options
author | Jim Meyering <jim@meyering.net> | 2005-10-24 10:22:10 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2005-10-24 10:22:10 +0000 |
commit | b8cedd257ad21e739caaaf77cb5d26514686d942 (patch) | |
tree | 5c6cd8e25a1fe85931ddd4c67a7d7a47dee9f2fc | |
parent | 946e7dc9300fa9833db8310932bfe1af69e1f5ff (diff) | |
download | coreutils-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.c | 19 |
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; + } } } } |