rpm
5.2.1
|
00001 /*@-modfilesys@*/ 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 #include <rpmcb.h> 00010 #include <rpmmacro.h> /* XXX rpmExpand */ 00011 #include <rpmtypes.h> 00012 #include <rpmtag.h> 00013 #include <rpmdb.h> 00014 00015 #include <rpmte.h> /* XXX rpmElementType */ 00016 #include <pkgio.h> /* XXX rpmElementType */ 00017 00018 #define _RPMGI_INTERNAL 00019 #define _RPMTS_INTERNAL /* XXX ts->probs et al */ 00020 #include <rpmgi.h> 00021 00022 #include "manifest.h" 00023 00024 #include <rpmlib.h> 00025 00026 #include "debug.h" 00027 00028 /*@access FD_t @*/ /* XXX void * arg */ 00029 /*@access fnpyKey @*/ 00030 /*@access rpmmi @*/ 00031 /*@access rpmts @*/ 00032 /*@access rpmps @*/ 00033 00036 /*@unchecked@*/ 00037 int _rpmgi_debug = 0; 00038 00041 /*@unchecked@*/ 00042 rpmgiFlags giFlags = RPMGI_NONE; 00043 00046 /*@unchecked@*/ 00047 static int indent = 2; 00048 00051 /*@unchecked@*/ /*@observer@*/ 00052 static const char * ftsInfoStrings[] = { 00053 "UNKNOWN", 00054 "D", 00055 "DC", 00056 "DEFAULT", 00057 "DNR", 00058 "DOT", 00059 "DP", 00060 "ERR", 00061 "F", 00062 "INIT", 00063 "NS", 00064 "NSOK", 00065 "SL", 00066 "SLNONE", 00067 "W", 00068 }; 00069 00072 /*@observer@*/ 00073 static const char * ftsInfoStr(int fts_info) 00074 /*@*/ 00075 { 00076 00077 if (!(fts_info >= 1 && fts_info <= 14)) 00078 fts_info = 0; 00079 /*@-compmempass@*/ 00080 return ftsInfoStrings[ fts_info ]; 00081 /*@=compmempass@*/ 00082 } 00083 00091 /*@null@*/ 00092 static FD_t rpmgiOpen(const char * path, const char * fmode) 00093 /*@globals rpmGlobalMacroContext, h_errno, errno, internalState @*/ 00094 /*@modifies rpmGlobalMacroContext, h_errno, errno, internalState @*/ 00095 { 00096 const char * fn = rpmExpand(path, NULL); 00097 FD_t fd; 00098 00099 /* FIXME (see http://rpm5.org/community/rpm-devel/0523.html) */ 00100 errno = 0; 00101 fd = Fopen(fn, fmode); 00102 00103 if (fd == NULL || Ferror(fd)) { 00104 rpmlog(RPMLOG_ERR, _("open of %s failed: %s\n"), fn, Fstrerror(fd)); 00105 if (fd != NULL) (void) Fclose(fd); 00106 fd = NULL; 00107 } 00108 fn = _free(fn); 00109 00110 return fd; 00111 } 00112 00119 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path) 00120 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00121 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00122 { 00123 FD_t fd = rpmgiOpen(path, "r%{?_rpmgio}"); 00124 rpmRC rpmrc = RPMRC_FAIL; 00125 00126 if (fd != NULL) { 00127 rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv); 00128 (void) Fclose(fd); 00129 } 00130 return rpmrc; 00131 } 00132 00133 Header rpmgiReadHeader(rpmgi gi, const char * path) 00134 { 00135 FD_t fd = rpmgiOpen(path, "r%{?_rpmgio}"); 00136 Header h = NULL; 00137 00138 if (fd != NULL) { 00139 /* XXX what if path needs expansion? */ 00140 rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h); 00141 00142 (void) Fclose(fd); 00143 00144 switch (rpmrc) { 00145 case RPMRC_NOTFOUND: 00146 /* XXX Read a package manifest. Restart ftswalk on success. */ 00147 case RPMRC_FAIL: 00148 default: 00149 (void)headerFree(h); 00150 h = NULL; 00151 break; 00152 case RPMRC_NOTTRUSTED: 00153 case RPMRC_NOKEY: 00154 case RPMRC_OK: 00155 break; 00156 } 00157 } 00158 00159 return h; 00160 } 00161 00167 static rpmRC rpmgiLoadNextKey(rpmgi gi) 00168 /*@modifies gi @*/ 00169 { 00170 rpmRC rpmrc = RPMRC_NOTFOUND; 00171 if (gi->argv != NULL && gi->argv[gi->i] != NULL) { 00172 gi->keyp = gi->argv[gi->i]; 00173 gi->keylen = 0; 00174 rpmrc = RPMRC_OK; 00175 } else { 00176 gi->i = -1; 00177 gi->keyp = NULL; 00178 gi->keylen = 0; 00179 } 00180 return rpmrc; 00181 } 00182 00191 static rpmRC rpmgiLoadReadHeader(rpmgi gi) 00192 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00193 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00194 { 00195 rpmRC rpmrc = RPMRC_NOTFOUND; 00196 Header h = NULL; 00197 00198 if (gi->argv != NULL && gi->argv[gi->i] != NULL) 00199 do { 00200 const char * fn; /* XXX gi->hdrPath? */ 00201 00202 fn = gi->argv[gi->i]; 00203 /* XXX Skip +bing -bang =boom special arguments. */ 00204 if (strchr("-+=", *fn) == NULL && !(gi->flags & RPMGI_NOHEADER)) { 00205 h = rpmgiReadHeader(gi, fn); 00206 if (h != NULL) 00207 rpmrc = RPMRC_OK; 00208 } else 00209 rpmrc = RPMRC_OK; 00210 00211 if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST) 00212 break; 00213 if (errno == ENOENT) 00214 break; 00215 00216 /* Not a header, so try for a manifest. */ 00217 gi->argv[gi->i] = NULL; /* Mark the insertion point */ 00218 rpmrc = rpmgiLoadManifest(gi, fn); 00219 /* XXX its unclear if RPMRC_NOTFOUND should fail or continue here. */ 00220 if (rpmrc != RPMRC_OK) { 00221 gi->argv[gi->i] = fn; /* Manifest failed, restore fn */ 00222 break; 00223 } 00224 fn = _free(fn); 00225 rpmrc = RPMRC_NOTFOUND; 00226 } while (1); 00227 00228 if (rpmrc == RPMRC_OK && h != NULL) 00229 gi->h = headerLink(h); 00230 (void)headerFree(h); 00231 h = NULL; 00232 00233 return rpmrc; 00234 } 00235 00241 /*@null@*/ 00242 static rpmRC rpmgiWalkPathFilter(rpmgi gi) 00243 /*@*/ 00244 { 00245 FTSENT * fts = gi->fts; 00246 rpmRC rpmrc = RPMRC_NOTFOUND; 00247 const char * s; 00248 00249 if (_rpmgi_debug < 0) 00250 rpmlog(RPMLOG_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info), 00251 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "", 00252 fts->fts_name, 00253 ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : "")); 00254 00255 switch (fts->fts_info) { 00256 case FTS_D: /* preorder directory */ 00257 break; 00258 case FTS_DP: /* postorder directory */ 00259 break; 00260 case FTS_F: /* regular file */ 00261 if ((size_t)fts->fts_namelen <= sizeof(".rpm")) 00262 break; 00263 /* Ignore all but *.rpm files. */ 00264 s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm"); 00265 if (strcmp(s, ".rpm")) 00266 break; 00267 rpmrc = RPMRC_OK; 00268 break; 00269 case FTS_NS: /* stat(2) failed */ 00270 case FTS_DNR: /* unreadable directory */ 00271 case FTS_ERR: /* error; errno is set */ 00272 break; 00273 case FTS_DC: /* directory that causes cycles */ 00274 case FTS_DEFAULT: /* none of the above */ 00275 case FTS_DOT: /* dot or dot-dot */ 00276 case FTS_INIT: /* initialized only */ 00277 case FTS_NSOK: /* no stat(2) requested */ 00278 case FTS_SL: /* symbolic link */ 00279 case FTS_SLNONE: /* symbolic link without target */ 00280 case FTS_W: /* whiteout object */ 00281 default: 00282 break; 00283 } 00284 return rpmrc; 00285 } 00286 00292 /*@null@*/ 00293 static rpmRC rpmgiWalkReadHeader(rpmgi gi) 00294 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00295 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00296 { 00297 rpmRC rpmrc = RPMRC_NOTFOUND; 00298 00299 if (gi->ftsp != NULL) 00300 while ((gi->fts = Fts_read(gi->ftsp)) != NULL) { 00301 if (gi->walkPathFilter) 00302 rpmrc = (*gi->walkPathFilter) (gi); 00303 else 00304 rpmrc = rpmgiWalkPathFilter(gi); 00305 if (rpmrc == RPMRC_OK) 00306 break; 00307 } 00308 00309 if (rpmrc == RPMRC_OK) { 00310 Header h = NULL; 00311 if (!(gi->flags & RPMGI_NOHEADER)) { 00312 /* XXX rpmrc = rpmgiLoadReadHeader(gi); */ 00313 if (gi->fts != NULL) /* XXX can't happen */ 00314 h = rpmgiReadHeader(gi, gi->fts->fts_path); 00315 } 00316 if (h != NULL) { 00317 gi->h = headerLink(h); 00318 (void)headerFree(h); 00319 h = NULL; 00320 /*@-noeffectuncon@*/ 00321 if (gi->stash != NULL) 00322 (void) (*gi->stash) (gi, gi->h); 00323 /*@=noeffectuncon@*/ 00324 } 00325 } 00326 00327 return rpmrc; 00328 } 00329 00330 const char * rpmgiEscapeSpaces(const char * s) 00331 { 00332 const char * se; 00333 const char * t; 00334 char * te; 00335 size_t nb = 0; 00336 00337 for (se = s; *se; se++) { 00338 if (isspace(*se)) 00339 nb++; 00340 nb++; 00341 } 00342 nb++; 00343 00344 t = te = xmalloc(nb); 00345 for (se = s; *se; se++) { 00346 if (isspace(*se)) 00347 *te++ = '\\'; 00348 *te++ = *se; 00349 } 00350 *te = '\0'; 00351 return t; 00352 } 00353 00360 static rpmRC rpmgiGlobArgv(rpmgi gi, /*@null@*/ ARGV_t argv) 00361 /*@globals internalState @*/ 00362 /*@modifies gi, internalState @*/ 00363 { 00364 const char * arg; 00365 rpmRC rpmrc = RPMRC_OK; 00366 int ac = 0; 00367 int xx; 00368 00369 /* XXX Expand globs only if requested or for gi specific tags */ 00370 if ((gi->flags & RPMGI_NOGLOB) 00371 || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK)) 00372 { 00373 if (argv != NULL) { 00374 while (argv[ac] != NULL) 00375 ac++; 00376 /*@-nullstate@*/ /* XXX argv is not NULL */ 00377 xx = argvAppend(&gi->argv, argv); 00378 /*@=nullstate@*/ 00379 } 00380 gi->argc = ac; 00381 return rpmrc; 00382 } 00383 00384 if (argv != NULL) 00385 while ((arg = *argv++) != NULL) { 00386 const char * t = rpmgiEscapeSpaces(arg); 00387 ARGV_t av = NULL; 00388 00389 xx = rpmGlob(t, &ac, &av); 00390 xx = argvAppend(&gi->argv, av); 00391 gi->argc += ac; 00392 av = argvFree(av); 00393 t = _free(t); 00394 ac = 0; 00395 } 00396 return rpmrc; 00397 } 00398 00404 static rpmRC rpmgiInitFilter(rpmgi gi) 00405 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00406 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00407 { 00408 rpmRC rpmrc = RPMRC_OK; 00409 ARGV_t av; 00410 int res = 0; 00411 00412 gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen); 00413 00414 if (_rpmgi_debug < 0) 00415 fprintf(stderr, "*** gi %p key %p[%d]\tmi %p\n", gi, gi->keyp, (int)gi->keylen, gi->mi); 00416 00417 if (gi->argv != NULL) 00418 for (av = (const char **) gi->argv; *av != NULL; av++) { 00419 if (gi->tag == RPMDBI_PACKAGES) { 00420 int tag = RPMTAG_NAME; 00421 const char * pat; 00422 char * a, * ae; 00423 00424 pat = a = xstrdup(*av); 00425 tag = RPMTAG_NAME; 00426 00427 /* Parse for "tag=pattern" args. */ 00428 if ((ae = strchr(a, '=')) != NULL) { 00429 *ae++ = '\0'; 00430 if (*a != '\0') { /* XXX HACK: permit '=foo' */ 00431 tag = tagValue(a); 00432 if (tag < 0) { 00433 rpmlog(RPMLOG_NOTICE, _("unknown tag: \"%s\"\n"), a); 00434 res = 1; 00435 } 00436 } 00437 pat = ae; 00438 } 00439 if (!res) { 00440 if (_rpmgi_debug < 0) 00441 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (int)(av - gi->argv), *av, tagName(tag), pat); 00442 res = rpmmiAddPattern(gi->mi, tag, RPMMIRE_DEFAULT, pat); 00443 } 00444 a = _free(a); 00445 } 00446 00447 if (res == 0) 00448 continue; 00449 00450 gi->mi = rpmmiFree(gi->mi); /* XXX odd side effect? */ 00451 rpmrc = RPMRC_FAIL; 00452 break; 00453 } 00454 00455 return rpmrc; 00456 } 00457 00458 /*@-mustmod@*/ 00459 static void rpmgiFini(void * _gi) 00460 /*@globals rpmGlobalMacroContext @*/ 00461 /*@modifies _gi, rpmGlobalMacroContext @*/ 00462 { 00463 rpmgi gi = _gi; 00464 int xx; 00465 00466 gi->hdrPath = _free(gi->hdrPath); 00467 (void)headerFree(gi->h); 00468 gi->h = NULL; 00469 00470 gi->argv = argvFree(gi->argv); 00471 00472 if (gi->ftsp != NULL) { 00473 xx = Fts_close(gi->ftsp); 00474 gi->ftsp = NULL; 00475 gi->fts = NULL; 00476 } 00477 if (gi->fd != NULL) { 00478 xx = Fclose(gi->fd); 00479 gi->fd = NULL; 00480 } 00481 gi->tsi = rpmtsiFree(gi->tsi); 00482 gi->mi = rpmmiFree(gi->mi); 00483 (void)rpmtsFree(gi->ts); 00484 gi->ts = NULL; 00485 } 00486 /*@=mustmod@*/ 00487 00488 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00489 rpmioPool _rpmgiPool; 00490 00491 static rpmgi rpmgiGetPool(/*@null@*/ rpmioPool pool) 00492 /*@globals _rpmgiPool, fileSystem, internalState @*/ 00493 /*@modifies pool, _rpmgiPool, fileSystem, internalState @*/ 00494 { 00495 rpmgi gi; 00496 00497 if (_rpmgiPool == NULL) { 00498 _rpmgiPool = rpmioNewPool("gi", sizeof(*gi), -1, _rpmgi_debug, 00499 NULL, NULL, rpmgiFini); 00500 pool = _rpmgiPool; 00501 } 00502 return (rpmgi) rpmioGetPool(pool, sizeof(*gi)); 00503 } 00504 00505 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen) 00506 { 00507 rpmgi gi = rpmgiGetPool(_rpmgiPool); 00508 00509 if (gi == NULL) /* XXX can't happen */ 00510 return NULL; 00511 00512 /*@-assignexpose -castexpose @*/ 00513 gi->ts = rpmtsLink(ts, "rpmgiNew"); 00514 /*@=assignexpose =castexpose @*/ 00515 gi->tsOrder = rpmtsOrder; 00516 gi->tag = (rpmTag) tag; 00517 /*@-assignexpose@*/ 00518 gi->keyp = keyp; 00519 /*@=assignexpose@*/ 00520 gi->keylen = keylen; 00521 00522 gi->flags = 0; 00523 gi->active = 0; 00524 gi->i = -1; 00525 gi->hdrPath = NULL; 00526 gi->h = NULL; 00527 00528 gi->tsi = NULL; 00529 gi->mi = NULL; 00530 gi->fd = NULL; 00531 gi->argv = xcalloc(1, sizeof(*gi->argv)); 00532 gi->argc = 0; 00533 gi->ftsOpts = 0; 00534 gi->ftsp = NULL; 00535 gi->fts = NULL; 00536 gi->walkPathFilter = NULL; 00537 00538 gi = rpmgiLink(gi, "rpmgiNew"); 00539 00540 return gi; 00541 } 00542 00543 /*@observer@*/ /*@unchecked@*/ 00544 static const char * _query_hdlist_path = "/usr/share/comps/%{_arch}/hdlist"; 00545 00546 rpmRC rpmgiNext(/*@null@*/ rpmgi gi) 00547 { 00548 char hnum[32]; 00549 rpmRC rpmrc = RPMRC_NOTFOUND; 00550 int xx; 00551 00552 if (gi == NULL) 00553 return rpmrc; 00554 00555 if (_rpmgi_debug) 00556 fprintf(stderr, "*** rpmgiNext(%p) tag %s\n", gi, tagName(gi->tag)); 00557 00558 /* Free header from previous iteration. */ 00559 (void)headerFree(gi->h); 00560 gi->h = NULL; 00561 gi->hdrPath = _free(gi->hdrPath); 00562 hnum[0] = '\0'; 00563 00564 if (++gi->i >= 0) 00565 switch (gi->tag) { 00566 default: 00567 if (!gi->active) { 00568 nextkey: 00569 rpmrc = rpmgiLoadNextKey(gi); 00570 if (rpmrc != RPMRC_OK) 00571 goto enditer; 00572 rpmrc = rpmgiInitFilter(gi); 00573 if (rpmrc != RPMRC_OK || gi->mi == NULL) { 00574 gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ 00575 gi->i++; 00576 goto nextkey; 00577 } 00578 rpmrc = RPMRC_NOTFOUND; /* XXX hack */ 00579 gi->active = 1; 00580 } 00581 if (gi->mi != NULL) { /* XXX unnecessary */ 00582 Header h = rpmmiNext(gi->mi); 00583 if (h != NULL) { 00584 if (!(gi->flags & RPMGI_NOHEADER)) 00585 gi->h = headerLink(h); 00586 sprintf(hnum, "%u", rpmmiInstance(gi->mi)); 00587 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); 00588 rpmrc = RPMRC_OK; 00589 /* XXX header reference held by iterator, so no headerFree */ 00590 } 00591 } 00592 if (rpmrc != RPMRC_OK) { 00593 gi->mi = rpmmiFree(gi->mi); 00594 goto nextkey; 00595 } 00596 break; 00597 case RPMDBI_PACKAGES: 00598 if (!gi->active) { 00599 rpmrc = rpmgiInitFilter(gi); 00600 if (rpmrc != RPMRC_OK) { 00601 gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ 00602 goto enditer; 00603 } 00604 rpmrc = RPMRC_NOTFOUND; /* XXX hack */ 00605 gi->active = 1; 00606 } 00607 if (gi->mi != NULL) { /* XXX unnecessary */ 00608 Header h = rpmmiNext(gi->mi); 00609 if (h != NULL) { 00610 if (!(gi->flags & RPMGI_NOHEADER)) 00611 gi->h = headerLink(h); 00612 sprintf(hnum, "%u", rpmmiInstance(gi->mi)); 00613 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); 00614 rpmrc = RPMRC_OK; 00615 /* XXX header reference held by iterator, so no headerFree */ 00616 } 00617 } 00618 if (rpmrc != RPMRC_OK) { 00619 gi->mi = rpmmiFree(gi->mi); 00620 goto enditer; 00621 } 00622 break; 00623 case RPMDBI_REMOVED: 00624 case RPMDBI_ADDED: 00625 { rpmte p; 00626 int teType = 0; 00627 const char * teTypeString = NULL; 00628 00629 if (!gi->active) { 00630 gi->tsi = rpmtsiInit(gi->ts); 00631 gi->active = 1; 00632 } 00633 if ((p = rpmtsiNext(gi->tsi, teType)) != NULL) { 00634 Header h = rpmteHeader(p); 00635 if (h != NULL) 00636 if (!(gi->flags & RPMGI_NOHEADER)) { 00637 gi->h = headerLink(h); 00638 switch(rpmteType(p)) { 00639 case TR_ADDED: teTypeString = "+++"; /*@switchbreak@*/break; 00640 case TR_REMOVED: teTypeString = "---"; /*@switchbreak@*/break; 00641 } 00642 sprintf(hnum, "%u", (unsigned)gi->i); 00643 gi->hdrPath = rpmExpand("%s h# ", teTypeString, hnum, NULL); 00644 rpmrc = RPMRC_OK; 00645 (void)headerFree(h); 00646 h = NULL; 00647 } 00648 } 00649 if (rpmrc != RPMRC_OK) { 00650 gi->tsi = rpmtsiFree(gi->tsi); 00651 goto enditer; 00652 } 00653 } break; 00654 case RPMDBI_HDLIST: 00655 if (!gi->active) { 00656 const char * path = rpmExpand("%{?_query_hdlist_path}", NULL); 00657 if (path == NULL || *path == '\0') { 00658 path = _free(path); 00659 path = rpmExpand(_query_hdlist_path, NULL); 00660 } 00661 gi->fd = rpmgiOpen(path, "rm%{?_rpmgio}"); 00662 gi->active = 1; 00663 path = _free(path); 00664 } 00665 if (gi->fd != NULL) { 00666 Header h = NULL; 00667 const char item[] = "Header"; 00668 const char * msg = NULL; 00669 /*@+voidabstract@*/ 00670 rpmrc = rpmpkgRead(item, gi->fd, &h, &msg); 00671 /*@=voidabstract@*/ 00672 if (rpmrc != RPMRC_OK) { 00673 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg); 00674 h = NULL; 00675 } 00676 msg = _free(msg); 00677 if (h != NULL) { 00678 if (!(gi->flags & RPMGI_NOHEADER)) 00679 gi->h = headerLink(h); 00680 sprintf(hnum, "%u", (unsigned)gi->i); 00681 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL); 00682 rpmrc = RPMRC_OK; 00683 (void)headerFree(h); 00684 h = NULL; 00685 } 00686 } 00687 if (rpmrc != RPMRC_OK) { 00688 if (gi->fd != NULL) (void) Fclose(gi->fd); 00689 gi->fd = NULL; 00690 goto enditer; 00691 } 00692 break; 00693 case RPMDBI_ARGLIST: 00694 /* XXX gi->active initialize? */ 00695 if (_rpmgi_debug < 0) 00696 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]); 00697 /* Read next header, lazily expanding manifests as found. */ 00698 rpmrc = rpmgiLoadReadHeader(gi); 00699 00700 if (rpmrc != RPMRC_OK) /* XXX check this */ 00701 goto enditer; 00702 00703 gi->hdrPath = xstrdup(gi->argv[gi->i]); 00704 break; 00705 case RPMDBI_FTSWALK: 00706 if (gi->argv == NULL || gi->argv[0] == NULL) /* HACK */ 00707 goto enditer; 00708 00709 if (!gi->active) { 00710 gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL); 00711 /* XXX NULL with open(2)/malloc(3) errno set */ 00712 gi->active = 1; 00713 } 00714 00715 /* Read next header, lazily walking file tree. */ 00716 rpmrc = rpmgiWalkReadHeader(gi); 00717 00718 if (rpmrc != RPMRC_OK) { 00719 xx = Fts_close(gi->ftsp); 00720 gi->ftsp = NULL; 00721 goto enditer; 00722 } 00723 00724 if (gi->fts != NULL) 00725 gi->hdrPath = xstrdup(gi->fts->fts_path); 00726 break; 00727 } 00728 00729 if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) { 00730 /* XXX rpmgi hack: Save header in transaction element. */ 00731 if (gi->flags & RPMGI_ERASING) { 00732 static int hdrx = 0; 00733 int dboffset = headerGetInstance(gi->h); 00734 if (dboffset <= 0) 00735 dboffset = --hdrx; 00736 xx = rpmtsAddEraseElement(gi->ts, gi->h, dboffset); 00737 } else 00738 xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL); 00739 } 00740 00741 return rpmrc; 00742 00743 enditer: 00744 if (gi->flags & RPMGI_TSORDER) { 00745 rpmts ts = gi->ts; 00746 rpmps ps; 00747 int i; 00748 00749 /* Block access to indices used for depsolving. */ 00750 if (!(gi->flags & RPMGI_ERASING)) { 00751 (void) rpmtsSetGoal(ts, TSM_INSTALL); 00752 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMDBI_DEPENDS); 00753 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_BASENAMES); 00754 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_PROVIDENAME); 00755 } else { 00756 (void) rpmtsSetGoal(ts, TSM_ERASE); 00757 } 00758 00759 xx = rpmtsCheck(ts); 00760 00761 /* Permit access to indices used for depsolving. */ 00762 if (!(gi->flags & RPMGI_ERASING)) { 00763 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_PROVIDENAME); 00764 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_BASENAMES); 00765 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS); 00766 } 00767 00768 /* XXX query/verify will need the glop added to a buffer instead. */ 00769 ps = rpmtsProblems(ts); 00770 if (rpmpsNumProblems(ps) > 0) { 00771 /* XXX rpminstall will need RPMLOG_ERR */ 00772 rpmlog(RPMLOG_INFO, _("Failed dependencies:\n")); 00773 if (rpmIsVerbose()) 00774 rpmpsPrint(NULL, ps); 00775 00776 if (ts->suggests != NULL && ts->nsuggests > 0) { 00777 rpmlog(RPMLOG_INFO, _(" Suggested resolutions:\n")); 00778 for (i = 0; i < ts->nsuggests; i++) { 00779 const char * str = ts->suggests[i]; 00780 00781 if (str == NULL) 00782 break; 00783 00784 rpmlog(RPMLOG_INFO, "\t%s\n", str); 00785 00786 ts->suggests[i] = NULL; 00787 str = _free(str); 00788 } 00789 ts->suggests = _free(ts->suggests); 00790 } 00791 00792 } 00793 ps = rpmpsFree(ps); 00794 ts->probs = rpmpsFree(ts->probs); /* XXX hackery */ 00795 00796 /* XXX Display dependency loops with rpm -qvT. */ 00797 if (rpmIsVerbose()) 00798 (void) rpmtsSetDFlags(ts, (rpmtsDFlags(ts) | RPMDEPS_FLAG_DEPLOOPS)); 00799 00800 xx = (*gi->tsOrder) (ts); 00801 00802 /* XXX hackery alert! */ 00803 gi->tag = (!(gi->flags & RPMGI_ERASING) ? RPMDBI_ADDED : RPMDBI_REMOVED); 00804 gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER); 00805 00806 } 00807 00808 (void)headerFree(gi->h); 00809 gi->h = NULL; 00810 gi->hdrPath = _free(gi->hdrPath); 00811 gi->i = -1; 00812 gi->active = 0; 00813 return rpmrc; 00814 } 00815 00816 rpmgiFlags rpmgiGetFlags(rpmgi gi) 00817 { 00818 return (gi != NULL ? gi->flags : RPMGI_NONE); 00819 } 00820 00821 const char * rpmgiHdrPath(rpmgi gi) 00822 { 00823 return (gi != NULL ? gi->hdrPath : NULL); 00824 } 00825 00826 Header rpmgiHeader(rpmgi gi) 00827 { 00828 /*@-compdef -refcounttrans -retexpose -usereleased@*/ 00829 return (gi != NULL ? gi->h : NULL); 00830 /*@=compdef =refcounttrans =retexpose =usereleased@*/ 00831 } 00832 00833 rpmts rpmgiTs(rpmgi gi) 00834 { 00835 /*@-compdef -refcounttrans -retexpose -usereleased@*/ 00836 return (gi != NULL ? gi->ts : NULL); 00837 /*@=compdef =refcounttrans =retexpose =usereleased@*/ 00838 } 00839 00840 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags) 00841 { 00842 if (gi == NULL) return RPMRC_FAIL; 00843 gi->ftsOpts = ftsOpts; 00844 gi->flags = flags; 00845 return rpmgiGlobArgv(gi, argv); 00846 } 00847 00848 /*@=modfilesys@*/