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

Generated on Sat Oct 1 16:24:10 2011 for rpm by  doxygen 1.4.4