Branch data Line data Source code
1 : : /*
2 : : * dpkg-query - program for query the dpkg database
3 : : * querycmd.c - status enquiry and listing options
4 : : *
5 : : * Copyright © 1995,1996 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2000,2001 Wichert Akkerman <wakkerma@debian.org>
7 : : * Copyright © 2006-2015 Guillem Jover <guillem@debian.org>
8 : : * Copyright © 2011 Linaro Limited
9 : : * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
10 : : *
11 : : * This is free software; you can redistribute it and/or modify
12 : : * it under the terms of the GNU General Public License as published by
13 : : * the Free Software Foundation; either version 2 of the License, or
14 : : * (at your option) any later version.
15 : : *
16 : : * This is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU General Public License for more details.
20 : : *
21 : : * You should have received a copy of the GNU General Public License
22 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
23 : : */
24 : :
25 : : #include <config.h>
26 : : #include <compat.h>
27 : :
28 : : #include <sys/types.h>
29 : : #include <sys/stat.h>
30 : :
31 : : #ifdef HAVE_LOCALE_H
32 : : #include <locale.h>
33 : : #endif
34 : : #include <errno.h>
35 : : #include <limits.h>
36 : : #include <string.h>
37 : : #include <fcntl.h>
38 : : #include <dirent.h>
39 : : #include <fnmatch.h>
40 : : #include <unistd.h>
41 : : #include <stdlib.h>
42 : : #include <stdio.h>
43 : :
44 : : #include <dpkg/i18n.h>
45 : : #include <dpkg/dpkg.h>
46 : : #include <dpkg/dpkg-db.h>
47 : : #include <dpkg/debug.h>
48 : : #include <dpkg/pkg-array.h>
49 : : #include <dpkg/pkg-spec.h>
50 : : #include <dpkg/pkg-format.h>
51 : : #include <dpkg/pkg-show.h>
52 : : #include <dpkg/string.h>
53 : : #include <dpkg/path.h>
54 : : #include <dpkg/file.h>
55 : : #include <dpkg/pager.h>
56 : : #include <dpkg/options.h>
57 : : #include <dpkg/db-ctrl.h>
58 : : #include <dpkg/db-fsys.h>
59 : :
60 : : #include "actions.h"
61 : :
62 : : static const char *opt_showformat = "${binary:Package}\t${Version}\n";
63 : :
64 : : static int opt_loadavail = 0;
65 : :
66 : : static int
67 : 0 : pkg_array_match_patterns(struct pkg_array *array,
68 : : pkg_array_visitor_func *pkg_visitor, void *pkg_data,
69 : : const char *const *argv)
70 : : {
71 : : int argc, i, ip, *found;
72 : 0 : int misses = 0;
73 : : struct pkg_spec *ps;
74 : :
75 [ # # ]: 0 : for (argc = 0; argv[argc]; argc++);
76 : 0 : found = m_calloc(argc, sizeof(int));
77 : :
78 : 0 : ps = m_malloc(sizeof(*ps) * argc);
79 [ # # ]: 0 : for (ip = 0; ip < argc; ip++) {
80 : 0 : pkg_spec_init(&ps[ip], PKG_SPEC_PATTERNS | PKG_SPEC_ARCH_WILDCARD);
81 : 0 : pkg_spec_parse(&ps[ip], argv[ip]);
82 : : }
83 : :
84 [ # # ]: 0 : for (i = 0; i < array->n_pkgs; i++) {
85 : : struct pkginfo *pkg;
86 : 0 : bool pkg_found = false;
87 : :
88 : 0 : pkg = array->pkgs[i];
89 [ # # ]: 0 : for (ip = 0; ip < argc; ip++) {
90 [ # # ]: 0 : if (pkg_spec_match_pkg(&ps[ip], pkg, &pkg->installed)) {
91 : 0 : pkg_found = true;
92 : 0 : found[ip]++;
93 : : }
94 : : }
95 [ # # ]: 0 : if (!pkg_found)
96 : 0 : array->pkgs[i] = NULL;
97 : : }
98 : :
99 : 0 : pkg_array_foreach(array, pkg_visitor, pkg_data);
100 : :
101 [ # # ]: 0 : for (ip = 0; ip < argc; ip++) {
102 [ # # ]: 0 : if (!found[ip]) {
103 : 0 : notice(_("no packages found matching %s"), argv[ip]);
104 : 0 : misses++;
105 : : }
106 : 0 : pkg_spec_destroy(&ps[ip]);
107 : : }
108 : :
109 : 0 : free(ps);
110 : 0 : free(found);
111 : :
112 : 0 : return misses;
113 : : }
114 : :
115 : : struct list_format {
116 : : bool head;
117 : : int nw;
118 : : int vw;
119 : : int aw;
120 : : int dw;
121 : : };
122 : :
123 : : static void
124 : 0 : list_format_init(struct list_format *fmt, struct pkg_array *array)
125 : : {
126 : : int i;
127 : :
128 [ # # ]: 0 : if (fmt->nw != 0)
129 : 0 : return;
130 : :
131 : 0 : fmt->nw = 14;
132 : 0 : fmt->vw = 12;
133 : 0 : fmt->aw = 12;
134 : 0 : fmt->dw = 33;
135 : :
136 [ # # ]: 0 : for (i = 0; i < array->n_pkgs; i++) {
137 : : int plen, vlen, alen, dlen;
138 : :
139 [ # # ]: 0 : if (array->pkgs[i] == NULL)
140 : 0 : continue;
141 : :
142 : 0 : plen = str_width(pkg_name(array->pkgs[i], pnaw_nonambig));
143 : 0 : vlen = str_width(versiondescribe(&array->pkgs[i]->installed.version,
144 : : vdew_nonambig));
145 : 0 : alen = str_width(dpkg_arch_describe(array->pkgs[i]->installed.arch));
146 : 0 : pkg_synopsis(array->pkgs[i], &dlen);
147 : :
148 [ # # ]: 0 : if (plen > fmt->nw)
149 : 0 : fmt->nw = plen;
150 [ # # ]: 0 : if (vlen > fmt->vw)
151 : 0 : fmt->vw = vlen;
152 [ # # ]: 0 : if (alen > fmt->aw)
153 : 0 : fmt->aw = alen;
154 [ # # ]: 0 : if (dlen > fmt->dw)
155 : 0 : fmt->dw = dlen;
156 : : }
157 : : }
158 : :
159 : : static void
160 : 0 : list_format_print(struct list_format *fmt,
161 : : int c_want, int c_status, int c_eflag,
162 : : const char *name, const char *version, const char *arch,
163 : : const char *desc, int desc_len)
164 : : {
165 : : struct str_crop_info ns, vs, as, ds;
166 : :
167 : 0 : str_gen_crop(name, fmt->nw, &ns);
168 : 0 : str_gen_crop(version, fmt->vw, &vs);
169 : 0 : str_gen_crop(arch, fmt->aw, &as);
170 : 0 : str_gen_crop(desc, desc_len, &ds);
171 : :
172 : 0 : printf("%c%c%c %-*.*s %-*.*s %-*.*s %.*s\n", c_want, c_status, c_eflag,
173 : : ns.max_bytes, ns.str_bytes, name,
174 : : vs.max_bytes, vs.str_bytes, version,
175 : : as.max_bytes, as.str_bytes, arch,
176 : : ds.str_bytes, desc);
177 : 0 : }
178 : :
179 : : static void
180 : 0 : list_format_print_header(struct list_format *fmt)
181 : : {
182 : : int l;
183 : :
184 [ # # ]: 0 : if (fmt->head)
185 : 0 : return;
186 : :
187 : : /* TRANSLATORS: This is the header that appears on 'dpkg-query -l'. The
188 : : * string should remain under 80 characters. The uppercase letters in
189 : : * the state values denote the abbreviated letter that will appear on
190 : : * the first three columns, which should ideally match the English one
191 : : * (e.g. Remove → supRimeix), see dpkg-query(1) for further details. The
192 : : * translated message can use additional lines if needed. */
193 : 0 : fputs(_("\
194 : : Desired=Unknown/Install/Remove/Purge/Hold\n\
195 : : | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend\n\
196 : : |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)\n"), stdout);
197 : 0 : list_format_print(fmt, '|', '|', '/', _("Name"), _("Version"),
198 : 0 : _("Architecture"), _("Description"), fmt->dw);
199 : :
200 : : /* Status */
201 : 0 : printf("+++-");
202 : :
203 : : /* Package name. */
204 [ # # ]: 0 : for (l = 0; l < fmt->nw; l++)
205 : 0 : printf("=");
206 : 0 : printf("-");
207 : :
208 : : /* Version. */
209 [ # # ]: 0 : for (l = 0; l < fmt->vw; l++)
210 : 0 : printf("=");
211 : 0 : printf("-");
212 : :
213 : : /* Architecture. */
214 [ # # ]: 0 : for (l = 0; l < fmt->aw; l++)
215 : 0 : printf("=");
216 : 0 : printf("-");
217 : :
218 : : /* Description. */
219 [ # # ]: 0 : for (l = 0; l < fmt->dw; l++)
220 : 0 : printf("=");
221 : 0 : printf("\n");
222 : :
223 : 0 : fmt->head = true;
224 : : }
225 : :
226 : : static void
227 : 0 : pkg_array_list_item(struct pkg_array *array, struct pkginfo *pkg, void *pkg_data)
228 : : {
229 : 0 : struct list_format *fmt = pkg_data;
230 : : int l;
231 : : const char *pdesc;
232 : :
233 : 0 : list_format_init(fmt, array);
234 : 0 : list_format_print_header(fmt);
235 : :
236 : 0 : pdesc = pkg_synopsis(pkg, &l);
237 : 0 : l = min(l, fmt->dw);
238 : :
239 : 0 : list_format_print(fmt,
240 : : pkg_abbrev_want(pkg),
241 : : pkg_abbrev_status(pkg),
242 : : pkg_abbrev_eflag(pkg),
243 : : pkg_name(pkg, pnaw_nonambig),
244 : 0 : versiondescribe(&pkg->installed.version, vdew_nonambig),
245 : : dpkg_arch_describe(pkg->installed.arch),
246 : : pdesc, l);
247 : 0 : }
248 : :
249 : : static int
250 : 0 : listpackages(const char *const *argv)
251 : : {
252 : : struct pkg_array array;
253 : 0 : int misses = 0;
254 : : struct list_format fmt;
255 : : struct pager *pager;
256 : :
257 [ # # ]: 0 : if (!opt_loadavail)
258 : 0 : modstatdb_open(msdbrw_readonly);
259 : : else
260 : 0 : modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
261 : :
262 : 0 : pkg_array_init_from_hash(&array);
263 : 0 : pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
264 : :
265 : 0 : memset(&fmt, 0, sizeof(fmt));
266 : :
267 : 0 : pager = pager_spawn(_("showing package list on pager"));
268 : :
269 [ # # ]: 0 : if (!*argv) {
270 : : int i;
271 : :
272 [ # # ]: 0 : for (i = 0; i < array.n_pkgs; i++) {
273 : : struct pkginfo *pkg;
274 : :
275 : 0 : pkg = array.pkgs[i];
276 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
277 : 0 : array.pkgs[i] = NULL;
278 : : }
279 : :
280 : 0 : pkg_array_foreach(&array, pkg_array_list_item, &fmt);
281 : : } else {
282 : 0 : misses = pkg_array_match_patterns(&array, pkg_array_list_item, &fmt, argv);
283 : : }
284 : :
285 : 0 : m_output(stdout, _("<standard output>"));
286 : 0 : m_output(stderr, _("<standard error>"));
287 : :
288 : 0 : pager_reap(pager);
289 : :
290 : 0 : pkg_array_destroy(&array);
291 : 0 : modstatdb_shutdown();
292 : :
293 : 0 : return !!misses;
294 : : }
295 : :
296 : : static int
297 : 0 : searchoutput(struct fsys_namenode *namenode)
298 : : {
299 : : struct fsys_node_pkgs_iter *iter;
300 : : struct pkginfo *pkg_owner;
301 : : int found;
302 : :
303 [ # # ]: 0 : if (namenode->divert) {
304 : 0 : const char *name_from = namenode->divert->camefrom ?
305 [ # # ]: 0 : namenode->divert->camefrom->name : namenode->name;
306 : 0 : const char *name_to = namenode->divert->useinstead ?
307 [ # # ]: 0 : namenode->divert->useinstead->name : namenode->name;
308 : :
309 [ # # ]: 0 : if (namenode->divert->pkgset) {
310 : 0 : printf(_("diversion by %s from: %s\n"),
311 : 0 : namenode->divert->pkgset->name, name_from);
312 : 0 : printf(_("diversion by %s to: %s\n"),
313 : 0 : namenode->divert->pkgset->name, name_to);
314 : : } else {
315 : 0 : printf(_("local diversion from: %s\n"), name_from);
316 : 0 : printf(_("local diversion to: %s\n"), name_to);
317 : : }
318 : : }
319 : 0 : found= 0;
320 : :
321 : 0 : iter = fsys_node_pkgs_iter_new(namenode);
322 [ # # ]: 0 : while ((pkg_owner = fsys_node_pkgs_iter_next(iter))) {
323 [ # # ]: 0 : if (found)
324 : 0 : fputs(", ", stdout);
325 : 0 : fputs(pkg_name(pkg_owner, pnaw_nonambig), stdout);
326 : 0 : found++;
327 : : }
328 : 0 : fsys_node_pkgs_iter_free(iter);
329 : :
330 [ # # ]: 0 : if (found) printf(": %s\n",namenode->name);
331 : 0 : return found + (namenode->divert ? 1 : 0);
332 : : }
333 : :
334 : : static int
335 : 0 : searchfiles(const char *const *argv)
336 : : {
337 : : const char *thisarg;
338 : 0 : int misses = 0;
339 : 0 : struct varbuf path = VARBUF_INIT;
340 : : static struct varbuf vb;
341 : :
342 [ # # ]: 0 : if (!*argv)
343 : 0 : badusage(_("--search needs at least one file name pattern argument"));
344 : :
345 : 0 : modstatdb_open(msdbrw_readonly);
346 : 0 : ensure_allinstfiles_available_quiet();
347 : 0 : ensure_diversions();
348 : :
349 [ # # ]: 0 : while ((thisarg = *argv++) != NULL) {
350 : : struct fsys_namenode *namenode;
351 : 0 : int found = 0;
352 : :
353 [ # # ]: 0 : if (!strchr("*[?/",*thisarg)) {
354 : 0 : varbuf_reset(&vb);
355 : 0 : varbuf_add_char(&vb, '*');
356 : 0 : varbuf_add_str(&vb, thisarg);
357 : 0 : varbuf_add_char(&vb, '*');
358 : 0 : thisarg= vb.buf;
359 : : }
360 [ # # ]: 0 : if (!strpbrk(thisarg, "*[?\\")) {
361 : : /* Trim trailing ‘/’ and ‘/.’ from the argument if it is not
362 : : * a pattern, just a pathname. */
363 : 0 : varbuf_set_str(&path, thisarg);
364 : 0 : varbuf_trunc(&path, path_trim_slash_slashdot(path.buf));
365 : :
366 : 0 : namenode = fsys_hash_find_node(path.buf, FHFF_NONE);
367 : 0 : found += searchoutput(namenode);
368 : : } else {
369 : : struct fsys_hash_iter *iter;
370 : :
371 : 0 : iter = fsys_hash_iter_new();
372 [ # # ]: 0 : while ((namenode = fsys_hash_iter_next(iter)) != NULL) {
373 [ # # ]: 0 : if (fnmatch(thisarg,namenode->name,0)) continue;
374 : 0 : found+= searchoutput(namenode);
375 : : }
376 : 0 : fsys_hash_iter_free(iter);
377 : : }
378 [ # # ]: 0 : if (!found) {
379 : 0 : notice(_("no path found matching pattern %s"), thisarg);
380 : 0 : misses++;
381 : 0 : m_output(stderr, _("<standard error>"));
382 : : } else {
383 : 0 : m_output(stdout, _("<standard output>"));
384 : : }
385 : : }
386 : 0 : modstatdb_shutdown();
387 : :
388 : 0 : varbuf_destroy(&path);
389 : :
390 : 0 : return !!misses;
391 : : }
392 : :
393 : : static int
394 : 0 : print_status(const char *const *argv)
395 : : {
396 : 0 : int misses = 0;
397 : :
398 : 0 : modstatdb_open(msdbrw_readonly);
399 : :
400 [ # # ]: 0 : if (!*argv) {
401 : 0 : writedb_stanzas(stdout, _("<standard output>"), 0);
402 : : } else {
403 : : const char *thisarg;
404 : :
405 [ # # ]: 0 : while ((thisarg = *argv++) != NULL) {
406 : : struct pkginfo *pkg;
407 : :
408 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, thisarg);
409 : :
410 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED &&
411 [ # # # # ]: 0 : pkg->priority == PKG_PRIO_UNKNOWN &&
412 : 0 : str_is_unset(pkg->section) &&
413 [ # # ]: 0 : !pkg->archives &&
414 [ # # ]: 0 : pkg->want == PKG_WANT_UNKNOWN &&
415 [ # # ]: 0 : !pkg_is_informative(pkg, &pkg->installed)) {
416 : 0 : notice(_("package '%s' is not installed and no information is available"),
417 : : pkg_name(pkg, pnaw_nonambig));
418 : 0 : misses++;
419 : : } else {
420 : 0 : write_stanza(stdout, _("<standard output>"), pkg, &pkg->installed);
421 : : }
422 : :
423 [ # # ]: 0 : if (*argv != NULL)
424 : 0 : putchar('\n');
425 : : }
426 : : }
427 : :
428 : 0 : m_output(stdout, _("<standard output>"));
429 [ # # ]: 0 : if (misses) {
430 : 0 : fputs(_("Use dpkg --info (= dpkg-deb --info) to examine archive files.\n"),
431 : : stderr);
432 : 0 : m_output(stderr, _("<standard error>"));
433 : : }
434 : :
435 : 0 : modstatdb_shutdown();
436 : :
437 : 0 : return !!misses;
438 : : }
439 : :
440 : : static int
441 : 0 : print_avail(const char *const *argv)
442 : : {
443 : 0 : int misses = 0;
444 : :
445 : 0 : modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
446 : :
447 [ # # ]: 0 : if (!*argv) {
448 : 0 : writedb_stanzas(stdout, _("<standard output>"), wdb_dump_available);
449 : : } else {
450 : : const char *thisarg;
451 : :
452 [ # # ]: 0 : while ((thisarg = *argv++) != NULL) {
453 : : struct pkginfo *pkg;
454 : :
455 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, thisarg);
456 : :
457 [ # # ]: 0 : if (!pkg_is_informative(pkg, &pkg->available)) {
458 : 0 : notice(_("package '%s' is not available"),
459 : : pkgbin_name(pkg, &pkg->available, pnaw_nonambig));
460 : 0 : misses++;
461 : : } else {
462 : 0 : write_stanza(stdout, _("<standard output>"), pkg, &pkg->available);
463 : : }
464 : :
465 [ # # ]: 0 : if (*argv != NULL)
466 : 0 : putchar('\n');
467 : : }
468 : : }
469 : :
470 : 0 : m_output(stdout, _("<standard output>"));
471 [ # # ]: 0 : if (misses)
472 : 0 : m_output(stderr, _("<standard error>"));
473 : :
474 : 0 : modstatdb_shutdown();
475 : :
476 : 0 : return !!misses;
477 : : }
478 : :
479 : : static int
480 : 0 : list_files(const char *const *argv)
481 : : {
482 : : const char *thisarg;
483 : : struct fsys_namenode_list *file;
484 : : struct pkginfo *pkg;
485 : : struct fsys_namenode *namenode;
486 : 0 : int misses = 0;
487 : :
488 [ # # ]: 0 : if (!*argv)
489 : 0 : badusage(_("--%s needs at least one package name argument"), cipaction->olong);
490 : :
491 : 0 : modstatdb_open(msdbrw_readonly);
492 : :
493 [ # # ]: 0 : while ((thisarg = *argv++) != NULL) {
494 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, thisarg);
495 : :
496 [ # # ]: 0 : switch (pkg->status) {
497 : 0 : case PKG_STAT_NOTINSTALLED:
498 : 0 : notice(_("package '%s' is not installed"),
499 : : pkg_name(pkg, pnaw_nonambig));
500 : 0 : misses++;
501 : 0 : break;
502 : 0 : default:
503 : 0 : ensure_packagefiles_available(pkg);
504 : 0 : ensure_diversions();
505 : 0 : file = pkg->files;
506 [ # # ]: 0 : if (!file) {
507 : 0 : printf(_("Package '%s' does not contain any files (!)\n"),
508 : : pkg_name(pkg, pnaw_nonambig));
509 : : } else {
510 [ # # ]: 0 : while (file) {
511 : 0 : namenode = file->namenode;
512 : 0 : puts(namenode->name);
513 [ # # # # ]: 0 : if (namenode->divert && !namenode->divert->camefrom) {
514 [ # # ]: 0 : if (!namenode->divert->pkgset)
515 : 0 : printf(_("locally diverted to: %s\n"),
516 : 0 : namenode->divert->useinstead->name);
517 [ # # ]: 0 : else if (pkg->set == namenode->divert->pkgset)
518 : 0 : printf(_("package diverts others to: %s\n"),
519 : 0 : namenode->divert->useinstead->name);
520 : : else
521 : 0 : printf(_("diverted by %s to: %s\n"),
522 : 0 : namenode->divert->pkgset->name,
523 : 0 : namenode->divert->useinstead->name);
524 : : }
525 : 0 : file = file->next;
526 : : }
527 : : }
528 : 0 : break;
529 : : }
530 : :
531 [ # # ]: 0 : if (*argv != NULL)
532 : 0 : putchar('\n');
533 : : }
534 : :
535 : 0 : m_output(stdout, _("<standard output>"));
536 [ # # ]: 0 : if (misses) {
537 : 0 : fputs(_("Use dpkg --contents (= dpkg-deb --contents) to list archive files contents.\n"),
538 : : stderr);
539 : 0 : m_output(stderr, _("<standard error>"));
540 : : }
541 : :
542 : 0 : modstatdb_shutdown();
543 : :
544 : 0 : return !!misses;
545 : : }
546 : :
547 : : static void
548 : 0 : pkg_array_load_db_fsys(struct pkg_array *array, struct pkginfo *pkg, void *pkg_data)
549 : : {
550 : 0 : ensure_packagefiles_available(pkg);
551 : 0 : }
552 : :
553 : : static void
554 : 0 : pkg_array_show_item(struct pkg_array *array, struct pkginfo *pkg, void *pkg_data)
555 : : {
556 : 0 : struct pkg_format_node *fmt = pkg_data;
557 : :
558 : 0 : pkg_format_show(fmt, pkg, &pkg->installed);
559 : 0 : }
560 : :
561 : : static int
562 : 0 : showpackages(const char *const *argv)
563 : : {
564 : : struct dpkg_error err;
565 : : struct pkg_array array;
566 : : struct pkg_format_node *fmt;
567 : : bool fmt_needs_db_fsys;
568 : 0 : int misses = 0;
569 : :
570 : 0 : fmt = pkg_format_parse(opt_showformat, &err);
571 [ # # ]: 0 : if (!fmt) {
572 : 0 : notice(_("error in show format: %s"), err.str);
573 : 0 : dpkg_error_destroy(&err);
574 : 0 : return 2;
575 : : }
576 : :
577 : 0 : fmt_needs_db_fsys = pkg_format_needs_db_fsys(fmt);
578 : :
579 [ # # ]: 0 : if (!opt_loadavail)
580 : 0 : modstatdb_open(msdbrw_readonly);
581 : : else
582 : 0 : modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
583 : :
584 : 0 : pkg_array_init_from_hash(&array);
585 : 0 : pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
586 : :
587 [ # # ]: 0 : if (!*argv) {
588 : : int i;
589 : :
590 [ # # ]: 0 : if (fmt_needs_db_fsys)
591 : 0 : ensure_allinstfiles_available_quiet();
592 [ # # ]: 0 : for (i = 0; i < array.n_pkgs; i++) {
593 : : struct pkginfo *pkg;
594 : :
595 : 0 : pkg = array.pkgs[i];
596 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
597 : 0 : continue;
598 : 0 : pkg_format_show(fmt, pkg, &pkg->installed);
599 : : }
600 : : } else {
601 [ # # ]: 0 : if (fmt_needs_db_fsys)
602 : 0 : pkg_array_foreach(&array, pkg_array_load_db_fsys, NULL);
603 : 0 : misses = pkg_array_match_patterns(&array, pkg_array_show_item, fmt, argv);
604 : : }
605 : :
606 : 0 : m_output(stdout, _("<standard output>"));
607 : 0 : m_output(stderr, _("<standard error>"));
608 : :
609 : 0 : pkg_array_destroy(&array);
610 : 0 : pkg_format_free(fmt);
611 : 0 : modstatdb_shutdown();
612 : :
613 : 0 : return !!misses;
614 : : }
615 : :
616 : : static bool
617 : 0 : pkg_infodb_is_internal(const char *filetype)
618 : : {
619 : : /* Do not expose internal database files. */
620 [ # # ]: 0 : if (strcmp(filetype, LISTFILE) == 0 ||
621 [ # # ]: 0 : strcmp(filetype, CONFFILESFILE) == 0)
622 : 0 : return true;
623 : :
624 [ # # ]: 0 : if (strlen(filetype) > MAXCONTROLFILENAME)
625 : 0 : return true;
626 : :
627 : 0 : return false;
628 : : }
629 : :
630 : : static void
631 : 0 : pkg_infodb_check_filetype(const char *filetype)
632 : : {
633 : : const char *c;
634 : :
635 : : /* Validate control file name for sanity. */
636 [ # # ]: 0 : for (c = "/."; *c; c++)
637 [ # # ]: 0 : if (strchr(filetype, *c))
638 : 0 : badusage(_("control file contains %c"), *c);
639 : 0 : }
640 : :
641 : : static void
642 : 0 : pkg_infodb_print_filename(const char *filename, const char *filetype)
643 : : {
644 [ # # ]: 0 : if (pkg_infodb_is_internal(filetype))
645 : 0 : return;
646 : :
647 : 0 : printf("%s\n", filename);
648 : : }
649 : :
650 : : static void
651 : 0 : pkg_infodb_print_filetype(const char *filename, const char *filetype)
652 : : {
653 [ # # ]: 0 : if (pkg_infodb_is_internal(filetype))
654 : 0 : return;
655 : :
656 : 0 : printf("%s\n", filetype);
657 : : }
658 : :
659 : : static void
660 : 0 : control_path_file(struct pkginfo *pkg, const char *control_file)
661 : : {
662 : : const char *control_pathname;
663 : : struct stat st;
664 : :
665 : 0 : control_pathname = pkg_infodb_get_file(pkg, &pkg->installed, control_file);
666 [ # # ]: 0 : if (stat(control_pathname, &st) < 0)
667 : 0 : return;
668 [ # # ]: 0 : if (!S_ISREG(st.st_mode))
669 : 0 : return;
670 : :
671 : 0 : pkg_infodb_print_filename(control_pathname, control_file);
672 : : }
673 : :
674 : : static int
675 : 0 : control_path(const char *const *argv)
676 : : {
677 : : struct pkginfo *pkg;
678 : : const char *pkgname;
679 : : const char *control_file;
680 : :
681 : 0 : pkgname = *argv++;
682 [ # # ]: 0 : if (!pkgname)
683 : 0 : badusage(_("--%s needs at least one package name argument"),
684 : 0 : cipaction->olong);
685 : :
686 : 0 : control_file = *argv++;
687 [ # # # # ]: 0 : if (control_file && *argv)
688 : 0 : badusage(_("--%s takes at most two arguments"), cipaction->olong);
689 : :
690 [ # # ]: 0 : if (control_file)
691 : 0 : pkg_infodb_check_filetype(control_file);
692 : :
693 : 0 : modstatdb_open(msdbrw_readonly);
694 : :
695 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, pkgname);
696 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
697 : 0 : ohshit(_("package '%s' is not installed"),
698 : : pkg_name(pkg, pnaw_nonambig));
699 : :
700 [ # # ]: 0 : if (control_file)
701 : 0 : control_path_file(pkg, control_file);
702 : : else
703 : 0 : pkg_infodb_foreach(pkg, &pkg->installed, pkg_infodb_print_filename);
704 : :
705 : 0 : modstatdb_shutdown();
706 : :
707 : 0 : return 0;
708 : : }
709 : :
710 : : static int
711 : 0 : control_list(const char *const *argv)
712 : : {
713 : : struct pkginfo *pkg;
714 : : const char *pkgname;
715 : :
716 : 0 : pkgname = *argv++;
717 [ # # # # ]: 0 : if (!pkgname || *argv)
718 : 0 : badusage(_("--%s takes one package name argument"), cipaction->olong);
719 : :
720 : 0 : modstatdb_open(msdbrw_readonly);
721 : :
722 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, pkgname);
723 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
724 : 0 : ohshit(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
725 : :
726 : 0 : pkg_infodb_foreach(pkg, &pkg->installed, pkg_infodb_print_filetype);
727 : :
728 : 0 : modstatdb_shutdown();
729 : :
730 : 0 : return 0;
731 : : }
732 : :
733 : : static int
734 : 0 : control_show(const char *const *argv)
735 : : {
736 : : struct pkginfo *pkg;
737 : : const char *pkgname;
738 : : const char *filename;
739 : : const char *control_file;
740 : :
741 : 0 : pkgname = *argv++;
742 [ # # # # ]: 0 : if (!pkgname || !*argv)
743 : 0 : badusage(_("--%s takes exactly two arguments"),
744 : 0 : cipaction->olong);
745 : :
746 : 0 : control_file = *argv++;
747 [ # # # # ]: 0 : if (!control_file || *argv)
748 : 0 : badusage(_("--%s takes exactly two arguments"), cipaction->olong);
749 : :
750 : 0 : pkg_infodb_check_filetype(control_file);
751 : :
752 : 0 : modstatdb_open(msdbrw_readonly);
753 : :
754 : 0 : pkg = dpkg_options_parse_pkgname(cipaction, pkgname);
755 [ # # ]: 0 : if (pkg->status == PKG_STAT_NOTINSTALLED)
756 : 0 : ohshit(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
757 : :
758 [ # # ]: 0 : if (pkg_infodb_has_file(pkg, &pkg->installed, control_file))
759 : 0 : filename = pkg_infodb_get_file(pkg, &pkg->installed, control_file);
760 : : else
761 : 0 : ohshit(_("control file '%s' does not exist"), control_file);
762 : :
763 : 0 : modstatdb_shutdown();
764 : :
765 : 0 : file_show(filename);
766 : :
767 : 0 : return 0;
768 : : }
769 : :
770 : : static void
771 : 0 : set_no_pager(const struct cmdinfo *ci, const char *value)
772 : : {
773 : 0 : pager_enable(false);
774 : 0 : }
775 : :
776 : : static int
777 : 19 : printversion(const char *const *argv)
778 : : {
779 : 19 : printf(_("Debian %s package management program query tool version %s.\n"),
780 : : DPKGQUERY, PACKAGE_RELEASE);
781 : 19 : printf(_(
782 : : "This is free software; see the GNU General Public License version 2 or\n"
783 : : "later for copying conditions. There is NO warranty.\n"));
784 : :
785 : 19 : m_output(stdout, _("<standard output>"));
786 : :
787 : 19 : return 0;
788 : : }
789 : :
790 : : static int
791 : 0 : usage(const char *const *argv)
792 : : {
793 : 0 : printf(_(
794 : : "Usage: %s [<option>...] <command>\n"
795 : : "\n"), DPKGQUERY);
796 : :
797 : 0 : printf(_(
798 : : "Commands:\n"
799 : : " -s, --status [<package>...] Display package status details.\n"
800 : : " -p, --print-avail [<package>...] Display available version details.\n"
801 : : " -L, --listfiles <package>... List files 'owned' by package(s).\n"
802 : : " -l, --list [<pattern>...] List packages concisely.\n"
803 : : " -W, --show [<pattern>...] Show information on package(s).\n"
804 : : " -S, --search <pattern>... Find package(s) owning file(s).\n"
805 : : " --control-list <package> Print the package control file list.\n"
806 : : " --control-show <package> <file>\n"
807 : : " Show the package control file.\n"
808 : : " -c, --control-path <package> [<file>]\n"
809 : : " Print path for package control file.\n"
810 : : "\n"));
811 : :
812 : 0 : printf(_(
813 : : " -?, --help Show this help message.\n"
814 : : " --version Show the version.\n"
815 : : "\n"));
816 : :
817 : 0 : printf(_(
818 : : "Options:\n"
819 : : " --admindir=<directory> Use <directory> instead of %s.\n"
820 : : " --root=<directory> Use <directory> instead of %s.\n"
821 : : " --load-avail Use available file on --show and --list.\n"
822 : : " --no-pager Disables the use of any pager.\n"
823 : : " -f|--showformat=<format> Use alternative format for --show.\n"
824 : : "\n"), ADMINDIR, "/");
825 : :
826 : 0 : printf(_(
827 : : "Format syntax:\n"
828 : : " A format is a string that will be output for each package. The format\n"
829 : : " can include the standard escape sequences \\n (newline), \\r (carriage\n"
830 : : " return) or \\\\ (plain backslash). Package information can be included\n"
831 : : " by inserting variable references to package fields using the ${var[;width]}\n"
832 : : " syntax. Fields will be right-aligned unless the width is negative in which\n"
833 : : " case left alignment will be used.\n"));
834 : :
835 : 0 : m_output(stdout, _("<standard output>"));
836 : :
837 : 0 : return 0;
838 : : }
839 : :
840 : : static const char printforhelp[] = N_(
841 : : "Use --help for help about querying packages.");
842 : :
843 : : /* This table has both the action entries in it and the normal options.
844 : : * The action entries are made with the ACTION macro, as they all
845 : : * have a very similar structure. */
846 : : static const struct cmdinfo cmdinfos[]= {
847 : : ACTION( "listfiles", 'L', act_listfiles, list_files ),
848 : : ACTION( "status", 's', act_status, print_status ),
849 : : ACTION( "print-avail", 'p', act_printavail, print_avail ),
850 : : ACTION( "list", 'l', act_listpackages, listpackages ),
851 : : ACTION( "search", 'S', act_searchfiles, searchfiles ),
852 : : ACTION( "show", 'W', act_listpackages, showpackages ),
853 : : ACTION( "control-path", 'c', act_controlpath, control_path ),
854 : : ACTION( "control-list", 0, act_controllist, control_list ),
855 : : ACTION( "control-show", 0, act_controlshow, control_show ),
856 : : ACTION( "help", '?', act_help, usage ),
857 : : ACTION( "version", 0, act_version, printversion ),
858 : :
859 : : { "admindir", 0, 1, NULL, NULL, set_admindir, 0 },
860 : : { "root", 0, 1, NULL, NULL, set_root, 0 },
861 : : { "load-avail", 0, 0, &opt_loadavail, NULL, NULL, 1 },
862 : : { "showformat", 'f', 1, NULL, &opt_showformat, NULL },
863 : : { "no-pager", 0, 0, NULL, NULL, set_no_pager },
864 : : { NULL, 0, 0, NULL, NULL, NULL }
865 : : };
866 : :
867 : 19 : int main(int argc, const char *const *argv) {
868 : : int ret;
869 : :
870 : 19 : dpkg_set_report_piped_mode(_IOFBF);
871 : 19 : dpkg_locales_init(PACKAGE);
872 : 19 : dpkg_program_init("dpkg-query");
873 : 19 : dpkg_options_parse(&argv, cmdinfos, printforhelp);
874 : :
875 : 19 : debug(dbg_general, "root=%s admindir=%s", dpkg_fsys_get_dir(), dpkg_db_get_dir());
876 : :
877 [ - + ]: 19 : if (!cipaction) badusage(_("need an action option"));
878 : :
879 : 19 : ret = cipaction->action(argv);
880 : :
881 : 19 : dpkg_program_done();
882 : 19 : dpkg_locales_done();
883 : :
884 : 19 : return ret;
885 : : }
|