rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/verify.c
Go to the documentation of this file.

    00001
    00006 #include "system.h"
    00007
    00008 #include <rpmio.h>
    00009 #include <rpmiotypes.h>
    00010 #include <rpmcb.h>
    00011 #include "ugid.h"
    00012
    00013 #include <rpmtypes.h>
    00014 #include <rpmtag.h>
    00015
    00016 #include <rpmfi.h>
    00017
    00018 #define _RPMSQ_INTERNAL
    00019 #include "psm.h"
    00020
    00021 #include "legacy.h"     /* XXX dodigest(), uidToUname(), gnameToGid */
    00022
    00023 #define _RPMPS_INTERNAL /* XXX rpmps needs iterator. */
    00024 #define _RPMTS_INTERNAL /* XXX expose rpmtsSetScriptFd */
    00025 #include <rpmcli.h>
    00026
    00027 #include "debug.h"
    00028
    00029 /*@access rpmts @*/     /* XXX cast */
    00030 /*@access rpmpsm @*/    /* XXX for %verifyscript through rpmpsmStage() */
    00031
    00032 #define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
    00033
    00034 /*@unchecked@*/
    00035 extern int _rpmds_unspecified_epoch_noise;
    00036
    00046 static int rpmVerifyFile(const rpmts ts, const rpmfi fi,
    00047                 /*@out@*/ rpmVerifyAttrs * res, rpmVerifyAttrs omitMask)
    00048         /*@globals h_errno, fileSystem, internalState @*/
    00049         /*@modifies fi, *res, fileSystem, internalState @*/
    00050         /*@requires maxSet(res) >= 0 @*/
    00051 {
    00052     unsigned short fmode = rpmfiFMode(fi);
    00053     rpmfileAttrs fileAttrs = rpmfiFFlags(fi);
    00054     rpmVerifyAttrs flags = rpmfiVFlags(fi);
    00055     const char * fn = rpmfiFN(fi);
    00056     const char * rootDir = rpmtsRootDir(ts);
    00057     struct stat sb;
    00058     int rc;
    00059
    00060     /* Prepend the path to root (if specified). */
    00061     if (rootDir && *rootDir != '\0'
    00062      && !(rootDir[0] == '/' && rootDir[1] == '\0'))
    00063     {
    00064         int nb = strlen(fn) + strlen(rootDir) + 1;
    00065         char * tb = alloca(nb);
    00066         char * t;
    00067
    00068         t = tb;
    00069         *t = '\0';
    00070         t = stpcpy(t, rootDir);
    00071         while (t > tb && t[-1] == '/') {
    00072             --t;
    00073             *t = '\0';
    00074         }
    00075         t = stpcpy(t, fn);
    00076         fn = tb;
    00077     }
    00078
    00079     *res = RPMVERIFY_NONE;
    00080
    00081     /*
    00082      * Check to see if the file was installed - if not pretend all is OK.
    00083      */
    00084     switch (rpmfiFState(fi)) {
    00085     case RPMFILE_STATE_NETSHARED:
    00086     case RPMFILE_STATE_REPLACED:
    00087     case RPMFILE_STATE_NOTINSTALLED:
    00088     case RPMFILE_STATE_WRONGCOLOR:
    00089         return 0;
    00090         /*@notreached@*/ break;
    00091     case RPMFILE_STATE_NORMAL:
    00092         break;
    00093     }
    00094
    00095     if (fn == NULL || Lstat(fn, &sb) != 0) {
    00096         *res |= RPMVERIFY_LSTATFAIL;
    00097         return 1;
    00098     }
    00099
    00100     /*
    00101      * Not all attributes of non-regular files can be verified.
    00102      */
    00103     if (S_ISDIR(sb.st_mode))
    00104         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00105                         RPMVERIFY_LINKTO);
    00106     else if (S_ISLNK(sb.st_mode)) {
    00107         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00108                 RPMVERIFY_MODE);
    00109 #if CHOWN_FOLLOWS_SYMLINK
    00110             flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
    00111 #endif
    00112     }
    00113     else if (S_ISFIFO(sb.st_mode))
    00114         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00115                         RPMVERIFY_LINKTO);
    00116     else if (S_ISCHR(sb.st_mode))
    00117         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00118                         RPMVERIFY_LINKTO);
    00119     else if (S_ISBLK(sb.st_mode))
    00120         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00121                         RPMVERIFY_LINKTO);
    00122     else
    00123         flags &= ~(RPMVERIFY_LINKTO);
    00124
    00125     /*
    00126      * Content checks of %ghost files are meaningless.
    00127      */
    00128     if (fileAttrs & RPMFILE_GHOST)
    00129         flags &= ~(RPMVERIFY_FDIGEST | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
    00130                         RPMVERIFY_LINKTO);
    00131
    00132     /*
    00133      * Don't verify any features in omitMask.
    00134      */
    00135     flags &= ~(omitMask | RPMVERIFY_FAILURES);
    00136
    00137
    00138     if (flags & RPMVERIFY_FDIGEST) {
    00139         int dalgo = 0;
    00140         size_t dlen = 0;
    00141         const unsigned char * digest = rpmfiDigest(fi, &dalgo, &dlen);
    00142
    00143         if (digest == NULL)
    00144             *res |= RPMVERIFY_FDIGEST;
    00145         else {
    00146         /* XXX If --nofdigest, then prelinked library sizes fail to verify. */
    00147             unsigned char * fdigest = memset(alloca(dlen), 0, dlen);
    00148             size_t fsize;
    00149             rc = dodigest(dalgo, fn, fdigest, 0, &fsize);
    00150             sb.st_size = fsize;
    00151             if (rc)
    00152                 *res |= (RPMVERIFY_READFAIL|RPMVERIFY_FDIGEST);
    00153             else
    00154             if (memcmp(fdigest, digest, dlen))
    00155                 *res |= RPMVERIFY_FDIGEST;
    00156         }
    00157     }
    00158
    00159     if (flags & RPMVERIFY_LINKTO) {
    00160         char linkto[1024+1];
    00161         int size = 0;
    00162
    00163         if ((size = Readlink(fn, linkto, sizeof(linkto)-1)) == -1)
    00164             *res |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
    00165         else {
    00166             const char * flink = rpmfiFLink(fi);
    00167             linkto[size] = '\0';
    00168             if (flink == NULL || strcmp(linkto, flink))
    00169                 *res |= RPMVERIFY_LINKTO;
    00170         }
    00171     }
    00172
    00173     if (flags & RPMVERIFY_FILESIZE) {
    00174         if (sb.st_size != rpmfiFSize(fi))
    00175             *res |= RPMVERIFY_FILESIZE;
    00176     }
    00177
    00178     if (flags & RPMVERIFY_MODE) {
    00179         unsigned short metamode = fmode;
    00180         unsigned short filemode;
    00181
    00182         /*
    00183          * Platforms (like AIX) where sizeof(unsigned short) != sizeof(mode_t)
    00184          * need the (unsigned short) cast here.
    00185          */
    00186         filemode = (unsigned short)sb.st_mode;
    00187
    00188         /*
    00189          * Comparing the type of %ghost files is meaningless, but perms are OK.
    00190          */
    00191         if (fileAttrs & RPMFILE_GHOST) {
    00192             metamode &= ~0xf000;
    00193             filemode &= ~0xf000;
    00194         }
    00195
    00196         if (metamode != filemode)
    00197             *res |= RPMVERIFY_MODE;
    00198     }
    00199
    00200     if (flags & RPMVERIFY_RDEV) {
    00201         if (S_ISCHR(fmode) != S_ISCHR(sb.st_mode)
    00202          || S_ISBLK(fmode) != S_ISBLK(sb.st_mode))
    00203         {
    00204             *res |= RPMVERIFY_RDEV;
    00205         } else if (S_ISDEV(fmode) && S_ISDEV(sb.st_mode)) {
    00206             rpmuint16_t st_rdev = (rpmuint16_t)(sb.st_rdev & 0xffff);
    00207             rpmuint16_t frdev = (rpmuint16_t)(rpmfiFRdev(fi) & 0xffff);
    00208             if (st_rdev != frdev)
    00209                 *res |= RPMVERIFY_RDEV;
    00210         }
    00211     }
    00212
    00213     if (flags & RPMVERIFY_MTIME) {
    00214         if ((rpmuint32_t)sb.st_mtime != rpmfiFMtime(fi))
    00215             *res |= RPMVERIFY_MTIME;
    00216     }
    00217
    00218     if (flags & RPMVERIFY_USER) {
    00219         const char * name = uidToUname(sb.st_uid);
    00220         const char * fuser = rpmfiFUser(fi);
    00221         if (name == NULL || fuser == NULL || strcmp(name, fuser))
    00222             *res |= RPMVERIFY_USER;
    00223     }
    00224
    00225     if (flags & RPMVERIFY_GROUP) {
    00226         const char * name = gidToGname(sb.st_gid);
    00227         const char * fgroup = rpmfiFGroup(fi);
    00228         if (name == NULL || fgroup == NULL || strcmp(name, fgroup))
    00229             *res |= RPMVERIFY_GROUP;
    00230     }
    00231
    00232     return 0;
    00233 }
    00234
    00244 static int rpmVerifyScript(/*@unused@*/ QVA_t qva, rpmts ts,
    00245                 rpmfi fi, /*@null@*/ FD_t scriptFd)
    00246         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00247         /*@modifies ts, fi, scriptFd, rpmGlobalMacroContext,
    00248                 fileSystem, internalState @*/
    00249 {
    00250     rpmpsm psm = rpmpsmNew(ts, NULL, fi);
    00251     int rc = 0;
    00252
    00253     if (psm == NULL)    /* XXX can't happen */
    00254         return rc;
    00255
    00256     if (scriptFd != NULL)
    00257         rpmtsSetScriptFd(psm->ts, scriptFd);
    00258
    00259     psm->stepName = "verify";
    00260     psm->scriptTag = RPMTAG_VERIFYSCRIPT;
    00261     psm->progTag = RPMTAG_VERIFYSCRIPTPROG;
    00262     rc = rpmpsmStage(psm, PSM_SCRIPT);
    00263
    00264     psm->stepName = "sanitycheck";
    00265     psm->scriptTag = RPMTAG_SANITYCHECK;
    00266     psm->progTag = RPMTAG_SANITYCHECKPROG;
    00267     rc = rpmpsmStage(psm, PSM_SCRIPT);
    00268
    00269     if (scriptFd != NULL)
    00270         rpmtsSetScriptFd(psm->ts, NULL);
    00271
    00272     psm = rpmpsmFree(psm, "rpmVerifyScript");
    00273
    00274     return rc;
    00275 }
    00276
    00284 static int verifyHeader(QVA_t qva, const rpmts ts, rpmfi fi)
    00285         /*@globals h_errno, fileSystem, internalState @*/
    00286         /*@modifies fi, fileSystem, internalState  @*/
    00287 {
    00288     rpmVerifyAttrs verifyResult = 0;
    00289     /*@-type@*/ /* FIX: union? */
    00290     rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
    00291     /*@=type@*/
    00292     int ec = 0;         /* assume no problems */
    00293     char * t, * te;
    00294     char buf[BUFSIZ];
    00295     int i;
    00296
    00297     te = t = buf;
    00298     *te = '\0';
    00299
    00300 /*@-castexpose@*/
    00301     fi = rpmfiLink(fi, "verifyHeader");
    00302 /*@=castexpose@*/
    00303     fi = rpmfiInit(fi, 0);
    00304     if (fi != NULL)     /* XXX lclint */
    00305     while ((i = rpmfiNext(fi)) >= 0) {
    00306         rpmfileAttrs fflags;
    00307         int rc;
    00308
    00309         fflags = rpmfiFFlags(fi);
    00310
    00311         /* If not querying %config, skip config files. */
    00312         if ((qva->qva_fflags & RPMFILE_CONFIG) && (fflags & RPMFILE_CONFIG))
    00313             continue;
    00314
    00315         /* If not querying %doc, skip doc files. */
    00316         if ((qva->qva_fflags & RPMFILE_DOC) && (fflags & RPMFILE_DOC))
    00317             continue;
    00318
    00319         /* If not verifying %ghost, skip ghost files. */
    00320         /* XXX the broken!!! logic disables %ghost queries always. */
    00321         if (!(qva->qva_fflags & RPMFILE_GHOST) && (fflags & RPMFILE_GHOST))
    00322             continue;
    00323
    00324         rc = rpmVerifyFile(ts, fi, &verifyResult, omitMask);
    00325         if (rc) {
    00326             if (qva->qva_mode != 'v')   /* XXX no output w verify(...) probe. */
    00327             if (!(fflags & (RPMFILE_MISSINGOK|RPMFILE_GHOST)) || rpmIsVerbose()) {
    00328                 sprintf(te, _("missing   %c %s"),
    00329                         ((fflags & RPMFILE_CONFIG)      ? 'c' :
    00330                          (fflags & RPMFILE_DOC)         ? 'd' :
    00331                          (fflags & RPMFILE_GHOST)       ? 'g' :
    00332                          (fflags & RPMFILE_LICENSE)     ? 'l' :
    00333                          (fflags & RPMFILE_PUBKEY)      ? 'P' :
    00334                          (fflags & RPMFILE_README)      ? 'r' : ' '),
    00335                         rpmfiFN(fi));
    00336                 te += strlen(te);
    00337                 if ((verifyResult & RPMVERIFY_LSTATFAIL) != 0 && errno != ENOENT) {
    00338                     sprintf(te, " (%s)", strerror(errno));
    00339                     te += strlen(te);
    00340                 }
    00341                 ec = rc;
    00342             }
    00343         } else if (verifyResult || rpmIsVerbose()) {
    00344             const char * size, * digest, * link, * mtime, * mode;
    00345             const char * group, * user, * rdev;
    00346             /*@observer@*/ static const char *const aok = ".";
    00347             /*@observer@*/ static const char *const unknown = "?";
    00348
    00349             if (!ec)
    00350                 ec = (verifyResult != 0);
    00351
    00352             if (qva->qva_mode != 'v') { /* XXX no output w verify(...) probe. */
    00353 #define _verify(_RPMVERIFY_F, _C)       \
    00354         ((verifyResult & _RPMVERIFY_F) ? _C : aok)
    00355 #define _verifylink(_RPMVERIFY_F, _C)   \
    00356         ((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \
    00357          (verifyResult & _RPMVERIFY_F) ? _C : aok)
    00358 #define _verifyfile(_RPMVERIFY_F, _C)   \
    00359         ((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
    00360          (verifyResult & _RPMVERIFY_F) ? _C : aok)
    00361
    00362                 digest = _verifyfile(RPMVERIFY_FDIGEST, "5");
    00363                 size = _verify(RPMVERIFY_FILESIZE, "S");
    00364                 link = _verifylink(RPMVERIFY_LINKTO, "L");
    00365                 mtime = _verify(RPMVERIFY_MTIME, "T");
    00366                 rdev = _verify(RPMVERIFY_RDEV, "D");
    00367                 user = _verify(RPMVERIFY_USER, "U");
    00368                 group = _verify(RPMVERIFY_GROUP, "G");
    00369                 mode = _verify(RPMVERIFY_MODE, "M");
    00370
    00371 #undef _verifyfile
    00372 #undef _verifylink
    00373 #undef _verify
    00374
    00375                 sprintf(te, "%s%s%s%s%s%s%s%s  %c %s",
    00376                     size, mode, digest, rdev, link, user, group, mtime,
    00377                         ((fflags & RPMFILE_CONFIG)      ? 'c' :
    00378                          (fflags & RPMFILE_DOC) ? 'd' :
    00379                          (fflags & RPMFILE_GHOST)       ? 'g' :
    00380                          (fflags & RPMFILE_LICENSE)     ? 'l' :
    00381                          (fflags & RPMFILE_PUBKEY)      ? 'P' :
    00382                          (fflags & RPMFILE_README)      ? 'r' : ' '),
    00383                         rpmfiFN(fi));
    00384                 te += strlen(te);
    00385             }
    00386         }
    00387
    00388         if (qva->qva_mode != 'v')       /* XXX no output w verify(...) probe. */
    00389         if (te > t) {
    00390             *te++ = '\n';
    00391             *te = '\0';
    00392             rpmlog(RPMLOG_NOTICE, "%s", t);
    00393             te = t = buf;
    00394             *t = '\0';
    00395         }
    00396     }
    00397     fi = rpmfiUnlink(fi, "verifyHeader");
    00398
    00399     return ec;
    00400 }
    00401
    00409 static int verifyDependencies(/*@unused@*/ QVA_t qva, rpmts ts,
    00410                 Header h)
    00411         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00412         /*@modifies ts, h, rpmGlobalMacroContext, fileSystem, internalState @*/
    00413 {
    00414 #ifdef  NOTYET
    00415     int instance = headerGetInstance(h);
    00416 #endif
    00417     rpmps ps;
    00418     int rc = 0;         /* assume no problems */
    00419     int xx;
    00420
    00421     rpmtsEmpty(ts);
    00422 #ifdef  NOTYET
    00423     if (instance > 0)
    00424         (void) rpmtsAddEraseElement(ts, h, instance);
    00425     else
    00426 #endif
    00427         (void) rpmtsAddInstallElement(ts, h, NULL, 0, NULL);
    00428
    00429     xx = rpmtsCheck(ts);
    00430     ps = rpmtsProblems(ts);
    00431
    00432     if (rpmpsNumProblems(ps) > 0) {
    00433         const char * altNEVR;
    00434         const char * pkgNEVR = NULL;
    00435         rpmpsi psi;
    00436         rpmProblem prob;
    00437         char * t, * te;
    00438         int nb = 512;
    00439
    00440         psi = rpmpsInitIterator(ps);
    00441         while (rpmpsNextIterator(psi) >= 0) {
    00442             prob = rpmpsProblem(psi);
    00443             if (pkgNEVR == NULL)
    00444                 pkgNEVR = rpmProblemGetPkgNEVR(prob);
    00445
    00446             altNEVR = rpmProblemGetAltNEVR(prob);
    00447 assert(altNEVR != NULL);
    00448             if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
    00449                 nb += sizeof("\tRequires: ")-1;
    00450             if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
    00451                 nb += sizeof("\tConflicts: ")-1;
    00452             nb += strlen(altNEVR+2) + sizeof("\n") - 1;
    00453
    00454         }
    00455         psi = rpmpsFreeIterator(psi);
    00456
    00457         te = t = alloca(nb);
    00458         *te = '\0';
    00459         sprintf(te, _("Unsatisfied dependencies for %s:\n"), pkgNEVR);
    00460         te += strlen(te);
    00461
    00462         psi = rpmpsInitIterator(ps);
    00463         while (rpmpsNextIterator(psi) >= 0) {
    00464             prob = rpmpsProblem(psi);
    00465
    00466             if ((altNEVR = rpmProblemGetAltNEVR(prob)) == NULL)
    00467                 altNEVR = "? ?altNEVR?";
    00468             if (altNEVR[0] == 'R' && altNEVR[1] == ' ')
    00469                 te = stpcpy(te, "\tRequires: ");
    00470             if (altNEVR[0] == 'C' && altNEVR[1] == ' ')
    00471                 te = stpcpy(te, "\tConflicts: ");
    00472             te = stpcpy( stpcpy(te, altNEVR+2), "\n");
    00473
    00474             rc++;
    00475         }
    00476         psi = rpmpsFreeIterator(psi);
    00477
    00478         if (te > t) {
    00479             *te++ = '\n';
    00480             *te = '\0';
    00481             rpmlog(RPMLOG_NOTICE, "%s", t);
    00482             te = t;
    00483             *t = '\0';
    00484         }
    00485     }
    00486
    00487     ps = rpmpsFree(ps);
    00488
    00489     rpmtsEmpty(ts);
    00490
    00491     return rc;
    00492 }
    00493
    00494 int showVerifyPackage(QVA_t qva, rpmts ts, Header h)
    00495 {
    00496     int scareMem = 0;
    00497     rpmfi fi = NULL;
    00498     int ec = 0;
    00499     int rc;
    00500
    00501     fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
    00502     if (fi != NULL) {
    00503         if (qva->qva_flags & VERIFY_DEPS) {
    00504             int save_noise = _rpmds_unspecified_epoch_noise;
    00505 /*@-mods@*/
    00506             if (rpmIsVerbose())
    00507                 _rpmds_unspecified_epoch_noise = 1;
    00508             if ((rc = verifyDependencies(qva, ts, h)) != 0)
    00509                 ec = rc;
    00510             _rpmds_unspecified_epoch_noise = save_noise;
    00511 /*@=mods@*/
    00512         }
    00513         if (qva->qva_flags & VERIFY_FILES) {
    00514             if ((rc = verifyHeader(qva, ts, fi)) != 0)
    00515                 ec = rc;
    00516         }
    00517         if ((qva->qva_flags & VERIFY_SCRIPT)
    00518          && (headerIsEntry(h, RPMTAG_VERIFYSCRIPT) ||
    00519              headerIsEntry(h, RPMTAG_SANITYCHECK)))
    00520         {
    00521             FD_t fdo = fdDup(STDOUT_FILENO);
    00522
    00523             rc = rpmfiSetHeader(fi, h);
    00524             if ((rc = rpmVerifyScript(qva, ts, fi, fdo)) != 0)
    00525                 ec = rc;
    00526             if (fdo != NULL)
    00527                 rc = Fclose(fdo);
    00528             rc = rpmfiSetHeader(fi, NULL);
    00529         }
    00530
    00531         fi = rpmfiFree(fi);
    00532     }
    00533
    00534     return ec;
    00535 }
    00536
    00537 int rpmcliVerify(rpmts ts, QVA_t qva, const char ** argv)
    00538 {
    00539     rpmdepFlags depFlags = qva->depFlags, odepFlags;
    00540     rpmtransFlags transFlags = qva->transFlags, otransFlags;
    00541     rpmVSFlags vsflags, ovsflags;
    00542     int ec = 0;
    00543
    00544     if (qva->qva_showPackage == NULL)
    00545         qva->qva_showPackage = showVerifyPackage;
    00546
    00547     /* XXX verify flags are inverted from query. */
    00548     vsflags = rpmExpandNumeric("%{?_vsflags_verify}");
    00549     if (!(qva->qva_flags & VERIFY_DIGEST))
    00550         vsflags |= _RPMVSF_NODIGESTS;
    00551     if (!(qva->qva_flags & VERIFY_SIGNATURE))
    00552         vsflags |= _RPMVSF_NOSIGNATURES;
    00553     if (!(qva->qva_flags & VERIFY_HDRCHK))
    00554         vsflags |= RPMVSF_NOHDRCHK;
    00555     vsflags &= ~RPMVSF_NEEDPAYLOAD;
    00556
    00557     odepFlags = rpmtsSetDFlags(ts, depFlags);
    00558     otransFlags = rpmtsSetFlags(ts, transFlags);
    00559     ovsflags = rpmtsSetVSFlags(ts, vsflags);
    00560     ec = rpmcliArgIter(ts, qva, argv);
    00561     vsflags = rpmtsSetVSFlags(ts, ovsflags);
    00562     transFlags = rpmtsSetFlags(ts, otransFlags);
    00563     depFlags = rpmtsSetDFlags(ts, odepFlags);
    00564
    00565     if (qva->qva_showPackage == showVerifyPackage)
    00566         qva->qva_showPackage = NULL;
    00567
    00568     rpmtsEmpty(ts);
    00569
    00570     return ec;
    00571 }