summaryrefslogtreecommitdiff
path: root/bin/mkdir/mkdir.c
diff options
context:
space:
mode:
authorCharles Longeau <chl@cvs.openbsd.org>2008-01-02 09:27:03 +0000
committerCharles Longeau <chl@cvs.openbsd.org>2008-01-02 09:27:03 +0000
commit743b56ad6ebbf1a76814167c86e05eafdae19768 (patch)
treed796f29695526130da267b08deed3d58651425fa /bin/mkdir/mkdir.c
parent8d7ee87dc0353862378071ec699c23bb285285e5 (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.c23
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)