enquiry.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. /*
  2. * dpkg - main program for package management
  3. * enquiry.c - status enquiry and listing options
  4. *
  5. * Copyright © 1995,1996 Ian Jackson <ian@chiark.greenend.org.uk>
  6. * Copyright © 2006, 2008-2015 Guillem Jover <guillem@debian.org>
  7. * Copyright © 2011 Linaro Limited
  8. * Copyright © 2011 Raphaël Hertzog <hertzog@debian.org>
  9. *
  10. * This is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  22. */
  23. #include <config.h>
  24. #include <compat.h>
  25. #include <sys/types.h>
  26. #include <assert.h>
  27. #include <string.h>
  28. #include <fcntl.h>
  29. #include <unistd.h>
  30. #include <stdbool.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <dpkg/i18n.h>
  34. #include <dpkg/dpkg.h>
  35. #include <dpkg/dpkg-db.h>
  36. #include <dpkg/arch.h>
  37. #include <dpkg/pkg-array.h>
  38. #include <dpkg/pkg-show.h>
  39. #include <dpkg/string.h>
  40. #include <dpkg/options.h>
  41. #include "filesdb.h"
  42. #include "infodb.h"
  43. #include "main.h"
  44. struct audit_problem {
  45. bool (*check)(struct pkginfo *, const struct audit_problem *problem);
  46. union {
  47. int number;
  48. const char *string;
  49. } value;
  50. const char *explanation;
  51. };
  52. static bool
  53. audit_reinstreq(struct pkginfo *pkg, const struct audit_problem *problem)
  54. {
  55. return pkg->eflag & PKG_EFLAG_REINSTREQ;
  56. }
  57. static bool
  58. audit_status(struct pkginfo *pkg, const struct audit_problem *problem)
  59. {
  60. if (pkg->eflag & PKG_EFLAG_REINSTREQ)
  61. return false;
  62. return (int)pkg->status == problem->value.number;
  63. }
  64. static bool
  65. audit_infofile(struct pkginfo *pkg, const struct audit_problem *problem)
  66. {
  67. if (pkg->status < PKG_STAT_HALFINSTALLED)
  68. return false;
  69. return !pkg_infodb_has_file(pkg, &pkg->installed, problem->value.string);
  70. }
  71. static bool
  72. audit_arch(struct pkginfo *pkg, const struct audit_problem *problem)
  73. {
  74. if (pkg->status < PKG_STAT_HALFINSTALLED)
  75. return false;
  76. return pkg->installed.arch->type == (enum dpkg_arch_type)problem->value.number;
  77. }
  78. static const struct audit_problem audit_problems[] = {
  79. {
  80. .check = audit_reinstreq,
  81. .value.number = 0,
  82. .explanation = N_(
  83. "The following packages are in a mess due to serious problems during\n"
  84. "installation. They must be reinstalled for them (and any packages\n"
  85. "that depend on them) to function properly:\n")
  86. }, {
  87. .check = audit_status,
  88. .value.number = PKG_STAT_UNPACKED,
  89. .explanation = N_(
  90. "The following packages have been unpacked but not yet configured.\n"
  91. "They must be configured using dpkg --configure or the configure\n"
  92. "menu option in dselect for them to work:\n")
  93. }, {
  94. .check = audit_status,
  95. .value.number = PKG_STAT_HALFCONFIGURED,
  96. .explanation = N_(
  97. "The following packages are only half configured, probably due to problems\n"
  98. "configuring them the first time. The configuration should be retried using\n"
  99. "dpkg --configure <package> or the configure menu option in dselect:\n")
  100. }, {
  101. .check = audit_status,
  102. .value.number = PKG_STAT_HALFINSTALLED,
  103. .explanation = N_(
  104. "The following packages are only half installed, due to problems during\n"
  105. "installation. The installation can probably be completed by retrying it;\n"
  106. "the packages can be removed using dselect or dpkg --remove:\n")
  107. }, {
  108. .check = audit_status,
  109. .value.number = PKG_STAT_TRIGGERSAWAITED,
  110. .explanation = N_(
  111. "The following packages are awaiting processing of triggers that they\n"
  112. "have activated in other packages. This processing can be requested using\n"
  113. "dselect or dpkg --configure --pending (or dpkg --triggers-only):\n")
  114. }, {
  115. .check = audit_status,
  116. .value.number = PKG_STAT_TRIGGERSPENDING,
  117. .explanation = N_(
  118. "The following packages have been triggered, but the trigger processing\n"
  119. "has not yet been done. Trigger processing can be requested using\n"
  120. "dselect or dpkg --configure --pending (or dpkg --triggers-only):\n")
  121. }, {
  122. .check = audit_infofile,
  123. .value.string = LISTFILE,
  124. .explanation = N_(
  125. "The following packages are missing the list control file in the\n"
  126. "database, they need to be reinstalled:\n")
  127. }, {
  128. .check = audit_infofile,
  129. .value.string = HASHFILE,
  130. .explanation = N_(
  131. "The following packages are missing the md5sums control file in the\n"
  132. "database, they need to be reinstalled:\n")
  133. }, {
  134. .check = audit_arch,
  135. .value.number = DPKG_ARCH_EMPTY,
  136. .explanation = N_("The following packages do not have an architecture:\n")
  137. }, {
  138. .check = audit_arch,
  139. .value.number = DPKG_ARCH_ILLEGAL,
  140. .explanation = N_("The following packages have an illegal architecture:\n")
  141. }, {
  142. .check = audit_arch,
  143. .value.number = DPKG_ARCH_UNKNOWN,
  144. .explanation = N_(
  145. "The following packages have an unknown foreign architecture, which will\n"
  146. "cause dependency issues on front-ends. This can be fixed by registering\n"
  147. "the foreign architecture with dpkg --add-architecture:\n")
  148. }, {
  149. .check = NULL
  150. }
  151. };
  152. static void describebriefly(struct pkginfo *pkg) {
  153. int maxl, l;
  154. const char *pdesc;
  155. maxl= 57;
  156. l= strlen(pkg->set->name);
  157. if (l>20) maxl -= (l-20);
  158. pdesc = pkg_summary(pkg, &pkg->installed, &l);
  159. l = min(l, maxl);
  160. printf(" %-20s %.*s\n", pkg_name(pkg, pnaw_nonambig), l, pdesc);
  161. }
  162. static struct pkginfo *
  163. pkg_array_mapper(const char *name)
  164. {
  165. struct pkginfo *pkg;
  166. pkg = dpkg_options_parse_pkgname(cipaction, name);
  167. if (pkg->status == PKG_STAT_NOTINSTALLED)
  168. notice(_("package '%s' is not installed"), pkg_name(pkg, pnaw_nonambig));
  169. return pkg;
  170. }
  171. int
  172. audit(const char *const *argv)
  173. {
  174. const struct audit_problem *problem;
  175. struct pkg_array array;
  176. bool head_running = false;
  177. int i;
  178. modstatdb_open(msdbrw_readonly);
  179. if (!*argv)
  180. pkg_array_init_from_db(&array);
  181. else
  182. pkg_array_init_from_names(&array, pkg_array_mapper, (const char **)argv);
  183. pkg_array_sort(&array, pkg_sorter_by_nonambig_name_arch);
  184. for (problem = audit_problems; problem->check; problem++) {
  185. bool head = false;
  186. for (i = 0; i < array.n_pkgs; i++) {
  187. struct pkginfo *pkg = array.pkgs[i];
  188. if (!problem->check(pkg, problem))
  189. continue;
  190. if (!head_running) {
  191. if (modstatdb_is_locked())
  192. puts(_(
  193. "Another process has locked the database for writing, and might currently be\n"
  194. "modifying it, some of the following problems might just be due to that.\n"));
  195. head_running = true;
  196. }
  197. if (!head) {
  198. fputs(gettext(problem->explanation), stdout);
  199. head = true;
  200. }
  201. describebriefly(pkg);
  202. }
  203. if (head) putchar('\n');
  204. }
  205. pkg_array_destroy(&array);
  206. m_output(stdout, _("<standard output>"));
  207. return 0;
  208. }
  209. struct sectionentry {
  210. struct sectionentry *next;
  211. const char *name;
  212. int count;
  213. };
  214. static bool
  215. yettobeunpacked(struct pkginfo *pkg, const char **thissect)
  216. {
  217. if (pkg->want != PKG_WANT_INSTALL)
  218. return false;
  219. switch (pkg->status) {
  220. case PKG_STAT_UNPACKED:
  221. case PKG_STAT_INSTALLED:
  222. case PKG_STAT_HALFCONFIGURED:
  223. case PKG_STAT_TRIGGERSPENDING:
  224. case PKG_STAT_TRIGGERSAWAITED:
  225. return false;
  226. case PKG_STAT_NOTINSTALLED:
  227. case PKG_STAT_HALFINSTALLED:
  228. case PKG_STAT_CONFIGFILES:
  229. if (thissect)
  230. *thissect = str_is_set(pkg->section) ? pkg->section :
  231. C_("section", "<unknown>");
  232. return true;
  233. default:
  234. internerr("unknown package status '%d'", pkg->status);
  235. }
  236. return false;
  237. }
  238. int
  239. unpackchk(const char *const *argv)
  240. {
  241. int totalcount, sects;
  242. struct sectionentry *sectionentries, *se, **sep;
  243. struct pkgiterator *it;
  244. struct pkginfo *pkg;
  245. const char *thissect;
  246. char buf[20];
  247. int width;
  248. if (*argv)
  249. badusage(_("--%s takes no arguments"), cipaction->olong);
  250. modstatdb_open(msdbrw_readonly);
  251. totalcount= 0;
  252. sectionentries = NULL;
  253. sects= 0;
  254. it = pkg_db_iter_new();
  255. while ((pkg = pkg_db_iter_next_pkg(it))) {
  256. if (!yettobeunpacked(pkg, &thissect)) continue;
  257. for (se= sectionentries; se && strcasecmp(thissect,se->name); se= se->next);
  258. if (!se) {
  259. se= nfmalloc(sizeof(struct sectionentry));
  260. for (sep= &sectionentries;
  261. *sep && strcasecmp(thissect,(*sep)->name) > 0;
  262. sep= &(*sep)->next);
  263. se->name= thissect;
  264. se->count= 0;
  265. se->next= *sep;
  266. *sep= se;
  267. sects++;
  268. }
  269. se->count++; totalcount++;
  270. }
  271. pkg_db_iter_free(it);
  272. if (totalcount == 0)
  273. return 0;
  274. if (totalcount <= 12) {
  275. it = pkg_db_iter_new();
  276. while ((pkg = pkg_db_iter_next_pkg(it))) {
  277. if (!yettobeunpacked(pkg, NULL))
  278. continue;
  279. describebriefly(pkg);
  280. }
  281. pkg_db_iter_free(it);
  282. } else if (sects <= 12) {
  283. for (se= sectionentries; se; se= se->next) {
  284. sprintf(buf,"%d",se->count);
  285. printf(_(" %d in %s: "),se->count,se->name);
  286. width= 70-strlen(se->name)-strlen(buf);
  287. while (width > 59) { putchar(' '); width--; }
  288. it = pkg_db_iter_new();
  289. while ((pkg = pkg_db_iter_next_pkg(it))) {
  290. const char *pkgname;
  291. if (!yettobeunpacked(pkg,&thissect)) continue;
  292. if (strcasecmp(thissect,se->name)) continue;
  293. pkgname = pkg_name(pkg, pnaw_nonambig);
  294. width -= strlen(pkgname);
  295. width--;
  296. if (width < 4) { printf(" ..."); break; }
  297. printf(" %s", pkgname);
  298. }
  299. pkg_db_iter_free(it);
  300. putchar('\n');
  301. }
  302. } else {
  303. printf(P_(" %d package, from the following section:",
  304. " %d packages, from the following sections:", totalcount),
  305. totalcount);
  306. width= 0;
  307. for (se= sectionentries; se; se= se->next) {
  308. sprintf(buf,"%d",se->count);
  309. width -= (6 + strlen(se->name) + strlen(buf));
  310. if (width < 0) { putchar('\n'); width= 73 - strlen(se->name) - strlen(buf); }
  311. printf(" %s (%d)",se->name,se->count);
  312. }
  313. putchar('\n');
  314. }
  315. m_output(stdout, _("<standard output>"));
  316. return 0;
  317. }
  318. static int
  319. assert_version_support(const char *const *argv,
  320. struct dpkg_version *version,
  321. const char *feature_name)
  322. {
  323. struct pkginfo *pkg;
  324. if (*argv)
  325. badusage(_("--%s takes no arguments"), cipaction->olong);
  326. modstatdb_open(msdbrw_readonly);
  327. pkg = pkg_db_find_singleton("dpkg");
  328. switch (pkg->status) {
  329. case PKG_STAT_INSTALLED:
  330. case PKG_STAT_TRIGGERSPENDING:
  331. return 0;
  332. case PKG_STAT_UNPACKED:
  333. case PKG_STAT_HALFCONFIGURED:
  334. case PKG_STAT_HALFINSTALLED:
  335. case PKG_STAT_TRIGGERSAWAITED:
  336. if (dpkg_version_relate(&pkg->configversion, DPKG_RELATION_GE, version))
  337. return 0;
  338. printf(_("Version of dpkg with working %s support not yet configured.\n"
  339. " Please use 'dpkg --configure dpkg', and then try again.\n"),
  340. feature_name);
  341. return 1;
  342. default:
  343. printf(_("dpkg not recorded as installed, cannot check for %s support!\n"),
  344. feature_name);
  345. return 1;
  346. }
  347. }
  348. int
  349. assertpredep(const char *const *argv)
  350. {
  351. struct dpkg_version version = { 0, "1.1.0", NULL };
  352. return assert_version_support(argv, &version, _("Pre-Depends field"));
  353. }
  354. int
  355. assertepoch(const char *const *argv)
  356. {
  357. struct dpkg_version version = { 0, "1.4.0.7", NULL };
  358. return assert_version_support(argv, &version, _("epoch"));
  359. }
  360. int
  361. assertlongfilenames(const char *const *argv)
  362. {
  363. struct dpkg_version version = { 0, "1.4.1.17", NULL };
  364. return assert_version_support(argv, &version, _("long filenames"));
  365. }
  366. int
  367. assertmulticonrep(const char *const *argv)
  368. {
  369. struct dpkg_version version = { 0, "1.4.1.19", NULL };
  370. return assert_version_support(argv, &version,
  371. _("multiple Conflicts and Replaces"));
  372. }
  373. int
  374. assertmultiarch(const char *const *argv)
  375. {
  376. struct dpkg_version version = { 0, "1.16.2", NULL };
  377. return assert_version_support(argv, &version, _("multi-arch"));
  378. }
  379. int
  380. assertverprovides(const char *const *argv)
  381. {
  382. struct dpkg_version version = { 0, "1.17.11", NULL };
  383. return assert_version_support(argv, &version, _("versioned Provides"));
  384. }
  385. /**
  386. * Print a single package which:
  387. * (a) is the target of one or more relevant predependencies.
  388. * (b) has itself no unsatisfied pre-dependencies.
  389. *
  390. * If such a package is present output is the Packages file entry,
  391. * which can be massaged as appropriate.
  392. *
  393. * Exit status:
  394. * 0 = a package printed, OK
  395. * 1 = no suitable package available
  396. * 2 = error
  397. */
  398. int
  399. predeppackage(const char *const *argv)
  400. {
  401. static struct varbuf vb;
  402. struct pkgiterator *it;
  403. struct pkginfo *pkg = NULL, *startpkg, *trypkg;
  404. struct dependency *dep;
  405. struct deppossi *possi, *provider;
  406. if (*argv)
  407. badusage(_("--%s takes no arguments"), cipaction->olong);
  408. modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
  409. /* We use clientdata->istobe to detect loops. */
  410. clear_istobes();
  411. dep = NULL;
  412. it = pkg_db_iter_new();
  413. while (!dep && (pkg = pkg_db_iter_next_pkg(it))) {
  414. /* Ignore packages user doesn't want. */
  415. if (pkg->want != PKG_WANT_INSTALL)
  416. continue;
  417. /* Ignore packages not available. */
  418. if (!pkg->files)
  419. continue;
  420. pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
  421. for (dep= pkg->available.depends; dep; dep= dep->next) {
  422. if (dep->type != dep_predepends) continue;
  423. if (depisok(dep, &vb, NULL, NULL, true))
  424. continue;
  425. /* This will leave dep non-NULL, and so exit the loop. */
  426. break;
  427. }
  428. pkg->clientdata->istobe = PKG_ISTOBE_NORMAL;
  429. /* If dep is NULL we go and get the next package. */
  430. }
  431. pkg_db_iter_free(it);
  432. if (!dep)
  433. return 1; /* Not found. */
  434. assert(pkg);
  435. startpkg= pkg;
  436. pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
  437. /* OK, we have found an unsatisfied predependency.
  438. * Now go and find the first thing we need to install, as a first step
  439. * towards satisfying it. */
  440. do {
  441. /* We search for a package which would satisfy dep, and put it in pkg. */
  442. for (possi = dep->list, pkg = NULL;
  443. !pkg && possi;
  444. possi=possi->next) {
  445. struct deppossi_pkg_iterator *possi_iter;
  446. possi_iter = deppossi_pkg_iter_new(possi, wpb_available);
  447. while (!pkg && (trypkg = deppossi_pkg_iter_next(possi_iter))) {
  448. if (trypkg->files &&
  449. trypkg->clientdata->istobe == PKG_ISTOBE_NORMAL &&
  450. versionsatisfied(&trypkg->available, possi)) {
  451. pkg = trypkg;
  452. break;
  453. }
  454. for (provider = possi->ed->depended.available;
  455. !pkg && provider;
  456. provider = provider->next) {
  457. if (provider->up->type != dep_provides)
  458. continue;
  459. if (!pkg_virtual_deppossi_satisfied(possi, provider))
  460. continue;
  461. trypkg = provider->up->up;
  462. if (!trypkg->files)
  463. continue;
  464. if (trypkg->clientdata->istobe == PKG_ISTOBE_NORMAL) {
  465. pkg = trypkg;
  466. break;
  467. }
  468. }
  469. }
  470. deppossi_pkg_iter_free(possi_iter);
  471. }
  472. if (!pkg) {
  473. varbuf_reset(&vb);
  474. describedepcon(&vb,dep);
  475. varbuf_end_str(&vb);
  476. notice(_("cannot see how to satisfy pre-dependency:\n %s"), vb.buf);
  477. ohshit(_("cannot satisfy pre-dependencies for %.250s (wanted due to %.250s)"),
  478. pkgbin_name(dep->up, &dep->up->available, pnaw_nonambig),
  479. pkgbin_name(startpkg, &startpkg->available, pnaw_nonambig));
  480. }
  481. pkg->clientdata->istobe = PKG_ISTOBE_PREINSTALL;
  482. for (dep= pkg->available.depends; dep; dep= dep->next) {
  483. if (dep->type != dep_predepends) continue;
  484. if (depisok(dep, &vb, NULL, NULL, true))
  485. continue;
  486. /* This will leave dep non-NULL, and so exit the loop. */
  487. break;
  488. }
  489. } while (dep);
  490. /* OK, we've found it - pkg has no unsatisfied pre-dependencies! */
  491. writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
  492. m_output(stdout, _("<standard output>"));
  493. return 0;
  494. }
  495. int
  496. printarch(const char *const *argv)
  497. {
  498. if (*argv)
  499. badusage(_("--%s takes no arguments"), cipaction->olong);
  500. printf("%s\n", dpkg_arch_get(DPKG_ARCH_NATIVE)->name);
  501. m_output(stdout, _("<standard output>"));
  502. return 0;
  503. }
  504. int
  505. printinstarch(const char *const *argv)
  506. {
  507. warning(_("obsolete option '--%s'; please use '--%s' instead"),
  508. "print-installation-architecture", "print-architecture");
  509. return printarch(argv);
  510. }
  511. int
  512. print_foreign_arches(const char *const *argv)
  513. {
  514. struct dpkg_arch *arch;
  515. if (*argv)
  516. badusage(_("--%s takes no arguments"), cipaction->olong);
  517. dpkg_arch_load_list();
  518. for (arch = dpkg_arch_get_list(); arch; arch = arch->next) {
  519. if (arch->type != DPKG_ARCH_FOREIGN)
  520. continue;
  521. printf("%s\n", arch->name);
  522. }
  523. m_output(stdout, _("<standard output>"));
  524. return 0;
  525. }
  526. int
  527. cmpversions(const char *const *argv)
  528. {
  529. struct relationinfo {
  530. const char *string;
  531. /* These values are exit status codes, so 0 = true, 1 = false. */
  532. int if_lesser, if_equal, if_greater;
  533. int if_none_a, if_none_both, if_none_b;
  534. bool obsolete;
  535. };
  536. static const struct relationinfo relationinfos[]= {
  537. /* < = > !a!2!b */
  538. { "le", 0,0,1, 0,0,1 },
  539. { "lt", 0,1,1, 0,1,1 },
  540. { "eq", 1,0,1, 1,0,1 },
  541. { "ne", 0,1,0, 0,1,0 },
  542. { "ge", 1,0,0, 1,0,0 },
  543. { "gt", 1,1,0, 1,1,0 },
  544. /* These treat an empty version as later than any version. */
  545. { "le-nl", 0,0,1, 1,0,0 },
  546. { "lt-nl", 0,1,1, 1,1,0 },
  547. { "ge-nl", 1,0,0, 0,0,1 },
  548. { "gt-nl", 1,1,0, 0,1,1 },
  549. /* For compatibility with dpkg control file syntax. */
  550. { "<", 0,0,1, 0,0,1, .obsolete = true },
  551. { "<=", 0,0,1, 0,0,1 },
  552. { "<<", 0,1,1, 0,1,1 },
  553. { "=", 1,0,1, 1,0,1 },
  554. { ">", 1,0,0, 1,0,0, .obsolete = true },
  555. { ">=", 1,0,0, 1,0,0 },
  556. { ">>", 1,1,0, 1,1,0 },
  557. { NULL }
  558. };
  559. const struct relationinfo *rip;
  560. struct dpkg_version a, b;
  561. struct dpkg_error err;
  562. int rc;
  563. if (!argv[0] || !argv[1] || !argv[2] || argv[3])
  564. badusage(_("--compare-versions takes three arguments:"
  565. " <version> <relation> <version>"));
  566. for (rip=relationinfos; rip->string && strcmp(rip->string,argv[1]); rip++);
  567. if (!rip->string) badusage(_("--compare-versions bad relation"));
  568. if (rip->obsolete)
  569. warning(_("--%s used with obsolete relation operator '%s'"),
  570. cipaction->olong, rip->string);
  571. if (*argv[0] && strcmp(argv[0],"<unknown>")) {
  572. if (parseversion(&a, argv[0], &err) < 0) {
  573. dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[0]);
  574. dpkg_error_destroy(&err);
  575. }
  576. } else {
  577. dpkg_version_blank(&a);
  578. }
  579. if (*argv[2] && strcmp(argv[2],"<unknown>")) {
  580. if (parseversion(&b, argv[2], &err) < 0) {
  581. dpkg_error_print(&err, _("version '%s' has bad syntax"), argv[2]);
  582. dpkg_error_destroy(&err);
  583. }
  584. } else {
  585. dpkg_version_blank(&b);
  586. }
  587. if (!dpkg_version_is_informative(&a)) {
  588. if (dpkg_version_is_informative(&b))
  589. return rip->if_none_a;
  590. else
  591. return rip->if_none_both;
  592. } else if (!dpkg_version_is_informative(&b)) {
  593. return rip->if_none_b;
  594. }
  595. rc = dpkg_version_compare(&a, &b);
  596. debug(dbg_general, "cmpversions a='%s' b='%s' r=%d",
  597. versiondescribe(&a,vdew_always),
  598. versiondescribe(&b,vdew_always),
  599. rc);
  600. if (rc > 0)
  601. return rip->if_greater;
  602. else if (rc < 0)
  603. return rip->if_lesser;
  604. else
  605. return rip->if_equal;
  606. }