#include #include #include #include #include #include "lib/messages.h" #include "install.h" #include "query.h" #include "rpmlib.h" #include "url.h" #include "verify.h" static void verifyHeader(char * prefix, Header h, int verifyFlags); static void verifyMatches(char * prefix, rpmdb db, dbiIndexSet matches, int verifyFlags); static void verifyDependencies(rpmdb db, Header h); static void verifyHeader(char * prefix, Header h, int verifyFlags) { char ** fileList; int count, type; int verifyResult; int i; char * size, * md5, * link, * mtime, * mode; char * group, * user, * rdev; int_32 * fileFlagsList; int omitMask = 0; if (!(verifyFlags & VERIFY_MD5)) omitMask = RPMVERIFY_MD5; headerGetEntry(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlagsList, NULL); if (headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count)) { for (i = 0; i < count; i++) { if (rpmVerifyFile(prefix, h, i, &verifyResult, omitMask)) printf("missing %s\n", fileList[i]); else { size = md5 = link = mtime = mode = "."; user = group = rdev = "."; if (!verifyResult) continue; if (verifyResult & RPMVERIFY_MD5) md5 = "5"; if (verifyResult & RPMVERIFY_FILESIZE) size = "S"; if (verifyResult & RPMVERIFY_LINKTO) link = "L"; if (verifyResult & RPMVERIFY_MTIME) mtime = "T"; if (verifyResult & RPMVERIFY_RDEV) rdev = "D"; if (verifyResult & RPMVERIFY_USER) user = "U"; if (verifyResult & RPMVERIFY_GROUP) group = "G"; if (verifyResult & RPMVERIFY_MODE) mode = "M"; printf("%s%s%s%s%s%s%s%s %c %s\n", size, mode, md5, rdev, link, user, group, mtime, fileFlagsList[i] & RPMFILE_CONFIG ? 'c' : ' ', fileList[i]); } } free(fileList); } } static void verifyDependencies(rpmdb db, Header h) { rpmDependencies rpmdep; struct rpmDependencyConflict * conflicts; int numConflicts; char * name, * version, * release; int type, count, i; rpmdep = rpmdepDependencies(db); rpmdepAddPackage(rpmdep, h); rpmdepCheck(rpmdep, &conflicts, &numConflicts); rpmdepDone(rpmdep); if (numConflicts) { headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count); headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &version, &count); headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &release, &count); printf("Unsatisfied dependencies for %s-%s-%s: ", name, version, release); for (i = 0; i < numConflicts; i++) { if (i) printf(", "); printf("%s", conflicts[i].needsName); if (conflicts[i].needsFlags) { printDepFlags(stdout, conflicts[i].needsVersion, conflicts[i].needsFlags); } } printf("\n"); rpmdepFreeConflicts(conflicts, numConflicts); } } static void verifyPackage(char * root, rpmdb db, Header h, int verifyFlags) { if (verifyFlags & VERIFY_DEPS) verifyDependencies(db, h); if (verifyFlags & VERIFY_FILES) verifyHeader(root, h, verifyFlags); if (verifyFlags & VERIFY_SCRIPT) { rpmVerifyScript(root, h, 1); } } static void verifyMatches(char * prefix, rpmdb db, dbiIndexSet matches, int verifyFlags) { int i; Header h; for (i = 0; i < matches.count; i++) { if (matches.recs[i].recOffset) { rpmMessage(RPMMESS_DEBUG, "verifying record number %d\n", matches.recs[i].recOffset); h = rpmdbGetRecord(db, matches.recs[i].recOffset); if (!h) { fprintf(stderr, "error: could not read database record\n"); } else { verifyPackage(prefix, db, h, verifyFlags); headerFree(h); } } } } void doVerify(char * prefix, enum verifysources source, char ** argv, int verifyFlags) { Header h; int offset; int fd; int rc; int isSource; rpmdb db; dbiIndexSet matches; struct urlContext context; char * arg; int isUrl; char path[255]; if (source == VERIFY_RPM && !(verifyFlags & VERIFY_DEPS)) { db = NULL; } else { if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) { exit(1); } } if (source == VERIFY_EVERY) { offset = rpmdbFirstRecNum(db); while (offset) { h = rpmdbGetRecord(db, offset); if (!h) { fprintf(stderr, "could not read database record!\n"); exit(1); } verifyPackage(prefix, db, h, verifyFlags); headerFree(h); offset = rpmdbNextRecNum(db, offset); } } else { while (*argv) { arg = *argv++; switch (source) { case VERIFY_RPM: if (urlIsURL(arg)) { isUrl = 1; if ((fd = urlGetFd(arg, &context)) < 0) { fprintf(stderr, "open of %s failed: %s\n", arg, ftpStrerror(fd)); } } else if (!strcmp(arg, "-")) { fd = 0; } else { if ((fd = open(arg, O_RDONLY)) < 0) { fprintf(stderr, "open of %s failed: %s\n", arg, strerror(errno)); } } if (fd >= 0) { rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL); close(fd); switch (rc) { case 0: verifyPackage(prefix, db, h, verifyFlags); headerFree(h); break; case 1: fprintf(stderr, "%s is not an RPM\n", arg); } } break; case VERIFY_GRP: if (rpmdbFindByGroup(db, arg, &matches)) { fprintf(stderr, "group %s does not contain any pacakges\n", arg); } else { verifyMatches(prefix, db, matches, verifyFlags); dbiFreeIndexRecord(matches); } break; case VERIFY_PATH: if (*arg != '/') { if (realpath(arg, path) != NULL) arg = path; } if (rpmdbFindByFile(db, arg, &matches)) { fprintf(stderr, "file %s is not owned by any package\n", arg); } else { verifyMatches(prefix, db, matches, verifyFlags); dbiFreeIndexRecord(matches); } break; case VERIFY_PACKAGE: rc = findPackageByLabel(db, arg, &matches); if (rc == 1) fprintf(stderr, "package %s is not installed\n", arg); else if (rc == 2) { fprintf(stderr, "error looking for package %s\n", arg); } else { verifyMatches(prefix, db, matches, verifyFlags); dbiFreeIndexRecord(matches); } break; case VERIFY_EVERY: ; /* nop */ } } } if (source != VERIFY_RPM) { rpmdbClose(db); } }