Add -R flag (similar to -r but the other way 'round)

This commit is contained in:
hubertf 1999-03-08 00:20:21 +00:00
parent eed16d934a
commit 4db56769f5
4 changed files with 201 additions and 61 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: delete.h,v 1.3 1999/02/26 10:49:30 chopps Exp $ */
/* $NetBSD: delete.h,v 1.4 1999/03/08 00:20:21 hubertf Exp $ */
/* from FreeBSD Id: delete.h,v 1.4 1997/02/22 16:09:35 peter Exp */
@ -30,8 +30,7 @@ extern char *ProgramPath;
extern Boolean NoDeInstall;
extern Boolean CleanDirs;
extern Boolean Force;
extern Boolean Recurse;
extern char *Directory;
extern char *PkgName;
extern Boolean Recurse_up;
extern Boolean Recurse_down;
#endif /* _INST_DELETE_H_INCLUDE */

View File

@ -1,11 +1,11 @@
/* $NetBSD: main.c,v 1.9 1999/03/03 17:29:58 hubertf Exp $ */
/* $NetBSD: main.c,v 1.10 1999/03/08 00:20:21 hubertf Exp $ */
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char *rcsid = "from FreeBSD Id: main.c,v 1.11 1997/10/08 07:46:48 charnier Exp";
#else
__RCSID("$NetBSD: main.c,v 1.9 1999/03/03 17:29:58 hubertf Exp $");
__RCSID("$NetBSD: main.c,v 1.10 1999/03/08 00:20:21 hubertf Exp $");
#endif
#endif
@ -35,20 +35,21 @@ __RCSID("$NetBSD: main.c,v 1.9 1999/03/03 17:29:58 hubertf Exp $");
#include "lib.h"
#include "delete.h"
static char Options[] = "hvDdnfFrOp:";
static char Options[] = "hvDdnfFp:OrR";
char *Prefix = NULL;
char *ProgramPath = NULL;
Boolean NoDeInstall = FALSE;
Boolean CleanDirs = FALSE;
Boolean File2Pkg = FALSE;
Boolean Recurse = FALSE;
Boolean Recurse_up = FALSE;
Boolean Recurse_down = FALSE;
Boolean OnlyDeleteFromPkgDB = FALSE;
static void
usage(void)
{
fprintf(stderr, "usage: pkg_delete [-vDdnFfrO] [-p prefix] pkg-name ...\n");
fprintf(stderr, "usage: pkg_delete [-vDdnFfOrR] [-p prefix] pkg-name ...\n");
exit(1);
}
@ -93,7 +94,11 @@ main(int argc, char **argv)
break;
case 'r':
Recurse = TRUE;
Recurse_up = TRUE;
break;
case 'R':
Recurse_down = TRUE;
break;
case 'O':

View File

@ -1,11 +1,11 @@
/* $NetBSD: perform.c,v 1.16 1999/03/03 20:12:06 hubertf Exp $ */
/* $NetBSD: perform.c,v 1.17 1999/03/08 00:20:21 hubertf Exp $ */
#include <sys/cdefs.h>
#ifndef lint
#if 0
static const char *rcsid = "from FreeBSD Id: perform.c,v 1.15 1997/10/13 15:03:52 jkh Exp";
#else
__RCSID("$NetBSD: perform.c,v 1.16 1999/03/03 20:12:06 hubertf Exp $");
__RCSID("$NetBSD: perform.c,v 1.17 1999/03/08 00:20:21 hubertf Exp $");
#endif
#endif
@ -70,14 +70,20 @@ typedef struct _rec_del_t {
TAILQ_HEAD(_rec_del_head_t, _rec_del_t);
typedef struct _rec_del_head_t rec_del_head_t;
rec_del_t *alloc_rec_del(char *);
rec_del_t *find_on_queue(rec_del_head_t *, char *);
void free_rec_del(rec_del_t *);
int recurse_require_find(rec_del_t *);
int require_find(char *, char *);
int require_delete(char *);
void require_print(int);
int undepend(const char *deppkgname, char *pkg2delname);
/* In which direction to search in require_find() */
typedef enum {
FIND_UP, FIND_DOWN
} rec_find_t;
static rec_del_t *alloc_rec_del(const char *);
static rec_del_t *find_on_queue(rec_del_head_t *, const char *);
static void free_rec_del(rec_del_t *);
static int require_find_recursive_up(rec_del_t *);
static int require_find_recursive_down(rec_del_t *, package_t *);
static int require_find(char *, rec_find_t);
static int require_delete(char *, int);
static void require_print(void);
static int undepend(const char *deppkgname, char *pkg2delname);
static char LogDir[FILENAME_MAX];
static char linebuf[FILENAME_MAX];
@ -85,8 +91,8 @@ static char pkgdir[FILENAME_MAX];
static package_t Plist;
rec_del_head_t rdfindq;
rec_del_head_t rddelq;
static rec_del_head_t rdfindq;
static rec_del_head_t rddelq;
static void
sanity_check(char *pkg)
@ -168,7 +174,7 @@ undepend(const char *deppkgname, char *pkg2delname)
/* add a package to the recursive delete list */
rec_del_t *
alloc_rec_del(char *pkgname)
alloc_rec_del(const char *pkgname)
{
rec_del_t *rdp;
@ -187,7 +193,7 @@ free_rec_del(rec_del_t *rdp)
}
rec_del_t *
find_on_queue(rec_del_head_t *qp, char *name)
find_on_queue(rec_del_head_t *qp, const char *name)
{
rec_del_t *rdp;
@ -198,13 +204,20 @@ find_on_queue(rec_del_head_t *qp, char *name)
}
/* delete from 'home' all packages on rec_del_list */
/* delete from directory 'home' all packages on rec_del_list
* if tryall is set, ignore errors from pkg_delete */
int
require_delete(char *home)
require_delete(char *home, int tryall)
{
rec_del_t *rdp;
int rv, fail;
char *tmp;
int oldcwd;
/* save cwd */
oldcwd=open(".", O_RDONLY, 0);
if (oldcwd == -1)
err(1, "cannot open \".\"");
(void)snprintf(pkgdir, sizeof(pkgdir), "%s",
(tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR);
@ -215,7 +228,7 @@ require_delete(char *home)
for (; rdp; rdp = TAILQ_NEXT(rdp, rd_link)) {
/* go to the db dir */
if (chdir(pkgdir) == FAIL) {
warnx("unable to change directory to %s, deinstall failed",
warnx("unable to change directory to %s, deinstall failed (1)",
pkgdir);
fail = 1;
break;
@ -229,7 +242,7 @@ require_delete(char *home)
/* return home for execution of command */
if (chdir(home) == FAIL) {
warnx("unable to change directory to %s! deinstall failed", home);
warnx("unable to change directory to %s, deinstall failed (2)", home);
fail = 1;
break;
}
@ -252,7 +265,7 @@ require_delete(char *home)
rdp->rd_name);
/* check for delete failure */
if (rv) {
if (rv && !tryall) {
fail = 1;
warnx("had problem removing %s%s", rdp->rd_name,
Force ? ", continuing" : "");
@ -268,17 +281,18 @@ require_delete(char *home)
}
/* return to the log dir */
if (chdir(LogDir) == FAIL) {
warnx("unable to change directory to %s! deinstall failed", LogDir);
if (fchdir(oldcwd) == FAIL) {
warnx("unable to change to previous directory, deinstall failed");
fail = 1;
}
return (fail);
}
/* recursively find all packages, return 1 on errors */
/* recursively find all packages "up" the tree (follow +REQUIRED_BY)
* return 1 on errors */
int
recurse_require_find(rec_del_t *thisrdp)
require_find_recursive_up(rec_del_t *thisrdp)
{
rec_del_head_t reqq;
rec_del_t *rdp = NULL;
@ -328,13 +342,11 @@ recurse_require_find(rec_del_t *thisrdp)
TAILQ_REMOVE(&reqq, rdp, rd_link);
/* find direct required requires */
if (recurse_require_find(rdp))
if (require_find_recursive_up(rdp))
goto fail;
/*
* all requires taken care of, add to tail of delete queue
* if not already there
*/
/* all requires taken care of, add to tail of delete queue
* if not already there */
if (find_on_queue(&rddelq, rdp->rd_name))
free_rec_del(rdp);
else
@ -354,8 +366,107 @@ fail:
return (1);
}
/* recursively find all packages "down" the tree (follow @pkgdep)
* return 1 on errors */
int
require_find(char *home, char *pkg)
require_find_recursive_down(rec_del_t *thisrdp, package_t *plist)
{
plist_t *p;
rec_del_t *rdp, *rdp2;
rec_del_head_t reqq;
int rc, fail=0;
/* see if we are on the find queue -- circular dependency */
if ((rdp = find_on_queue(&rdfindq, thisrdp->rd_name))) {
warnx("circular dependency found for pkg %s", rdp->rd_name);
return (1);
}
TAILQ_INIT(&reqq);
/* width-first scan */
/* first enqueue all @pkgdep's to rddelq, then (further below)
* go in recursively */
for (p = plist->head; p ; p = p->next) {
switch(p->type) {
case PLIST_PKGDEP:
rdp = alloc_rec_del(p->name);
TAILQ_INSERT_TAIL(&reqq, rdp, rd_link);
rdp2 = find_on_queue(&rddelq, p->name);
if (rdp2)
TAILQ_REMOVE(&rddelq, rdp2, rd_link);
rdp = alloc_rec_del(p->name);
TAILQ_INSERT_TAIL(&rddelq, rdp, rd_link);
break;
default:
break;
}
}
while ((rdp = TAILQ_FIRST(&reqq))) {
FILE *cfile;
package_t rPlist;
char *tmp;
plist_t *p;
/* remove a direct req from our queue */
TAILQ_REMOVE(&reqq, rdp, rd_link);
/* Reset some state */
rPlist.head = NULL;
rPlist.tail = NULL;
/* prepare for recursion */
chdir((tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR);
chdir(rdp->rd_name);
sanity_check(rdp->rd_name);
cfile = fopen(CONTENTS_FNAME, "r");
if (!cfile) {
warn("unable to open '%s' file", CONTENTS_FNAME);
fail=1;
goto fail;
}
/* If we have a prefix, add it now */
if (Prefix)
add_plist(&rPlist, PLIST_CWD, Prefix);
read_plist(&rPlist, cfile);
fclose(cfile);
p = find_plist(&rPlist, PLIST_CWD);
if (!p) {
warnx("package '%s' doesn't have a prefix", rdp->rd_name);
fail=1;
goto fail;
}
/* put ourselves on the top of the find queue */
TAILQ_INSERT_HEAD(&rdfindq, thisrdp, rd_link);
rc=require_find_recursive_down(rdp, &rPlist);
if (rc) {
fail=1;
goto fail;
}
/* take ourselves off the find queue */
TAILQ_REMOVE(&rdfindq, thisrdp, rd_link);
free_rec_del(rdp);
}
fail:
/* Clean out reqq */
while ((rdp = TAILQ_FIRST(&reqq))) {
TAILQ_REMOVE(&reqq, rdp, rd_link);
free_rec_del(rdp);
}
return fail;
}
int
require_find(char *pkg, rec_find_t updown)
{
rec_del_t *rdp;
int rv;
@ -364,27 +475,29 @@ require_find(char *home, char *pkg)
TAILQ_INIT(&rddelq);
rdp = alloc_rec_del(pkg);
rv = recurse_require_find(rdp);
switch (updown) {
case FIND_UP:
rv = require_find_recursive_up(rdp);
break;
case FIND_DOWN:
rv = require_find_recursive_down(rdp, &Plist);
break;
}
free_rec_del(rdp);
return (rv);
}
void
require_print(int del)
require_print(void)
{
rec_del_t *rdp;
/* print all but last -- deleting if requested */
if (del) {
while ((rdp = TAILQ_FIRST(&rddelq))) {
TAILQ_REMOVE(&rddelq, rdp, rd_link);
fprintf(stderr, "\t%s\n", rdp->rd_name);
free_rec_del(rdp);
}
} else {
for (rdp = TAILQ_FIRST(&rddelq); rdp; rdp = TAILQ_NEXT(rdp, rd_link))
fprintf(stderr, "\t%s\n", rdp->rd_name);
while ((rdp = TAILQ_FIRST(&rddelq))) {
TAILQ_REMOVE(&rddelq, rdp, rd_link);
fprintf(stderr, "\t%s\n", rdp->rd_name);
free_rec_del(rdp);
}
}
@ -416,20 +529,24 @@ pkg_do(char *pkg)
return 1;
}
if (!isemptyfile(REQUIRED_BY_FNAME)) {
if (!Recurse)
/* This package is required by others
* Either nuke them (-r), or stop.
*/
if (!Recurse_up)
warnx("package `%s' is required by other packages:", pkg);
else if (Verbose)
printf("building list of packages that require `%s'"
printf("Building list of packages that require `%s'"
" to deinstall\n", pkg);
if (require_find(home, pkg)) {
if (!Force || Recurse)
if (require_find(pkg, FIND_UP)) {
if (!Force || Recurse_up)
return (1);
}
if (!Recurse) {
require_print(1);
chdir(LogDir); /* CWD was changed by require_find() */
if (!Recurse_up) {
require_print();
return 1;
} else
require_delete(home);
require_delete(home, 0);
}
sanity_check(LogDir);
cfile = fopen(CONTENTS_FNAME, "r");
@ -496,6 +613,16 @@ pkg_do(char *pkg)
findmatchingname((tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
p->name, undepend, pkg);
}
if (Recurse_down) {
/* Also remove the packages further down, now that there's
* (most likely) nothing left which requires them. */
if (Verbose)
printf("Building list of packages that `%s' required\n", pkg);
if (require_find(pkg, FIND_DOWN))
return (1);
require_delete(home, 1);
}
return 0;
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: pkg_delete.1,v 1.9 1999/03/07 11:58:28 mycroft Exp $
.\" $NetBSD: pkg_delete.1,v 1.10 1999/03/08 00:20:21 hubertf Exp $
.\"
.\" FreeBSD install - a package for the installation and maintainance
.\" of non-core utilities.
@ -17,7 +17,7 @@
.\"
.\" from FreeBSD: @(#)pkg_delete.1
.\"
.Dd March 3rd, 1999
.Dd March 8rd, 1999
.Dt pkg_delete 1
.Os FreeBSD 2.0
.Sh NAME
@ -25,7 +25,7 @@
.Nd a utility for deleting previously installed software package distributions
.Sh SYNOPSIS
.Nm ""
.Op Fl vDdnFfO
.Op Fl vDdnFfOrR
.Bk -words
.Op Fl p Ar prefix
.Ek
@ -97,6 +97,14 @@ first builds a list of all packages that require (directly and indirectly)
the one being deleted. It then deletes these packages using
.Nm pkg_delete
with the given options before deleting the user specified package.
.It Fl R
Like the
.Fl r
option, this does a recursive delete. The
.Fl R
option deletes the given package and any packages required by
it, unless some other package still needs them. This can be used
to delete a package and all the packages it needs.
.It Fl d
Remove empty directories created by file cleanup. By default, only
files/directories explicitly listed in a package's contents (either as
@ -205,5 +213,6 @@ refined it for
.Nx
.It "Hubert Feyrer"
.Nx
wildcard dependency processing, pkgdb, etc.
wildcard dependency processing, pkgdb, recursive "down"
delete, etc.
.El