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