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 *
forcetype_str(enum forcetype type)50 forcetype_str(enum forcetype type)
51 {
52 switch (type) {
53 case FORCETYPE_DISABLED:
54 return " ";
55 case FORCETYPE_ENABLED:
56 return "[*]";
57 case FORCETYPE_DAMAGE:
58 return "[!]";
59 default:
60 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_("Process 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-essential",
210 FORCE_REMOVE_ESSENTIAL,
211 FORCETYPE_DAMAGE,
212 N_("Remove an essential package"),
213 }, {
214 NULL
215 }
216 };
217
218 bool
in_force(int flags)219 in_force(int flags)
220 {
221 return (flags & force_flags) == flags;
222 }
223
224 void
set_force(int flags)225 set_force(int flags)
226 {
227 force_flags |= flags;
228 }
229
230 void
reset_force(int flags)231 reset_force(int flags)
232 {
233 force_flags &= ~flags;
234 }
235
236 char *
get_force_string(void)237 get_force_string(void)
238 {
239 const struct forceinfo *fip;
240 struct varbuf vb = VARBUF_INIT;
241
242 for (fip = forceinfos; fip->name; fip++) {
243 if ((enum force_flags)fip->flag == FORCE_ALL ||
244 (fip->flag & force_mask) != fip->flag ||
245 !in_force(fip->flag))
246 continue;
247
248 if (vb.used)
249 varbuf_add_char(&vb, ',');
250 varbuf_add_str(&vb, fip->name);
251 }
252 varbuf_end_str(&vb);
253
254 return varbuf_detach(&vb);
255 }
256
257 static inline void
print_forceinfo_line(int type,const char * name,const char * desc)258 print_forceinfo_line(int type, const char *name, const char *desc)
259 {
260 printf(" %s %-18s %s\n", forcetype_str(type), name, desc);
261 }
262
263 static void
print_forceinfo(const struct forceinfo * fi)264 print_forceinfo(const struct forceinfo *fi)
265 {
266 char *desc, *line;
267
268 desc = m_strdup(gettext(fi->desc));
269
270 line = strtok(desc, "\n");
271 print_forceinfo_line(fi->type, fi->name, line);
272 while ((line = strtok(NULL, "\n")))
273 print_forceinfo_line(FORCETYPE_DISABLED, "", line);
274
275 free(desc);
276 }
277
278 void
parse_force(const char * value,bool set)279 parse_force(const char *value, bool set)
280 {
281 const char *comma;
282 size_t l;
283 const struct forceinfo *fip;
284
285 if (strcmp(value, "help") == 0) {
286 printf(_(
287 "%s forcing options - control behaviour when problems found:\n"
288 " warn but continue: --force-<thing>,<thing>,...\n"
289 " stop with error: --refuse-<thing>,<thing>,... | --no-force-<thing>,...\n"
290 " Forcing things:\n"), dpkg_get_progname());
291
292 for (fip = forceinfos; fip->name; fip++)
293 if ((enum force_flags)fip->flag == FORCE_ALL ||
294 (fip->flag & force_mask) == fip->flag)
295 print_forceinfo(fip);
296
297 printf(_(
298 "\n"
299 "WARNING - use of options marked [!] can seriously damage your installation.\n"
300 "Forcing options marked [*] are enabled by default.\n"));
301 m_output(stdout, _("<standard output>"));
302
303 printf(_(
304 "\n"
305 "Currently enabled options:\n"
306 " %s\n"), get_force_string());
307
308 exit(0);
309 }
310
311 for (;;) {
312 comma = strchrnul(value, ',');
313 l = (size_t)(comma - value);
314 for (fip = forceinfos; fip->name; fip++)
315 if (strncmp(fip->name, value, l) == 0 &&
316 strlen(fip->name) == l)
317 break;
318
319 if (!fip->name) {
320 badusage(_("unknown force/refuse option '%.*s'"),
321 (int)min(l, 250), value);
322 } else if (fip->flag) {
323 if (set)
324 set_force(fip->flag);
325 else
326 reset_force(fip->flag);
327 } else {
328 warning(_("obsolete force/refuse option '%s'"),
329 fip->name);
330 }
331
332 if (*comma == '\0')
333 break;
334 value = ++comma;
335 }
336 }
337
338 void
set_force_default(int mask)339 set_force_default(int mask)
340 {
341 const char *force_env;
342 const struct forceinfo *fip;
343
344 force_mask = mask;
345
346 /* If we get passed force options from the environment, do not
347 * initialize from the built-in defaults. */
348 force_env = getenv("DPKG_FORCE");
349 if (force_env != NULL) {
350 if (force_env[0] != '\0')
351 parse_force(force_env, 1);
352 return;
353 }
354
355 for (fip = forceinfos; fip->name; fip++)
356 if (fip->type == FORCETYPE_ENABLED)
357 set_force(fip->flag);
358 }
359
360 void
set_force_option(const struct cmdinfo * cip,const char * value)361 set_force_option(const struct cmdinfo *cip, const char *value)
362 {
363 bool set = cip->arg_int;
364
365 parse_force(value, set);
366 }
367
368 void
reset_force_option(const struct cmdinfo * cip,const char * value)369 reset_force_option(const struct cmdinfo *cip, const char *value)
370 {
371 reset_force(cip->arg_int);
372 }
373
374 void
forcibleerr(int forceflag,const char * fmt,...)375 forcibleerr(int forceflag, const char *fmt, ...)
376 {
377 va_list args;
378
379 va_start(args, fmt);
380 if (in_force(forceflag)) {
381 warning(_("overriding problem because --force enabled:"));
382 warningv(fmt, args);
383 } else {
384 ohshitv(fmt, args);
385 }
386 va_end(args);
387 }
388
389 int
forcible_nonroot_error(int rc)390 forcible_nonroot_error(int rc)
391 {
392 if (in_force(FORCE_NON_ROOT) && errno == EPERM)
393 return 0;
394 return rc;
395 }
396