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 
00025 /*@unchecked@*/
00026 int _rpmgi_debug = 0;
00027 
00028 /*@unchecked@*/
00029 rpmgiFlags giFlags = RPMGI_NONE;
00030 
00031 /*@unchecked@*/
00032 static int indent = 2;
00033 
00034 /*@unchecked@*/ /*@observer@*/
00035 static const char * ftsInfoStrings[] = {
00036     "UNKNOWN",
00037     "D",
00038     "DC",
00039     "DEFAULT",
00040     "DNR",
00041     "DOT",
00042     "DP",
00043     "ERR",
00044     "F",
00045     "INIT",
00046     "NS",
00047     "NSOK",
00048     "SL",
00049     "SLNONE",
00050     "W",
00051 };
00052 
00053 /*@observer@*/
00054 static const char * ftsInfoStr(int fts_info)
00055         /*@*/
00056 {
00057 
00058     if (!(fts_info >= 1 && fts_info <= 14))
00059         fts_info = 0;
00060 /*@-compmempass@*/
00061     return ftsInfoStrings[ fts_info ];
00062 /*@=compmempass@*/
00063 }
00064 
00072 /*@null@*/
00073 static FD_t rpmgiOpen(const char * path, const char * fmode)
00074         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00075         /*@modifies rpmGlobalMacroContext, h_errno, internalState @*/
00076 {
00077     const char * fn = rpmExpand(path, NULL);
00078     FD_t fd = Fopen(fn, fmode);
00079 
00080     if (fd == NULL || Ferror(fd)) {
00081         rpmError(RPMERR_OPEN, _("open of %s failed: %s\n"), fn, Fstrerror(fd));
00082         if (fd != NULL) (void) Fclose(fd);
00083         fd = NULL;
00084     }
00085     fn = _free(fn);
00086 
00087     return fd;
00088 }
00089 
00096 static rpmRC rpmgiLoadManifest(rpmgi gi, const char * path)
00097         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00098         /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
00099 {
00100     FD_t fd = rpmgiOpen(path, "r.ufdio");
00101     rpmRC rpmrc = RPMRC_FAIL;
00102 
00103     if (fd != NULL) {
00104         rpmrc = rpmReadPackageManifest(fd, &gi->argc, &gi->argv);
00105         (void) Fclose(fd);
00106     }
00107     return rpmrc;
00108 }
00109 
00116 /*@null@*/
00117 static Header rpmgiReadHeader(rpmgi gi, const char * path)
00118         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00119         /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
00120 {
00121     FD_t fd = rpmgiOpen(path, "r.ufdio");
00122     Header h = NULL;
00123 
00124     if (fd != NULL) {
00125         /* XXX what if path needs expansion? */
00126         rpmRC rpmrc = rpmReadPackageFile(gi->ts, fd, path, &h);
00127 
00128         (void) Fclose(fd);
00129 
00130         switch (rpmrc) {
00131         case RPMRC_NOTFOUND:
00132             /* XXX Read a package manifest. Restart ftswalk on success. */
00133         case RPMRC_FAIL:
00134         default:
00135             h = headerFree(h);
00136             break;
00137         case RPMRC_NOTTRUSTED:
00138         case RPMRC_NOKEY:
00139         case RPMRC_OK:
00140             break;
00141         }
00142     }
00143 
00144     return h;
00145 }
00146 
00155 /*@null@*/
00156 static rpmRC rpmgiLoadReadHeader(rpmgi gi)
00157         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00158         /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
00159 {
00160     rpmRC rpmrc = RPMRC_NOTFOUND;
00161     Header h = NULL;
00162 
00163     if (gi->argv != NULL && gi->argv[gi->i] != NULL)
00164     do {
00165         const char * fn;        /* XXX gi->hdrPath? */
00166 
00167         fn = gi->argv[gi->i];
00168         if (!(gi->flags & RPMGI_NOHEADER)) {
00169             h = rpmgiReadHeader(gi, fn);
00170             if (h != NULL)
00171                 rpmrc = RPMRC_OK;
00172         } else
00173             rpmrc = RPMRC_OK;
00174 
00175         if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST)
00176             break;
00177         if (errno == ENOENT) {
00178             break;
00179         }
00180 
00181         /* Not a header, so try for a manifest. */
00182         gi->argv[gi->i] = NULL;         /* Mark the insertion point */
00183         rpmrc = rpmgiLoadManifest(gi, fn);
00184         if (rpmrc != RPMRC_OK) {
00185             gi->argv[gi->i] = fn;       /* Manifest failed, restore fn */
00186             break;
00187         }
00188         fn = _free(fn);
00189         rpmrc = RPMRC_NOTFOUND;
00190     } while (1);
00191 
00192     if (rpmrc == RPMRC_OK && h != NULL)
00193         gi->h = headerLink(h);
00194     h = headerFree(h);
00195 
00196     return rpmrc;
00197 }
00198 
00204 /*@null@*/
00205 static rpmRC rpmgiWalkPathFilter(rpmgi gi)
00206         /*@*/
00207 {
00208     FTSENT * fts = gi->fts;
00209     rpmRC rpmrc = RPMRC_NOTFOUND;
00210     const char * s;
00211 
00212 if (_rpmgi_debug < 0)
00213 rpmMessage(RPMMESS_DEBUG, "FTS_%s\t%*s %s%s\n", ftsInfoStr(fts->fts_info),
00214                 indent * (fts->fts_level < 0 ? 0 : fts->fts_level), "",
00215                 fts->fts_name,
00216         ((fts->fts_info == FTS_D || fts->fts_info == FTS_DP) ? "/" : ""));
00217 
00218     switch (fts->fts_info) {
00219     case FTS_D:         /* preorder directory */
00220         break;
00221     case FTS_DP:        /* postorder directory */
00222         break;
00223     case FTS_F:         /* regular file */
00224         /* Ignore all but *.rpm files. */
00225         s = fts->fts_name + fts->fts_namelen + 1 - sizeof(".rpm");
00226         if (strcmp(s, ".rpm"))
00227             break;
00228         rpmrc = RPMRC_OK;
00229         break;
00230     case FTS_NS:        /* stat(2) failed */
00231     case FTS_DNR:       /* unreadable directory */
00232     case FTS_ERR:       /* error; errno is set */
00233         break;
00234     case FTS_DC:        /* directory that causes cycles */
00235     case FTS_DEFAULT:   /* none of the above */
00236     case FTS_DOT:       /* dot or dot-dot */
00237     case FTS_INIT:      /* initialized only */
00238     case FTS_NSOK:      /* no stat(2) requested */
00239     case FTS_SL:        /* symbolic link */
00240     case FTS_SLNONE:    /* symbolic link without target */
00241     case FTS_W:         /* whiteout object */
00242     default:
00243         break;
00244     }
00245     return rpmrc;
00246 }
00247 
00253 /*@null@*/
00254 static rpmRC rpmgiWalkReadHeader(rpmgi gi)
00255         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00256         /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
00257 {
00258     rpmRC rpmrc = RPMRC_NOTFOUND;
00259 
00260     if (gi->ftsp != NULL)
00261     while ((gi->fts = Fts_read(gi->ftsp)) != NULL) {
00262         rpmrc = rpmgiWalkPathFilter(gi);
00263         if (rpmrc == RPMRC_OK)
00264             break;
00265     }
00266 
00267     if (rpmrc == RPMRC_OK) {
00268         Header h = NULL;
00269         if (!(gi->flags & RPMGI_NOHEADER)) {
00270             /* XXX rpmrc = rpmgiLoadReadHeader(gi); */
00271             if (gi->fts != NULL)        /* XXX can't happen */
00272                 h = rpmgiReadHeader(gi, gi->fts->fts_path);
00273         }
00274         if (h != NULL)
00275             gi->h = headerLink(h);
00276         h = headerFree(h);
00277     }
00278 
00279     return rpmrc;
00280 }
00281 
00288 static rpmRC rpmgiGlobArgv(rpmgi gi, /*@null@*/ ARGV_t argv)
00289         /*@globals internalState @*/
00290         /*@modifies gi, internalState @*/
00291 {
00292     const char * arg;
00293     rpmRC rpmrc = RPMRC_OK;
00294     int ac = 0;
00295     int xx;
00296 
00297     /* XXX Expand globs only if requested or for gi specific tags */
00298     if ((gi->flags & RPMGI_NOGLOB)
00299      || !(gi->tag == RPMDBI_HDLIST || gi->tag == RPMDBI_ARGLIST || gi->tag == RPMDBI_FTSWALK))
00300     {
00301         if (argv != NULL) {
00302             while (argv[ac] != NULL)
00303                 ac++;
00304 /*@-nullstate@*/ /* XXX argv is not NULL */
00305             xx = argvAppend(&gi->argv, argv);
00306 /*@=nullstate@*/
00307         }
00308         gi->argc = ac;
00309         return rpmrc;
00310     }
00311 
00312     if (argv != NULL)
00313     while ((arg = *argv++) != NULL) {
00314         ARGV_t av = NULL;
00315 
00316         xx = rpmGlob(arg, &ac, &av);
00317         xx = argvAppend(&gi->argv, av);
00318         gi->argc += ac;
00319         av = argvFree(av);
00320         ac = 0;
00321     }
00322     return rpmrc;
00323 }
00324 
00330 static rpmRC rpmgiInitFilter(rpmgi gi)
00331         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00332         /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/
00333 {
00334     rpmRC rpmrc = RPMRC_OK;
00335     ARGV_t av;
00336     int res = 0;
00337 
00338     gi->mi = rpmtsInitIterator(gi->ts, gi->tag, gi->keyp, gi->keylen);
00339 
00340 if (_rpmgi_debug < 0)
00341 fprintf(stderr, "*** gi %p\tmi %p\n", gi, gi->mi);
00342 
00343     if (gi->argv != NULL)
00344     for (av = (const char **) gi->argv; *av != NULL; av++) {
00345         int tag = RPMTAG_NAME;
00346         const char * pat;
00347         char * a, * ae;
00348 
00349         pat = a = xstrdup(*av);
00350         tag = RPMTAG_NAME;
00351 
00352         /* Parse for "tag=pattern" args. */
00353 /*@-branchstate@*/
00354         if ((ae = strchr(a, '=')) != NULL) {
00355             *ae++ = '\0';
00356             tag = tagValue(a);
00357             if (tag < 0) {
00358                 rpmError(RPMERR_QUERYINFO, _("unknown tag: \"%s\"\n"), a);
00359                 res = 1;
00360             }
00361             pat = ae;
00362         }
00363 /*@=branchstate@*/
00364 
00365         if (!res) {
00366 if (_rpmgi_debug  < 0)
00367 fprintf(stderr, "\tav %p[%d]: \"%s\" -> %s ~= \"%s\"\n", gi->argv, (av - gi->argv), *av, tagName(tag), pat);
00368             res = rpmdbSetIteratorRE(gi->mi, tag, RPMMIRE_DEFAULT, pat);
00369         }
00370         a = _free(a);
00371 
00372         if (res == 0)
00373             continue;
00374 
00375         gi->mi = rpmdbFreeIterator(gi->mi);     /* XXX odd side effect? */
00376         rpmrc = RPMRC_FAIL;
00377         break;
00378     }
00379 
00380     return rpmrc;
00381 }
00382 
00383 rpmgi XrpmgiUnlink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00384 {
00385     if (gi == NULL) return NULL;
00386 
00387 if (_rpmgi_debug && msg != NULL)
00388 fprintf(stderr, "--> gi %p -- %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00389 
00390     gi->nrefs--;
00391     return NULL;
00392 }
00393 
00394 rpmgi XrpmgiLink(rpmgi gi, const char * msg, const char * fn, unsigned ln)
00395 {
00396     if (gi == NULL) return NULL;
00397     gi->nrefs++;
00398 
00399 if (_rpmgi_debug && msg != NULL)
00400 fprintf(stderr, "--> gi %p ++ %d %s at %s:%u\n", gi, gi->nrefs, msg, fn, ln);
00401 
00402     /*@-refcounttrans@*/ return gi; /*@=refcounttrans@*/
00403 }
00404 
00405 rpmgi rpmgiFree(rpmgi gi)
00406 {
00407     if (gi == NULL)
00408         return NULL;
00409 
00410     if (gi->nrefs > 1)
00411         return rpmgiUnlink(gi, __FUNCTION__);
00412 
00413     (void) rpmgiUnlink(gi, __FUNCTION__);
00414 
00415 /*@-usereleased@*/
00416 
00417     gi->hdrPath = _free(gi->hdrPath);
00418     gi->h = headerFree(gi->h);
00419 
00420     gi->argv = argvFree(gi->argv);
00421 
00422     if (gi->ftsp != NULL) {
00423         int xx;
00424         xx = Fts_close(gi->ftsp);
00425         gi->ftsp = NULL;
00426         gi->fts = NULL;
00427     }
00428     if (gi->fd != NULL) {
00429         (void) Fclose(gi->fd);
00430         gi->fd = NULL;
00431     }
00432     gi->tsi = rpmtsiFree(gi->tsi);
00433     gi->mi = rpmdbFreeIterator(gi->mi);
00434     gi->ts = rpmtsFree(gi->ts);
00435 
00436     memset(gi, 0, sizeof(*gi));         /* XXX trash and burn */
00437 /*@-refcounttrans@*/
00438     gi = _free(gi);
00439 /*@=refcounttrans@*/
00440 /*@=usereleased@*/
00441     return NULL;
00442 }
00443 
00444 rpmgi rpmgiNew(rpmts ts, int tag, const void * keyp, size_t keylen)
00445 {
00446     rpmgi gi = xcalloc(1, sizeof(*gi));
00447 
00448     if (gi == NULL)
00449         return NULL;
00450 
00451     gi->ts = rpmtsLink(ts, __FUNCTION__);
00452     gi->tag = tag;
00453 /*@-assignexpose@*/
00454     gi->keyp = keyp;
00455 /*@=assignexpose@*/
00456     gi->keylen = keylen;
00457 
00458     gi->flags = 0;
00459     gi->active = 0;
00460     gi->i = -1;
00461     gi->hdrPath = NULL;
00462     gi->h = NULL;
00463 
00464     gi->tsi = NULL;
00465     gi->mi = NULL;
00466     gi->fd = NULL;
00467     gi->argv = xcalloc(1, sizeof(*gi->argv));
00468     gi->argc = 0;
00469     gi->ftsOpts = 0;
00470     gi->ftsp = NULL;
00471     gi->fts = NULL;
00472 
00473     gi = rpmgiLink(gi, __FUNCTION__);
00474 
00475     return gi;
00476 }
00477 
00478 rpmRC rpmgiNext(/*@null@*/ rpmgi gi)
00479 {
00480     char hnum[32];
00481     rpmRC rpmrc = RPMRC_NOTFOUND;
00482     int xx;
00483 
00484     if (gi == NULL)
00485         return rpmrc;
00486 
00487     /* Free header from previous iteration. */
00488     gi->h = headerFree(gi->h);
00489     gi->hdrPath = _free(gi->hdrPath);
00490     hnum[0] = '\0';
00491 
00492 /*@-branchstate@*/
00493     if (++gi->i >= 0)
00494     switch (gi->tag) {
00495     default:
00496     case RPMDBI_PACKAGES:
00497         if (!gi->active) {
00498             rpmrc = rpmgiInitFilter(gi);
00499             if (rpmrc != RPMRC_OK) {
00500                 gi->mi = rpmdbFreeIterator(gi->mi);     /* XXX unnecessary */
00501                 goto enditer;
00502             }
00503             rpmrc = RPMRC_NOTFOUND;     /* XXX hack */
00504             gi->active = 1;
00505         }
00506         if (gi->mi != NULL) {   /* XXX unnecessary */
00507             Header h = rpmdbNextIterator(gi->mi);
00508             if (h != NULL) {
00509                 if (!(gi->flags & RPMGI_NOHEADER))
00510                     gi->h = headerLink(h);
00511                 sprintf(hnum, "%u", rpmdbGetIteratorOffset(gi->mi));
00512                 gi->hdrPath = rpmExpand("rpmdb h# ", hnum, NULL);
00513                 rpmrc = RPMRC_OK;
00514                 /* XXX header reference held by iterator, so no headerFree */
00515             }
00516         }
00517         if (rpmrc != RPMRC_OK) {
00518             gi->mi = rpmdbFreeIterator(gi->mi);
00519             goto enditer;
00520         }
00521         break;
00522     case RPMDBI_ADDED:
00523     {   rpmte p;
00524 
00525         if (!gi->active) {
00526             gi->tsi = rpmtsiInit(gi->ts);
00527             gi->active = 1;
00528         }
00529         if ((p = rpmtsiNext(gi->tsi, TR_ADDED)) != NULL) {
00530             Header h = rpmteHeader(p);
00531             if (h != NULL)
00532                 if (!(gi->flags & RPMGI_NOHEADER)) {
00533                     gi->h = headerLink(h);
00534                 sprintf(hnum, "%u", (unsigned)gi->i);
00535                 gi->hdrPath = rpmExpand("added h# ", hnum, NULL);
00536                 rpmrc = RPMRC_OK;
00537                 h = headerFree(h);
00538             }
00539         }
00540         if (rpmrc != RPMRC_OK) {
00541             gi->tsi = rpmtsiFree(gi->tsi);
00542             goto enditer;
00543         }
00544     }   break;
00545     case RPMDBI_HDLIST:
00546         if (!gi->active) {
00547             const char * path = "/usr/share/comps/%{_arch}/hdlist";
00548             gi->fd = rpmgiOpen(path, "r.ufdio");
00549             gi->active = 1;
00550         }
00551         if (gi->fd != NULL) {
00552             Header h = headerRead(gi->fd, HEADER_MAGIC_YES);
00553             if (h != NULL) {
00554                 if (!(gi->flags & RPMGI_NOHEADER))
00555                     gi->h = headerLink(h);
00556                 sprintf(hnum, "%u", (unsigned)gi->i);
00557                 gi->hdrPath = rpmExpand("hdlist h# ", hnum, NULL);
00558                 rpmrc = RPMRC_OK;
00559                 h = headerFree(h);
00560             }
00561         }
00562         if (rpmrc != RPMRC_OK) {
00563             if (gi->fd != NULL) (void) Fclose(gi->fd);
00564             gi->fd = NULL;
00565             goto enditer;
00566         }
00567         break;
00568     case RPMDBI_ARGLIST:
00569         /* XXX gi->active initialize? */
00570 if (_rpmgi_debug  < 0)
00571 fprintf(stderr, "*** gi %p\t%p[%d]: %s\n", gi, gi->argv, gi->i, gi->argv[gi->i]);
00572         /* Read next header, lazily expanding manifests as found. */
00573         rpmrc = rpmgiLoadReadHeader(gi);
00574 
00575         if (rpmrc != RPMRC_OK)  /* XXX check this */
00576             goto enditer;
00577 
00578         gi->hdrPath = xstrdup(gi->argv[gi->i]);
00579         break;
00580     case RPMDBI_FTSWALK:
00581         if (gi->argv == NULL)           /* HACK */
00582             goto enditer;
00583 
00584         if (!gi->active) {
00585             gi->ftsp = Fts_open((char *const *)gi->argv, gi->ftsOpts, NULL);
00586             /* XXX NULL with open(2)/malloc(3) errno set */
00587             gi->active = 1;
00588         }
00589 
00590         /* Read next header, lazily walking file tree. */
00591         rpmrc = rpmgiWalkReadHeader(gi);
00592 
00593         if (rpmrc != RPMRC_OK) {
00594             xx = Fts_close(gi->ftsp);
00595             gi->ftsp = NULL;
00596             goto enditer;
00597         }
00598 
00599         if (gi->fts != NULL)
00600             gi->hdrPath = xstrdup(gi->fts->fts_path);
00601         break;
00602     }
00603 /*@=branchstate@*/
00604 
00605     if ((gi->flags & RPMGI_TSADD) && gi->h != NULL) {
00606         /* XXX rpmgi hack: Save header in transaction element. */
00607         xx = rpmtsAddInstallElement(gi->ts, gi->h, (fnpyKey)gi->hdrPath, 2, NULL);
00608     }
00609 
00610     return rpmrc;
00611 
00612 enditer:
00613     if (gi->flags & RPMGI_TSORDER) {
00614         rpmts ts = gi->ts;
00615         rpmps ps;
00616         int i;
00617 
00618         /* XXX installed database needs close here. */
00619         xx = rpmtsCloseDB(ts);
00620         ts->dbmode = -1;        /* XXX disable lazy opens */
00621 
00622         xx = rpmtsCheck(ts);
00623 
00624         /* XXX query/verify will need the glop added to a buffer instead. */
00625         ps = rpmtsProblems(ts);
00626         if (rpmpsNumProblems(ps) > 0) {
00627             /* XXX rpminstall will need RPMMESS_ERROR */
00628             rpmMessage(RPMMESS_VERBOSE, _("Failed dependencies:\n"));
00629             if (rpmIsVerbose())
00630                 rpmpsPrint(NULL, ps);
00631 
00632 /*@-branchstate@*/
00633             if (ts->suggests != NULL && ts->nsuggests > 0) {
00634                 rpmMessage(RPMMESS_VERBOSE, _("    Suggested resolutions:\n"));
00635                 for (i = 0; i < ts->nsuggests; i++) {
00636                     const char * str = ts->suggests[i];
00637 
00638                     if (str == NULL)
00639                         break;
00640 
00641                     rpmMessage(RPMMESS_VERBOSE, "\t%s\n", str);
00642                 
00643                     ts->suggests[i] = NULL;
00644                     str = _free(str);
00645                 }
00646                 ts->suggests = _free(ts->suggests);
00647             }
00648 /*@=branchstate@*/
00649 
00650         }
00651         ps = rpmpsFree(ps);
00652         ts->probs = rpmpsFree(ts->probs);       /* XXX hackery */
00653 
00654         xx = rpmtsOrder(ts);
00655 
00656         gi->tag = RPMDBI_ADDED;                 /* XXX hackery */
00657         gi->flags &= ~(RPMGI_TSADD|RPMGI_TSORDER);
00658 
00659     }
00660 
00661     gi->h = headerFree(gi->h);
00662     gi->hdrPath = _free(gi->hdrPath);
00663     gi->i = -1;
00664     gi->active = 0;
00665     return rpmrc;
00666 }
00667 
00668 const char * rpmgiHdrPath(rpmgi gi)
00669 {
00670     return (gi != NULL ? gi->hdrPath : NULL);
00671 }
00672 
00673 Header rpmgiHeader(rpmgi gi)
00674 {
00675 /*@-compdef -refcounttrans -retexpose -usereleased@*/
00676     return (gi != NULL ? gi->h : NULL);
00677 /*@=compdef =refcounttrans =retexpose =usereleased@*/
00678 }
00679 
00680 rpmts rpmgiTs(rpmgi gi)
00681 {
00682 /*@-compdef -refcounttrans -retexpose -usereleased@*/
00683     return (gi != NULL ? gi->ts : NULL);
00684 /*@=compdef =refcounttrans =retexpose =usereleased@*/
00685 }
00686 
00687 rpmRC rpmgiSetArgs(rpmgi gi, ARGV_t argv, int ftsOpts, rpmgiFlags flags)
00688 {
00689     gi->ftsOpts = ftsOpts;
00690     gi->flags = flags;
00691     return rpmgiGlobArgv(gi, argv);
00692 }
00693 
00694 /*@=modfilesys@*/

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2