Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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

Generated on Thu Feb 17 17:06:39 2005 for rpm by  doxygen 1.3.9.1