diff options
author | Charles Longeau <chl@cvs.openbsd.org> | 2008-01-02 09:27:03 +0000 |
---|---|---|
committer | Charles Longeau <chl@cvs.openbsd.org> | 2008-01-02 09:27:03 +0000 |
commit | 743b56ad6ebbf1a76814167c86e05eafdae19768 (patch) | |
tree | d796f29695526130da267b08deed3d58651425fa /bin/mkdir/mkdir.c | |
parent | 8d7ee87dc0353862378071ec699c23bb285285e5 (diff) |
fix PR 5141:
race condition in mkdir -p that may lead to an erroneous successful exit status.
reported by Ralf Wildenhues <Ralf.Wildenhues at gmx.de>
fix based on a suggested patch by Bruno Carnazzi <bcarnazzi at gmail.com>,
largely inspired by NetBSD mkdir()s implementation
looks OK otto@ OK millert@
Diffstat (limited to 'bin/mkdir/mkdir.c')
-rw-r--r-- | bin/mkdir/mkdir.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/bin/mkdir/mkdir.c b/bin/mkdir/mkdir.c index df593e71b9c..0a2fe086224 100644 --- a/bin/mkdir/mkdir.c +++ b/bin/mkdir/mkdir.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mkdir.c,v 1.19 2007/08/06 19:16:05 sobrado Exp $ */ +/* $OpenBSD: mkdir.c,v 1.20 2008/01/02 09:27:02 chl Exp $ */ /* $NetBSD: mkdir.c,v 1.14 1995/06/25 21:59:21 mycroft Exp $ */ /* @@ -40,7 +40,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94"; #else -static char rcsid[] = "$OpenBSD: mkdir.c,v 1.19 2007/08/06 19:16:05 sobrado Exp $"; +static char rcsid[] = "$OpenBSD: mkdir.c,v 1.20 2008/01/02 09:27:02 chl Exp $"; #endif #endif /* not lint */ @@ -154,16 +154,21 @@ mkpath(char *path, mode_t mode, mode_t dir_mode) done = (*slash == '\0'); *slash = '\0'; - if (stat(path, &sb)) { - if (errno != ENOENT || - (mkdir(path, done ? mode : dir_mode) && - errno != EEXIST)) { + if (mkdir(path, done ? mode : dir_mode) < 0) { + int mkdir_errno = errno; + + if (stat(path, &sb)) { + /* Not there; use mkdir()s errno */ + errno = mkdir_errno; + warn("%s", path); + return (-1); + } + if (!S_ISDIR(sb.st_mode)) { + /* Is there, but isn't a directory */ + errno = ENOTDIR; warn("%s", path); return (-1); } - } else if (!S_ISDIR(sb.st_mode)) { - warnx("%s: %s", path, strerror(ENOTDIR)); - return (-1); } if (done) |