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

Generated on Fri Aug 11 12:48:13 2006 for rpm by  doxygen 1.4.7