rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmgi.c
Go to the documentation of this file.

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