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