rpm/oldrpmdb.c

577 lines
14 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rpmerr.h"
#include "rpm_malloc.h"
#include "messages.h"
#include "misc.h"
#include "oldrpmdb.h"
static int labelstrlistToLabelList(char * str, int length,
struct oldrpmdbLabel ** list);
static char * getScript(char * which, struct oldrpmdb *oldrpmdb,
struct oldrpmdbLabel label);
static char * prefix = "/var/lib/rpm";
char * oldrpmdbLabelToLabelstr(struct oldrpmdbLabel label, int withFileNum) {
char * c;
char buffer[50];
if (withFileNum && label.fileNumber > -1)
c = malloc(strlen(label.name) + strlen(label.version) +
strlen(label.release) + 10);
else
c = malloc(strlen(label.name) + strlen(label.version) +
strlen(label.release) + 3);
strcpy(c, label.name);
strcat(c, ":");
strcat(c, label.version);
strcat(c, ":");
strcat(c, label.release);
if (withFileNum && label.fileNumber > -1) {
sprintf(buffer, "%d", label.fileNumber);
strcat(c, ":");
strcat(c, buffer);
}
return c;
}
int oldrpmdbLabelstrToLabel(char * str, int length, struct oldrpmdbLabel * label) {
char * chptr;
label->freeType = RPMDB_FREENAME;
label->next = NULL;
label->name = malloc(length + 1);
if (!label->name) {
return 1;
}
memcpy(label->name, str, length);
label->name[length] = '\0';
chptr = label->name;
while (*chptr != ':') chptr++;
*chptr = '\0';
label->version = ++chptr;
while (*chptr != ':') chptr++;
*chptr = '\0';
label->release = chptr + 1;
label->fileNumber = -1;
/* there might be a path number tagged on to the end of this */
while ((chptr - label->name) < length && *chptr != ':') chptr++;
if ((chptr - label->name) < length) {
*chptr = '\0';
label->fileNumber = atoi(chptr + 1);
}
return 0;
}
static int labelstrlistToLabelList(char * str, int length,
struct oldrpmdbLabel ** list) {
char * start, * chptr;
struct oldrpmdbLabel * head = NULL;
struct oldrpmdbLabel * tail = NULL;
struct oldrpmdbLabel * label;
start = str;
for (chptr = start; (chptr - str) < length; chptr++) {
/* spaces following a space get ignored */
if (*chptr == ' ' && start < chptr) {
label = malloc(sizeof(struct oldrpmdbLabel));
if (!label) {
oldrpmdbFreeLabelList(head);
return 1;
}
if (oldrpmdbLabelstrToLabel(start, chptr - start, label)) {
free(label);
oldrpmdbFreeLabelList(head);
return 1;
}
if (!head) {
head = label;
tail = label;
} else {
tail->next = label;
tail = tail->next;
}
start = chptr + 1;
}
}
/* a space on the end would break things horribly w/o this test */
if (start < chptr) {
label = malloc(sizeof(struct oldrpmdbLabel));
if (!label) {
oldrpmdbFreeLabelList(head);
return 1;
}
if (oldrpmdbLabelstrToLabel(start, chptr - start, label)) {
free(label);
oldrpmdbFreeLabelList(head);
return 1;
}
if (!head) {
head = label;
tail = label;
} else {
tail->next = label;
tail = tail->next;
}
start = chptr + 1;
}
*list = head;
return 0;
}
/* returns 0 on success, -1 on failure */
int oldrpmdbOpen(struct oldrpmdb * oldrpmdb) {
unsigned int gdbmFlags;
char path[255];
int goterr = 0;
oldrpmdb->rpmdbError = RPMDB_NONE;
gdbmFlags = GDBM_READER;
strcpy(path, prefix);
strcat(path, "/packages");
oldrpmdb->packages = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->packages) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
strcpy(path, prefix);
strcat(path, "/nameidx");
oldrpmdb->nameIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->packages) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
strcpy(path, prefix);
strcat(path, "/pathidx");
oldrpmdb->pathIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->packages) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
strcpy(path, prefix);
strcat(path, "/iconidx");
oldrpmdb->iconIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->iconIndex) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
strcpy(path, prefix);
strcat(path, "/groupindex");
oldrpmdb->groupIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->packages) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
strcpy(path, prefix);
strcat(path, "/postidx");
oldrpmdb->postIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
if (!oldrpmdb->postIndex) {
error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
goterr = 1;
}
if (goterr) {
oldrpmdbClose(oldrpmdb);
return -1;
}
return 0;
}
void oldrpmdbClose(struct oldrpmdb * oldrpmdb) {
gdbm_close(oldrpmdb->packages);
gdbm_close(oldrpmdb->nameIndex);
gdbm_close(oldrpmdb->pathIndex);
gdbm_close(oldrpmdb->postIndex);
gdbm_close(oldrpmdb->groupIndex);
gdbm_close(oldrpmdb->iconIndex);
}
struct oldrpmdbLabel * oldrpmdbGetAllLabels(struct oldrpmdb * oldrpmdb) {
datum rec;
struct oldrpmdbLabel * head = NULL;
struct oldrpmdbLabel * tail = NULL;
struct oldrpmdbLabel * label;
oldrpmdb->rpmdbError = RPMDB_NONE;
rec = gdbm_firstkey(oldrpmdb->packages);
while (rec.dptr) {
label = malloc(sizeof(struct oldrpmdbLabel));
if (!label) {
oldrpmdbFreeLabelList(head);
oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
return NULL;
}
if (oldrpmdbLabelstrToLabel(rec.dptr, rec.dsize, label)) {
free(label);
oldrpmdbFreeLabelList(head);
oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
return NULL;
}
if (!head) {
head = label;
tail = label;
} else {
tail->next = label;
tail = tail->next;
}
rec = gdbm_nextkey(oldrpmdb->packages, rec);
}
return head;
}
struct oldrpmdbLabel * oldrpmdbFindPackagesByFile(struct oldrpmdb * oldrpmdb, char * path) {
datum rec;
datum key;
struct oldrpmdbLabel * list;
oldrpmdb->rpmdbError = RPMDB_NONE;
key.dptr = path;
key.dsize = strlen(path);
rec = gdbm_fetch(oldrpmdb->pathIndex, key);
if (!rec.dptr)
return NULL;
if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
free(rec.dptr);
oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
return NULL;
}
free(rec.dptr);
return list;
}
struct oldrpmdbLabel * oldrpmdbFindPackagesByLabel(struct oldrpmdb * oldrpmdb,
struct oldrpmdbLabel label)
/* the Name has to be here. The version/release fields optionally
restrict the search. Either will do. */
{
datum rec;
datum key;
struct oldrpmdbLabel * list;
struct oldrpmdbLabel * prospect;
struct oldrpmdbLabel * parent;
int bad;
oldrpmdb->rpmdbError = RPMDB_NONE;
key.dptr = label.name;
key.dsize = strlen(label.name);
rec = gdbm_fetch(oldrpmdb->nameIndex, key);
if (!rec.dptr)
return NULL;
if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
free(rec.dptr);
oldrpmdb->rpmdbError = RPMDB_NO_MEMORY;
return NULL;
}
free(rec.dptr);
prospect = list;
parent = NULL;
while (prospect) {
bad = 0;
if (label.version && strcmp(label.version, prospect->version))
bad = 1;
else if (label.release && strcmp(label.release, prospect->release))
bad = 1;
if (bad) {
oldrpmdbFreeLabel(*prospect);
if (!parent) {
list = prospect->next;
free(prospect);
prospect = list;
} else {
parent->next = prospect->next;
free(prospect);
prospect = parent->next;
}
} else {
prospect = prospect->next;
}
}
return list;
}
struct oldrpmdbLabel oldrpmdbMakeLabel(char * name, char * version, char * release,
int fileNumber, enum oldrpmdbFreeType freeType) {
struct oldrpmdbLabel label;
label.next = NULL;
label.freeType = freeType;
label.name = name;
label.version = version;
label.release = release;
label.fileNumber = fileNumber;
return label;
}
void oldrpmdbFreeLabelList(struct oldrpmdbLabel * list) {
struct oldrpmdbLabel * saved;
while (list) {
oldrpmdbFreeLabel(*list);
saved = list->next;
free(list);
list = saved;
}
}
void oldrpmdbFreeLabel(struct oldrpmdbLabel label) {
if (label.freeType == RPMDB_NOFREE) return;
free(label.name);
if (label.freeType == RPMDB_FREEALL) {
free(label.version);
free(label.release);
}
}
/* Returns NULL on error */
char * oldrpmdbGetPackageGroup(struct oldrpmdb * oldrpmdb, struct oldrpmdbLabel label) {
datum key, rec;
char * g;
key.dptr = label.name;
key.dsize = strlen(label.name);
rec = gdbm_fetch(oldrpmdb->groupIndex, key);
if (!rec.dptr) {
return strdup("Unknown");
}
g = malloc(rec.dsize + 1);
strncpy(g, rec.dptr, rec.dsize);
g[rec.dsize] = '\0';
free(rec.dptr);
return g;
}
static char * getScript(char * which, struct oldrpmdb *oldrpmdb,
struct oldrpmdbLabel label) {
datum key, rec;
char * labelstr, * l;
labelstr = oldrpmdbLabelToLabelstr(label, 0);
labelstr = realloc(labelstr, strlen(labelstr) + 10);
strcat(labelstr, ":");
strcat(labelstr, which);
key.dptr = labelstr;
key.dsize = strlen(labelstr);
rec = gdbm_fetch(oldrpmdb->postIndex, key);
free(labelstr);
if (!rec.dptr) return NULL;
l = malloc(rec.dsize + 1);
strncpy(l, rec.dptr, rec.dsize);
l[rec.dsize] = '\0';
free(rec.dptr);
return l;
}
char *oldrpmdbGetPackagePostun (struct oldrpmdb *oldrpmdb,
struct oldrpmdbLabel label) {
return getScript("post", oldrpmdb, label);
}
char *oldrpmdbGetPackagePreun (struct oldrpmdb *oldrpmdb,
struct oldrpmdbLabel label) {
return getScript("pre", oldrpmdb, label);
}
/* Returns NULL on error or if no icon exists */
char * oldrpmdbGetPackageGif(struct oldrpmdb * oldrpmdb,
struct oldrpmdbLabel label, int * size) {
datum key, rec;
char * labelstr;
labelstr = oldrpmdbLabelToLabelstr(label, 0);
key.dptr = labelstr;
key.dsize = strlen(labelstr);
rec = gdbm_fetch(oldrpmdb->iconIndex, key);
free(labelstr);
if (!rec.dptr) {
return NULL;
}
*size = rec.dsize;
return rec.dptr;
}
/* return 0 on success, 1 on failure */
int oldrpmdbGetPackageInfo(struct oldrpmdb * oldrpmdb, struct oldrpmdbLabel label,
struct oldrpmdbPackageInfo * pinfo) {
char * labelstr;
char ** list, ** prelist;
char ** strptr;
datum key, rec;
int i, j;
labelstr = oldrpmdbLabelToLabelstr(label, 0);
message(MESS_DEBUG, "pulling %s from database\n", labelstr);
key.dptr = labelstr;
key.dsize = strlen(labelstr);
rec = gdbm_fetch(oldrpmdb->packages, key);
if (!rec.dptr) {
error(RPMERR_OLDDBCORRUPT, "package not found in database");
return 1;
}
free(labelstr);
list = splitString(rec.dptr, rec.dsize, '\1');
free(rec.dptr);
pinfo->version = strdup(list[1]);
pinfo->release = strdup(list[2]);
/* list[3] == "1" always */
pinfo->name = malloc(strlen(list[0]) + strlen(list[4]) + 2);
strcpy(pinfo->name, list[0]);
if (strlen(list[4])) {
strcat(pinfo->name, "-");
strcat(pinfo->name, list[4]);
}
pinfo->labelstr = malloc(strlen(pinfo->name) + strlen(pinfo->version) +
strlen(pinfo->release) + 3);
strcpy(pinfo->labelstr, pinfo->name);
strcat(pinfo->labelstr, ":");
strcat(pinfo->labelstr, pinfo->version);
strcat(pinfo->labelstr, ":");
strcat(pinfo->labelstr, pinfo->release);
pinfo->preamble = strdup(list[5]);
pinfo->installTime = atoi(list[6]);
pinfo->fileCount = atoi(list[7]);
prelist = splitString(pinfo->preamble, strlen(pinfo->preamble), '\n');
/* these are optional */
pinfo->distribution = NULL;
pinfo->vendor = NULL;
pinfo->description = NULL;
pinfo->copyright = NULL;
for (strptr = prelist; *strptr; strptr++) {
if (!strncasecmp("Description: ", *strptr, 13))
pinfo->description = strdup((*strptr) + 13);
else if (!strncasecmp("Copyright: ", *strptr, 11))
pinfo->copyright = strdup((*strptr) + 11);
else if (!strncasecmp("Distribution: ", *strptr, 14))
pinfo->distribution = strdup((*strptr) + 14);
else if (!strncasecmp("Vendor: ", *strptr, 8))
pinfo->vendor = strdup((*strptr) + 8);
else if (!strncasecmp("size: ", *strptr, 6))
pinfo->size = atoi((*strptr) + 6);
else if (!strncasecmp("BuildDate: ", *strptr, 11))
pinfo->buildTime =atoi((*strptr) + 11);
else if (!strncasecmp("BuildHost: ", *strptr, 11))
pinfo->buildHost = strdup((*strptr) + 11);
}
freeSplitString(prelist);
if (!pinfo->vendor) pinfo->vendor = strdup("");
if (!pinfo->description) pinfo->description = strdup("");
if (!pinfo->distribution) pinfo->distribution = strdup("");
if (!pinfo->copyright) {
pinfo->copyright = strdup("");
printf("no copyright!\n");
}
pinfo->files = malloc(sizeof(struct oldrpmFileInfo) * pinfo->fileCount);
j = 8;
for (i = 0; i < pinfo->fileCount; i++) {
oldrpmfileFromInfoLine(list[j], list[j + 1], list[j + 2],
&pinfo->files[i]);
j += 3;
}
freeSplitString(list);
return 0;
}
void oldrpmdbFreePackageInfo(struct oldrpmdbPackageInfo package) {
int i;
free(package.version);
free(package.release);
free(package.name);
free(package.labelstr);
free(package.buildHost);
free(package.vendor);
free(package.description);
free(package.copyright);
free(package.distribution);
free(package.preamble);
for (i = 0; i < package.fileCount; i++) {
oldrpmfileFree(&package.files[i]);
}
free(package.files);
}
int oldrpmdbLabelCmp(struct oldrpmdbLabel * one, struct oldrpmdbLabel * two) {
int i;
if ((i = strcmp(one->name, two->name)))
return i;
else if ((i = strcmp(one->version, two->version)))
return i;
else
return strcmp(one->release, two->release);
}
void oldrpmdbSetPrefix(char * new) {
prefix = new;
}