Branch data Line data Source code
1 : : /*
2 : : * dpkg - main program for package management
3 : : * force.c - force operation support
4 : : *
5 : : * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2006-2019 Guillem Jover <guillem@debian.org>
7 : : *
8 : : * This is free software; you can redistribute it and/or modify
9 : : * it under the terms of the GNU General Public License as published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : *
13 : : * This is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include <config.h>
23 : : #include <compat.h>
24 : :
25 : : #include <errno.h>
26 : : #include <string.h>
27 : : #include <stdbool.h>
28 : : #include <stdarg.h>
29 : : #include <stdlib.h>
30 : : #include <stdio.h>
31 : :
32 : : #include <dpkg/macros.h>
33 : : #include <dpkg/i18n.h>
34 : : #include <dpkg/dpkg.h>
35 : : #include <dpkg/dpkg-db.h>
36 : : #include <dpkg/options.h>
37 : :
38 : : #include "force.h"
39 : :
40 : : static int force_mask;
41 : : static int force_flags;
42 : :
43 : : enum forcetype {
44 : : FORCETYPE_DISABLED,
45 : : FORCETYPE_ENABLED,
46 : : FORCETYPE_DAMAGE,
47 : : };
48 : :
49 : : static const char *
50 : 0 : forcetype_str(enum forcetype type)
51 : : {
52 [ # # # # ]: 0 : switch (type) {
53 : 0 : case FORCETYPE_DISABLED:
54 : 0 : return " ";
55 : 0 : case FORCETYPE_ENABLED:
56 : 0 : return "[*]";
57 : 0 : case FORCETYPE_DAMAGE:
58 : 0 : return "[!]";
59 : 0 : default:
60 : 0 : internerr("unknown force type '%d'", type);
61 : : }
62 : : }
63 : :
64 : : static const struct forceinfo {
65 : : const char *name;
66 : : int flag;
67 : : char type;
68 : : const char *desc;
69 : : } forceinfos[] = {
70 : : {
71 : : "all",
72 : : FORCE_ALL,
73 : : FORCETYPE_DAMAGE,
74 : : N_("Set all force options"),
75 : : }, {
76 : : "security-mac",
77 : : FORCE_SECURITY_MAC,
78 : : FORCETYPE_ENABLED,
79 : : N_("Use MAC based security if available"),
80 : : }, {
81 : : "downgrade",
82 : : FORCE_DOWNGRADE,
83 : : FORCETYPE_ENABLED,
84 : : N_("Replace a package with a lower version"),
85 : : }, {
86 : : "configure-any",
87 : : FORCE_CONFIGURE_ANY,
88 : : FORCETYPE_DISABLED,
89 : : N_("Configure any package which may help this one"),
90 : : }, {
91 : : "hold",
92 : : FORCE_HOLD,
93 : : FORCETYPE_DISABLED,
94 : : N_("Install or remove incidental packages even when on hold"),
95 : : }, {
96 : : "not-root",
97 : : FORCE_NON_ROOT,
98 : : FORCETYPE_DISABLED,
99 : : N_("Try to (de)install things even when not root"),
100 : : }, {
101 : : "bad-path",
102 : : FORCE_BAD_PATH,
103 : : FORCETYPE_DISABLED,
104 : : N_("PATH is missing important programs, problems likely"),
105 : : }, {
106 : : "bad-verify",
107 : : FORCE_BAD_VERIFY,
108 : : FORCETYPE_DISABLED,
109 : : N_("Install a package even if it fails authenticity check"),
110 : : }, {
111 : : "bad-version",
112 : : FORCE_BAD_VERSION,
113 : : FORCETYPE_DISABLED,
114 : : N_("Process even packages with wrong versions"),
115 : : }, {
116 : : "statoverride-add",
117 : : FORCE_STATOVERRIDE_ADD,
118 : : FORCETYPE_DISABLED,
119 : : N_("Overwrite an existing stat override when adding it"),
120 : : }, {
121 : : "statoverride-remove",
122 : : FORCE_STATOVERRIDE_DEL,
123 : : FORCETYPE_DISABLED,
124 : : N_("Ignore a missing stat override when removing it"),
125 : : }, {
126 : : "overwrite",
127 : : FORCE_OVERWRITE,
128 : : FORCETYPE_DISABLED,
129 : : N_("Overwrite a file from one package with another"),
130 : : }, {
131 : : "overwrite-diverted",
132 : : FORCE_OVERWRITE_DIVERTED,
133 : : FORCETYPE_DISABLED,
134 : : N_("Overwrite a diverted file with an undiverted version"),
135 : : }, {
136 : : "overwrite-dir",
137 : : FORCE_OVERWRITE_DIR,
138 : : FORCETYPE_DAMAGE,
139 : : N_("Overwrite one package's directory with another's file"),
140 : : }, {
141 : : "unsafe-io",
142 : : FORCE_UNSAFE_IO,
143 : : FORCETYPE_DAMAGE,
144 : : N_("Do not perform safe I/O operations when unpacking"),
145 : : }, {
146 : : "script-chrootless",
147 : : FORCE_SCRIPT_CHROOTLESS,
148 : : FORCETYPE_DAMAGE,
149 : : N_("Do not chroot into maintainer script environment"),
150 : : }, {
151 : : "confnew",
152 : : FORCE_CONFF_NEW,
153 : : FORCETYPE_DAMAGE,
154 : : N_("Always use the new config files, don't prompt"),
155 : : }, {
156 : : "confold",
157 : : FORCE_CONFF_OLD,
158 : : FORCETYPE_DAMAGE,
159 : : N_("Always use the old config files, don't prompt"),
160 : : }, {
161 : : "confdef",
162 : : FORCE_CONFF_DEF,
163 : : FORCETYPE_DAMAGE,
164 : : N_("Use the default option for new config files if one\n"
165 : : "is available, don't prompt. If no default can be found,\n"
166 : : "you will be prompted unless one of the confold or\n"
167 : : "confnew options is also given"),
168 : : }, {
169 : : "confmiss",
170 : : FORCE_CONFF_MISS,
171 : : FORCETYPE_DAMAGE,
172 : : N_("Always install missing config files"),
173 : : }, {
174 : : "confask",
175 : : FORCE_CONFF_ASK,
176 : : FORCETYPE_DAMAGE,
177 : : N_("Offer to replace config files with no new versions"),
178 : : }, {
179 : : "architecture",
180 : : FORCE_ARCHITECTURE,
181 : : FORCETYPE_DAMAGE,
182 : : N_("Process even packages with wrong or no architecture"),
183 : : }, {
184 : : "breaks",
185 : : FORCE_BREAKS,
186 : : FORCETYPE_DAMAGE,
187 : : N_("Install even if it would break another package"),
188 : : }, {
189 : : "conflicts",
190 : : FORCE_CONFLICTS,
191 : : FORCETYPE_DAMAGE,
192 : : N_("Allow installation of conflicting packages"),
193 : : }, {
194 : : "depends",
195 : : FORCE_DEPENDS,
196 : : FORCETYPE_DAMAGE,
197 : : N_("Turn all dependency problems into warnings"),
198 : : }, {
199 : : "depends-version",
200 : : FORCE_DEPENDS_VERSION,
201 : : FORCETYPE_DAMAGE,
202 : : N_("Turn dependency version problems into warnings"),
203 : : }, {
204 : : "remove-reinstreq",
205 : : FORCE_REMOVE_REINSTREQ,
206 : : FORCETYPE_DAMAGE,
207 : : N_("Remove packages which require installation"),
208 : : }, {
209 : : "remove-protected",
210 : : FORCE_REMOVE_PROTECTED,
211 : : FORCETYPE_DAMAGE,
212 : : N_("Remove a protected package"),
213 : : }, {
214 : : "remove-essential",
215 : : FORCE_REMOVE_ESSENTIAL,
216 : : FORCETYPE_DAMAGE,
217 : : N_("Remove an essential package"),
218 : : }, {
219 : : NULL
220 : : }
221 : : };
222 : :
223 : : bool
224 : 1392 : in_force(int flags)
225 : : {
226 : 1392 : return (flags & force_flags) == flags;
227 : : }
228 : :
229 : : void
230 : 190 : set_force(int flags)
231 : : {
232 : 190 : force_flags |= flags;
233 : 190 : }
234 : :
235 : : void
236 : 0 : reset_force(int flags)
237 : : {
238 : 0 : force_flags &= ~flags;
239 : 0 : }
240 : :
241 : : char *
242 : 48 : get_force_string(void)
243 : : {
244 : : const struct forceinfo *fip;
245 : 48 : struct varbuf vb = VARBUF_INIT;
246 : :
247 [ + + ]: 1440 : for (fip = forceinfos; fip->name; fip++) {
248 [ + + ]: 1392 : if ((enum force_flags)fip->flag == FORCE_ALL ||
249 [ + - ]: 1344 : (fip->flag & force_mask) != fip->flag ||
250 [ + + ]: 1344 : !in_force(fip->flag))
251 : 1296 : continue;
252 : :
253 [ + + ]: 96 : if (vb.used)
254 : 48 : varbuf_add_char(&vb, ',');
255 : 96 : varbuf_add_str(&vb, fip->name);
256 : : }
257 : :
258 : 48 : return varbuf_detach(&vb);
259 : : }
260 : :
261 : : static inline void
262 : 0 : print_forceinfo_line(int type, const char *name, const char *desc)
263 : : {
264 : 0 : printf(" %s %-18s %s\n", forcetype_str(type), name, desc);
265 : 0 : }
266 : :
267 : : static void
268 : 0 : print_forceinfo(const struct forceinfo *fi)
269 : : {
270 : : char *desc, *line;
271 : :
272 : 0 : desc = m_strdup(gettext(fi->desc));
273 : :
274 : 0 : line = strtok(desc, "\n");
275 : 0 : print_forceinfo_line(fi->type, fi->name, line);
276 [ # # ]: 0 : while ((line = strtok(NULL, "\n")))
277 : 0 : print_forceinfo_line(FORCETYPE_DISABLED, "", line);
278 : :
279 : 0 : free(desc);
280 : 0 : }
281 : :
282 : : void
283 : 0 : parse_force(const char *value, bool set)
284 : : {
285 : : const struct forceinfo *fip;
286 : :
287 [ # # ]: 0 : if (strcmp(value, "help") == 0) {
288 : 0 : char *force_string = get_force_string();
289 : :
290 : 0 : printf(_(
291 : : "%s forcing options - control behavior when problems found:\n"
292 : : " warn but continue: --force-<thing>,<thing>,...\n"
293 : : " stop with error: --refuse-<thing>,<thing>,... | --no-force-<thing>,...\n"
294 : : " Forcing things:\n"), dpkg_get_progname());
295 : :
296 [ # # ]: 0 : for (fip = forceinfos; fip->name; fip++)
297 [ # # ]: 0 : if ((enum force_flags)fip->flag == FORCE_ALL ||
298 [ # # ]: 0 : (fip->flag & force_mask) == fip->flag)
299 : 0 : print_forceinfo(fip);
300 : :
301 : 0 : printf(_(
302 : : "\n"
303 : : "WARNING - use of options marked [!] can seriously damage your installation.\n"
304 : : "Forcing options marked [*] are enabled by default.\n"));
305 : 0 : m_output(stdout, _("<standard output>"));
306 : :
307 : 0 : printf(_(
308 : : "\n"
309 : : "Currently enabled options:\n"
310 : : " %s\n"), force_string);
311 : :
312 : 0 : free(force_string);
313 : :
314 : 0 : exit(0);
315 : : }
316 : :
317 : 0 : for (;;) {
318 : : const char *comma;
319 : : size_t l;
320 : :
321 : 0 : comma = strchrnul(value, ',');
322 : 0 : l = (size_t)(comma - value);
323 [ # # ]: 0 : for (fip = forceinfos; fip->name; fip++)
324 [ # # ]: 0 : if (strncmp(fip->name, value, l) == 0 &&
325 [ # # ]: 0 : strlen(fip->name) == l)
326 : 0 : break;
327 : :
328 [ # # ]: 0 : if (!fip->name) {
329 [ # # ]: 0 : badusage(_("unknown force/refuse option '%.*s'"),
330 : : (int)min(l, 250), value);
331 [ # # ]: 0 : } else if (fip->flag) {
332 [ # # ]: 0 : if (set)
333 : 0 : set_force(fip->flag);
334 : : else
335 : 0 : reset_force(fip->flag);
336 : : } else {
337 : 0 : warning(_("obsolete force/refuse option '%s'"),
338 : 0 : fip->name);
339 : : }
340 : :
341 [ # # ]: 0 : if (*comma == '\0')
342 : 0 : break;
343 : 0 : value = ++comma;
344 : : }
345 : 0 : }
346 : :
347 : : void
348 : 95 : set_force_default(int mask)
349 : : {
350 : : const char *force_env;
351 : : const struct forceinfo *fip;
352 : :
353 : 95 : force_mask = mask;
354 : :
355 : : /* If we get passed force options from the environment, do not
356 : : * initialize from the built-in defaults. */
357 : 95 : force_env = getenv("DPKG_FORCE");
358 [ - + ]: 95 : if (force_env != NULL) {
359 [ # # ]: 0 : if (force_env[0] != '\0')
360 : 0 : parse_force(force_env, 1);
361 : 0 : return;
362 : : }
363 : :
364 [ + + ]: 2850 : for (fip = forceinfos; fip->name; fip++)
365 [ + + ]: 2755 : if (fip->type == FORCETYPE_ENABLED)
366 : 190 : set_force(fip->flag);
367 : : }
368 : :
369 : : void
370 : 0 : set_force_option(const struct cmdinfo *cip, const char *value)
371 : : {
372 : 0 : bool set = cip->arg_int;
373 : :
374 : 0 : parse_force(value, set);
375 : 0 : }
376 : :
377 : : void
378 : 0 : reset_force_option(const struct cmdinfo *cip, const char *value)
379 : : {
380 : 0 : reset_force(cip->arg_int);
381 : 0 : }
382 : :
383 : : void
384 : 0 : forcibleerr(int forceflag, const char *fmt, ...)
385 : : {
386 : : va_list args;
387 : :
388 : 0 : va_start(args, fmt);
389 [ # # ]: 0 : if (in_force(forceflag)) {
390 : 0 : warning(_("overriding problem because --force enabled:"));
391 : 0 : warningv(fmt, args);
392 : : } else {
393 : 0 : ohshitv(fmt, args);
394 : : }
395 : 0 : va_end(args);
396 : 0 : }
397 : :
398 : : int
399 : 0 : forcible_nonroot_error(int rc)
400 : : {
401 [ # # # # ]: 0 : if (in_force(FORCE_NON_ROOT) && errno == EPERM)
402 : 0 : return 0;
403 : 0 : return rc;
404 : : }
|