rpm 5.3.12
lib/verify.c
Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmiotypes.h>
00009 #include <rpmio.h>
00010 #include <rpmcb.h>
00011 #include "ugid.h"
00012 
00013 #include <rpmtypes.h>
00014 #include <rpmtag.h>
00015 #include <pkgio.h>
00016 
00017 #define _RPMFI_INTERNAL
00018 #include <rpmfi.h>
00019 
00020 #define _RPMSQ_INTERNAL
00021 #include "psm.h"
00022 
00023 #include "legacy.h"     /* XXX dodigest(), uidToUname(), gnameToGid */
00024 
00025 #define _RPMPS_INTERNAL /* XXX rpmps needs iterator. */
00026 #define _RPMTS_INTERNAL /* XXX expose rpmtsSetScriptFd */
00027 #include <rpmcli.h>
00028 
00029 #include "debug.h"
00030 
00031 /*@access rpmts @*/     /* XXX cast */
00032 /*@access rpmpsm @*/    /* XXX for %verifyscript through rpmpsmStage() */
00033 
00034 #define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
00035 
00036 /*@unchecked@*/
00037 extern int _rpmds_unspecified_epoch_noise;
00038 
00039 typedef struct rpmvf_s * rpmvf;
00040 struct rpmvf_s {
00041     struct rpmioItem_s _item;   
00042     const char * fn;
00043     const char * flink;
00044     struct stat  sb;
00045     rpmfileAttrs fflags;
00046     rpmfileState fstate;
00047     rpmVerifyAttrs vflags;
00048     int dalgo;
00049     size_t dlen;
00050     const unsigned char * digest;
00051     const char * fuser;
00052     const char * fgroup;
00053 #if defined(__LCLINT__NOTYET)
00054 /*@refs@*/
00055     int nrefs;                  
00056 #endif
00057 };
00058 
00059 static rpmvf rpmvfFree(/*@only@*/ rpmvf vf)
00060         /*@modifies vf @*/
00061 {
00062 
00063     if (vf) {
00064 #ifdef  NOTYET
00065         yarnPossess(vf->_item.use);
00066         if (yarnPeekLock(vf->_item.use) <= 1L) {
00067             yarnLock use = vf->_item.use;
00068             vf->fn = _free(vf->fn);
00069             vf = _free(vf);
00070             yarnTwist(use, TO, 0);
00071             use = yarnFreeLock(use);
00072         } else
00073             yarnTwist(vf->_item.use, BY, -1);
00074 #else
00075         vf->fn = _free(vf->fn);
00076         vf = _free(vf);
00077 #endif
00078     }
00079     return NULL;
00080 }
00081 
00082 /*@only@*/
00083 static rpmvf rpmvfNew(rpmts ts, rpmfi fi, int i, rpmVerifyAttrs omitMask)
00084         /*@*/
00085 {
00086     rpmvf vf = xcalloc(1, sizeof(*vf));
00087 
00088 #ifdef  NOTYET
00089     vf->_item.use = yarnNewLock(1);
00090     vf->_item.pool = NULL;
00091 #endif
00092 
00093 /*@-mods@*/
00094     vf->fn = rpmGetPath(rpmtsRootDir(ts), fi->dnl[fi->dil[i]], fi->bnl[i], NULL);
00095 /*@=mods@*/
00096     vf->flink = fi->flinks[i];
00097     vf->fuser = fi->fuser[i];
00098     vf->fgroup = fi->fgroup[i];
00099 
00100     {   struct stat *st = &vf->sb;
00101         st->st_dev =
00102         st->st_rdev = fi->frdevs[i];
00103         st->st_ino = fi->finodes[i];
00104         st->st_mode = fi->fmodes[i];
00105 #ifdef  NOTNEEDED
00106         st->st_nlink = rpmfiFNlink(fi) + (int)S_ISDIR(st->st_mode);
00107 #endif
00108         if (unameToUid(vf->fuser, &st->st_uid) == -1)
00109             st->st_uid = 0;             /* XXX */
00110         if (gnameToGid(vf->fgroup, &st->st_gid) == -1)
00111             st->st_gid = 0;             /* XXX */
00112         st->st_size = fi->fsizes[i];
00113         st->st_blksize = 4 * 1024;      /* XXX */
00114         st->st_blocks = (st->st_size + (st->st_blksize - 1)) / st->st_blksize;
00115         st->st_atime =
00116         st->st_ctime =
00117         st->st_mtime = fi->fmtimes[i];
00118     }
00119 
00120     vf->fflags = fi->fflags[i];
00121     vf->fstate = fi->fstates[i];
00122     vf->vflags = fi->vflags[i];
00123     vf->dalgo = fi->fdigestalgos
00124                 ? fi->fdigestalgos[i]
00125                 : fi->digestalgo;
00126     vf->dlen = fi->digestlen;
00127     vf->digest = fi->digests + (fi->digestlen * i);
00128 
00129     /* Don't verify any features in omitMask. */
00130     vf->vflags &= ~(omitMask | RPMVERIFY_FAILURES);
00131 
00132     /* Content checks of %ghost files are meaningless. */
00133     if (vf->fflags & RPMFILE_GHOST)
00134         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00135                         RPMVERIFY_LINKTO | RPMVERIFY_HMAC);
00136 
00137     return vf;
00138 }
00139 
00146 static int rpmvfVerify(rpmvf vf, int spew)
00147         /*@globals h_errno, fileSystem, internalState @*/
00148         /*@modifies vf, fileSystem, internalState @*/
00149 {
00150     rpmVerifyAttrs res = RPMVERIFY_NONE;
00151     struct stat sb;
00152     int ec = 0;
00153 
00154     /* Check to see if the file was installed - if not pretend all is OK. */
00155     switch (vf->fstate) {
00156     default:
00157     case RPMFILE_STATE_NETSHARED:
00158     case RPMFILE_STATE_REPLACED:
00159     case RPMFILE_STATE_NOTINSTALLED:
00160     case RPMFILE_STATE_WRONGCOLOR:
00161         goto exit;
00162         /*@notreached@*/ break;
00163     case RPMFILE_STATE_NORMAL:
00164         break;
00165     }
00166 
00167 assert(vf->fn != NULL);
00168     if (vf->fn == NULL || Lstat(vf->fn, &sb) != 0) {
00169         res |= RPMVERIFY_LSTATFAIL;
00170         ec = 1;
00171         goto exit;
00172     }
00173 
00174     /* Not all attributes of non-regular files can be verified. */
00175     if (S_ISDIR(sb.st_mode))
00176         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00177                         RPMVERIFY_LINKTO | RPMVERIFY_HMAC);
00178     else if (S_ISLNK(sb.st_mode)) {
00179         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00180                 RPMVERIFY_MODE | RPMVERIFY_HMAC);
00181 #if CHOWN_FOLLOWS_SYMLINK
00182         vf->vflags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
00183 #endif
00184     }
00185     else if (S_ISFIFO(sb.st_mode))
00186         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00187                         RPMVERIFY_LINKTO | RPMVERIFY_HMAC);
00188     else if (S_ISCHR(sb.st_mode))
00189         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00190                         RPMVERIFY_LINKTO | RPMVERIFY_HMAC);
00191     else if (S_ISBLK(sb.st_mode))
00192         vf->vflags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00193                         RPMVERIFY_LINKTO | RPMVERIFY_HMAC);
00194     else
00195         vf->vflags &= ~(RPMVERIFY_LINKTO);
00196 
00197     if (vf->vflags & (RPMVERIFY_FDIGEST | RPMVERIFY_HMAC)) {
00198         if (vf->digest == NULL || vf->dlen == 0)
00199             res |= RPMVERIFY_FDIGEST;
00200         else {
00201         /* XXX If --nofdigest, then prelinked library sizes fail to verify. */
00202             unsigned char * fdigest = memset(alloca(vf->dlen), 0, vf->dlen);
00203             size_t fsize = 0;
00204 #define _mask   (RPMVERIFY_FDIGEST|RPMVERIFY_HMAC)
00205             unsigned dflags = (vf->vflags & _mask) == RPMVERIFY_HMAC
00206                 ? 0x2 : 0x0;
00207 #undef  _mask
00208             int rc = dodigest(vf->dalgo, vf->fn, fdigest, dflags, &fsize);
00209             sb.st_size = fsize;
00210             if (rc)
00211                 res |= (RPMVERIFY_READFAIL|RPMVERIFY_FDIGEST);
00212             else
00213             if (memcmp(fdigest, vf->digest, vf->dlen))
00214                 res |= RPMVERIFY_FDIGEST;
00215         }
00216     }
00217 
00218     if (vf->vflags & RPMVERIFY_LINKTO) {
00219         char linkto[1024+1];
00220         int size = 0;
00221 
00222         if ((size = Readlink(vf->fn, linkto, sizeof(linkto)-1)) == -1)
00223             res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
00224         else {
00225             linkto[size] = '\0';
00226             if (vf->flink == NULL || strcmp(linkto, vf->flink))
00227                 res |= RPMVERIFY_LINKTO;
00228         }
00229     }
00230 
00231     if (vf->vflags & RPMVERIFY_FILESIZE) {
00232         if (sb.st_size != vf->sb.st_size)
00233             res |= RPMVERIFY_FILESIZE;
00234     }
00235 
00236     if (vf->vflags & RPMVERIFY_MODE) {
00237         /* XXX AIX has sizeof(mode_t) > sizeof(unsigned short) */
00238         unsigned short metamode = (unsigned short)vf->sb.st_mode;
00239         unsigned short filemode = (unsigned short)sb.st_mode;
00240 
00241         /* Comparing type of %ghost files is meaningless, but perms are OK. */
00242         if (vf->fflags & RPMFILE_GHOST) {
00243             metamode &= ~0xf000;
00244             filemode &= ~0xf000;
00245         }
00246         if (metamode != filemode)
00247             res |= RPMVERIFY_MODE;
00248     }
00249 
00250     if (vf->vflags & RPMVERIFY_RDEV) {
00251         if (S_ISCHR(vf->sb.st_mode) != S_ISCHR(sb.st_mode)
00252          || S_ISBLK(vf->sb.st_mode) != S_ISBLK(sb.st_mode))
00253             res |= RPMVERIFY_RDEV;
00254         else if (S_ISDEV(vf->sb.st_mode) && S_ISDEV(sb.st_mode)) {
00255             rpmuint16_t st_rdev = (rpmuint16_t)(sb.st_rdev & 0xffff);
00256             rpmuint16_t frdev = (rpmuint16_t)(vf->sb.st_rdev & 0xffff);
00257             if (st_rdev != frdev)
00258                 res |= RPMVERIFY_RDEV;
00259         }
00260     }
00261 
00262     if (vf->vflags & RPMVERIFY_MTIME) {
00263         if (sb.st_mtime != vf->sb.st_mtime)
00264             res |= RPMVERIFY_MTIME;
00265     }
00266 
00267     if (vf->vflags & RPMVERIFY_USER) {
00268         const char * fuser = uidToUname(sb.st_uid);
00269         if (fuser == NULL || vf->fuser == NULL || strcmp(fuser, vf->fuser))
00270             res |= RPMVERIFY_USER;
00271     }
00272 
00273     if (vf->vflags & RPMVERIFY_GROUP) {
00274         const char * fgroup = gidToGname(sb.st_gid);
00275         if (fgroup == NULL || vf->fgroup == NULL || strcmp(fgroup, vf->fgroup))
00276             res |= RPMVERIFY_GROUP;
00277     }
00278 
00279 exit:
00280 
00281     if (spew) { /* XXX no output w verify(...) probe. */
00282         char buf[BUFSIZ];
00283         char * t = buf;
00284         char * te = t;
00285         *te = '\0';
00286         if (ec) {
00287             if (!(vf->fflags & (RPMFILE_MISSINGOK|RPMFILE_GHOST))
00288              || rpmIsVerbose())
00289             {
00290                 sprintf(te, _("missing   %c %s"),
00291                         ((vf->fflags & RPMFILE_CONFIG)  ? 'c' :
00292                          (vf->fflags & RPMFILE_DOC)     ? 'd' :
00293                          (vf->fflags & RPMFILE_GHOST)   ? 'g' :
00294                          (vf->fflags & RPMFILE_LICENSE) ? 'l' :
00295                          (vf->fflags & RPMFILE_PUBKEY)  ? 'P' :
00296                          (vf->fflags & RPMFILE_README)  ? 'r' : ' '),
00297                         vf->fn);
00298                 if ((res & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) {
00299                     te += strlen(te);
00300                     sprintf(te, " (%s)", strerror(errno));
00301                 }
00302             }
00303         } else if (res || rpmIsVerbose()) {
00304             /*@observer@*/ static const char aok[] = ".";
00305             /*@observer@*/ static const char unknown[] = "?";
00306 
00307 #define _verify(_RPMVERIFY_F, _C)       \
00308         ((res & _RPMVERIFY_F) ? _C : aok)
00309 #define _verifylink(_RPMVERIFY_F, _C)   \
00310         ((res & RPMVERIFY_READLINKFAIL) ? unknown : \
00311          (res & _RPMVERIFY_F) ? _C : aok)
00312 #define _verifyfile(_RPMVERIFY_F, _C)   \
00313         ((res & RPMVERIFY_READFAIL) ? unknown : \
00314          (res & _RPMVERIFY_F) ? _C : aok)
00315         
00316             const char * digest = _verifyfile(RPMVERIFY_FDIGEST, "5");
00317             const char * size = _verify(RPMVERIFY_FILESIZE, "S");
00318             const char * link = _verifylink(RPMVERIFY_LINKTO, "L");
00319             const char * mtime = _verify(RPMVERIFY_MTIME, "T");
00320             const char * rdev = _verify(RPMVERIFY_RDEV, "D");
00321             const char * user = _verify(RPMVERIFY_USER, "U");
00322             const char * group = _verify(RPMVERIFY_GROUP, "G");
00323             const char * mode = _verify(RPMVERIFY_MODE, "M");
00324 
00325 #undef _verifyfile
00326 #undef _verifylink
00327 #undef _verify
00328 
00329             sprintf(te, "%s%s%s%s%s%s%s%s  %c %s",
00330                     size, mode, digest, rdev, link, user, group, mtime,
00331                         ((vf->fflags & RPMFILE_CONFIG)  ? 'c' :
00332                          (vf->fflags & RPMFILE_DOC)     ? 'd' :
00333                          (vf->fflags & RPMFILE_GHOST)   ? 'g' :
00334                          (vf->fflags & RPMFILE_LICENSE) ? 'l' :
00335                          (vf->fflags & RPMFILE_PUBKEY)  ? 'P' :
00336                          (vf->fflags & RPMFILE_README)  ? 'r' : ' '),
00337                         vf->fn);
00338 
00339         }
00340 
00341         if (t && *t)
00342             rpmlog(RPMLOG_NOTICE, "%s\n", t);
00343 
00344     }
00345 
00346     return (res != 0);
00347 }
00348 
00358 static int rpmVerifyScript(/*@unused@*/ QVA_t qva, rpmts ts,
00359                 rpmfi fi, /*@null@*/ FD_t scriptFd)
00360         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00361         /*@modifies ts, fi, scriptFd, rpmGlobalMacroContext,
00362                 fileSystem, internalState @*/
00363 {
00364     rpmpsm psm;
00365     rpmRC rc;
00366     int ec = 0;
00367 
00368     if (scriptFd != NULL)
00369         rpmtsSetScriptFd(ts, scriptFd);
00370 
00371     psm = rpmpsmNew(ts, NULL, fi);
00372 
00373     rc = rpmpsmScriptStage(psm, RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG);
00374     if (rc != RPMRC_OK)
00375         ec = 1;
00376 
00377     rc = rpmpsmScriptStage(psm, RPMTAG_SANITYCHECK, RPMTAG_SANITYCHECKPROG);
00378     if (rc != RPMRC_OK)
00379         ec = 1;
00380 
00381     psm = rpmpsmFree(psm, __FUNCTION__);
00382 
00383     if (scriptFd != NULL)
00384         rpmtsSetScriptFd(ts, NULL);
00385 
00386     return ec;
00387 }
00388 
00396 static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts,
00397                 Header h)
00398         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00399         /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
00400 {
00401 #ifdef  NOTYET
00402     uint32_t hdrNum = headerGetInstance(h);
00403 #endif
00404     rpmps ps;
00405     int rc = 0;         /* assume no problems */
00406     int xx;
00407 
00408     rpmtsEmpty(ts);
00409 
00410 #ifdef  NOTYET
00411     if (hdrNum > 0)
00412         (void) rpmtsAddEraseElement(ts, h, hdrNum);
00413     else
00414 #endif
00415         (void) rpmtsAddInstallElement(ts, h, headerGetOrigin(h), 0, NULL);
00416 
00417     xx = rpmtsCheck(ts);
00418     ps = rpmtsProblems(ts);
00419 
00420     if (rpmpsNumProblems(ps) > 0) {
00421         const char * altNEVR;
00422         const char * pkgNEVR = NULL;
00423         rpmpsi psi;
00424         rpmProblem prob;
00425         char * t, * te;
00426         int nb = 512;
00427 
00428         psi = rpmpsInitIterator(ps);
00429         while (rpmpsNextIterator(psi) >= 0) {
00430             prob = rpmpsProblem(psi);
00431             if (pkgNEVR == NULL)
00432                 pkgNEVR = rpmProblemGetPkgNEVR(prob);
00433 
00434             altNEVR = rpmProblemGetAltNEVR(prob);
00435 assert(altNEVR != NULL);
00436             if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
00437                 nb += sizeof("\tRequires: ")-1;
00438             if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
00439                 nb += sizeof("\tConflicts: ")-1;
00440             nb += strlen(altNEVR+2) + sizeof("\n") - 1;
00441 
00442         }
00443         psi = rpmpsFreeIterator(psi);
00444 
00445         te = t = alloca(nb);
00446         *te = '\0';
00447         sprintf(te, _("Unsatisfied dependencies for %s:\n"), pkgNEVR);
00448         te += strlen(te);
00449 
00450         psi = rpmpsInitIterator(ps);
00451         while (rpmpsNextIterator(psi) >= 0) {
00452             prob = rpmpsProblem(psi);
00453 
00454             if ((altNEVR = rpmProblemGetAltNEVR(prob)) == NULL)
00455                 altNEVR = "? ?altNEVR?";
00456             if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
00457                 te = stpcpy(te, "\tRequires: ");
00458             if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
00459                 te = stpcpy(te, "\tConflicts: ");
00460             te = stpcpy( stpcpy(te, altNEVR+2), "\n");
00461 
00462             rc++;
00463         }
00464         psi = rpmpsFreeIterator(psi);
00465 
00466         if (te > t) {
00467             *te++ = '\n';
00468             *te = '\0';
00469             rpmlog(RPMLOG_NOTICE, "%s", t);
00470             te = t;
00471             *t = '\0';
00472         }
00473     }
00474 
00475     ps = rpmpsFree(ps);
00476 
00477     rpmtsEmpty(ts);
00478 
00479     return rc;
00480 }
00481 
00482 int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
00483 {
00484     static int scareMem = 0;
00485     rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
00486     int spew = (qva->qva_mode != 'v');  /* XXX no output w verify(...) probe. */
00487     int ec = 0;
00488     int i;
00489 rpmfi fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
00490 uint32_t fc = rpmfiFC(fi);
00491 
00492   {
00493     /* Verify header digest/signature. */
00494     if (qva->qva_flags & (VERIFY_DIGEST | VERIFY_SIGNATURE))
00495     {
00496         const char * horigin = headerGetOrigin(h);
00497         const char * msg = NULL;
00498         size_t uhlen = 0;
00499         void * uh = headerUnload(h, &uhlen);
00500         int lvl = headerCheck(rpmtsDig(ts), uh, uhlen, &msg) == RPMRC_FAIL
00501                 ? RPMLOG_ERR : RPMLOG_DEBUG;
00502         rpmlog(lvl, "%s: %s\n",
00503                 (horigin ? horigin : "verify"), (msg ? msg : ""));
00504         rpmtsCleanDig(ts);
00505         uh = _free(uh);
00506         msg = _free(msg);
00507     }
00508 
00509     /* Verify file digests. */
00510     if (fc > 0 && (qva->qva_flags & VERIFY_FILES))
00511 #if defined(_OPENMP)
00512     #pragma omp parallel for private(i) reduction(+:ec)
00513 #endif
00514     for (i = 0; i < (int)fc; i++) {
00515         int fflags = fi->fflags[i];
00516         rpmvf vf;
00517         int rc;
00518 
00519         /* If not querying %config, skip config files. */
00520         if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG))
00521             continue;
00522 
00523         /* If not querying %doc, skip doc files. */
00524         if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC))
00525             continue;
00526 
00527         /* If not verifying %ghost, skip ghost files. */
00528         /* XXX the broken!!! logic disables %ghost queries always. */
00529         if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
00530             continue;
00531 
00532         /* Gather per-file data into a carrier. */
00533         vf = rpmvfNew(ts, fi, i, omitMask);
00534 
00535         /* Verify per-file metadata. */
00536         rc = rpmvfVerify(vf, spew);
00537         if (rc)
00538             ec += rc;
00539 
00540         (void) rpmvfFree(vf);
00541         vf = NULL;
00542     }
00543 
00544     /* Run verify/sanity scripts (if any). */
00545     if (qva->qva_flags & VERIFY_SCRIPT)
00546     {
00547         int rc;
00548 
00549         if (headerIsEntry(h, RPMTAG_VERIFYSCRIPT) ||
00550             headerIsEntry(h, RPMTAG_SANITYCHECK))
00551         {
00552             FD_t fdo = fdDup(STDOUT_FILENO);
00553 
00554             rc = rpmfiSetHeader(fi, h);
00555             if ((rc = rpmVerifyScript(qva, ts, fi, fdo)) != 0)
00556                 ec += rc;
00557             if (fdo != NULL)
00558                 rc = Fclose(fdo);
00559             rc = rpmfiSetHeader(fi, NULL);
00560         }
00561     }
00562 
00563     /* Verify dependency assertions. */
00564     if (qva->qva_flags & VERIFY_DEPS)
00565     {
00566         int save_noise = _rpmds_unspecified_epoch_noise;
00567         int rc;
00568 
00569 /*@-mods@*/
00570         if (rpmIsVerbose())
00571             _rpmds_unspecified_epoch_noise = 1;
00572         if ((rc = verifyDependencies(qva, ts, h)) != 0)
00573             ec += rc;
00574         _rpmds_unspecified_epoch_noise = save_noise;
00575 /*@=mods@*/
00576     }
00577   }
00578 
00579     fi = rpmfiFree(fi);
00580 
00581     return ec;
00582 }
00583 
00584 int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv)
00585 {
00586     rpmdepFlags depFlags = qva->depFlags, odepFlags;
00587     rpmtransFlags transFlags = qva->transFlags, otransFlags;
00588     rpmVSFlags vsflags, ovsflags;
00589     int ec = 0;
00590 
00591 #if defined(_OPENMP)
00592 (void) tagName(0);      /* XXX instantiate the tagname store. */
00593 omp_set_nested(1);      /* XXX permit nested thread teams. */
00594 #endif
00595 
00596     if (qva->qva_showPackage == NULL)
00597         qva->qva_showPackage = showVerifyPackage;
00598 
00599     /* XXX verify flags are inverted from query. */
00600     vsflags = rpmExpandNumeric("%{?_vsflags_verify}");
00601     if (!(qva->qva_flags & VERIFY_DIGEST))
00602         vsflags |= _RPMVSF_NODIGESTS;
00603     if (!(qva->qva_flags & VERIFY_SIGNATURE))
00604         vsflags |= _RPMVSF_NOSIGNATURES;
00605     if (!(qva->qva_flags & VERIFY_HDRCHK))
00606         vsflags |= RPMVSF_NOHDRCHK;
00607     vsflags &= ~RPMVSF_NEEDPAYLOAD;
00608 
00609     odepFlags = rpmtsSetDFlags(ts, depFlags);
00610     otransFlags = rpmtsSetFlags(ts, transFlags);
00611     ovsflags = rpmtsSetVSFlags(ts, vsflags);
00612     ec = rpmcliArgIter(ts, qva, argv);
00613     vsflags = rpmtsSetVSFlags(ts, ovsflags);
00614     transFlags = rpmtsSetFlags(ts, otransFlags);
00615     depFlags = rpmtsSetDFlags(ts, odepFlags);
00616 
00617     if (qva->qva_showPackage == showVerifyPackage)
00618         qva->qva_showPackage = NULL;
00619 
00620     rpmtsEmpty(ts);
00621 
00622     return ec;
00623 }