#include #include #include #include #include #include #include #include "hash.h" #define MAXPKGS 1024 void compareFileList(int availFileCount, char **availFiles, int installedFileCount, char **installedFiles, struct hash_table *ht) { int installedX, availX, rc; availX = 0; installedX = 0; while (installedX < installedFileCount) { if (availX == availFileCount) { /* All the rest have moved */ /* printf("=> %s\n", installedFiles[installedX]); */ add_to_table(ht, installedFiles[installedX]); installedX++; } else { rc = strcmp(availFiles[availX], installedFiles[installedX]); if (rc > 0) { /* Avail > Installed -- file has moved */ /* printf("=> %s\n", installedFiles[installedX]); */ add_to_table(ht, installedFiles[installedX]); installedX++; } else if (rc < 0) { /* Avail < Installed -- avail has some new files */ availX++; } else { /* Files are equal -- file not moved */ availX++; installedX++; } } } } void errorFunction(void) { } int findUpgradePackages(rpmdb db, int ugdbfd, struct hash_table *ht, int *resultArray, int *availPkgs) { int pkgNum, skipThis; Header h, installedHeader; char *name, *version, *release; dbIndexSet matches; int rc, i; char **installedFiles, **availFiles; int installedFileCount, availFileCount; lseek(ugdbfd, 0, SEEK_SET); pkgNum = 0; while ((h = readHeader(ugdbfd, HEADER_MAGIC))) { name = version = release = NULL; getEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL); getEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL); getEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL); if (! (name && version && release)) { /* bum header */ printf("Failed with bad header\n"); exit(1); } /* XXX - Need to do serial number stuff someday */ /*printf("Avail: %s-%s-%s\n", name, version, release);*/ rc = rpmdbFindPackage(db, name, &matches); /*printf("Find returned: %d\n", rc);*/ if (rc == 0) { skipThis = 0; errSetCallback(errorFunction); for (i = 0; i < matches.count; i++) { if (rpmEnsureOlder(db, name, version, release, matches.recs[i].recOffset)) { /* already have a newer version installed */ /*printf("Already have newer version\n");*/ skipThis = 1; break; } } errSetCallback(NULL); if (! skipThis) { /* no newer version installed */ /*printf("No newer version installed\n");*/ skipThis = 0; } } else { skipThis = 1; /*printf("Not installed\n");*/ } if (skipThis) { /*printf("DO NOT INSTALL\n");*/ } else { /*printf("UPGRADE\n");*/ resultArray[pkgNum] = 1; getEntry(h, RPMTAG_FILENAMES, NULL, (void **) &availFiles, &availFileCount); for (i = 0; i < matches.count; i++) { /* Compare the file lists */ installedHeader = rpmdbGetRecord(db, matches.recs[i].recOffset); getEntry(installedHeader, RPMTAG_FILENAMES, NULL, (void **) &installedFiles, &installedFileCount); compareFileList(availFileCount, availFiles, installedFileCount, installedFiles, ht); free(installedFiles); freeHeader(installedHeader); } free(availFiles); } if (rc == 0) { freeDBIndexRecord(matches); } /*printf("\n\n");*/ freeHeader(h); pkgNum++; } *availPkgs = pkgNum; return 0; } int removeMovedFilesAlreadyHandled(int ugdbfd, struct hash_table *ht, int *resultArray) { int pkgNum; char *name; int i; Header h; char **availFiles; int availFileCount; char *file; lseek(ugdbfd, 0, SEEK_SET); pkgNum = 0; while ((h = readHeader(ugdbfd, HEADER_MAGIC))) { if (resultArray[pkgNum]) { name = NULL; getEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL); getEntry(h, RPMTAG_FILENAMES, NULL, (void **) &availFiles, &availFileCount); for (i = 0; i < availFileCount; i++) { if ((file = in_table(ht, availFiles[i]))) { *file = '\0'; printf("File already in %s: %s\n", name, availFiles[i]); resultArray[pkgNum] = 1; break; } } free(availFiles); } pkgNum++; freeHeader(h); } return 0; } int findPackagesWithRelocatedFiles(int ugdbfd, struct hash_table *ht, int *resultArray) { int pkgNum; char *name; int i; Header h; char **availFiles; int availFileCount; char *file; lseek(ugdbfd, 0, SEEK_SET); pkgNum = 0; while ((h = readHeader(ugdbfd, HEADER_MAGIC))) { if (! resultArray[pkgNum]) { name = NULL; getEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL); getEntry(h, RPMTAG_FILENAMES, NULL, (void **) &availFiles, &availFileCount); for (i = 0; i < availFileCount; i++) { if ((file = in_table(ht, availFiles[i]))) { *file = '\0'; printf("Found file in %s: %s\n", name, availFiles[i]); resultArray[pkgNum] = 1; break; } } free(availFiles); } pkgNum++; freeHeader(h); } return 0; } int main(int argc, char **argv) { int fd; rpmdb db; struct hash_table *hashTable; int installThisPackage[MAXPKGS]; int availPkgs, i; if ((fd = open(argv[1], O_RDONLY)) < 0) { perror("open"); exit(1); } if (rpmdbOpen("/", &db, O_RDONLY, 0644)) { fprintf(stderr, "error: cannot open /var/lib/rpm/packages.rpm\n"); exit(1); } for(i = 0; i < MAXPKGS; i++) { installThisPackage[i] = 0; } hashTable = new_table(1103); findUpgradePackages(db, fd, hashTable, installThisPackage, &availPkgs); rpmdbClose(db); hash_stats(hashTable); removeMovedFilesAlreadyHandled(fd, hashTable, installThisPackage); findPackagesWithRelocatedFiles(fd, hashTable, installThisPackage); close(fd); return 0; }