lib/query.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #ifndef PATH_MAX
00009 /*@-incondefs@*/        /* FIX: long int? */
00010 # define PATH_MAX 255
00011 /*@=incondefs@*/
00012 #endif
00013 
00014 #include <rpmcli.h>
00015 
00016 #include "rpmdb.h"
00017 #include "rpmfi.h"
00018 
00019 #define _RPMGI_INTERNAL /* XXX for gi->flags */
00020 #include "rpmgi.h"
00021 #include "rpmts.h"
00022 
00023 #include "manifest.h"
00024 #include "misc.h"       /* XXX for rpmGlob() */
00025 
00026 #include "debug.h"
00027 
00028 /*@access rpmgi @*/
00029 
00032 static void printFileInfo(char * te, const char * name,
00033                           unsigned int size, unsigned short mode,
00034                           unsigned int mtime,
00035                           unsigned short rdev, unsigned int nlink,
00036                           const char * owner, const char * group,
00037                           const char * linkto)
00038         /*@modifies *te @*/
00039 {
00040     char sizefield[15];
00041     char ownerfield[8+1], groupfield[8+1];
00042     char timefield[100];
00043     time_t when = mtime;  /* important if sizeof(int_32) ! sizeof(time_t) */
00044     struct tm * tm;
00045     static time_t now;
00046     static struct tm nowtm;
00047     const char * namefield = name;
00048     char * perms = rpmPermsString(mode);
00049 
00050     /* On first call, grab snapshot of now */
00051     if (now == 0) {
00052         now = time(NULL);
00053         tm = localtime(&now);
00054 /*@-boundsread@*/
00055         if (tm) nowtm = *tm;    /* structure assignment */
00056 /*@=boundsread@*/
00057     }
00058 
00059     strncpy(ownerfield, owner, sizeof(ownerfield));
00060     ownerfield[sizeof(ownerfield)-1] = '\0';
00061 
00062     strncpy(groupfield, group, sizeof(groupfield));
00063     groupfield[sizeof(groupfield)-1] = '\0';
00064 
00065     /* this is normally right */
00066     sprintf(sizefield, "%12u", size);
00067 
00068     /* this knows too much about dev_t */
00069 
00070     if (S_ISLNK(mode)) {
00071         char *nf = alloca(strlen(name) + sizeof(" -> ") + strlen(linkto));
00072         sprintf(nf, "%s -> %s", name, linkto);
00073         namefield = nf;
00074     } else if (S_ISCHR(mode)) {
00075         perms[0] = 'c';
00076         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00077                         ((unsigned)rdev & 0xff));
00078     } else if (S_ISBLK(mode)) {
00079         perms[0] = 'b';
00080         sprintf(sizefield, "%3u, %3u", ((unsigned)(rdev >> 8) & 0xff),
00081                         ((unsigned)rdev & 0xff));
00082     }
00083 
00084     /* Convert file mtime to display format */
00085     tm = localtime(&when);
00086     timefield[0] = '\0';
00087     if (tm != NULL)
00088     {   const char *fmt;
00089         if (now > when + 6L * 30L * 24L * 60L * 60L ||  /* Old. */
00090             now < when - 60L * 60L)                     /* In the future.  */
00091         {
00092         /* The file is fairly old or in the future.
00093          * POSIX says the cutoff is 6 months old;
00094          * approximate this by 6*30 days.
00095          * Allow a 1 hour slop factor for what is considered "the future",
00096          * to allow for NFS server/client clock disagreement.
00097          * Show the year instead of the time of day.
00098          */        
00099             fmt = "%b %e  %Y";
00100         } else {
00101             fmt = "%b %e %H:%M";
00102         }
00103         (void)strftime(timefield, sizeof(timefield) - 1, fmt, tm);
00104     }
00105 
00106     sprintf(te, "%s %4d %-8s%-8s %10s %s %s", perms,
00107         (int)nlink, ownerfield, groupfield, sizefield, timefield, namefield);
00108     perms = _free(perms);
00109 }
00110 
00113 static inline /*@null@*/ const char * queryHeader(Header h, const char * qfmt)
00114         /*@*/
00115 {
00116     const char * errstr = "(unkown error)";
00117     const char * str;
00118 
00119 /*@-modobserver@*/
00120     str = headerSprintf(h, qfmt, rpmTagTable, rpmHeaderFormats, &errstr);
00121 /*@=modobserver@*/
00122     if (str == NULL)
00123         rpmError(RPMERR_QFMT, _("incorrect format: %s\n"), errstr);
00124     return str;
00125 }
00126 
00129 static void flushBuffer(char ** tp, char ** tep, int nonewline)
00130         /*@ modifies *tp, *tep @*/
00131 {
00132     char *t, *te;
00133 
00134     t = *tp;
00135     te = *tep;
00136     if (te > t) {
00137         if (!nonewline) {
00138             *te++ = '\n';
00139             *te = '\0';
00140         }
00141         rpmMessage(RPMMESS_NORMAL, "%s", t);
00142         te = t;
00143         *t = '\0';
00144     }
00145     *tp = t;
00146     *tep = te;
00147 }
00148 
00149 int showQueryPackage(QVA_t qva, rpmts ts, Header h)
00150 {
00151     int scareMem = 0;
00152     rpmfi fi = NULL;
00153     char * t, * te;
00154     char * prefix = NULL;
00155     int rc = 0;         /* XXX FIXME: need real return code */
00156     int i;
00157 
00158     te = t = xmalloc(BUFSIZ);
00159 /*@-boundswrite@*/
00160     *te = '\0';
00161 /*@=boundswrite@*/
00162 
00163     if (qva->qva_queryFormat != NULL) {
00164         const char * str = queryHeader(h, qva->qva_queryFormat);
00165         /*@-branchstate@*/
00166         if (str) {
00167             size_t tb = (te - t);
00168             size_t sb = strlen(str);
00169 
00170             if (sb >= (BUFSIZ - tb)) {
00171                 t = xrealloc(t, BUFSIZ+sb);
00172                 te = t + tb;
00173             }
00174 /*@-boundswrite@*/
00175             /*@-usereleased@*/
00176             te = stpcpy(te, str);
00177             /*@=usereleased@*/
00178 /*@=boundswrite@*/
00179             str = _free(str);
00180             flushBuffer(&t, &te, 1);
00181         }
00182         /*@=branchstate@*/
00183     }
00184 
00185     if (!(qva->qva_flags & QUERY_FOR_LIST))
00186         goto exit;
00187 
00188     fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00189     if (rpmfiFC(fi) <= 0) {
00190 /*@-boundswrite@*/
00191         te = stpcpy(te, _("(contains no files)"));
00192 /*@=boundswrite@*/
00193         goto exit;
00194     }
00195 
00196     fi = rpmfiInit(fi, 0);
00197     if (fi != NULL)
00198     while ((i = rpmfiNext(fi)) >= 0) {
00199         rpmfileAttrs fflags;
00200         unsigned short fmode;
00201         unsigned short frdev;
00202         unsigned int fmtime;
00203         rpmfileState fstate;
00204         size_t fsize;
00205         const char * fn;
00206         char fmd5[32+1];
00207         const char * fuser;
00208         const char * fgroup;
00209         const char * flink;
00210         int_32 fnlink;
00211 
00212         fflags = rpmfiFFlags(fi);
00213         fmode = rpmfiFMode(fi);
00214         frdev = rpmfiFRdev(fi);
00215         fmtime = rpmfiFMtime(fi);
00216         fstate = rpmfiFState(fi);
00217         fsize = rpmfiFSize(fi);
00218         fn = rpmfiFN(fi);
00219 /*@-bounds@*/
00220         {   static char hex[] = "0123456789abcdef";
00221             const char * s = rpmfiMD5(fi);
00222             char * p = fmd5;
00223             int j;
00224             for (j = 0; j < 16; j++) {
00225                 unsigned k = *s++;
00226                 *p++ = hex[ (k >> 4) & 0xf ];
00227                 *p++ = hex[ (k     ) & 0xf ];
00228             }
00229             *p = '\0';
00230         }
00231 /*@=bounds@*/
00232         fuser = rpmfiFUser(fi);
00233         fgroup = rpmfiFGroup(fi);
00234         flink = rpmfiFLink(fi);
00235         fnlink = rpmfiFNlink(fi);
00236 
00237         /* If querying only docs, skip non-doc files. */
00238         if ((qva->qva_flags & QUERY_FOR_DOCS) && !(fflags & RPMFILE_DOC))
00239             continue;
00240 
00241         /* If querying only configs, skip non-config files. */
00242         if ((qva->qva_flags & QUERY_FOR_CONFIG) && !(fflags & RPMFILE_CONFIG))
00243             continue;
00244 
00245         /* If not querying %ghost, skip ghost files. */
00246         if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
00247             continue;
00248 
00249 /*@-boundswrite@*/
00250         if (!rpmIsVerbose() && prefix)
00251             te = stpcpy(te, prefix);
00252 
00253         if (qva->qva_flags & QUERY_FOR_STATE) {
00254             switch (fstate) {
00255             case RPMFILE_STATE_NORMAL:
00256                 te = stpcpy(te, _("normal        "));
00257                 /*@switchbreak@*/ break;
00258             case RPMFILE_STATE_REPLACED:
00259                 te = stpcpy(te, _("replaced      "));
00260                 /*@switchbreak@*/ break;
00261             case RPMFILE_STATE_NOTINSTALLED:
00262                 te = stpcpy(te, _("not installed "));
00263                 /*@switchbreak@*/ break;
00264             case RPMFILE_STATE_NETSHARED:
00265                 te = stpcpy(te, _("net shared    "));
00266                 /*@switchbreak@*/ break;
00267             case RPMFILE_STATE_WRONGCOLOR:
00268                 te = stpcpy(te, _("wrong color   "));
00269                 /*@switchbreak@*/ break;
00270             case RPMFILE_STATE_MISSING:
00271                 te = stpcpy(te, _("(no state)    "));
00272                 /*@switchbreak@*/ break;
00273             default:
00274                 sprintf(te, _("(unknown %3d) "), fstate);
00275                 te += strlen(te);
00276                 /*@switchbreak@*/ break;
00277             }
00278         }
00279 /*@=boundswrite@*/
00280 
00281         if (qva->qva_flags & QUERY_FOR_DUMPFILES) {
00282             sprintf(te, "%s %d %d %s 0%o ", fn, (int)fsize, fmtime, fmd5, fmode);
00283             te += strlen(te);
00284 
00285             if (fuser && fgroup) {
00286 /*@-nullpass@*/
00287                 sprintf(te, "%s %s", fuser, fgroup);
00288 /*@=nullpass@*/
00289                 te += strlen(te);
00290             } else {
00291                 rpmError(RPMERR_INTERNAL,
00292                         _("package has not file owner/group lists\n"));
00293             }
00294 
00295             sprintf(te, " %s %s %u ", 
00296                                  fflags & RPMFILE_CONFIG ? "1" : "0",
00297                                  fflags & RPMFILE_DOC ? "1" : "0",
00298                                  frdev);
00299             te += strlen(te);
00300 
00301             sprintf(te, "%s", (flink && *flink ? flink : "X"));
00302             te += strlen(te);
00303         } else
00304         if (!rpmIsVerbose()) {
00305 /*@-boundswrite@*/
00306             te = stpcpy(te, fn);
00307 /*@=boundswrite@*/
00308         }
00309         else {
00310 
00311             /* XXX Adjust directory link count and size for display output. */
00312             if (S_ISDIR(fmode)) {
00313                 fnlink++;
00314                 fsize = 0;
00315             }
00316 
00317             if (fuser && fgroup) {
00318 /*@-nullpass@*/
00319                 printFileInfo(te, fn, fsize, fmode, fmtime, frdev, fnlink,
00320                                         fuser, fgroup, flink);
00321 /*@=nullpass@*/
00322                 te += strlen(te);
00323             } else {
00324                 rpmError(RPMERR_INTERNAL,
00325                         _("package has neither file owner or id lists\n"));
00326             }
00327         }
00328         flushBuffer(&t, &te, 0);
00329     }
00330             
00331     rc = 0;
00332 
00333 exit:
00334     flushBuffer(&t, &te, 0);
00335     t = _free(t);
00336 
00337     fi = rpmfiFree(fi);
00338     return rc;
00339 }
00340 
00341 void rpmDisplayQueryTags(FILE * fp)
00342 {
00343     const struct headerTagTableEntry_s * t;
00344     int i;
00345     const struct headerSprintfExtension_s * ext = rpmHeaderFormats;
00346 
00347     for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++)
00348         if (t->name) fprintf(fp, "%s\n", t->name + 7);
00349 
00350     while (ext->name != NULL) {
00351         if (ext->type == HEADER_EXT_MORE) {
00352             ext = ext->u.more;
00353             continue;
00354         }
00355         /* XXX don't print query tags twice. */
00356         for (i = 0, t = rpmTagTable; i < rpmTagTableSize; i++, t++) {
00357             if (t->name == NULL)        /* XXX programmer error. */
00358                 /*@innercontinue@*/ continue;
00359             if (!strcmp(t->name, ext->name))
00360                 /*@innerbreak@*/ break;
00361         }
00362         if (i >= rpmTagTableSize && ext->type == HEADER_EXT_TAG)
00363             fprintf(fp, "%s\n", ext->name + 7);
00364         ext++;
00365     }
00366 }
00367 
00368 static int rpmgiShowMatches(QVA_t qva, rpmts ts)
00369         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00370         /*@modifies qva, rpmGlobalMacroContext, h_errno, internalState @*/
00371 {
00372     rpmgi gi = qva->qva_gi;
00373     int ec = 0;
00374 
00375     while (rpmgiNext(gi) == RPMRC_OK) {
00376         Header h;
00377         int rc;
00378 
00379         h = rpmgiHeader(gi);
00380         if (h == NULL)          /* XXX perhaps stricter break instead? */
00381             continue;
00382         if ((rc = qva->qva_showPackage(qva, ts, h)) != 0)
00383             ec = rc;
00384         if (qva->qva_source == RPMQV_DBOFFSET)
00385             break;
00386     }
00387     return ec;
00388 }
00389 
00390 int rpmcliShowMatches(QVA_t qva, rpmts ts)
00391 {
00392     Header h;
00393     int ec = 0;
00394 
00395     while ((h = rpmdbNextIterator(qva->qva_mi)) != NULL) {
00396         int rc;
00397         if ((rc = qva->qva_showPackage(qva, ts, h)) != 0)
00398             ec = rc;
00399         if (qva->qva_source == RPMQV_DBOFFSET)
00400             break;
00401     }
00402     qva->qva_mi = rpmdbFreeIterator(qva->qva_mi);
00403     return ec;
00404 }
00405 
00411 static inline unsigned char nibble(char c)
00412         /*@*/
00413 {
00414     if (c >= '0' && c <= '9')
00415         return (c - '0');
00416     if (c >= 'A' && c <= 'F')
00417         return (c - 'A') + 10;
00418     if (c >= 'a' && c <= 'f')
00419         return (c - 'a') + 10;
00420     return 0;
00421 }
00422 
00423 /*@-bounds@*/ /* LCL: segfault (realpath annotation?) */
00424 int rpmQueryVerify(QVA_t qva, rpmts ts, const char * arg)
00425 {
00426     int res = 0;
00427     const char * s;
00428     int i;
00429     int provides_checked = 0;
00430 
00431     (void) rpmdbCheckSignals();
00432 
00433     if (qva->qva_showPackage == NULL)
00434         return 1;
00435 
00436     /*@-branchstate@*/
00437     switch (qva->qva_source) {
00438     case RPMQV_RPM:
00439         res = rpmgiShowMatches(qva, ts);
00440         break;
00441 
00442     case RPMQV_ALL:
00443         res = rpmgiShowMatches(qva, ts);
00444         break;
00445 
00446     case RPMQV_HDLIST:
00447         res = rpmgiShowMatches(qva, ts);
00448         break;
00449 
00450     case RPMQV_FTSWALK:
00451         res = rpmgiShowMatches(qva, ts);
00452         break;
00453 
00454     case RPMQV_SPECFILE:
00455         res = ((qva->qva_specQuery != NULL)
00456                 ? qva->qva_specQuery(ts, qva, arg) : 1);
00457         break;
00458 
00459     case RPMQV_GROUP:
00460         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_GROUP, arg, 0);
00461         if (qva->qva_mi == NULL) {
00462             rpmError(RPMERR_QUERYINFO,
00463                 _("group %s does not contain any packages\n"), arg);
00464             res = 1;
00465         } else
00466             res = rpmcliShowMatches(qva, ts);
00467         break;
00468 
00469     case RPMQV_TRIGGEREDBY:
00470         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_TRIGGERNAME, arg, 0);
00471         if (qva->qva_mi == NULL) {
00472             rpmError(RPMERR_QUERYINFO, _("no package triggers %s\n"), arg);
00473             res = 1;
00474         } else
00475             res = rpmcliShowMatches(qva, ts);
00476         break;
00477 
00478     case RPMQV_PKGID:
00479     {   unsigned char MD5[16];
00480         unsigned char * t;
00481 
00482         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00483             {};
00484         if (i != 32) {
00485             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "pkgid", arg);
00486             return 1;
00487         }
00488 
00489         MD5[0] = '\0';
00490         for (i = 0, t = MD5, s = arg; i < 16; i++, t++, s += 2)
00491             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00492         
00493         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_SIGMD5, MD5, sizeof(MD5));
00494         if (qva->qva_mi == NULL) {
00495             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00496                         "pkgid", arg);
00497             res = 1;
00498         } else
00499             res = rpmcliShowMatches(qva, ts);
00500     }   break;
00501 
00502     case RPMQV_HDRID:
00503         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00504             {};
00505         if (i != 40) {
00506             rpmError(RPMERR_QUERYINFO, _("malformed %s: %s\n"), "hdrid", arg);
00507             return 1;
00508         }
00509 
00510         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_SHA1HEADER, arg, 0);
00511         if (qva->qva_mi == NULL) {
00512             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00513                         "hdrid", arg);
00514             res = 1;
00515         } else
00516             res = rpmcliShowMatches(qva, ts);
00517         break;
00518 
00519     case RPMQV_FILEID:
00520     {   unsigned char MD5[16];
00521         unsigned char * t;
00522 
00523         for (i = 0, s = arg; *s && isxdigit(*s); s++, i++)
00524             {};
00525         if (i != 32) {
00526             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "fileid", arg);
00527             return 1;
00528         }
00529 
00530         MD5[0] = '\0';
00531         for (i = 0, t = MD5, s = arg; i < 16; i++, t++, s += 2)
00532             *t = (nibble(s[0]) << 4) | nibble(s[1]);
00533 
00534         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_FILEMD5S, MD5, sizeof(MD5));
00535         if (qva->qva_mi == NULL) {
00536             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00537                         "fileid", arg);
00538             res = 1;
00539         } else
00540             res = rpmcliShowMatches(qva, ts);
00541     }   break;
00542 
00543     case RPMQV_TID:
00544     {   int mybase = 10;
00545         const char * myarg = arg;
00546         char * end = NULL;
00547         unsigned iid;
00548 
00549         /* XXX should be in strtoul */
00550         if (*myarg == '0') {
00551             myarg++;
00552             mybase = 8;
00553             if (*myarg == 'x') {
00554                 myarg++;
00555                 mybase = 16;
00556             }
00557         }
00558         iid = strtoul(myarg, &end, mybase);
00559         if ((*end) || (end == arg) || (iid == ULONG_MAX)) {
00560             rpmError(RPMERR_QUERY, _("malformed %s: %s\n"), "tid", arg);
00561             return 1;
00562         }
00563         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_INSTALLTID, &iid, sizeof(iid));
00564         if (qva->qva_mi == NULL) {
00565             rpmError(RPMERR_QUERYINFO, _("no package matches %s: %s\n"),
00566                         "tid", arg);
00567             res = 1;
00568         } else
00569             res = rpmcliShowMatches(qva, ts);
00570     }   break;
00571 
00572     case RPMQV_WHATREQUIRES:
00573         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_REQUIRENAME, arg, 0);
00574         if (qva->qva_mi == NULL) {
00575             rpmError(RPMERR_QUERYINFO, _("no package requires %s\n"), arg);
00576             res = 1;
00577         } else
00578             res = rpmcliShowMatches(qva, ts);
00579         break;
00580 
00581     case RPMQV_WHATPROVIDES:
00582         if (arg[0] != '/') {
00583             provides_checked = 1;
00584             qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, arg, 0);
00585             if (qva->qva_mi == NULL) {
00586                 rpmError(RPMERR_QUERYINFO, _("no package provides %s\n"), arg);
00587                 res = 1;
00588             } else
00589                 res = rpmcliShowMatches(qva, ts);
00590             break;
00591         }
00592         /*@fallthrough@*/
00593     case RPMQV_PATH:
00594     {   char * fn;
00595         int myerrno = 0;
00596 
00597         for (s = arg; *s != '\0'; s++)
00598             if (!(*s == '.' || *s == '/'))
00599                 /*@loopbreak@*/ break;
00600 
00601         if (*s == '\0') {
00602             char fnbuf[PATH_MAX];
00603             fn = realpath(arg, fnbuf);
00604             if (fn)
00605                 fn = xstrdup(fn);
00606             else
00607                 fn = xstrdup(arg);
00608         } else if (*arg != '/') {
00609             const char *curDir = currentDirectory();
00610             fn = (char *) rpmGetPath(curDir, "/", arg, NULL);
00611             curDir = _free(curDir);
00612         } else
00613             fn = xstrdup(arg);
00614         (void) rpmCleanPath(fn);
00615 
00616         qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_BASENAMES, fn, 0);
00617         if (qva->qva_mi == NULL) {
00618             if (access(fn, F_OK) != 0)
00619                 myerrno = errno;
00620             else if (!provides_checked)
00621                 qva->qva_mi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, fn, 0);
00622         }
00623 
00624         if (myerrno != 0) {
00625             rpmError(RPMERR_QUERY, _("file %s: %s\n"), fn, strerror(myerrno));
00626             res = 1;
00627         } else if (qva->qva_mi == NULL) {
00628             rpmError(RPMERR_QUERYINFO,
00629                 _("file %s is not owned by any package\n"), fn);
00630             res = 1;
00631         } else
00632             res = rpmcliShowMatches(qva, ts);
00633 
00634         fn = _free(fn);
00635     }   break;
00636 
00637     case RPMQV_DBOFFSET:
00638     {   int mybase = 10;
00639         const char * myarg = arg;
00640         char * end = NULL;
00641         unsigned recOffset;
00642 
00643         /* XXX should be in strtoul */
00644         if (*myarg == '0') {
00645             myarg++;
00646             mybase = 8;
00647             if (*myarg == 'x') {
00648                 myarg++;
00649                 mybase = 16;
00650             }
00651         }
00652         recOffset = strtoul(myarg, &end, mybase);
00653         if ((*end) || (end == arg) || (recOffset == ULONG_MAX)) {
00654             rpmError(RPMERR_QUERYINFO, _("invalid package number: %s\n"), arg);
00655             return 1;
00656         }
00657         rpmMessage(RPMMESS_DEBUG, _("package record number: %u\n"), recOffset);
00658         /* RPMDBI_PACKAGES */
00659         qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_PACKAGES, &recOffset, sizeof(recOffset));
00660         if (qva->qva_mi == NULL) {
00661             rpmError(RPMERR_QUERYINFO,
00662                 _("record %u could not be read\n"), recOffset);
00663             res = 1;
00664         } else
00665             res = rpmcliShowMatches(qva, ts);
00666     }   break;
00667 
00668     case RPMQV_PACKAGE:
00669         /* XXX HACK to get rpmdbFindByLabel out of the API */
00670         qva->qva_mi = rpmtsInitIterator(ts, RPMDBI_LABEL, arg, 0);
00671         if (qva->qva_mi == NULL) {
00672             rpmError(RPMERR_QUERYINFO, _("package %s is not installed\n"), arg);
00673             res = 1;
00674         } else
00675             res = rpmcliShowMatches(qva, ts);
00676         break;
00677     }
00678     /*@=branchstate@*/
00679    
00680     return res;
00681 }
00682 /*@=bounds@*/
00683 
00684 int rpmcliArgIter(rpmts ts, QVA_t qva, ARGV_t argv)
00685 {
00686     rpmRC rpmrc = RPMRC_NOTFOUND;
00687     int ec = 0;
00688 
00689     switch (qva->qva_source) {
00690     case RPMQV_ALL:
00691         qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0);
00692         qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, RPMGI_NONE);
00693 
00694         if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD))  /* Load the ts with headers. */
00695         while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
00696             {};
00697         if (rpmrc != RPMRC_NOTFOUND)
00698             return 1;   /* XXX should be no. of failures. */
00699         
00700         /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
00701         ec = rpmQueryVerify(qva, ts, (const char *) argv);
00702         /*@=nullpass@*/
00703         rpmtsEmpty(ts);
00704         break;
00705     case RPMQV_RPM:
00706         qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0);
00707         qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags);
00708 
00709         if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD))  /* Load the ts with headers. */
00710         while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
00711             {};
00712         if (rpmrc != RPMRC_NOTFOUND)
00713             return 1;   /* XXX should be no. of failures. */
00714         
00715         /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
00716         ec = rpmQueryVerify(qva, ts, NULL);
00717         /*@=nullpass@*/
00718         rpmtsEmpty(ts);
00719         break;
00720     case RPMQV_HDLIST:
00721         qva->qva_gi = rpmgiNew(ts, RPMDBI_HDLIST, NULL, 0);
00722         qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags);
00723 
00724         if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD))  /* Load the ts with headers. */
00725         while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
00726             {};
00727         if (rpmrc != RPMRC_NOTFOUND)
00728             return 1;   /* XXX should be no. of failures. */
00729         
00730         /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
00731         ec = rpmQueryVerify(qva, ts, NULL);
00732         /*@=nullpass@*/
00733         rpmtsEmpty(ts);
00734         break;
00735     case RPMQV_FTSWALK:
00736         if (ftsOpts == 0)
00737             ftsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
00738         qva->qva_gi = rpmgiNew(ts, RPMDBI_FTSWALK, NULL, 0);
00739         qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, giFlags);
00740 
00741         if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD))  /* Load the ts with headers. */
00742         while ((rpmrc = rpmgiNext(qva->qva_gi)) == RPMRC_OK)
00743             {};
00744         if (rpmrc != RPMRC_NOTFOUND)
00745             return 1;   /* XXX should be no. of failures. */
00746         
00747         /*@-nullpass@*/ /* FIX: argv can be NULL, cast to pass argv array */
00748         ec = rpmQueryVerify(qva, ts, NULL);
00749         /*@=nullpass@*/
00750         rpmtsEmpty(ts);
00751         break;
00752     default:
00753         qva->qva_gi = rpmgiNew(ts, RPMDBI_ARGLIST, NULL, 0);
00754         qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts,
00755                 (giFlags | (RPMGI_NOGLOB|RPMGI_NOHEADER)));
00756         while (rpmgiNext(qva->qva_gi) == RPMRC_OK) {
00757             ec += rpmQueryVerify(qva, ts, rpmgiHdrPath(qva->qva_gi));
00758             rpmtsEmpty(ts);
00759         }
00760         break;
00761     }
00762 
00763     qva->qva_gi = rpmgiFree(qva->qva_gi);
00764 
00765     return ec;
00766 }
00767 
00768 int rpmcliQuery(rpmts ts, QVA_t qva, const char ** argv)
00769 {
00770     rpmVSFlags vsflags, ovsflags;
00771     int ec = 0;
00772 
00773     if (qva->qva_showPackage == NULL)
00774         qva->qva_showPackage = showQueryPackage;
00775 
00776     /* If --queryformat unspecified, then set default now. */
00777     if (!(qva->qva_flags & _QUERY_FOR_BITS) && qva->qva_queryFormat == NULL) {
00778         qva->qva_queryFormat = rpmExpand("%{?_query_all_fmt}\n", NULL);
00779         if (!(qva->qva_queryFormat != NULL && *qva->qva_queryFormat != '\0')) {
00780             qva->qva_queryFormat = _free(qva->qva_queryFormat);
00781             qva->qva_queryFormat = xstrdup("%{name}-%{version}-%{release}\n");
00782         }
00783     }
00784 
00785     vsflags = rpmExpandNumeric("%{?_vsflags_query}");
00786     if (qva->qva_flags & VERIFY_DIGEST)
00787         vsflags |= _RPMVSF_NODIGESTS;
00788     if (qva->qva_flags & VERIFY_SIGNATURE)
00789         vsflags |= _RPMVSF_NOSIGNATURES;
00790     if (qva->qva_flags & VERIFY_HDRCHK)
00791         vsflags |= RPMVSF_NOHDRCHK;
00792 
00793     ovsflags = rpmtsSetVSFlags(ts, vsflags);
00794     ec = rpmcliArgIter(ts, qva, argv);
00795     vsflags = rpmtsSetVSFlags(ts, ovsflags);
00796 
00797     if (qva->qva_showPackage == showQueryPackage)
00798         qva->qva_showPackage = NULL;
00799 
00800     return ec;
00801 }

Generated on Wed Jan 28 12:45:24 2009 for rpm by  doxygen 1.4.7