rpm  4.5
rpmgi.c
Go to the documentation of this file.
1 /*@-modfilesys@*/
5 #include "system.h"
6 
7 #include <rpmlib.h>
8 #include <rpmte.h> /* XXX rpmElementType */
9 
10 #define _RPMGI_INTERNAL
11 #define _RPMTS_INTERNAL /* XXX ts->probs et al */
12 #include <rpmgi.h>
13 
14 #include <rpmdb.h>
15 #include <rpmmacro.h> /* XXX rpmExpand */
16 #include "manifest.h"
17 
18 #include "debug.h"
19 
20 /*@access fnpyKey @*/
21 /*@access rpmdbMatchIterator @*/
22 /*@access rpmts @*/
23 /*@access rpmps @*/
24 
27 /*@unchecked@*/
28 int _rpmgi_debug = 0;
29 
32 /*@unchecked@*/
34 
37 /*@unchecked@*/
38 static int indent = 2;
39 
42 /*@unchecked@*/ /*@observer@*/
43 static const char * ftsInfoStrings[] = {
44  "UNKNOWN",
45  "D",
46  "DC",
47  "DEFAULT",
48  "DNR",
49  "DOT",
50  "DP",
51  "ERR",
52  "F",
53  "INIT",
54  "NS",
55  "NSOK",
56  "SL",
57  "SLNONE",
58  "W",
59 };
60 
63 /*@observer@*/
64 static const char * ftsInfoStr(int fts_info)
65  /*@*/
66 {
67 
68  if (!(fts_info >= 1 && fts_info <= 14))
69  fts_info = 0;
70 /*@-compmempass@*/
71  return ftsInfoStrings[ fts_info ];
72 /*@=compmempass@*/
73 }
74 
82 /*@null@*/
83 static FD_t rpmgiOpen(const char * path, const char * fmode)
84  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
85  /*@modifies rpmGlobalMacroContext, h_errno, internalState @*/
86 {
87  const char * fn = rpmExpand(path, NULL);
88  FD_t fd;
89 
90  /* FIXME (see http://rpm5.org/community/rpm-devel/0523.html) */
91  errno = 0;
92  fd = Fopen(fn, fmode);
93 
94  if (fd == NULL || Ferror(fd)) {
95  rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fn, Fstrerror(fd));
96  if (fd != NULL) (void) Fclose(fd);
97  fd = NULL;
98  }
99  fn = _free(fn);
100 
101  return fd;
102 }
103 
110 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path)
111  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
112  /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
113 {
114  FD_t fd = rpmgiOpen(path, "r");
115  rpmRC rpmrc = RPMRC_FAIL;
116 
117  if (fd != NULL) {
118  rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv);
119  (void) Fclose(fd);
120  }
121  return rpmrc;
122 }
123 
130 /*@null@*/
131 static Header rpmgiReadHeader(rpmgi gi, const char * path)
132  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
133  /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
134 {
135  FD_t fd = rpmgiOpen(path, "r");
136  Header h = NULL;
137 
138  if (fd != NULL) {
139  /* XXX what if path needs expansion? */
140  rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h);
141 
142  (void) Fclose(fd);
143 
144  switch (rpmrc) {
145  case RPMRC_NOTFOUND:
146  /* XXX Read a package manifest. Restart ftswalk on success. */
147  case RPMRC_FAIL:
148  default:
149  h = headerFree(h);
150  break;
151  case RPMRC_NOTTRUSTED:
152  case RPMRC_NOKEY:
153  case RPMRC_OK:
154  break;
155  }
156  }
157 
158  return h;
159 }
160 
167  /*@modifies gi @*/
168 {
169  rpmRC rpmrc = RPMRC_NOTFOUND;
170  if (gi->argv != NULL && gi->argv[gi->i] != NULL) {
171  gi->keyp = gi->argv[gi->i];
172  gi->keylen = 0;
173  rpmrc = RPMRC_OK;
174  } else {
175  gi->i = -1;
176  gi->keyp = NULL;
177  gi->keylen = 0;
178  }
179  return rpmrc;
180 }
181 
191  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
192  /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
193 {
194  rpmRC rpmrc = RPMRC_NOTFOUND;
195  Header h = NULL;
196 
197  if (gi->argv != NULL && gi->argv[gi->i] != NULL)
198  do {
199  const char * fn; /* XXX gi->hdrPath? */
200 
201  fn = gi->argv[gi->i];
202  if (!(gi->flags & RPMGI_NOHEADER)) {
203  h = rpmgiReadHeader(gi, fn);
204  if (h != NULL)
205  rpmrc = RPMRC_OK;
206  } else
207  rpmrc = RPMRC_OK;
208 
209  if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST)
210  break;
211  if (errno == ENOENT)
212  break;
213 
214  /* Not a header, so try for a manifest. */
215  gi->argv[gi->i] = NULL; /* Mark the insertion point */
216  rpmrc = rpmgiLoadManifest(gi, fn);
217  if (rpmrc != RPMRC_OK) {
218  gi->argv[gi->i] = fn; /* Manifest failed, restore fn */
219  break;
220  }
221  fn = _free(fn);
222  rpmrc = RPMRC_NOTFOUND;
223  } while (1);
224 
225  if (rpmrc == RPMRC_OK && h != NULL)
226  gi->h = headerLink(h);
227  h = headerFree(h);
228 
229  return rpmrc;
230 }
231 
237 /*@null@*/
239  /*@*/
240 {
241  FTSENT * fts = gi->fts;
242  rpmRC rpmrc = RPMRC_NOTFOUND;
243  const char * s;
244 
245 if (_rpmgi_debug < 0)
246 rpmMessage(RPMMESS_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info),
247  indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
248  fts->fts_name,
249  ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : ""));
250 
251  switch (fts->fts_info) {
252  case FTS_D: /* preorder directory */
253  break;
254  case FTS_DP: /* postorder directory */
255  break;
256  case FTS_F: /* regular file */
257  /* Ignore all but *.rpm files. */
258  s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm");
259  if (strcmp(s, ".rpm"))
260  break;
261  rpmrc = RPMRC_OK;
262  break;
263  case FTS_NS: /* stat(2) failed */
264  case FTS_DNR: /* unreadable directory */
265  case FTS_ERR: /* error; errno is set */
266  break;
267  case FTS_DC: /* directory that causes cycles */
268  case FTS_DEFAULT: /* none of the above */
269  case FTS_DOT: /* dot or dot-dot */
270  case FTS_INIT: /* initialized only */
271  case FTS_NSOK: /* no stat(2) requested */
272  case FTS_SL: /* symbolic link */
273  case FTS_SLNONE: /* symbolic link without target */
274  case FTS_W: /* whiteout object */
275  default:
276  break;
277  }
278  return rpmrc;
279 }
280 
286 /*@null@*/
288  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
289  /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
290 {
291  rpmRC rpmrc = RPMRC_NOTFOUND;
292 
293  if (gi->ftsp != NULL)
294  while ((gi->fts = Fts_read(gi->ftsp)) != NULL) {
295  if (gi->walkPathFilter)
296  rpmrc = (*gi->walkPathFilter) (gi);
297  else
298  rpmrc = rpmgiWalkPathFilter(gi);
299  if (rpmrc == RPMRC_OK)
300  break;
301  }
302 
303  if (rpmrc == RPMRC_OK) {
304  Header h = NULL;
305  if (!(gi->flags & RPMGI_NOHEADER)) {
306  /* XXX rpmrc = rpmgiLoadReadHeader(gi); */
307  if (gi->fts != NULL) /* XXX can't happen */
308  h = rpmgiReadHeader(gi, gi->fts->fts_path);
309  }
310  if (h != NULL) {
311  gi->h = headerLink(h);
312  h = headerFree(h);
313 /*@-noeffectuncon@*/
314  if (gi->stash != NULL)
315  (void) (*gi->stash) (gi, gi->h);
316 /*@=noeffectuncon@*/
317  }
318  }
319 
320  return rpmrc;
321 }
322 
323 const char * rpmgiEscapeSpaces(const char * s)
324 {
325  const char * se;
326  const char * t;
327  char * te;
328  size_t nb = 0;
329 
330  for (se = s; *se; se++) {
331  if (isspace(*se))
332  nb++;
333  nb++;
334  }
335  nb++;
336 
337  t = te = xmalloc(nb);
338  for (se = s; *se; se++) {
339  if (isspace(*se))
340  *te++ = '\\';
341  *te++ = *se;
342  }
343  *te = '\0';
344  return t;
345 }
346 
353 static rpmRC rpmgiGlobArgv(rpmgi gi, /*@null@*/ ARGV_t argv)
354  /*@globals internalState @*/
355  /*@modifies gi, internalState @*/
356 {
357  const char * arg;
358  rpmRC rpmrc = RPMRC_OK;
359  int ac = 0;
360  int xx;
361 
362  /* XXX Expand globs only if requested or for gi specific tags */
363  if ((gi->flags & RPMGI_NOGLOB)
364  || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK))
365  {
366  if (argv != NULL) {
367  while (argv[ac] != NULL)
368  ac++;
369 /*@-nullstate@*/ /* XXX argv is not NULL */
370  xx = argvAppend(&gi->argv, argv);
371 /*@=nullstate@*/
372  }
373  gi->argc = ac;
374  return rpmrc;
375  }
376 
377  if (argv != NULL)
378  while ((arg = *argv++) != NULL) {
379  const char * t = rpmgiEscapeSpaces(arg);
380  ARGV_t av = NULL;
381 
382  xx = rpmGlob(t, &ac, &av);
383  xx = argvAppend(&gi->argv, av);
384  gi->argc += ac;
385  av = argvFree(av);
386  t = _free(t);
387  ac = 0;
388  }
389  return rpmrc;
390 }
391 
398  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
399  /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
400 {
401  rpmRC rpmrc = RPMRC_OK;
402  ARGV_t av;
403  int res = 0;
404 
405  gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen);
406 
407 if (_rpmgi_debug < 0)
408 fprintf(stderr, "*** gi %p key %p[%d]\tmi %p\n", gi, gi->keyp, (int)gi->keylen, gi->mi);
409 
410  if (gi->argv != NULL)
411  for (av = (const char **) gi->argv; *av != NULL; av++) {
412  if (gi->tag == RPMDBI_PACKAGES) {
413  int tag = RPMTAG_NAME;
414  const char * pat;
415  char * a, * ae;
416 
417  pat = a = xstrdup(*av);
418  tag = RPMTAG_NAME;
419 
420  /* Parse for "tag=pattern" args. */
421 /*@-branchstate@*/
422  if ((ae = strchr(a, '=')) != NULL) {
423  *ae++ = '\0';
424  if (*a != '\0') { /* XXX HACK: permit '=foo' */
425  tag = tagValue(a);
426  if (tag < 0) {
427  rpmError(RPMERR_QUERYINFO, _("unknown tag: \"%s\"\n"), a);
428  res = 1;
429  }
430  }
431  pat = ae;
432  }
433 /*@=branchstate@*/
434  if (!res) {
435 if (_rpmgi_debug < 0)
436 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (int)(av - gi->argv), *av, tagName(tag), pat);
437  res = rpmdbSetIteratorRE(gi->mi, tag, RPMMIRE_DEFAULT, pat);
438  }
439  a = _free(a);
440  }
441 
442  if (res == 0)
443  continue;
444 
445  gi->mi = rpmdbFreeIterator(gi->mi); /* XXX odd side effect? */
446  rpmrc = RPMRC_FAIL;
447  break;
448  }
449 
450  return rpmrc;
451 }
452 
453 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
454 {
455  if (gi == NULL) return NULL;
456 
457 if (_rpmgi_debug && msg != NULL)
458 fprintf(stderr, "--> gi %p -- %d %s(%s) at %s:%u\n", gi, gi->nrefs, msg, tagName(gi->tag), fn, ln);
459 
460  gi->nrefs--;
461  return NULL;
462 }
463 
464 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
465 {
466  if (gi == NULL) return NULL;
467  gi->nrefs++;
468 
469 if (_rpmgi_debug && msg != NULL)
470 fprintf(stderr, "--> gi %p ++ %d %s(%s) at %s:%u\n", gi, gi->nrefs, msg, tagName(gi->tag), fn, ln);
471 
472  /*@-refcounttrans@*/ return gi; /*@=refcounttrans@*/
473 }
474 
476 {
477  if (gi == NULL)
478  return NULL;
479 
480  if (gi->nrefs > 1)
481  return rpmgiUnlink(gi, __FUNCTION__);
482 
483  (void) rpmgiUnlink(gi, __FUNCTION__);
484 
485 /*@-usereleased@*/
486 
487  gi->hdrPath = _free(gi->hdrPath);
488  gi->h = headerFree(gi->h);
489 
490  gi->argv = argvFree(gi->argv);
491 
492  if (gi->ftsp != NULL) {
493  int xx;
494  xx = Fts_close(gi->ftsp);
495  gi->ftsp = NULL;
496  gi->fts = NULL;
497  }
498  if (gi->fd != NULL) {
499  (void) Fclose(gi->fd);
500  gi->fd = NULL;
501  }
502  gi->tsi = rpmtsiFree(gi->tsi);
503  gi->mi = rpmdbFreeIterator(gi->mi);
504  gi->ts = rpmtsFree(gi->ts);
505 
506  memset(gi, 0, sizeof(*gi)); /* XXX trash and burn */
507 /*@-refcounttrans@*/
508  gi = _free(gi);
509 /*@=refcounttrans@*/
510 /*@=usereleased@*/
511  return NULL;
512 }
513 
514 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
515 {
516  rpmgi gi = xcalloc(1, sizeof(*gi));
517 
518  if (gi == NULL)
519  return NULL;
520 
521  gi->ts = rpmtsLink(ts, __FUNCTION__);
522  gi->tsOrder = rpmtsOrder;
523  gi->tag = tag;
524 /*@-assignexpose@*/
525  gi->keyp = keyp;
526 /*@=assignexpose@*/
527  gi->keylen = keylen;
528 
529  gi->flags = 0;
530  gi->active = 0;
531  gi->i = -1;
532  gi->hdrPath = NULL;
533  gi->h = NULL;
534 
535  gi->tsi = NULL;
536  gi->mi = NULL;
537  gi->fd = NULL;
538  gi->argv = xcalloc(1, sizeof(*gi->argv));
539  gi->argc = 0;
540  gi->ftsOpts = 0;
541  gi->ftsp = NULL;
542  gi->fts = NULL;
543  gi->walkPathFilter = NULL;
544 
545  gi = rpmgiLink(gi, __FUNCTION__);
546 
547  return gi;
548 }
549 
550 /*@observer@*/ /*@unchecked@*/
551 static const char * _query_hdlist_path = "/usr/share/comps/%{_arch}/hdlist";
552 
553 rpmRC rpmgiNext(/*@null@*/ rpmgi gi)
554 {
555  char hnum[32];
556  rpmRC rpmrc = RPMRC_NOTFOUND;
557  int xx;
558 
559  if (gi == NULL)
560  return rpmrc;
561 
562 if (_rpmgi_debug)
563 fprintf(stderr, "*** %s(%p) tag %s\n", __FUNCTION__, gi, tagName(gi->tag));
564 
565  /* Free header from previous iteration. */
566  gi->h = headerFree(gi->h);
567  gi->hdrPath = _free(gi->hdrPath);
568  hnum[0] = '\0';
569 
570 /*@-branchstate@*/
571  if (++gi->i >= 0)
572  switch (gi->tag) {
573  default:
574  if (!gi->active) {
575 nextkey:
576  rpmrc = rpmgiLoadNextKey(gi);
577  if (rpmrc != RPMRC_OK)
578  goto enditer;
579  rpmrc = rpmgiInitFilter(gi);
580  if (rpmrc != RPMRC_OK || gi->mi == NULL) {
581  gi->mi = rpmdbFreeIterator(gi->mi); /* XXX unnecessary */
582  gi->i++;
583  goto nextkey;
584  }
585  rpmrc = RPMRC_NOTFOUND; /* XXX hack */
586  gi->active = 1;
587  }
588  if (gi->mi != NULL) { /* XXX unnecessary */
589  Header h = rpmdbNextIterator(gi->mi);
590  if (h != NULL) {
591  if (!(gi->flags & RPMGI_NOHEADER))
592  gi->h = headerLink(h);
593  sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
594  gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
595  rpmrc = RPMRC_OK;
596  /* XXX header reference held by iterator, so no headerFree */
597  }
598  }
599  if (rpmrc != RPMRC_OK) {
600  gi->mi = rpmdbFreeIterator(gi->mi);
601  goto nextkey;
602  }
603  break;
604  case RPMDBI_PACKAGES:
605  if (!gi->active) {
606  rpmrc = rpmgiInitFilter(gi);
607  if (rpmrc != RPMRC_OK) {
608  gi->mi = rpmdbFreeIterator(gi->mi); /* XXX unnecessary */
609  goto enditer;
610  }
611  rpmrc = RPMRC_NOTFOUND; /* XXX hack */
612  gi->active = 1;
613  }
614  if (gi->mi != NULL) { /* XXX unnecessary */
615  Header h = rpmdbNextIterator(gi->mi);
616  if (h != NULL) {
617  if (!(gi->flags & RPMGI_NOHEADER))
618  gi->h = headerLink(h);
619  sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
620  gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
621  rpmrc = RPMRC_OK;
622  /* XXX header reference held by iterator, so no headerFree */
623  }
624  }
625  if (rpmrc != RPMRC_OK) {
626  gi->mi = rpmdbFreeIterator(gi->mi);
627  goto enditer;
628  }
629  break;
630  case RPMDBI_REMOVED:
631  case RPMDBI_ADDED:
632  { rpmte p;
633  int teType = 0;
634  const char * teTypeString = NULL;
635 
636  if (!gi->active) {
637  gi->tsi = rpmtsiInit(gi->ts);
638  gi->active = 1;
639  }
640  if ((p = rpmtsiNext(gi->tsi, teType)) != NULL) {
641  Header h = rpmteHeader(p);
642  if (h != NULL)
643  if (!(gi->flags & RPMGI_NOHEADER)) {
644  gi->h = headerLink(h);
645  switch(rpmteType(p)) {
646  case TR_ADDED: teTypeString = "+++"; /*@switchbreak@*/break;
647  case TR_REMOVED: teTypeString = "---"; /*@switchbreak@*/break;
648  }
649  sprintf(hnum, "%u", (unsigned)gi->i);
650  gi->hdrPath = rpmExpand("%s h# ", teTypeString, hnum, NULL);
651  rpmrc = RPMRC_OK;
652  h = headerFree(h);
653  }
654  }
655  if (rpmrc != RPMRC_OK) {
656  gi->tsi = rpmtsiFree(gi->tsi);
657  goto enditer;
658  }
659  } break;
660  case RPMDBI_HDLIST:
661  if (!gi->active) {
662  const char * path = rpmExpand("%{?_query_hdlist_path}", NULL);
663  if (path == NULL || *path == '\0') {
664  path = _free(path);
665  path = rpmExpand(_query_hdlist_path, NULL);
666  }
667  gi->fd = rpmgiOpen(path, "rm");
668  gi->active = 1;
669  path = _free(path);
670  }
671  if (gi->fd != NULL) {
672  Header h = headerRead(gi->fd, HEADER_MAGIC_YES);
673  if (h != NULL) {
674  if (!(gi->flags & RPMGI_NOHEADER))
675  gi->h = headerLink(h);
676  sprintf(hnum, "%u", (unsigned)gi->i);
677  gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
678  rpmrc = RPMRC_OK;
679  h = headerFree(h);
680  }
681  }
682  if (rpmrc != RPMRC_OK) {
683  if (gi->fd != NULL) (void) Fclose(gi->fd);
684  gi->fd = NULL;
685  goto enditer;
686  }
687  break;
688  case RPMDBI_ARGLIST:
689  /* XXX gi->active initialize? */
690 if (_rpmgi_debug < 0)
691 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
692  /* Read next header, lazily expanding manifests as found. */
693  rpmrc = rpmgiLoadReadHeader(gi);
694 
695  if (rpmrc != RPMRC_OK) /* XXX check this */
696  goto enditer;
697 
698  gi->hdrPath = xstrdup(gi->argv[gi->i]);
699  break;
700  case RPMDBI_FTSWALK:
701  if (gi->argv == NULL || gi->argv[0] == NULL) /* HACK */
702  goto enditer;
703 
704  if (!gi->active) {
705  gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
706  /* XXX NULL with open(2)/malloc(3) errno set */
707  gi->active = 1;
708  }
709 
710  /* Read next header, lazily walking file tree. */
711  rpmrc = rpmgiWalkReadHeader(gi);
712 
713  if (rpmrc != RPMRC_OK) {
714  xx = Fts_close(gi->ftsp);
715  gi->ftsp = NULL;
716  goto enditer;
717  }
718 
719  if (gi->fts != NULL)
720  gi->hdrPath = xstrdup(gi->fts->fts_path);
721  break;
722  }
723 /*@=branchstate@*/
724 
725  if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) {
726  /* XXX rpmgi hack: Save header in transaction element. */
727  if (gi->flags & RPMGI_ERASING) {
728  static int hdrx = 0;
729  int dboffset = headerGetInstance(gi->h);
730  if (dboffset <= 0)
731  dboffset = --hdrx;
732  xx = rpmtsAddEraseElement(gi->ts, gi->h, dboffset);
733  } else
734  xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL);
735  }
736 
737  return rpmrc;
738 
739 enditer:
740  if (gi->flags & RPMGI_TSORDER) {
741  rpmts ts = gi->ts;
742  rpmps ps;
743  int i;
744 
745  /* Block access to indices used for depsolving. */
746  if (!(gi->flags & RPMGI_ERASING)) {
747  ts->goal = TSM_INSTALL;
748  xx = rpmdbBlockDBI(ts->rdb, -RPMDBI_DEPENDS);
749  xx = rpmdbBlockDBI(ts->rdb, -RPMTAG_BASENAMES);
750  xx = rpmdbBlockDBI(ts->rdb, -RPMTAG_PROVIDENAME);
751  } else {
752  ts->goal = TSM_ERASE;
753  }
754 
755  xx = rpmtsCheck(ts);
756 
757  /* Permit access to indices used for depsolving. */
758  if (!(gi->flags & RPMGI_ERASING)) {
759  xx = rpmdbBlockDBI(ts->rdb, +RPMTAG_PROVIDENAME);
760  xx = rpmdbBlockDBI(ts->rdb, +RPMTAG_BASENAMES);
761  xx = rpmdbBlockDBI(ts->rdb, +RPMDBI_DEPENDS);
762  }
763 
764  /* XXX query/verify will need the glop added to a buffer instead. */
765  ps = rpmtsProblems(ts);
766  if (rpmpsNumProblems(ps) > 0) {
767  /* XXX rpminstall will need RPMMESS_ERROR */
768  rpmMessage(RPMMESS_VERBOSE, _("Failed dependencies:\n"));
769  if (rpmIsVerbose())
770  rpmpsPrint(NULL, ps);
771 
772 /*@-branchstate@*/
773  if (ts->suggests != NULL && ts->nsuggests > 0) {
774  rpmMessage(RPMMESS_VERBOSE, _(" Suggested resolutions:\n"));
775  for (i = 0; i < ts->nsuggests; i++) {
776  const char * str = ts->suggests[i];
777 
778  if (str == NULL)
779  break;
780 
781  rpmMessage(RPMMESS_VERBOSE, "\t%s\n", str);
782 
783  ts->suggests[i] = NULL;
784  str = _free(str);
785  }
786  ts->suggests = _free(ts->suggests);
787  }
788 /*@=branchstate@*/
789 
790  }
791  ps = rpmpsFree(ps);
792  ts->probs = rpmpsFree(ts->probs); /* XXX hackery */
793 
794  /* XXX Display dependency loops with rpm -qvT. */
795  if (rpmIsVerbose())
797 
798  xx = (*gi->tsOrder) (ts);
799 
800  /* XXX hackery alert! */
801  gi->tag = (!(gi->flags & RPMGI_ERASING) ? RPMDBI_ADDED : RPMDBI_REMOVED);
802  gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER);
803 
804  }
805 
806  gi->h = headerFree(gi->h);
807  gi->hdrPath = _free(gi->hdrPath);
808  gi->i = -1;
809  gi->active = 0;
810  return rpmrc;
811 }
812 
813 const char * rpmgiHdrPath(rpmgi gi)
814 {
815  return (gi != NULL ? gi->hdrPath : NULL);
816 }
817 
819 {
820 /*@-compdef -refcounttrans -retexpose -usereleased@*/
821  return (gi != NULL ? gi->h : NULL);
822 /*@=compdef =refcounttrans =retexpose =usereleased@*/
823 }
824 
826 {
827 /*@-compdef -refcounttrans -retexpose -usereleased@*/
828  return (gi != NULL ? gi->ts : NULL);
829 /*@=compdef =refcounttrans =retexpose =usereleased@*/
830 }
831 
833 {
834  if (gi == NULL) return RPMRC_FAIL;
835  gi->ftsOpts = ftsOpts;
836  gi->flags = flags;
837  return rpmgiGlobArgv(gi, argv);
838 }
839 
840 /*@=modfilesys@*/