diff options
author | jkh <jkh@FreeBSD.org> | 1997-06-29 10:41:49 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1997-06-29 10:41:49 +0000 |
commit | 4bb6ae9575ad1b207a84af41097dcd0249b9de7e (patch) | |
tree | b9903527c441fd7785b80009ee38cd263f262eef | |
parent | 4e5976e2979afbe2791f220e6d21e6456590f3c6 (diff) | |
download | FreeBSD-src-4bb6ae9575ad1b207a84af41097dcd0249b9de7e.zip FreeBSD-src-4bb6ae9575ad1b207a84af41097dcd0249b9de7e.tar.gz |
Add support for @option preserve - moves existing files out of the way
before replacing them (using pkgname to make this hopefully unique).
Delete also moves them back, if they exist, resulting in a package
which can be "backed out" with reasonable safety.
-rw-r--r-- | usr.sbin/pkg_install/add/extract.c | 46 | ||||
-rw-r--r-- | usr.sbin/pkg_install/add/perform.c | 7 | ||||
-rw-r--r-- | usr.sbin/pkg_install/lib/plist.c | 29 |
3 files changed, 71 insertions, 11 deletions
diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c index efc8c05..03c7231 100644 --- a/usr.sbin/pkg_install/add/extract.c +++ b/usr.sbin/pkg_install/add/extract.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id: extract.c,v 1.12 1997/02/25 07:22:23 jkh Exp $"; +static const char *rcsid = "$Id: extract.c,v 1.13 1997/05/24 21:45:55 ache Exp $"; #endif /* @@ -45,6 +45,33 @@ static const char *rcsid = "$Id: extract.c,v 1.12 1997/02/25 07:22:23 jkh Exp $" perm_count = 0; \ } +static void +rollback(char *name, char *home, PackingList start, PackingList stop) +{ + PackingList q; + char try[FILENAME_MAX], bup[FILENAME_MAX], *dir; + + dir = home; + for (q = start; q != stop; q = q->next) { + if (q->type == PLIST_FILE) { + snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name); + snprintf(bup, FILENAME_MAX, "%s.%s", try, name); + if (fexists(bup)) { + (void)chflags(try, 0); + (void)unlink(try); + if (rename(bup, try)) + whinge("rollback: unable to rename %s back to %s.", bup, try); + } + } + else if (q->type == PLIST_CWD) { + if (strcmp(q->name, ".")) + dir = q->name; + else + dir = home; + } + } +} + void extract_plist(char *home, Package *pkg) { @@ -52,6 +79,7 @@ extract_plist(char *home, Package *pkg) char *last_file; char *where_args, *perm_args, *last_chdir; int maxargs, where_count = 0, perm_count = 0, add_count; + Boolean preserve; maxargs = sysconf(_SC_ARG_MAX) / 2; /* Just use half the argument space */ where_args = alloca(maxargs); @@ -66,6 +94,7 @@ extract_plist(char *home, Package *pkg) perm_args[0] = 0; last_chdir = 0; + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; /* Reset the world */ Owner = NULL; @@ -94,6 +123,21 @@ extract_plist(char *home, Package *pkg) /* first try to rename it into place */ sprintf(try, "%s/%s", Directory, p->name); + if (preserve) { + char pf[FILENAME_MAX]; + + if (!PkgName) { + whinge("Package set preserve option but has no name - bailing out."); + return; + } + snprintf(pf, FILENAME_MAX, "%s.%s", try, PkgName); + (void)chflags(try, 0); /* XXX hack - if truly immutable, rename fails */ + if (rename(try, pf)) { + whinge("Unable to back up %s to %s, aborting pkg_add", try, pf); + rollback(PkgName, home, pkg->head, p); + return; + } + } if (rename(p->name, try) == 0) { /* try to add to list of perms to be changed and run in bulk. */ if (p->name[0] == '/' || TOOBIG(p->name)) { diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c index 58cf603..dcb0f9e 100644 --- a/usr.sbin/pkg_install/add/perform.c +++ b/usr.sbin/pkg_install/add/perform.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id$"; +static const char *rcsid = "$Id: perform.c,v 1.41 1997/02/22 16:09:20 peter Exp $"; #endif /* @@ -458,11 +458,6 @@ cleanup(int signo) { if (signo) printf("Signal %d received, cleaning up..\n", signo); - if (Plist.head) { - if (!Fake) - delete_package(FALSE, FALSE, &Plist); - free_plist(&Plist); - } if (!Fake && LogDir[0]) vsystem("%s -rf %s", REMOVE_CMD, LogDir); leave_playpen(Home); diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c index 72db68e..5380187 100644 --- a/usr.sbin/pkg_install/lib/plist.c +++ b/usr.sbin/pkg_install/lib/plist.c @@ -1,5 +1,5 @@ #ifndef lint -static const char *rcsid = "$Id$"; +static const char *rcsid = "$Id: plist.c,v 1.19 1997/02/22 16:09:51 peter Exp $"; #endif /* @@ -23,6 +23,7 @@ static const char *rcsid = "$Id$"; */ #include "lib.h" +#include <errno.h> #include <md5.h> /* Add an item to a packing list */ @@ -352,10 +353,16 @@ delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) PackingList p; char *Where = ".", *last_file = ""; Boolean fail = SUCCESS; - char tmp[FILENAME_MAX]; + Boolean preserve; + char tmp[FILENAME_MAX], *name = NULL; + preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; for (p = pkg->head; p; p = p->next) { switch (p->type) { + case PLIST_NAME: + name = p->name; + break; + case PLIST_IGNORE: p = p->next; break; @@ -401,8 +408,22 @@ delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg) } if (Verbose) printf("Delete file %s\n", tmp); - - if (!Fake && delete_hierarchy(tmp, ign_err, nukedirs)) { + if (!Fake && preserve) { + if (!name) + whinge("preserve set but no package name supplied!"); + else { + char tmp2[FILENAME_MAX]; + + snprintf(tmp2, FILENAME_MAX, "%s.%s", tmp, name); + if (fexists(tmp2)) { + (void)chflags(tmp, 0); + delete_hierarchy(tmp, TRUE, TRUE); + if (rename(tmp2, tmp)) + whinge("preserve: Unable to restore %s as %s, errno = %d", tmp2, tmp, errno); + } + } + } + else if (!Fake && delete_hierarchy(tmp, ign_err, nukedirs)) { whinge("Unable to completely remove file '%s'", tmp); fail = FAIL; } |