summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pkg_install/delete
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2001-02-19 13:26:13 +0000
committersobomax <sobomax@FreeBSD.org>2001-02-19 13:26:13 +0000
commit6664ec33aac715f2be038c5e77df2aadbbd996b4 (patch)
tree45bc21e96042c8f76f4ba333eb9216dded1d9531 /usr.sbin/pkg_install/delete
parent4c1233433d4d46f6e4a755a79944ded2cc7e5420 (diff)
downloadFreeBSD-src-6664ec33aac715f2be038c5e77df2aadbbd996b4.zip
FreeBSD-src-6664ec33aac715f2be038c5e77df2aadbbd996b4.tar.gz
Improve pkg_delete(1) behaviour when deleting several packages at once.
Instead of trying to delete packages in the same order as they were specified in the command line, reorder deletion in such a way that if package A depends on package B then package A will be deleted before B no matter in which order they were specified in the command line. Reviewed by: jkh, will Approved by: jkh
Diffstat (limited to 'usr.sbin/pkg_install/delete')
-rw-r--r--usr.sbin/pkg_install/delete/perform.c77
1 files changed, 74 insertions, 3 deletions
diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c
index 7752938..7f294c0 100644
--- a/usr.sbin/pkg_install/delete/perform.c
+++ b/usr.sbin/pkg_install/delete/perform.c
@@ -30,16 +30,51 @@ static const char rcsid[] =
static int pkg_do(char *);
static void sanity_check(char *);
static void undepend(PackingList, char *);
+static int chkifdepends(char *pkgname1, char *pkgname2);
static char LogDir[FILENAME_MAX];
int
pkg_perform(char **pkgs)
{
- int i, err_cnt = 0;
-
- for (i = 0; pkgs[i]; i++)
+ char *tmp;
+ int i, j;
+ int err_cnt = 0;
+ int loop_cnt;
+
+ for (i = 0; pkgs[i]; i++) {
+ /*
+ * Check to see if any other package in pkgs[i+1:] depends
+ * on pkgs[i] and deffer removal of pkgs[i] if so.
+ */
+ loop_cnt = 0;
+ for (j = i + 1; pkgs[j]; j++) {
+ if (chkifdepends(pkgs[j], pkgs[i]) == 1) {
+ /*
+ * Try to avoid deadlock if package A depends on B which in
+ * turn depends on C and C due to an error depends on A.
+ * Use ugly but simple method, becase it Should Never
+ * Happen[tm] in the real life anyway.
+ */
+ if (loop_cnt > 4096) {
+ warnx("dependency loop detected for package %s", pkgs[j]);
+ err_cnt++;
+ break;
+ }
+ loop_cnt++;
+ tmp = pkgs[i];
+ pkgs[i] = pkgs[j];
+ pkgs[j] = tmp;
+ /*
+ * Another iteration requred to check if new pkgs[i]
+ * itself has any packages that depend on it
+ */
+ j--;
+ }
+ }
err_cnt += pkg_do(pkgs[i]);
+ }
+
return err_cnt;
}
@@ -293,3 +328,39 @@ undepend(PackingList p, char *pkgname)
remove(ftmp); /* just in case */
return;
}
+
+/*
+ * Check to see if pkgname1 depends on pkgname2.
+ * Returns 1 if depends, 0 if not, and -1 if error occured.
+ */
+static int
+chkifdepends(char *pkgname1, char *pkgname2)
+{
+ FILE *fp;
+ char fname[FILENAME_MAX];
+ char fbuf[FILENAME_MAX];
+ char *tmp;
+ int retval;
+
+ sprintf(fname, "%s/%s/%s",
+ (tmp = getenv(PKG_DBDIR)) ? tmp : DEF_LOG_DIR,
+ pkgname2, REQUIRED_BY_FNAME);
+ fp = fopen(fname, "r");
+ if (fp == NULL) {
+ /* Probably pkgname2 doesn't have any packages that depend on it */
+ return 0;
+ }
+
+ retval = 0;
+ while (fgets(fbuf, sizeof(fbuf), fp) != NULL) {
+ if (fbuf[strlen(fbuf)-1] == '\n')
+ fbuf[strlen(fbuf)-1] = '\0';
+ if (strcmp(fbuf, pkgname1) == 0) { /* match */
+ retval = 1;
+ break;
+ }
+ }
+
+ fclose(fp);
+ return retval;
+}
OpenPOWER on IntegriCloud