From owner-freebsd-ports Sun Feb 18 6:44:54 2001 Delivered-To: freebsd-ports@freebsd.org Received: from blizzard.sabbo.net (ns.sabbo.net [193.193.218.18]) by hub.freebsd.org (Postfix) with ESMTP id 34F4D37B491; Sun, 18 Feb 2001 06:44:39 -0800 (PST) Received: from vic.sabbo.net (root@vic.sabbo.net [193.193.218.112]) by blizzard.sabbo.net (8.10.1/8.10.1) with ESMTP id f1IEiXn27225; Sun, 18 Feb 2001 16:44:35 +0200 Received: (from max@localhost) by vic.sabbo.net (8.11.2/8.11.2) id f1IEif600926; Sun, 18 Feb 2001 16:44:41 +0200 (EET) (envelope-from sobomax@FreeBSD.org) From: Maxim Sobolev Message-Id: <200102181444.f1IEif600926@vic.sabbo.net> Subject: Request for comment: pkg_delete(1) improvement To: ports@freebsd.org Date: Sun, 18 Feb 2001 16:44:35 +0200 (EET) Cc: jkh@freebsd.org X-Mailer: ELM [version 2.5 PL3] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="%--multipart-mixed-boundary-1.883.982507475--%" Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org --%--multipart-mixed-boundary-1.883.982507475--% Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Hi folks, You all should know that current pkg_delete(1)'s behaviour is suboptimal when several packages to be deleted are specified in command line. The problem is that pkg_delete(1) tries to delete packages in exacly the same order as they were specified in the command line, ignoring dependencies between packages involved. Attached patch should solve this problem by reordering packages to ensure proper removal order. After this patch applied you should be able to delete all installed packaged in one turn using `pkg_delete /var/db/pkg/*'. -Maxim --%--multipart-mixed-boundary-1.883.982507475--% Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Description: ASCII C program text Content-Disposition: attachment; filename="pkg_delete-reordering.diff" --- perform.c 2001/02/18 08:36:10 1.1 +++ perform.c 2001/02/18 11:44:02 @@ -30,16 +30,51 @@ 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; } @@ -292,4 +327,40 @@ warnx("error renaming `%s' to `%s'", ftmp, fname); 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; } --%--multipart-mixed-boundary-1.883.982507475--%-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message