querycmd.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  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 <ian@chiark.greenend.org.uk>
  6. * Copyright © 2000,2001 Wichert Akkerman <wakkerma@debian.org>
  7. * Copyright © 2006-2012 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 <http://www.gnu.org/licenses/>.
  23. */
  24. #include <config.h>
  25. #include <compat.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/termios.h>
  30. #if HAVE_LOCALE_H
  31. #include <locale.h>
  32. #endif
  33. #include <string.h>
  34. #include <fcntl.h>
  35. #include <dirent.h>
  36. #include <fnmatch.h>
  37. #include <unistd.h>
  38. #include <stdlib.h>
  39. #include <stdio.h>
  40. #include <dpkg/i18n.h>
  41. #include <dpkg/dpkg.h>
  42. #include <dpkg/dpkg-db.h>
  43. #include <dpkg/pkg-array.h>
  44. #include <dpkg/pkg-spec.h>
  45. #include <dpkg/pkg-format.h>
  46. #include <dpkg/pkg-show.h>
  47. #include <dpkg/string.h>
  48. #include <dpkg/path.h>
  49. #include <dpkg/file.h>
  50. #include <dpkg/options.h>
  51. #include "filesdb.h"
  52. #include "infodb.h"
  53. #include "main.h"
  54. static const char *showformat = "${binary:Package}\t${Version}\n";
  55. static int opt_loadavail = 0;
  56. static int getwidth(void) {
  57. int fd;
  58. int res;
  59. struct winsize ws;
  60. const char *columns;
  61. columns = getenv("COLUMNS");
  62. if (columns) {
  63. res = atoi(columns);
  64. if (res > 0)
  65. return res;
  66. }
  67. if (!isatty(1))
  68. return -1;
  69. else {
  70. res = 80;
  71. fd = open("/dev/tty", O_RDONLY);
  72. if (fd != -1) {
  73. if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
  74. res = ws.ws_col;
  75. close(fd);
  76. }
  77. return res;
  78. }
  79. }
  80. struct list_format {
  81. bool head;
  82. int nw;
  83. int vw;
  84. int aw;
  85. int dw;
  86. };
  87. static void
  88. list_format_init(struct list_format *fmt, struct pkg_array *array)
  89. {
  90. int w;
  91. if (fmt->nw != 0)
  92. return;
  93. w = getwidth();
  94. if (w == -1) {
  95. int i;
  96. fmt->nw = 14;
  97. fmt->vw = 12;
  98. fmt->aw = 12;
  99. fmt->dw = 33;
  100. for (i = 0; i < array->n_pkgs; i++) {
  101. int plen, vlen, alen, dlen;
  102. plen = str_width(pkg_name(array->pkgs[i], pnaw_nonambig));
  103. vlen = str_width(versiondescribe(&array->pkgs[i]->installed.version,
  104. vdew_nonambig));
  105. alen = str_width(dpkg_arch_describe(array->pkgs[i]->installed.arch));
  106. pkg_summary(array->pkgs[i], &array->pkgs[i]->installed, &dlen);
  107. if (plen > fmt->nw)
  108. fmt->nw = plen;
  109. if (vlen > fmt->vw)
  110. fmt->vw = vlen;
  111. if (alen > fmt->aw)
  112. fmt->aw = alen;
  113. if (dlen > fmt->dw)
  114. fmt->dw = dlen;
  115. }
  116. } else {
  117. w -= 80;
  118. /* Let's not try to deal with terminals that are too small. */
  119. if (w < 0)
  120. w = 0;
  121. /* Halve that so we can add it to both the name and description. */
  122. w >>= 1;
  123. /* Name width. */
  124. fmt->nw = (14 + (w / 2));
  125. /* Version width. */
  126. fmt->vw = (12 + (w / 4));
  127. /* Architecture width. */
  128. fmt->aw = (12 + (w / 4));
  129. /* Description width. */
  130. fmt->dw = (33 + w);
  131. }
  132. }
  133. static void
  134. list_format_print(struct list_format *fmt,
  135. int c_want, int c_status, int c_eflag,
  136. const char *name, const char *version, const char *arch,
  137. const char *desc, int desc_len)
  138. {
  139. struct str_crop_info ns, vs, as, ds;
  140. str_gen_crop(name, fmt->nw, &ns);
  141. str_gen_crop(version, fmt->vw, &vs);
  142. str_gen_crop(arch, fmt->aw, &as);
  143. str_gen_crop(desc, desc_len, &ds);
  144. printf("%c%c%c %-*.*s %-*.*s %-*.*s %.*s\n", c_want, c_status, c_eflag,
  145. ns.max_bytes, ns.str_bytes, name,
  146. vs.max_bytes, vs.str_bytes, version,
  147. as.max_bytes, as.str_bytes, arch,
  148. ds.str_bytes, desc);
  149. }
  150. static void
  151. list_format_print_header(struct list_format *fmt)
  152. {
  153. int l;
  154. if (fmt->head)
  155. return;
  156. /* TRANSLATORS: This is the header that appears on 'dpkg-query -l'. The
  157. * string should remain under 80 characters. The uppercase letters in
  158. * the state values denote the abbreviated letter that will appear on
  159. * the first three columns, which should ideally match the English one
  160. * (e.g. Remove → supRimeix), see dpkg-query(1) for further details. The
  161. * translated message can use additional lines if needed. */
  162. fputs(_("\
  163. Desired=Unknown/Install/Remove/Purge/Hold\n\
  164. | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend\n\
  165. |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)\n"), stdout);
  166. list_format_print(fmt, '|', '|', '/', _("Name"), _("Version"),
  167. _("Architecture"), _("Description"), fmt->dw);
  168. /* Status */
  169. printf("+++-");
  170. /* Package name. */
  171. for (l = 0; l < fmt->nw; l++)
  172. printf("=");
  173. printf("-");
  174. /* Version. */
  175. for (l = 0; l < fmt->vw; l++)
  176. printf("=");
  177. printf("-");
  178. /* Architecture. */
  179. for (l = 0; l < fmt->aw; l++)
  180. printf("=");
  181. printf("-");
  182. /* Description. */
  183. for (l = 0; l < fmt->dw; l++)
  184. printf("=");
  185. printf("\n");
  186. fmt->head = true;
  187. }
  188. static void
  189. list1package(struct pkginfo *pkg, struct list_format *fmt, struct pkg_array *array)
  190. {
  191. int l;
  192. const char *pdesc;
  193. list_format_init(fmt, array);
  194. list_format_print_header(fmt);
  195. pdesc = pkg_summary(pkg, &pkg->installed, &l);
  196. l = min(l, fmt->dw);
  197. list_format_print(fmt,
  198. pkg_abbrev_want(pkg),
  199. pkg_abbrev_status(pkg),
  200. pkg_abbrev_eflag(pkg),
  201. pkg_name(pkg, pnaw_nonambig),
  202. versiondescribe(&pkg->installed.version, vdew_nonambig),
  203. dpkg_arch_describe(pkg->installed.arch),
  204. pdesc, l);
  205. }
  206. static int
  207. listpackages(const char *const *argv)
  208. {
  209. struct pkg_array array;
  210. struct pkginfo *pkg;
  211. int i;
  212. int failures = 0;
  213. struct list_format fmt;
  214. if (!opt_loadavail)
  215. modstatdb_open(msdbrw_readonly);
  216. else
  217. modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
  218. pkg_array_init_from_db(&array);
  219. pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
  220. memset(&fmt, 0, sizeof(fmt));
  221. if (!*argv) {
  222. for (i = 0; i < array.n_pkgs; i++) {
  223. pkg = array.pkgs[i];
  224. if (pkg->status == stat_notinstalled) continue;
  225. list1package(pkg, &fmt, &array);
  226. }
  227. } else {
  228. int argc, ip, *found;
  229. struct pkg_spec *ps;
  230. for (argc = 0; argv[argc]; argc++);
  231. found = m_calloc(sizeof(int) * argc);
  232. ps = m_malloc(sizeof(*ps) * argc);
  233. for (ip = 0; ip < argc; ip++) {
  234. pkg_spec_init(&ps[ip], psf_patterns | psf_arch_def_wildcard);
  235. pkg_spec_parse(&ps[ip], argv[ip]);
  236. }
  237. for (i = 0; i < array.n_pkgs; i++) {
  238. pkg = array.pkgs[i];
  239. for (ip = 0; ip < argc; ip++) {
  240. if (pkg_spec_match_pkg(&ps[ip], pkg, &pkg->installed)) {
  241. list1package(pkg, &fmt, &array);
  242. found[ip]++;
  243. break;
  244. }
  245. }
  246. }
  247. /* FIXME: we might get non-matching messages for sub-patterns specified
  248. * after their super-patterns, due to us skipping on first match. */
  249. for (ip = 0; ip < argc; ip++) {
  250. if (!found[ip]) {
  251. notice(_("no packages found matching %s"), argv[ip]);
  252. failures++;
  253. }
  254. pkg_spec_destroy(&ps[ip]);
  255. }
  256. free(ps);
  257. free(found);
  258. }
  259. m_output(stdout, _("<standard output>"));
  260. m_output(stderr, _("<standard error>"));
  261. pkg_array_destroy(&array);
  262. modstatdb_shutdown();
  263. return failures;
  264. }
  265. static int searchoutput(struct filenamenode *namenode) {
  266. struct filepackages_iterator *iter;
  267. struct pkginfo *pkg_owner;
  268. int found;
  269. if (namenode->divert) {
  270. const char *name_from = namenode->divert->camefrom ?
  271. namenode->divert->camefrom->name : namenode->name;
  272. const char *name_to = namenode->divert->useinstead ?
  273. namenode->divert->useinstead->name : namenode->name;
  274. if (namenode->divert->pkgset) {
  275. printf(_("diversion by %s from: %s\n"),
  276. namenode->divert->pkgset->name, name_from);
  277. printf(_("diversion by %s to: %s\n"),
  278. namenode->divert->pkgset->name, name_to);
  279. } else {
  280. printf(_("local diversion from: %s\n"), name_from);
  281. printf(_("local diversion to: %s\n"), name_to);
  282. }
  283. }
  284. found= 0;
  285. iter = filepackages_iter_new(namenode);
  286. while ((pkg_owner = filepackages_iter_next(iter))) {
  287. if (found)
  288. fputs(", ", stdout);
  289. fputs(pkg_name(pkg_owner, pnaw_nonambig), stdout);
  290. found++;
  291. }
  292. filepackages_iter_free(iter);
  293. if (found) printf(": %s\n",namenode->name);
  294. return found + (namenode->divert ? 1 : 0);
  295. }
  296. static int
  297. searchfiles(const char *const *argv)
  298. {
  299. struct filenamenode *namenode;
  300. struct fileiterator *iter;
  301. const char *thisarg;
  302. int found;
  303. int failures = 0;
  304. struct varbuf path = VARBUF_INIT;
  305. static struct varbuf vb;
  306. if (!*argv)
  307. badusage(_("--search needs at least one file name pattern argument"));
  308. modstatdb_open(msdbrw_readonly);
  309. ensure_allinstfiles_available_quiet();
  310. ensure_diversions();
  311. while ((thisarg = *argv++) != NULL) {
  312. found= 0;
  313. /* Trim trailing ‘/’ and ‘/.’ from the argument if it's
  314. * not a pattern, just a path. */
  315. if (!strpbrk(thisarg, "*[?\\")) {
  316. varbuf_reset(&path);
  317. varbuf_add_str(&path, thisarg);
  318. varbuf_end_str(&path);
  319. varbuf_trunc(&path, path_trim_slash_slashdot(path.buf));
  320. thisarg = path.buf;
  321. }
  322. if (!strchr("*[?/",*thisarg)) {
  323. varbuf_reset(&vb);
  324. varbuf_add_char(&vb, '*');
  325. varbuf_add_str(&vb, thisarg);
  326. varbuf_add_char(&vb, '*');
  327. varbuf_end_str(&vb);
  328. thisarg= vb.buf;
  329. }
  330. if (!strpbrk(thisarg, "*[?\\")) {
  331. namenode= findnamenode(thisarg, 0);
  332. found += searchoutput(namenode);
  333. } else {
  334. iter = files_db_iter_new();
  335. while ((namenode = files_db_iter_next(iter)) != NULL) {
  336. if (fnmatch(thisarg,namenode->name,0)) continue;
  337. found+= searchoutput(namenode);
  338. }
  339. files_db_iter_free(iter);
  340. }
  341. if (!found) {
  342. notice(_("no path found matching pattern %s"), thisarg);
  343. failures++;
  344. m_output(stderr, _("<standard error>"));
  345. } else {
  346. m_output(stdout, _("<standard output>"));
  347. }
  348. }
  349. modstatdb_shutdown();
  350. varbuf_destroy(&path);
  351. return failures;
  352. }
  353. static int
  354. enqperpackage(const char *const *argv)
  355. {
  356. const char *thisarg;
  357. struct fileinlist *file;
  358. struct pkginfo *pkg;
  359. struct filenamenode *namenode;
  360. int failures = 0;
  361. if (!*argv)
  362. badusage(_("--%s needs at least one package name argument"), cipaction->olong);
  363. if (cipaction->arg_int == act_printavail)
  364. modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
  365. else
  366. modstatdb_open(msdbrw_readonly);
  367. while ((thisarg = *argv++) != NULL) {
  368. struct dpkg_error err;
  369. pkg = pkg_spec_parse_pkg(thisarg, &err);
  370. if (pkg == NULL)
  371. badusage(_("--%s needs a valid package name but '%.250s' is not: %s"),
  372. cipaction->olong, thisarg, err.str);
  373. switch (cipaction->arg_int) {
  374. case act_status:
  375. if (pkg->status == stat_notinstalled &&
  376. pkg->priority == pri_unknown &&
  377. str_is_unset(pkg->section) &&
  378. !pkg->files &&
  379. pkg->want == want_unknown &&
  380. !pkg_is_informative(pkg, &pkg->installed)) {
  381. notice(_("package '%s' is not installed and no information is available"),
  382. pkg_name(pkg, pnaw_nonambig));
  383. failures++;
  384. } else {
  385. writerecord(stdout, _("<standard output>"), pkg, &pkg->installed);
  386. }
  387. break;
  388. case act_printavail:
  389. if (!pkg_is_informative(pkg, &pkg->available)) {
  390. notice(_("package '%s' is not available"),
  391. pkgbin_name(pkg, &pkg->available, pnaw_nonambig));
  392. failures++;
  393. } else {
  394. writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
  395. }
  396. break;
  397. case act_listfiles:
  398. switch (pkg->status) {
  399. case stat_notinstalled:
  400. notice(_("package '%s' is not installed"),
  401. pkg_name(pkg, pnaw_nonambig));
  402. failures++;
  403. break;
  404. default:
  405. ensure_packagefiles_available(pkg);
  406. ensure_diversions();
  407. file= pkg->clientdata->files;
  408. if (!file) {
  409. printf(_("Package `%s' does not contain any files (!)\n"),
  410. pkg_name(pkg, pnaw_nonambig));
  411. } else {
  412. while (file) {
  413. namenode= file->namenode;
  414. puts(namenode->name);
  415. if (namenode->divert && !namenode->divert->camefrom) {
  416. if (!namenode->divert->pkgset)
  417. printf(_("locally diverted to: %s\n"),
  418. namenode->divert->useinstead->name);
  419. else if (pkg->set == namenode->divert->pkgset)
  420. printf(_("package diverts others to: %s\n"),
  421. namenode->divert->useinstead->name);
  422. else
  423. printf(_("diverted by %s to: %s\n"),
  424. namenode->divert->pkgset->name,
  425. namenode->divert->useinstead->name);
  426. }
  427. file= file->next;
  428. }
  429. }
  430. break;
  431. }
  432. break;
  433. default:
  434. internerr("unknown action '%d'", cipaction->arg_int);
  435. }
  436. if (*argv != NULL)
  437. putchar('\n');
  438. m_output(stdout, _("<standard output>"));
  439. }
  440. if (failures) {
  441. fputs(_("Use dpkg --info (= dpkg-deb --info) to examine archive files,\n"
  442. "and dpkg --contents (= dpkg-deb --contents) to list their contents.\n"),stderr);
  443. m_output(stderr, _("<standard error>"));
  444. }
  445. modstatdb_shutdown();
  446. return failures;
  447. }
  448. static int
  449. showpackages(const char *const *argv)
  450. {
  451. struct dpkg_error err;
  452. struct pkg_array array;
  453. struct pkginfo *pkg;
  454. struct pkg_format_node *fmt;
  455. int i;
  456. int failures = 0;
  457. fmt = pkg_format_parse(showformat, &err);
  458. if (!fmt) {
  459. notice(_("error in show format: %s"), err.str);
  460. dpkg_error_destroy(&err);
  461. failures++;
  462. return failures;
  463. }
  464. if (!opt_loadavail)
  465. modstatdb_open(msdbrw_readonly);
  466. else
  467. modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
  468. pkg_array_init_from_db(&array);
  469. pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
  470. if (!*argv) {
  471. for (i = 0; i < array.n_pkgs; i++) {
  472. pkg = array.pkgs[i];
  473. if (pkg->status == stat_notinstalled) continue;
  474. pkg_format_show(fmt, pkg, &pkg->installed);
  475. }
  476. } else {
  477. int argc, ip, *found;
  478. struct pkg_spec *ps;
  479. for (argc = 0; argv[argc]; argc++);
  480. found = m_calloc(sizeof(int) * argc);
  481. ps = m_malloc(sizeof(*ps) * argc);
  482. for (ip = 0; ip < argc; ip++) {
  483. pkg_spec_init(&ps[ip], psf_patterns | psf_arch_def_wildcard);
  484. pkg_spec_parse(&ps[ip], argv[ip]);
  485. }
  486. for (i = 0; i < array.n_pkgs; i++) {
  487. pkg = array.pkgs[i];
  488. for (ip = 0; ip < argc; ip++) {
  489. if (pkg_spec_match_pkg(&ps[ip], pkg, &pkg->installed)) {
  490. pkg_format_show(fmt, pkg, &pkg->installed);
  491. found[ip]++;
  492. break;
  493. }
  494. }
  495. }
  496. /* FIXME: we might get non-matching messages for sub-patterns specified
  497. * after their super-patterns, due to us skipping on first match. */
  498. for (ip = 0; ip < argc; ip++) {
  499. if (!found[ip]) {
  500. notice(_("no packages found matching %s"), argv[ip]);
  501. failures++;
  502. }
  503. pkg_spec_destroy(&ps[ip]);
  504. }
  505. free(ps);
  506. free(found);
  507. }
  508. m_output(stdout, _("<standard output>"));
  509. m_output(stderr, _("<standard error>"));
  510. pkg_array_destroy(&array);
  511. pkg_format_free(fmt);
  512. modstatdb_shutdown();
  513. return failures;
  514. }
  515. static bool
  516. pkg_infodb_is_internal(const char *filetype)
  517. {
  518. /* Do not expose internal database files. */
  519. if (strcmp(filetype, LISTFILE) == 0 ||
  520. strcmp(filetype, CONFFILESFILE) == 0)
  521. return true;
  522. if (strlen(filetype) > MAXCONTROLFILENAME)
  523. return true;
  524. return false;
  525. }
  526. static void
  527. pkg_infodb_check_filetype(const char *filetype)
  528. {
  529. const char *c;
  530. /* Validate control file name for sanity. */
  531. for (c = "/."; *c; c++)
  532. if (strchr(filetype, *c))
  533. badusage(_("control file contains %c"), *c);
  534. }
  535. static void
  536. pkg_infodb_print_filename(const char *filename, const char *filetype)
  537. {
  538. if (pkg_infodb_is_internal(filetype))
  539. return;
  540. printf("%s\n", filename);
  541. }
  542. static void
  543. pkg_infodb_print_filetype(const char *filename, const char *filetype)
  544. {
  545. if (pkg_infodb_is_internal(filetype))
  546. return;
  547. printf("%s\n", filetype);
  548. }
  549. static void
  550. control_path_file(struct pkginfo *pkg, const char *control_file)
  551. {
  552. const char *control_path;
  553. struct stat st;
  554. control_path = pkg_infodb_get_file(pkg, &pkg->installed, control_file);
  555. if (stat(control_path, &st) < 0)
  556. return;
  557. if (!S_ISREG(st.st_mode))
  558. return;
  559. pkg_infodb_print_filename(control_path, control_file);
  560. }
  561. static int
  562. control_path(const char *const *argv)
  563. {
  564. struct dpkg_error err;
  565. struct pkginfo *pkg;
  566. const char *pkgname;
  567. const char *control_file;
  568. pkgname = *argv++;
  569. if (!pkgname)
  570. badusage(_("--%s needs at least one package name argument"),
  571. cipaction->olong);
  572. control_file = *argv++;
  573. if (control_file && *argv)
  574. badusage(_("--%s takes at most two arguments"), cipaction->olong);
  575. if (control_file)
  576. pkg_infodb_check_filetype(control_file);
  577. modstatdb_open(msdbrw_readonly);
  578. pkg = pkg_spec_parse_pkg(pkgname, &err);
  579. if (pkg == NULL)
  580. badusage(_("--%s needs a valid package name but '%.250s' is not: %s"),
  581. cipaction->olong, pkgname, err.str);
  582. if (pkg->status == stat_notinstalled)
  583. ohshit(_("package '%s' is not installed"),
  584. pkg_name(pkg, pnaw_nonambig));
  585. if (control_file)
  586. control_path_file(pkg, control_file);
  587. else
  588. pkg_infodb_foreach(pkg, &pkg->installed, pkg_infodb_print_filename);
  589. modstatdb_shutdown();
  590. return 0;
  591. }
  592. static int
  593. control_list(const char *const *argv)
  594. {
  595. struct dpkg_error err;
  596. struct pkginfo *pkg;
  597. const char *pkgname;
  598. pkgname = *argv++;
  599. if (!pkgname || *argv)
  600. badusage(_("--%s takes one package name argument"), cipaction->olong);
  601. modstatdb_open(msdbrw_readonly);
  602. pkg = pkg_spec_parse_pkg(pkgname, &err);
  603. if (pkg == NULL)
  604. badusage(_("--%s needs a valid package name but '%.250s' is not: %s"),
  605. cipaction->olong, pkgname, err.str);
  606. if (pkg->status == stat_notinstalled)
  607. ohshit(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
  608. pkg_infodb_foreach(pkg, &pkg->installed, pkg_infodb_print_filetype);
  609. modstatdb_shutdown();
  610. return 0;
  611. }
  612. static int
  613. control_show(const char *const *argv)
  614. {
  615. struct dpkg_error err;
  616. struct pkginfo *pkg;
  617. const char *pkgname;
  618. const char *filename;
  619. const char *control_file;
  620. pkgname = *argv++;
  621. if (!pkgname || !*argv)
  622. badusage(_("--%s takes exactly two arguments"),
  623. cipaction->olong);
  624. control_file = *argv++;
  625. if (!control_file || *argv)
  626. badusage(_("--%s takes exactly two arguments"), cipaction->olong);
  627. pkg_infodb_check_filetype(control_file);
  628. modstatdb_open(msdbrw_readonly);
  629. pkg = pkg_spec_parse_pkg(pkgname, &err);
  630. if (pkg == NULL)
  631. badusage(_("--%s needs a valid package name but '%.250s' is not: %s"),
  632. cipaction->olong, pkgname, err.str);
  633. if (pkg->status == stat_notinstalled)
  634. ohshit(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
  635. if (pkg_infodb_has_file(pkg, &pkg->installed, control_file))
  636. filename = pkg_infodb_get_file(pkg, &pkg->installed, control_file);
  637. else
  638. ohshit(_("control file '%s' does not exist"), control_file);
  639. modstatdb_shutdown();
  640. file_show(filename);
  641. return 0;
  642. }
  643. static void DPKG_ATTR_NORET
  644. printversion(const struct cmdinfo *ci, const char *value)
  645. {
  646. printf(_("Debian %s package management program query tool version %s.\n"),
  647. DPKGQUERY, DPKG_VERSION_ARCH);
  648. printf(_(
  649. "This is free software; see the GNU General Public License version 2 or\n"
  650. "later for copying conditions. There is NO warranty.\n"));
  651. m_output(stdout, _("<standard output>"));
  652. exit(0);
  653. }
  654. static void DPKG_ATTR_NORET
  655. usage(const struct cmdinfo *ci, const char *value)
  656. {
  657. printf(_(
  658. "Usage: %s [<option> ...] <command>\n"
  659. "\n"), DPKGQUERY);
  660. printf(_(
  661. "Commands:\n"
  662. " -s|--status <package> ... Display package status details.\n"
  663. " -p|--print-avail <package> ... Display available version details.\n"
  664. " -L|--listfiles <package> ... List files `owned' by package(s).\n"
  665. " -l|--list [<pattern> ...] List packages concisely.\n"
  666. " -W|--show [<pattern> ...] Show information on package(s).\n"
  667. " -S|--search <pattern> ... Find package(s) owning file(s).\n"
  668. " --control-list <package> Print the package control file list.\n"
  669. " --control-show <package> <file>\n"
  670. " Show the package control file.\n"
  671. " -c|--control-path <package> [<file>]\n"
  672. " Print path for package control file.\n"
  673. "\n"));
  674. printf(_(
  675. " -?, --help Show this help message.\n"
  676. " --version Show the version.\n"
  677. "\n"));
  678. printf(_(
  679. "Options:\n"
  680. " --admindir=<directory> Use <directory> instead of %s.\n"
  681. " --load-avail Use available file on --show and --list.\n"
  682. " -f|--showformat=<format> Use alternative format for --show.\n"
  683. "\n"), ADMINDIR);
  684. printf(_(
  685. "Format syntax:\n"
  686. " A format is a string that will be output for each package. The format\n"
  687. " can include the standard escape sequences \\n (newline), \\r (carriage\n"
  688. " return) or \\\\ (plain backslash). Package information can be included\n"
  689. " by inserting variable references to package fields using the ${var[;width]}\n"
  690. " syntax. Fields will be right-aligned unless the width is negative in which\n"
  691. " case left alignment will be used.\n"));
  692. m_output(stdout, _("<standard output>"));
  693. exit(0);
  694. }
  695. static const char printforhelp[] = N_(
  696. "Use --help for help about querying packages.");
  697. static const char *admindir;
  698. /* This table has both the action entries in it and the normal options.
  699. * The action entries are made with the ACTION macro, as they all
  700. * have a very similar structure. */
  701. static const struct cmdinfo cmdinfos[]= {
  702. ACTION( "listfiles", 'L', act_listfiles, enqperpackage ),
  703. ACTION( "status", 's', act_status, enqperpackage ),
  704. ACTION( "print-avail", 'p', act_printavail, enqperpackage ),
  705. ACTION( "list", 'l', act_listpackages, listpackages ),
  706. ACTION( "search", 'S', act_searchfiles, searchfiles ),
  707. ACTION( "show", 'W', act_listpackages, showpackages ),
  708. ACTION( "control-path", 'c', act_controlpath, control_path ),
  709. ACTION( "control-list", 0, act_controllist, control_list ),
  710. ACTION( "control-show", 0, act_controlshow, control_show ),
  711. { "admindir", 0, 1, NULL, &admindir, NULL },
  712. { "load-avail", 0, 0, &opt_loadavail, NULL, NULL, 1 },
  713. { "showformat", 'f', 1, NULL, &showformat, NULL },
  714. { "help", '?', 0, NULL, NULL, usage },
  715. { "version", 0, 0, NULL, NULL, printversion },
  716. { NULL, 0, 0, NULL, NULL, NULL }
  717. };
  718. int main(int argc, const char *const *argv) {
  719. int ret;
  720. setlocale(LC_ALL, "");
  721. bindtextdomain(PACKAGE, LOCALEDIR);
  722. textdomain(PACKAGE);
  723. dpkg_set_progname("dpkg-query");
  724. standard_startup();
  725. myopt(&argv, cmdinfos, printforhelp);
  726. admindir = dpkg_db_set_dir(admindir);
  727. if (!cipaction) badusage(_("need an action option"));
  728. setvbuf(stdout, NULL, _IONBF, 0);
  729. filesdbinit();
  730. ret = cipaction->action(argv);
  731. standard_shutdown();
  732. return !!ret;
  733. }