Branch data Line data Source code
1 : : /*
2 : : * dpkg - main program for package management
3 : : * enquiry.c - status enquiry and listing options
4 : : *
5 : : * Copyright © 1995,1996 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2006, 2008-2016 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 : :
29 : : #include <string.h>
30 : : #include <fcntl.h>
31 : : #include <unistd.h>
32 : : #include <stdbool.h>
33 : : #include <stdlib.h>
34 : : #include <stdio.h>
35 : :
36 : : #include <dpkg/i18n.h>
37 : : #include <dpkg/dpkg.h>
38 : : #include <dpkg/dpkg-db.h>
39 : : #include <dpkg/arch.h>
40 : : #include <dpkg/pkg-array.h>
41 : : #include <dpkg/pkg-show.h>
42 : : #include <dpkg/triglib.h>
43 : : #include <dpkg/string.h>
44 : : #include <dpkg/options.h>
45 : : #include <dpkg/db-ctrl.h>
46 : : #include <dpkg/db-fsys.h>
47 : :
48 : : #include "main.h"
49 : :
50 : : struct audit_problem {
51 : : bool (*check)(struct pkginfo *, const struct audit_problem *problem);
52 : : union {
53 : : int number;
54 : : const char *string;
55 : : } value;
56 : : const char *explanation;
57 : : };
58 : :
59 : : static bool
60 : 0 : audit_reinstreq(struct pkginfo *pkg, const struct audit_problem *problem)
61 : : {
62 : 0 : return pkg->eflag & PKG_EFLAG_REINSTREQ;
63 : : }
64 : :
65 : : static bool
66 : 0 : audit_status(struct pkginfo *pkg, const struct audit_problem *problem)
67 : : {
68 [ # # ]: 0 : if (pkg->eflag & PKG_EFLAG_REINSTREQ)
69 : 0 : return false;
70 : 0 : return (int)pkg->status == problem->value.number;
71 : : }
72 : :
73 : : static bool
74 : 0 : audit_infofile(struct pkginfo *pkg, const struct audit_problem *problem)
75 : : {
76 [ # # ]: 0 : if (pkg->status < PKG_STAT_HALFINSTALLED)
77 : 0 : return false;
78 : 0 : return !pkg_infodb_has_file(pkg, &pkg->installed, problem->value.string);
79 : : }
80 : :
81 : : static bool
82 : 0 : audit_arch(struct pkginfo *pkg, const struct audit_problem *problem)
83 : : {
84 [ # # ]: 0 : if (pkg->status < PKG_STAT_HALFINSTALLED)
85 : 0 : return false;
86 : 0 : return pkg->installed.arch->type == (enum dpkg_arch_type)problem->value.number;
87 : : }
88 : :
89 : : static const struct audit_problem audit_problems[] = {
90 : : {
91 : : .check = audit_reinstreq,
92 : : .value.number = 0,
93 : : .explanation = N_(
94 : : "The following packages are in a mess due to serious problems during\n"
95 : : "installation. They must be reinstalled for them (and any packages\n"
96 : : "that depend on them) to function properly:\n")
97 : : }, {
98 : : .check = audit_status,
99 : : .value.number = PKG_STAT_UNPACKED,
100 : : .explanation = N_(
101 : : "The following packages have been unpacked but not yet configured.\n"
102 : : "They must be configured using dpkg --configure or the configure\n"
103 : : "menu option in dselect for them to work:\n")
104 : : }, {
105 : : .check = audit_status,
106 : : .value.number = PKG_STAT_HALFCONFIGURED,
107 : : .explanation = N_(
108 : : "The following packages are only half configured, probably due to problems\n"
109 : : "configuring them the first time. The configuration should be retried using\n"
110 : : "dpkg --configure <package> or the configure menu option in dselect:\n")
111 : : }, {
112 : : .check = audit_status,
113 : : .value.number = PKG_STAT_HALFINSTALLED,
114 : : .explanation = N_(
115 : : "The following packages are only half installed, due to problems during\n"
116 : : "installation. The installation can probably be completed by retrying it;\n"
117 : : "the packages can be removed using dselect or dpkg --remove:\n")
118 : : }, {
119 : : .check = audit_status,
120 : : .value.number = PKG_STAT_TRIGGERSAWAITED,
121 : : .explanation = N_(
122 : : "The following packages are awaiting processing of triggers that they\n"
123 : : "have activated in other packages. This processing can be requested using\n"
124 : : "dselect or dpkg --configure --pending (or dpkg --triggers-only):\n")
125 : : }, {
126 : : .check = audit_status,
127 : : .value.number = PKG_STAT_TRIGGERSPENDING,
128 : : .explanation = N_(
129 : : "The following packages have been triggered, but the trigger processing\n"
130 : : "has not yet been done. Trigger processing can be requested using\n"
131 : : "dselect or dpkg --configure --pending (or dpkg --triggers-only):\n")
132 : : }, {
133 : : .check = audit_infofile,
134 : : .value.string = LISTFILE,
135 : : .explanation = N_(
136 : : "The following packages are missing the list control file in the\n"
137 : : "database, they need to be reinstalled:\n")
138 : : }, {
139 : : .check = audit_infofile,
140 : : .value.string = HASHFILE,
141 : : .explanation = N_(
142 : : "The following packages are missing the md5sums control file in the\n"
143 : : "database, they need to be reinstalled:\n")
144 : : }, {
145 : : .check = audit_arch,
146 : : .value.number = DPKG_ARCH_EMPTY,
147 : : .explanation = N_("The following packages do not have an architecture:\n")
148 : : }, {
149 : : .check = audit_arch,
150 : : .value.number = DPKG_ARCH_ILLEGAL,
151 : : .explanation = N_("The following packages have an illegal architecture:\n")
152 : : }, {
153 : : .check = audit_arch,
154 : : .value.number = DPKG_ARCH_UNKNOWN,
155 : : .explanation = N_(
156 : : "The following packages have an unknown foreign architecture, which will\n"
157 : : "cause dependency issues on front-ends. This can be fixed by registering\n"
158 : : "the foreign architecture with dpkg --add-architecture:\n")
159 : : }, {
160 : : .check = NULL
161 : : }
162 : : };
163 : :
164 : 0 : static void describebriefly(struct pkginfo *pkg) {
165 : : int maxl, l;
166 : : const char *pdesc;
167 : :
168 : 0 : maxl= 57;
169 : 0 : l= strlen(pkg->set->name);
170 [ # # ]: 0 : if (l>20) maxl -= (l-20);
171 : :
172 : 0 : pdesc = pkgbin_synopsis(pkg, &pkg->installed, &l);
173 : 0 : l = min(l, maxl);
174 : :
175 : 0 : printf(" %-20s %.*s\n", pkg_name(pkg, pnaw_nonambig), l, pdesc);
176 : 0 : }
177 : :
178 : : static struct pkginfo *
179 : 0 : pkg_array_mapper(const char *name)
180 : : {
181 : : struct pkginfo *pkg;
182 : :
183 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, name);
184 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
185 : 0 : notice(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
186 : :
187 : 0 : return pkg;
188 : : }
189 : :
190 : : int
191 : 0 : audit(const char *const *argv)
192 : : {
193 : : const struct audit_problem *problem;
194 : : struct pkg_array array;
195 : 0 : bool head_running = false;
196 : : int i;
197 : :
198 : 0 : modstatdb_open(msdbrw_readonly);
199 : :
200 [ # # ]: 0 : if (!*argv)
201 : 0 : pkg_array_init_from_hash(&array);
202 : : else
203 : 0 : pkg_array_init_from_names(&array, pkg_array_mapper, (const char **)argv);
204 : :
205 : 0 : pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
206 : :
207 [ # # ]: 0 : for (problem = audit_problems; problem->check; problem++) {
208 : 0 : bool head = false;
209 : :
210 [ # # ]: 0 : for (i = 0; i < array.n_pkgs; i++) {
211 : 0 : struct pkginfo *pkg = array.pkgs[i];
212 : :
213 [ # # ]: 0 : if (!problem->check(pkg, problem))
214 : 0 : continue;
215 [ # # ]: 0 : if (!head_running) {
216 [ # # ]: 0 : if (modstatdb_is_locked())
217 : 0 : puts(_(
218 : : "Another process has locked the database for writing, and might currently be\n"
219 : : "modifying it, some of the following problems might just be due to that.\n"));
220 : 0 : head_running = true;
221 : : }
222 [ # # ]: 0 : if (!head) {
223 : 0 : fputs(gettext(problem->explanation), stdout);
224 : 0 : head = true;
225 : : }
226 : 0 : describebriefly(pkg);
227 : : }
228 : :
229 [ # # ]: 0 : if (head) putchar('\n');
230 : : }
231 : :
232 : 0 : pkg_array_destroy(&array);
233 : :
234 : 0 : m_output(stdout, _("<standard output>"));
235 : :
236 : 0 : return 0;
237 : : }
238 : :
239 : : struct sectionentry {
240 : : struct sectionentry *next;
241 : : const char *name;
242 : : int count;
243 : : };
244 : :
245 : : static bool
246 : 0 : yettobeunpacked(struct pkginfo *pkg, const char **thissect)
247 : : {
248 [ # # ]: 0 : if (pkg->want != PKG_WANT_INSTALL)
249 : 0 : return false;
250 : :
251 [ # # # ]: 0 : switch (pkg->status) {
252 : 0 : case PKG_STAT_UNPACKED:
253 : : case PKG_STAT_INSTALLED:
254 : : case PKG_STAT_HALFCONFIGURED:
255 : : case PKG_STAT_TRIGGERSPENDING:
256 : : case PKG_STAT_TRIGGERSAWAITED:
257 : 0 : return false;
258 : 0 : case PKG_STAT_NOTINSTALLED:
259 : : case PKG_STAT_HALFINSTALLED:
260 : : case PKG_STAT_CONFIGFILES:
261 [ # # ]: 0 : if (thissect)
262 [ # # ]: 0 : *thissect = str_is_set(pkg->section) ? pkg->section :
263 : 0 : C_("section", "<unknown>");
264 : 0 : return true;
265 : 0 : default:
266 : 0 : internerr("unknown package status '%d'", pkg->status);
267 : : }
268 : : return false;
269 : : }
270 : :
271 : : int
272 : 0 : unpackchk(const char *const *argv)
273 : : {
274 : : int totalcount, sects;
275 : : struct sectionentry *sectionentries, *se, **sep;
276 : : struct pkg_hash_iter *iter;
277 : : struct pkginfo *pkg;
278 : : const char *thissect;
279 : : char buf[20];
280 : : int width;
281 : :
282 [ # # ]: 0 : if (*argv)
283 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
284 : :
285 : 0 : modstatdb_open(msdbrw_readonly);
286 : :
287 : 0 : totalcount= 0;
288 : 0 : sectionentries = NULL;
289 : 0 : sects= 0;
290 : 0 : iter = pkg_hash_iter_new();
291 [ # # ]: 0 : while ((pkg = pkg_hash_iter_next_pkg(iter))) {
292 [ # # ]: 0 : if (!yettobeunpacked(pkg, &thissect)) continue;
293 [ # # # # ]: 0 : for (se= sectionentries; se && strcasecmp(thissect,se->name); se= se->next);
294 [ # # ]: 0 : if (!se) {
295 : 0 : se = nfmalloc(sizeof(*se));
296 : 0 : for (sep= §ionentries;
297 [ # # # # ]: 0 : *sep && strcasecmp(thissect,(*sep)->name) > 0;
298 : 0 : sep= &(*sep)->next);
299 : 0 : se->name= thissect;
300 : 0 : se->count= 0;
301 : 0 : se->next= *sep;
302 : 0 : *sep= se;
303 : 0 : sects++;
304 : : }
305 : 0 : se->count++; totalcount++;
306 : : }
307 : 0 : pkg_hash_iter_free(iter);
308 : :
309 [ # # ]: 0 : if (totalcount == 0)
310 : 0 : return 0;
311 : :
312 [ # # ]: 0 : if (totalcount <= 12) {
313 : 0 : iter = pkg_hash_iter_new();
314 [ # # ]: 0 : while ((pkg = pkg_hash_iter_next_pkg(iter))) {
315 [ # # ]: 0 : if (!yettobeunpacked(pkg, NULL))
316 : 0 : continue;
317 : 0 : describebriefly(pkg);
318 : : }
319 : 0 : pkg_hash_iter_free(iter);
320 [ # # ]: 0 : } else if (sects <= 12) {
321 [ # # ]: 0 : for (se= sectionentries; se; se= se->next) {
322 : 0 : sprintf(buf,"%d",se->count);
323 : 0 : printf(_(" %d in %s: "),se->count,se->name);
324 : 0 : width= 70-strlen(se->name)-strlen(buf);
325 [ # # ]: 0 : while (width > 59) { putchar(' '); width--; }
326 : 0 : iter = pkg_hash_iter_new();
327 [ # # ]: 0 : while ((pkg = pkg_hash_iter_next_pkg(iter))) {
328 : : const char *pkgname;
329 : :
330 [ # # ]: 0 : if (!yettobeunpacked(pkg,&thissect)) continue;
331 [ # # ]: 0 : if (strcasecmp(thissect,se->name)) continue;
332 : 0 : pkgname = pkg_name(pkg, pnaw_nonambig);
333 : 0 : width -= strlen(pkgname);
334 : 0 : width--;
335 [ # # ]: 0 : if (width < 4) { printf(" ..."); break; }
336 : 0 : printf(" %s", pkgname);
337 : : }
338 : 0 : pkg_hash_iter_free(iter);
339 : 0 : putchar('\n');
340 : : }
341 : : } else {
342 : 0 : printf(P_(" %d package, from the following section:",
343 : : " %d packages, from the following sections:", totalcount),
344 : : totalcount);
345 : 0 : width= 0;
346 [ # # ]: 0 : for (se= sectionentries; se; se= se->next) {
347 : 0 : sprintf(buf,"%d",se->count);
348 : 0 : width -= (6 + strlen(se->name) + strlen(buf));
349 [ # # ]: 0 : if (width < 0) { putchar('\n'); width= 73 - strlen(se->name) - strlen(buf); }
350 : 0 : printf(" %s (%d)",se->name,se->count);
351 : : }
352 : 0 : putchar('\n');
353 : : }
354 : :
355 : 0 : m_output(stdout, _("<standard output>"));
356 : :
357 : 0 : return 0;
358 : : }
359 : :
360 : : static const struct assert_feature {
361 : : const char *name;
362 : : const char *desc;
363 : : const char *version;
364 : : } assert_features[] = {
365 : : {
366 : : .name = "support-predepends",
367 : : .desc = N_("the Pre-Depends field"),
368 : : .version = "1.1.0",
369 : : }, {
370 : : .name = "working-epoch",
371 : : .desc = N_("epochs in versions"),
372 : : .version = "1.4.0.7",
373 : : }, {
374 : : .name = "long-filenames",
375 : : .desc = N_("long filenames in .deb archives"),
376 : : .version = "1.4.1.17",
377 : : }, {
378 : : .name = "multi-conrep",
379 : : .desc = N_("multiple Conflicts and Replaces"),
380 : : .version = "1.4.1.19",
381 : : }, {
382 : : .name = "multi-arch",
383 : : .desc = N_("multi-arch fields and semantics"),
384 : : .version = "1.16.2",
385 : : }, {
386 : : .name = "versioned-provides",
387 : : .desc = N_("versioned relationships in the Provides field"),
388 : : .version = "1.17.11",
389 : : }, {
390 : : .name = "protected-field",
391 : : .desc = N_("the Protected field"),
392 : : .version = "1.20.1",
393 : : }, {
394 : : .name = NULL,
395 : : }
396 : : };
397 : :
398 : : static int
399 : 0 : assert_version_support(const char *const *argv,
400 : : const struct assert_feature *feature)
401 : : {
402 : : const char *running_version_str;
403 : 0 : struct dpkg_version running_version = DPKG_VERSION_INIT;
404 : 0 : struct dpkg_version version = { 0, feature->version, NULL };
405 : 0 : struct dpkg_error err = DPKG_ERROR_INIT;
406 : :
407 [ # # ]: 0 : if (*argv)
408 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
409 : :
410 : : /*
411 : : * When using the feature asserts, we want to know whether the currently
412 : : * running dpkg, which we might be running under (say from within a
413 : : * maintainer script) and which might have a different version, supports
414 : : * the requested feature. As dpkg is an Essential package, it is expected
415 : : * to work even when just unpacked, and so its own version is enough.
416 : : */
417 : 0 : running_version_str = getenv("DPKG_RUNNING_VERSION");
418 : :
419 : : /*
420 : : * If we are not running from within a maintainer script, then that means
421 : : * once we do, the executed dpkg will support the requested feature, if
422 : : * we know about it. Always return success in that case.
423 : : */
424 [ # # ]: 0 : if (str_is_unset(running_version_str))
425 : 0 : return 0;
426 : :
427 [ # # ]: 0 : if (parseversion(&running_version, running_version_str, &err) < 0)
428 : 0 : ohshit(_("cannot parse dpkg running version '%s': %s"),
429 : : running_version_str, err.str);
430 : :
431 [ # # ]: 0 : if (dpkg_version_relate(&running_version, DPKG_RELATION_GE, &version))
432 : 0 : return 0;
433 : :
434 : 0 : printf(_("Running version of dpkg does not support %s.\n"
435 : : " Please upgrade to at least dpkg %s, and then try again.\n"),
436 : 0 : feature->desc, versiondescribe(&version, vdew_nonambig));
437 : 0 : return 1;
438 : : }
439 : :
440 : : const char *assert_feature_name;
441 : :
442 : : int
443 : 0 : assert_feature(const char *const *argv)
444 : : {
445 : : const struct assert_feature *feature;
446 : :
447 [ # # ]: 0 : if (strcmp(assert_feature_name, "help") == 0) {
448 : 0 : printf(_("%s assert options - assert whether features are supported:\n"),
449 : : dpkg_get_progname());
450 : :
451 [ # # ]: 0 : for (feature = assert_features; feature->name; feature++) {
452 : 0 : printf(" %-19s %-9s %s\n", feature->name, feature->version,
453 : 0 : gettext(feature->desc));
454 : : }
455 : :
456 : 0 : exit(0);
457 : : }
458 : :
459 [ # # ]: 0 : for (feature = assert_features; feature->name; feature++) {
460 [ # # ]: 0 : if (strcmp(feature->name, assert_feature_name) != 0)
461 : 0 : continue;
462 : :
463 : 0 : return assert_version_support(argv, feature);
464 : : }
465 : :
466 : 0 : badusage(_("unknown --%s-<feature>"), cipaction->olong);
467 : : }
468 : :
469 : : /**
470 : : * Print a single package which:
471 : : * (a) is the target of one or more relevant predependencies.
472 : : * (b) has itself no unsatisfied pre-dependencies.
473 : : *
474 : : * If such a package is present output is the Packages file entry,
475 : : * which can be massaged as appropriate.
476 : : *
477 : : * Exit status:
478 : : * 0 = a package printed, OK
479 : : * 1 = no suitable package available
480 : : * 2 = error
481 : : */
482 : : int
483 : 0 : predeppackage(const char *const *argv)
484 : : {
485 : : static struct varbuf vb;
486 : :
487 : : struct pkg_hash_iter *iter;
488 : 0 : struct pkginfo *pkg = NULL, *startpkg, *trypkg;
489 : : struct dependency *dep;
490 : : struct deppossi *possi, *provider;
491 : :
492 [ # # ]: 0 : if (*argv)
493 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
494 : :
495 : 0 : modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
496 : : /* We use clientdata->istobe to detect loops. */
497 : 0 : clear_istobes();
498 : :
499 : 0 : dep = NULL;
500 : 0 : iter = pkg_hash_iter_new();
501 [ # # # # ]: 0 : while (!dep && (pkg = pkg_hash_iter_next_pkg(iter))) {
502 : : /* Ignore packages user doesn't want. */
503 [ # # ]: 0 : if (pkg->want != PKG_WANT_INSTALL)
504 : 0 : continue;
505 : : /* Ignore packages not available. */
506 [ # # ]: 0 : if (!pkg->archives)
507 : 0 : continue;
508 : 0 : pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
509 [ # # ]: 0 : for (dep= pkg->available.depends; dep; dep= dep->next) {
510 [ # # ]: 0 : if (dep->type != dep_predepends) continue;
511 [ # # ]: 0 : if (depisok(dep, &vb, NULL, NULL, true))
512 : 0 : continue;
513 : : /* This will leave dep non-NULL, and so exit the loop. */
514 : 0 : break;
515 : : }
516 : 0 : pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
517 : : /* If dep is NULL we go and get the next package. */
518 : : }
519 : 0 : pkg_hash_iter_free(iter);
520 : :
521 [ # # ]: 0 : if (!dep)
522 : 0 : return 1; /* Not found. */
523 [ # # ]: 0 : if (pkg == NULL)
524 : 0 : internerr("unexpected unfound package");
525 : :
526 : 0 : startpkg= pkg;
527 : 0 : pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
528 : :
529 : : /* OK, we have found an unsatisfied predependency.
530 : : * Now go and find the first thing we need to install, as a first step
531 : : * towards satisfying it. */
532 : : do {
533 : : /* We search for a package which would satisfy dep, and put it in pkg. */
534 : 0 : for (possi = dep->list, pkg = NULL;
535 [ # # # # ]: 0 : !pkg && possi;
536 : 0 : possi=possi->next) {
537 : : struct deppossi_pkg_iterator *possi_iter;
538 : :
539 : 0 : possi_iter = deppossi_pkg_iter_new(possi, wpb_available);
540 [ # # # # ]: 0 : while (!pkg && (trypkg = deppossi_pkg_iter_next(possi_iter))) {
541 [ # # ]: 0 : if (trypkg->archives &&
542 [ # # # # ]: 0 : trypkg->clientdata->istobe == PKG_ISTOBE_NORMAL &&
543 : 0 : versionsatisfied(&trypkg->available, possi)) {
544 : 0 : pkg = trypkg;
545 : 0 : break;
546 : : }
547 : 0 : for (provider = possi->ed->depended.available;
548 [ # # # # ]: 0 : !pkg && provider;
549 : 0 : provider = provider->next) {
550 [ # # ]: 0 : if (provider->up->type != dep_provides)
551 : 0 : continue;
552 [ # # ]: 0 : if (!pkg_virtual_deppossi_satisfied(possi, provider))
553 : 0 : continue;
554 : 0 : trypkg = provider->up->up;
555 [ # # ]: 0 : if (!trypkg->archives)
556 : 0 : continue;
557 [ # # ]: 0 : if (trypkg->clientdata->istobe == PKG_ISTOBE_NORMAL) {
558 : 0 : pkg = trypkg;
559 : 0 : break;
560 : : }
561 : : }
562 : : }
563 : 0 : deppossi_pkg_iter_free(possi_iter);
564 : : }
565 [ # # ]: 0 : if (!pkg) {
566 : 0 : varbuf_reset(&vb);
567 : 0 : describedepcon(&vb,dep);
568 : 0 : notice(_("cannot see how to satisfy pre-dependency:\n %s"), vb.buf);
569 : 0 : ohshit(_("cannot satisfy pre-dependencies for %.250s (wanted due to %.250s)"),
570 : 0 : pkgbin_name(dep->up, &dep->up->available, pnaw_nonambig),
571 : : pkgbin_name(startpkg, &startpkg->available, pnaw_nonambig));
572 : : }
573 : 0 : pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
574 [ # # ]: 0 : for (dep= pkg->available.depends; dep; dep= dep->next) {
575 [ # # ]: 0 : if (dep->type != dep_predepends) continue;
576 [ # # ]: 0 : if (depisok(dep, &vb, NULL, NULL, true))
577 : 0 : continue;
578 : : /* This will leave dep non-NULL, and so exit the loop. */
579 : 0 : break;
580 : : }
581 [ # # ]: 0 : } while (dep);
582 : :
583 : : /* OK, we've found it - pkg has no unsatisfied pre-dependencies! */
584 : 0 : write_stanza(stdout, _("<standard output>"), pkg, &pkg->available);
585 : :
586 : 0 : m_output(stdout, _("<standard output>"));
587 : :
588 : 0 : return 0;
589 : : }
590 : :
591 : : int
592 : 0 : printarch(const char *const *argv)
593 : : {
594 [ # # ]: 0 : if (*argv)
595 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
596 : :
597 : 0 : printf("%s\n", dpkg_arch_get(DPKG_ARCH_NATIVE)->name);
598 : :
599 : 0 : m_output(stdout, _("<standard output>"));
600 : :
601 : 0 : return 0;
602 : : }
603 : :
604 : : int
605 : 0 : print_foreign_arches(const char *const *argv)
606 : : {
607 : : struct dpkg_arch *arch;
608 : :
609 [ # # ]: 0 : if (*argv)
610 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
611 : :
612 : 0 : dpkg_arch_load_list();
613 : :
614 [ # # ]: 0 : for (arch = dpkg_arch_get_list(); arch; arch = arch->next) {
615 [ # # ]: 0 : if (arch->type != DPKG_ARCH_FOREIGN)
616 : 0 : continue;
617 : :
618 : 0 : printf("%s\n", arch->name);
619 : : }
620 : :
621 : 0 : m_output(stdout, _("<standard output>"));
622 : :
623 : 0 : return 0;
624 : : }
625 : :
626 : : int
627 : 0 : validate_pkgname(const char *const *argv)
628 : : {
629 : : const char *emsg;
630 : :
631 [ # # # # ]: 0 : if (!argv[0] || argv[1])
632 : 0 : badusage(_("--%s takes one <pkgname> argument"), cipaction->olong);
633 : :
634 : 0 : emsg = pkg_name_is_illegal(argv[0]);
635 [ # # ]: 0 : if (emsg)
636 : 0 : ohshit(_("package name '%s' is invalid: %s"), argv[0], emsg);
637 : :
638 : 0 : return 0;
639 : : }
640 : :
641 : : int
642 : 0 : validate_trigname(const char *const *argv)
643 : : {
644 : : const char *emsg;
645 : :
646 [ # # # # ]: 0 : if (!argv[0] || argv[1])
647 : 0 : badusage(_("--%s takes one <trigname> argument"), cipaction->olong);
648 : :
649 : 0 : emsg = trig_name_is_illegal(argv[0]);
650 [ # # ]: 0 : if (emsg)
651 : 0 : ohshit(_("trigger name '%s' is invalid: %s"), argv[0], emsg);
652 : :
653 : 0 : return 0;
654 : : }
655 : :
656 : : int
657 : 0 : validate_archname(const char *const *argv)
658 : : {
659 : : const char *emsg;
660 : :
661 [ # # # # ]: 0 : if (!argv[0] || argv[1])
662 : 0 : badusage(_("--%s takes one <archname> argument"), cipaction->olong);
663 : :
664 : 0 : emsg = dpkg_arch_name_is_illegal(argv[0]);
665 [ # # ]: 0 : if (emsg)
666 : 0 : ohshit(_("architecture name '%s' is invalid: %s"), argv[0], emsg);
667 : :
668 : 0 : return 0;
669 : : }
670 : :
671 : : int
672 : 0 : validate_version(const char *const *argv)
673 : : {
674 : : struct dpkg_version version;
675 : : struct dpkg_error err;
676 : :
677 [ # # # # ]: 0 : if (!argv[0] || argv[1])
678 : 0 : badusage(_("--%s takes one <version> argument"), cipaction->olong);
679 : :
680 [ # # ]: 0 : if (parseversion(&version, argv[0], &err) < 0) {
681 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[0]);
682 : 0 : dpkg_error_destroy(&err);
683 : :
684 : 0 : return 1;
685 : : }
686 : :
687 : 0 : return 0;
688 : : }
689 : :
690 : : int
691 : 0 : cmpversions(const char *const *argv)
692 : : {
693 : : struct relationinfo {
694 : : const char *op;
695 : : /* These values are exit status codes. */
696 : : int if_lesser, if_equal, if_greater;
697 : : int if_none_a, if_none_both, if_none_b;
698 : : bool obsolete;
699 : : };
700 : :
701 : : static const struct relationinfo relationinfos[]= {
702 : : {
703 : : .op = "le",
704 : : .if_lesser = EXIT_SUCCESS,
705 : : .if_equal = EXIT_SUCCESS,
706 : : .if_greater = EXIT_FAILURE,
707 : : .if_none_a = EXIT_SUCCESS,
708 : : .if_none_both = EXIT_SUCCESS,
709 : : .if_none_b = EXIT_FAILURE,
710 : : }, {
711 : : .op = "lt",
712 : : .if_lesser = EXIT_SUCCESS,
713 : : .if_equal = EXIT_FAILURE,
714 : : .if_greater = EXIT_FAILURE,
715 : : .if_none_a = EXIT_SUCCESS,
716 : : .if_none_both = EXIT_FAILURE,
717 : : .if_none_b = EXIT_FAILURE,
718 : : }, {
719 : : .op = "eq",
720 : : .if_lesser = EXIT_FAILURE,
721 : : .if_equal = EXIT_SUCCESS,
722 : : .if_greater = EXIT_FAILURE,
723 : : .if_none_a = EXIT_FAILURE,
724 : : .if_none_both = EXIT_SUCCESS,
725 : : .if_none_b = EXIT_FAILURE,
726 : : }, {
727 : : .op = "ne",
728 : : .if_lesser = EXIT_SUCCESS,
729 : : .if_equal = EXIT_FAILURE,
730 : : .if_greater = EXIT_SUCCESS,
731 : : .if_none_a = EXIT_SUCCESS,
732 : : .if_none_both = EXIT_FAILURE,
733 : : .if_none_b = EXIT_SUCCESS,
734 : : }, {
735 : : .op = "ge",
736 : : .if_lesser = EXIT_FAILURE,
737 : : .if_equal = EXIT_SUCCESS,
738 : : .if_greater = EXIT_SUCCESS,
739 : : .if_none_a = EXIT_FAILURE,
740 : : .if_none_both = EXIT_SUCCESS,
741 : : .if_none_b = EXIT_SUCCESS,
742 : : }, {
743 : : .op = "gt",
744 : : .if_lesser = EXIT_FAILURE,
745 : : .if_equal = EXIT_FAILURE,
746 : : .if_greater = EXIT_SUCCESS,
747 : : .if_none_a = EXIT_FAILURE,
748 : : .if_none_both = EXIT_FAILURE,
749 : : .if_none_b = EXIT_SUCCESS,
750 : : },
751 : :
752 : : /* These treat an empty version as later than any version. */
753 : : {
754 : : .op = "le-nl",
755 : : .if_lesser = EXIT_SUCCESS,
756 : : .if_equal = EXIT_SUCCESS,
757 : : .if_greater = EXIT_FAILURE,
758 : : .if_none_a = EXIT_FAILURE,
759 : : .if_none_both = EXIT_SUCCESS,
760 : : .if_none_b = EXIT_SUCCESS,
761 : : }, {
762 : : .op = "lt-nl",
763 : : .if_lesser = EXIT_SUCCESS,
764 : : .if_equal = EXIT_FAILURE,
765 : : .if_greater = EXIT_FAILURE,
766 : : .if_none_a = EXIT_FAILURE,
767 : : .if_none_both = EXIT_FAILURE,
768 : : .if_none_b = EXIT_SUCCESS,
769 : : }, {
770 : : .op = "ge-nl",
771 : : .if_lesser = EXIT_FAILURE,
772 : : .if_equal = EXIT_SUCCESS,
773 : : .if_greater = EXIT_SUCCESS,
774 : : .if_none_a = EXIT_SUCCESS,
775 : : .if_none_both = EXIT_SUCCESS,
776 : : .if_none_b = EXIT_FAILURE,
777 : : }, {
778 : : .op = "gt-nl",
779 : : .if_lesser = EXIT_FAILURE,
780 : : .if_equal = EXIT_FAILURE,
781 : : .if_greater = EXIT_SUCCESS,
782 : : .if_none_a = EXIT_SUCCESS,
783 : : .if_none_both = EXIT_FAILURE,
784 : : .if_none_b = EXIT_FAILURE,
785 : : },
786 : :
787 : : /* For compatibility with dpkg control file syntax. */
788 : : {
789 : : .op = "<",
790 : : .if_lesser = EXIT_SUCCESS,
791 : : .if_equal = EXIT_SUCCESS,
792 : : .if_greater = EXIT_FAILURE,
793 : : .if_none_a = EXIT_SUCCESS,
794 : : .if_none_both = EXIT_SUCCESS,
795 : : .if_none_b = EXIT_FAILURE,
796 : : .obsolete = true,
797 : : }, {
798 : : .op = "<=",
799 : : .if_lesser = EXIT_SUCCESS,
800 : : .if_equal = EXIT_SUCCESS,
801 : : .if_greater = EXIT_FAILURE,
802 : : .if_none_a = EXIT_SUCCESS,
803 : : .if_none_both = EXIT_SUCCESS,
804 : : .if_none_b = EXIT_FAILURE,
805 : : }, {
806 : : .op = "<<",
807 : : .if_lesser = EXIT_SUCCESS,
808 : : .if_equal = EXIT_FAILURE,
809 : : .if_greater = EXIT_FAILURE,
810 : : .if_none_a = EXIT_SUCCESS,
811 : : .if_none_both = EXIT_FAILURE,
812 : : .if_none_b = EXIT_FAILURE,
813 : : }, {
814 : : .op = "=",
815 : : .if_lesser = EXIT_FAILURE,
816 : : .if_equal = EXIT_SUCCESS,
817 : : .if_greater = EXIT_FAILURE,
818 : : .if_none_a = EXIT_FAILURE,
819 : : .if_none_both = EXIT_SUCCESS,
820 : : .if_none_b = EXIT_FAILURE,
821 : : }, {
822 : : .op = ">",
823 : : .if_lesser = EXIT_FAILURE,
824 : : .if_equal = EXIT_SUCCESS,
825 : : .if_greater = EXIT_SUCCESS,
826 : : .if_none_a = EXIT_FAILURE,
827 : : .if_none_both = EXIT_SUCCESS,
828 : : .if_none_b = EXIT_SUCCESS,
829 : : .obsolete = true,
830 : : }, {
831 : : .op = ">=",
832 : : .if_lesser = EXIT_FAILURE,
833 : : .if_equal = EXIT_SUCCESS,
834 : : .if_greater = EXIT_SUCCESS,
835 : : .if_none_a = EXIT_FAILURE,
836 : : .if_none_both = EXIT_SUCCESS,
837 : : .if_none_b = EXIT_SUCCESS,
838 : : }, {
839 : : .op = ">>",
840 : : .if_lesser = EXIT_FAILURE,
841 : : .if_equal = EXIT_FAILURE,
842 : : .if_greater = EXIT_SUCCESS,
843 : : .if_none_a = EXIT_FAILURE,
844 : : .if_none_both = EXIT_FAILURE,
845 : : .if_none_b = EXIT_SUCCESS,
846 : : }, {
847 : : .op = NULL,
848 : : }
849 : : };
850 : :
851 : : const struct relationinfo *rip;
852 : : struct dpkg_version a, b;
853 : : struct dpkg_error err;
854 : : int rc;
855 : :
856 [ # # # # : 0 : if (!argv[0] || !argv[1] || !argv[2] || argv[3])
# # # # ]
857 : 0 : badusage(_("--compare-versions takes three arguments:"
858 : : " <version> <relation> <version>"));
859 : :
860 [ # # # # ]: 0 : for (rip = relationinfos; rip->op && strcmp(rip->op, argv[1]); rip++)
861 : : ;
862 : :
863 [ # # ]: 0 : if (!rip->op)
864 : 0 : badusage(_("--compare-versions bad relation"));
865 : :
866 [ # # ]: 0 : if (rip->obsolete)
867 : 0 : warning(_("--%s used with obsolete relation operator '%s'"),
868 : 0 : cipaction->olong, rip->op);
869 : :
870 [ # # # # ]: 0 : if (*argv[0] && strcmp(argv[0],"<unknown>")) {
871 [ # # ]: 0 : if (parseversion(&a, argv[0], &err) < 0) {
872 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[0]);
873 : 0 : dpkg_error_destroy(&err);
874 : : }
875 : : } else {
876 : 0 : dpkg_version_blank(&a);
877 : : }
878 [ # # # # ]: 0 : if (*argv[2] && strcmp(argv[2],"<unknown>")) {
879 [ # # ]: 0 : if (parseversion(&b, argv[2], &err) < 0) {
880 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[2]);
881 : 0 : dpkg_error_destroy(&err);
882 : : }
883 : : } else {
884 : 0 : dpkg_version_blank(&b);
885 : : }
886 [ # # ]: 0 : if (!dpkg_version_is_informative(&a)) {
887 [ # # ]: 0 : if (dpkg_version_is_informative(&b))
888 : 0 : return rip->if_none_a;
889 : : else
890 : 0 : return rip->if_none_both;
891 [ # # ]: 0 : } else if (!dpkg_version_is_informative(&b)) {
892 : 0 : return rip->if_none_b;
893 : : }
894 : 0 : rc = dpkg_version_compare(&a, &b);
895 : 0 : debug(dbg_general, "cmpversions a='%s' b='%s' r=%d",
896 : : versiondescribe_c(&a,vdew_always),
897 : : versiondescribe_c(&b,vdew_always),
898 : : rc);
899 [ # # ]: 0 : if (rc > 0)
900 : 0 : return rip->if_greater;
901 [ # # ]: 0 : else if (rc < 0)
902 : 0 : return rip->if_lesser;
903 : : else
904 : 0 : return rip->if_equal;
905 : : }
|