Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/src/delete.c
2065 views
1
/*-
2
* Copyright (c) 2011-2012 Baptiste Daroussin <[email protected]>
3
* Copyright (c) 2011-2012 Julien Laffaye <[email protected]>
4
* Copyright (c) 2011-2012 Marin Atanasov Nikolov <[email protected]>
5
* Copyright (c) 2013-2014 Matthew Seaman <[email protected]>
6
* Copyright (c) 2016 Vsevolod Stakhov <[email protected]>
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
usage_delete(void)
43
{
44
fprintf(stderr, "Usage: pkg delete [-DfnqRy] [-Cgix] <pkg-name> ...\n");
45
fprintf(stderr, " pkg delete [-Dnqy] -a\n\n");
46
fprintf(stderr, "For more information see 'pkg help delete'.\n");
47
}
48
49
int
50
exec_delete(int argc, char **argv)
51
{
52
struct pkg_jobs *jobs = NULL;
53
struct pkgdb *db = NULL;
54
match_t match = MATCH_EXACT;
55
pkg_flags f = PKG_FLAG_NONE;
56
bool recursive_flag = false, rc = false;
57
int retcode = EXIT_FAILURE;
58
int ch;
59
int i;
60
int lock_type = PKGDB_LOCK_ADVISORY;
61
int locked_pkgs = 0;
62
int nbactions = 0;
63
int scriptnoexec = 0;
64
65
struct option longopts[] = {
66
{ "all", no_argument, NULL, 'a' },
67
{ "case-sensitive", no_argument, NULL, 'C' },
68
{ "no-scripts", no_argument, NULL, 'D' },
69
{ "script-no-exec", no_argument, &scriptnoexec, 1 },
70
{ "force", no_argument, NULL, 'f' },
71
{ "glob", no_argument, NULL, 'g' },
72
{ "case-insensitive", no_argument, NULL, 'i' },
73
{ "dry-run", no_argument, NULL, 'n' },
74
{ "quiet", no_argument, NULL, 'q' },
75
{ "recursive", no_argument, NULL, 'R' },
76
{ "regex", no_argument, NULL, 'x' },
77
{ "yes", no_argument, NULL, 'y' },
78
{ NULL, 0, NULL, 0 },
79
};
80
81
82
while ((ch = getopt_long(argc, argv, "+aCDfginqRxy", longopts, NULL)) != -1) {
83
switch (ch) {
84
case 'a':
85
match = MATCH_ALL;
86
break;
87
case 'C':
88
pkgdb_set_case_sensitivity(true);
89
break;
90
case 'D':
91
f |= PKG_FLAG_NOSCRIPT;
92
break;
93
case 'f':
94
f |= PKG_FLAG_FORCE;
95
force = true;
96
break;
97
case 'g':
98
match = MATCH_GLOB;
99
break;
100
case 'i':
101
pkgdb_set_case_sensitivity(false);
102
break;
103
case 'n':
104
f |= PKG_FLAG_DRY_RUN;
105
lock_type = PKGDB_LOCK_READONLY;
106
dry_run = true;
107
break;
108
case 'q':
109
quiet = true;
110
break;
111
case 'R':
112
recursive_flag = true;
113
break;
114
case 'x':
115
match = MATCH_REGEX;
116
break;
117
case 'y':
118
yes = true;
119
break;
120
case 0:
121
if (scriptnoexec)
122
f |= PKG_FLAG_NOEXEC;
123
break;
124
default:
125
usage_delete();
126
return (EXIT_FAILURE);
127
}
128
}
129
130
argc -= optind;
131
argv += optind;
132
133
if (argc < 1 && match != MATCH_ALL) {
134
usage_delete();
135
return (EXIT_FAILURE);
136
}
137
138
if (dry_run)
139
retcode = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
140
else
141
retcode = pkgdb_access(PKGDB_MODE_READ|PKGDB_MODE_WRITE,
142
PKGDB_DB_LOCAL);
143
144
if (retcode == EPKG_ENODB) {
145
warnx("No packages installed. Nothing to do!");
146
return (EXIT_SUCCESS);
147
} else if (retcode == EPKG_ENOACCESS) {
148
warnx("Insufficient privileges to delete packages");
149
return (EXIT_FAILURE);
150
} else if (retcode != EPKG_OK) {
151
warnx("Error accessing the package database");
152
return (EXIT_FAILURE);
153
}
154
155
if (pkgdb_open(&db, PKGDB_DEFAULT) != EPKG_OK)
156
return (EXIT_FAILURE);
157
158
if (pkgdb_obtain_lock(db, lock_type) != EPKG_OK) {
159
pkgdb_close(db);
160
warnx("Cannot get an advisory lock on a database, it is locked by another process");
161
return (EXIT_FAILURE);
162
}
163
164
165
if (pkg_jobs_new(&jobs, PKG_JOBS_DEINSTALL, db) != EPKG_OK) {
166
pkgdb_close(db);
167
return (EXIT_FAILURE);
168
}
169
170
/*
171
* By default delete packages recursively.
172
* If force mode is enabled then we try to remove packages non-recursively.
173
* However, if -f and -R flags are both enabled then we return to
174
* recursive deletion.
175
*/
176
if (!force || recursive_flag)
177
f |= PKG_FLAG_RECURSIVE;
178
179
pkg_jobs_set_flags(jobs, f);
180
181
if (match == MATCH_EXACT) {
182
for (i = 0; i < argc; i++) {
183
if (strchr(argv[i], '*') != NULL) {
184
match = MATCH_GLOB;
185
break;
186
}
187
}
188
}
189
190
if (pkg_jobs_add(jobs, match, argv, argc) == EPKG_FATAL)
191
goto cleanup;
192
193
if (pkg_jobs_solve(jobs) != EPKG_OK) {
194
fprintf(stderr, "Cannot perform request\n");
195
retcode = EXIT_FAILURE;
196
goto cleanup;
197
}
198
199
if (pkg_jobs_has_lockedpkgs(jobs)) {
200
printf("The following package(s) are locked or vital and may not ");
201
printf("be removed:\n\n");
202
pkg_jobs_iter_lockedpkgs(jobs, print_pkg, &locked_pkgs);
203
putchar('\n');
204
}
205
206
/* check if we have something to deinstall */
207
if ((nbactions = pkg_jobs_count(jobs)) == 0) {
208
if (argc == 0) {
209
if (!quiet)
210
printf("Nothing to do.\n");
211
212
retcode = EXIT_SUCCESS;
213
goto cleanup;
214
}
215
if (!quiet) {
216
printf("%d packages requested for removal: "
217
"%d locked, %d missing\n",
218
argc, locked_pkgs, argc - locked_pkgs);
219
}
220
if (locked_pkgs > 0) {
221
retcode = EPKG_LOCKED;
222
} else {
223
retcode = EXIT_FAILURE;
224
}
225
goto cleanup;
226
}
227
228
if (!quiet || dry_run) {
229
if (!quiet) {
230
print_jobs_summary(jobs,
231
"Deinstallation has been requested for the following %d packages "
232
"(of %d packages in the universe):\n\n", nbactions,
233
pkg_jobs_total(jobs));
234
}
235
if (dry_run) {
236
retcode = EXIT_SUCCESS;
237
goto cleanup;
238
}
239
rc = query_yesno(false,
240
"\nProceed with deinstalling packages? ");
241
}
242
else
243
rc = yes;
244
245
if (!rc || (retcode = pkg_jobs_apply(jobs)) != EPKG_OK)
246
goto cleanup;
247
248
if (messages != NULL) {
249
fflush(messages->fp);
250
printf("%s", messages->buf);
251
}
252
pkgdb_compact(db);
253
254
retcode = EXIT_SUCCESS;
255
256
cleanup:
257
pkgdb_release_lock(db, lock_type);
258
pkg_jobs_free(jobs);
259
pkgdb_close(db);
260
261
return (retcode);
262
}
263
264