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