Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

lib/rpmgi.c

Go to the documentation of this file.
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@*/

Generated on Sun Aug 18 10:48:16 2013 for rpm by  doxygen 1.4.4