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 : varbuf_end_str(&vb);
569 : 0 : notice(_("cannot see how to satisfy pre-dependency:\n %s"), vb.buf);
570 : 0 : ohshit(_("cannot satisfy pre-dependencies for %.250s (wanted due to %.250s)"),
571 : 0 : pkgbin_name(dep->up, &dep->up->available, pnaw_nonambig),
572 : : pkgbin_name(startpkg, &startpkg->available, pnaw_nonambig));
573 : : }
574 : 0 : pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
575 [ # # ]: 0 : for (dep= pkg->available.depends; dep; dep= dep->next) {
576 [ # # ]: 0 : if (dep->type != dep_predepends) continue;
577 [ # # ]: 0 : if (depisok(dep, &vb, NULL, NULL, true))
578 : 0 : continue;
579 : : /* This will leave dep non-NULL, and so exit the loop. */
580 : 0 : break;
581 : : }
582 [ # # ]: 0 : } while (dep);
583 : :
584 : : /* OK, we've found it - pkg has no unsatisfied pre-dependencies! */
585 : 0 : writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
586 : :
587 : 0 : m_output(stdout, _("<standard output>"));
588 : :
589 : 0 : return 0;
590 : : }
591 : :
592 : : int
593 : 0 : printarch(const char *const *argv)
594 : : {
595 [ # # ]: 0 : if (*argv)
596 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
597 : :
598 : 0 : printf("%s\n", dpkg_arch_get(DPKG_ARCH_NATIVE)->name);
599 : :
600 : 0 : m_output(stdout, _("<standard output>"));
601 : :
602 : 0 : return 0;
603 : : }
604 : :
605 : : int
606 : 0 : print_foreign_arches(const char *const *argv)
607 : : {
608 : : struct dpkg_arch *arch;
609 : :
610 [ # # ]: 0 : if (*argv)
611 : 0 : badusage(_("--%s takes no arguments"), cipaction->olong);
612 : :
613 : 0 : dpkg_arch_load_list();
614 : :
615 [ # # ]: 0 : for (arch = dpkg_arch_get_list(); arch; arch = arch->next) {
616 [ # # ]: 0 : if (arch->type != DPKG_ARCH_FOREIGN)
617 : 0 : continue;
618 : :
619 : 0 : printf("%s\n", arch->name);
620 : : }
621 : :
622 : 0 : m_output(stdout, _("<standard output>"));
623 : :
624 : 0 : return 0;
625 : : }
626 : :
627 : : int
628 : 0 : validate_pkgname(const char *const *argv)
629 : : {
630 : : const char *emsg;
631 : :
632 [ # # # # ]: 0 : if (!argv[0] || argv[1])
633 : 0 : badusage(_("--%s takes one <pkgname> argument"), cipaction->olong);
634 : :
635 : 0 : emsg = pkg_name_is_illegal(argv[0]);
636 [ # # ]: 0 : if (emsg)
637 : 0 : ohshit(_("package name '%s' is invalid: %s"), argv[0], emsg);
638 : :
639 : 0 : return 0;
640 : : }
641 : :
642 : : int
643 : 0 : validate_trigname(const char *const *argv)
644 : : {
645 : : const char *emsg;
646 : :
647 [ # # # # ]: 0 : if (!argv[0] || argv[1])
648 : 0 : badusage(_("--%s takes one <trigname> argument"), cipaction->olong);
649 : :
650 : 0 : emsg = trig_name_is_illegal(argv[0]);
651 [ # # ]: 0 : if (emsg)
652 : 0 : ohshit(_("trigger name '%s' is invalid: %s"), argv[0], emsg);
653 : :
654 : 0 : return 0;
655 : : }
656 : :
657 : : int
658 : 0 : validate_archname(const char *const *argv)
659 : : {
660 : : const char *emsg;
661 : :
662 [ # # # # ]: 0 : if (!argv[0] || argv[1])
663 : 0 : badusage(_("--%s takes one <archname> argument"), cipaction->olong);
664 : :
665 : 0 : emsg = dpkg_arch_name_is_illegal(argv[0]);
666 [ # # ]: 0 : if (emsg)
667 : 0 : ohshit(_("architecture name '%s' is invalid: %s"), argv[0], emsg);
668 : :
669 : 0 : return 0;
670 : : }
671 : :
672 : : int
673 : 0 : validate_version(const char *const *argv)
674 : : {
675 : : struct dpkg_version version;
676 : : struct dpkg_error err;
677 : :
678 [ # # # # ]: 0 : if (!argv[0] || argv[1])
679 : 0 : badusage(_("--%s takes one <version> argument"), cipaction->olong);
680 : :
681 [ # # ]: 0 : if (parseversion(&version, argv[0], &err) < 0) {
682 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[0]);
683 : 0 : dpkg_error_destroy(&err);
684 : :
685 : 0 : return 1;
686 : : }
687 : :
688 : 0 : return 0;
689 : : }
690 : :
691 : : int
692 : 0 : cmpversions(const char *const *argv)
693 : : {
694 : : struct relationinfo {
695 : : const char *op;
696 : : /* These values are exit status codes. */
697 : : int if_lesser, if_equal, if_greater;
698 : : int if_none_a, if_none_both, if_none_b;
699 : : bool obsolete;
700 : : };
701 : :
702 : : static const struct relationinfo relationinfos[]= {
703 : : {
704 : : .op = "le",
705 : : .if_lesser = EXIT_SUCCESS,
706 : : .if_equal = EXIT_SUCCESS,
707 : : .if_greater = EXIT_FAILURE,
708 : : .if_none_a = EXIT_SUCCESS,
709 : : .if_none_both = EXIT_SUCCESS,
710 : : .if_none_b = EXIT_FAILURE,
711 : : }, {
712 : : .op = "lt",
713 : : .if_lesser = EXIT_SUCCESS,
714 : : .if_equal = EXIT_FAILURE,
715 : : .if_greater = EXIT_FAILURE,
716 : : .if_none_a = EXIT_SUCCESS,
717 : : .if_none_both = EXIT_FAILURE,
718 : : .if_none_b = EXIT_FAILURE,
719 : : }, {
720 : : .op = "eq",
721 : : .if_lesser = EXIT_FAILURE,
722 : : .if_equal = EXIT_SUCCESS,
723 : : .if_greater = EXIT_FAILURE,
724 : : .if_none_a = EXIT_FAILURE,
725 : : .if_none_both = EXIT_SUCCESS,
726 : : .if_none_b = EXIT_FAILURE,
727 : : }, {
728 : : .op = "ne",
729 : : .if_lesser = EXIT_SUCCESS,
730 : : .if_equal = EXIT_FAILURE,
731 : : .if_greater = EXIT_SUCCESS,
732 : : .if_none_a = EXIT_SUCCESS,
733 : : .if_none_both = EXIT_FAILURE,
734 : : .if_none_b = EXIT_SUCCESS,
735 : : }, {
736 : : .op = "ge",
737 : : .if_lesser = EXIT_FAILURE,
738 : : .if_equal = EXIT_SUCCESS,
739 : : .if_greater = EXIT_SUCCESS,
740 : : .if_none_a = EXIT_FAILURE,
741 : : .if_none_both = EXIT_SUCCESS,
742 : : .if_none_b = EXIT_SUCCESS,
743 : : }, {
744 : : .op = "gt",
745 : : .if_lesser = EXIT_FAILURE,
746 : : .if_equal = EXIT_FAILURE,
747 : : .if_greater = EXIT_SUCCESS,
748 : : .if_none_a = EXIT_FAILURE,
749 : : .if_none_both = EXIT_FAILURE,
750 : : .if_none_b = EXIT_SUCCESS,
751 : : },
752 : :
753 : : /* These treat an empty version as later than any version. */
754 : : {
755 : : .op = "le-nl",
756 : : .if_lesser = EXIT_SUCCESS,
757 : : .if_equal = EXIT_SUCCESS,
758 : : .if_greater = EXIT_FAILURE,
759 : : .if_none_a = EXIT_FAILURE,
760 : : .if_none_both = EXIT_SUCCESS,
761 : : .if_none_b = EXIT_SUCCESS,
762 : : }, {
763 : : .op = "lt-nl",
764 : : .if_lesser = EXIT_SUCCESS,
765 : : .if_equal = EXIT_FAILURE,
766 : : .if_greater = EXIT_FAILURE,
767 : : .if_none_a = EXIT_FAILURE,
768 : : .if_none_both = EXIT_FAILURE,
769 : : .if_none_b = EXIT_SUCCESS,
770 : : }, {
771 : : .op = "ge-nl",
772 : : .if_lesser = EXIT_FAILURE,
773 : : .if_equal = EXIT_SUCCESS,
774 : : .if_greater = EXIT_SUCCESS,
775 : : .if_none_a = EXIT_SUCCESS,
776 : : .if_none_both = EXIT_SUCCESS,
777 : : .if_none_b = EXIT_FAILURE,
778 : : }, {
779 : : .op = "gt-nl",
780 : : .if_lesser = EXIT_FAILURE,
781 : : .if_equal = EXIT_FAILURE,
782 : : .if_greater = EXIT_SUCCESS,
783 : : .if_none_a = EXIT_SUCCESS,
784 : : .if_none_both = EXIT_FAILURE,
785 : : .if_none_b = EXIT_FAILURE,
786 : : },
787 : :
788 : : /* For compatibility with dpkg control file syntax. */
789 : : {
790 : : .op = "<",
791 : : .if_lesser = EXIT_SUCCESS,
792 : : .if_equal = EXIT_SUCCESS,
793 : : .if_greater = EXIT_FAILURE,
794 : : .if_none_a = EXIT_SUCCESS,
795 : : .if_none_both = EXIT_SUCCESS,
796 : : .if_none_b = EXIT_FAILURE,
797 : : .obsolete = true,
798 : : }, {
799 : : .op = "<=",
800 : : .if_lesser = EXIT_SUCCESS,
801 : : .if_equal = EXIT_SUCCESS,
802 : : .if_greater = EXIT_FAILURE,
803 : : .if_none_a = EXIT_SUCCESS,
804 : : .if_none_both = EXIT_SUCCESS,
805 : : .if_none_b = EXIT_FAILURE,
806 : : }, {
807 : : .op = "<<",
808 : : .if_lesser = EXIT_SUCCESS,
809 : : .if_equal = EXIT_FAILURE,
810 : : .if_greater = EXIT_FAILURE,
811 : : .if_none_a = EXIT_SUCCESS,
812 : : .if_none_both = EXIT_FAILURE,
813 : : .if_none_b = EXIT_FAILURE,
814 : : }, {
815 : : .op = "=",
816 : : .if_lesser = EXIT_FAILURE,
817 : : .if_equal = EXIT_SUCCESS,
818 : : .if_greater = EXIT_FAILURE,
819 : : .if_none_a = EXIT_FAILURE,
820 : : .if_none_both = EXIT_SUCCESS,
821 : : .if_none_b = EXIT_FAILURE,
822 : : }, {
823 : : .op = ">",
824 : : .if_lesser = EXIT_FAILURE,
825 : : .if_equal = EXIT_SUCCESS,
826 : : .if_greater = EXIT_SUCCESS,
827 : : .if_none_a = EXIT_FAILURE,
828 : : .if_none_both = EXIT_SUCCESS,
829 : : .if_none_b = EXIT_SUCCESS,
830 : : .obsolete = true,
831 : : }, {
832 : : .op = ">=",
833 : : .if_lesser = EXIT_FAILURE,
834 : : .if_equal = EXIT_SUCCESS,
835 : : .if_greater = EXIT_SUCCESS,
836 : : .if_none_a = EXIT_FAILURE,
837 : : .if_none_both = EXIT_SUCCESS,
838 : : .if_none_b = EXIT_SUCCESS,
839 : : }, {
840 : : .op = ">>",
841 : : .if_lesser = EXIT_FAILURE,
842 : : .if_equal = EXIT_FAILURE,
843 : : .if_greater = EXIT_SUCCESS,
844 : : .if_none_a = EXIT_FAILURE,
845 : : .if_none_both = EXIT_FAILURE,
846 : : .if_none_b = EXIT_SUCCESS,
847 : : }, {
848 : : .op = NULL,
849 : : }
850 : : };
851 : :
852 : : const struct relationinfo *rip;
853 : : struct dpkg_version a, b;
854 : : struct dpkg_error err;
855 : : int rc;
856 : :
857 [ # # # # : 0 : if (!argv[0] || !argv[1] || !argv[2] || argv[3])
# # # # ]
858 : 0 : badusage(_("--compare-versions takes three arguments:"
859 : : " <version> <relation> <version>"));
860 : :
861 [ # # # # ]: 0 : for (rip = relationinfos; rip->op && strcmp(rip->op, argv[1]); rip++)
862 : : ;
863 : :
864 [ # # ]: 0 : if (!rip->op)
865 : 0 : badusage(_("--compare-versions bad relation"));
866 : :
867 [ # # ]: 0 : if (rip->obsolete)
868 : 0 : warning(_("--%s used with obsolete relation operator '%s'"),
869 : 0 : cipaction->olong, rip->op);
870 : :
871 [ # # # # ]: 0 : if (*argv[0] && strcmp(argv[0],"<unknown>")) {
872 [ # # ]: 0 : if (parseversion(&a, argv[0], &err) < 0) {
873 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[0]);
874 : 0 : dpkg_error_destroy(&err);
875 : : }
876 : : } else {
877 : 0 : dpkg_version_blank(&a);
878 : : }
879 [ # # # # ]: 0 : if (*argv[2] && strcmp(argv[2],"<unknown>")) {
880 [ # # ]: 0 : if (parseversion(&b, argv[2], &err) < 0) {
881 : 0 : dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[2]);
882 : 0 : dpkg_error_destroy(&err);
883 : : }
884 : : } else {
885 : 0 : dpkg_version_blank(&b);
886 : : }
887 [ # # ]: 0 : if (!dpkg_version_is_informative(&a)) {
888 [ # # ]: 0 : if (dpkg_version_is_informative(&b))
889 : 0 : return rip->if_none_a;
890 : : else
891 : 0 : return rip->if_none_both;
892 [ # # ]: 0 : } else if (!dpkg_version_is_informative(&b)) {
893 : 0 : return rip->if_none_b;
894 : : }
895 : 0 : rc = dpkg_version_compare(&a, &b);
896 : 0 : debug(dbg_general, "cmpversions a='%s' b='%s' r=%d",
897 : : versiondescribe_c(&a,vdew_always),
898 : : versiondescribe_c(&b,vdew_always),
899 : : rc);
900 [ # # ]: 0 : if (rc > 0)
901 : 0 : return rip->if_greater;
902 [ # # ]: 0 : else if (rc < 0)
903 : 0 : return rip->if_lesser;
904 : : else
905 : 0 : return rip->if_equal;
906 : : }
|