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

Generated on Fri Aug 11 11:29:26 2006 for rpm by  doxygen 1.4.7