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

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