Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2011-2012 Marin Atanasov Nikolov <dnaeon@gmail.com>
5 : : * Copyright (c) 2013-2014 Matthew Seaman <matthew@FreeBSD.org>
6 : : * Copyright (c) 2016 Vsevolod Stakhov <vsevolod@FreeBSD.org>
7 : : * All rights reserved.
8 : : *
9 : : * Redistribution and use in source and binary forms, with or without
10 : : * modification, are permitted provided that the following conditions
11 : : * are met:
12 : : * 1. Redistributions of source code must retain the above copyright
13 : : * notice, this list of conditions and the following disclaimer
14 : : * in this position and unchanged.
15 : : * 2. Redistributions in binary form must reproduce the above copyright
16 : : * notice, this list of conditions and the following disclaimer in the
17 : : * documentation and/or other materials provided with the distribution.
18 : : *
19 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
20 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
23 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #include <err.h>
32 : : #include <getopt.h>
33 : : #include <stdio.h>
34 : : #include <string.h>
35 : : #include <unistd.h>
36 : :
37 : : #include <pkg.h>
38 : :
39 : : #include "pkgcli.h"
40 : :
41 : : void
42 : 0 : usage_delete(void)
43 : : {
44 : 0 : fprintf(stderr, "Usage: pkg delete [-DfnqRy] [-Cgix] <pkg-name> ...\n");
45 : 0 : fprintf(stderr, " pkg delete [-Dnqy] -a\n\n");
46 : 0 : fprintf(stderr, "For more information see 'pkg help delete'.\n");
47 : 0 : }
48 : :
49 : : int
50 : 111 : exec_delete(int argc, char **argv)
51 : : {
52 : 111 : struct pkg_jobs *jobs = NULL;
53 : 111 : struct pkgdb *db = NULL;
54 : 111 : match_t match = MATCH_EXACT;
55 : 111 : pkg_flags f = PKG_FLAG_NONE;
56 : 111 : bool recursive_flag = false, rc = false;
57 : 111 : int retcode = EXIT_FAILURE;
58 : : int ch;
59 : : int i;
60 : 111 : int lock_type = PKGDB_LOCK_ADVISORY;
61 : 111 : int locked_pkgs = 0;
62 : :
63 : 111 : struct option longopts[] = {
64 : : { "all", no_argument, NULL, 'a' },
65 : : { "case-sensitive", no_argument, NULL, 'C' },
66 : : { "no-scripts", no_argument, NULL, 'D' },
67 : : { "force", no_argument, NULL, 'f' },
68 : : { "glob", no_argument, NULL, 'g' },
69 : : { "case-insensitive", no_argument, NULL, 'i' },
70 : : { "dry-run", no_argument, NULL, 'n' },
71 : : { "quiet", no_argument, NULL, 'q' },
72 : : { "recursive", no_argument, NULL, 'R' },
73 : : { "regex", no_argument, NULL, 'x' },
74 : : { "yes", no_argument, NULL, 'y' },
75 : : { NULL, 0, NULL, 0 },
76 : : };
77 : :
78 : 111 : nbactions = nbdone = 0;
79 : :
80 [ + + ]: 262 : while ((ch = getopt_long(argc, argv, "+aCDfginqRxy", longopts, NULL)) != -1) {
81 [ + - - + : 151 : switch (ch) {
- - - + -
- + - ]
82 : : case 'a':
83 : 4 : match = MATCH_ALL;
84 : 4 : break;
85 : : case 'C':
86 : 0 : pkgdb_set_case_sensitivity(true);
87 : 0 : break;
88 : : case 'D':
89 : 0 : f |= PKG_FLAG_NOSCRIPT;
90 : 0 : break;
91 : : case 'f':
92 : 16 : f |= PKG_FLAG_FORCE;
93 : 16 : force = true;
94 : 16 : break;
95 : : case 'g':
96 : 0 : match = MATCH_GLOB;
97 : 0 : break;
98 : : case 'i':
99 : 0 : pkgdb_set_case_sensitivity(false);
100 : 0 : break;
101 : : case 'n':
102 : 0 : f |= PKG_FLAG_DRY_RUN;
103 : 0 : lock_type = PKGDB_LOCK_READONLY;
104 : 0 : dry_run = true;
105 : 0 : break;
106 : : case 'q':
107 : 20 : quiet = true;
108 : 20 : break;
109 : : case 'R':
110 : 0 : recursive_flag = true;
111 : 0 : break;
112 : : case 'x':
113 : 0 : match = MATCH_REGEX;
114 : 0 : break;
115 : : case 'y':
116 : 111 : yes = true;
117 : 111 : break;
118 : : default:
119 : 0 : usage_delete();
120 : 0 : return (EXIT_FAILURE);
121 : : }
122 : : }
123 : :
124 : 111 : argc -= optind;
125 : 111 : argv += optind;
126 : :
127 [ + + + - ]: 111 : if (argc < 1 && match != MATCH_ALL) {
128 : 0 : usage_delete();
129 : 0 : return (EXIT_FAILURE);
130 : : }
131 : :
132 [ - + ]: 111 : if (dry_run)
133 : 0 : retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
134 : : else
135 : 111 : retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
136 : : PKGDB_DB_LOCAL);
137 : :
138 [ - + ]: 111 : if (retcode == EPKG_ENODB) {
139 : 0 : warnx("No packages installed. Nothing to do!");
140 : 0 : return (EXIT_SUCCESS);
141 [ - + ]: 111 : } else if (retcode == EPKG_ENOACCESS) {
142 : 0 : warnx("Insufficient privileges to delete packages");
143 : 0 : return (EXIT_FAILURE);
144 [ - + ]: 111 : } else if (retcode != EPKG_OK) {
145 : 0 : warnx("Error accessing the package database");
146 : 0 : return (EXIT_FAILURE);
147 : : }
148 : :
149 [ - + ]: 111 : if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
150 : 0 : return (EXIT_FAILURE);
151 : :
152 [ - + ]: 111 : if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
153 : 0 : pkgdb_close(db);
154 : 0 : warnx("Cannot get an advisory lock on a database, it is locked by another process");
155 : 0 : return (EXIT_FAILURE);
156 : : }
157 : :
158 : :
159 [ - + ]: 111 : if (pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db) != EPKG_OK) {
160 : 0 : pkgdb_close(db);
161 : 0 : return (EXIT_FAILURE);
162 : : }
163 : :
164 : : /*
165 : : * By default delete packages recursively.
166 : : * If force mode is enabled then we try to remove packages non-recursively.
167 : : * However, if -f and -R flags are both enabled then we return to
168 : : * recursive deletion.
169 : : */
170 [ + + - + ]: 111 : if (!force || recursive_flag)
171 : 95 : f |= PKG_FLAG_RECURSIVE;
172 : :
173 : 111 : pkg_jobs_set_flags(jobs, f);
174 : :
175 [ + + ]: 111 : if (match == MATCH_EXACT) {
176 [ + + ]: 214 : for (i = 0; i < argc; i++) {
177 [ + - ]: 107 : if (strchr(argv[i], '*') != NULL) {
178 : 0 : match = MATCH_GLOB;
179 : 0 : break;
180 : : }
181 : 107 : }
182 : 107 : }
183 : :
184 [ - + ]: 111 : if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
185 : 0 : goto cleanup;
186 : :
187 [ - + ]: 111 : if (pkg_jobs_solve(jobs) != EPKG_OK) {
188 : 0 : fprintf(stderr, "Cannot perform request\n");
189 : 0 : retcode = EXIT_FAILURE;
190 : 0 : goto cleanup;
191 : : }
192 : :
193 [ + + ]: 111 : if (pkg_jobs_has_lockedpkgs(jobs)) {
194 : 4 : printf("The following package(s) are locked and may not ");
195 : 4 : printf("be removed:\n\n");
196 : 4 : pkg_jobs_iter_lockedpkgs(jobs, print_pkg, &locked_pkgs);
197 : 4 : printf("\n");
198 : 4 : }
199 : :
200 : : /* check if we have something to deinstall */
201 [ + + ]: 111 : if ((nbactions = pkg_jobs_count(jobs)) == 0) {
202 [ + - ]: 4 : if (argc == 0) {
203 [ # # ]: 0 : if (!quiet)
204 : 0 : printf("Nothing to do.\n");
205 : :
206 : 0 : retcode = EXIT_SUCCESS;
207 : 0 : goto cleanup;
208 : : }
209 [ - + ]: 4 : if (!quiet) {
210 : 4 : printf("%d packages requested for removal: "
211 : : "%d locked, %d missing\n",
212 : 4 : argc, locked_pkgs, argc - locked_pkgs);
213 : 4 : }
214 [ + - ]: 4 : if (locked_pkgs > 0) {
215 : 4 : retcode = EPKG_LOCKED;
216 : 4 : } else {
217 : 0 : retcode = EXIT_FAILURE;
218 : : }
219 : 4 : goto cleanup;
220 : : }
221 : :
222 [ + + - + ]: 107 : if (!quiet || dry_run) {
223 [ - + ]: 87 : if (!quiet) {
224 : 174 : print_jobs_summary(jobs,
225 : : "Deinstallation has been requested for the following %d packages "
226 : 87 : "(of %d packages in the universe):\n\n", nbactions,
227 : 87 : pkg_jobs_total(jobs));
228 : 87 : }
229 [ - + ]: 87 : if (dry_run) {
230 : 0 : retcode = EXIT_SUCCESS;
231 : 0 : goto cleanup;
232 : : }
233 : 87 : rc = query_yesno(false,
234 : : "\nProceed with deinstalling packages? ");
235 : 87 : }
236 : : else
237 : 20 : rc = yes;
238 : :
239 [ + - + + ]: 107 : if (!rc || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK)
240 : 8 : goto cleanup;
241 : :
242 [ + + ]: 99 : if (messages != NULL) {
243 : 12 : fflush(messages->fp);
244 : 12 : printf("%s", messages->buf);
245 : 12 : }
246 : 99 : pkgdb_compact(db);
247 : :
248 [ + - ]: 198 : if (rc)
249 : 99 : retcode = EXIT_SUCCESS;
250 : : else
251 : 0 : retcode = EXIT_FAILURE;
252 : :
253 : : cleanup:
254 : 111 : pkgdb_release_lock(db, lock_type);
255 : 111 : pkg_jobs_free(jobs);
256 : 111 : pkgdb_close(db);
257 : :
258 : 111 : return (retcode);
259 : 111 : }
|