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

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

Generated on Tue Sep 17 15:59:50 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002