Commit | Line | Data |
---|---|---|
1479465f GJ |
1 | /* |
2 | * dpkg - main program for package management | |
3 | * packages.c - common to actions that process packages | |
4 | * | |
5 | * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk> | |
6 | * Copyright © 2006-2014 Guillem Jover <guillem@debian.org> | |
7 | * Copyright © 2011 Linaro Limited | |
8 | * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org> | |
9 | * | |
10 | * This is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * This is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
22 | */ | |
23 | ||
24 | #include <config.h> | |
25 | #include <compat.h> | |
26 | ||
27 | #include <sys/types.h> | |
28 | #include <sys/stat.h> | |
29 | ||
30 | #include <assert.h> | |
31 | #include <string.h> | |
32 | #include <fcntl.h> | |
33 | #include <dirent.h> | |
34 | #include <unistd.h> | |
35 | #include <stdlib.h> | |
36 | #include <stdio.h> | |
37 | ||
38 | #include <dpkg/i18n.h> | |
39 | #include <dpkg/dpkg.h> | |
40 | #include <dpkg/dpkg-db.h> | |
41 | #include <dpkg/pkg-list.h> | |
42 | #include <dpkg/pkg-queue.h> | |
43 | #include <dpkg/string.h> | |
44 | #include <dpkg/options.h> | |
45 | ||
46 | #include "filesdb.h" | |
47 | #include "infodb.h" | |
48 | #include "main.h" | |
49 | ||
50 | static struct pkginfo *progress_bytrigproc; | |
51 | static struct pkg_queue queue = PKG_QUEUE_INIT; | |
52 | ||
53 | int sincenothing = 0, dependtry = 1; | |
54 | ||
55 | void | |
56 | enqueue_package(struct pkginfo *pkg) | |
57 | { | |
58 | ensure_package_clientdata(pkg); | |
59 | if (pkg->clientdata->enqueued) | |
60 | return; | |
61 | pkg->clientdata->enqueued = true; | |
62 | pkg_queue_push(&queue, pkg); | |
63 | } | |
64 | ||
65 | void | |
66 | enqueue_package_mark_seen(struct pkginfo *pkg) | |
67 | { | |
68 | enqueue_package(pkg); | |
69 | pkg->clientdata->cmdline_seen++; | |
70 | } | |
71 | ||
72 | static void | |
73 | enqueue_pending(void) | |
74 | { | |
75 | struct pkgiterator *iter; | |
76 | struct pkginfo *pkg; | |
77 | ||
78 | iter = pkg_db_iter_new(); | |
79 | while ((pkg = pkg_db_iter_next_pkg(iter)) != NULL) { | |
80 | switch (cipaction->arg_int) { | |
81 | case act_configure: | |
82 | if (!(pkg->status == PKG_STAT_UNPACKED || | |
83 | pkg->status == PKG_STAT_HALFCONFIGURED || | |
84 | pkg->trigpend_head)) | |
85 | continue; | |
86 | if (pkg->want != PKG_WANT_INSTALL) | |
87 | continue; | |
88 | break; | |
89 | case act_triggers: | |
90 | if (!pkg->trigpend_head) | |
91 | continue; | |
92 | if (pkg->want != PKG_WANT_INSTALL) | |
93 | continue; | |
94 | break; | |
95 | case act_remove: | |
96 | case act_purge: | |
97 | if (pkg->want != PKG_WANT_PURGE) { | |
98 | if (pkg->want != PKG_WANT_DEINSTALL) | |
99 | continue; | |
100 | if (pkg->status == PKG_STAT_CONFIGFILES) | |
101 | continue; | |
102 | } | |
103 | if (pkg->status == PKG_STAT_NOTINSTALLED) | |
104 | continue; | |
105 | break; | |
106 | default: | |
107 | internerr("unknown action '%d'", cipaction->arg_int); | |
108 | } | |
109 | enqueue_package(pkg); | |
110 | } | |
111 | pkg_db_iter_free(iter); | |
112 | } | |
113 | ||
114 | static void | |
115 | enqueue_specified(const char *const *argv) | |
116 | { | |
117 | const char *thisarg; | |
118 | ||
119 | while ((thisarg = *argv++) != NULL) { | |
120 | struct pkginfo *pkg; | |
121 | ||
122 | pkg = dpkg_options_parse_pkgname(cipaction, thisarg); | |
123 | if (pkg->status == PKG_STAT_NOTINSTALLED && | |
124 | str_match_end(pkg->set->name, DEBEXT)) { | |
125 | badusage(_("you must specify packages by their own names, " | |
126 | "not by quoting the names of the files they come in")); | |
127 | } | |
128 | enqueue_package_mark_seen(pkg); | |
129 | } | |
130 | ||
131 | if (cipaction->arg_int == act_configure) | |
132 | trigproc_populate_deferred(); | |
133 | } | |
134 | ||
135 | int | |
136 | packages(const char *const *argv) | |
137 | { | |
138 | trigproc_install_hooks(); | |
139 | ||
140 | modstatdb_open(f_noact ? msdbrw_readonly : | |
141 | fc_nonroot ? msdbrw_write : | |
142 | msdbrw_needsuperuser); | |
143 | checkpath(); | |
144 | pkg_infodb_upgrade(); | |
145 | ||
146 | log_message("startup packages %s", cipaction->olong); | |
147 | ||
148 | if (f_pending) { | |
149 | if (*argv) | |
150 | badusage(_("--%s --pending does not take any non-option arguments"),cipaction->olong); | |
151 | ||
152 | enqueue_pending(); | |
153 | } else { | |
154 | if (!*argv) | |
155 | badusage(_("--%s needs at least one package name argument"), cipaction->olong); | |
156 | ||
157 | enqueue_specified(argv); | |
158 | } | |
159 | ||
160 | ensure_diversions(); | |
161 | ||
162 | process_queue(); | |
163 | trigproc_run_deferred(); | |
164 | ||
165 | modstatdb_shutdown(); | |
166 | ||
167 | return 0; | |
168 | } | |
169 | ||
170 | void process_queue(void) { | |
171 | struct pkg_list *rundown; | |
172 | struct pkginfo *volatile pkg; | |
173 | volatile enum action action_todo; | |
174 | jmp_buf ejbuf; | |
175 | enum pkg_istobe istobe = PKG_ISTOBE_NORMAL; | |
176 | ||
177 | if (abort_processing) | |
178 | return; | |
179 | ||
180 | clear_istobes(); | |
181 | ||
182 | switch (cipaction->arg_int) { | |
183 | case act_triggers: | |
184 | case act_configure: | |
185 | case act_install: | |
186 | istobe = PKG_ISTOBE_INSTALLNEW; | |
187 | break; | |
188 | case act_remove: | |
189 | case act_purge: | |
190 | istobe = PKG_ISTOBE_REMOVE; | |
191 | break; | |
192 | default: | |
193 | internerr("unknown action '%d'", cipaction->arg_int); | |
194 | } | |
195 | for (rundown = queue.head; rundown; rundown = rundown->next) { | |
196 | ensure_package_clientdata(rundown->pkg); | |
197 | ||
198 | /* We have processed this package more than once. There are no duplicates | |
199 | * as we make sure of that when enqueuing them. */ | |
200 | if (rundown->pkg->clientdata->cmdline_seen > 1) { | |
201 | switch (cipaction->arg_int) { | |
202 | case act_triggers: | |
203 | case act_configure: case act_remove: case act_purge: | |
204 | printf(_("Package %s listed more than once, only processing once.\n"), | |
205 | pkg_name(rundown->pkg, pnaw_nonambig)); | |
206 | break; | |
207 | case act_install: | |
208 | printf(_("More than one copy of package %s has been unpacked\n" | |
209 | " in this run ! Only configuring it once.\n"), | |
210 | pkg_name(rundown->pkg, pnaw_nonambig)); | |
211 | break; | |
212 | default: | |
213 | internerr("unknown action '%d'", cipaction->arg_int); | |
214 | } | |
215 | } | |
216 | rundown->pkg->clientdata->istobe = istobe; | |
217 | } | |
218 | ||
219 | while (!pkg_queue_is_empty(&queue)) { | |
220 | pkg = pkg_queue_pop(&queue); | |
221 | if (!pkg) | |
222 | continue; /* Duplicate, which we removed earlier. */ | |
223 | ||
224 | ensure_package_clientdata(pkg); | |
225 | pkg->clientdata->enqueued = false; | |
226 | ||
227 | action_todo = cipaction->arg_int; | |
228 | ||
229 | if (sincenothing++ > queue.length * 3 + 2) { | |
230 | /* Make sure that even if we have exceeded the queue since not having | |
231 | * made any progress, we are not getting stuck trying to progress by | |
232 | * trigger processing, w/o jumping into the next dependtry. */ | |
233 | dependtry++; | |
234 | sincenothing = 0; | |
235 | assert(dependtry <= 4); | |
236 | } else if (sincenothing > queue.length * 2 + 2) { | |
237 | /* XXX: This probably needs moving into a new dependtry instead. */ | |
238 | if (progress_bytrigproc && progress_bytrigproc->trigpend_head) { | |
239 | enqueue_package(pkg); | |
240 | pkg = progress_bytrigproc; | |
241 | action_todo = act_configure; | |
242 | } else { | |
243 | dependtry++; | |
244 | sincenothing = 0; | |
245 | assert(dependtry <= 4); | |
246 | } | |
247 | } | |
248 | ||
249 | debug(dbg_general, "process queue pkg %s queue.len %d progress %d, try %d", | |
250 | pkg_name(pkg, pnaw_always), queue.length, sincenothing, dependtry); | |
251 | ||
252 | if (pkg->status > PKG_STAT_INSTALLED) | |
253 | internerr("package status (%d) > PKG_STAT_INSTALLED", pkg->status); | |
254 | ||
255 | if (setjmp(ejbuf)) { | |
256 | /* Give up on it from the point of view of other packages, i.e. reset | |
257 | * istobe. */ | |
258 | pkg->clientdata->istobe = PKG_ISTOBE_NORMAL; | |
259 | ||
260 | pop_error_context(ehflag_bombout); | |
261 | if (abort_processing) | |
262 | return; | |
263 | continue; | |
264 | } | |
265 | push_error_context_jump(&ejbuf, print_error_perpackage, | |
266 | pkg_name(pkg, pnaw_nonambig)); | |
267 | ||
268 | switch (action_todo) { | |
269 | case act_triggers: | |
270 | if (!pkg->trigpend_head) | |
271 | ohshit(_("package %.250s is not ready for trigger processing\n" | |
272 | " (current status '%.250s' with no pending triggers)"), | |
273 | pkg_name(pkg, pnaw_nonambig), pkg_status_name(pkg)); | |
274 | /* Fall through. */ | |
275 | case act_install: | |
276 | /* Don't try to configure pkgs that we've just disappeared. */ | |
277 | if (pkg->status == PKG_STAT_NOTINSTALLED) | |
278 | break; | |
279 | /* Fall through. */ | |
280 | case act_configure: | |
281 | /* Do whatever is most needed. */ | |
282 | if (pkg->trigpend_head) | |
283 | trigproc(pkg, TRIGPROC_REQUIRED); | |
284 | else | |
285 | deferred_configure(pkg); | |
286 | break; | |
287 | case act_remove: case act_purge: | |
288 | deferred_remove(pkg); | |
289 | break; | |
290 | default: | |
291 | internerr("unknown action '%d'", cipaction->arg_int); | |
292 | } | |
293 | m_output(stdout, _("<standard output>")); | |
294 | m_output(stderr, _("<standard error>")); | |
295 | ||
296 | pop_error_context(ehflag_normaltidy); | |
297 | } | |
298 | assert(!queue.length); | |
299 | } | |
300 | ||
301 | /*** Dependency processing - common to --configure and --remove. ***/ | |
302 | ||
303 | /* | |
304 | * The algorithm for deciding what to configure or remove first is as | |
305 | * follows: | |
306 | * | |
307 | * Loop through all packages doing a ‘try 1’ until we've been round and | |
308 | * nothing has been done, then do ‘try 2’ and ‘try 3’ likewise. | |
309 | * | |
310 | * When configuring, in each try we check to see whether all | |
311 | * dependencies of this package are done. If so we do it. If some of | |
312 | * the dependencies aren't done yet but will be later we defer the | |
313 | * package, otherwise it is an error. | |
314 | * | |
315 | * When removing, in each try we check to see whether there are any | |
316 | * packages that would have dependencies missing if we removed this | |
317 | * one. If not we remove it now. If some of these packages are | |
318 | * themselves scheduled for removal we defer the package until they | |
319 | * have been done. | |
320 | * | |
321 | * The criteria for satisfying a dependency vary with the various | |
322 | * tries. In try 1 we treat the dependencies as absolute. In try 2 we | |
323 | * check break any cycles in the dependency graph involving the package | |
324 | * we are trying to process before trying to process the package | |
325 | * normally. In try 3 (which should only be reached if | |
326 | * --force-depends-version is set) we ignore version number clauses in | |
327 | * Depends lines. In try 4 (only reached if --force-depends is set) we | |
328 | * say "ok" regardless. | |
329 | * | |
330 | * If we are configuring and one of the packages we depend on is | |
331 | * awaiting configuration but wasn't specified in the argument list we | |
332 | * will add it to the argument list if --configure-any is specified. | |
333 | * In this case we note this as having "done something" so that we | |
334 | * don't needlessly escalate to higher levels of dependency checking | |
335 | * and breaking. | |
336 | */ | |
337 | ||
338 | enum found_status { | |
339 | FOUND_NONE = 0, | |
340 | FOUND_DEFER = 1, | |
341 | FOUND_FORCED = 2, | |
342 | FOUND_OK = 3, | |
343 | }; | |
344 | ||
345 | /* | |
346 | * Return values: | |
347 | * 0: cannot be satisfied. | |
348 | * 1: defer: may be satisfied later, when other packages are better or | |
349 | * at higher dependtry due to --force | |
350 | * will set *fixbytrig to package whose trigger processing would help | |
351 | * if applicable (and leave it alone otherwise). | |
352 | * 2: not satisfied but forcing | |
353 | * (*interestingwarnings >= 0 on exit? caller is to print oemsgs). | |
354 | * 3: satisfied now. | |
355 | */ | |
356 | static enum found_status | |
357 | deppossi_ok_found(struct pkginfo *possdependee, struct pkginfo *requiredby, | |
358 | struct pkginfo *removing, struct deppossi *provider, | |
359 | struct pkginfo **fixbytrig, | |
360 | bool *matched, struct deppossi *checkversion, | |
361 | int *interestingwarnings, struct varbuf *oemsgs) | |
362 | { | |
363 | enum found_status thisf; | |
364 | ||
365 | if (ignore_depends(possdependee)) { | |
366 | debug(dbg_depcondetail," ignoring depended package so ok and found"); | |
367 | return FOUND_OK; | |
368 | } | |
369 | thisf = FOUND_NONE; | |
370 | if (possdependee == removing) { | |
371 | if (provider) { | |
372 | varbuf_printf(oemsgs, | |
373 | _(" Package %s which provides %s is to be removed.\n"), | |
374 | pkg_name(possdependee, pnaw_nonambig), | |
375 | provider->ed->name); | |
376 | } else { | |
377 | varbuf_printf(oemsgs, _(" Package %s is to be removed.\n"), | |
378 | pkg_name(possdependee, pnaw_nonambig)); | |
379 | } | |
380 | ||
381 | *matched = true; | |
382 | debug(dbg_depcondetail," removing possdependee, returning %d",thisf); | |
383 | return thisf; | |
384 | } | |
385 | switch (possdependee->status) { | |
386 | case PKG_STAT_UNPACKED: | |
387 | case PKG_STAT_HALFCONFIGURED: | |
388 | case PKG_STAT_TRIGGERSAWAITED: | |
389 | case PKG_STAT_TRIGGERSPENDING: | |
390 | case PKG_STAT_INSTALLED: | |
391 | if (checkversion) { | |
392 | if (provider) { | |
393 | debug(dbg_depcondetail, " checking package %s provided by pkg %s", | |
394 | checkversion->ed->name, pkg_name(possdependee, pnaw_always)); | |
395 | if (!pkg_virtual_deppossi_satisfied(checkversion, provider)) { | |
396 | varbuf_printf(oemsgs, | |
397 | _(" Version of %s on system, provided by %s, is %s.\n"), | |
398 | checkversion->ed->name, | |
399 | pkg_name(possdependee, pnaw_always), | |
400 | versiondescribe(&provider->version, vdew_nonambig)); | |
401 | if (fc_dependsversion) | |
402 | thisf = (dependtry >= 3) ? FOUND_FORCED : FOUND_DEFER; | |
403 | debug(dbg_depcondetail, " bad version"); | |
404 | goto unsuitable; | |
405 | } | |
406 | } else { | |
407 | debug(dbg_depcondetail, " checking non-provided pkg %s", | |
408 | pkg_name(possdependee, pnaw_always)); | |
409 | if (!versionsatisfied(&possdependee->installed, checkversion)) { | |
410 | varbuf_printf(oemsgs, _(" Version of %s on system is %s.\n"), | |
411 | pkg_name(possdependee, pnaw_nonambig), | |
412 | versiondescribe(&possdependee->installed.version, | |
413 | vdew_nonambig)); | |
414 | if (fc_dependsversion) | |
415 | thisf = (dependtry >= 3) ? FOUND_FORCED : FOUND_DEFER; | |
416 | debug(dbg_depcondetail, " bad version"); | |
417 | goto unsuitable; | |
418 | } | |
419 | } | |
420 | } | |
421 | if (possdependee->status == PKG_STAT_INSTALLED || | |
422 | possdependee->status == PKG_STAT_TRIGGERSPENDING) { | |
423 | debug(dbg_depcondetail," is installed, ok and found"); | |
424 | return FOUND_OK; | |
425 | } | |
426 | if (possdependee->status == PKG_STAT_TRIGGERSAWAITED) { | |
427 | assert(possdependee->trigaw.head); | |
428 | if (removing || | |
429 | !(f_triggers || | |
430 | possdependee->clientdata->istobe == PKG_ISTOBE_INSTALLNEW)) { | |
431 | if (provider) { | |
432 | varbuf_printf(oemsgs, | |
433 | _(" Package %s which provides %s awaits trigger processing.\n"), | |
434 | pkg_name(possdependee, pnaw_nonambig), | |
435 | provider->ed->name); | |
436 | } else { | |
437 | varbuf_printf(oemsgs, | |
438 | _(" Package %s awaits trigger processing.\n"), | |
439 | pkg_name(possdependee, pnaw_nonambig)); | |
440 | } | |
441 | debug(dbg_depcondetail, " triggers-awaited, no fixbytrig"); | |
442 | goto unsuitable; | |
443 | } | |
444 | /* We don't check the status of trigaw.head->pend here, just in case | |
445 | * we get into the pathological situation where Triggers-Awaited but | |
446 | * the named package doesn't actually have any pending triggers. In | |
447 | * that case we queue the non-pending package for trigger processing | |
448 | * anyway, and that trigger processing will be a noop except for | |
449 | * sorting out all of the packages which name it in Triggers-Awaited. | |
450 | * | |
451 | * (This situation can only arise if modstatdb_note success in | |
452 | * clearing the triggers-pending status of the pending package | |
453 | * but then fails to go on to update the awaiters.) */ | |
454 | *fixbytrig = possdependee->trigaw.head->pend; | |
455 | debug(dbg_depcondetail, | |
456 | " triggers-awaited, fixbytrig '%s', defer", | |
457 | pkg_name(*fixbytrig, pnaw_always)); | |
458 | return FOUND_DEFER; | |
459 | } | |
460 | if (possdependee->clientdata && | |
461 | possdependee->clientdata->istobe == PKG_ISTOBE_INSTALLNEW) { | |
462 | debug(dbg_depcondetail," unpacked/halfconfigured, defer"); | |
463 | return FOUND_DEFER; | |
464 | } else if (!removing && fc_configureany && | |
465 | !skip_due_to_hold(possdependee) && | |
466 | !(possdependee->status == PKG_STAT_HALFCONFIGURED)) { | |
467 | notice(_("also configuring '%s' (required by '%s')"), | |
468 | pkg_name(possdependee, pnaw_nonambig), | |
469 | pkg_name(requiredby, pnaw_nonambig)); | |
470 | enqueue_package(possdependee); | |
471 | sincenothing = 0; | |
472 | return FOUND_DEFER; | |
473 | } else { | |
474 | if (provider) { | |
475 | varbuf_printf(oemsgs, | |
476 | _(" Package %s which provides %s is not configured yet.\n"), | |
477 | pkg_name(possdependee, pnaw_nonambig), | |
478 | provider->ed->name); | |
479 | } else { | |
480 | varbuf_printf(oemsgs, _(" Package %s is not configured yet.\n"), | |
481 | pkg_name(possdependee, pnaw_nonambig)); | |
482 | } | |
483 | ||
484 | debug(dbg_depcondetail, " not configured/able"); | |
485 | goto unsuitable; | |
486 | } | |
487 | ||
488 | default: | |
489 | if (provider) { | |
490 | varbuf_printf(oemsgs, | |
491 | _(" Package %s which provides %s is not installed.\n"), | |
492 | pkg_name(possdependee, pnaw_nonambig), | |
493 | provider->ed->name); | |
494 | } else { | |
495 | varbuf_printf(oemsgs, _(" Package %s is not installed.\n"), | |
496 | pkg_name(possdependee, pnaw_nonambig)); | |
497 | } | |
498 | ||
499 | debug(dbg_depcondetail, " not installed"); | |
500 | goto unsuitable; | |
501 | } | |
502 | ||
503 | unsuitable: | |
504 | debug(dbg_depcondetail, " returning %d", thisf); | |
505 | (*interestingwarnings)++; | |
506 | ||
507 | return thisf; | |
508 | } | |
509 | ||
510 | static void | |
511 | breaks_check_one(struct varbuf *aemsgs, enum dep_check *ok, | |
512 | struct deppossi *breaks, struct pkginfo *broken, | |
513 | struct pkginfo *breaker, struct deppossi *virtbroken) | |
514 | { | |
515 | struct varbuf depmsg = VARBUF_INIT; | |
516 | ||
517 | debug(dbg_depcondetail, " checking breaker %s virtbroken %s", | |
518 | pkg_name(breaker, pnaw_always), | |
519 | virtbroken ? virtbroken->ed->name : "<none>"); | |
520 | ||
521 | if (breaker->status == PKG_STAT_NOTINSTALLED || | |
522 | breaker->status == PKG_STAT_CONFIGFILES) | |
523 | return; | |
524 | if (broken == breaker) return; | |
525 | if (!versionsatisfied(&broken->installed, breaks)) return; | |
526 | /* The test below can only trigger if dep_breaks start having | |
527 | * arch qualifiers different from “any”. */ | |
528 | if (!archsatisfied(&broken->installed, breaks)) | |
529 | return; | |
530 | if (ignore_depends(breaker)) return; | |
531 | if (virtbroken && ignore_depends(&virtbroken->ed->pkg)) | |
532 | return; | |
533 | if (virtbroken && !pkg_virtual_deppossi_satisfied(breaks, virtbroken)) | |
534 | return; | |
535 | ||
536 | varbufdependency(&depmsg, breaks->up); | |
537 | varbuf_end_str(&depmsg); | |
538 | varbuf_printf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"), | |
539 | pkg_name(breaker, pnaw_nonambig), | |
540 | versiondescribe(&breaker->installed.version, vdew_nonambig), | |
541 | depmsg.buf, gettext(statusstrings[breaker->status])); | |
542 | varbuf_destroy(&depmsg); | |
543 | ||
544 | if (virtbroken) { | |
545 | varbuf_printf(aemsgs, _(" %s (%s) provides %s.\n"), | |
546 | pkg_name(broken, pnaw_nonambig), | |
547 | versiondescribe(&broken->installed.version, vdew_nonambig), | |
548 | virtbroken->ed->name); | |
549 | } else if (breaks->verrel != DPKG_RELATION_NONE) { | |
550 | varbuf_printf(aemsgs, _(" Version of %s to be configured is %s.\n"), | |
551 | pkg_name(broken, pnaw_nonambig), | |
552 | versiondescribe(&broken->installed.version, vdew_nonambig)); | |
553 | if (fc_dependsversion) return; | |
554 | } | |
555 | if (force_breaks(breaks)) return; | |
556 | *ok = DEP_CHECK_HALT; | |
557 | } | |
558 | ||
559 | static void | |
560 | breaks_check_target(struct varbuf *aemsgs, enum dep_check *ok, | |
561 | struct pkginfo *broken, struct pkgset *target, | |
562 | struct deppossi *virtbroken) | |
563 | { | |
564 | struct deppossi *possi; | |
565 | ||
566 | for (possi = target->depended.installed; possi; possi = possi->rev_next) { | |
567 | if (possi->up->type != dep_breaks) continue; | |
568 | breaks_check_one(aemsgs, ok, possi, broken, possi->up->up, virtbroken); | |
569 | } | |
570 | } | |
571 | ||
572 | enum dep_check | |
573 | breakses_ok(struct pkginfo *pkg, struct varbuf *aemsgs) | |
574 | { | |
575 | struct dependency *dep; | |
576 | struct deppossi *virtbroken; | |
577 | enum dep_check ok = DEP_CHECK_OK; | |
578 | ||
579 | debug(dbg_depcon, " checking Breaks"); | |
580 | ||
581 | breaks_check_target(aemsgs, &ok, pkg, pkg->set, NULL); | |
582 | ||
583 | for (dep= pkg->installed.depends; dep; dep= dep->next) { | |
584 | if (dep->type != dep_provides) continue; | |
585 | virtbroken = dep->list; | |
586 | debug(dbg_depcondetail, " checking virtbroken %s", virtbroken->ed->name); | |
587 | breaks_check_target(aemsgs, &ok, pkg, virtbroken->ed, virtbroken); | |
588 | } | |
589 | return ok; | |
590 | } | |
591 | ||
592 | /* | |
593 | * Checks [Pre]-Depends only. | |
594 | */ | |
595 | enum dep_check | |
596 | dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing, | |
597 | struct varbuf *aemsgs) | |
598 | { | |
599 | /* Valid values: 2 = ok, 1 = defer, 0 = halt. */ | |
600 | enum dep_check ok; | |
601 | /* Valid values: 0 = none, 1 = defer, 2 = withwarning, 3 = ok. */ | |
602 | enum found_status found, thisf; | |
603 | int interestingwarnings; | |
604 | bool matched, anycannotfixbytrig; | |
605 | struct varbuf oemsgs = VARBUF_INIT; | |
606 | struct dependency *dep; | |
607 | struct deppossi *possi, *provider; | |
608 | struct pkginfo *possfixbytrig, *canfixbytrig; | |
609 | ||
610 | interestingwarnings= 0; | |
611 | ok = DEP_CHECK_OK; | |
612 | debug(dbg_depcon,"checking dependencies of %s (- %s)", | |
613 | pkg_name(pkg, pnaw_always), | |
614 | removing ? pkg_name(removing, pnaw_always) : "<none>"); | |
615 | ||
616 | anycannotfixbytrig = false; | |
617 | canfixbytrig = NULL; | |
618 | for (dep= pkg->installed.depends; dep; dep= dep->next) { | |
619 | if (dep->type != dep_depends && dep->type != dep_predepends) continue; | |
620 | debug(dbg_depcondetail," checking group ..."); | |
621 | matched = false; | |
622 | varbuf_reset(&oemsgs); | |
623 | found = FOUND_NONE; | |
624 | possfixbytrig = NULL; | |
625 | for (possi = dep->list; found != FOUND_OK && possi; possi = possi->next) { | |
626 | struct deppossi_pkg_iterator *possi_iter; | |
627 | struct pkginfo *pkg_pos; | |
628 | ||
629 | debug(dbg_depcondetail," checking possibility -> %s",possi->ed->name); | |
630 | if (possi->cyclebreak) { | |
631 | debug(dbg_depcondetail," break cycle so ok and found"); | |
632 | found = FOUND_OK; | |
633 | break; | |
634 | } | |
635 | ||
636 | thisf = FOUND_NONE; | |
637 | possi_iter = deppossi_pkg_iter_new(possi, wpb_installed); | |
638 | while ((pkg_pos = deppossi_pkg_iter_next(possi_iter))) { | |
639 | thisf = deppossi_ok_found(pkg_pos, pkg, removing, NULL, | |
640 | &possfixbytrig, &matched, possi, | |
641 | &interestingwarnings, &oemsgs); | |
642 | if (thisf > found) | |
643 | found = thisf; | |
644 | if (found == FOUND_OK) | |
645 | break; | |
646 | } | |
647 | deppossi_pkg_iter_free(possi_iter); | |
648 | ||
649 | if (found != FOUND_OK) { | |
650 | for (provider = possi->ed->depended.installed; | |
651 | found != FOUND_OK && provider; | |
652 | provider = provider->rev_next) { | |
653 | if (provider->up->type != dep_provides) | |
654 | continue; | |
655 | debug(dbg_depcondetail, " checking provider %s", | |
656 | pkg_name(provider->up->up, pnaw_always)); | |
657 | if (!deparchsatisfied(&provider->up->up->installed, provider->arch, | |
658 | possi)) { | |
659 | debug(dbg_depcondetail, " provider does not satisfy arch"); | |
660 | continue; | |
661 | } | |
662 | thisf = deppossi_ok_found(provider->up->up, pkg, removing, provider, | |
663 | &possfixbytrig, &matched, possi, | |
664 | &interestingwarnings, &oemsgs); | |
665 | if (thisf == FOUND_DEFER && provider->up->up == pkg && !removing) { | |
666 | /* IOW, if the pkg satisfies its own dep (via a provide), then | |
667 | * we let it pass, even if it isn't configured yet (as we're | |
668 | * installing it). */ | |
669 | thisf = FOUND_OK; | |
670 | } | |
671 | if (thisf > found) | |
672 | found = thisf; | |
673 | } | |
674 | } | |
675 | debug(dbg_depcondetail," found %d",found); | |
676 | if (thisf > found) found= thisf; | |
677 | } | |
678 | if (fc_depends) { | |
679 | thisf = (dependtry >= 4) ? FOUND_FORCED : FOUND_DEFER; | |
680 | if (thisf > found) { | |
681 | found = thisf; | |
682 | debug(dbg_depcondetail, " rescued by force-depends, found %d", found); | |
683 | } | |
684 | } | |
685 | debug(dbg_depcondetail, " found %d matched %d possfixbytrig %s", | |
686 | found, matched, | |
687 | possfixbytrig ? pkg_name(possfixbytrig, pnaw_always) : "-"); | |
688 | if (removing && !matched) continue; | |
689 | switch (found) { | |
690 | case FOUND_NONE: | |
691 | anycannotfixbytrig = true; | |
692 | ok = DEP_CHECK_HALT; | |
693 | /* Fall through. */ | |
694 | case FOUND_FORCED: | |
695 | varbuf_add_str(aemsgs, " "); | |
696 | varbuf_add_pkgbin_name(aemsgs, pkg, &pkg->installed, pnaw_nonambig); | |
697 | varbuf_add_str(aemsgs, _(" depends on ")); | |
698 | varbufdependency(aemsgs, dep); | |
699 | if (interestingwarnings) { | |
700 | /* Don't print the line about the package to be removed if | |
701 | * that's the only line. */ | |
702 | varbuf_end_str(&oemsgs); | |
703 | varbuf_add_str(aemsgs, _("; however:\n")); | |
704 | varbuf_add_str(aemsgs, oemsgs.buf); | |
705 | } else { | |
706 | varbuf_add_str(aemsgs, ".\n"); | |
707 | } | |
708 | break; | |
709 | case FOUND_DEFER: | |
710 | if (possfixbytrig) | |
711 | canfixbytrig = possfixbytrig; | |
712 | else | |
713 | anycannotfixbytrig = true; | |
714 | if (ok > DEP_CHECK_DEFER) | |
715 | ok = DEP_CHECK_DEFER; | |
716 | break; | |
717 | case FOUND_OK: | |
718 | break; | |
719 | default: | |
720 | internerr("unknown value for found '%d'", found); | |
721 | } | |
722 | } | |
723 | if (ok == DEP_CHECK_HALT && | |
724 | (pkg->clientdata && pkg->clientdata->istobe == PKG_ISTOBE_REMOVE)) | |
725 | ok = DEP_CHECK_DEFER; | |
726 | if (!anycannotfixbytrig && canfixbytrig) | |
727 | progress_bytrigproc = canfixbytrig; | |
728 | ||
729 | varbuf_destroy(&oemsgs); | |
730 | debug(dbg_depcon,"ok %d msgs >>%.*s<<", ok, (int)aemsgs->used, aemsgs->buf); | |
731 | return ok; | |
732 | } |