rpm  5.2.1
query.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #ifndef PATH_MAX
9 /*@-incondefs@*/ /* FIX: long int? */
10 # define PATH_MAX 255
11 /*@=incondefs@*/
12 #endif
13 
14 #include <rpmio.h>
15 #include <rpmiotypes.h>
16 #include <poptIO.h>
17 
18 #include <rpmtag.h>
19 #include "rpmdb.h"
20 
21 #include "rpmfi.h"
22 #define _RPMTS_INTERNAL /* XXX for ts->rdb */
23 #include "rpmts.h"
24 #include "rpmgi.h"
25 
26 #include "manifest.h"
27 #include "misc.h" /* XXX for currentDirectory() */
28 
29 #include <rpmcli.h>
30 
31 #include "debug.h"
32 
33 /*@access rpmts @*/ /* XXX cast */
34 
37 static void printFileInfo(char * te, const char * name,
38  size_t size, unsigned short mode,
39  unsigned int mtime,
40  unsigned short rdev, unsigned int nlink,
41  const char * owner, const char * group,
42  const char * linkto)
43  /*@modifies *te @*/
44 {
45  char sizefield[15];
46 #if defined(RPM_VENDOR_OPENPKG) /* adjust-verbose-listing */
47  /* In verbose file listing output, give the owner and group fields
48  more width and at the same time reduce the nlink and size fields
49  more to typical sizes within OpenPKG. */
50  char ownerfield[13+1], groupfield[13+1];
51 #else
52  char ownerfield[8+1], groupfield[8+1];
53 #endif
54  char timefield[100];
55  time_t when = mtime; /* important if sizeof(rpmuint32_t) ! sizeof(time_t) */
56  struct tm * tm;
57  static time_t now;
58  static struct tm nowtm;
59  const char * namefield = name;
60  char * perms = rpmPermsString(mode);
61 
62  /* On first call, grab snapshot of now */
63  if (now == 0) {
64  now = time(NULL);
65  tm = localtime(&now);
66  if (tm) nowtm = *tm; /* structure assignment */
67  }
68 
69  strncpy(ownerfield, owner, sizeof(ownerfield));
70  ownerfield[sizeof(ownerfield)-1] = '\0';
71 
72  strncpy(groupfield, group, sizeof(groupfield));
73  groupfield[sizeof(groupfield)-1] = '\0';
74 
75  /* this is normally right */
76 #if defined(RPM_VENDOR_OPENPKG) /* adjust-verbose-listing */
77  /* In verbose file listing output, give the owner and group fields
78  more width and at the same time reduce the nlink and size fields
79  more to typical sizes within OpenPKG. */
80  sprintf(sizefield, "%8u", (unsigned)size);
81 #else
82  sprintf(sizefield, "%12u", (unsigned)size);
83 #endif
84 
85  /* this knows too much about dev_t */
86 
87  if (S_ISLNK(mode)) {
88  char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto));
89  sprintf(nf, "%s -> %s", name, linkto);
90  namefield = nf;
91  } else if (S_ISCHR(mode)) {
92  perms[0] = 'c';
93  sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
94  ((unsigned)rdev & 0xff));
95  } else if (S_ISBLK(mode)) {
96  perms[0] = 'b';
97  sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
98  ((unsigned)rdev & 0xff));
99  }
100 
101  /* Convert file mtime to display format */
102  tm = localtime(&when);
103  timefield[0] = '\0';
104  if (tm != NULL)
105  { const char *fmt;
106  if (now > when + 6L * 30L * 24L * 60L * 60L || /* Old. */
107  now < when - 60L * 60L) /* In the future. */
108  {
109  /* The file is fairly old or in the future.
110  * POSIX says the cutoff is 6 months old;
111  * approximate this by 6*30 days.
112  * Allow a 1 hour slop factor for what is considered "the future",
113  * to allow for NFS server/client clock disagreement.
114  * Show the year instead of the time of day.
115  */
116  fmt = "%b %e %Y";
117  } else {
118  fmt = "%b %e %H:%M";
119  }
120  (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm);
121  }
122 
123 #if defined(RPM_VENDOR_OPENPKG) /* adjust-verbose-listing */
124  /* In verbose file listing output, give the owner and group fields
125  more width and at the same time reduce the nlink and size fields
126  more to typical sizes within OpenPKG. */
127  sprintf(te, "%s %d %-13s %-13s %8s %s %s", perms,
128  (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield);
129 #else
130  sprintf(te, "%s %4d %-7s %-8s %10s %s %s", perms,
131  (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield);
132 #endif
133  perms = _free(perms);
134 }
135 
138 static inline /*@null@*/ const char * queryHeader(Header h, const char * qfmt)
139  /*@globals internalState @*/
140  /*@modifies h, internalState @*/
141 {
142  const char * errstr = "(unkown error)";
143  const char * str;
144 
145 /*@-modobserver@*/
146  str = headerSprintf(h, qfmt, NULL, rpmHeaderFormats, &errstr);
147 /*@=modobserver@*/
148  if (str == NULL)
149  rpmlog(RPMLOG_ERR, _("incorrect format: %s\n"), errstr);
150  return str;
151 }
152 
155 static void flushBuffer(char ** tp, char ** tep, int nonewline)
156  /*@modifies *tp, **tp, *tep, **tep @*/
157 {
158  char *t, *te;
159 
160  t = *tp;
161  te = *tep;
162  if (te > t) {
163  if (!nonewline) {
164  *te++ = '\n';
165  *te = '\0';
166  }
167  rpmlog(RPMLOG_NOTICE, "%s", t);
168  te = t;
169  *t = '\0';
170  }
171  *tp = t;
172  *tep = te;
173 }
174 
176 {
177  int scareMem = 0;
178  rpmfi fi = NULL;
179  size_t tb = 2 * BUFSIZ;
180  size_t sb;
181  char * t, * te;
182  char * prefix = NULL;
183  int rc = 0; /* XXX FIXME: need real return code */
184  int i;
185 
186  te = t = xmalloc(tb);
187  *te = '\0';
188 
189  if (qva->qva_queryFormat != NULL) {
190  const char * str;
191 /*@-type@*/ /* FIX rpmtsGetRDB()? */
192  (void) headerSetRpmdb(h, ts->rdb);
193 /*@=type@*/
194  str = queryHeader(h, qva->qva_queryFormat);
195  (void) headerSetRpmdb(h, NULL);
196  if (str) {
197  size_t tx = (te - t);
198 
199  sb = strlen(str);
200  if (sb) {
201  tb += sb;
202  t = xrealloc(t, tb);
203  te = t + tx;
204  }
205  /*@-usereleased@*/
206  te = stpcpy(te, str);
207  /*@=usereleased@*/
208  str = _free(str);
209  flushBuffer(&t, &te, 1);
210  }
211  }
212 
213  if (!(qva->qva_flags & QUERY_FOR_LIST))
214  goto exit;
215 
216  fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
217  if (rpmfiFC(fi) <= 0) {
218  te = stpcpy(te, _("(contains no files)"));
219  goto exit;
220  }
221 
222  fi = rpmfiInit(fi, 0);
223  if (fi != NULL)
224  while ((i = rpmfiNext(fi)) >= 0) {
225  rpmfileAttrs fflags;
226  unsigned short fmode;
227  unsigned short frdev;
228  unsigned int fmtime;
229  rpmfileState fstate;
230  size_t fsize;
231  const char * fn;
232  const char * fdigest;
233  const char * fuser;
234  const char * fgroup;
235  const char * flink;
236  rpmuint32_t fnlink;
237 
238  fflags = rpmfiFFlags(fi);
239  fmode = rpmfiFMode(fi);
240  frdev = rpmfiFRdev(fi);
241  fmtime = rpmfiFMtime(fi);
242  fstate = rpmfiFState(fi);
243  fsize = rpmfiFSize(fi);
244  fn = rpmfiFN(fi);
245  { static char hex[] = "0123456789abcdef";
246  int dalgo = 0;
247  size_t dlen = 0;
248  const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
249  char * p;
250  size_t j;
251  fdigest = p = xcalloc(1, ((2 * dlen) + 1));
252  for (j = 0; j < dlen; j++) {
253  unsigned k = *digest++;
254  *p++ = hex[ (k >> 4) & 0xf ];
255  *p++ = hex[ (k ) & 0xf ];
256  }
257  *p = '\0';
258  }
259  fuser = rpmfiFUser(fi);
260  fgroup = rpmfiFGroup(fi);
261  flink = rpmfiFLink(fi);
262  fnlink = rpmfiFNlink(fi);
263 assert(fn != NULL);
264 assert(fdigest != NULL);
265 
266  /* If querying only docs, skip non-doc files. */
267  if ((qva->qva_flags & QUERY_FOR_DOCS) && !(fflags & RPMFILE_DOC))
268  continue;
269 
270  /* If querying only configs, skip non-config files. */
271  if ((qva->qva_flags & QUERY_FOR_CONFIG) && !(fflags & RPMFILE_CONFIG))
272  continue;
273 
274  /* If not querying %config, skip config files. */
275  if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG))
276  continue;
277 
278  /* If not querying %doc, skip doc files. */
279  if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC))
280  continue;
281 
282  /* If not querying %ghost, skip ghost files. */
283  if ((qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
284  continue;
285 
286  /* Insure space for header derived data */
287  sb = 0;
288  if (fn) sb += strlen(fn);
289  if (fdigest) sb += strlen(fdigest);
290  if (fuser) sb += strlen(fuser);
291  if (fgroup) sb += strlen(fgroup);
292  if (flink) sb += strlen(flink);
293  if ((sb + BUFSIZ) > tb) {
294  size_t tx = (te - t);
295  tb += sb + BUFSIZ;
296  t = xrealloc(t, tb);
297  te = t + tx;
298  }
299 
300  if (!rpmIsVerbose() && prefix)
301  te = stpcpy(te, prefix);
302 
303  if (qva->qva_flags & QUERY_FOR_STATE) {
304  switch (fstate) {
306  te = stpcpy(te, _("normal "));
307  /*@switchbreak@*/ break;
309  te = stpcpy(te, _("replaced "));
310  /*@switchbreak@*/ break;
312  te = stpcpy(te, _("not installed "));
313  /*@switchbreak@*/ break;
315  te = stpcpy(te, _("net shared "));
316  /*@switchbreak@*/ break;
318  te = stpcpy(te, _("wrong color "));
319  /*@switchbreak@*/ break;
321  te = stpcpy(te, _("(no state) "));
322  /*@switchbreak@*/ break;
323  default:
324  sprintf(te, _("(unknown %3d) "), fstate);
325  te += strlen(te);
326  /*@switchbreak@*/ break;
327  }
328  }
329 
330  if (qva->qva_flags & QUERY_FOR_DUMPFILES) {
331  sprintf(te, "%s %d %d %s 0%o ",
332  fn, (int)fsize, fmtime, fdigest, fmode);
333  te += strlen(te);
334 
335  if (fuser && fgroup) {
336 /*@-nullpass@*/
337  sprintf(te, "%s %s", fuser, fgroup);
338 /*@=nullpass@*/
339  te += strlen(te);
340  } else {
341  rpmlog(RPMLOG_CRIT, _("package without owner/group tags\n"));
342  }
343 
344  sprintf(te, " %s %s %u ",
345  fflags & RPMFILE_CONFIG ? "1" : "0",
346  fflags & RPMFILE_DOC ? "1" : "0",
347  frdev);
348  te += strlen(te);
349 
350  sprintf(te, "%s", (flink && *flink ? flink : "X"));
351  te += strlen(te);
352  } else
353  if (!rpmIsVerbose()) {
354  te = stpcpy(te, fn);
355  }
356  else {
357 
358  /* XXX Adjust directory link count and size for display output. */
359  if (S_ISDIR(fmode)) {
360  fnlink++;
361  fsize = 0;
362  }
363 
364  if (fuser && fgroup) {
365 /*@-nullpass@*/
366  printFileInfo(te, fn, fsize, fmode, fmtime, frdev, fnlink,
367  fuser, fgroup, flink);
368 /*@=nullpass@*/
369  te += strlen(te);
370  } else {
371  rpmlog(RPMLOG_CRIT, _("package without owner/group tags\n"));
372  }
373  }
374  flushBuffer(&t, &te, 0);
375  fdigest = _free(fdigest);
376  }
377 
378  rc = 0;
379 
380 exit:
381  flushBuffer(&t, &te, 0);
382  t = _free(t);
383 
384  fi = rpmfiFree(fi);
385  return rc;
386 }
387 
388 static int rpmgiShowMatches(QVA_t qva, rpmts ts)
389  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
390  /*@modifies qva, rpmGlobalMacroContext, h_errno, internalState @*/
391 {
392  rpmgi gi = qva->qva_gi;
393  rpmRC rpmrc = RPMRC_NOTFOUND;
394  int ec = 0;
395 
396  while ((rpmrc = rpmgiNext(gi)) == RPMRC_OK) {
397  Header h;
398  int rc;
399 
400 #ifdef NOTYET /* XXX exiting here will leave stale locks. */
401  (void) rpmdbCheckSignals();
402 #endif
403 
404  h = rpmgiHeader(gi);
405  if (h == NULL) /* XXX perhaps stricter break instead? */
406  continue;
407  if ((rc = qva->qva_showPackage(qva, ts, h)) != 0)
408  ec = rc;
409  if (qva->qva_source == RPMQV_DBOFFSET)
410  break;
411  }
412  if (ec == 0 && rpmrc == RPMRC_FAIL)
413  ec++;
414  return ec;
415 }
416 
418 {
419  Header h;
420  int ec = 1;
421 
422  qva->qva_showFAIL = qva->qva_showOK = 0;
423  while ((h = rpmmiNext(qva->qva_mi)) != NULL) {
424  ec = qva->qva_showPackage(qva, ts, h);
425  if (ec)
426  qva->qva_showFAIL++;
427  else
428  qva->qva_showOK++;
429  if (qva->qva_source == RPMQV_DBOFFSET)
430  break;
431  }
432  qva->qva_mi = rpmmiFree(qva->qva_mi);
433  return ec;
434 }
435 
441 static inline unsigned char nibble(char c)
442  /*@*/
443 {
444  if (c >= '0' && c <= '9')
445  return (c - '0');
446  if (c >= 'A' && c <= 'F')
447  return (c - 'A') + 10;
448  if (c >= 'a' && c <= 'f')
449  return (c - 'a') + 10;
450  return 0;
451 }
452 
453 int rpmQueryVerify(QVA_t qva, rpmts ts, const char * arg)
454 {
455  int res = 0;
456  const char * s;
457  int i;
458  int provides_checked = 0;
459 
460  (void) rpmdbCheckSignals();
461 
462  if (qva->qva_showPackage == NULL)
463  return 1;
464 
465  switch (qva->qva_source) {
466 #ifdef NOTYET
467  default:
468 #endif
469  case RPMQV_GROUP:
470  case RPMQV_TRIGGEREDBY:
471  case RPMQV_WHATCONFLICTS:
472  case RPMQV_WHATOBSOLETES:
473  qva->qva_mi = rpmtsInitIterator(ts, qva->qva_source, arg, 0);
474  if (qva->qva_mi == NULL) {
475  rpmlog(RPMLOG_NOTICE, _("key \"%s\" not found in %s table\n"),
476  arg, tagName((rpmTag)qva->qva_source));
477  res = 1;
478  } else
479  res = rpmcliShowMatches(qva, ts);
480  break;
481 
482  case RPMQV_RPM:
483  res = rpmgiShowMatches(qva, ts);
484  break;
485 
486  case RPMQV_ALL:
487  res = rpmgiShowMatches(qva, ts);
488  break;
489 
490  case RPMQV_HDLIST:
491  res = rpmgiShowMatches(qva, ts);
492  break;
493 
494  case RPMQV_FTSWALK:
495  res = rpmgiShowMatches(qva, ts);
496  break;
497 
498  case RPMQV_SPECSRPM:
499  case RPMQV_SPECFILE:
500  res = ((qva->qva_specQuery != NULL)
501  ? qva->qva_specQuery(ts, qva, arg) : 1);
502  break;
503 
504 #ifdef DYING
505  case RPMQV_GROUP:
506  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_GROUP, arg, 0);
507  if (qva->qva_mi == NULL) {
509  _("group %s does not contain any packages\n"), arg);
510  res = 1;
511  } else
512  res = rpmcliShowMatches(qva, ts);
513  break;
514 
515  case RPMQV_TRIGGEREDBY:
516  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, arg, 0);
517  if (qva->qva_mi == NULL) {
518  rpmlog(RPMLOG_NOTICE, _("no package triggers %s\n"), arg);
519  res = 1;
520  } else
521  res = rpmcliShowMatches(qva, ts);
522  break;
523 #endif
524 
525  case RPMQV_SOURCEPKGID:
526  case RPMQV_PKGID:
527  { unsigned char MD5[16];
528  unsigned char * t;
529  rpmuint32_t tag;
530 
531  for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
532  {};
533  if (i != 32) {
534  rpmlog(RPMLOG_NOTICE, _("malformed %s: %s\n"), "pkgid", arg);
535  return 1;
536  }
537 
538  MD5[0] = '\0';
539  for (i = 0, t = MD5, s = arg; i < 16; i++, t++, s += 2)
540  *t = (nibble(s[0]) << 4) | nibble(s[1]);
541 
542  tag = (qva->qva_source == RPMQV_PKGID
544  qva->qva_mi = rpmtsInitIterator(ts, tag, MD5, sizeof(MD5));
545  if (qva->qva_mi == NULL) {
546  rpmlog(RPMLOG_NOTICE, _("no package matches %s: %s\n"),
547  "pkgid", arg);
548  res = 1;
549  } else
550  res = rpmcliShowMatches(qva, ts);
551  } break;
552 
553  case RPMQV_HDRID:
554  for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
555  {};
556  if (i != 40) {
557  rpmlog(RPMLOG_NOTICE, _("malformed %s: %s\n"), "hdrid", arg);
558  return 1;
559  }
560 
561  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, arg, 0);
562  if (qva->qva_mi == NULL) {
563  rpmlog(RPMLOG_NOTICE, _("no package matches %s: %s\n"),
564  "hdrid", arg);
565  res = 1;
566  } else
567  res = rpmcliShowMatches(qva, ts);
568  break;
569 
570  case RPMQV_FILEID:
571  { unsigned char * t;
572  unsigned char * digest;
573  size_t dlen;
574 
575  /* Insure even no. of digits and at least 8 digits. */
576  for (dlen = 0, s = arg; *s && isxdigit(*s); s++, dlen++)
577  {};
578  if ((dlen & 1) || dlen < 8) {
579  rpmlog(RPMLOG_ERR, _("malformed %s: %s\n"), "fileid", arg);
580  return 1;
581  }
582 
583  dlen /= 2;
584  digest = memset(alloca(dlen), 0, dlen);
585  for (t = digest, s = arg; *s; t++, s += 2)
586  *t = (nibble(s[0]) << 4) | nibble(s[1]);
587 
588  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_FILEDIGESTS, digest, dlen);
589  if (qva->qva_mi == NULL) {
590  rpmlog(RPMLOG_NOTICE, _("no package matches %s: %s\n"),
591  "fileid", arg);
592  res = 1;
593  } else
594  res = rpmcliShowMatches(qva, ts);
595  } break;
596 
597  case RPMQV_TID:
598  { int mybase = 10;
599  const char * myarg = arg;
600  char * end = NULL;
601  unsigned iid;
602 
603  /* XXX should be in strtoul */
604  if (*myarg == '0') {
605  myarg++;
606  mybase = 8;
607  if (*myarg == 'x') {
608  myarg++;
609  mybase = 16;
610  }
611  }
612  iid = (unsigned) strtoul(myarg, &end, mybase);
613  if ((*end) || (end == arg) || (iid == UINT_MAX)) {
614  rpmlog(RPMLOG_ERR, _("malformed %s: %s\n"), "tid", arg);
615  return 1;
616  }
617  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_INSTALLTID, &iid, sizeof(iid));
618  if (qva->qva_mi == NULL) {
619  rpmlog(RPMLOG_NOTICE, _("no package matches %s: %s\n"),
620  "tid", arg);
621  res = 1;
622  } else
623  res = rpmcliShowMatches(qva, ts);
624  } break;
625 
626  case RPMQV_WHATNEEDS:
627  case RPMQV_WHATREQUIRES:
628  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, arg, 0);
629  if (qva->qva_mi == NULL) {
630  rpmlog(RPMLOG_NOTICE, _("no package requires %s\n"), arg);
631  res = 1;
632  } else
633  res = rpmcliShowMatches(qva, ts);
634  break;
635 
636  case RPMQV_WHATPROVIDES:
637  if (arg[0] != '/') {
638  provides_checked = 1;
639  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, arg, 0);
640  if (qva->qva_mi == NULL) {
641  rpmlog(RPMLOG_NOTICE, _("no package provides %s\n"), arg);
642  res = 1;
643  } else
644  res = rpmcliShowMatches(qva, ts);
645  break;
646  }
647  /*@fallthrough@*/
648  case RPMQV_PATH:
649  { char * fn;
650 
651  for (s = arg; *s != '\0'; s++)
652  if (!(*s == '.' || *s == '/'))
653  /*@loopbreak@*/ break;
654 
655  if (*s == '\0') {
656  char fnbuf[PATH_MAX];
657  fn = Realpath(arg, fnbuf);
658  fn = xstrdup( (fn != NULL ? fn : arg) );
659  } else if (*arg != '/') {
660  const char *curDir = currentDirectory();
661  fn = (char *) rpmGetPath(curDir, "/", arg, NULL);
662  curDir = _free(curDir);
663  } else
664  fn = xstrdup(arg);
665 assert(fn != NULL);
666  (void) rpmCleanPath(fn);
667 
668  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, fn, 0);
669  if (qva->qva_mi == NULL && !provides_checked)
670  qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, fn, 0);
671 
672  if (qva->qva_mi == NULL) {
673  struct stat sb;
674  if (Lstat(fn, &sb) != 0)
675  rpmlog(RPMLOG_NOTICE, _("file %s: %s\n"), fn, strerror(errno));
676  else
678  _("file %s is not owned by any package\n"), fn);
679  res = 1;
680  } else
681  res = rpmcliShowMatches(qva, ts);
682 
683  fn = _free(fn);
684  } break;
685 
686  case RPMQV_DBOFFSET:
687  { int mybase = 10;
688  const char * myarg = arg;
689  char * end = NULL;
690  unsigned recOffset;
691 
692  /* XXX should be in strtoul */
693  if (*myarg == '0') {
694  myarg++;
695  mybase = 8;
696  if (*myarg == 'x') {
697  myarg++;
698  mybase = 16;
699  }
700  }
701  recOffset = (unsigned) strtoul(myarg, &end, mybase);
702  if ((*end) || (end == arg) || (recOffset == UINT_MAX)) {
703  rpmlog(RPMLOG_NOTICE, _("invalid package number: %s\n"), arg);
704  return 1;
705  }
706  rpmlog(RPMLOG_DEBUG, D_("package record number: %u\n"), recOffset);
707  qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
708  if (qva->qva_mi == NULL) {
710  _("record %u could not be read\n"), recOffset);
711  res = 1;
712  } else
713  res = rpmcliShowMatches(qva, ts);
714  } break;
715 
716  case RPMQV_PACKAGE:
717  /* XXX HACK to get rpmdbFindByLabel out of the API */
718  qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0);
719  if (qva->qva_mi == NULL) {
720  rpmlog(RPMLOG_NOTICE, _("package %s is not installed\n"), arg);
721  res = 1;
722  } else {
723  res = rpmcliShowMatches(qva, ts);
724  /* detect foo.bogusarch empty iterations. */
725  if (qva->qva_showOK == 0 && qva->qva_showFAIL == 0) {
726  rpmlog(RPMLOG_NOTICE, _("package %s is not installed\n"), arg);
727  res = 1;
728  }
729  }
730  break;
731  }
732 
733  return res;
734 }
735 
736 int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_t argv)
737  /*@globals rpmioFtsOpts @*/
738  /*@modifies rpmioFtsOpts @*/
739 {
740  rpmRC rpmrc = RPMRC_NOTFOUND;
741  int ec = 0;
742 
743  switch (qva->qva_source) {
744  case RPMQV_ALL:
745  qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0);
746  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, RPMGI_NONE);
747 
748  if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */
749  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
750  {};
751  if (rpmrc != RPMRC_NOTFOUND)
752  return 1; /* XXX should be no. of failures. */
753 
754  /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
755  ec = rpmQueryVerify(qva, ts, (const char *) argv);
756  /*@=nullpass@*/
757  rpmtsEmpty(ts);
758  break;
759  case RPMQV_RPM:
760  qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0);
761  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags);
762 
763  if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */
764  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
765  {};
766  if (rpmrc != RPMRC_NOTFOUND)
767  return 1; /* XXX should be no. of failures. */
768 
769  /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
770  ec = rpmQueryVerify(qva, ts, NULL);
771  /*@=nullpass@*/
772  rpmtsEmpty(ts);
773  break;
774  case RPMQV_HDLIST:
775  qva->qva_gi = rpmgiNew(ts, RPMDBI_HDLIST, NULL, 0);
776  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags);
777 
778  if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */
779  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
780  {};
781  if (rpmrc != RPMRC_NOTFOUND)
782  return 1; /* XXX should be no. of failures. */
783 
784  /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
785  ec = rpmQueryVerify(qva, ts, NULL);
786  /*@=nullpass@*/
787  rpmtsEmpty(ts);
788  break;
789  case RPMQV_FTSWALK:
790  if (rpmioFtsOpts == 0)
792  qva->qva_gi = rpmgiNew(ts, RPMDBI_FTSWALK, NULL, 0);
793  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts, giFlags);
794 
795  if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */
796  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
797  {};
798  if (rpmrc != RPMRC_NOTFOUND)
799  return 1; /* XXX should be no. of failures. */
800 
801  /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
802  ec = rpmQueryVerify(qva, ts, NULL);
803  /*@=nullpass@*/
804  rpmtsEmpty(ts);
805  break;
806  default:
807  if (giFlags & RPMGI_TSADD) {
808  qva->qva_gi = rpmgiNew(ts, RPMDBI_LABEL, NULL, 0);
809  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts,
810  (giFlags | (RPMGI_NOGLOB )));
811  if (rpmgiGetFlags(qva->qva_gi) & RPMGI_TSADD) /* Load the ts with headers. */
812  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
813  {};
814  if (rpmrc != RPMRC_NOTFOUND)
815  return 1; /* XXX should be no. of failures. */
816  qva->qva_source = RPMQV_ALL;
817  /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
818  ec = rpmQueryVerify(qva, ts, NULL);
819  /*@=nullpass@*/
820  rpmtsEmpty(ts);
821  } else {
822  qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0);
823  qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, rpmioFtsOpts,
825  while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK) {
826  const char * path;
827  path = rpmgiHdrPath(qva->qva_gi);
828 assert(path != NULL);
829  ec += rpmQueryVerify(qva, ts, path);
830  rpmtsEmpty(ts);
831  }
832  }
833  break;
834  }
835 
836  qva->qva_gi = rpmgiFree(qva->qva_gi);
837 
838  return ec;
839 }
840 
841 int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv)
842 {
843  rpmdepFlags depFlags = qva->depFlags, odepFlags;
844  rpmtransFlags transFlags = qva->transFlags, otransFlags;
845  rpmVSFlags vsflags, ovsflags;
846  int ec = 0;
847 
848  if (qva->qva_showPackage == NULL)
850 
851  /* If --queryformat unspecified, then set default now. */
852  if (!(qva->qva_flags & _QUERY_FOR_BITS) && qva->qva_queryFormat == NULL) {
853  qva->qva_queryFormat = rpmExpand("%{?_query_all_fmt}\n", NULL);
854  if (!(qva->qva_queryFormat != NULL && *qva->qva_queryFormat != '\0')) {
856  qva->qva_queryFormat = xstrdup("%{name}-%{version}-%{release}.%{arch}\n");
857  }
858  }
859 
860  vsflags = rpmExpandNumeric("%{?_vsflags_query}");
861  if (qva->qva_flags & VERIFY_DIGEST)
862  vsflags |= _RPMVSF_NODIGESTS;
863  if (qva->qva_flags & VERIFY_SIGNATURE)
864  vsflags |= _RPMVSF_NOSIGNATURES;
865  if (qva->qva_flags & VERIFY_HDRCHK)
866  vsflags |= RPMVSF_NOHDRCHK;
867 
868  odepFlags = rpmtsSetDFlags(ts, depFlags);
869  otransFlags = rpmtsSetFlags(ts, transFlags);
870  ovsflags = rpmtsSetVSFlags(ts, vsflags);
871  ec = rpmcliArgIter(ts, qva, argv);
872  vsflags = rpmtsSetVSFlags(ts, ovsflags);
873  transFlags = rpmtsSetFlags(ts, otransFlags);
874  depFlags = rpmtsSetDFlags(ts, odepFlags);
875 
876  if (qva->qva_showPackage == showQueryPackage)
877  qva->qva_showPackage = NULL;
878 
879  return ec;
880 }