Index: head/usr.sbin/pkg_install/add/Makefile =================================================================== --- head/usr.sbin/pkg_install/add/Makefile (revision 17337) +++ head/usr.sbin/pkg_install/add/Makefile (revision 17338) @@ -1,18 +1,18 @@ PROG= pkg_add CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib .if exists(${.OBJDIR}/../lib) LDADD+= -L${.OBJDIR}/../lib -linstall DPADD+= ${.OBJDIR}/../lib/libinstall.a .else LDADD+= -L${.CURDIR}/../lib -linstall DPADD+= ${.CURDIR}/../lib/libinstall.a .endif -LDADD+= -lftpio -DPADD+= ${LIBFTPIO} +LDADD+= -lftpio -lmd +DPADD+= ${LIBFTPIO} ${LIBMD} SRCS= main.c perform.c futil.c extract.c .include Index: head/usr.sbin/pkg_install/add/main.c =================================================================== --- head/usr.sbin/pkg_install/add/main.c (revision 17337) +++ head/usr.sbin/pkg_install/add/main.c (revision 17338) @@ -1,169 +1,168 @@ #ifndef lint -static char *rcsid = "$Id: main.c,v 1.9 1995/11/12 04:55:19 jkh Exp $"; +static char *rcsid = "$Id: main.c,v 1.10 1996/03/12 06:12:36 jkh Exp $"; #endif /* * * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * This is the add module. * */ #include #include "lib.h" #include "add.h" static char Options[] = "hvIRfnp:SMt:"; char *Prefix = NULL; Boolean NoInstall = FALSE; Boolean NoRecord = FALSE; -Boolean Force = FALSE; char *Mode = NULL; char *Owner = NULL; char *Group = NULL; char *PkgName = NULL; char *Directory = NULL; char FirstPen[FILENAME_MAX]; add_mode_t AddMode = NORMAL; #define MAX_PKGS 20 char pkgnames[MAX_PKGS][MAXPATHLEN]; char *pkgs[MAX_PKGS]; int main(int argc, char **argv) { int ch, err; char **start; char *prog_name = argv[0], *cp; start = argv; while ((ch = getopt(argc, argv, Options)) != EOF) { switch(ch) { case 'v': Verbose = TRUE; break; case 'p': Prefix = optarg; break; case 'I': NoInstall = TRUE; break; case 'R': NoRecord = TRUE; break; case 'f': Force = TRUE; break; case 'n': Fake = TRUE; Verbose = TRUE; break; case 't': strcpy(FirstPen, optarg); break; case 'S': AddMode = SLAVE; break; case 'M': AddMode = MASTER; break; case 'h': case '?': default: usage(prog_name, NULL); break; } } argc -= optind; argv += optind; if (argc > MAX_PKGS) { whinge("Too many packages (max %d).", MAX_PKGS); return(1); } if (AddMode != SLAVE) { for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ; /* Get all the remaining package names, if any */ for (ch = 0; *argv; ch++, argv++) { if (!strcmp(*argv, "-")) /* stdin? */ pkgs[ch] = "-"; else if (isURL(*argv)) /* preserve URLs */ pkgs[ch] = strcpy(pkgnames[ch], *argv); else { /* expand all pathnames to fullnames */ if (fexists(*argv)) /* refers to a file directly */ pkgs[ch] = realpath(*argv, pkgnames[ch]); else { /* look for the file in the expected places */ if (!(cp = fileFindByPath(NULL, *argv))) whinge("Can't find package '%s'.", *argv); else pkgs[ch] = strcpy(pkgnames[ch], cp); } } } } /* If no packages, yelp */ else if (!ch) usage(prog_name, "Missing package name(s)"); else if (ch > 1 && AddMode == MASTER) usage(prog_name, "Only one package name may be specified with master mode"); if ((err = pkg_perform(pkgs)) != NULL) { if (Verbose) fprintf(stderr, "%d package addition(s) failed.\n", err); return err; } else return 0; } void usage(const char *name, const char *fmt, ...) { va_list args; va_start(args, fmt); if (fmt) { fprintf(stderr, "%s: ", name); vfprintf(stderr, fmt, args); fprintf(stderr, "\n\n"); } va_end(args); fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name); fprintf(stderr, "Where args are one or more of:\n\n"); fprintf(stderr, "-v verbose\n"); fprintf(stderr, "-p arg override prefix with arg\n"); fprintf(stderr, "-I don't execute pkg install script, if any\n"); fprintf(stderr, "-R don't record installation (can't delete!)\n"); fprintf(stderr, "-n don't actually install, just show steps\n"); fprintf(stderr, "-t temp use temp as template for mktemp()\n"); fprintf(stderr, "-S run in SLAVE mode\n"); fprintf(stderr, "-M run in MASTER mode\n"); exit(1); } Index: head/usr.sbin/pkg_install/create/Makefile =================================================================== --- head/usr.sbin/pkg_install/create/Makefile (revision 17337) +++ head/usr.sbin/pkg_install/create/Makefile (revision 17338) @@ -1,18 +1,18 @@ PROG= pkg_create CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib .if exists(${.OBJDIR}/../lib) LDADD+= -L${.OBJDIR}/../lib -linstall DPADD+= ${.OBJDIR}/../lib/libinstall.a .else LDADD+= -L${.CURDIR}/../lib -linstall DPADD+= ${.CURDIR}/../lib/libinstall.a .endif -LDADD+= -lftpio -DPADD+= ${LIBFTPIO} +LDADD+= -lftpio -lmd +DPADD+= ${LIBFTPIO} ${LIBMD} SRCS= main.c perform.c pl.c .include Index: head/usr.sbin/pkg_install/create/perform.c =================================================================== --- head/usr.sbin/pkg_install/create/perform.c (revision 17337) +++ head/usr.sbin/pkg_install/create/perform.c (revision 17338) @@ -1,286 +1,281 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.30 1996/03/20 19:05:59 jdp Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.31 1996/06/20 18:33:36 jkh Exp $"; #endif /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * This is the main body of the create module. * */ #include "lib.h" #include "create.h" #include #include #include #include #include static void sanity_check(void); static void make_dist(char *, char *, char *, Package *); static char *home; int pkg_perform(char **pkgs) { char *pkg = *pkgs; /* Only one arg to create */ char *cp; FILE *pkg_in, *fp; Package plist; char *suffix; /* What we tack on to the end of the finished package */ /* Preliminary setup */ sanity_check(); if (Verbose && !PlistOnly) printf("Creating package %s\n", pkg); get_dash_string(&Comment); get_dash_string(&Desc); if (!strcmp(Contents, "-")) pkg_in = stdin; else { pkg_in = fopen(Contents, "r"); if (!pkg_in) barf("Unable to open contents file '%s' for input.", Contents); } plist.head = plist.tail = NULL; /* Break the package name into base and desired suffix (if any) */ if ((cp = rindex(pkg, '.')) != NULL) { suffix = cp + 1; *cp = '\0'; } else suffix = "tgz"; /* Stick the dependencies, if any, at the top */ if (Pkgdeps) { if (Verbose && !PlistOnly) printf("Registering depends:"); while (Pkgdeps) { cp = strsep(&Pkgdeps, " \t\n"); if (*cp) { add_plist(&plist, PLIST_PKGDEP, cp); if (Verbose && !PlistOnly) printf(" %s", cp); } } if (Verbose && !PlistOnly) printf(".\n"); } /* Slurp in the packing list */ read_plist(&plist, pkg_in); /* Prefix should override the packing list */ if (Prefix) { delete_plist(&plist, FALSE, PLIST_CWD, NULL); add_plist_top(&plist, PLIST_CWD, Prefix); } /* * Run down the list and see if we've named it, if not stick in a name * at the top. */ if (find_plist(&plist, PLIST_NAME) == NULL) add_plist_top(&plist, PLIST_NAME, basename_of(pkg)); /* * We're just here for to dump out a revised plist for the FreeBSD ports * hack. It's not a real create in progress. */ if (PlistOnly) { write_plist(&plist, stdout); exit(0); } /* Make a directory to stomp around in */ home = make_playpen(PlayPen, 0); signal(SIGINT, cleanup); signal(SIGHUP, cleanup); /* Make first "real contents" pass over it */ check_list(home, &plist); (void) umask(022); /* make sure gen'ed directories, files don't have group or other write bits. */ /* copy_plist(home, &plist); */ /* mark_plist(&plist); */ /* Now put the release specific items in */ add_plist(&plist, PLIST_CWD, "."); write_file(COMMENT_FNAME, Comment); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, COMMENT_FNAME); write_file(DESC_FNAME, Desc); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, DESC_FNAME); if (Install) { copy_file(home, Install, INSTALL_FNAME); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, INSTALL_FNAME); } if (DeInstall) { copy_file(home, DeInstall, DEINSTALL_FNAME); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME); } if (Require) { copy_file(home, Require, REQUIRE_FNAME); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, REQUIRE_FNAME); } if (Display) { copy_file(home, Display, DISPLAY_FNAME); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, DISPLAY_FNAME); add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME); } if (Mtree) { copy_file(home, Mtree, MTREE_FNAME); add_plist(&plist, PLIST_IGNORE, NULL); add_plist(&plist, PLIST_FILE, MTREE_FNAME); add_plist(&plist, PLIST_MTREE, MTREE_FNAME); } - - /* Run through the list again, picking up extra "local" items */ - /* check_list(".", &plist); */ - /* copy_plist(".", &plist); */ - /* mark_plist(&plist); */ /* Finally, write out the packing list */ fp = fopen(CONTENTS_FNAME, "w"); if (!fp) barf("Can't open file %s for writing.", CONTENTS_FNAME); write_plist(&plist, fp); if (fclose(fp)) barf("Error while closing %s.", CONTENTS_FNAME); /* And stick it into a tar ball */ make_dist(home, pkg, suffix, &plist); /* Cleanup */ free(Comment); free(Desc); free_plist(&plist); cleanup(0); return TRUE; /* Success */ } static void make_dist(char *home, char *pkg, char *suffix, Package *plist) { char tball[FILENAME_MAX]; PackingList p; int ret; char *args[50]; /* Much more than enough. */ int nargs = 0; int pipefds[2]; FILE *totar; pid_t pid; args[nargs++] = "tar"; /* argv[0] */ if (*pkg == '/') snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suffix); else snprintf(tball, FILENAME_MAX, "%s/%s.%s", home, pkg, suffix); args[nargs++] = "-c"; args[nargs++] = "-f"; args[nargs++] = tball; if (index(suffix, 'z')) /* Compress/gzip? */ args[nargs++] = "-z"; if (Dereference) args[nargs++] = "-h"; if (ExcludeFrom) { args[nargs++] = "-X"; args[nargs++] = ExcludeFrom; } args[nargs++] = "-T"; /* Take filenames from file instead of args. */ args[nargs++] = "-"; /* Use stdin for the file. */ args[nargs] = NULL; if (Verbose) printf("Creating gzip'd tar ball in '%s'\n", tball); /* Set up a pipe for passing the filenames, and fork off a tar process. */ if (pipe(pipefds) == -1) barf("Cannot create pipe: %s", strerror(errno)); if ((pid = fork()) == -1) barf("Cannot fork process for tar: %s", strerror(errno)); if (pid == 0) { /* The child */ dup2(pipefds[0], 0); close(pipefds[0]); close(pipefds[1]); execv("/usr/bin/tar", args); barf("Failed to execute tar command: %s", strerror(errno)); } /* Meanwhile, back in the parent process ... */ close(pipefds[0]); if ((totar = fdopen(pipefds[1], "w")) == NULL) barf("fdopen failed: %s", strerror(errno)); fprintf(totar, "%s\n", CONTENTS_FNAME); fprintf(totar, "%s\n", COMMENT_FNAME); fprintf(totar, "%s\n", DESC_FNAME); if (Install) fprintf(totar, "%s\n", INSTALL_FNAME); if (DeInstall) fprintf(totar, "%s\n", DEINSTALL_FNAME); if (Require) fprintf(totar, "%s\n", REQUIRE_FNAME); if (Display) fprintf(totar, "%s\n", DISPLAY_FNAME); if (Mtree) fprintf(totar, "%s\n", MTREE_FNAME); for (p = plist->head; p; p = p->next) { if (p->type == PLIST_FILE) fprintf(totar, "%s\n", p->name); else if (p->type == PLIST_CWD || p->type == PLIST_SRC) fprintf(totar, "-C\n%s\n", p->name); else if (p->type == PLIST_IGNORE) p = p->next; } fclose(totar); wait(&ret); /* assume either signal or bad exit is enough for us */ if (ret) barf("tar command failed with code %d", ret); } static void sanity_check() { if (!Comment) barf("Required package comment string is missing (-c comment)."); if (!Desc) barf("Required package description string is missing (-d desc)."); if (!Contents) barf("Required package contents list is missing (-f [-]file)."); } /* Clean up those things that would otherwise hang around */ void cleanup(int sig) { leave_playpen(home); } Index: head/usr.sbin/pkg_install/create/pl.c =================================================================== --- head/usr.sbin/pkg_install/create/pl.c (revision 17337) +++ head/usr.sbin/pkg_install/create/pl.c (revision 17338) @@ -1,216 +1,218 @@ #ifndef lint -static const char *rcsid = "$Id: pl.c,v 1.6 1994/12/06 00:51:38 jkh Exp $"; +static const char *rcsid = "$Id: pl.c,v 1.7 1995/05/30 03:49:56 rgrimes Exp $"; #endif /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * Routines for dealing with the packing list. * */ #include "lib.h" #include "create.h" #include +#include /* Check a list for files that require preconversion */ void check_list(char *home, Package *pkg) { - char cmd[FILENAME_MAX]; - char name[FILENAME_MAX]; char *where = home; char *there = NULL; PackingList p = pkg->head; while (p) { if (p->type == PLIST_CWD) where = p->name; else if (p->type == PLIST_IGNORE) p = p->next; else if (p->type == PLIST_SRC) { there = p->name; } else if (p->type == PLIST_FILE) { - cmd[0] = '\0'; + char *cp, name[FILENAME_MAX], buf[33]; + sprintf(name, "%s/%s", there ? there : where, p->name); + if ((cp = MD5File(name, buf)) != NULL) { + PackingList tmp = new_plist_entry(); - if (*cmd) { - if (Verbose) - printf("Uncompressing-> %s\n", cmd); - if (system(cmd)) - barf("%s failed!", cmd); - nuke_suffix(p->name); + tmp->name = copy_string(strconcat("MD5:", cp)); + tmp->type = PLIST_COMMENT; + tmp->next = p->next; + tmp->prev = p; + p->next = tmp; + p = tmp; } } p = p->next; } } static int trylink(const char *from, const char *to) { if (link(from, to) == 0) return 0; if (errno == ENOENT) { /* try making the container directory */ char *cp = strrchr(to, '/'); if (cp) vsystem("mkdir -p %.*s", cp - to, to); return link(from, to); } return -1; } #define STARTSTRING "tar cf -" #define TOOBIG(str) strlen(str) + 6 + strlen(home) + where_count > maxargs #define PUSHOUT() /* push out string */ \ if (where_count > sizeof(STARTSTRING)-1) { \ strcat(where_args, "|tar xpf -"); \ if (system(where_args)) \ barf("can't invoke tar pipeline"); \ memset(where_args, 0, maxargs); \ last_chdir = NULL; \ strcpy(where_args, STARTSTRING); \ where_count = sizeof(STARTSTRING)-1; \ } /* * Copy unmarked files in packing list to playpen - marked files * have already been copied in an earlier pass through the list. */ void copy_plist(char *home, Package *plist) { PackingList p = plist->head; char *where = home; char *there = NULL, *mythere; char *where_args, *last_chdir, *root = "/"; int maxargs, where_count = 0, add_count; struct stat stb; dev_t curdir; maxargs = sysconf(_SC_ARG_MAX); maxargs -= 64; /* some slop for the tar cmd text, and sh -c */ where_args = malloc(maxargs); if (!where_args) barf("can't get argument list space"); memset(where_args, 0, maxargs); strcpy(where_args, STARTSTRING); where_count = sizeof(STARTSTRING)-1; last_chdir = 0; if (stat(".", &stb) == 0) curdir = stb.st_dev; else curdir = (dev_t) -1; /* It's ok if this is a valid dev_t; this is just a hint for an optimization. */ while (p) { if (p->type == PLIST_CWD) where = p->name; else if (p->type == PLIST_SRC) there = p->name; else if (p->type == PLIST_IGNORE) p = p->next; else if (p->type == PLIST_FILE && !p->marked) { char fn[FILENAME_MAX]; /* First, look for it in the "home" dir */ sprintf(fn, "%s/%s", home, p->name); if (fexists(fn)) { if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && S_ISREG(stb.st_mode)) { /* if we can link it to the playpen, that avoids a copy and saves time. */ if (p->name[0] != '/') { /* don't link abspn stuff--it doesn't come from local dir! */ if (trylink(fn, p->name) == 0) { p = p->next; continue; } } } if (TOOBIG(fn)) { PUSHOUT(); } if (p->name[0] == '/') { add_count = snprintf(&where_args[where_count], maxargs - where_count, " %s %s", last_chdir == root ? "" : "-C /", p->name); last_chdir = root; } else { add_count = snprintf(&where_args[where_count], maxargs - where_count, " %s%s %s", last_chdir == home ? "" : "-C ", last_chdir == home ? "" : home, p->name); last_chdir = home; } if (add_count > maxargs - where_count) barf("oops, miscounted strings!"); where_count += add_count; } /* * Otherwise, try along the actual extraction path.. */ else { if (p->name[0] == '/') mythere = root; else mythere = there; sprintf(fn, "%s/%s", mythere ? mythere : where, p->name); if (lstat(fn, &stb) == 0 && stb.st_dev == curdir && S_ISREG(stb.st_mode)) { /* if we can link it to the playpen, that avoids a copy and saves time. */ if (trylink(fn, p->name) == 0) { p = p->next; continue; } } if (TOOBIG(p->name)) { PUSHOUT(); } if (last_chdir == (mythere ? mythere : where)) add_count = snprintf(&where_args[where_count], maxargs - where_count, " %s", p->name); else add_count = snprintf(&where_args[where_count], maxargs - where_count, " -C %s %s", mythere ? mythere : where, p->name); if (add_count > maxargs - where_count) barf("oops, miscounted strings!"); where_count += add_count; last_chdir = (mythere ? mythere : where); } } p = p->next; } PUSHOUT(); free(where_args); } Index: head/usr.sbin/pkg_install/delete/Makefile =================================================================== --- head/usr.sbin/pkg_install/delete/Makefile (revision 17337) +++ head/usr.sbin/pkg_install/delete/Makefile (revision 17338) @@ -1,17 +1,17 @@ PROG= pkg_delete CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib .if exists(${.OBJDIR}/../lib) LDADD+= -L${.OBJDIR}/../lib -linstall DPADD+= ${.OBJDIR}/../lib/libinstall.a .else LDADD+= -L${.CURDIR}/../lib -linstall DPADD+= ${.CURDIR}/../lib/libinstall.a .endif -LDADD+= -lftpio -DPADD+= ${LIBFTPIO} +LDADD+= -lftpio -lmd +DPADD+= ${LIBFTPIO} ${LIBMD} SRCS= main.c perform.c .include Index: head/usr.sbin/pkg_install/delete/main.c =================================================================== --- head/usr.sbin/pkg_install/delete/main.c (revision 17337) +++ head/usr.sbin/pkg_install/delete/main.c (revision 17338) @@ -1,124 +1,123 @@ #ifndef lint -static char *rcsid = "$Id: main.c,v 1.4 1995/05/30 03:49:57 rgrimes Exp $"; +static char *rcsid = "$Id: main.c,v 1.5 1996/06/20 18:33:43 jkh Exp $"; #endif /* * * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * This is the delete module. * */ #include "lib.h" #include "delete.h" #include static char Options[] = "hvDdnfp:"; char *Prefix = NULL; Boolean NoDeInstall = FALSE; Boolean CleanDirs = FALSE; -Boolean Force = FALSE; int main(int argc, char **argv) { int ch, error; char **pkgs, **start; char *prog_name = argv[0]; pkgs = start = argv; while ((ch = getopt(argc, argv, Options)) != EOF) switch(ch) { case 'v': Verbose = TRUE; break; case 'f': Force = TRUE; break; case 'p': Prefix = optarg; break; case 'D': NoDeInstall = TRUE; break; case 'd': CleanDirs = TRUE; break; case 'n': Fake = TRUE; Verbose = TRUE; break; case 'h': case '?': default: usage(prog_name, NULL); break; } argc -= optind; argv += optind; /* Get all the remaining package names, if any */ /* Get all the remaining package names, if any */ while (*argv) *pkgs++ = *argv++; /* If no packages, yelp */ if (pkgs == start) usage(prog_name, "Missing package name(s)"); *pkgs = NULL; if (!Fake && getuid() != 0) errx(1, "You must be root to delete packages."); if ((error = pkg_perform(start)) != NULL) { if (Verbose) fprintf(stderr, "%d package deletion(s) failed.\n", error); return error; } else return 0; } void usage(const char *name, const char *fmt, ...) { va_list args; va_start(args, fmt); if (fmt) { fprintf(stderr, "%s: ", name); vfprintf(stderr, fmt, args); fprintf(stderr, "\n\n"); } va_end(args); fprintf(stderr, "Usage: %s [args] pkg [ .. pkg ]\n", name); fprintf(stderr, "Where args are one or more of:\n\n"); fprintf(stderr, "-v verbose\n"); fprintf(stderr, "-p arg override prefix with arg\n"); fprintf(stderr, "-d delete empty directories when deinstalling\n"); fprintf(stderr, "-f force delete even if dependencies exist\n"); fprintf(stderr, " or deinstall/requirement checks fail\n"); fprintf(stderr, "-D don't execute pkg de-install script, if any\n"); fprintf(stderr, "-n don't actually de-install, just show steps\n"); exit(1); } Index: head/usr.sbin/pkg_install/delete/perform.c =================================================================== --- head/usr.sbin/pkg_install/delete/perform.c (revision 17337) +++ head/usr.sbin/pkg_install/delete/perform.c (revision 17338) @@ -1,212 +1,212 @@ #ifndef lint -static const char *rcsid = "$Id: perform.c,v 1.8 1995/11/12 04:55:30 jkh Exp $"; +static const char *rcsid = "$Id: perform.c,v 1.9 1996/06/20 18:33:44 jkh Exp $"; #endif /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * This is the main body of the delete module. * */ #include "lib.h" #include "delete.h" static int pkg_do(char *); static void sanity_check(char *); static void undepend(PackingList, char *); static char LogDir[FILENAME_MAX]; int pkg_perform(char **pkgs) { int i, err_cnt = 0; for (i = 0; pkgs[i]; i++) err_cnt += pkg_do(pkgs[i]); return err_cnt; } static Package Plist; /* This is seriously ugly code following. Written very fast! */ static int pkg_do(char *pkg) { FILE *cfile; char home[FILENAME_MAX]; PackingList p; char *tmp; /* Reset some state */ if (Plist.head) free_plist(&Plist); sprintf(LogDir, "%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, pkg); if (!fexists(LogDir)) { whinge("No such package '%s' installed.", pkg); return 1; } if (!getcwd(home, FILENAME_MAX)) barf("Unable to get current working directory!"); if (chdir(LogDir) == FAIL) { whinge("Unable to change directory to %s! Deinstall failed.", LogDir); return 1; } if (!isemptyfile(REQUIRED_BY_FNAME)) { char buf[512]; whinge("Package `%s' is required by these other packages", pkg); whinge("and may not be deinstalled%s:", Force ? " (but I'll delete it anyway)" : "" ); cfile = fopen(REQUIRED_BY_FNAME, "r"); if (cfile) { while (fgets(buf, sizeof(buf), cfile)) fprintf(stderr, "%s", buf); fclose(cfile); } else whinge("cannot open requirements file `%s'", REQUIRED_BY_FNAME); if (!Force) return 1; } sanity_check(LogDir); cfile = fopen(CONTENTS_FNAME, "r"); if (!cfile) { whinge("Unable to open '%s' file.", CONTENTS_FNAME); return 1; } /* If we have a prefix, add it now */ if (Prefix) add_plist(&Plist, PLIST_CWD, Prefix); read_plist(&Plist, cfile); fclose(cfile); setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : NULL, 1); if (fexists(REQUIRE_FNAME)) { if (Verbose) printf("Executing 'require' script.\n"); vsystem("chmod +x %s", REQUIRE_FNAME); /* be sure */ if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) { whinge("Package %s fails requirements %s", pkg, Force ? "." : "- not deleted."); if (!Force) return 1; } } if (!NoDeInstall && fexists(DEINSTALL_FNAME)) { if (Fake) printf("Would execute de-install script at this point.\n"); else { vsystem("chmod +x %s", DEINSTALL_FNAME); /* make sure */ if (vsystem("./%s %s DEINSTALL", DEINSTALL_FNAME, pkg)) { whinge("De-Install script returned error status."); if (!Force) return 1; } } } if (chdir(home) == FAIL) barf("Toto! This doesn't look like Kansas anymore!"); if (!Fake) { /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */ if (delete_package(FALSE, CleanDirs, &Plist) == FAIL) whinge("Couldn't entirely delete package (perhaps the packing list is\n" "incorrectly specified?)\n"); if (vsystem("%s -r %s", REMOVE_CMD, LogDir)) { whinge("Couldn't remove log entry in %s, de-install failed.", LogDir); - return 1; + if (!Force) + return 1; } } for (p = Plist.head; p ; p = p->next) { if (p->type != PLIST_PKGDEP) continue; if (Verbose) - printf("Attempting to remove dependency on package `%s'\n", - p->name); + printf("Attempting to remove dependency on package `%s'\n", p->name); if (!Fake) undepend(p, pkg); } return 0; } static void sanity_check(char *pkg) { if (!fexists(CONTENTS_FNAME)) barf("Installed package %s has no %s file!", pkg, CONTENTS_FNAME); } void cleanup(int sig) { /* Nothing to do */ } static void undepend(PackingList p, char *pkgname) { char fname[FILENAME_MAX], ftmp[FILENAME_MAX]; char fbuf[FILENAME_MAX]; FILE *fp, *fpwr; char *tmp; int s; sprintf(fname, "%s/%s/%s", (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR, p->name, REQUIRED_BY_FNAME); fp = fopen(fname, "r"); if (fp == NULL) { whinge("Couldn't open dependency file `%s'", fname); return; } sprintf(ftmp, "%s.XXXXXX", fname); s = mkstemp(ftmp); if (s == -1) { fclose(fp); whinge("Couldn't open temp file `%s'", ftmp); return; } fpwr = fdopen(s, "w"); if (fpwr == NULL) { close(s); fclose(fp); whinge("Couldn't fdopen temp file `%s'", ftmp); remove(ftmp); return; } while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { if (fbuf[strlen(fbuf)-1] == '\n') fbuf[strlen(fbuf)-1] = '\0'; if (strcmp(fbuf, pkgname)) /* no match */ fputs(fbuf, fpwr), putc('\n', fpwr); } (void) fclose(fp); if (fchmod(s, 0644) == FAIL) { whinge("Error changing permission of temp file `%s'", ftmp); fclose(fpwr); remove(ftmp); return; } if (fclose(fpwr) == EOF) { whinge("Error closing temp file `%s'", ftmp); remove(ftmp); return; } if (rename(ftmp, fname) == -1) whinge("Error renaming `%s' to `%s'", ftmp, fname); remove(ftmp); /* just in case */ return; } Index: head/usr.sbin/pkg_install/info/Makefile =================================================================== --- head/usr.sbin/pkg_install/info/Makefile (revision 17337) +++ head/usr.sbin/pkg_install/info/Makefile (revision 17338) @@ -1,17 +1,17 @@ PROG= pkg_info CFLAGS+= ${DEBUG} -I${.CURDIR}/../lib .if exists(${.OBJDIR}/../lib) LDADD+= -L${.OBJDIR}/../lib -linstall DPADD+= ${.OBJDIR}/../lib/libinstall.a .else LDADD+= -L${.CURDIR}/../lib -linstall DPADD+= ${.CURDIR}/../lib/libinstall.a .endif -LDADD+= -lftpio -DPADD+= ${LIBFTPIO} +LDADD+= -lftpio -lmd +DPADD+= ${LIBFTPIO} ${LIBMD} SRCS= main.c perform.c show.c .include Index: head/usr.sbin/pkg_install/lib/global.c =================================================================== --- head/usr.sbin/pkg_install/lib/global.c (revision 17337) +++ head/usr.sbin/pkg_install/lib/global.c (revision 17338) @@ -1,33 +1,34 @@ #ifndef lint -static const char *rcsid = "$Id: global.c,v 1.1.1.1 1993/08/26 01:19:55 jkh Exp $"; +static const char *rcsid = "$Id: global.c,v 1.2 1994/04/05 14:08:45 jkh Exp $"; #endif /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * Semi-convenient place to stick some needed globals. * */ #include "lib.h" /* These are global for all utils */ Boolean Verbose = FALSE; Boolean Fake = FALSE; +Boolean Force = FALSE; int AutoAnswer = FALSE; Index: head/usr.sbin/pkg_install/lib/lib.h =================================================================== --- head/usr.sbin/pkg_install/lib/lib.h (revision 17337) +++ head/usr.sbin/pkg_install/lib/lib.h (revision 17338) @@ -1,176 +1,177 @@ -/* $Id: lib.h,v 1.20 1996/06/08 00:46:32 alex Exp $ */ +/* $Id: lib.h,v 1.21 1996/06/20 18:33:53 jkh Exp $ */ /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * Include and define various things wanted by the library routines. * */ #ifndef _INST_LIB_LIB_H_ #define _INST_LIB_LIB_H_ /* Includes */ #include #include #include #include #include #include #include #include #include #include /* Macros */ #define SUCCESS (0) #define FAIL (-1) #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #define YES 2 #define NO 1 /* Usually "rm", but often "echo" during debugging! */ #define REMOVE_CMD "rm" /* Usually "rm", but often "echo" during debugging! */ #define RMDIR_CMD "rmdir" /* Where we put logging information by default, else ${PKG_DBDIR} if set */ #define DEF_LOG_DIR "/var/db/pkg" /* just in case we change the environment variable name */ #define PKG_DBDIR "PKG_DBDIR" /* The names of our "special" files */ -#define CONTENTS_FNAME "+CONTENTS" -#define COMMENT_FNAME "+COMMENT" -#define DESC_FNAME "+DESC" -#define INSTALL_FNAME "+INSTALL" -#define DEINSTALL_FNAME "+DEINSTALL" -#define REQUIRE_FNAME "+REQUIRE" +#define CONTENTS_FNAME "+CONTENTS" +#define COMMENT_FNAME "+COMMENT" +#define DESC_FNAME "+DESC" +#define INSTALL_FNAME "+INSTALL" +#define DEINSTALL_FNAME "+DEINSTALL" +#define REQUIRE_FNAME "+REQUIRE" #define REQUIRED_BY_FNAME "+REQUIRED_BY" -#define DISPLAY_FNAME "+DISPLAY" -#define MTREE_FNAME "+MTREE_DIRS" +#define DISPLAY_FNAME "+DISPLAY" +#define MTREE_FNAME "+MTREE_DIRS" -#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ +#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ /* The name of the "prefix" environment variable given to scripts */ #define PKG_PREFIX_VNAME "PKG_PREFIX" enum _plist_t { PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD, - PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, - PLIST_IGNORE, PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY, + PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE, + PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY, PLIST_PKGDEP, PLIST_MTREE, PLIST_DIR_RM, PLIST_IGNORE_INST, PLIST_OPTION }; typedef enum _plist_t plist_t; /* Types */ typedef unsigned int Boolean; struct _plist { struct _plist *prev, *next; char *name; Boolean marked; plist_t type; }; typedef struct _plist *PackingList; struct _pack { struct _plist *head, *tail; }; typedef struct _pack Package; /* Prototypes */ /* Misc */ int vsystem(const char *, ...); void cleanup(int); char *make_playpen(char *, size_t); char *where_playpen(void); void leave_playpen(char *); off_t min_free(char *); /* String */ char *get_dash_string(char **); char *copy_string(char *); Boolean suffix(char *, char *); void nuke_suffix(char *); void str_lowercase(char *); char *basename_of(char *); char *strconcat(char *, char *); /* File */ Boolean fexists(char *); Boolean isdir(char *); Boolean isemptydir(char *fname); Boolean isemptyfile(char *fname); Boolean isfile(char *); Boolean isempty(char *); Boolean isURL(char *); char *fileGetURL(char *, char *); char *fileURLFilename(char *, char *, int); char *fileURLHost(char *, char *, int); char *fileFindByPath(char *, char *); char *fileGetContents(char *); void write_file(char *, char *); void copy_file(char *, char *, char *); void move_file(char *, char *, char *); void copy_hierarchy(char *, char *, Boolean); int delete_hierarchy(char *, Boolean, Boolean); int unpack(char *, char *); void format_cmd(char *, char *, char *, char *); /* Msg */ void upchuck(const char *); void barf(const char *, ...); void whinge(const char *, ...); Boolean y_or_n(Boolean, const char *, ...); /* Packing list */ PackingList new_plist_entry(void); PackingList last_plist(Package *); PackingList find_plist(Package *, plist_t); char *find_plist_option(Package *, char *name); void plist_delete(Package *, Boolean, plist_t, char *); void free_plist(Package *); void mark_plist(Package *); void csum_plist_entry(char *, PackingList); void add_plist(Package *, plist_t, char *); void add_plist_top(Package *, plist_t, char *); void delete_plist(Package *pkg, Boolean all, plist_t type, char *name); void write_plist(Package *, FILE *); void read_plist(Package *, FILE *); int plist_cmd(char *, char **); int delete_package(Boolean, Boolean, Package *); /* For all */ void usage(const char *, const char *, ...); int pkg_perform(char **); /* Externs */ extern Boolean Verbose; extern Boolean Fake; +extern Boolean Force; extern int AutoAnswer; #endif /* _INST_LIB_LIB_H_ */ Index: head/usr.sbin/pkg_install/lib/plist.c =================================================================== --- head/usr.sbin/pkg_install/lib/plist.c (revision 17337) +++ head/usr.sbin/pkg_install/lib/plist.c (revision 17338) @@ -1,447 +1,481 @@ #ifndef lint -static const char *rcsid = "$Id: plist.c,v 1.15 1995/11/12 04:55:40 jkh Exp $"; +static const char *rcsid = "$Id: plist.c,v 1.16 1996/06/20 18:33:55 jkh Exp $"; #endif /* * FreeBSD install - a package for the installation and maintainance * of non-core utilities. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Jordan K. Hubbard * 18 July 1993 * * General packing list routines. * */ #include "lib.h" +#include /* Add an item to a packing list */ void add_plist(Package *p, plist_t type, char *arg) { PackingList tmp; tmp = new_plist_entry(); tmp->name = copy_string(arg); tmp->type = type; if (!p->head) p->head = p->tail = tmp; else { tmp->prev = p->tail; p->tail->next = tmp; p->tail = tmp; } } void add_plist_top(Package *p, plist_t type, char *arg) { PackingList tmp; tmp = new_plist_entry(); tmp->name = copy_string(arg); tmp->type = type; if (!p->head) p->head = p->tail = tmp; else { tmp->next = p->head; p->head->prev = tmp; p->head = tmp; } } /* Return the last (most recent) entry in a packing list */ PackingList last_plist(Package *p) { return p->tail; } /* Mark all items in a packing list to prevent iteration over them */ void mark_plist(Package *pkg) { PackingList p = pkg->head; while (p) { p->marked = TRUE; p = p->next; } } /* Find a given item in a packing list and, if so, return it (else NULL) */ PackingList find_plist(Package *pkg, plist_t type) { PackingList p = pkg->head; while (p) { if (p->type == type) return p; p = p->next; } return NULL; } /* Look for a specific boolean option argument in the list */ char * find_plist_option(Package *pkg, char *name) { PackingList p = pkg->head; while (p) { if (p->type == PLIST_OPTION && !strcmp(p->name, name)) return p->name; p = p->next; } return NULL; } /* * Delete plist item 'type' in the list (if 'name' is non-null, match it * too.) If 'all' is set, delete all items, not just the first occurance. */ void delete_plist(Package *pkg, Boolean all, plist_t type, char *name) { PackingList p = pkg->head; while (p) { PackingList pnext = p->next; if (p->type == type && (!name || !strcmp(name, p->name))) { free(p->name); if (p->prev) p->prev->next = pnext; else pkg->head = pnext; if (pnext) pnext->prev = p->prev; else pkg->tail = p->prev; free(p); if (!all) return; p = pnext; } else p = p->next; } } /* Allocate a new packing list entry */ PackingList new_plist_entry(void) { PackingList ret; ret = (PackingList)malloc(sizeof(struct _plist)); bzero(ret, sizeof(struct _plist)); return ret; } /* Free an entire packing list */ void free_plist(Package *pkg) { PackingList p = pkg->head; while (p) { PackingList p1 = p->next; free(p->name); free(p); p = p1; } pkg->head = pkg->tail = NULL; } /* * For an ascii string denoting a plist command, return its code and * optionally its argument(s) */ int plist_cmd(char *s, char **arg) { char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */ char *cp, *sp; strcpy(cmd, s); str_lowercase(cmd); cp = cmd; sp = s; while (*cp) { if (isspace(*cp)) { *cp = '\0'; while (isspace(*sp)) /* Never sure if macro, increment later */ ++sp; break; } ++cp, ++sp; } if (arg) *arg = sp; if (!strcmp(cmd, "cwd")) return PLIST_CWD; else if (!strcmp(cmd, "srcdir")) return PLIST_SRC; else if (!strcmp(cmd, "cd")) return PLIST_CWD; else if (!strcmp(cmd, "exec")) return PLIST_CMD; else if (!strcmp(cmd, "unexec")) return PLIST_UNEXEC; else if (!strcmp(cmd, "mode")) return PLIST_CHMOD; else if (!strcmp(cmd, "owner")) return PLIST_CHOWN; else if (!strcmp(cmd, "group")) return PLIST_CHGRP; else if (!strcmp(cmd, "comment")) return PLIST_COMMENT; else if (!strcmp(cmd, "ignore")) return PLIST_IGNORE; else if (!strcmp(cmd, "ignore_inst")) return PLIST_IGNORE_INST; else if (!strcmp(cmd, "name")) return PLIST_NAME; else if (!strcmp(cmd, "display")) return PLIST_DISPLAY; else if (!strcmp(cmd, "pkgdep")) return PLIST_PKGDEP; else if (!strcmp(cmd, "mtree")) return PLIST_MTREE; else if (!strcmp(cmd, "dirrm")) return PLIST_DIR_RM; else if (!strcmp(cmd, "option")) return PLIST_OPTION; else return FAIL; } /* Read a packing list from a file */ void read_plist(Package *pkg, FILE *fp) { char *cp, pline[FILENAME_MAX]; int cmd; while (fgets(pline, FILENAME_MAX, fp)) { - int len = strlen(pline) - 1; + int len = strlen(pline); - while (isspace(pline[len])) - pline[len--] = '\0'; - if (len <= 0) + while (len && isspace(pline[len - 1])) + pline[--len] = '\0'; + if (!len) continue; cp = pline; if (pline[0] == CMD_CHAR) { cmd = plist_cmd(pline + 1, &cp); if (cmd == FAIL) barf("Bad command '%s'", pline); if (*cp == '\0') cp = NULL; } else cmd = PLIST_FILE; add_plist(pkg, cmd, cp); } } /* Write a packing list to a file, converting commands to ascii equivs */ void write_plist(Package *pkg, FILE *fp) { PackingList plist = pkg->head; while (plist) { switch(plist->type) { case PLIST_FILE: fprintf(fp, "%s\n", plist->name); break; case PLIST_CWD: fprintf(fp, "%ccwd %s\n", CMD_CHAR, plist->name); break; case PLIST_SRC: fprintf(fp, "%csrcdir %s\n", CMD_CHAR, plist->name); break; case PLIST_CMD: fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name); break; case PLIST_UNEXEC: fprintf(fp, "%cunexec %s\n", CMD_CHAR, plist->name); break; case PLIST_CHMOD: fprintf(fp, "%cmode %s\n", CMD_CHAR, plist->name ? plist->name : ""); break; case PLIST_CHOWN: fprintf(fp, "%cowner %s\n", CMD_CHAR, plist->name ? plist->name : ""); break; case PLIST_CHGRP: fprintf(fp, "%cgroup %s\n", CMD_CHAR, plist->name ? plist->name : ""); break; case PLIST_COMMENT: fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name); break; case PLIST_IGNORE: case PLIST_IGNORE_INST: /* a one-time non-ignored file */ fprintf(fp, "%cignore\n", CMD_CHAR); break; case PLIST_NAME: fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name); break; case PLIST_DISPLAY: fprintf(fp, "%cdisplay %s\n", CMD_CHAR, plist->name); break; case PLIST_PKGDEP: fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name); break; case PLIST_MTREE: fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name); break; case PLIST_DIR_RM: fprintf(fp, "%cdirrm %s\n", CMD_CHAR, plist->name); break; case PLIST_OPTION: fprintf(fp, "%coption %s\n", CMD_CHAR, plist->name); break; default: barf("Unknown command type %d (%s)\n", plist->type, plist->name); break; } plist = plist->next; } } /* * Delete the results of a package installation. * * This is here rather than in the pkg_delete code because pkg_add needs to * run it too in cases of failure. */ int delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) { - PackingList p = pkg->head; + PackingList p; char *Where = ".", *last_file = ""; Boolean fail = SUCCESS; + char tmp[FILENAME_MAX]; - if (!p) - return FAIL; - while (p) { - if (p->type == PLIST_CWD) { + for (p = pkg->head; p; p = p->next) { + switch (p->type) { + case PLIST_IGNORE: + p = p->next; + break; + + case PLIST_CWD: Where = p->name; if (Verbose) printf("Change working directory to %s\n", Where); - } - else if (p->type == PLIST_UNEXEC) { - char cmd[FILENAME_MAX]; + break; - format_cmd(cmd, p->name, Where, last_file); + case PLIST_UNEXEC: + format_cmd(tmp, p->name, Where, last_file); if (Verbose) - printf("Execute `%s'\n", cmd); - if (!Fake && system(cmd)) { - whinge("unexec command for `%s' failed.", cmd); + printf("Execute `%s'\n", tmp); + if (!Fake && system(tmp)) { + whinge("unexec command for `%s' failed.", tmp); fail = FAIL; } - } - else if (p->type == PLIST_IGNORE) - p = p->next; - else if (p->type == PLIST_FILE || p->type == PLIST_DIR_RM) { - char full_name[FILENAME_MAX]; + break; - sprintf(full_name, "%s/%s", Where, p->name); - if (isdir(full_name) && p->type == PLIST_FILE) { + case PLIST_FILE: + sprintf(tmp, "%s/%s", Where, p->name); + if (isdir(tmp)) { whinge("Attempting to delete directory `%s' as a file\n" - "This packing list is incorrect - ignoring delete request.\n", full_name); + "This packing list is incorrect - ignoring delete request.\n", tmp); } else { + if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) { + char *cp, buf[33]; + + if ((cp = MD5File(tmp, buf)) != NULL) { + /* Mismatch? */ + if (strcmp(cp, p->next->name + 4)) { + if (Verbose) + printf("%s fails original MD5 checksum - %s\n", + tmp, Force ? "deleted anyway." : "not deleted."); + if (!Force) { + fail = FAIL; + continue; + } + } + } + } if (Verbose) - printf("Delete %s %s\n", !isdir(full_name) ? "file" : " directory", full_name); + printf("Delete file %s\n", tmp); - if (!Fake && delete_hierarchy(full_name, ign_err, p->type == PLIST_DIR_RM ? FALSE : nukedirs)) { - whinge("Unable to completely remove file '%s'", full_name); + if (!Fake && delete_hierarchy(tmp, ign_err, nukedirs)) { + whinge("Unable to completely remove file '%s'", tmp); fail = FAIL; } } last_file = p->name; + break; + + case PLIST_DIR_RM: + sprintf(tmp, "%s/%s", Where, p->name); + if (!isdir(tmp)) { + whinge("Attempting to delete file `%s' as a directory\n" + "This packing list is incorrect - ignoring delete request.\n", tmp); + } + else { + if (Verbose) + printf("Delete directory %s\n", tmp); + if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) { + whinge("Unable to completely remove directory '%s'", tmp); + fail = FAIL; + } + } + last_file = p->name; + break; } - p = p->next; } return fail; } #ifdef DEBUG #define RMDIR(dir) vsystem("%s %s", RMDIR_CMD, dir) #define REMOVE(dir,ie) vsystem("%s %s%s", REMOVE_CMD, (ie ? "-f " : ""), dir) #else #define RMDIR rmdir #define REMOVE(file,ie) (remove(file) && !(ie)) #endif /* Selectively delete a hierarchy */ int delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) { char *cp1, *cp2; cp1 = cp2 = dir; if (!fexists(dir)) { if (!ign_err) whinge("%s `%s' doesn't really exist.", isdir(dir) ? "Directory" : "File", dir); } else if (nukedirs) { if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir)) return 1; } else if (isdir(dir)) { if (RMDIR(dir) && !ign_err) return 1; } else { if (REMOVE(dir, ign_err)) return 1; } if (!nukedirs) return 0; while (cp2) { if ((cp2 = rindex(cp1, '/')) != NULL) *cp2 = '\0'; if (!isemptydir(dir)) return 0; if (RMDIR(dir) && !ign_err) if (!fexists(dir)) whinge("Directory `%s' doesn't really exist.", dir); else return 1; /* back up the pathname one component */ if (cp2) { cp1 = dir; } } return 0; }