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

Generated on Sat Oct 1 20:21:01 2011 for rpm by  doxygen 1.4.4