enquiry.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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-2014 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 & eflag_reinstreq;
  56. }
  57. static bool
  58. audit_status(struct pkginfo *pkg, const struct audit_problem *problem)
  59. {
  60. if (pkg->eflag & 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 < 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 < 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 = 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 = 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 = 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 = 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 = 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_NONE,
  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 == 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 != want_install)
  218. return false;
  219. switch (pkg->status) {
  220. case stat_unpacked: case stat_installed: case stat_halfconfigured:
  221. case stat_triggerspending:
  222. case stat_triggersawaited:
  223. return false;
  224. case stat_notinstalled: case stat_halfinstalled: case stat_configfiles:
  225. if (thissect)
  226. *thissect = str_is_set(pkg->section) ? pkg->section :
  227. C_("section", "<unknown>");
  228. return true;
  229. default:
  230. internerr("unknown package status '%d'", pkg->status);
  231. }
  232. return false;
  233. }
  234. int
  235. unpackchk(const char *const *argv)
  236. {
  237. int totalcount, sects;
  238. struct sectionentry *sectionentries, *se, **sep;
  239. struct pkgiterator *it;
  240. struct pkginfo *pkg;
  241. const char *thissect;
  242. char buf[20];
  243. int width;
  244. if (*argv)
  245. badusage(_("--%s takes no arguments"), cipaction->olong);
  246. modstatdb_open(msdbrw_readonly);
  247. totalcount= 0;
  248. sectionentries = NULL;
  249. sects= 0;
  250. it = pkg_db_iter_new();
  251. while ((pkg = pkg_db_iter_next_pkg(it))) {
  252. if (!yettobeunpacked(pkg, &thissect)) continue;
  253. for (se= sectionentries; se && strcasecmp(thissect,se->name); se= se->next);
  254. if (!se) {
  255. se= nfmalloc(sizeof(struct sectionentry));
  256. for (sep= &sectionentries;
  257. *sep && strcasecmp(thissect,(*sep)->name) > 0;
  258. sep= &(*sep)->next);
  259. se->name= thissect;
  260. se->count= 0;
  261. se->next= *sep;
  262. *sep= se;
  263. sects++;
  264. }
  265. se->count++; totalcount++;
  266. }
  267. pkg_db_iter_free(it);
  268. if (totalcount == 0)
  269. return 0;
  270. if (totalcount <= 12) {
  271. it = pkg_db_iter_new();
  272. while ((pkg = pkg_db_iter_next_pkg(it))) {
  273. if (!yettobeunpacked(pkg, NULL))
  274. continue;
  275. describebriefly(pkg);
  276. }
  277. pkg_db_iter_free(it);
  278. } else if (sects <= 12) {
  279. for (se= sectionentries; se; se= se->next) {
  280. sprintf(buf,"%d",se->count);
  281. printf(_(" %d in %s: "),se->count,se->name);
  282. width= 70-strlen(se->name)-strlen(buf);
  283. while (width > 59) { putchar(' '); width--; }
  284. it = pkg_db_iter_new();
  285. while ((pkg = pkg_db_iter_next_pkg(it))) {
  286. const char *pkgname;
  287. if (!yettobeunpacked(pkg,&thissect)) continue;
  288. if (strcasecmp(thissect,se->name)) continue;
  289. pkgname = pkg_name(pkg, pnaw_nonambig);
  290. width -= strlen(pkgname);
  291. width--;
  292. if (width < 4) { printf(" ..."); break; }
  293. printf(" %s", pkgname);
  294. }
  295. pkg_db_iter_free(it);
  296. putchar('\n');
  297. }
  298. } else {
  299. printf(P_(" %d package, from the following section:",
  300. " %d packages, from the following sections:", totalcount),
  301. totalcount);
  302. width= 0;
  303. for (se= sectionentries; se; se= se->next) {
  304. sprintf(buf,"%d",se->count);
  305. width -= (6 + strlen(se->name) + strlen(buf));
  306. if (width < 0) { putchar('\n'); width= 73 - strlen(se->name) - strlen(buf); }
  307. printf(" %s (%d)",se->name,se->count);
  308. }
  309. putchar('\n');
  310. }
  311. m_output(stdout, _("<standard output>"));
  312. return 0;
  313. }
  314. static int
  315. assert_version_support(const char *const *argv,
  316. struct dpkg_version *version,
  317. const char *feature_name)
  318. {
  319. struct pkginfo *pkg;
  320. if (*argv)
  321. badusage(_("--%s takes no arguments"), cipaction->olong);
  322. modstatdb_open(msdbrw_readonly);
  323. pkg = pkg_db_find_singleton("dpkg");
  324. switch (pkg->status) {
  325. case stat_installed:
  326. case stat_triggerspending:
  327. return 0;
  328. case stat_unpacked: case stat_halfconfigured: case stat_halfinstalled:
  329. case stat_triggersawaited:
  330. if (dpkg_version_relate(&pkg->configversion, DPKG_RELATION_GE, version))
  331. return 0;
  332. printf(_("Version of dpkg with working %s support not yet configured.\n"
  333. " Please use 'dpkg --configure dpkg', and then try again.\n"),
  334. feature_name);
  335. return 1;
  336. default:
  337. printf(_("dpkg not recorded as installed, cannot check for %s support!\n"),
  338. feature_name);
  339. return 1;
  340. }
  341. }
  342. int
  343. assertpredep(const char *const *argv)
  344. {
  345. struct dpkg_version version = { 0, "1.1.0", NULL };
  346. return assert_version_support(argv, &version, _("Pre-Depends field"));
  347. }
  348. int
  349. assertepoch(const char *const *argv)
  350. {
  351. struct dpkg_version version = { 0, "1.4.0.7", NULL };
  352. return assert_version_support(argv, &version, _("epoch"));
  353. }
  354. int
  355. assertlongfilenames(const char *const *argv)
  356. {
  357. struct dpkg_version version = { 0, "1.4.1.17", NULL };
  358. return assert_version_support(argv, &version, _("long filenames"));
  359. }
  360. int
  361. assertmulticonrep(const char *const *argv)
  362. {
  363. struct dpkg_version version = { 0, "1.4.1.19", NULL };
  364. return assert_version_support(argv, &version,
  365. _("multiple Conflicts and Replaces"));
  366. }
  367. int
  368. assertmultiarch(const char *const *argv)
  369. {
  370. struct dpkg_version version = { 0, "1.16.2", NULL };
  371. return assert_version_support(argv, &version, _("multi-arch"));
  372. }
  373. /**
  374. * Print a single package which:
  375. * (a) is the target of one or more relevant predependencies.
  376. * (b) has itself no unsatisfied pre-dependencies.
  377. *
  378. * If such a package is present output is the Packages file entry,
  379. * which can be massaged as appropriate.
  380. *
  381. * Exit status:
  382. * 0 = a package printed, OK
  383. * 1 = no suitable package available
  384. * 2 = error
  385. */
  386. int
  387. predeppackage(const char *const *argv)
  388. {
  389. static struct varbuf vb;
  390. struct pkgiterator *it;
  391. struct pkginfo *pkg = NULL, *startpkg, *trypkg;
  392. struct dependency *dep;
  393. struct deppossi *possi, *provider;
  394. if (*argv)
  395. badusage(_("--%s takes no arguments"), cipaction->olong);
  396. modstatdb_open(msdbrw_readonly | msdbrw_available_readonly);
  397. /* We use clientdata->istobe to detect loops. */
  398. clear_istobes();
  399. dep = NULL;
  400. it = pkg_db_iter_new();
  401. while (!dep && (pkg = pkg_db_iter_next_pkg(it))) {
  402. /* Ignore packages user doesn't want. */
  403. if (pkg->want != want_install)
  404. continue;
  405. /* Ignore packages not available. */
  406. if (!pkg->files)
  407. continue;
  408. pkg->clientdata->istobe= itb_preinstall;
  409. for (dep= pkg->available.depends; dep; dep= dep->next) {
  410. if (dep->type != dep_predepends) continue;
  411. if (depisok(dep, &vb, NULL, NULL, true))
  412. continue;
  413. /* This will leave dep non-NULL, and so exit the loop. */
  414. break;
  415. }
  416. pkg->clientdata->istobe= itb_normal;
  417. /* If dep is NULL we go and get the next package. */
  418. }
  419. pkg_db_iter_free(it);
  420. if (!dep)
  421. return 1; /* Not found. */
  422. assert(pkg);
  423. startpkg= pkg;
  424. pkg->clientdata->istobe= itb_preinstall;
  425. /* OK, we have found an unsatisfied predependency.
  426. * Now go and find the first thing we need to install, as a first step
  427. * towards satisfying it. */
  428. do {
  429. /* We search for a package which would satisfy dep, and put it in pkg. */
  430. for (possi = dep->list, pkg = NULL;
  431. !pkg && possi;
  432. possi=possi->next) {
  433. struct deppossi_pkg_iterator *possi_iter;
  434. possi_iter = deppossi_pkg_iter_new(possi, wpb_available);
  435. while (!pkg && (trypkg = deppossi_pkg_iter_next(possi_iter))) {
  436. if (trypkg->files && trypkg->clientdata->istobe == itb_normal &&
  437. versionsatisfied(&trypkg->available, possi)) {
  438. pkg = trypkg;
  439. break;
  440. }
  441. if (possi->verrel != DPKG_RELATION_NONE)
  442. continue;
  443. for (provider = possi->ed->depended.available;
  444. !pkg && provider;
  445. provider = provider->next) {
  446. if (provider->up->type != dep_provides)
  447. continue;
  448. trypkg = provider->up->up;
  449. if (!trypkg->files)
  450. continue;
  451. if (trypkg->clientdata->istobe == itb_normal) {
  452. pkg = trypkg;
  453. break;
  454. }
  455. }
  456. }
  457. deppossi_pkg_iter_free(possi_iter);
  458. }
  459. if (!pkg) {
  460. varbuf_reset(&vb);
  461. describedepcon(&vb,dep);
  462. varbuf_end_str(&vb);
  463. notice(_("cannot see how to satisfy pre-dependency:\n %s"), vb.buf);
  464. ohshit(_("cannot satisfy pre-dependencies for %.250s (wanted due to %.250s)"),
  465. pkgbin_name(dep->up, &dep->up->available, pnaw_nonambig),
  466. pkgbin_name(startpkg, &startpkg->available, pnaw_nonambig));
  467. }
  468. pkg->clientdata->istobe= itb_preinstall;
  469. for (dep= pkg->available.depends; dep; dep= dep->next) {
  470. if (dep->type != dep_predepends) continue;
  471. if (depisok(dep, &vb, NULL, NULL, true))
  472. continue;
  473. /* This will leave dep non-NULL, and so exit the loop. */
  474. break;
  475. }
  476. } while (dep);
  477. /* OK, we've found it - pkg has no unsatisfied pre-dependencies! */
  478. writerecord(stdout, _("<standard output>"), pkg, &pkg->available);
  479. m_output(stdout, _("<standard output>"));
  480. return 0;
  481. }
  482. int
  483. printarch(const char *const *argv)
  484. {
  485. if (*argv)
  486. badusage(_("--%s takes no arguments"), cipaction->olong);
  487. printf("%s\n", dpkg_arch_get(DPKG_ARCH_NATIVE)->name);
  488. m_output(stdout, _("<standard output>"));
  489. return 0;
  490. }
  491. int
  492. printinstarch(const char *const *argv)
  493. {
  494. warning(_("obsolete option '--%s'; please use '--%s' instead"),
  495. "print-installation-architecture", "print-architecture");
  496. return printarch(argv);
  497. }
  498. int
  499. print_foreign_arches(const char *const *argv)
  500. {
  501. struct dpkg_arch *arch;
  502. if (*argv)
  503. badusage(_("--%s takes no arguments"), cipaction->olong);
  504. dpkg_arch_load_list();
  505. for (arch = dpkg_arch_get_list(); arch; arch = arch->next) {
  506. if (arch->type != DPKG_ARCH_FOREIGN)
  507. continue;
  508. printf("%s\n", arch->name);
  509. }
  510. m_output(stdout, _("<standard output>"));
  511. return 0;
  512. }
  513. int
  514. cmpversions(const char *const *argv)
  515. {
  516. struct relationinfo {
  517. const char *string;
  518. /* These values are exit status codes, so 0 = true, 1 = false. */
  519. int if_lesser, if_equal, if_greater;
  520. int if_none_a, if_none_both, if_none_b;
  521. };
  522. static const struct relationinfo relationinfos[]= {
  523. /* < = > !a!2!b */
  524. { "le", 0,0,1, 0,0,1 },
  525. { "lt", 0,1,1, 0,1,1 },
  526. { "eq", 1,0,1, 1,0,1 },
  527. { "ne", 0,1,0, 0,1,0 },
  528. { "ge", 1,0,0, 1,0,0 },
  529. { "gt", 1,1,0, 1,1,0 },
  530. /* These treat an empty version as later than any version. */
  531. { "le-nl", 0,0,1, 1,0,0 },
  532. { "lt-nl", 0,1,1, 1,1,0 },
  533. { "ge-nl", 1,0,0, 0,0,1 },
  534. { "gt-nl", 1,1,0, 0,1,1 },
  535. /* For compatibility with dpkg control file syntax. */
  536. { "<", 0,0,1, 0,0,1 },
  537. { "<=", 0,0,1, 0,0,1 },
  538. { "<<", 0,1,1, 0,1,1 },
  539. { "=", 1,0,1, 1,0,1 },
  540. { ">", 1,0,0, 1,0,0 },
  541. { ">=", 1,0,0, 1,0,0 },
  542. { ">>", 1,1,0, 1,1,0 },
  543. { NULL }
  544. };
  545. const struct relationinfo *rip;
  546. struct dpkg_version a, b;
  547. struct dpkg_error err;
  548. int rc;
  549. if (!argv[0] || !argv[1] || !argv[2] || argv[3])
  550. badusage(_("--compare-versions takes three arguments:"
  551. " <version> <relation> <version>"));
  552. for (rip=relationinfos; rip->string && strcmp(rip->string,argv[1]); rip++);
  553. if (!rip->string) badusage(_("--compare-versions bad relation"));
  554. if (*argv[0] && strcmp(argv[0],"<unknown>")) {
  555. if (parseversion(&a, argv[0], &err) < 0) {
  556. if (err.type == DPKG_MSG_WARN)
  557. warning(_("version '%s' has bad syntax: %s"), argv[0], err.str);
  558. else
  559. ohshit(_("version '%s' has bad syntax: %s"), argv[0], err.str);
  560. dpkg_error_destroy(&err);
  561. }
  562. } else {
  563. dpkg_version_blank(&a);
  564. }
  565. if (*argv[2] && strcmp(argv[2],"<unknown>")) {
  566. if (parseversion(&b, argv[2], &err) < 0) {
  567. if (err.type == DPKG_MSG_WARN)
  568. warning(_("version '%s' has bad syntax: %s"), argv[2], err.str);
  569. else
  570. ohshit(_("version '%s' has bad syntax: %s"), argv[2], err.str);
  571. dpkg_error_destroy(&err);
  572. }
  573. } else {
  574. dpkg_version_blank(&b);
  575. }
  576. if (!dpkg_version_is_informative(&a)) {
  577. if (dpkg_version_is_informative(&b))
  578. return rip->if_none_a;
  579. else
  580. return rip->if_none_both;
  581. } else if (!dpkg_version_is_informative(&b)) {
  582. return rip->if_none_b;
  583. }
  584. rc = dpkg_version_compare(&a, &b);
  585. debug(dbg_general, "cmpversions a='%s' b='%s' r=%d",
  586. versiondescribe(&a,vdew_always),
  587. versiondescribe(&b,vdew_always),
  588. rc);
  589. if (rc > 0)
  590. return rip->if_greater;
  591. else if (rc < 0)
  592. return rip->if_lesser;
  593. else
  594. return rip->if_equal;
  595. }