summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_install
diff options
context:
space:
mode:
authorben <ben>2005-11-22 15:44:59 +0000
committerben <ben>2005-11-22 15:44:59 +0000
commitb6f14f278317d2627fde7e121c97bb9832aff6a2 (patch)
tree38d3c61e2ba04f9f4e240fbc2a08bd94f821ca61 /pkgtools/pkg_install
parent214b4cdab61c385b2541e4a407d2f9d1ac90f4b7 (diff)
downloadpkgsrc-b6f14f278317d2627fde7e121c97bb9832aff6a2.tar.gz
Reduce the use of the system() function in pkg_install to avoid quoting
problems. Instead, use exec*() functions. Replace PUSHOUT() macro and string buffers with a function that operates on data structures. If it is necessary to copy files into place from staging area, then use pax to copy them. Add functions in pexec.c to create a pipe for sending data to a child process. Replace pipe code in create/perform.c with these functions. Use these functions instead of command-line arguments when copying files into place from staging area. Three system() references remain: @exec, @unexec, and vsystem().
Diffstat (limited to 'pkgtools/pkg_install')
-rw-r--r--pkgtools/pkg_install/files/add/Makefile.in4
-rw-r--r--pkgtools/pkg_install/files/add/add.h4
-rw-r--r--pkgtools/pkg_install/files/add/extract.c182
-rw-r--r--pkgtools/pkg_install/files/add/futil.c70
-rw-r--r--pkgtools/pkg_install/files/add/perform.c25
-rw-r--r--pkgtools/pkg_install/files/create/Makefile.in5
-rw-r--r--pkgtools/pkg_install/files/create/perform.c45
-rw-r--r--pkgtools/pkg_install/files/info/perform.c60
-rw-r--r--pkgtools/pkg_install/files/lib/Makefile.in4
-rw-r--r--pkgtools/pkg_install/files/lib/fexec.c60
-rw-r--r--pkgtools/pkg_install/files/lib/file.c62
-rw-r--r--pkgtools/pkg_install/files/lib/lib.h28
-rw-r--r--pkgtools/pkg_install/files/lib/pexec.c93
-rw-r--r--pkgtools/pkg_install/files/lib/version.h4
14 files changed, 425 insertions, 221 deletions
diff --git a/pkgtools/pkg_install/files/add/Makefile.in b/pkgtools/pkg_install/files/add/Makefile.in
index 69006f17ff4..20ebe3dbf67 100644
--- a/pkgtools/pkg_install/files/add/Makefile.in
+++ b/pkgtools/pkg_install/files/add/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.12 2004/08/21 06:33:40 jlam Exp $
+# $NetBSD: Makefile.in,v 1.13 2005/11/22 15:44:59 ben Exp $
srcdir= @srcdir@
@@ -14,7 +14,7 @@ CC= @CC@
CCLD= $(CC)
LIBS= -linstall @LIBS@
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib
-DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\" -DMTREE_CMD=\"@mtree@\" -DTAR_CMD=\"@tar@\"
+DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\" -DMTREE_CMD=\"@mtree@\" -DTAR_CMD=\"@tar@\" -DPAX_CMD=\"@pax@\"
CFLAGS= @CFLAGS@
LDFLAGS= @LDFLAGS@ -L../lib
diff --git a/pkgtools/pkg_install/files/add/add.h b/pkgtools/pkg_install/files/add/add.h
index 42b4f030311..5cef817ca5c 100644
--- a/pkgtools/pkg_install/files/add/add.h
+++ b/pkgtools/pkg_install/files/add/add.h
@@ -1,4 +1,4 @@
-/* $NetBSD: add.h,v 1.5 2005/11/05 13:20:09 wiz Exp $ */
+/* $NetBSD: add.h,v 1.6 2005/11/22 15:44:59 ben Exp $ */
/* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */
@@ -48,6 +48,6 @@ extern add_mode_t AddMode;
int make_hierarchy(char *);
int extract_plist(char *, package_t *);
-void apply_perms(char *, char *);
+void apply_perms(char *, char **, int);
#endif /* _INST_ADD_H_INCLUDE */
diff --git a/pkgtools/pkg_install/files/add/extract.c b/pkgtools/pkg_install/files/add/extract.c
index e9d1030a459..1d154d9235c 100644
--- a/pkgtools/pkg_install/files/add/extract.c
+++ b/pkgtools/pkg_install/files/add/extract.c
@@ -1,4 +1,4 @@
-/* $NetBSD: extract.c,v 1.12 2005/07/25 13:03:59 hubertf Exp $ */
+/* $NetBSD: extract.c,v 1.13 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,11 +7,14 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
+#if HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
#ifndef lint
#if 0
static const char *rcsid = "FreeBSD - Id: extract.c,v 1.17 1997/10/08 07:45:35 charnier Exp";
#else
-__RCSID("$NetBSD: extract.c,v 1.12 2005/07/25 13:03:59 hubertf Exp $");
+__RCSID("$NetBSD: extract.c,v 1.13 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -41,41 +44,70 @@ __RCSID("$NetBSD: extract.c,v 1.12 2005/07/25 13:03:59 hubertf Exp $");
#include "lib.h"
#include "add.h"
-#define TAR_ARGS " cf - "
-#define TARX_CMD "|" TAR_CMD " xpf - -C "
+lfile_head_t files;
+lfile_head_t perms;
/*
- * This macro is used to determine if the 'where_args' buffer is big enough to add the
- * current string (usually a filename) plus some extra commands (the contents of TARX_CMD, and
- * the directory name stored in 'Directory').
- *
- * The string " 'str'" will be added so we need room for the string plus 3 chars plus the other arguments.
- *
- * In addition, we will add " 'srt'" to the perm_args buffer so we need to ensure that there is room
- * for that.
+ * Copy files from staging area to todir.
+ * This is only used when the files cannot be directory rename()ed.
*/
-#define TOOBIG(str) ((strlen(str) + 3 + strlen(TARX_CMD) + strlen(Directory) + where_count >= maxargs) \
- || (strlen(str) + 3 + perm_count >= maxargs))
-
-#define PUSHOUT(todir) /* push out string */ \
- if (where_count > sizeof(TAR_CMD) + sizeof(TAR_ARGS)-1) { \
- strlcat(where_args, TARX_CMD, maxargs); \
- strlcat(where_args, todir, maxargs); \
- if (system(where_args)) { \
- cleanup(0); \
- errx(2, "can not invoke %lu byte %s pipeline: %s", \
- (u_long)strlen(where_args), TAR_CMD, \
- where_args); \
- } \
- strlcpy(where_args, TAR_CMD TAR_ARGS, maxargs); \
- where_count = strlen(where_args); \
- } \
- if (perm_count) { \
- apply_perms(todir, perm_args); \
- perm_args[0] = 0; \
- perm_count = 0; \
+static void
+pushout(char *todir)
+{
+ pipe_to_system_t *pipe_to;
+ char *file_args[4];
+ char **perm_argv;
+ int perm_argc = 1;
+ lfile_t *lfp;
+ int count;
+
+ /* set up arguments to run "pax -r -w -p e" */
+ file_args[0] = strrchr(PAX_CMD, '/');
+ if (file_args[0] == NULL)
+ file_args[0] = PAX_CMD;
+ else
+ file_args[0]++;
+ file_args[1] = "-rwpe";
+ file_args[2] = todir;
+ file_args[3] = NULL;
+
+ /* count entries for files */
+ count = 0;
+ TAILQ_FOREACH(lfp, &files, lf_link)
+ count++;
+
+ if (count > 0) {
+ /* open pipe, feed it files, close pipe */
+ pipe_to = pipe_to_system_begin(PAX_CMD, file_args, NULL);
+ while ((lfp = TAILQ_FIRST(&files)) != NULL) {
+ fprintf(pipe_to->fp, "%s\n", lfp->lf_name);
+ TAILQ_REMOVE(&files, lfp, lf_link);
+ free(lfp);
+ }
+ pipe_to_system_end(pipe_to);
+ }
+
+ /* count entries for permissions */
+ count = 0;
+ TAILQ_FOREACH(lfp, &perms, lf_link)
+ count++;
+
+ if (count > 0) {
+ perm_argv = malloc((count + 1) * sizeof(char *));
+ perm_argc = 0;
+ TAILQ_FOREACH(lfp, &perms, lf_link)
+ perm_argv[perm_argc++] = lfp->lf_name;
+ perm_argv[perm_argc] = NULL;
+ apply_perms(todir, perm_argv, perm_argc);
+
+ /* empty the perm list */
+ while ((lfp = TAILQ_FIRST(&perms)) != NULL) {
+ TAILQ_REMOVE(&perms, lfp, lf_link);
+ free(lfp);
+ }
+ free(perm_argv);
}
-
+}
static void
rollback(char *name, char *home, plist_t *start, plist_t *stop)
@@ -113,34 +145,12 @@ extract_plist(char *home, package_t *pkg)
{
plist_t *p = pkg->head;
char *last_file;
- char *where_args, *perm_args, *last_chdir;
- int maxargs, where_count = 0, perm_count = 0, add_count;
+ char *last_chdir;
Boolean preserve;
+ lfile_t *lfp;
- maxargs = sysconf(_SC_ARG_MAX) / 2; /* Just use half the argument space */
- where_args = malloc(maxargs);
- if (!where_args) {
- cleanup(0);
- errx(2, "can't get argument list space");
- }
- perm_args = malloc(maxargs);
- if (!perm_args) {
- cleanup(0);
- errx(2, "can't get argument list space");
- }
- strlcpy(where_args, TAR_CMD TAR_ARGS, maxargs);
- /*
- * we keep track of how many characters are stored in 'where_args' with 'where_count'.
- * Note this doesn't include the trailing null character.
- */
- where_count = strlen(where_args);
-
- perm_args[0] = 0;
- /*
- * we keep track of how many characters are stored in 'perm__args' with 'perm_count'.
- * Note this doesn't include the trailing null character.
- */
- perm_count = 0;
+ TAILQ_INIT(&files);
+ TAILQ_INIT(&perms);
last_chdir = 0;
preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
@@ -197,8 +207,6 @@ extract_plist(char *home, package_t *pkg)
"unable to back up %s to %s, aborting pkg_add",
try, pf);
rollback(PkgName, home, pkg->head, p);
- free(perm_args);
- free(where_args);
return 0;
}
}
@@ -228,40 +236,18 @@ extract_plist(char *home, package_t *pkg)
}
/* try to add to list of perms to be changed and run in bulk. */
- if (p->name[0] == '/' || TOOBIG(p->name)) {
- PUSHOUT(Directory);
- }
- /* note, if the following line is modified, TOOBIG must be adjusted accordingly */
- add_count = snprintf(&perm_args[perm_count], maxargs - perm_count, "'%s' ", p->name);
- if (add_count > maxargs - perm_count) {
- cleanup(0);
- errx(2, "oops, miscounted strings!");
- }
- perm_count += add_count;
+ if (p->name[0] == '/')
+ pushout(Directory);
+
+ LFILE_ADD(&perms, lfp, p->name);
} else {
/* rename failed, try copying with a big tar command */
if (last_chdir != Directory) {
- PUSHOUT(last_chdir);
+ pushout(last_chdir);
last_chdir = Directory;
- } else if (p->name[0] == '/' || TOOBIG(p->name)) {
- PUSHOUT(Directory);
- }
- /* note, if the following line is modified, TOOBIG must be adjusted accordingly */
- add_count = snprintf(&where_args[where_count], maxargs - where_count, " '%s'", p->name);
- if (add_count > maxargs - where_count) {
- cleanup(0);
- errx(2, "oops, miscounted strings!");
- }
- where_count += add_count;
- /* note, if the following line is modified, TOOBIG must be adjusted accordingly */
- add_count = snprintf(&perm_args[perm_count],
- maxargs - perm_count,
- "'%s' ", p->name);
- if (add_count > maxargs - perm_count) {
- cleanup(0);
- errx(2, "oops, miscounted strings!");
+ } else if (p->name[0] == '/') {
+ pushout(Directory);
}
- perm_count += add_count;
if (!NoRecord) {
/* note in pkgdb */
@@ -272,6 +258,8 @@ extract_plist(char *home, package_t *pkg)
char *s, t[MaxPathSize], *u;
int rc;
+ LFILE_ADD(&files, lfp, p->name);
+ LFILE_ADD(&perms, lfp, p->name);
if (p->name[0] == '/')
u = p->name;
else {
@@ -299,7 +287,7 @@ extract_plist(char *home, package_t *pkg)
case PLIST_CWD:
if (Verbose)
printf("extract: CWD to %s\n", p->name);
- PUSHOUT(Directory);
+ pushout(Directory);
if (strcmp(p->name, ".")) {
if (!Fake && make_hierarchy(p->name) == FAIL) {
cleanup(0);
@@ -312,24 +300,24 @@ extract_plist(char *home, package_t *pkg)
case PLIST_CMD:
format_cmd(cmd, sizeof(cmd), p->name, Directory, last_file);
- PUSHOUT(Directory);
+ pushout(Directory);
printf("Executing '%s'\n", cmd);
if (!Fake && system(cmd))
warnx("command '%s' failed", cmd);
break;
case PLIST_CHMOD:
- PUSHOUT(Directory);
+ pushout(Directory);
Mode = p->name;
break;
case PLIST_CHOWN:
- PUSHOUT(Directory);
+ pushout(Directory);
Owner = p->name;
break;
case PLIST_CHGRP:
- PUSHOUT(Directory);
+ pushout(Directory);
Group = p->name;
break;
@@ -345,10 +333,8 @@ extract_plist(char *home, package_t *pkg)
}
p = p->next;
}
- PUSHOUT(Directory);
+ pushout(Directory);
if (!NoRecord)
pkgdb_close();
- free(perm_args);
- free(where_args);
return 1;
}
diff --git a/pkgtools/pkg_install/files/add/futil.c b/pkgtools/pkg_install/files/add/futil.c
index b15874ff500..e2810f94bb6 100644
--- a/pkgtools/pkg_install/files/add/futil.c
+++ b/pkgtools/pkg_install/files/add/futil.c
@@ -1,4 +1,4 @@
-/* $NetBSD: futil.c,v 1.6 2003/10/29 23:00:28 jlam Exp $ */
+/* $NetBSD: futil.c,v 1.7 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -11,7 +11,7 @@
#if 0
static const char *rcsid = "from FreeBSD Id: futil.c,v 1.7 1997/10/08 07:45:39 charnier Exp";
#else
-__RCSID("$NetBSD: futil.c,v 1.6 2003/10/29 23:00:28 jlam Exp $");
+__RCSID("$NetBSD: futil.c,v 1.7 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -49,6 +49,10 @@ int
make_hierarchy(char *dir)
{
char *cp1, *cp2;
+ char *argv[2];
+
+ argv[0] = dir;
+ argv[1] = NULL;
if (dir[0] == '/')
cp1 = cp2 = dir + 1;
@@ -63,7 +67,7 @@ make_hierarchy(char *dir)
} else {
if (fexec("mkdir", dir, NULL))
return FAIL;
- apply_perms(NULL, dir);
+ apply_perms(NULL, argv, 1);
}
/* Put it back */
if (cp2) {
@@ -78,41 +82,71 @@ make_hierarchy(char *dir)
* Using permission defaults, apply them as necessary
*/
void
-apply_perms(char *dir, char *arg)
+apply_perms(char *dir, char **args, int nargs)
{
char *cd_to;
char owner_group[128];
+ const char **argv;
+ int argc = 0;
+ int i;
+
+ argv = malloc((nargs + 4) * sizeof(char *));
+ /*
+ * elements 0..2 are set later depending on Mode.
+ * args is a NULL terminated list of file names.
+ * by appending them to argv, argv becomes NULL terminated also.
+ */
+ for (i = 0; i <= nargs; i++)
+ argv[i + 3] = args[i];
- if (!dir || *arg == '/')/* absolute path? */
+ if (!dir || args[0][0] == '/') /* absolute path? */
cd_to = "/";
else
cd_to = dir;
- if (Mode)
- if (fcexec(cd_to, CHMOD_CMD, "-R", Mode, arg, NULL))
- warnx("couldn't change modes of '%s' to '%s'", arg,
- Mode);
+ if (Mode) {
+ argv[0] = CHMOD_CMD;
+ argv[1] = "-R";
+ argv[2] = Mode;
+ if (pfcexec(cd_to, argv))
+ warnx("couldn't change modes of '%s' ... to '%s'",
+ args[0], Mode);
+ }
if (Owner != NULL && Group != NULL) {
if (snprintf(owner_group, sizeof(owner_group),
"%s:%s", Owner, Group) > sizeof(owner_group)) {
warnx("'%s:%s' is too long (%lu max)",
Owner, Group, (unsigned long) sizeof(owner_group));
+ free(argv);
return;
}
- if (fcexec(cd_to, CHOWN_CMD, "-R", owner_group, arg))
- warnx("couldn't change owner/group of '%s' to '%s:%s'",
- arg, Owner, Group);
+ argv[0] = CHOWN_CMD;
+ argv[1] = "-R";
+ argv[2] = owner_group;
+ if (pfcexec(cd_to, argv))
+ warnx("couldn't change owner/group of '%s' ... to '%s:%s'",
+ args[0], Owner, Group);
+ free(argv);
return;
}
if (Owner != NULL) {
- if (fcexec(cd_to, CHOWN_CMD, "-R", Owner, arg, NULL))
- warnx("couldn't change owner of '%s' to '%s'", arg,
- Owner);
+ argv[0] = CHOWN_CMD;
+ argv[1] = "-R";
+ argv[2] = Owner;
+ if (pfcexec(cd_to, argv))
+ warnx("couldn't change owner of '%s' ... to '%s'",
+ args[0], Owner);
+ free(argv);
+
return;
}
if (Group != NULL) {
- if (fcexec(cd_to, CHGRP_CMD, "-R", Group, arg, NULL))
- warnx("couldn't change group of '%s' to '%s'", arg,
- Group);
+ argv[0] = CHGRP_CMD;
+ argv[1] = "-R";
+ argv[2] = Group;
+ if (pfcexec(cd_to, argv))
+ warnx("couldn't change group of '%s' ... to '%s'",
+ args[0], Group);
}
+ free(argv);
}
diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c
index 047853de2dd..95b5935679f 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.34 2005/11/05 13:20:09 wiz Exp $ */
+/* $NetBSD: perform.c,v 1.35 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,11 +7,14 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
+#if HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
#ifndef lint
#if 0
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp";
#else
-__RCSID("$NetBSD: perform.c,v 1.34 2005/11/05 13:20:09 wiz Exp $");
+__RCSID("$NetBSD: perform.c,v 1.35 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -70,6 +73,8 @@ static int zapLogDir; /* Should we delete LogDir? */
static package_t Plist;
static char *Home;
+static lfile_head_t files;
+
/*
* Some systems such as OpenBSD-3.6 do not provide PRIu64.
* Others such as AIX-4.3.2 have a broken PRIu64 which includes
@@ -219,7 +224,7 @@ pkg_do(const char *pkg, lpkg_head_t *pkgs)
int replacing = 0;
char *where_to;
char dbdir[MaxPathSize];
- const char *exact, *extra1;
+ const char *exact;
FILE *cfile;
int errc, err_prescan;
plist_t *p;
@@ -229,6 +234,8 @@ pkg_do(const char *pkg, lpkg_head_t *pkgs)
int rc;
uint64_t needed;
Boolean is_depoted_pkg = FALSE;
+ lfile_t *lfp;
+ int result;
errc = 0;
zapLogDir = 0;
@@ -289,10 +296,9 @@ pkg_do(const char *pkg, lpkg_head_t *pkgs)
goto bomb;
}
}
- extra1 = CONTENTS_FNAME;
+ LFILE_ADD(&files, lfp, CONTENTS_FNAME);
} else {
/* some values for stdin */
- extra1 = NULL;
sb.st_size = 100000; /* Make up a plausible average size */
}
Home = make_playpen(playpen, sizeof(playpen), sb.st_size * 4);
@@ -300,7 +306,12 @@ pkg_do(const char *pkg, lpkg_head_t *pkgs)
warnx("unable to make playpen for %ld bytes",
(long) (sb.st_size * 4));
where_to = Home;
- if (unpack(pkg, extra1)) {
+ result = unpack(pkg, &files);
+ while ((lfp = TAILQ_FIRST(&files)) != NULL) {
+ TAILQ_REMOVE(&files, lfp, lf_link);
+ free(lfp);
+ }
+ if (result) {
warnx("unable to extract table of contents file from `%s' - not a package?",
pkg);
goto bomb;
@@ -1060,6 +1071,8 @@ pkg_perform(lpkg_head_t *pkgs)
signal(SIGINT, cleanup);
signal(SIGHUP, cleanup);
+ TAILQ_INIT(&files);
+
if (AddMode == SLAVE)
err_cnt = pkg_do(NULL, NULL);
else {
diff --git a/pkgtools/pkg_install/files/create/Makefile.in b/pkgtools/pkg_install/files/create/Makefile.in
index 912dd2be029..80948a65bff 100644
--- a/pkgtools/pkg_install/files/create/Makefile.in
+++ b/pkgtools/pkg_install/files/create/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.11 2004/08/21 06:33:40 jlam Exp $
+# $NetBSD: Makefile.in,v 1.12 2005/11/22 15:44:59 ben Exp $
srcdir= @srcdir@
@@ -11,12 +11,13 @@ man1dir= $(mandir)/man1
cat1dir= $(mandir)/cat1
tar= @tar@
+pax= @pax@
CC= @CC@
CCLD= $(CC)
LIBS= -linstall @LIBS@
CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib
-DEFS= @DEFS@ -DTAR_CMD=\"$(tar)\"
+DEFS= @DEFS@ -DTAR_CMD=\"$(tar)\" -DPAX_CMD=\"$(pax)\"
CFLAGS= @CFLAGS@
LDFLAGS= @LDFLAGS@ -L../lib
diff --git a/pkgtools/pkg_install/files/create/perform.c b/pkgtools/pkg_install/files/create/perform.c
index 5b6ceb56dfa..aa01a188200 100644
--- a/pkgtools/pkg_install/files/create/perform.c
+++ b/pkgtools/pkg_install/files/create/perform.c
@@ -1,4 +1,4 @@
-/* $NetBSD: perform.c,v 1.9 2005/11/07 22:57:48 wiz Exp $ */
+/* $NetBSD: perform.c,v 1.10 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -11,7 +11,7 @@
#if 0
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp";
#else
-__RCSID("$NetBSD: perform.c,v 1.9 2005/11/07 22:57:48 wiz Exp $");
+__RCSID("$NetBSD: perform.c,v 1.10 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -52,6 +52,7 @@ __RCSID("$NetBSD: perform.c,v 1.9 2005/11/07 22:57:48 wiz Exp $");
#endif
static char *Home;
+void cleanup_callback(void);
static void
make_dist(const char *home, const char *pkg, const char *suffix, const package_t *plist)
@@ -61,9 +62,8 @@ make_dist(const char *home, const char *pkg, const char *suffix, const package_t
int ret;
char *args[50]; /* Much more than enough. */
int nargs = 1;
- int pipefds[2];
FILE *totar;
- pid_t pid;
+ pipe_to_system_t *to_pipe;
if ((args[0] = strrchr(TAR_CMD, '/')) == NULL)
args[0] = TAR_CMD;
@@ -93,30 +93,8 @@ make_dist(const char *home, const char *pkg, const char *suffix, const package_t
args[nargs++] = "-"; /* Use stdin for the file. */
args[nargs] = NULL;
- /* Set up a pipe for passing the filenames, and fork off a tar process. */
- if (pipe(pipefds) == -1) {
- cleanup(0);
- errx(2, "cannot create pipe");
- }
- if ((pid = fork()) == -1) {
- cleanup(0);
- errx(2, "cannot fork process for %s", TAR_CMD);
- }
- if (pid == 0) { /* The child */
- dup2(pipefds[0], 0);
- close(pipefds[0]);
- close(pipefds[1]);
- execvp(TAR_CMD, args);
- cleanup(0);
- errx(2, "failed to execute %s command", TAR_CMD);
- }
-
- /* Meanwhile, back in the parent process ... */
- close(pipefds[0]);
- if ((totar = fdopen(pipefds[1], "w")) == NULL) {
- cleanup(0);
- errx(2, "fdopen failed");
- }
+ to_pipe = pipe_to_system_begin(TAR_CMD, args, cleanup_callback);
+ totar = to_pipe->fp;
fprintf(totar, "%s\n", CONTENTS_FNAME);
fprintf(totar, "%s\n", COMMENT_FNAME);
@@ -173,8 +151,7 @@ make_dist(const char *home, const char *pkg, const char *suffix, const package_t
}
}
- fclose(totar);
- waitpid(-1, &ret, 0);
+ ret = pipe_to_system_end(to_pipe);
/* assume either signal or bad exit is enough for us */
if (ret) {
cleanup(0);
@@ -199,6 +176,14 @@ sanity_check(void)
}
}
+/*
+ * Clean up callback for pipe_to_system()
+ */
+void
+cleanup_callback(void)
+{
+ cleanup(0);
+}
/*
* Clean up those things that would otherwise hang around
diff --git a/pkgtools/pkg_install/files/info/perform.c b/pkgtools/pkg_install/files/info/perform.c
index d159c49d636..3a390fe95ce 100644
--- a/pkgtools/pkg_install/files/info/perform.c
+++ b/pkgtools/pkg_install/files/info/perform.c
@@ -1,4 +1,4 @@
-/* $NetBSD: perform.c,v 1.25 2005/11/14 09:42:38 dillo Exp $ */
+/* $NetBSD: perform.c,v 1.26 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,11 +7,14 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
+#if HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
#ifndef lint
#if 0
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.23 1997/10/13 15:03:53 jkh Exp";
#else
-__RCSID("$NetBSD: perform.c,v 1.25 2005/11/14 09:42:38 dillo Exp $");
+__RCSID("$NetBSD: perform.c,v 1.26 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -60,6 +63,8 @@ __RCSID("$NetBSD: perform.c,v 1.25 2005/11/14 09:42:38 dillo Exp $");
static char *Home;
+static lfile_head_t files;
+
static int
pkg_do(char *pkg)
{
@@ -69,7 +74,8 @@ pkg_do(char *pkg)
struct stat sb;
char *cp = NULL;
int code = 0;
- char flist[sizeof(ALL_FNAMES)] = "\0";
+ lfile_t *lfp;
+ int result;
if (IS_URL(pkg)) {
if ((cp = fileGetURL(pkg)) != NULL) {
@@ -117,23 +123,30 @@ pkg_do(char *pkg)
*/
/* Determine which +-files to unpack - not all may be present! */
- strcat(flist, CONTENTS_FNAME); strcat(flist, " ");
- strcat(flist, COMMENT_FNAME); strcat(flist, " ");
- strcat(flist, DESC_FNAME); strcat(flist, " ");
- if (Flags & SHOW_MTREE) { strcat(flist, MTREE_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_BUILD_VERSION) { strcat(flist, BUILD_VERSION_FNAME); strcat(flist, " "); }
- if (Flags & (SHOW_BUILD_INFO|SHOW_BI_VAR)) {
- strcat(flist, BUILD_INFO_FNAME);
- strcat(flist, " ");
- }
- if (Flags & SHOW_PKG_SIZE) { strcat(flist, SIZE_PKG_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_ALL_SIZE) { strcat(flist, SIZE_ALL_FNAME); strcat(flist, " "); }
+ LFILE_ADD(&files, lfp, CONTENTS_FNAME);
+ LFILE_ADD(&files, lfp, COMMENT_FNAME);
+ LFILE_ADD(&files, lfp, DESC_FNAME);
+ if (Flags & SHOW_MTREE)
+ LFILE_ADD(&files, lfp, MTREE_FNAME);
+ if (Flags & SHOW_BUILD_VERSION)
+ LFILE_ADD(&files, lfp, BUILD_VERSION_FNAME);
+ if (Flags & SHOW_BUILD_INFO)
+ LFILE_ADD(&files, lfp, BUILD_INFO_FNAME);
+ if (Flags & SHOW_PKG_SIZE)
+ LFILE_ADD(&files, lfp, SIZE_PKG_FNAME);
+ if (Flags & SHOW_ALL_SIZE)
+ LFILE_ADD(&files, lfp, SIZE_ALL_FNAME);
#if 0
- if (Flags & SHOW_REQBY) { strcat(flist, REQUIRED_BY_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_DISPLAY) { strcat(flist, DISPLAY_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_INSTALL) { strcat(flist, INSTALL_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_DEINSTALL) { strcat(flist, DEINSTALL_FNAME); strcat(flist, " "); }
- if (Flags & SHOW_REQUIRE) { strcat(flist, REQUIRE_FNAME); strcat(flist, " "); }
+ if (Flags & SHOW_REQBY)
+ LFILE_ADD(&files, lfp, REQUIRED_BY_FNAME);
+ if (Flags & SHOW_DISPLAY)
+ LFILE_ADD(&files, lfp, DISPLAY_FNAME);
+ if (Flags & SHOW_INSTALL)
+ LFILE_ADD(&files, lfp, INSTALL_FNAME);
+ if (Flags & SHOW_DEINSTALL)
+ LFILE_ADD(&files, lfp, DEINSTALL_FNAME);
+ if (Flags & SHOW_REQUIRE)
+ LFILE_ADD(&files, lfp, REQUIRE_FNAME);
/* PRESERVE_FNAME? */
#endif
@@ -143,7 +156,12 @@ pkg_do(char *pkg)
goto bail;
}
Home = make_playpen(PlayPen, PlayPenSize, sb.st_size / 2);
- if (unpack(fname, flist)) {
+ result = unpack(fname, &files);
+ while ((lfp = TAILQ_FIRST(&files)) != NULL) {
+ TAILQ_REMOVE(&files, lfp, lf_link);
+ free(lfp);
+ }
+ if (result) {
warnx("error during unpacking, no info for '%s' available", pkg);
code = 1;
goto bail;
@@ -378,6 +396,8 @@ pkg_perform(lpkg_head_t *pkghead)
signal(SIGINT, cleanup);
+ TAILQ_INIT(&files);
+
dbdir = _pkgdb_getPKGDB_DIR();
/* Overriding action? */
diff --git a/pkgtools/pkg_install/files/lib/Makefile.in b/pkgtools/pkg_install/files/lib/Makefile.in
index 58535ed8da2..05f0a184f1a 100644
--- a/pkgtools/pkg_install/files/lib/Makefile.in
+++ b/pkgtools/pkg_install/files/lib/Makefile.in
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.in,v 1.10 2005/11/14 09:17:40 dillo Exp $
+# $NetBSD: Makefile.in,v 1.11 2005/11/22 15:44:59 ben Exp $
srcdir= @srcdir@
@@ -17,7 +17,7 @@ CFLAGS= @CFLAGS@
LIB= libinstall.a
OBJS= automatic.o dewey.o fexec.o file.o ftpio.o global.o lpkg.o path.o pen.o \
- pkgdb.o plist.o str.o var.o version.o
+ pexec.o pkgdb.o plist.o str.o var.o version.o
all: $(LIB)
diff --git a/pkgtools/pkg_install/files/lib/fexec.c b/pkgtools/pkg_install/files/lib/fexec.c
index 94810825656..2a29b63cc9b 100644
--- a/pkgtools/pkg_install/files/lib/fexec.c
+++ b/pkgtools/pkg_install/files/lib/fexec.c
@@ -65,11 +65,46 @@
#include "lib.h"
#ifndef lint
-__RCSID("$NetBSD: fexec.c,v 1.5 2003/10/29 23:00:28 jlam Exp $");
+__RCSID("$NetBSD: fexec.c,v 1.6 2005/11/22 15:44:59 ben Exp $");
#endif
static int vfcexec(const char *, int, const char *, va_list);
+/*
+ * fork, then change current working directory to path and
+ * execute the command and arguments in the argv array.
+ * wait for the command to finish, then return the exit status.
+ */
+int
+pfcexec(const char *path, const char **argv)
+{
+ pid_t child;
+ int status;
+
+ child = vfork();
+ switch (child) {
+ case 0:
+ if ((path != NULL) && (chdir(path) < 0))
+ _exit(127);
+
+ (void) execvp(argv[0], (char ** const)argv);
+ _exit(127);
+ /* NOTREACHED */
+ case -1:
+ return -1;
+ }
+
+ while (waitpid(child, &status, 0) < 0) {
+ if (errno != EINTR)
+ return -1;
+ }
+
+ if (!WIFEXITED(status))
+ return -1;
+
+ return WEXITSTATUS(status);
+}
+
static int
vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
{
@@ -113,28 +148,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap)
argv[argc++] = arg;
} while (arg != NULL);
- child = vfork();
- switch (child) {
- case 0:
- if ((path != NULL) && (chdir(path) < 0))
- _exit(127);
-
- (void) execvp(argv[0], (char ** const)argv);
- _exit(127);
- /* NOTREACHED */
- case -1:
- return -1;
- }
-
- while (waitpid(child, &status, 0) < 0) {
- if (errno != EINTR)
- return -1;
- }
-
- if (!WIFEXITED(status))
- return -1;
-
- return WEXITSTATUS(status);
+ return pfcexec(path, argv);
}
int
diff --git a/pkgtools/pkg_install/files/lib/file.c b/pkgtools/pkg_install/files/lib/file.c
index 5b97fbacf2a..746cdffec1b 100644
--- a/pkgtools/pkg_install/files/lib/file.c
+++ b/pkgtools/pkg_install/files/lib/file.c
@@ -1,4 +1,4 @@
-/* $NetBSD: file.c,v 1.14 2005/02/04 09:10:13 jlam Exp $ */
+/* $NetBSD: file.c,v 1.15 2005/11/22 15:44:59 ben Exp $ */
#if HAVE_CONFIG_H
#include "config.h"
@@ -7,11 +7,17 @@
#if HAVE_SYS_CDEFS_H
#include <sys/cdefs.h>
#endif
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_SYS_QUEUE_H
+#include <sys/queue.h>
+#endif
#ifndef lint
#if 0
static const char *rcsid = "from FreeBSD Id: file.c,v 1.29 1997/10/08 07:47:54 charnier Exp";
#else
-__RCSID("$NetBSD: file.c,v 1.14 2005/02/04 09:10:13 jlam Exp $");
+__RCSID("$NetBSD: file.c,v 1.15 2005/11/22 15:44:59 ben Exp $");
#endif
#endif
@@ -616,13 +622,23 @@ remove_files(const char *path, const char *pattern)
* Unpack a tar file
*/
int
-unpack(const char *pkg, const char *flist)
+unpack(const char *pkg, const lfile_head_t *filesp)
{
- char args[10] = "-";
char cmd[MaxPathSize];
const char *decompress_cmd = NULL;
const char *suf;
-
+ int count = 0;
+ lfile_t *lfp;
+ char **up_argv;
+ int up_argc = 7;
+ int index = 0;
+ int result;
+
+ if (filesp != NULL)
+ TAILQ_FOREACH(lfp, filesp, lf_link)
+ count++;
+ up_argc += count;
+ up_argv = malloc((count + up_argc + 1) * sizeof(char *));
if (!IS_STDIN(pkg)) {
suf = suffix_of(pkg);
if (!strcmp(suf, "tbz") || !strcmp(suf, "bz2"))
@@ -636,16 +652,34 @@ unpack(const char *pkg, const char *flist)
} else
decompress_cmd = GZIP_CMD;
- strlcat(args, "xpf", sizeof(args));
- sprintf(cmd, "%s %s %s %s %s %s %s", TAR_CMD,
- flist ? "--fast-read" : "",
- decompress_cmd != NULL ? "--use-compress-program" : "",
- decompress_cmd != NULL ? decompress_cmd : "", args, pkg,
- flist ? flist : "");
+ up_argv[index] = strrchr(TAR_CMD, '/');
+ if (up_argv[index] == NULL)
+ up_argv[index] = TAR_CMD;
+ else
+ up_argv[index]++; /* skip / character */
+ if (count > 0)
+ up_argv[++index] = "--fast-read";
+ if (decompress_cmd != NULL) {
+ up_argv[++index] = "--use-compress-program";
+ up_argv[++index] = (char *)decompress_cmd;
+ }
+ up_argv[++index] = "-xpf";
+ up_argv[++index] = (char *)pkg;
+ if (count > 0)
+ TAILQ_FOREACH(lfp, filesp, lf_link)
+ up_argv[++index] = lfp->lf_name;
+ up_argv[++index] = NULL;
+
+ if (Verbose) {
+ printf("running: %s", TAR_CMD);
+ for (index = 1; up_argv[index] != NULL; index++)
+ printf(" %s", up_argv[index]);
+ printf("\n");
+ }
- if (Verbose)
- printf("running: %s\n", cmd);
- if (system(cmd) != 0) {
+ result = pfcexec(NULL, (const char **)up_argv);
+ free(up_argv);
+ if (result != 0) {
warnx("extract of %s failed", pkg);
return 1;
}
diff --git a/pkgtools/pkg_install/files/lib/lib.h b/pkgtools/pkg_install/files/lib/lib.h
index 88bbb73d8ec..a0a397130cc 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.17 2005/11/05 13:20:09 wiz Exp $ */
+/* $NetBSD: lib.h,v 1.18 2005/11/22 15:44:59 ben Exp $ */
/* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */
@@ -255,6 +255,19 @@ enum {
LegibleChecksumLen = 33
};
+/* List of files */
+typedef struct _lfile_t {
+ TAILQ_ENTRY(_lfile_t) lf_link;
+ char *lf_name;
+} lfile_t;
+TAILQ_HEAD(_lfile_head_t, _lfile_t);
+typedef struct _lfile_head_t lfile_head_t;
+#define LFILE_ADD(lfhead,lfp,str) do { \
+ lfp = malloc(sizeof(lfile_t)); \
+ lfp->lf_name = str; \
+ TAILQ_INSERT_TAIL(lfhead,lfp,lf_link); \
+ } while(0)
+
/* List of packages */
typedef struct _lpkg_t {
TAILQ_ENTRY(_lpkg_t) lp_link;
@@ -267,6 +280,14 @@ typedef struct _lpkg_head_t lpkg_head_t;
* is currently ignored */
typedef int (*matchfn) (const char *, void *);
+/* This structure describes a pipe to a child process */
+typedef struct {
+ int fds[2]; /* pipe, 0=child stdin, 1=parent output */
+ FILE *fp; /* output from parent process */
+ pid_t pid; /* process id of child process */
+ void (*cleanup)(void); /* called on non-zero child exit status */
+} pipe_to_system_t;
+
/* If URLlength()>0, then there is a ftp:// or http:// in the string,
* and this must be an URL. Hide this behind a more obvious name. */
#define IS_URL(str) (URLlength(str) > 0)
@@ -287,6 +308,9 @@ void show_version(void);
int fexec(const char *, ...);
int fexec_skipempty(const char *, ...);
int fcexec(const char *, const char *, ...);
+int pfcexec(const char *path, const char **argv);
+pipe_to_system_t *pipe_to_system_begin(const char *, char *const *, void (*)(void));
+int pipe_to_system_end(pipe_to_system_t *);
/* variables file handling */
@@ -337,7 +361,7 @@ void move_file(char *, char *, char *);
void move_files(const char *, const char *, const char *);
void remove_files(const char *, const char *);
int delete_hierarchy(char *, Boolean, Boolean);
-int unpack(const char *, const char *);
+int unpack(const char *, const lfile_head_t *);
void format_cmd(char *, size_t, char *, char *, char *);
/* ftpio.c: FTP handling */
diff --git a/pkgtools/pkg_install/files/lib/pexec.c b/pkgtools/pkg_install/files/lib/pexec.c
new file mode 100644
index 00000000000..6277f5b2604
--- /dev/null
+++ b/pkgtools/pkg_install/files/lib/pexec.c
@@ -0,0 +1,93 @@
+#include <sys/wait.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "lib.h"
+
+/*
+ * If the supplied callback is not NULL, then call it.
+ */
+static void call_callback(void (*callback)(void))
+{
+ if (callback != NULL) {
+ callback();
+ }
+}
+
+/*
+ * create pipe, fork and exec file with arguments in argv
+ * child takes stdin from pipe, set up fp for parent to
+ * output to pipe, and return this information.
+ */
+pipe_to_system_t *pipe_to_system_begin(const char *file, char *const argv[],
+ void (*cleanup_callback)(void))
+{
+ pipe_to_system_t *retval;
+
+ retval = malloc(sizeof(pipe_to_system_t));
+ if (retval == NULL) {
+ call_callback(cleanup_callback);
+ errx(2, "can't get pipe space");
+ }
+
+ retval->cleanup = cleanup_callback;
+
+ if (pipe(retval->fds) == -1) {
+ call_callback(retval->cleanup);
+ errx(2, "cannot create pipe");
+ }
+
+ retval->pid = fork();
+ if (retval->pid == -1) {
+ call_callback(retval->cleanup);
+ errx(2, "cannot fork process for %s", file);
+ }
+
+ if (retval->pid == 0) { /* The child */
+ if (retval->fds[0] != 0) {
+ dup2(retval->fds[0], 0);
+ close(retval->fds[0]);
+ }
+ close(retval->fds[1]);
+ execvp(file, argv);
+ warn("failed to execute %s command", file);
+ _exit(2);
+ }
+
+ /* Meanwhile, back in the parent process ... */
+ close(retval->fds[0]);
+ retval->fp = fdopen(retval->fds[1], "w");
+ if (retval->fp == NULL) {
+ call_callback(retval->cleanup);
+ errx(2, "fdopen failed");
+ }
+ return retval;
+}
+
+/*
+ * close pipe and wait for child to exit. on non-zero exit status,
+ * call cleanup callback. return exit status.
+ */
+int pipe_to_system_end(pipe_to_system_t *to_pipe)
+{
+ int status;
+ int wait_ret;
+
+ fclose(to_pipe->fp);
+ wait_ret = waitpid(to_pipe->pid, &status, 0);
+ if (wait_ret < 0) {
+ if (errno != EINTR) {
+ call_callback(to_pipe->cleanup);
+ errx(2, "waitpid returned failure");
+ }
+ }
+ if (!WIFEXITED(status)) {
+ call_callback(to_pipe->cleanup);
+ errx(2, "waitpid: process terminated abnormally");
+ }
+ free(to_pipe);
+ return WEXITSTATUS(status);
+}
diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h
index 12da4101c11..87486a82a6c 100644
--- a/pkgtools/pkg_install/files/lib/version.h
+++ b/pkgtools/pkg_install/files/lib/version.h
@@ -1,4 +1,4 @@
-/* $NetBSD: version.h,v 1.51 2005/11/14 09:42:39 dillo Exp $ */
+/* $NetBSD: version.h,v 1.52 2005/11/22 15:44:59 ben Exp $ */
/*
* Copyright (c) 2001 Thomas Klausner. All rights reserved.
@@ -33,6 +33,6 @@
#ifndef _INST_LIB_VERSION_H_
#define _INST_LIB_VERSION_H_
-#define PKGTOOLS_VERSION "20051114"
+#define PKGTOOLS_VERSION "20051122"
#endif /* _INST_LIB_VERSION_H_ */