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

lib/verify.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmcli.h>
00009 
00010 #include "psm.h"
00011 #include "md5.h"
00012 #include "misc.h"       /* XXX for uidToUname() and gnameToGid() */
00013 #include "debug.h"
00014 
00015 /*@access TFI_t*/
00016 /*@access PSM_t*/
00017 /*@access FD_t*/        /* XXX compared with NULL */
00018 /*@access rpmdb*/       /* XXX compared with NULL */
00019 
00020 static int _ie = 0x44332211;
00021 static union _vendian {
00022 /*@unused@*/ int i;
00023     char b[4];
00024 } *_endian = (union _vendian *)&_ie;
00025 #define IS_BIG_ENDIAN()         (_endian->b[0] == '\x44')
00026 #define IS_LITTLE_ENDIAN()      (_endian->b[0] == '\x11')
00027 
00028 #define S_ISDEV(m) (S_ISBLK((m)) || S_ISCHR((m)))
00029 
00030 int rpmVerifyFile(const char * root, Header h, int filenum,
00031                 rpmVerifyAttrs * result, rpmVerifyAttrs omitMask)
00032 {
00033     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00034     HFD_t hfd = headerFreeData;
00035     int_32 * fileFlags;
00036     rpmfileAttrs fileAttrs = RPMFILE_NONE;
00037     int_32 * verifyFlags;
00038     rpmVerifyAttrs flags = RPMVERIFY_ALL;
00039     unsigned short * modeList;
00040     const char * fileStatesList;
00041     const char * filespec = NULL;
00042     int count;
00043     int rc;
00044     struct stat sb;
00045     int_32 useBrokenMd5;
00046 
00047   if (IS_BIG_ENDIAN()) {        /* XXX was ifdef WORDS_BIGENDIAN */
00048     int_32 * brokenPtr;
00049     if (!hge(h, RPMTAG_BROKENMD5, NULL, (void **) &brokenPtr, NULL)) {
00050         HAE_t hae = (HAE_t)headerAddEntry;
00051         const char * rpmVersion;
00052 
00053         if (hge(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmVersion, NULL)) {
00054             useBrokenMd5 = ((rpmvercmp(rpmVersion, "2.3.3") >= 0) &&
00055                             (rpmvercmp(rpmVersion, "2.3.8") <= 0));
00056         } else {
00057             useBrokenMd5 = 1;
00058         }
00059         (void) hae(h, RPMTAG_BROKENMD5, RPM_INT32_TYPE, &useBrokenMd5, 1);
00060     } else {
00061         useBrokenMd5 = *brokenPtr;
00062     }
00063   } else {
00064     useBrokenMd5 = 0;
00065   }
00066 
00067     (void) hge(h, RPMTAG_FILEMODES, NULL, (void **) &modeList, &count);
00068     if (hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlags, NULL))
00069         fileAttrs = fileFlags[filenum];
00070 
00071     if (hge(h, RPMTAG_FILEVERIFYFLAGS, NULL, (void **) &verifyFlags, NULL))
00072         flags = verifyFlags[filenum];
00073 
00074     {
00075         const char ** baseNames;
00076         const char ** dirNames;
00077         int_32 * dirIndexes;
00078         rpmTagType bnt, dnt;
00079 
00080         if (hge(h, RPMTAG_BASENAMES, &bnt, (void **) &baseNames, NULL)
00081         &&  hge(h, RPMTAG_DIRNAMES, &dnt, (void **) &dirNames, NULL)
00082         &&  hge(h, RPMTAG_DIRINDEXES, NULL, (void **) &dirIndexes, NULL))
00083         {
00084             int nb = (strlen(dirNames[dirIndexes[filenum]]) + 
00085                       strlen(baseNames[filenum]) + strlen(root) + 5);
00086             char * t = alloca(nb);
00087             filespec = t;
00088             *t = '\0';
00089             if (root && !(root[0] == '/' && root[1] == '\0')) {
00090                 t = stpcpy(t, root);
00091                 while (t > filespec && t[-1] == '/') {
00092                     --t;
00093                     *t = '\0';
00094                 }
00095             }
00096             t = stpcpy(t, dirNames[dirIndexes[filenum]]);
00097             t = stpcpy(t, baseNames[filenum]);
00098         }
00099         baseNames = hfd(baseNames, bnt);
00100         dirNames = hfd(dirNames, dnt);
00101     }
00102 
00103     *result = RPMVERIFY_NONE;
00104 
00105     /*
00106      * Check to see if the file was installed - if not pretend all is OK.
00107      */
00108     if (hge(h, RPMTAG_FILESTATES, NULL, (void **) &fileStatesList, NULL) &&
00109         fileStatesList != NULL)
00110     {
00111         rpmfileState fstate = fileStatesList[filenum];
00112         switch (fstate) {
00113         case RPMFILE_STATE_NETSHARED:
00114         case RPMFILE_STATE_REPLACED:
00115         case RPMFILE_STATE_NOTINSTALLED:
00116             return 0;
00117             /*@notreached@*/ break;
00118         case RPMFILE_STATE_NORMAL:
00119             break;
00120         }
00121     }
00122 
00123     if (filespec == NULL) {
00124         *result |= RPMVERIFY_LSTATFAIL;
00125         return 1;
00126     }
00127 
00128     if (Lstat(filespec, &sb) != 0) {
00129         *result |= RPMVERIFY_LSTATFAIL;
00130         return 1;
00131     }
00132 
00133     /*
00134      * Not all attributes of non-regular files can be verified.
00135      */
00136     if (S_ISDIR(sb.st_mode))
00137         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
00138                         RPMVERIFY_LINKTO);
00139     else if (S_ISLNK(sb.st_mode)) {
00140         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME |
00141                 RPMVERIFY_MODE);
00142 #if CHOWN_FOLLOWS_SYMLINK
00143             flags &= ~(RPMVERIFY_USER | RPMVERIFY_GROUP);
00144 #endif
00145     }
00146     else if (S_ISFIFO(sb.st_mode))
00147         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
00148                         RPMVERIFY_LINKTO);
00149     else if (S_ISCHR(sb.st_mode))
00150         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
00151                         RPMVERIFY_LINKTO);
00152     else if (S_ISBLK(sb.st_mode))
00153         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
00154                         RPMVERIFY_LINKTO);
00155     else 
00156         flags &= ~(RPMVERIFY_LINKTO);
00157 
00158     /*
00159      * Content checks of %ghost files are meaningless.
00160      */
00161     if (fileAttrs & RPMFILE_GHOST)
00162         flags &= ~(RPMVERIFY_MD5 | RPMVERIFY_FILESIZE | RPMVERIFY_MTIME | 
00163                         RPMVERIFY_LINKTO);
00164 
00165     /*
00166      * Don't verify any features in omitMask.
00167      */
00168     flags &= ~(omitMask | RPMVERIFY_LSTATFAIL|RPMVERIFY_READFAIL|RPMVERIFY_READLINKFAIL);
00169 
00170     if (flags & RPMVERIFY_MD5) {
00171         unsigned char md5sum[40];
00172         const char ** md5List;
00173         rpmTagType mdt;
00174 
00175         if (!hge(h, RPMTAG_FILEMD5S, &mdt, (void **) &md5List, NULL))
00176             *result |= RPMVERIFY_MD5;
00177         else {
00178             if (useBrokenMd5)
00179                 rc = mdfileBroken(filespec, md5sum);
00180             else
00181                 rc = mdfile(filespec, md5sum);
00182 
00183             if (rc)
00184                 *result |= (RPMVERIFY_READFAIL|RPMVERIFY_MD5);
00185             else if (strcmp(md5sum, md5List[filenum]))
00186                 *result |= RPMVERIFY_MD5;
00187         }
00188         md5List = hfd(md5List, mdt);
00189     } 
00190 
00191     if (flags & RPMVERIFY_LINKTO) {
00192         char linkto[1024];
00193         int size = 0;
00194         const char ** linktoList;
00195         rpmTagType ltt;
00196 
00197         if (!hge(h, RPMTAG_FILELINKTOS, &ltt, (void **) &linktoList, NULL)
00198         || (size = Readlink(filespec, linkto, sizeof(linkto)-1)) == -1)
00199             *result |= (RPMVERIFY_READLINKFAIL|RPMVERIFY_LINKTO);
00200         else {
00201             linkto[size] = '\0';
00202             if (strcmp(linkto, linktoList[filenum]))
00203                 *result |= RPMVERIFY_LINKTO;
00204         }
00205         linktoList = hfd(linktoList, ltt);
00206     } 
00207 
00208     if (flags & RPMVERIFY_FILESIZE) {
00209         int_32 * sizeList;
00210 
00211         if (!hge(h, RPMTAG_FILESIZES, NULL, (void **) &sizeList, NULL)
00212         || sizeList[filenum] != sb.st_size)
00213             *result |= RPMVERIFY_FILESIZE;
00214     } 
00215 
00216     if (flags & RPMVERIFY_MODE) {
00217         unsigned short metamode = modeList[filenum];
00218         unsigned short filemode;
00219 
00220         /*
00221          * Platforms (like AIX) where sizeof(unsigned short) != sizeof(mode_t)
00222          * need the (unsigned short) cast here. 
00223          */
00224         filemode = (unsigned short)sb.st_mode;
00225 
00226         /*
00227          * Comparing the type of %ghost files is meaningless, but perms are OK.
00228          */
00229         if (fileAttrs & RPMFILE_GHOST) {
00230             metamode &= ~0xf000;
00231             filemode &= ~0xf000;
00232         }
00233 
00234         if (metamode != filemode)
00235             *result |= RPMVERIFY_MODE;
00236     }
00237 
00238     if (flags & RPMVERIFY_RDEV) {
00239         if (S_ISCHR(modeList[filenum]) != S_ISCHR(sb.st_mode) ||
00240             S_ISBLK(modeList[filenum]) != S_ISBLK(sb.st_mode))
00241         {
00242             *result |= RPMVERIFY_RDEV;
00243         } else if (S_ISDEV(modeList[filenum]) && S_ISDEV(sb.st_mode)) {
00244             unsigned short * rdevList;
00245             if (!hge(h, RPMTAG_FILERDEVS, NULL, (void **) &rdevList, NULL)
00246             || rdevList[filenum] != sb.st_rdev)
00247                 *result |= RPMVERIFY_RDEV;
00248         } 
00249     }
00250 
00251     if (flags & RPMVERIFY_MTIME) {
00252         int_32 * mtimeList;
00253 
00254         if (!hge(h, RPMTAG_FILEMTIMES, NULL, (void **) &mtimeList, NULL)
00255         ||  mtimeList[filenum] != sb.st_mtime)
00256             *result |= RPMVERIFY_MTIME;
00257     }
00258 
00259     if (flags & RPMVERIFY_USER) {
00260         const char * name;
00261         const char ** unameList;
00262         int_32 * uidList;
00263         rpmTagType unt;
00264 
00265         if (hge(h, RPMTAG_FILEUSERNAME, &unt, (void **) &unameList, NULL)) {
00266             name = uidToUname(sb.st_uid);
00267             if (!name || strcmp(unameList[filenum], name))
00268                 *result |= RPMVERIFY_USER;
00269             unameList = hfd(unameList, unt);
00270         } else if (hge(h, RPMTAG_FILEUIDS, NULL, (void **) &uidList, NULL)) {
00271             if (uidList[filenum] != sb.st_uid)
00272                 *result |= RPMVERIFY_GROUP;
00273         } else {
00274             rpmError(RPMERR_INTERNAL, _("package lacks both user name and id "
00275                   "lists (this should never happen)\n"));
00276             *result |= RPMVERIFY_GROUP;
00277         }
00278     }
00279 
00280     if (flags & RPMVERIFY_GROUP) {
00281         const char ** gnameList;
00282         int_32 * gidList;
00283         rpmTagType gnt;
00284         gid_t gid;
00285 
00286         if (hge(h, RPMTAG_FILEGROUPNAME, &gnt, (void **) &gnameList, NULL)) {
00287             rc =  gnameToGid(gnameList[filenum], &gid);
00288             if (rc || (gid != sb.st_gid))
00289                 *result |= RPMVERIFY_GROUP;
00290             gnameList = hfd(gnameList, gnt);
00291         } else if (hge(h, RPMTAG_FILEGIDS, NULL, (void **) &gidList, NULL)) {
00292             if (gidList[filenum] != sb.st_gid)
00293                 *result |= RPMVERIFY_GROUP;
00294         } else {
00295             rpmError(RPMERR_INTERNAL, _("package lacks both group name and id "
00296                      "lists (this should never happen)\n"));
00297             *result |= RPMVERIFY_GROUP;
00298         }
00299     }
00300 
00301     return 0;
00302 }
00303 
00312 int rpmVerifyScript(const char * rootDir, Header h, /*@null@*/ FD_t scriptFd)
00313 {
00314     rpmdb rpmdb = NULL;
00315     rpmTransactionSet ts = rpmtransCreateSet(rpmdb, rootDir);
00316     TFI_t fi = xcalloc(1, sizeof(*fi));
00317     struct psm_s psmbuf;
00318     PSM_t psm = &psmbuf;
00319     int rc;
00320 
00321     if (scriptFd != NULL)
00322         ts->scriptFd = fdLink(scriptFd, "rpmVerifyScript");
00323     fi->magic = TFIMAGIC;
00324     loadFi(h, fi);
00325     memset(psm, 0, sizeof(*psm));
00326     psm->ts = ts;
00327     psm->fi = fi;
00328     psm->stepName = "verify";
00329     psm->scriptTag = RPMTAG_VERIFYSCRIPT;
00330     psm->progTag = RPMTAG_VERIFYSCRIPTPROG;
00331     rc = psmStage(psm, PSM_SCRIPT);
00332     freeFi(fi);
00333     fi = _free(fi);
00334     ts = rpmtransFree(ts);
00335     return rc;
00336 }
00337 
00338 int rpmVerifyDigest(Header h)
00339 {
00340     HGE_t hge = (HGE_t)headerGetEntry;  /* XXX headerGetEntryMinMemory? */
00341     HFD_t hfd = headerFreeData;
00342     void * uh = NULL;
00343     rpmTagType uht;
00344     int_32 uhc;
00345     const char * hdigest;
00346     rpmTagType hdt;
00347     int flags = RPMDIGEST_SHA1;
00348     int ec = 0;         /* assume no problems */
00349 
00350     /* Retrieve header digest. */
00351     if (!hge(h, RPMTAG_SHA1HEADER, &hdt, (void **) &hdigest, NULL)
00352     &&  !hge(h, RPMTAG_SHA1RHN, &hdt, (void **) &hdigest, NULL))
00353     {
00354         if (hge(h, RPMTAG_BADSHA1HEADER, &hdt, (void **) &hdigest, NULL))
00355             flags |= (RPMDIGEST_REVERSE|RPMDIGEST_BCSWAP);
00356         else
00357             return 0;
00358     }
00359     /* Regenerate original header. */
00360     if (!hge(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00361         return 0;
00362 
00363     if (hdigest == NULL || uh == NULL)
00364         return 0;
00365 
00366     /* Compute header digest. */
00367     {   DIGEST_CTX ctx = rpmDigestInit(flags);
00368         const char * digest;
00369         size_t digestlen;
00370 
00371         rpmDigestUpdate(ctx, uh, uhc);
00372         rpmDigestFinal(ctx, (void **)&digest, &digestlen, 1);
00373 
00374         /* XXX can't happen: report NULL malloc return as a digest failure. */
00375         ec = (digest == NULL || strcmp(hdigest, digest)) ? 1 : 0;
00376         digest = _free(digest);
00377     }
00378 
00379     uh = hfd(uh, uht);
00380     hdigest = hfd(hdigest, hdt);
00381 
00382     return ec;
00383 }
00384 
00390 static int verifyHeader(QVA_t qva, Header h)
00391         /*@modifies h @*/
00392 {
00393     HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00394     char buf[BUFSIZ];
00395     char * t, * te;
00396     const char * prefix = (qva->qva_prefix ? qva->qva_prefix : "");
00397     const char ** fileNames = NULL;
00398     int count;
00399     int_32 * fileFlags = NULL;
00400     rpmVerifyAttrs verifyResult = 0;
00401     rpmVerifyAttrs omitMask = ((qva->qva_flags & VERIFY_ATTRS) ^ VERIFY_ATTRS);
00402     int ec = 0;         /* assume no problems */
00403     int i;
00404 
00405     te = t = buf;
00406     *te = '\0';
00407 
00408     if (!hge(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlags, NULL))
00409         goto exit;
00410 
00411     if (!headerIsEntry(h, RPMTAG_BASENAMES))
00412         goto exit;
00413 
00414     rpmBuildFileList(h, &fileNames, &count);
00415 
00416     for (i = 0; i < count; i++) {
00417         rpmfileAttrs fileAttrs;
00418         int rc;
00419 
00420         fileAttrs = fileFlags[i];
00421 
00422         /* If not verifying %ghost, skip ghost files. */
00423         if (!(qva->qva_fflags & RPMFILE_GHOST)
00424         && (fileAttrs & RPMFILE_GHOST))
00425             continue;
00426 
00427         rc = rpmVerifyFile(prefix, h, i, &verifyResult, omitMask);
00428         if (rc) {
00429             if (!(fileAttrs & RPMFILE_MISSINGOK) || rpmIsVerbose()) {
00430                 sprintf(te, _("missing    %s"), fileNames[i]);
00431                 te += strlen(te);
00432                 ec = rc;
00433             }
00434         } else if (verifyResult) {
00435             const char * size, * md5, * link, * mtime, * mode;
00436             const char * group, * user, * rdev;
00437             /*@observer@*/ static const char *const aok = ".";
00438             /*@observer@*/ static const char *const unknown = "?";
00439 
00440             ec = 1;
00441 
00442 #define _verify(_RPMVERIFY_F, _C)       \
00443         ((verifyResult & _RPMVERIFY_F) ? _C : aok)
00444 #define _verifylink(_RPMVERIFY_F, _C)   \
00445         ((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \
00446          (verifyResult & _RPMVERIFY_F) ? _C : aok)
00447 #define _verifyfile(_RPMVERIFY_F, _C)   \
00448         ((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
00449          (verifyResult & _RPMVERIFY_F) ? _C : aok)
00450         
00451             md5 = _verifyfile(RPMVERIFY_MD5, "5");
00452             size = _verify(RPMVERIFY_FILESIZE, "S");
00453             link = _verifylink(RPMVERIFY_LINKTO, "L");
00454             mtime = _verify(RPMVERIFY_MTIME, "T");
00455             rdev = _verify(RPMVERIFY_RDEV, "D");
00456             user = _verify(RPMVERIFY_USER, "U");
00457             group = _verify(RPMVERIFY_GROUP, "G");
00458             mode = _verify(RPMVERIFY_MODE, "M");
00459 
00460 #undef _verify
00461 #undef _verifylink
00462 #undef _verifyfile
00463 
00464             sprintf(te, "%s%s%s%s%s%s%s%s %c %s",
00465                         size, mode, md5, rdev, link, user, group, mtime, 
00466                         ((fileAttrs & RPMFILE_CONFIG)   ? 'c' :
00467                          (fileAttrs & RPMFILE_DOC)      ? 'd' :
00468                          (fileAttrs & RPMFILE_GHOST)    ? 'g' :
00469                          (fileAttrs & RPMFILE_LICENSE)  ? 'l' :
00470                          (fileAttrs & RPMFILE_README)   ? 'r' : ' '), 
00471                         fileNames[i]);
00472             te += strlen(te);
00473         }
00474 
00475         if (te > t) {
00476             *te++ = '\n';
00477             *te = '\0';
00478             rpmMessage(RPMMESS_NORMAL, "%s", t);
00479             te = t = buf;
00480             *t = '\0';
00481         }
00482     }
00483         
00484 exit:
00485     fileNames = _free(fileNames);
00486     return ec;
00487 }
00488 
00495 static int verifyDependencies(rpmdb rpmdb, Header h)
00496         /*@modifies h @*/
00497 {
00498     rpmTransactionSet ts;
00499     rpmDependencyConflict conflicts;
00500     int numConflicts;
00501     int rc = 0;         /* assume no problems */
00502     int i;
00503 
00504     ts = rpmtransCreateSet(rpmdb, NULL);
00505     (void) rpmtransAddPackage(ts, h, NULL, NULL, 0, NULL);
00506 
00507     (void) rpmdepCheck(ts, &conflicts, &numConflicts);
00508     ts = rpmtransFree(ts);
00509 
00510     if (numConflicts) {
00511         const char *n, *v, *r;
00512         char * t, * te;
00513         int nb = 512;
00514         (void) headerNVR(h, &n, &v, &r);
00515 
00516         for (i = 0; i < numConflicts; i++) {
00517             nb += strlen(conflicts[i].needsName) + sizeof(", ") - 1;
00518             if (conflicts[i].needsFlags)
00519                 nb += strlen(conflicts[i].needsVersion) + 5;
00520         }
00521         te = t = alloca(nb);
00522         *te = '\0';
00523         sprintf(te, _("Unsatisfied dependencies for %s-%s-%s: "), n, v, r);
00524         te += strlen(te);
00525         for (i = 0; i < numConflicts; i++) {
00526             if (i) te = stpcpy(te, ", ");
00527             te = stpcpy(te, conflicts[i].needsName);
00528             if (conflicts[i].needsFlags) {
00529                 int flags = conflicts[i].needsFlags;
00530                 *te++ = ' ';
00531                 if (flags & RPMSENSE_LESS)      *te++ = '<';
00532                 if (flags & RPMSENSE_GREATER)   *te++ = '>';
00533                 if (flags & RPMSENSE_EQUAL)     *te++ = '=';
00534                 *te++ = ' ';
00535                 te = stpcpy(te, conflicts[i].needsVersion);
00536             }
00537         }
00538         conflicts = rpmdepFreeConflicts(conflicts, numConflicts);
00539         if (te > t) {
00540             *te++ = '\n';
00541             *te = '\0';
00542             rpmMessage(RPMMESS_NORMAL, "%s", t);
00543             te = t;
00544             *t = '\0';
00545         }
00546         rc = 1;
00547     }
00548     return rc;
00549 }
00550 
00551 int showVerifyPackage(QVA_t qva, rpmdb rpmdb, Header h)
00552 {
00553     const char * prefix = (qva->qva_prefix ? qva->qva_prefix : "");
00554     int ec = 0;
00555     int rc;
00556 
00557     if (qva->qva_flags & VERIFY_DIGEST) {
00558         if ((rc = rpmVerifyDigest(h)) != 0) {
00559             const char *n, *v, *r;
00560             (void) headerNVR(h, &n, &v, &r);
00561             rpmMessage(RPMMESS_NORMAL,
00562                    _("%s-%s-%s: immutable header region digest check failed\n"),
00563                         n, v, r);
00564             ec = rc;
00565         }
00566     }
00567     if (qva->qva_flags & VERIFY_DEPS) {
00568         if ((rc = verifyDependencies(rpmdb, h)) != 0)
00569             ec = rc;
00570     }
00571     if (qva->qva_flags & VERIFY_FILES) {
00572         if ((rc = verifyHeader(qva, h)) != 0)
00573             ec = rc;
00574     }
00575     if (qva->qva_flags & VERIFY_SCRIPT) {
00576         FD_t fdo = fdDup(STDOUT_FILENO);
00577         if ((rc = rpmVerifyScript(prefix, h, fdo)) != 0)
00578             ec = rc;
00579         if (fdo)
00580             rc = Fclose(fdo);
00581     }
00582     return ec;
00583 }
00584 
00585 int rpmVerify(QVA_t qva, rpmQVSources source, const char * arg)
00586 {
00587     rpmdb rpmdb = NULL;
00588     int rc;
00589 
00590     switch (source) {
00591     case RPMQV_RPM:
00592         if (!(qva->qva_flags & VERIFY_DEPS))
00593             break;
00594         /*@fallthrough@*/
00595     default:
00596         if ((rc = rpmdbOpen(qva->qva_prefix, &rpmdb, O_RDONLY, 0644)) != 0)
00597             return 1;
00598         break;
00599     }
00600 
00601     rc = rpmQueryVerify(qva, source, arg, rpmdb, showVerifyPackage);
00602 
00603     if (rpmdb != NULL)
00604         (void) rpmdbClose(rpmdb);
00605 
00606     return rc;
00607 }

Generated on Wed Mar 13 15:34:49 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002