rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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