summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2008-02-13 14:50:52 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2008-02-13 14:50:52 +0000
commit1fade25aa77465c09e8c40896b78c15a89b5bd84 (patch)
treeecd1c1b353a752e9dfedd8d6faa86c2f51b15eb2
parent3c8792186afbd1eaf231282df06c176271789239 (diff)
Rework the fix in 1.20. The original fix causes problems for systrace
policies since mkdir(2) will be called for each directory in the path, even things like / or /usr. We now use a hybrid approach uses stat(2) until either we find something missing or we reach that last component. Then we switch to calling mkdir(). Tested by bernd@ and chl@
-rw-r--r--bin/mkdir/mkdir.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/bin/mkdir/mkdir.c b/bin/mkdir/mkdir.c
index 0a2fe086224..b4e320998c5 100644
--- a/bin/mkdir/mkdir.c
+++ b/bin/mkdir/mkdir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mkdir.c,v 1.20 2008/01/02 09:27:02 chl Exp $ */
+/* $OpenBSD: mkdir.c,v 1.21 2008/02/13 14:50:51 millert 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.20 2008/01/02 09:27:02 chl Exp $";
+static char rcsid[] = "$OpenBSD: mkdir.c,v 1.21 2008/02/13 14:50:51 millert Exp $";
#endif
#endif /* not lint */
@@ -143,7 +143,7 @@ mkpath(char *path, mode_t mode, mode_t dir_mode)
{
struct stat sb;
char *slash;
- int done;
+ int done, exists;
slash = path;
@@ -154,12 +154,16 @@ mkpath(char *path, mode_t mode, mode_t dir_mode)
done = (*slash == '\0');
*slash = '\0';
- if (mkdir(path, done ? mode : dir_mode) < 0) {
- int mkdir_errno = errno;
+ /* skip existing path components */
+ exists = !stat(path, &sb);
+ if (!done && exists && S_ISDIR(sb.st_mode)) {
+ *slash = '/';
+ continue;
+ }
- if (stat(path, &sb)) {
- /* Not there; use mkdir()s errno */
- errno = mkdir_errno;
+ if (mkdir(path, done ? mode : dir_mode) < 0) {
+ if (!exists) {
+ /* Not there */
warn("%s", path);
return (-1);
}