diff options
author | joerg <joerg@pkgsrc.org> | 2008-07-30 15:02:18 +0000 |
---|---|---|
committer | joerg <joerg@pkgsrc.org> | 2008-07-30 15:02:18 +0000 |
commit | 43b61a44f873fe5498a75e3ed8f6d0211303c5b7 (patch) | |
tree | cc6987986b9c3e24b1d2ff2dc5e22d72b3bce925 | |
parent | 589e1e7556685cf5f486d44e96f412e3d985971d (diff) | |
download | pkgsrc-43b61a44f873fe5498a75e3ed8f6d0211303c5b7.tar.gz |
Internal implementation of mkdir_p.
-rw-r--r-- | pkgtools/pkg_install/files/add/perform.c | 53 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/lib.h | 4 |
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" |