summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoerg <joerg>2008-07-30 15:02:18 +0000
committerjoerg <joerg>2008-07-30 15:02:18 +0000
commit310a202d8296661b713087792dbd11af3e51945f (patch)
treecc6987986b9c3e24b1d2ff2dc5e22d72b3bce925
parent147044c111bd9b2b3b573ea354b3d35634fdde80 (diff)
downloadpkgsrc-310a202d8296661b713087792dbd11af3e51945f.tar.gz
Internal implementation of mkdir_p.
-rw-r--r--pkgtools/pkg_install/files/add/perform.c53
-rw-r--r--pkgtools/pkg_install/files/lib/lib.h4
2 files changed, 51 insertions, 6 deletions
diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c
index a80eec06ab1..b66686dbbad 100644
--- a/pkgtools/pkg_install/files/add/perform.c
+++ b/pkgtools/pkg_install/files/add/perform.c
@@ -1,4 +1,4 @@
-/* $NetBSD: perform.c,v 1.70.4.10 2008/06/27 15:25:52 joerg Exp $ */
+/* $NetBSD: perform.c,v 1.70.4.11 2008/07/30 15:02:18 joerg Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
#endif
@@ -6,7 +6,7 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
-__RCSID("$NetBSD: perform.c,v 1.70.4.10 2008/06/27 15:25:52 joerg Exp $");
+__RCSID("$NetBSD: perform.c,v 1.70.4.11 2008/07/30 15:02:18 joerg Exp $");
/*-
* Copyright (c) 2003 Grant Beattie <grant@NetBSD.org>
@@ -123,7 +123,54 @@ static int pkg_do(const char *, int);
static int
mkdir_p(const char *path)
{
- return fexec(MKDIR_CMD, "-p", path, (void *)NULL);
+ char *p, *cur_end;
+ int done;
+
+ /*
+ * Handle the easy case of direct success or
+ * pre-existing directory first.
+ */
+ if (mkdir(path, 0777) == 0 || errno == EEXIST)
+ return 0;
+ if (errno != ENOENT)
+ return -1;
+
+ if ((p = strdup(path)) == NULL)
+ err(EXIT_FAILURE, "strdup failed");
+
+ cur_end = p;
+
+ for (;;) {
+ /*
+ * First skip leading slashes either from / or
+ * from the last iteration.
+ */
+ cur_end += strspn(cur_end, "/");
+ /* Find end of actual directory name. */
+ cur_end += strcspn(cur_end, "/");
+
+ /*
+ * Remember if this is the last component and
+ * overwrite / if needed.
+ */
+ done = (*cur_end == '\0');
+ *cur_end = '\0';
+
+ /*
+ * ENOENT can only happen if something else races us,
+ * in which case we should better give up.
+ */
+ if (mkdir(p, 0777) == -1 && errno != EEXIST) {
+ free(p);
+ return -1;
+ }
+ if (done)
+ break;
+ *cur_end = '/';
+ }
+
+ free(p);
+ return 0;
}
/*
diff --git a/pkgtools/pkg_install/files/lib/lib.h b/pkgtools/pkg_install/files/lib/lib.h
index 20fcb870735..4eaa9d9e4c9 100644
--- a/pkgtools/pkg_install/files/lib/lib.h
+++ b/pkgtools/pkg_install/files/lib/lib.h
@@ -1,4 +1,4 @@
-/* $NetBSD: lib.h,v 1.42.2.7 2008/07/05 17:26:39 joerg Exp $ */
+/* $NetBSD: lib.h,v 1.42.2.8 2008/07/30 15:02:18 joerg Exp $ */
/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */
@@ -86,8 +86,6 @@
#define DEF_UMASK 022
#endif
-#define MKDIR_CMD "mkdir"
-
/* Usually "rm", but often "echo" during debugging! */
#define REMOVE_CMD "rm"