querycmd.c 23 KB

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