diff options
author | ben <ben@pkgsrc.org> | 2005-11-22 15:44:59 +0000 |
---|---|---|
committer | ben <ben@pkgsrc.org> | 2005-11-22 15:44:59 +0000 |
commit | df7be8ce2f4f055c4ab1e8c23c843f83176cd9ac (patch) | |
tree | 38d3c61e2ba04f9f4e240fbc2a08bd94f821ca61 /pkgtools | |
parent | 86999188667288211b1335b23d71fce848cc2612 (diff) | |
download | pkgsrc-df7be8ce2f4f055c4ab1e8c23c843f83176cd9ac.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')
-rw-r--r-- | pkgtools/pkg_install/files/add/Makefile.in | 4 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/add/add.h | 4 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/add/extract.c | 182 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/add/futil.c | 70 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/add/perform.c | 25 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/create/Makefile.in | 5 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/create/perform.c | 45 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/info/perform.c | 60 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/Makefile.in | 4 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/fexec.c | 60 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/file.c | 62 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/lib.h | 28 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/pexec.c | 93 | ||||
-rw-r--r-- | pkgtools/pkg_install/files/lib/version.h | 4 |
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_ */ |