• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

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

Generated on Mon Nov 29 2010 05:18:43 for rpm by  doxygen 1.7.2