diff options
| author | Maxim Sobolev <sobomax@FreeBSD.org> | 2001-02-19 13:26:13 +0000 |
|---|---|---|
| committer | Maxim Sobolev <sobomax@FreeBSD.org> | 2001-02-19 13:26:13 +0000 |
| commit | 2a0eee8b7f85090881a9f52c8471eac2f936bf67 (patch) | |
| tree | 31ea1ef60dd7fc2eb991973d0cd1cc220211981a | |
| parent | 928268064f1ccaf8d4a4c249dfc35eb8c59dce96 (diff) | |
Notes
| -rw-r--r-- | usr.sbin/pkg_install/delete/perform.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c index 775293859ef6..7f294c06b85e 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; + char *tmp; + int i, j; + int err_cnt = 0; + int loop_cnt; - for (i = 0; pkgs[i]; i++) + 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; +} |
