rpm/verify.c

265 lines
6.7 KiB
C

#include "system.h"
#include "build/rpmbuild.h"
#include "install.h"
#include "url.h"
#include "verify.h"
static int verifyHeader(const char * prefix, Header h, int verifyFlags);
static int verifyMatches(const char * prefix, rpmdb db, dbiIndexSet matches,
int verifyFlags);
static int verifyDependencies(rpmdb db, Header h);
static int verifyHeader(const char * prefix, Header h, int verifyFlags) {
const char ** fileList;
int count, type;
int verifyResult;
int i, ec, rc;
int_32 * fileFlagsList;
int omitMask = 0;
ec = 0;
if (!(verifyFlags & VERIFY_MD5)) omitMask = RPMVERIFY_MD5;
if (headerGetEntry(h, RPMTAG_FILEFLAGS, NULL, (void **) &fileFlagsList, NULL) &&
headerGetEntry(h, RPMTAG_FILENAMES, &type, (void **) &fileList, &count)) {
for (i = 0; i < count; i++) {
if ((rc = rpmVerifyFile(prefix, h, i, &verifyResult, omitMask)) != 0) {
fprintf(stdout, _("missing %s\n"), fileList[i]);
} else {
const char * size, * md5, * link, * mtime, * mode;
const char * group, * user, * rdev;
static const char * aok = ".";
static const char * unknown = "?";
if (!verifyResult) continue;
rc = 1;
#define _verify(_RPMVERIFY_F, _C) \
((verifyResult & _RPMVERIFY_F) ? _C : aok)
#define _verifylink(_RPMVERIFY_F, _C) \
((verifyResult & RPMVERIFY_READLINKFAIL) ? unknown : \
(verifyResult & _RPMVERIFY_F) ? _C : aok)
#define _verifyfile(_RPMVERIFY_F, _C) \
((verifyResult & RPMVERIFY_READFAIL) ? unknown : \
(verifyResult & _RPMVERIFY_F) ? _C : aok)
md5 = _verifyfile(RPMVERIFY_MD5, "5");
size = _verify(RPMVERIFY_FILESIZE, "S");
link = _verifylink(RPMVERIFY_LINKTO, "L");
mtime = _verify(RPMVERIFY_MTIME, "T");
rdev = _verify(RPMVERIFY_RDEV, "D");
user = _verify(RPMVERIFY_USER, "U");
group = _verify(RPMVERIFY_GROUP, "G");
mode = _verify(RPMVERIFY_MODE, "M");
#undef _verify
#undef _verifylink
#undef _verifyfile
fprintf(stdout, "%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]);
}
if (rc)
ec = rc;
}
free(fileList);
}
return ec;
}
static int verifyDependencies(rpmdb db, Header h) {
rpmTransactionSet rpmdep;
struct rpmDependencyConflict * conflicts;
int numConflicts;
const char * name, * version, * release;
int type, count, i;
rpmdep = rpmtransCreateSet(db, NULL);
rpmtransAddPackage(rpmdep, h, NULL, NULL, 0, NULL);
rpmdepCheck(rpmdep, &conflicts, &numConflicts);
rpmtransFree(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);
fprintf(stdout, _("Unsatisfied dependencies for %s-%s-%s: "),
name, version, release);
for (i = 0; i < numConflicts; i++) {
if (i) fprintf(stdout, ", ");
fprintf(stdout, "%s", conflicts[i].needsName);
if (conflicts[i].needsFlags) {
printDepFlags(stdout, conflicts[i].needsVersion,
conflicts[i].needsFlags);
}
}
fprintf(stdout, "\n");
rpmdepFreeConflicts(conflicts, numConflicts);
return 1;
}
return 0;
}
static int verifyPackage(const char * root, rpmdb db, Header h, int verifyFlags) {
int ec, rc;
FD_t fdo;
ec = 0;
if ((verifyFlags & VERIFY_DEPS) &&
(rc = verifyDependencies(db, h)) != 0)
ec = rc;
if ((verifyFlags & VERIFY_FILES) &&
(rc = verifyHeader(root, h, verifyFlags)) != 0)
ec = rc;;
fdo = fdDup(STDOUT_FILENO);
if ((verifyFlags & VERIFY_SCRIPT) &&
(rc = rpmVerifyScript(root, h, fdo)) != 0)
ec = rc;
fdClose(fdo);
return ec;
}
static int verifyMatches(const char * prefix, rpmdb db, dbiIndexSet matches,
int verifyFlags) {
int ec, rc;
int i;
Header h;
ec = 0;
for (i = 0; i < dbiIndexSetCount(matches); i++) {
unsigned int recOffset = dbiIndexRecordOffset(matches, i);
if (recOffset == 0)
continue;
rpmMessage(RPMMESS_DEBUG, _("verifying record number %u\n"),
recOffset);
h = rpmdbGetRecord(db, recOffset);
if (h == NULL) {
fprintf(stderr, _("error: could not read database record\n"));
ec = 1;
} else {
if ((rc = verifyPackage(prefix, db, h, verifyFlags)) != 0)
ec = rc;
headerFree(h);
}
}
return ec;
}
int doVerify(const char * prefix, enum verifysources source, const char ** argv,
int verifyFlags) {
Header h;
int offset;
int ec, rc;
int isSource;
rpmdb db;
dbiIndexSet matches;
ec = 0;
if (source == VERIFY_RPM && !(verifyFlags & VERIFY_DEPS)) {
db = NULL;
} else {
if (rpmdbOpen(prefix, &db, O_RDONLY, 0644)) {
return 1; /* XXX was exit(EXIT_FAILURE) */
}
}
if (source == VERIFY_EVERY) {
for (offset = rpmdbFirstRecNum(db);
offset != 0;
offset = rpmdbNextRecNum(db, offset)) {
h = rpmdbGetRecord(db, offset);
if (h == NULL) {
fprintf(stderr, _("could not read database record!\n"));
return 1; /* XXX was exit(EXIT_FAILURE) */
}
if ((rc = verifyPackage(prefix, db, h, verifyFlags)) != 0)
ec = rc;
headerFree(h);
}
} else {
while (*argv) {
const char *arg = *argv++;
rc = 0;
switch (source) {
case VERIFY_RPM:
{ FD_t fd;
fd = ufdOpen(arg, O_RDONLY, 0);
if (fd == NULL) {
fprintf(stderr, _("open of %s failed\n"), arg);
break;
}
if (fdFileno(fd) >= 0) {
rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
}
ufdClose(fd);
switch (rc) {
case 0:
rc = verifyPackage(prefix, db, h, verifyFlags);
headerFree(h);
break;
case 1:
fprintf(stderr, _("%s is not an RPM\n"), arg);
break;
}
} break;
case VERIFY_GRP:
if (rpmdbFindByGroup(db, arg, &matches)) {
fprintf(stderr,
_("group %s does not contain any packages\n"),
arg);
} else {
rc = verifyMatches(prefix, db, matches, verifyFlags);
dbiFreeIndexRecord(matches);
}
break;
case VERIFY_PATH:
if (rpmdbFindByFile(db, arg, &matches)) {
fprintf(stderr, _("file %s is not owned by any package\n"),
arg);
} else {
rc = verifyMatches(prefix, db, matches, verifyFlags);
dbiFreeIndexRecord(matches);
}
break;
case VERIFY_PACKAGE:
rc = rpmdbFindByLabel(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 {
rc = verifyMatches(prefix, db, matches, verifyFlags);
dbiFreeIndexRecord(matches);
}
break;
case VERIFY_EVERY:
break;
}
if (rc)
ec = rc;
}
}
if (source != VERIFY_RPM) {
rpmdbClose(db);
}
return ec;
}