rpm 5.3.7
|
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 <rpmcli.h> /* XXX rpmcliInstallFoo() */ 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 #if defined(POSIX_FADV_WILLNEED) 00111 if(fd != NULL) 00112 (void) Fadvise(fd, 0, 0, POSIX_FADV_WILLNEED); 00113 #endif 00114 00115 return fd; 00116 } 00117 00124 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path) 00125 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00126 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00127 { 00128 FD_t fd = rpmgiOpen(path, "r%{?_rpmgio}"); 00129 rpmRC rpmrc = RPMRC_FAIL; 00130 00131 if (fd != NULL) { 00132 rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv); 00133 (void) Fclose(fd); 00134 } 00135 return rpmrc; 00136 } 00137 00138 Header rpmgiReadHeader(rpmgi gi, const char * path) 00139 { 00140 FD_t fd = rpmgiOpen(path, "r%{?_rpmgio}"); 00141 Header h = NULL; 00142 00143 if (fd != NULL) { 00144 /* XXX what if path needs expansion? */ 00145 rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h); 00146 00147 (void) Fclose(fd); 00148 00149 switch (rpmrc) { 00150 case RPMRC_NOTFOUND: 00151 /* XXX Read a package manifest. Restart ftswalk on success. */ 00152 case RPMRC_FAIL: 00153 default: 00154 (void)headerFree(h); 00155 h = NULL; 00156 break; 00157 case RPMRC_NOTTRUSTED: 00158 case RPMRC_NOKEY: 00159 case RPMRC_OK: 00160 break; 00161 } 00162 } 00163 00164 return h; 00165 } 00166 00172 static rpmRC rpmgiLoadNextKey(rpmgi gi) 00173 /*@modifies gi @*/ 00174 { 00175 rpmRC rpmrc = RPMRC_NOTFOUND; 00176 if (gi->argv != NULL && gi->argv[gi->i] != NULL) { 00177 gi->keyp = gi->argv[gi->i]; 00178 gi->keylen = 0; 00179 rpmrc = RPMRC_OK; 00180 } else { 00181 gi->i = -1; 00182 gi->keyp = NULL; 00183 gi->keylen = 0; 00184 } 00185 return rpmrc; 00186 } 00187 00196 static rpmRC rpmgiLoadReadHeader(rpmgi gi) 00197 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00198 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00199 { 00200 rpmRC rpmrc = RPMRC_NOTFOUND; 00201 Header h = NULL; 00202 00203 if (gi->argv != NULL && gi->argv[gi->i] != NULL) 00204 do { 00205 const char * fn; /* XXX gi->hdrPath? */ 00206 00207 fn = gi->argv[gi->i]; 00208 /* XXX Skip +bing -bang =boom special arguments. */ 00209 if (strchr("-+=", *fn) == NULL && !(gi->flags & RPMGI_NOHEADER)) { 00210 h = rpmgiReadHeader(gi, fn); 00211 if (h != NULL) 00212 rpmrc = RPMRC_OK; 00213 } else 00214 rpmrc = RPMRC_OK; 00215 00216 if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST) 00217 break; 00218 if (errno == ENOENT) 00219 break; 00220 00221 /* Not a header, so try for a manifest. */ 00222 gi->argv[gi->i] = NULL; /* Mark the insertion point */ 00223 rpmrc = rpmgiLoadManifest(gi, fn); 00224 /* XXX its unclear if RPMRC_NOTFOUND should fail or continue here. */ 00225 if (rpmrc != RPMRC_OK) { 00226 gi->argv[gi->i] = fn; /* Manifest failed, restore fn */ 00227 break; 00228 } 00229 fn = _free(fn); 00230 rpmrc = RPMRC_NOTFOUND; 00231 } while (1); 00232 00233 if (rpmrc == RPMRC_OK && h != NULL) 00234 gi->h = headerLink(h); 00235 (void)headerFree(h); 00236 h = NULL; 00237 00238 return rpmrc; 00239 } 00240 00246 /*@null@*/ 00247 static rpmRC rpmgiWalkPathFilter(rpmgi gi) 00248 /*@*/ 00249 { 00250 FTSENT * fts = gi->fts; 00251 rpmRC rpmrc = RPMRC_NOTFOUND; 00252 const char * s; 00253 00254 if (_rpmgi_debug < 0) 00255 rpmlog(RPMLOG_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info), 00256 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "", 00257 fts->fts_name, 00258 ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : "")); 00259 00260 switch (fts->fts_info) { 00261 case FTS_D: /* preorder directory */ 00262 break; 00263 case FTS_DP: /* postorder directory */ 00264 break; 00265 case FTS_F: /* regular file */ 00266 if ((size_t)fts->fts_namelen <= sizeof(".rpm")) 00267 break; 00268 /* Ignore all but *.rpm files. */ 00269 s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm"); 00270 if (strcmp(s, ".rpm")) 00271 break; 00272 rpmrc = RPMRC_OK; 00273 break; 00274 case FTS_NS: /* stat(2) failed */ 00275 case FTS_DNR: /* unreadable directory */ 00276 case FTS_ERR: /* error; errno is set */ 00277 break; 00278 case FTS_DC: /* directory that causes cycles */ 00279 case FTS_DEFAULT: /* none of the above */ 00280 case FTS_DOT: /* dot or dot-dot */ 00281 case FTS_INIT: /* initialized only */ 00282 case FTS_NSOK: /* no stat(2) requested */ 00283 case FTS_SL: /* symbolic link */ 00284 case FTS_SLNONE: /* symbolic link without target */ 00285 case FTS_W: /* whiteout object */ 00286 default: 00287 break; 00288 } 00289 return rpmrc; 00290 } 00291 00297 /*@null@*/ 00298 static rpmRC rpmgiWalkReadHeader(rpmgi gi) 00299 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00300 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00301 { 00302 rpmRC rpmrc = RPMRC_NOTFOUND; 00303 00304 if (gi->ftsp != NULL) 00305 while ((gi->fts = Fts_read(gi->ftsp)) != NULL) { 00306 if (gi->walkPathFilter) 00307 rpmrc = (*gi->walkPathFilter) (gi); 00308 else 00309 rpmrc = rpmgiWalkPathFilter(gi); 00310 if (rpmrc == RPMRC_OK) 00311 break; 00312 } 00313 00314 if (rpmrc == RPMRC_OK) { 00315 Header h = NULL; 00316 if (!(gi->flags & RPMGI_NOHEADER)) { 00317 /* XXX rpmrc = rpmgiLoadReadHeader(gi); */ 00318 if (gi->fts != NULL) /* XXX can't happen */ 00319 h = rpmgiReadHeader(gi, gi->fts->fts_path); 00320 } 00321 if (h != NULL) { 00322 gi->h = headerLink(h); 00323 (void)headerFree(h); 00324 h = NULL; 00325 /*@-noeffectuncon@*/ 00326 if (gi->stash != NULL) 00327 (void) (*gi->stash) (gi, gi->h); 00328 /*@=noeffectuncon@*/ 00329 } 00330 } 00331 00332 return rpmrc; 00333 } 00334 00335 const char * rpmgiEscapeSpaces(const char * s) 00336 { 00337 const char * se; 00338 const char * t; 00339 char * te; 00340 size_t nb = 0; 00341 00342 for (se = s; *se; se++) { 00343 if (isspace(*se)) 00344 nb++; 00345 nb++; 00346 } 00347 nb++; 00348 00349 t = te = xmalloc(nb); 00350 for (se = s; *se; se++) { 00351 if (isspace(*se)) 00352 *te++ = '\\'; 00353 *te++ = *se; 00354 } 00355 *te = '\0'; 00356 return t; 00357 } 00358 00365 static rpmRC rpmgiGlobArgv(rpmgi gi, /*@null@*/ ARGV_t argv) 00366 /*@globals internalState @*/ 00367 /*@modifies gi, internalState @*/ 00368 { 00369 const char * arg; 00370 rpmRC rpmrc = RPMRC_OK; 00371 int ac = 0; 00372 int xx; 00373 00374 /* XXX Expand globs only if requested or for gi specific tags */ 00375 if ((gi->flags & RPMGI_NOGLOB) 00376 || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK)) 00377 { 00378 if (argv != NULL) { 00379 while (argv[ac] != NULL) 00380 ac++; 00381 /*@-nullstate@*/ /* XXX argv is not NULL */ 00382 xx = argvAppend(&gi->argv, argv); 00383 /*@=nullstate@*/ 00384 } 00385 gi->argc = ac; 00386 return rpmrc; 00387 } 00388 00389 if (argv != NULL) 00390 while ((arg = *argv++) != NULL) { 00391 const char * t = rpmgiEscapeSpaces(arg); 00392 ARGV_t av = NULL; 00393 00394 xx = rpmGlob(t, &ac, &av); 00395 xx = argvAppend(&gi->argv, av); 00396 gi->argc += ac; 00397 av = argvFree(av); 00398 t = _free(t); 00399 ac = 0; 00400 } 00401 return rpmrc; 00402 } 00403 00409 static rpmRC rpmgiInitFilter(rpmgi gi) 00410 /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ 00411 /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ 00412 { 00413 rpmRC rpmrc = RPMRC_OK; 00414 ARGV_t av; 00415 int res = 0; 00416 00417 gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen); 00418 00419 if (_rpmgi_debug < 0) 00420 fprintf(stderr, "*** gi %p key %p[%d]\tmi %p\n", gi, gi->keyp, (int)gi->keylen, gi->mi); 00421 00422 if (gi->argv != NULL) 00423 for (av = (const char **) gi->argv; *av != NULL; av++) { 00424 if (gi->tag == RPMDBI_PACKAGES) { 00425 int tag = RPMTAG_NAME; 00426 const char * pat; 00427 char * a, * ae; 00428 00429 pat = a = xstrdup(*av); 00430 tag = RPMTAG_NAME; 00431 00432 /* Parse for "tag=pattern" args. */ 00433 if ((ae = strchr(a, '=')) != NULL) { 00434 *ae++ = '\0'; 00435 if (*a != '\0') { /* XXX HACK: permit '=foo' */ 00436 tag = tagValue(a); 00437 if (tag < 0) { 00438 rpmlog(RPMLOG_NOTICE, _("unknown tag: \"%s\"\n"), a); 00439 res = 1; 00440 } 00441 } 00442 pat = ae; 00443 } 00444 if (!res) { 00445 if (_rpmgi_debug < 0) 00446 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (int)(av - gi->argv), *av, tagName(tag), pat); 00447 res = rpmmiAddPattern(gi->mi, tag, RPMMIRE_DEFAULT, pat); 00448 } 00449 a = _free(a); 00450 } 00451 00452 if (res == 0) 00453 continue; 00454 00455 gi->mi = rpmmiFree(gi->mi); /* XXX odd side effect? */ 00456 rpmrc = RPMRC_FAIL; 00457 break; 00458 } 00459 00460 return rpmrc; 00461 } 00462 00463 /*@-mustmod@*/ 00464 static void rpmgiFini(void * _gi) 00465 /*@modifies _gi @*/ 00466 { 00467 rpmgi gi = _gi; 00468 int xx; 00469 00470 gi->hdrPath = _free(gi->hdrPath); 00471 (void)headerFree(gi->h); 00472 gi->h = NULL; 00473 00474 gi->argv = argvFree(gi->argv); 00475 00476 if (gi->ftsp != NULL) { 00477 xx = Fts_close(gi->ftsp); 00478 gi->ftsp = NULL; 00479 gi->fts = NULL; 00480 } 00481 if (gi->fd != NULL) { 00482 xx = Fclose(gi->fd); 00483 gi->fd = NULL; 00484 } 00485 gi->tsi = rpmtsiFree(gi->tsi); 00486 gi->mi = rpmmiFree(gi->mi); 00487 (void)rpmtsFree(gi->ts); 00488 gi->ts = NULL; 00489 } 00490 /*@=mustmod@*/ 00491 00492 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00493 rpmioPool _rpmgiPool; 00494 00495 static rpmgi rpmgiGetPool(/*@null@*/ rpmioPool pool) 00496 /*@globals _rpmgiPool, fileSystem, internalState @*/ 00497 /*@modifies pool, _rpmgiPool, fileSystem, internalState @*/ 00498 { 00499 rpmgi gi; 00500 00501 if (_rpmgiPool == NULL) { 00502 _rpmgiPool = rpmioNewPool("gi", sizeof(*gi), -1, _rpmgi_debug, 00503 NULL, NULL, rpmgiFini); 00504 pool = _rpmgiPool; 00505 } 00506 return (rpmgi) rpmioGetPool(pool, sizeof(*gi)); 00507 } 00508 00509 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen) 00510 { 00511 rpmgi gi = rpmgiGetPool(_rpmgiPool); 00512 00513 if (gi == NULL) /* XXX can't happen */ 00514 return NULL; 00515 00516 /*@-assignexpose -castexpose @*/ 00517 gi->ts = rpmtsLink(ts, "rpmgiNew"); 00518 /*@=assignexpose =castexpose @*/ 00519 gi->tsOrder = rpmcliInstallOrder; 00520 gi->tag = (rpmTag) tag; 00521 /*@-assignexpose@*/ 00522 gi->keyp = keyp; 00523 /*@=assignexpose@*/ 00524 gi->keylen = keylen; 00525 00526 gi->flags = 0; 00527 gi->active = 0; 00528 gi->i = -1; 00529 gi->hdrPath = NULL; 00530 gi->h = NULL; 00531 00532 gi->tsi = NULL; 00533 gi->mi = NULL; 00534 gi->fd = NULL; 00535 gi->argv = xcalloc(1, sizeof(*gi->argv)); 00536 gi->argc = 0; 00537 gi->ftsOpts = 0; 00538 gi->ftsp = NULL; 00539 gi->fts = NULL; 00540 gi->walkPathFilter = NULL; 00541 00542 gi = rpmgiLink(gi, "rpmgiNew"); 00543 00544 return gi; 00545 } 00546 00547 /*@observer@*/ /*@unchecked@*/ 00548 static const char * _query_hdlist_path = "/usr/share/comps/%{_arch}/hdlist"; 00549 00550 rpmRC rpmgiNext(/*@null@*/ rpmgi gi) 00551 { 00552 char hnum[32]; 00553 rpmRC rpmrc = RPMRC_NOTFOUND; 00554 int xx; 00555 00556 if (gi == NULL) 00557 return rpmrc; 00558 00559 if (_rpmgi_debug) 00560 fprintf(stderr, "--> %s(%p) tag %s\n", __FUNCTION__, gi, tagName(gi->tag)); 00561 00562 /* Free header from previous iteration. */ 00563 (void)headerFree(gi->h); 00564 gi->h = NULL; 00565 gi->hdrPath = _free(gi->hdrPath); 00566 hnum[0] = '\0'; 00567 00568 if (++gi->i >= 0) 00569 switch (gi->tag) { 00570 default: 00571 if (!gi->active) { 00572 nextkey: 00573 rpmrc = rpmgiLoadNextKey(gi); 00574 if (rpmrc != RPMRC_OK) 00575 goto enditer; 00576 rpmrc = rpmgiInitFilter(gi); 00577 if (rpmrc != RPMRC_OK || gi->mi == NULL) { 00578 gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ 00579 gi->i++; 00580 goto nextkey; 00581 } 00582 rpmrc = RPMRC_NOTFOUND; /* XXX hack */ 00583 gi->active = 1; 00584 } 00585 if (gi->mi != NULL) { /* XXX unnecessary */ 00586 Header h = rpmmiNext(gi->mi); 00587 if (h != NULL) { 00588 if (!(gi->flags & RPMGI_NOHEADER)) 00589 gi->h = headerLink(h); 00590 /* XXX use h->origin instead. */ 00591 sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi)); 00592 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); 00593 rpmrc = RPMRC_OK; 00594 /* XXX header reference held by iterator, so no headerFree */ 00595 } 00596 } 00597 if (rpmrc != RPMRC_OK) { 00598 gi->mi = rpmmiFree(gi->mi); 00599 goto nextkey; 00600 } 00601 break; 00602 case RPMDBI_PACKAGES: 00603 if (!gi->active) { 00604 rpmrc = rpmgiInitFilter(gi); 00605 if (rpmrc != RPMRC_OK) { 00606 gi->mi = rpmmiFree(gi->mi); /* XXX unnecessary */ 00607 goto enditer; 00608 } 00609 rpmrc = RPMRC_NOTFOUND; /* XXX hack */ 00610 gi->active = 1; 00611 } 00612 if (gi->mi != NULL) { /* XXX unnecessary */ 00613 Header h = rpmmiNext(gi->mi); 00614 if (h != NULL) { 00615 if (!(gi->flags & RPMGI_NOHEADER)) 00616 gi->h = headerLink(h); 00617 /* XXX use h->origin instead. */ 00618 sprintf(hnum, "%u", (unsigned)rpmmiInstance(gi->mi)); 00619 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL); 00620 rpmrc = RPMRC_OK; 00621 /* XXX header reference held by iterator, so no headerFree */ 00622 } 00623 } 00624 if (rpmrc != RPMRC_OK) { 00625 gi->mi = rpmmiFree(gi->mi); 00626 goto enditer; 00627 } 00628 break; 00629 case RPMDBI_REMOVED: 00630 case RPMDBI_ADDED: 00631 { rpmte p; 00632 int teType = 0; 00633 const char * teTypeString = NULL; 00634 00635 if (!gi->active) { 00636 gi->tsi = rpmtsiInit(gi->ts); 00637 gi->active = 1; 00638 } 00639 if ((p = rpmtsiNext(gi->tsi, teType)) != NULL) { 00640 Header h = rpmteHeader(p); 00641 if (h != NULL) 00642 if (!(gi->flags & RPMGI_NOHEADER)) { 00643 gi->h = headerLink(h); 00644 switch(rpmteType(p)) { 00645 case TR_ADDED: teTypeString = "+++"; /*@switchbreak@*/break; 00646 case TR_REMOVED: teTypeString = "---"; /*@switchbreak@*/break; 00647 } 00648 sprintf(hnum, "%u", (unsigned)gi->i); 00649 gi->hdrPath = rpmExpand("%s h# ", teTypeString, hnum, NULL); 00650 rpmrc = RPMRC_OK; 00651 (void)headerFree(h); 00652 h = NULL; 00653 } 00654 } 00655 if (rpmrc != RPMRC_OK) { 00656 gi->tsi = rpmtsiFree(gi->tsi); 00657 goto enditer; 00658 } 00659 } break; 00660 case RPMDBI_HDLIST: 00661 if (!gi->active) { 00662 const char * path = rpmExpand("%{?_query_hdlist_path}", NULL); 00663 if (path == NULL || *path == '\0') { 00664 path = _free(path); 00665 path = rpmExpand(_query_hdlist_path, NULL); 00666 } 00667 gi->fd = rpmgiOpen(path, "rm%{?_rpmgio}"); 00668 gi->active = 1; 00669 path = _free(path); 00670 } 00671 if (gi->fd != NULL) { 00672 Header h = NULL; 00673 const char item[] = "Header"; 00674 const char * msg = NULL; 00675 /*@+voidabstract@*/ 00676 rpmrc = rpmpkgRead(item, gi->fd, &h, &msg); 00677 /*@=voidabstract@*/ 00678 switch(rpmrc) { 00679 default: 00680 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", "rpmpkgRead", item, msg); 00681 case RPMRC_NOTFOUND: 00682 h = NULL; 00683 case RPMRC_OK: 00684 break; 00685 } 00686 msg = _free(msg); 00687 if (h != NULL) { 00688 if (!(gi->flags & RPMGI_NOHEADER)) 00689 gi->h = headerLink(h); 00690 sprintf(hnum, "%u", (unsigned)gi->i); 00691 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL); 00692 rpmrc = RPMRC_OK; 00693 (void)headerFree(h); 00694 h = NULL; 00695 } 00696 } 00697 if (rpmrc != RPMRC_OK) { 00698 if (gi->fd != NULL) (void) Fclose(gi->fd); 00699 gi->fd = NULL; 00700 goto enditer; 00701 } 00702 break; 00703 case RPMDBI_ARGLIST: 00704 /* XXX gi->active initialize? */ 00705 if (_rpmgi_debug < 0) 00706 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]); 00707 /* Read next header, lazily expanding manifests as found. */ 00708 rpmrc = rpmgiLoadReadHeader(gi); 00709 00710 if (rpmrc != RPMRC_OK) /* XXX check this */ 00711 goto enditer; 00712 00713 gi->hdrPath = xstrdup(gi->argv[gi->i]); 00714 break; 00715 case RPMDBI_FTSWALK: 00716 if (gi->argv == NULL || gi->argv[0] == NULL) /* HACK */ 00717 goto enditer; 00718 00719 if (!gi->active) { 00720 gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL); 00721 /* XXX NULL with open(2)/malloc(3) errno set */ 00722 gi->active = 1; 00723 } 00724 00725 /* Read next header, lazily walking file tree. */ 00726 rpmrc = rpmgiWalkReadHeader(gi); 00727 00728 if (rpmrc != RPMRC_OK) { 00729 xx = Fts_close(gi->ftsp); 00730 gi->ftsp = NULL; 00731 goto enditer; 00732 } 00733 00734 if (gi->fts != NULL) 00735 gi->hdrPath = xstrdup(gi->fts->fts_path); 00736 break; 00737 } 00738 00739 if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) { 00740 /* XXX rpmgi hack: Save header in transaction element. */ 00741 if (gi->flags & RPMGI_ERASING) { 00742 uint32_t hdrNum = headerGetInstance(gi->h); 00743 xx = rpmtsAddEraseElement(gi->ts, gi->h, hdrNum); 00744 } else 00745 xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL); 00746 } 00747 goto exit; 00748 00749 enditer: 00750 if (gi->flags & RPMGI_TSORDER) { 00751 rpmts ts = gi->ts; 00752 00753 /* Block access to indices used for depsolving. */ 00754 if (!(gi->flags & RPMGI_ERASING)) { 00755 (void) rpmtsSetGoal(ts, TSM_INSTALL); 00756 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMDBI_DEPENDS); 00757 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_BASENAMES); 00758 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), -RPMTAG_PROVIDENAME); 00759 } else { 00760 (void) rpmtsSetGoal(ts, TSM_ERASE); 00761 } 00762 00763 /* XXX query/verify will need the glop added to a buffer instead. */ 00764 xx = rpmcliInstallCheck(ts); 00765 xx = rpmcliInstallSuggests(ts); 00766 00767 /* Permit access to indices used for depsolving. */ 00768 if (!(gi->flags & RPMGI_ERASING)) { 00769 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_PROVIDENAME); 00770 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMTAG_BASENAMES); 00771 xx = rpmdbBlockDBI(rpmtsGetRdb(ts), RPMDBI_DEPENDS); 00772 } 00773 00774 /* XXX Display dependency loops with rpm -qvT. */ 00775 if (rpmIsVerbose()) 00776 (void) rpmtsSetDFlags(ts, (rpmtsDFlags(ts) | RPMDEPS_FLAG_DEPLOOPS)); 00777 00778 xx = (*gi->tsOrder) (ts); 00779 00780 /* XXX hackery alert! */ 00781 gi->tag = (!(gi->flags & RPMGI_ERASING) ? RPMDBI_ADDED : RPMDBI_REMOVED); 00782 gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER); 00783 00784 } 00785 00786 (void)headerFree(gi->h); 00787 gi->h = NULL; 00788 gi->hdrPath = _free(gi->hdrPath); 00789 gi->i = -1; 00790 gi->active = 0; 00791 00792 exit: 00793 if (_rpmgi_debug) 00794 fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, gi, rpmrc); 00795 return rpmrc; 00796 } 00797 00798 rpmgiFlags rpmgiGetFlags(rpmgi gi) 00799 { 00800 return (gi != NULL ? gi->flags : RPMGI_NONE); 00801 } 00802 00803 const char * rpmgiHdrPath(rpmgi gi) 00804 { 00805 return (gi != NULL ? gi->hdrPath : NULL); 00806 } 00807 00808 Header rpmgiHeader(rpmgi gi) 00809 { 00810 /*@-compdef -refcounttrans -retexpose -usereleased@*/ 00811 return (gi != NULL ? gi->h : NULL); 00812 /*@=compdef =refcounttrans =retexpose =usereleased@*/ 00813 } 00814 00815 rpmts rpmgiTs(rpmgi gi) 00816 { 00817 /*@-compdef -refcounttrans -retexpose -usereleased@*/ 00818 return (gi != NULL ? gi->ts : NULL); 00819 /*@=compdef =refcounttrans =retexpose =usereleased@*/ 00820 } 00821 00822 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags) 00823 { 00824 if (gi == NULL) return RPMRC_FAIL; 00825 gi->ftsOpts = ftsOpts; 00826 gi->flags = flags; 00827 return rpmgiGlobArgv(gi, argv); 00828 } 00829 00830 /*@=modfilesys@*/