pkg_delete.c revision 1.2
1/*-
2 * Copyright (c) 2009 Joerg Sonnenberger <joerg@NetBSD.org>.
3 * Copyright (c) 2003 Johnny Lam <jlam@NetBSD.org>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *    the documentation and/or other materials provided with the
15 *    distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30#if HAVE_CONFIG_H
31#include "config.h"
32#endif
33#include <nbcompat.h>
34#if HAVE_SYS_CDEFS_H
35#include <sys/cdefs.h>
36#endif
37__RCSID("$NetBSD: pkg_delete.c,v 1.2 2017/04/20 13:18:23 joerg Exp $");
38
39#if HAVE_ERR_H
40#include <err.h>
41#endif
42#include <stdio.h>
43#include <stdlib.h>
44
45#include "lib.h"
46
47static const char *pkgdb;
48static const char *destdir;
49static const char *prefix;
50
51static int keep_preserve;
52static int no_deinstall;
53static int find_by_filename;
54static int unregister_only;
55static int pkgdb_update_only;
56static int delete_recursive;
57static int delete_new_leaves;
58static int delete_automatic_leaves;
59
60static void
61usage(void)
62{
63	fprintf(stderr, "usage: pkg_delete [-DFfkNnORrVv] [-K pkg_dbdir]"
64	    " [-P destdir] [-p prefix] pkg-name ...\n");
65	exit(1);
66}
67
68static int
69add_by_filename(lpkg_head_t *pkgs, const char *filename)
70{
71	lpkg_t *lpp;
72	char *s;
73
74	if ((s = pkgdb_retrieve(filename)) == NULL) {
75		warnx("No matching package for file `%s' in pkgdb", filename);
76		return 1;
77	}
78
79	/* XXX Verify that pkgdb is consistent? Trust it for now... */
80
81	lpp = alloc_lpkg(s);
82	TAILQ_INSERT_TAIL(pkgs, lpp, lp_link);
83	return 0;
84}
85
86static int
87add_by_pattern(lpkg_head_t *pkgs, const char *pattern)
88{
89	switch (add_installed_pkgs_by_pattern(pattern, pkgs)) {
90	case 0:
91		warnx("No package matching `%s' found", pattern);
92		return 1;
93	case -1:
94		warnx("Error while iterating package database for `%s'",
95		    pattern);
96		return 1;
97	default:
98		return 0;
99	}
100}
101
102/*
103 * The argument is either a fixed package name or an absolute path.
104 * The latter is recognized for legacy compatibility and must point
105 * into the package database.
106 */
107static int
108add_by_pkgname(lpkg_head_t *pkgs, char *pkg)
109{
110	char *s;
111	lpkg_t *lpp;
112	size_t l;
113	const char *orig_pkg = pkg;
114
115	if (pkg[0] == '/') {
116		l = strlen(pkgdb);
117		if (strncmp(pkg, pkgdb, l) || pkg[l] != '/') {
118			warnx("Absolute path is not relative to "
119			    "package database, skipping: %s", pkg);
120			return 1;
121		}
122		pkg += l + 1;
123	}
124	l = strcspn(pkg, "/");
125	if (pkg[l + strspn(pkg + l, "/")] != '\0') {
126		warnx("`%s' is not a package name, skipping", orig_pkg);
127		return 1;
128	}
129	pkg[l] = '\0';
130
131	s = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
132	if (fexists(s)) {
133		free(s);
134		lpp = alloc_lpkg(pkg);
135		TAILQ_INSERT_TAIL(pkgs, lpp, lp_link);
136		return 0;
137	}
138	free(s);
139
140	switch (add_installed_pkgs_by_basename(pkg, pkgs)) {
141	case 0:
142		warnx("No matching package for basename `%s' of `%s'",
143		    pkg, orig_pkg);
144		return 1;
145	case -1:
146		warnx("Error expanding basename `%s' of `%s'",
147		    pkg, orig_pkg);
148		return 1;
149	default:
150		return 0;
151	}
152}
153
154/*
155 * Evaluate +REQUIRED_BY.  This function is used for four different
156 * tasks:
157 * 0: check if no depending packages remain
158 * 1: like 0, but prepend the depending packages to pkgs if they exist
159 * 2: print remaining packages to stderr
160 * 3: check all and at least one depending packages have been removed
161 */
162static int
163process_required_by(const char *pkg, lpkg_head_t *pkgs,
164    lpkg_head_t *sorted_pkgs, int action)
165{
166	char line[MaxPathSize], *eol, *fname;
167	FILE *fp;
168	lpkg_t *lpp;
169	int got_match, got_miss;
170
171	fname = pkgdb_pkg_file(pkg, REQUIRED_BY_FNAME);
172	if (!fexists(fname)) {
173		free(fname);
174		return 0;
175	}
176
177	if ((fp = fopen(fname, "r")) == NULL) {
178		warn("Failed to open `%s'", fname);
179		free(fname);
180		return -1;
181	}
182	free(fname);
183
184	got_match = 0;
185	got_miss = 0;
186
187	while (fgets(line, sizeof(line), fp)) {
188		if ((eol = strrchr(line, '\n')) != NULL)
189			*eol = '\0';
190		TAILQ_FOREACH(lpp, sorted_pkgs, lp_link) {
191			if (strcmp(lpp->lp_name, line) == 0)
192				break;
193		}
194		if (lpp != NULL) {
195			got_match = 1;
196			continue;
197		}
198		got_miss = 1;
199		if (pkgs) {
200			TAILQ_FOREACH(lpp, pkgs, lp_link) {
201				if (strcmp(lpp->lp_name, line) == 0)
202					break;
203			}
204			if (lpp != NULL)
205				continue;
206		}
207		switch (action) {
208		case 0:
209			fclose(fp);
210			return 1;
211		case 1:
212			lpp = alloc_lpkg(line);
213			TAILQ_INSERT_HEAD(pkgs, lpp, lp_link);
214			break;
215		case 2:
216			fprintf(stderr, "\t%s\n", line);
217			break;
218		case 3:
219			fclose(fp);
220			return 0;
221		}
222	}
223
224	fclose(fp);
225
226	return (action == 3 ? got_match : got_miss);
227}
228
229/*
230 * Main function to order the patterns from the command line and
231 * add the subtrees for -r processing as needed.
232 *
233 * The first part ensures that all packages are listed at most once
234 * in pkgs. Afterwards the list is scanned for packages without depending
235 * packages. Each such package is moved to sorted_pkgs in order.
236 * If -r is given, all dependencies are inserted at the head of pkgs.
237 * The loop has to continue as long as progress is made. This can happen
238 * either because another package has been added to pkgs due to recursion
239 * (head of pkgs changed) or because a package has no more depending packages
240 * (tail of sorted_pkgs changed).
241 *
242 * If no progress is made, the remaining packages are moved to sorted_pkgs
243 * and an error is returned for the !Force case.
244 */
245static int
246sort_and_recurse(lpkg_head_t *pkgs, lpkg_head_t *sorted_pkgs)
247{
248	lpkg_t *lpp, *lpp2, *lpp_next, *lpp_old_tail, *lpp_old_head;
249	int rv;
250
251	TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
252		TAILQ_FOREACH(lpp2, pkgs, lp_link) {
253			if (lpp != lpp2 &&
254			    strcmp(lpp->lp_name, lpp2->lp_name) == 0)
255				break;
256		}
257		if (lpp2 == NULL)
258			continue;
259		TAILQ_REMOVE(pkgs, lpp, lp_link);
260		free_lpkg(lpp);
261	}
262
263	while (!TAILQ_EMPTY(pkgs)) {
264		lpp_old_tail = TAILQ_LAST(sorted_pkgs, _lpkg_head_t);
265		lpp_old_head = TAILQ_FIRST(pkgs);
266
267		TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
268			rv = process_required_by(lpp->lp_name, pkgs,
269			    sorted_pkgs, delete_recursive ? 1 : 0);
270			if (rv)
271				continue;
272			TAILQ_REMOVE(pkgs, lpp, lp_link);
273			TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link);
274		}
275
276		if (lpp_old_tail == TAILQ_LAST(sorted_pkgs, _lpkg_head_t) &&
277		    lpp_old_head == TAILQ_FIRST(pkgs))
278			break;
279	}
280
281	if (TAILQ_EMPTY(pkgs))
282		return 0;
283
284	while (!TAILQ_EMPTY(pkgs)) {
285		lpp = TAILQ_FIRST(pkgs);
286		TAILQ_REMOVE(pkgs, lpp, lp_link);
287		fprintf(stderr,
288		    "Package `%s' is still required by other packages:\n",
289		    lpp->lp_name);
290		process_required_by(lpp->lp_name, NULL, sorted_pkgs, 2);
291		if (Force) {
292			TAILQ_INSERT_TAIL(sorted_pkgs, lpp, lp_link);
293		} else
294			free_lpkg(lpp);
295	}
296
297	return !Force;
298}
299
300struct find_leaves_data {
301	lpkg_head_t *pkgs;
302	int progress;
303};
304
305/*
306 * Iterator for finding leaf packages.
307 * Packages that are marked as not for deletion are not considered as
308 * leaves.  For all other packages it is checked if at least one package
309 * that depended on them is to be removed AND no depending package remains.
310 * If that is the case, the package is appended to the sorted list.
311 * As this package can't have depending packages left, the topological order
312 * remains consistent.
313 */
314static int
315find_new_leaves_iter(const char *pkg, void *cookie)
316{
317	char *fname;
318	struct find_leaves_data *data = cookie;
319	lpkg_t *lpp;
320
321	fname = pkgdb_pkg_file(pkg, PRESERVE_FNAME);
322	if (fexists(fname)) {
323		free(fname);
324		return 0;
325	}
326	free(fname);
327
328	if (delete_automatic_leaves && !delete_new_leaves &&
329	    !is_automatic_installed(pkg))
330		return 0;
331
332	/* Check whether this package is already on the list first. */
333	TAILQ_FOREACH(lpp, data->pkgs, lp_link) {
334		if (strcmp(lpp->lp_name, pkg) == 0)
335			return 0;
336	}
337
338	if (process_required_by(pkg, NULL, data->pkgs, 3) == 1) {
339		lpp = alloc_lpkg(pkg);
340		TAILQ_INSERT_TAIL(data->pkgs, lpp, lp_link);
341		data->progress = 1;
342	}
343
344	return 0;
345}
346
347/*
348 * Iterate over all installed packages and look for new leaf packages.
349 * As long as the loop adds one new leaf package, processing continues.
350 */
351static void
352find_new_leaves(lpkg_head_t *pkgs)
353{
354	struct find_leaves_data data;
355
356	data.pkgs = pkgs;
357	do {
358		data.progress = 0;
359		iterate_pkg_db(find_new_leaves_iter, &data);
360	} while (data.progress);
361}
362
363/*
364 * Check that no entry on the package list is marked as not for deletion.
365 */
366static int
367find_preserve_pkgs(lpkg_head_t *pkgs)
368{
369	lpkg_t *lpp, *lpp_next;
370	char *fname;
371	int found_preserve;
372
373	found_preserve = 0;
374	TAILQ_FOREACH_SAFE(lpp, pkgs, lp_link, lpp_next) {
375		fname = pkgdb_pkg_file(lpp->lp_name, PRESERVE_FNAME);
376		if (!fexists(fname)) {
377			free(fname);
378			continue;
379		}
380		free(fname);
381		if (keep_preserve) {
382			TAILQ_REMOVE(pkgs, lpp, lp_link);
383			free_lpkg(lpp);
384			continue;
385		}
386		if (!found_preserve)
387			warnx("The following packages are marked as not "
388			    "for deletion:");
389		found_preserve = 1;
390		fprintf(stderr, "\t%s\n", lpp->lp_name);
391	}
392	if (!found_preserve)
393		return 0;
394	if (Force == 0 || (!unregister_only && Force == 1))
395		return 1;
396	fprintf(stderr, "...but will delete them anyway\n");
397	return 0;
398}
399
400/*
401 * Run the +DEINSTALL script. Depending on whether this is
402 * pre- or post-deinstall phase, different arguments are passed down.
403 */
404static int
405run_deinstall_script(const char *pkg, int do_postdeinstall)
406{
407	const char *target, *text;
408	char *fname, *pkgdir;
409	int rv;
410
411	fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME);
412	if (!fexists(fname)) {
413		free(fname);
414		return 0;
415	}
416
417	if (do_postdeinstall) {
418		target = "POST-DEINSTALL";
419		text = "post-deinstall";
420	} else {
421		target = "DEINSTALL";
422		text = "deinstall";
423	}
424
425	if (Fake) {
426		printf("Would execute %s script with argument %s now\n",
427		    text, target);
428		free(fname);
429		return 0;
430	}
431
432	pkgdir = pkgdb_pkg_dir(pkg);
433	if (chmod(fname, 0555))
434		warn("chmod of `%s' failed", fname);
435	rv = fcexec(pkgdir, fname, pkg, target, NULL);
436	if (rv)
437		warnx("%s script returned error status", text);
438	free(pkgdir);
439	free(fname);
440	return rv;
441}
442
443/*
444 * Copy lines from fname to fname_tmp, filtering out lines equal to text.
445 * Afterwards rename fname_tmp to fname;
446 */
447static int
448remove_line(const char *fname, const char *fname_tmp, const char *text)
449{
450	FILE *fp, *fp_out;
451	char line[MaxPathSize], *eol;
452	int rv;
453
454	if ((fp = fopen(fname, "r")) == NULL) {
455		warn("Unable to open `%s'", fname);
456		return 1;
457	}
458	if ((fp_out = fopen(fname_tmp, "w")) == NULL) {
459		warn("Unable to open `%s'", fname_tmp);
460		fclose(fp);
461		return 1;
462	}
463
464	while (fgets(line, sizeof(line), fp) != NULL) {
465		if ((eol = strrchr(line, '\n')) != NULL)
466			*eol = '\0';
467		if (strcmp(line, text) == 0)
468			continue;
469		fprintf(fp_out, "%s\n", line);
470	}
471	fclose(fp);
472
473	if (fclose(fp_out) == EOF) {
474		remove(fname_tmp);
475		warnx("Failure while closing `%s' temp file", fname_tmp);
476		return 1;
477	}
478
479	if (rename(fname_tmp, fname) == -1) {
480		warn("Unable to rename `%s' to `%s'", fname_tmp, fname);
481		rv = 1;
482	} else
483		rv = 0;
484	remove(fname_tmp);
485
486	return rv;
487}
488
489/*
490 * remove_depend is used as iterator function below.
491 * The passed-in package name should be removed from the
492 * +REQUIRED_BY list of the dependency.  Such an entry
493 * can miss in a fully correct package database, if the pattern
494 * matches more than one package.
495 */
496static int
497remove_depend(const char *cur_pkg, void *cookie)
498{
499	const char *pkg = cookie;
500	char *fname, *fname2;
501	int rv;
502
503	fname = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME);
504	if (isemptyfile(fname)) {
505		free(fname);
506		return 0;
507	}
508	fname2 = pkgdb_pkg_file(cur_pkg, REQUIRED_BY_FNAME_TMP);
509
510	rv = remove_line(fname, fname2, pkg);
511
512	free(fname2);
513	free(fname);
514
515	return rv;
516}
517
518static int
519remove_pkg(const char *pkg)
520{
521	FILE *fp;
522	char *fname, *pkgdir;
523	package_t plist;
524	plist_t *p;
525	int rv, late_error;
526
527	if (pkgdb_update_only)
528		return pkgdb_remove_pkg(pkg) ? 0 : 1;
529
530	fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
531	if (!fexists(fname)) {
532		warnx("package `%s' is not installed, `%s' missing", pkg, fname);
533		free(fname);
534		return 1;
535	}
536	free(fname);
537
538	fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME);
539	if ((fp = fopen(fname, "r")) == NULL) {
540		warnx("Failed to open `%s'", fname);
541		free(fname);
542		return 1;
543	}
544	read_plist(&plist, fp);
545	fclose(fp);
546
547	/*
548	 * If a prefix has been provided, remove the first @cwd and
549	 * prepend that prefix.  This allows removing packages without
550	 * @cwd if really necessary.  pkg_admin rebuild is likely needed
551	 * afterwards though.
552	 */
553	if (prefix) {
554		delete_plist(&plist, FALSE, PLIST_CWD, NULL);
555		add_plist_top(&plist, PLIST_CWD, prefix);
556	}
557	if ((p = find_plist(&plist, PLIST_CWD)) == NULL) {
558		warnx("Package `%s' doesn't have a prefix", pkg);
559		return 1;
560	}
561
562	if (find_plist(&plist, PLIST_NAME) == NULL) {
563		/* Cheat a bit to allow removal of such bad packages. */
564		warnx("Package `%s' doesn't have a name", pkg);
565		add_plist_top(&plist, PLIST_NAME, pkg);
566	}
567
568	setenv(PKG_REFCOUNT_DBDIR_VNAME, config_pkg_refcount_dbdir, 1);
569	fname = pkgdb_pkg_dir(pkg);
570	setenv(PKG_METADATA_DIR_VNAME, fname, 1);
571	free(fname);
572	setenv(PKG_PREFIX_VNAME, p->name, 1);
573
574	if (!no_deinstall && !unregister_only) {
575		if (run_deinstall_script(pkg, 0) && !Force)
576			return 1;
577	}
578
579	late_error = 0;
580
581	if (Fake)
582		printf("Attempting to delete package `%s'\n", pkg);
583	else if (delete_package(FALSE, &plist, unregister_only,
584			        destdir) == FAIL) {
585		warnx("couldn't entirely delete package `%s'", pkg);
586		/*
587		 * XXX It could be nice to error out here explicitly,
588		 * XXX but this is problematic for missing or changed files.
589		 * XXX At least the inability to remove files at all should
590		 * XXX be handled though.
591		 */
592	}
593
594	/*
595	 * Past the point of no return. Files are gone, all that is left
596	 * is cleaning up registered dependencies and removing the meta data.
597	 * Errors in the remaining part are counted, but don't stop the
598	 * processing.
599	 */
600
601	for (p = plist.head; p; p = p->next) {
602	    if (p->type != PLIST_PKGDEP)
603		continue;
604	    if (Verbose)
605		printf("Attempting to remove dependency "
606		       "on package `%s'\n", p->name);
607	    if (Fake)
608		continue;
609	    match_installed_pkgs(p->name, remove_depend,
610				 __UNCONST(pkg));
611	}
612
613	free_plist(&plist);
614
615	if (!no_deinstall && !unregister_only)
616		late_error |= run_deinstall_script(pkg, 1);
617
618	if (Fake)
619		return 0;
620
621	/*
622	 * Kill the pkgdb subdirectory. The files have been removed, so
623	 * this is way beyond the point of no return.
624	 */
625	pkgdir = pkgdb_pkg_dir(pkg);
626	(void) remove_files(pkgdir, "+*");
627	rv = 1;
628	if (isemptydir(pkgdir)&& rmdir(pkgdir) == 0)
629		rv = 0;
630	else if (!Force)
631		warnx("Couldn't remove package directory in `%s'", pkgdir);
632	else if (recursive_remove(pkgdir, 1))
633		warn("Couldn't remove package directory `%s'", pkgdir);
634	else
635		warnx("Package directory `%s' forcefully removed", pkgdir);
636	free(pkgdir);
637
638	return rv | late_error;
639}
640
641int
642main(int argc, char *argv[])
643{
644	lpkg_head_t pkgs, sorted_pkgs;
645	int ch, r, has_error;
646	unsigned long bad_count;
647
648	TAILQ_INIT(&pkgs);
649	TAILQ_INIT(&sorted_pkgs);
650
651	setprogname(argv[0]);
652	while ((ch = getopt(argc, argv, "ADFfK:kNnOP:p:RrVv")) != -1) {
653		switch (ch) {
654		case 'A':
655			delete_automatic_leaves = 1;
656			break;
657		case 'D':
658			no_deinstall = 1;
659			break;
660		case 'F':
661			find_by_filename = 1;
662			break;
663		case 'f':
664			++Force;
665			break;
666		case 'K':
667			pkgdb_set_dir(optarg, 3);
668			break;
669		case 'k':
670			keep_preserve = 1;
671			break;
672		case 'N':
673			unregister_only = 1;
674			break;
675		case 'n':
676			Fake = 1;
677			break;
678		case 'O':
679			pkgdb_update_only = 1;
680			break;
681		case 'P':
682			destdir = optarg;
683			break;
684		case 'p':
685			prefix = optarg;
686			break;
687		case 'R':
688			delete_new_leaves = 1;
689			break;
690		case 'r':
691			delete_recursive = 1;
692			break;
693		case 'V':
694			show_version();
695			/* NOTREACHED */
696		case 'v':
697			++Verbose;
698			break;
699		default:
700			usage();
701			break;
702		}
703	}
704
705	pkg_install_config();
706
707	pkgdb = xstrdup(pkgdb_get_dir());
708
709	if (destdir != NULL) {
710		char *pkgdbdir;
711
712		pkgdbdir = xasprintf("%s/%s", destdir, pkgdb);
713		pkgdb_set_dir(pkgdbdir, 4);
714		free(pkgdbdir);
715	}
716
717	argc -= optind;
718	argv += optind;
719
720	if (argc == 0) {
721		if (find_by_filename)
722			warnx("Missing filename(s)");
723		else
724			warnx("Missing package name(s)");
725		usage();
726	}
727
728	if (Fake)
729		r = pkgdb_open(ReadOnly);
730	else
731		r = pkgdb_open(ReadWrite);
732
733	if (!r)
734		errx(EXIT_FAILURE, "Opening pkgdb failed");
735
736	/* First, process all command line options. */
737
738	has_error = 0;
739	for (; argc != 0; --argc, ++argv) {
740		if (find_by_filename)
741			has_error |= add_by_filename(&pkgs, *argv);
742		else if (ispkgpattern(*argv))
743			has_error |= add_by_pattern(&pkgs, *argv);
744		else
745			has_error |= add_by_pkgname(&pkgs, *argv);
746	}
747
748	if (has_error && !Force) {
749		pkgdb_close();
750		return EXIT_FAILURE;
751	}
752
753	/* Second, reorder and recursive if necessary. */
754
755	if (sort_and_recurse(&pkgs, &sorted_pkgs)) {
756		pkgdb_close();
757		return EXIT_FAILURE;
758	}
759
760	/* Third, add leaves if necessary. */
761
762	if (delete_new_leaves || delete_automatic_leaves)
763		find_new_leaves(&sorted_pkgs);
764
765	/*
766	 * Now that all packages to remove are known, check
767	 * if all are removable.  After that, start the actual
768	 * removal.
769	 */
770
771	if (find_preserve_pkgs(&sorted_pkgs)) {
772		pkgdb_close();
773		return EXIT_FAILURE;
774	}
775
776	setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1);
777
778	bad_count = 0;
779	while (!TAILQ_EMPTY(&sorted_pkgs)) {
780		lpkg_t *lpp;
781
782		lpp = TAILQ_FIRST(&sorted_pkgs);
783		TAILQ_REMOVE(&sorted_pkgs, lpp, lp_link);
784		if (remove_pkg(lpp->lp_name)) {
785			++bad_count;
786			if (!Force)
787				break;
788		}
789		free_lpkg(lpp);
790	}
791
792	pkgdb_close();
793
794	if (Force && bad_count && Verbose)
795		warnx("Removal of %lu packages failed", bad_count);
796
797	return bad_count > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
798}
799