home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
upgrade.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-09
|
11KB
|
448 lines
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <string.h>
#include "install.h"
#include "log.h"
#include "hash.h"
#include "pkgs.h"
#define MAXPKGS 1024
#if 0
static void printMemStats(char *mess)
{
char buf[1024];
printf("%s\n", mess);
sprintf(buf, "cat /proc/%d/status | grep VmSize", getpid());
system(buf);
}
#endif
static 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]); */
if (strncmp(installedFiles[installedX], "/etc/rc.d/", 10))
htAddToTable(ht, installedFiles[installedX]);
installedX++;
} else {
rc = strcmp(availFiles[availX], installedFiles[installedX]);
if (rc > 0) {
/* Avail > Installed -- file has moved */
/* printf("=> %s\n", installedFiles[installedX]); */
if (strncmp(installedFiles[installedX], "/etc/rc.d/", 10))
htAddToTable(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++;
}
}
}
}
static void addLostFiles( rpmdb db, struct pkgSet *psp, struct hash_table *ht)
{
int num;
Header h;
char *name;
struct packageInfo **pack;
struct packageInfo key;
struct packageInfo *keyaddr = &key;
char **installedFiles;
int installedFileCount;
num = rpmdbFirstRecNum(db);
while (num) {
h = rpmdbGetRecord(db, num);
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
key.name = name;
pack = bsearch(&keyaddr, psp->packages, psp->numPackages,
sizeof(*psp->packages), (void *)pkgCompare);
if (!pack) {
if (headerGetEntry(h, RPMTAG_FILENAMES, NULL,
(void **) &installedFiles, &installedFileCount)) {
compareFileList(0, NULL, installedFileCount,
installedFiles, ht);
free(installedFiles);
}
}
headerFree(h);
num = rpmdbNextRecNum(db, num);
}
}
static int findPackagesWithObsoletes(rpmdb db, struct pkgSet *psp)
{
dbiIndexSet matches;
int rc, count, obsoletesCount;
struct packageInfo **pip;
char **obsoletes;
count = psp->numPackages;
pip = psp->packages;
while (count--) {
if ((*pip)->selected) {
pip++;
continue;
}
if (headerGetEntry((*pip)->h, RPMTAG_OBSOLETES, NULL,
(void **) &obsoletes, &obsoletesCount)) {
while (obsoletesCount--) {
rc = rpmdbFindPackage(db, obsoletes[obsoletesCount], &matches);
if (!rc) {
if (matches.count) {
(*pip)->selected = 1;
dbiFreeIndexRecord(matches);
break;
}
dbiFreeIndexRecord(matches);
}
}
free(obsoletes);
}
pip++;
}
return 0;
}
static void errorFunction(void)
{
}
static int findUpgradePackages(rpmdb db, struct pkgSet *psp,
struct hash_table *ht)
{
int skipThis;
Header h, installedHeader;
char *name, *version, *release;
dbiIndexSet matches;
int rc, i, count;
char **installedFiles, **availFiles;
int installedFileCount, availFileCount;
struct packageInfo **pip;
count = psp->numPackages;
pip = psp->packages;
while (count--) {
h = (*pip)->h;
name = version = release = NULL;
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);
if (! (name && version && release)) {
/* bum header */
logMessage("Failed with bad header");
return(INST_ERROR);
}
/* XXX - Need to do serial number stuff someday */
/*printf("Avail: %s-%s-%s\n", name, version, release);*/
rc = rpmdbFindPackage(db, name, &matches);
if (rc == 0) {
skipThis = 0;
rpmErrorSetCallback(errorFunction);
for (i = 0; i < matches.count; i++) {
installedHeader =
rpmdbGetRecord(db, matches.recs[i].recOffset);
if (rpmVersionCompare(installedHeader, h) >= 0) {
/* already have a newer version installed */
/*printf("Already have newer version\n");*/
skipThis = 1;
break;
}
}
rpmErrorSetCallback(NULL);
if (! skipThis) {
/*printf("No newer version installed\n");*/
}
} else {
skipThis = 1;
/*printf("Not installed\n");*/
}
if (skipThis) {
/*printf("DO NOT INSTALL\n");*/
} else {
/*printf("UPGRADE\n");*/
(*pip)->selected = 1;
if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
(void **) &availFiles, &availFileCount)) {
availFiles = NULL;
availFileCount = 0;
}
for (i = 0; i < matches.count; i++) {
/* Compare the file lists */
installedHeader =
rpmdbGetRecord(db, matches.recs[i].recOffset);
if (!headerGetEntry(installedHeader, RPMTAG_FILENAMES, NULL,
(void **) &installedFiles,
&installedFileCount)) {
installedFiles = NULL;
installedFileCount = 0;
}
compareFileList(availFileCount, availFiles,
installedFileCount, installedFiles, ht);
if (installedFiles) {
free(installedFiles);
}
headerFree(installedHeader);
}
if (availFiles) {
free(availFiles);
}
}
if (rc == 0) {
dbiFreeIndexRecord(matches);
}
/*printf("\n\n");*/
pip++;
}
return 0;
}
static int removeMovedFilesAlreadyHandled(struct pkgSet *psp,
struct hash_table *ht)
{
char *name;
int i, count;
Header h;
char **availFiles;
int availFileCount;
char *file;
struct packageInfo **pip;
count = psp->numPackages;
pip = psp->packages;
while (count--) {
h = (*pip)->h;
if ((*pip)->selected) {
name = NULL;
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
if (!headerGetEntry(h, RPMTAG_FILENAMES, NULL,
(void **) &availFiles, &availFileCount)) {
availFiles = NULL;
availFileCount = 0;
}
for (i = 0; i < availFileCount; i++) {
if ((file = htInTable(ht, availFiles[i]))) {
*file = '\0';
/*printf("File already in %s: %s\n", name, availFiles[i]);*/
break;
}
}
if (availFiles) {
free(availFiles);
}
}
pip++;
}
return 0;
}
static int findPackagesWithRelocatedFiles(struct pkgSet *psp,
struct hash_table *ht)
{
char *name;
int i, count;
Header h;
char **availFiles;
int availFileCount;
char *file;
struct packageInfo **pip;
count = psp->numPackages;
pip = psp->packages;
while (count--) {
h = (*pip)->h;
if (! (*pip)->selected) {
name = NULL;
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
availFiles = NULL;
availFileCount = 0;
if (headerGetEntry(h, RPMTAG_FILENAMES, NULL,
(void **) &availFiles, &availFileCount)) {
for (i = 0; i < availFileCount; i++) {
if ((file = htInTable(ht, availFiles[i]))) {
*file = '\0';
/*printf("Found file in %s: %s\n", name,
availFiles[i]);*/
(*pip)->selected = 1;
break;
}
}
free(availFiles);
}
}
pip++;
}
return 0;
}
static void printCount(struct pkgSet *psp)
{
int i, upgradeCount;
struct packageInfo **pip;
upgradeCount = 0;
pip = psp->packages;
i = psp->numPackages;
while (i--) {
if ((*pip)->selected) {
upgradeCount++;
}
pip++;
}
logMessage("marked %d packages for upgrade", upgradeCount);
}
static int unmarkPackagesAlreadyInstalled(rpmdb db, struct pkgSet *psp)
{
dbiIndexSet matches;
Header h, installedHeader;
char *name, *version, *release;
struct packageInfo **pip;
int count, rc, i;
count = psp->numPackages;
pip = psp->packages;
while (count--) {
if ((*pip)->selected) {
h = (*pip)->h;
/* If this package is already installed, don't bother */
name = version = release = NULL;
headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);
if (! (name && version && release)) {
/* bum header */
logMessage("Failed with bad header");
return(INST_ERROR);
}
rc = rpmdbFindPackage(db, name, &matches);
if (rc == 0) {
rpmErrorSetCallback(errorFunction);
for (i = 0; i < matches.count; i++) {
installedHeader =
rpmdbGetRecord(db, matches.recs[i].recOffset);
if (rpmVersionCompare(installedHeader, h) >= 0) {
/* already have a newer version installed */
/*printf("Already have newer version\n");*/
(*pip)->selected = 0;
break;
}
}
rpmErrorSetCallback(NULL);
dbiFreeIndexRecord(matches);
}
}
pip++;
}
return 0;
}
int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot)
{
rpmdb db;
struct hash_table *hashTable;
logDebugMessage(("ugFindUpgradePackages() ..."));
rpmReadConfigFiles(NULL, NULL, NULL, 0);
if (rpmdbOpen(installRoot, &db, O_CREAT | O_RDWR, 0644)) {
logMessage("failed opening %s/var/lib/rpm/packages.rpm",
installRoot);
return(INST_ERROR);
}
hashTable = htNewTable(1103);
/* For all packages that are installed, if there is no package */
/* available by that name, add the package's files to the hash table */
addLostFiles(db, psp, hashTable);
logDebugMessage(("added lost files"));
printCount(psp);
/* Find packges that are new, and mark them in installThisPackage, */
/* updating availPkgs with the count. Also add files to the hash */
/* table that do not exist in the new package - they may have moved */
if (findUpgradePackages(db, psp, hashTable)) {
rpmdbClose(db);
return(INST_ERROR);
}
logDebugMessage(("found basic packages to upgrade"));
printCount(psp);
/*hash_stats(hashTable);*/
/* Remove any files that were added to the hash table that are in */
/* some other package marked for upgrade. */
removeMovedFilesAlreadyHandled(psp, hashTable);
logDebugMessage(("removed extra files which have moved"));
printCount(psp);
findPackagesWithRelocatedFiles(psp, hashTable);
logDebugMessage(("found packages with relocated files"));
printCount(psp);
findPackagesWithObsoletes(db, psp);
logDebugMessage(("found packages that obsolete installed packages"));
printCount(psp);
unmarkPackagesAlreadyInstalled(db, psp);
logDebugMessage(("unmarked packages already installed"));
printCount(psp);
htFreeHashTable(hashTable);
/*printMemStats("Done");*/
rpmdbClose(db);
return 0;
}