summaryrefslogtreecommitdiffstats
path: root/rpmmodule
diff options
context:
space:
mode:
authorErik Troan <ewt@redhat.com>1999-08-10 15:17:35 +0000
committerErik Troan <ewt@redhat.com>1999-08-10 15:17:35 +0000
commita6571fe035129ad6cac422e8005c943fe1fe02d2 (patch)
tree8261c79557c309eafcc445b15a4568c1cf66f275 /rpmmodule
parent1f9edbd74e990b5975288b599e9e80f3b01ebedd (diff)
downloadanaconda-a6571fe035129ad6cac422e8005c943fe1fe02d2.tar.gz
anaconda-a6571fe035129ad6cac422e8005c943fe1fe02d2.tar.xz
anaconda-a6571fe035129ad6cac422e8005c943fe1fe02d2.zip
added upgrade code
Diffstat (limited to 'rpmmodule')
-rw-r--r--rpmmodule/Makefile6
-rw-r--r--rpmmodule/rpmmodule.c47
-rw-r--r--rpmmodule/upgrade.c476
-rw-r--r--rpmmodule/upgrade.h17
4 files changed, 543 insertions, 3 deletions
diff --git a/rpmmodule/Makefile b/rpmmodule/Makefile
index 375829278..6ae8d1856 100644
--- a/rpmmodule/Makefile
+++ b/rpmmodule/Makefile
@@ -1,13 +1,13 @@
DESTDIR = $(TOPDIR)/RedHat/instimage/usr/lib/python1.5/site-packages
-CFLAGS += -I/usr/include/rpm -I/usr/include/python1.5 -g
+CFLAGS += -fPIC -I/usr/include/rpm -I/usr/include/python1.5 -g
TARGET = rpmmodule.so
all: $(TARGET)
-rpmmodule.so: rpmmodule.o
- gcc -shared -o $@ rpmmodule.o -lrpm -lz -ldb1
+rpmmodule.so: rpmmodule.o upgrade.o hash.o
+ gcc -shared -o $@ $^ -lrpm -lz -ldb1
clean:
rm -f *.o $(TARGET)
diff --git a/rpmmodule/rpmmodule.c b/rpmmodule/rpmmodule.c
index 852406f4d..6547ede23 100644
--- a/rpmmodule/rpmmodule.c
+++ b/rpmmodule/rpmmodule.c
@@ -1,3 +1,4 @@
+#include <alloca.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
@@ -6,6 +7,7 @@
#include "Python.h"
#include "rpmlib.h"
+#include "upgrade.h"
/* Forward types */
@@ -32,6 +34,7 @@ static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args);
static PyObject * archScore(PyObject * self, PyObject * args);
static PyObject * rpmHeaderFromPackage(PyObject * self, PyObject * args);
static PyObject * rpmHeaderFromList(PyObject * self, PyObject * args);
+static PyObject * findUpgradeSet(PyObject * self, PyObject * args);
static PyObject * rpmtransCreate(PyObject * self, PyObject * args);
static PyObject * rpmtransAdd(rpmtransObject * s, PyObject * args);
@@ -48,6 +51,7 @@ static int rpmtransSetAttr(rpmtransObject * o, char * name,
static PyMethodDef rpmModuleMethods[] = {
{ "opendb", (PyCFunction) rpmOpenDB, METH_VARARGS, NULL },
{ "archscore", (PyCFunction) archScore, METH_VARARGS, NULL },
+ { "findUpgradeSet", (PyCFunction) findUpgradeSet, METH_VARARGS, NULL },
{ "headerFromPackage", (PyCFunction) rpmHeaderFromPackage, METH_VARARGS, NULL },
{ "readHeaderList", (PyCFunction) rpmHeaderFromList, METH_VARARGS, NULL },
{ "TransactionSet", (PyCFunction) rpmtransCreate, METH_VARARGS, NULL },
@@ -272,6 +276,49 @@ void initrpm(void) {
PyInt_FromLong(RPMCALLBACK_UNINST_STOP));
}
+static PyObject * findUpgradeSet(PyObject * self, PyObject * args) {
+ PyObject * hdrList, * result;
+ char * root = "/";
+ int i, num;
+ struct pkgSet list;
+ hdrObject * hdr;
+
+ if (!PyArg_ParseTuple(args, "o|s", &hdrList, &root)) return NULL;
+
+ if (!PyList_Check(hdrList)) {
+ PyErr_SetString(PyExc_TypeError, "list of headers expected");
+ return NULL;
+ }
+
+ list.numPackages = PyList_Size(hdrList);
+ list.packages = alloca(sizeof(*list.packages) * list.numPackages);
+ for (i = 0; i < list.numPackages; i++) {
+ hdr = (hdrObject *) PyList_GetItem(hdrList, i);
+ if (hdr->ob_type != &hdrType) {
+ PyErr_SetString(PyExc_TypeError, "list of headers expected");
+ return NULL;
+ }
+ list.packages[i].h = hdr->h;
+ list.packages[i].selected = 0;
+
+ headerGetEntry(hdr->h, RPMTAG_NAME, NULL,
+ (void **) &list.packages[i].name, NULL);
+ }
+
+ if (ugFindUpgradePackages(&list, root)) {
+ PyErr_SetString(pyrpmError, "error during upgrade check");
+ return NULL;
+ }
+
+ result = PyList_New(0);
+ for (i = 0; i < list.numPackages; i++) {
+ if (list.packages[i].selected)
+ PyList_Append(result, PyList_GetItem(hdrList, i));
+ }
+
+ return result;
+}
+
static rpmdbObject * rpmOpenDB(PyObject * self, PyObject * args) {
rpmdbObject * o;
char * root = "";
diff --git a/rpmmodule/upgrade.c b/rpmmodule/upgrade.c
new file mode 100644
index 000000000..971555189
--- /dev/null
+++ b/rpmmodule/upgrade.c
@@ -0,0 +1,476 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <rpm/rpmlib.h>
+#include <rpm/header.h>
+#include <string.h>
+
+#include "hash.h"
+#include "upgrade.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
+
+int pkgCompare(void * first, void * second) {
+ struct packageInfo ** a = first;
+ struct packageInfo ** b = second;
+
+ /* put packages w/o names at the end */
+ if (!(*a)->name) return 1;
+ if (!(*b)->name) return -1;
+
+ return strcasecmp((*a)->name, (*b)->name);
+}
+
+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;
+ char **installedFiles;
+ int installedFileCount;
+
+ num = rpmdbFirstRecNum(db);
+ while (num) {
+ h = rpmdbGetRecord(db, num);
+ headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
+ if (name && !strcmp(name, "metroess")) {
+ /* metro was removed from 5.1, but leave it if it's already
+ installed */
+ headerFree(h);
+ num = rpmdbNextRecNum(db, num);
+ continue;
+ }
+ key.name = name;
+
+ pack = bsearch(&key, 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(-1);
+ }
+
+ /*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;
+ headerFree(installedHeader);
+ break;
+ }
+ headerFree(installedHeader);
+ }
+ 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(-1);
+ }
+ 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;
+ headerFree(installedHeader);
+ break;
+ }
+ headerFree(installedHeader);
+ }
+ rpmErrorSetCallback(NULL);
+ dbiFreeIndexRecord(matches);
+ }
+ }
+
+ pip++;
+ }
+
+ return 0;
+}
+
+static void emptyErrorCallback(void) {
+}
+
+int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot)
+{
+ rpmdb db;
+ struct hash_table *hashTable;
+ rpmErrorCallBackType old;
+
+ /*logDebugMessage(("ugFindUpgradePackages() ..."));*/
+
+ rpmReadConfigFiles(NULL, NULL);
+
+ rpmSetVerbosity(RPMMESS_FATALERROR);
+ old = rpmErrorSetCallback(emptyErrorCallback);
+
+ if (rpmdbOpenForTraversal(installRoot, &db)) {
+ /*logMessage("failed opening %s/var/lib/rpm/packages.rpm",
+ installRoot);*/
+ return(-1);
+ }
+
+ rpmErrorSetCallback(old);
+ rpmSetVerbosity(RPMMESS_NORMAL);
+
+ 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(-1);
+ }
+ /*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;
+}
diff --git a/rpmmodule/upgrade.h b/rpmmodule/upgrade.h
new file mode 100644
index 000000000..96dacba8b
--- /dev/null
+++ b/rpmmodule/upgrade.h
@@ -0,0 +1,17 @@
+#ifndef H_UPGRADE
+#define H_UPGRADE
+
+struct packageInfo {
+ Header h;
+ char selected;
+ char * name;
+} ;
+
+struct pkgSet {
+ struct packageInfo * packages;
+ int numPackages;
+};
+
+int ugFindUpgradePackages(struct pkgSet *psp, char *installRoot);
+
+#endif