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