--- /dev/null
+SUBDIRS = lib
+OBJS = spec.o
+PROGS = build
+
+WARNINGS = -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
+DEBUG = -g
+OPTS = -O2
+CFLAGS = $(WARNINGS) $(DEBUG) $(OPTS) -Ilib
+LDFLAGS = $(DEBUG) -Llib
+LOADLIBES = -lrpm
+
+all: make-subdirs $(OBJS) $(PROGS)
+
+make-subdirs:
+ for d in $(SUBDIRS); do \
+ (cd $$d; $(MAKE)) ;\
+ done
+
+build: build.o spec.o
+
+clean:
+ for d in $(SUBDIRS); do \
+ (cd $$d; $(MAKE) $@) ;\
+ done
+ rm -f *.o *~ $(PROGS)
--- /dev/null
+#include <stdio.h>
+#include "spec.h"
+
+void main(int argc, char **argv)
+{
+ FILE *f;
+
+ printf("hello\n");
+ f = fopen(argv[1], "r");
+ parse_spec(f);
+ fclose(f);
+}
--- /dev/null
+/* RPM - Copyright (C) 1995 Red Hat Software
+ *
+ * spec.c - routines for parsing a spec file
+ */
+
+#include "header.h"
+#include "spec.h"
+#include "rpmerr.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define LINE_BUF_SIZE 1024
+
+struct spec {
+ Header header;
+ char *prep;
+ char *build;
+ char *install;
+ char *clean;
+};
+
+void free_spec(Spec s)
+{
+ freeHeader(s->header);
+ free(s->prep);
+ free(s->build);
+ free(s->install);
+ free(s->clean);
+ free(s);
+}
+
+static int read_line(FILE *f, char *line);
+static int match_arch(char *s);
+static int match_os(char *s);
+
+static int match_arch(char *s)
+{
+ if (! strncmp(s, "%ifarch i386", 12)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int match_os(char *s)
+{
+ if (! strncmp(s, "%ifos linux", 11)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int reading = 0;
+static int iflevels = 0;
+static int skiplevels = 0;
+static int skip = 0;
+
+static int read_line(FILE *f, char *line)
+{
+ char *r = fgets(line, LINE_BUF_SIZE, f);
+
+ if (! r) {
+ /* the end */
+ if (iflevels) return RPMERR_UNMATCHEDIF;
+ return 0;
+ }
+
+ skip = 0;
+
+ if (! strncmp("%ifarch", line, 7)) {
+ iflevels++;
+ skip = 1;
+ if (! match_arch(line)) {
+ reading = 0;
+ skiplevels++;
+ }
+ }
+ if (! strncmp("%ifos", line, 5)) {
+ iflevels++;
+ skip = 1;
+ if (! match_os(line)) {
+ reading = 0;
+ skiplevels++;
+ }
+ }
+
+ if (! strncmp("%endif", line, 6)) {
+ iflevels--;
+ skip = 1;
+ if (skiplevels) {
+ if (! --skiplevels) reading = 1;
+ }
+ }
+
+ return 1;
+}
+
+Spec parse_spec(FILE *f)
+{
+ char line[LINE_BUF_SIZE];
+ Spec s = (struct spec *) malloc(sizeof(struct spec));
+ int x;
+
+ reading = 1;
+
+ while ((x = read_line(f, line))) {
+ if (!reading) continue;
+ if (skip) continue;
+ puts(line);
+ }
+ if (x < 0) {
+ /* error */
+ return NULL;
+ }
+
+ return s;
+}
--- /dev/null
+/* RPM - Copyright (C) 1995 Red Hat Software
+ *
+ * spec.h - routines for parsing are looking up info in a spec file
+ */
+
+#ifndef _spec_h
+#define _spec_h
+
+typedef struct spec *Spec;
+
+Spec parse_spec(FILE *f);
+void free_spec(Spec s);
+
+#endif _spec_h
--- /dev/null
+/* This converts an old style (rpm 1.x) database to the new style */
+
+#include <oldrpmdb.h>
+
+int convertDB(char * dbprefix) {
+
+}
--- /dev/null
+LIBS = -lefence
+
+LIBOBJECTS = header.o oldrpmdb.o misc.o messages.o
+LIBRPM = librpm.a
+
+WARNINGS = -Wall -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes
+DEBUG = -g
+OPTS = -O2
+
+all: test dump
+
+# -----------------------------------------------------------------------
+
+AR = ar r
+RANLIB = ranlib
+
+CFLAGS = $(WARNINGS) $(DEBUG) $(OPTS)
+LDFLAGS = $(DEBUG) $(LIBS)
+
+test: librpm.a
+ $(CC) -o $@ test.c librpm.a $(LIBS)
+
+dump: librpm.a
+ $(CC) -o $@ dump.c librpm.a $(LIBS)
+
+$(LIBRPM): $(LIBOBJECTS)
+ $(AR) $@ $(LIBOBJECTS)
+ $(RANLIB) $@
+
+clean:
+ rm -f *.a *.o *~ test dump test.out
--- /dev/null
+/* RPM - Copyright (C) 1995 Red Hat Software
+ *
+ * header.c - routines for managing rpm headers
+ */
+
+#include <asm/byteorder.h>
+#include <sys/mman.h>
+#include <ctype.h>
+#include <string.h>
+#include <malloc.h>
+#include "header.h"
+
+#define INDEX_MALLOC_SIZE 8
+#define DATA_MALLOC_SIZE 1024
+
+struct headerToken {
+ struct indexEntry *index;
+ int entries_malloced;
+ int entries_used;
+
+ char *data;
+ int data_malloced;
+ int data_used;
+
+ caddr_t mmapped_address;
+
+ int mutable;
+};
+
+/* All this is in network byte order! */
+struct indexEntry {
+ int_32 tag;
+ int_32 type;
+ int_32 offset; /* Offset from beginning of data segment */
+ int_32 count;
+};
+
+/********************************************************************/
+
+void writeHeader(FILE *f, Header h)
+{
+ int_32 l;
+
+ /* First write out the length of the index (count of index entries) */
+ l = htonl(h->entries_used);
+ fwrite(&l, sizeof(l), 1, f);
+
+ /* And the length of the data (number of bytes) */
+ l = htonl(h->data_used);
+ fwrite(&l, sizeof(l), 1, f);
+
+ /* Now write the index */
+ fwrite(h->index, sizeof(struct indexEntry), h->entries_used, f);
+
+ /* Finally write the data */
+ fwrite(h->data, h->data_used, 1, f);
+}
+
+Header mmapHeader(int fd, long offset)
+{
+ struct headerToken * h = malloc(sizeof(struct headerToken));
+ int_32 * p1, il, dl;
+ caddr_t p;
+ size_t bytes = 2 * sizeof(int_32);
+
+ p = mmap(0, bytes, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, offset);
+ if (!p)
+ return NULL;
+
+ p1 = (int_32 *) p;
+
+ il = ntohl(*p1++);
+ dl = ntohl(*p1++);
+ if (munmap((caddr_t) p, 0)) {
+ return NULL;
+ }
+
+ bytes += il * sizeof(struct indexEntry) + dl;
+ p = mmap(0, bytes, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+ h->index = (void *) (p + 2 * sizeof(int_32));
+ h->data = (void *) (p + 2 * sizeof(int_32) + il * sizeof(struct indexEntry));
+
+ h->entries_malloced = il;
+ h->entries_used = il;
+ h->data_malloced = dl;
+ h->data_used = dl;
+ h->mutable = 0;
+ h->mmapped_address = p;
+
+ return h;
+}
+
+Header readHeader(FILE *f)
+{
+ int_32 il, dl;
+
+ struct headerToken *h = (struct headerToken *)
+ malloc(sizeof(struct headerToken));
+
+ /* First read the index length (count of index entries) */
+ fread(&il, sizeof(il), 1, f);
+ il = ntohl(il);
+
+ /* Then read the data length (number of bytes) */
+ fread(&dl, sizeof(dl), 1, f);
+ dl = ntohl(dl);
+
+ /* Next read the index */
+ h->index = malloc(il * sizeof(struct indexEntry));
+ h->entries_malloced = il;
+ h->entries_used = il;
+ fread(h->index, sizeof(struct indexEntry), il, f);
+
+ /* Finally, read the data */
+ h->data = malloc(dl);
+ h->data_malloced = dl;
+ h->data_used = dl;
+ fread(h->data, dl, 1, f);
+
+ h->mutable = 0;
+
+ return h;
+}
+
+Header loadHeader(void *pv)
+{
+ int_32 il, dl;
+ char * p = pv;
+ struct headerToken *h = malloc(sizeof(struct headerToken));
+
+ il = ntohl( *((int_32 *)p) );
+ p += sizeof(int_32);
+ dl = ntohl( *((int_32 *)p) );
+ p += sizeof(int_32);
+
+ h->entries_malloced = il;
+ h->entries_used = il;
+ h->index = (struct indexEntry *) p;
+ p += il * sizeof(struct indexEntry);
+
+ h->data_malloced = dl;
+ h->data_used = dl;
+ h->data = p;
+
+ h->mutable = 0;
+
+ return h;
+}
+
+void *unloadHeader(Header h)
+{
+ void *p;
+ int_32 *pi;
+
+ pi = p = malloc(2 * sizeof(int_32) +
+ h->entries_used * sizeof(struct indexEntry) +
+ h->data_used);
+
+ *pi++ = h->entries_used;
+ *pi++ = h->data_used;
+ memcpy(pi, h->index, h->entries_used * sizeof(struct indexEntry));
+ pi += h->entries_used * sizeof(struct indexEntry);
+ memcpy(pi, h->data, h->data_used);
+
+ return p;
+}
+
+void dumpHeader(Header h, FILE *f, int flags)
+{
+ int i, c, ct;
+ struct indexEntry *p;
+ char *dp;
+ char ch;
+
+ /* First write out the length of the index (count of index entries) */
+ fprintf(f, "Entry count: %d\n", h->entries_used);
+
+ /* And the length of the data (number of bytes) */
+ fprintf(f, "Data count : %d\n", h->data_used);
+
+ /* Now write the index */
+ p = h->index;
+ /* Entry : 00 0x00000000 0x00000000 0x00000000 0x00000000 */
+ fprintf(f, "\n CT TAG TYPE OFFSET COUNT\n");
+ for (i = 0; i < h->entries_used; i++) {
+ fprintf(f, "Entry : %.3d 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", i,
+ (uint_32) ntohl(p->tag), (uint_32) ntohl(p->type),
+ (uint_32) ntohl(p->offset), (uint_32) ntohl(p->count));
+
+ if (flags & DUMP_INLINE) {
+ /* Print the data inline */
+ dp = h->data + ntohl(p->offset);
+ c = ntohl(p->count);
+ ct = 0;
+ switch (ntohl(p->type)) {
+ case INT32_TYPE:
+ while (c--) {
+ fprintf(f, " Data: %.3d 0x%.8x (%d)\n", ct++,
+ (uint_32) ntohl(*((int_32 *)dp)),
+ (uint_32) ntohl(*((int_32 *)dp)));
+ dp += sizeof(int_32);
+ }
+ break;
+
+ case INT16_TYPE:
+ while (c--) {
+ fprintf(f, " Data: %.3d 0x%.4x (%d)\n", ct++,
+ (short int) ntohs(*((int_16 *)dp)),
+ (short int) ntohs(*((int_16 *)dp)));
+ dp += sizeof(int_16);
+ }
+ break;
+ case INT8_TYPE:
+ while (c--) {
+ fprintf(f, " Data: %.3d 0x%.2x (%d)\n", ct++,
+ (char) *((int_8 *)dp),
+ (char) *((int_8 *)dp));
+ dp += sizeof(int_8);
+ }
+ break;
+ case CHAR_TYPE:
+ while (c--) {
+ ch = (char) *((char *)dp);
+ fprintf(f, " Data: %.3d 0x%2x %c (%d)\n", ct++,
+ ch,
+ (isprint(ch) ? ch : ' '),
+ (char) *((char *)dp));
+ dp += sizeof(char);
+ }
+ break;
+ case STRING_TYPE:
+ while (c--) {
+ fprintf(f, " Data: %.3d %s\n", ct++, (char *)dp);
+ dp = strchr(dp, 0);
+ dp++;
+ }
+ break;
+ default:
+ fprintf(stderr, "Data type %d not supprted\n", (int)ntohl(p->type));
+ exit(1);
+ }
+ }
+ p++;
+ }
+}
+
+void freeHeader(Header h)
+{
+ if (h->mutable) {
+ free(h->index);
+ free(h->data);
+ }
+ if (h->mmapped_address) {
+ munmap(h->mmapped_address, 0);
+ }
+ free(h);
+}
+
+int getEntry(Header h, int_32 tag, int_32 *type, void **p, int_32 *c)
+{
+ struct indexEntry *index = h->index;
+ int x = h->entries_used;
+ char **spp;
+ char *sp;
+
+ /* First find the tag */
+ tag = htonl(tag);
+ while (x && (tag != index->tag)) {
+ index++;
+ x--;
+ }
+ if (x == 0) {
+ return 0;
+ }
+
+ *type = ntohl(index->type);
+ *c = ntohl(index->count);
+
+ /* Now look it up */
+ switch (*type) {
+ case INT64_TYPE:
+ case INT32_TYPE:
+ case INT16_TYPE:
+ case INT8_TYPE:
+ case CHAR_TYPE:
+ *p = h->data + ntohl(index->offset);
+ break;
+ case STRING_TYPE:
+ if (*c == 1) {
+ /* Special case -- just return a pointer to the string */
+ *p = h->data + ntohl(index->offset);
+ } else {
+ /* Otherwise, build up an array of char* to return */
+ x = index->count;
+ p = malloc(x * sizeof(char *));
+ spp = (char **)p;
+ sp = h->data + ntohl(index->offset);
+ while(x--) {
+ *spp++ = sp;
+ sp = strchr(sp, 0);
+ sp++;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Data type %d not supprted\n", (int) *type);
+ exit(1);
+ }
+
+ return 1;
+}
+
+/********************************************************************/
+
+/*
+ * The following routines are used to build up a header.
+ */
+
+Header newHeader()
+{
+ struct headerToken *h = (struct headerToken *)
+ malloc(sizeof(struct headerToken));
+
+ h->data = malloc(DATA_MALLOC_SIZE);
+ h->data_malloced = DATA_MALLOC_SIZE;
+ h->data_used = 0;
+
+ h->index = malloc(INDEX_MALLOC_SIZE * sizeof(struct indexEntry));
+ h->entries_malloced = INDEX_MALLOC_SIZE;
+ h->entries_used = 0;
+
+ h->mutable = 1;
+ h->mmapped_address = (caddr_t) 0;
+
+ return (Header) h;
+}
+
+int addEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c)
+{
+ struct indexEntry *entry;
+ void *ptr;
+ char **spp;
+ char *sp;
+ int_32 *i32p;
+ int_16 *i16p;
+ int i, length;
+
+ if (c <= 0) {
+ fprintf(stderr, "Bad count for addEntry(): %d\n", (int)c);
+ exit(1);
+ }
+
+ if (h->mutable == 0) {
+ fprintf(stderr, "Attempted addEntry() to immutable header.\n");
+ exit(1);
+ }
+
+ /* Allocate more index space if necessary */
+ if (h->entries_used == h->entries_malloced) {
+ h->entries_malloced += INDEX_MALLOC_SIZE;
+ h->index = realloc(h->index,
+ h->entries_malloced * sizeof(struct indexEntry));
+ }
+
+ /* Fill in the index */
+ i = h->entries_used++;
+ entry = &((h->index)[i]);
+ entry->tag = htonl(tag);
+ entry->type = htonl(type);
+ entry->count = htonl(c);
+ entry->offset = htonl(h->data_used);
+
+ /* Compute length of data to add */
+ switch (type) {
+ case INT64_TYPE:
+ length = sizeof(int_64) * c;
+ break;
+ case INT32_TYPE:
+ length = sizeof(int_32) * c;
+ break;
+ case INT16_TYPE:
+ length = sizeof(int_16) * c;
+ break;
+ case INT8_TYPE:
+ length = sizeof(int_8) * c;
+ break;
+ case CHAR_TYPE:
+ length = sizeof(char) * c;
+ break;
+ case STRING_TYPE:
+ if (c == 1) {
+ /* Special case -- p is just the string */
+ length = strlen(p) + 1;
+ } else {
+ /* Compute sum of length of all strings, including null terminators */
+ i = c;
+ spp = p;
+ length = 0;
+ while (i--) {
+ /* add one for null termination */
+ length += strlen(*spp++) + 1;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Data type %d not supprted\n", (int)type);
+ exit(1);
+ }
+
+ /* Allocate more data space if necessary */
+ if ((length + h->data_used) > h->data_malloced) {
+ h->data_malloced += DATA_MALLOC_SIZE;
+ h->data = realloc(h->data, h->data_malloced);
+ }
+
+ /* Fill in the data */
+ ptr = h->data + h->data_used;
+ switch (type) {
+ case INT32_TYPE:
+ memcpy(ptr, p, length);
+ i = c;
+ i32p = (int_32 *)ptr;
+ while (i--) {
+ *i32p = htonl(*i32p);
+ i32p++;
+ }
+ break;
+ case INT16_TYPE:
+ memcpy(ptr, p, length);
+ i = c;
+ i16p = (int_16 *)ptr;
+ while (i--) {
+ *i16p = htons(*i16p);
+ i16p++;
+ }
+ break;
+ case INT8_TYPE:
+ case CHAR_TYPE:
+ memcpy(ptr, p, length);
+ break;
+ case STRING_TYPE:
+ if (c == 1) {
+ /* Special case -- p is just the string */
+ strcpy(ptr, p);
+ } else {
+ /* Otherwise, p is char** */
+ i = c;
+ spp = p;
+ sp = (char *)ptr;
+ while (i--) {
+ strcpy(sp, *spp);
+ sp += strlen(*spp++) + 1;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Data type %d not supprted\n", (int)type);
+ exit(1);
+ }
+
+ h->data_used += length;
+
+ return 1;
+}
--- /dev/null
+/* RPM - Copyright (C) 1995 Red Hat Software
+ *
+ * header.h - routines for managing rpm tagged structures
+ */
+
+#ifndef _header_h
+#define _header_h
+#include <stdio.h>
+
+#if defined(__alpha__)
+typedef long int int_64;
+typedef int int_32;
+typedef short int int_16;
+typedef char int_8;
+
+typedef unsigned int uint_32;
+
+#else
+
+typedef long long int int_64;
+typedef long int int_32;
+typedef short int int_16;
+typedef char int_8;
+
+typedef unsigned int uint_32;
+#endif
+
+typedef struct headerToken *Header;
+
+/* read and write a header from a file */
+Header readHeader(FILE *f);
+Header mmapHeader(int fd, long offset);
+void writeHeader(FILE *f, Header h);
+
+/* load and unload a header from a chunk of memory */
+Header loadHeader(void *p);
+void *unloadHeader(Header h);
+
+Header newHeader(void);
+void freeHeader(Header h);
+
+/* dump a header to a file, in human readable format */
+void dumpHeader(Header h, FILE *f, int flags);
+
+#define DUMP_INLINE 1
+#define DUMP_SYMBOLIC 2
+
+int getEntry(Header h, int_32 tag, int_32 *type, void **p, int_32 *c);
+int addEntry(Header h, int_32 tag, int_32 type, void *p, int_32 c);
+
+/* Entry Types */
+
+#define NULL_TYPE 0
+#define CHAR_TYPE 1
+#define INT8_TYPE 2
+#define INT16_TYPE 3
+#define INT32_TYPE 4
+#define INT64_TYPE 5
+#define STRING_TYPE 6
+
+/* Entries */
+
+#define NAME 1
+#define VERSION 2
+#define RELEASE 3
+#define SHORT_DESCRIPTION 4
+#define LONG_DESCRIPTION 5
+#define COPYRIGHT 6
+#define DISTRIBUTION 7
+#define VENDOR 8
+#define PACKAGER 9
+#define BUILD_DATE 10
+#define BUILD_HOST 11
+#define INSTALL_DATE 12
+#define GROUP 13
+#define SIZE 14
+#define URL 15
+#define OS 16
+#define ARCH 17
+#define CHANGELOG 18
+#define ICON 19
+#define SOURCE 20
+#define PATCH 21
+
+#endif _header_h
--- /dev/null
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "messages.h"
+
+static minLevel = MESS_NORMAL;
+
+void increaseVerbosity(void) {
+ minLevel--;
+}
+
+void setVerbosity(int level) {
+ minLevel = level;
+}
+
+void message(int level, char * format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (level >= minLevel) {
+ switch (level) {
+ case MESS_VERBOSE:
+ case MESS_NORMAL:
+ vfprintf(stdout, format, args);
+ break;
+
+ case MESS_DEBUG:
+ fprintf(stdout, "D: ");
+ vfprintf(stdout, format, args);
+ break;
+
+ case MESS_WARNING:
+ fprintf(stderr, "warning: ");
+ vfprintf(stderr, format, args);
+ break;
+
+ case MESS_ERROR:
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, format, args);
+ break;
+
+ case MESS_FATALERROR:
+ fprintf(stderr, "fatal error: ");
+ vfprintf(stderr, format, args);
+ exit(1);
+ break;
+ }
+ }
+}
--- /dev/null
+#ifndef H_MESSAGES
+#define H_MESSAGES
+
+#define MESS_DEBUG 1
+#define MESS_VERBOSE 2
+#define MESS_NORMAL 3
+#define MESS_WARNING 4
+#define MESS_ERROR 5
+#define MESS_FATALERROR 6
+
+#define MESS_QUIET (MESS_NORMAL + 1)
+
+void increaseVerbosity(void);
+void setVerbosity(int level);
+void message(int level, char * format, ...);
+
+#endif
--- /dev/null
+#include <stdlib.h>
+
+#include "misc.h"
+
+char ** splitString(char * str, int length, char sep) {
+ char * s, * source, * dest;
+ char ** list;
+ int i;
+ int fields;
+
+ s = malloc(length + 1);
+
+ fields = 1;
+ for (source = str, dest = s, i = 0; i < length; i++, source++, dest++) {
+ *dest = *source;
+ if (*dest == sep) fields++;
+ }
+
+ *dest = '\0';
+
+ list = malloc(sizeof(char *) * (fields + 1));
+
+ dest = s;
+ list[0] = dest;
+ i = 1;
+ while (i < fields) {
+ if (*dest == sep) {
+ list[i++] = dest + 1;
+ *dest = 0;
+ }
+ dest++;
+ }
+
+ list[i] = NULL;
+
+ return list;
+}
+
+void freeSplitString(char ** list) {
+ free(list[0]);
+ free(list);
+}
--- /dev/null
+#ifndef H_MISC
+#define H_MISC
+
+char ** splitString(char * str, int length, char sep);
+void freeSplitString(char ** list);
+
+#endif
--- /dev/null
+#ifndef _H_RPMDB
+#define _H_RPMDB
+
+#include <gdbm.h>
+
+#include "oldrpmfile.h"
+
+typedef enum { RPMDB_NONE, RPMDB_GDBM_ERROR, RPMDB_NO_MEMORY } rpm_error;
+
+struct rpmdb {
+ GDBM_FILE packages;
+ GDBM_FILE nameIndex;
+ GDBM_FILE pathIndex;
+ GDBM_FILE groupIndex;
+ GDBM_FILE iconIndex;
+ GDBM_FILE postIndex;
+ rpm_error rpmdbError;
+ gdbm_error gdbmError;
+};
+
+enum rpmdbFreeType { RPMDB_NOFREE, RPMDB_FREENAME, RPMDB_FREEALL } ;
+
+struct rpmdbLabel {
+ char * name, * version, * release;
+ enum rpmdbFreeType freeType;
+ struct rpmdbLabel * next;
+ int fileNumber; /* -1 means invalid */
+};
+
+struct rpmdbPackageInfo {
+ char * name, * version, * release;
+ char * labelstr;
+ unsigned int installTime, buildTime;
+ unsigned int size;
+ char * description;
+ char * distribution;
+ char * vendor;
+ char * buildHost;
+ char * preamble;
+ unsigned int fileCount;
+ struct rpmFileInfo * files;
+} ;
+
+#define RPMDB_READER 1
+
+int rpmdbOpen(struct rpmdb * rpmdb);
+void rpmdbClose(struct rpmdb * rpmdb);
+struct rpmdbLabel * rpmdbGetAllLabels(struct rpmdb * rpmdb);
+struct rpmdbLabel * rpmdbFindPackagesByFile(struct rpmdb * rpmdb, char * path);
+struct rpmdbLabel * rpmdbFindPackagesByLabel(struct rpmdb * rpmdb,
+ struct rpmdbLabel label);
+
+char * rpmdbGetPackageGroup(struct rpmdb * rpmdb, struct rpmdbLabel label);
+int rpmdbGetPackageInfo(struct rpmdb * rpmdb, struct rpmdbLabel label,
+ struct rpmdbPackageInfo * pinfo);
+void rpmdbFreePackageInfo(struct rpmdbPackageInfo package);
+
+struct rpmdbLabel rpmdbMakeLabel(char * name, char * version, char * release,
+ int fileNumber, enum rpmdbFreeType freeType);
+void rpmdbFreeLabelList(struct rpmdbLabel * list);
+void rpmdbFreeLabel(struct rpmdbLabel label);
+int rpmdbWasError(struct rpmdb * rpmdb);
+
+int rpmdbLabelstrToLabel(char * str, int length, struct rpmdbLabel * label);
+char * rpmdbLabelToLabelstr(struct rpmdbLabel label, int withFileNum);
+int rpmdbLabelCmp(struct rpmdbLabel * one, struct rpmdbLabel * two);
+
+void rpmdbSetPrefix(char * new);
+
+#endif
--- /dev/null
+#ifndef H_RPM_MALLOC
+#define H_RPM_MALLOC
+
+#ifndef __linux__
+#error malloc definition needed for non Linux OS
+#endif
+
+#endif
--- /dev/null
+#include <stdio.h>
+
+#include "rpmerr.h"
+
+void error(int code, ...)
+{
+ fprintf(stderr, "error, error, error\n");
+}
--- /dev/null
+#include "header.h"
+
+void main(int argc, char ** argv)
+{
+ Header h;
+ FILE *f;
+ char *sa[] = { "one", "two", "three" };
+ int_32 i32 = 400;
+ int_32 i32a[] = { 100, 200, 300 };
+ int_16 i16 = 1;
+ int_16 i16a[] = { 100, 200, 300 };
+ char ca[] = "char array";
+
+ h = newHeader();
+
+ addEntry(h, NAME, STRING_TYPE, "MarcEwing", 1);
+ addEntry(h, VERSION, STRING_TYPE, "1.1", 1);
+ addEntry(h, VERSION, STRING_TYPE, sa, 3);
+ addEntry(h, SIZE, INT32_TYPE, &i32, 1);
+ addEntry(h, SIZE, INT16_TYPE, &i16, 1);
+ addEntry(h, SIZE, INT16_TYPE, i16a, 3);
+ addEntry(h, VENDOR, CHAR_TYPE, ca, strlen(ca));
+ addEntry(h, SIZE, INT32_TYPE, i32a, 3);
+
+ f = fopen("test.out", "w");
+ writeHeader(f, h);
+ fclose(f);
+
+ dumpHeader(h, stdout, 1);
+}
+
+
--- /dev/null
+#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 rpmdbLabel ** list);
+static char * prefix = "/var/lib/rpm";
+
+char * rpmdbLabelToLabelstr(struct rpmdbLabel 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 rpmdbLabelstrToLabel(char * str, int length, struct rpmdbLabel * 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 rpmdbLabel ** list) {
+ char * start, * chptr;
+ struct rpmdbLabel * head = NULL;
+ struct rpmdbLabel * tail = NULL;
+ struct rpmdbLabel * label;
+
+ start = str;
+ for (chptr = start; (chptr - str) < length; chptr++) {
+ /* spaces following a space get ignored */
+ if (*chptr == ' ' && start < chptr) {
+ label = malloc(sizeof(struct rpmdbLabel));
+ if (!label) {
+ rpmdbFreeLabelList(head);
+ return 1;
+ }
+ if (rpmdbLabelstrToLabel(start, chptr - start, label)) {
+ free(label);
+ rpmdbFreeLabelList(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 rpmdbLabel));
+ if (!label) {
+ rpmdbFreeLabelList(head);
+ return 1;
+ }
+ if (rpmdbLabelstrToLabel(start, chptr - start, label)) {
+ free(label);
+ rpmdbFreeLabelList(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 rpmdbOpen(struct rpmdb * rpmdb) {
+ unsigned int gdbmFlags;
+ char path[255];
+ int goterr = 0;
+
+ rpmdb->rpmdbError = RPMDB_NONE;
+
+ gdbmFlags = GDBM_READER;
+
+ strcpy(path, prefix);
+ strcat(path, "/packages");
+ rpmdb->packages = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->packages) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ strcpy(path, prefix);
+ strcat(path, "/nameidx");
+ rpmdb->nameIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->packages) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ strcpy(path, prefix);
+ strcat(path, "/pathidx");
+ rpmdb->pathIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->packages) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ strcpy(path, prefix);
+ strcat(path, "/iconidx");
+ rpmdb->iconIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->iconIndex) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ strcpy(path, prefix);
+ strcat(path, "/groupindex");
+ rpmdb->groupIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->packages) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ strcpy(path, prefix);
+ strcat(path, "/postidx");
+ rpmdb->postIndex = gdbm_open(path, 1024, gdbmFlags, 0644, NULL);
+ if (!rpmdb->postIndex) {
+ error(RPMERR_GDBMOPEN, path, gdbm_strerror(gdbm_errno));
+ goterr = 1;
+ }
+
+ if (goterr) {
+ rpmdbClose(rpmdb);
+ return -1;
+ }
+
+ return 0;
+}
+
+void rpmdbClose(struct rpmdb * rpmdb) {
+ gdbm_close(rpmdb->packages);
+ gdbm_close(rpmdb->nameIndex);
+ gdbm_close(rpmdb->pathIndex);
+ gdbm_close(rpmdb->postIndex);
+ gdbm_close(rpmdb->groupIndex);
+ gdbm_close(rpmdb->iconIndex);
+}
+
+struct rpmdbLabel * rpmdbGetAllLabels(struct rpmdb * rpmdb) {
+ datum rec;
+
+ struct rpmdbLabel * head = NULL;
+ struct rpmdbLabel * tail = NULL;
+ struct rpmdbLabel * label;
+
+ rpmdb->rpmdbError = RPMDB_NONE;
+
+ rec = gdbm_firstkey(rpmdb->packages);
+ while (rec.dptr) {
+ label = malloc(sizeof(struct rpmdbLabel));
+ if (!label) {
+ rpmdbFreeLabelList(head);
+ rpmdb->rpmdbError = RPMDB_NO_MEMORY;
+ return NULL;
+ }
+ if (rpmdbLabelstrToLabel(rec.dptr, rec.dsize, label)) {
+ free(label);
+ rpmdbFreeLabelList(head);
+ rpmdb->rpmdbError = RPMDB_NO_MEMORY;
+ return NULL;
+ }
+
+ if (!head) {
+ head = label;
+ tail = label;
+ } else {
+ tail->next = label;
+ tail = tail->next;
+ }
+
+ rec = gdbm_nextkey(rpmdb->packages, rec);
+ }
+
+ return head;
+}
+
+struct rpmdbLabel * rpmdbFindPackagesByFile(struct rpmdb * rpmdb, char * path) {
+ datum rec;
+ datum key;
+ struct rpmdbLabel * list;
+
+ rpmdb->rpmdbError = RPMDB_NONE;
+
+ key.dptr = path;
+ key.dsize = strlen(path);
+ rec = gdbm_fetch(rpmdb->pathIndex, key);
+
+ if (!rec.dptr)
+ return NULL;
+ if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
+ free(rec.dptr);
+ rpmdb->rpmdbError = RPMDB_NO_MEMORY;
+ return NULL;
+ }
+ free(rec.dptr);
+
+ return list;
+}
+
+struct rpmdbLabel * rpmdbFindPackagesByLabel(struct rpmdb * rpmdb,
+ struct rpmdbLabel label)
+
+/* the Name has to be here. The version/release fields optionally
+ restrict the search. Either will do. */
+
+{
+ datum rec;
+ datum key;
+ struct rpmdbLabel * list;
+ struct rpmdbLabel * prospect;
+ struct rpmdbLabel * parent;
+ int bad;
+
+ rpmdb->rpmdbError = RPMDB_NONE;
+
+ key.dptr = label.name;
+ key.dsize = strlen(label.name);
+ rec = gdbm_fetch(rpmdb->nameIndex, key);
+
+ if (!rec.dptr)
+ return NULL;
+ if (labelstrlistToLabelList(rec.dptr, rec.dsize, &list)) {
+ free(rec.dptr);
+ rpmdb->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) {
+ rpmdbFreeLabel(*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 rpmdbLabel rpmdbMakeLabel(char * name, char * version, char * release,
+ int fileNumber, enum rpmdbFreeType freeType) {
+ struct rpmdbLabel label;
+
+ label.next = NULL;
+ label.freeType = freeType;
+ label.name = name;
+ label.version = version;
+ label.release = release;
+ label.fileNumber = fileNumber;
+
+ return label;
+}
+
+void rpmdbFreeLabelList(struct rpmdbLabel * list) {
+ struct rpmdbLabel * saved;
+
+ while (list) {
+ rpmdbFreeLabel(*list);
+ saved = list->next;
+ free(list);
+ list = saved;
+ }
+}
+
+void rpmdbFreeLabel(struct rpmdbLabel 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 * rpmdbGetPackageGroup(struct rpmdb * rpmdb, struct rpmdbLabel label) {
+ datum key, rec;
+
+ key.dptr = label.name;
+ key.dsize = strlen(label.name);
+
+ rec = gdbm_fetch(rpmdb->groupIndex, key);
+ if (!rec.dptr)
+ error(RPMERR_OLDDBCORRUPT, "group not found in database");
+
+ return rec.dptr;
+}
+
+/* return 0 on success, 1 on failure */
+int rpmdbGetPackageInfo(struct rpmdb * rpmdb, struct rpmdbLabel label,
+ struct rpmdbPackageInfo * pinfo) {
+ char * labelstr;
+ char ** list, ** prelist;
+ char ** strptr;
+ datum key, rec;
+ int i, j;
+
+ labelstr = rpmdbLabelToLabelstr(label, 0);
+
+ message(MESS_DEBUG, "pulling %s from database\n", labelstr);
+
+ key.dptr = labelstr;
+ key.dsize = strlen(labelstr);
+
+ rec = gdbm_fetch(rpmdb->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;
+
+ for (strptr = prelist; *strptr; strptr++) {
+ if (!strncmp("Description: ", *strptr, 13))
+ pinfo->description = strdup((*strptr) + 13);
+ else if (!strncmp("Distribution: ", *strptr, 14))
+ pinfo->distribution = strdup((*strptr) + 14);
+ else if (!strncmp("Vendor: ", *strptr, 8))
+ pinfo->vendor = strdup((*strptr) + 8);
+ else if (!strncmp("size: ", *strptr, 6))
+ pinfo->size = atoi((*strptr) + 6);
+ else if (!strncmp("BuildTime: ", *strptr, 11))
+ pinfo->buildTime =atoi((*strptr) + 11);
+ else if (!strncmp("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("");
+
+ pinfo->files = malloc(sizeof(struct rpmFileInfo) * pinfo->fileCount);
+
+ j = 8;
+ for (i = 0; i < pinfo->fileCount; i++) {
+ rpmfileFromInfoLine(list[j], list[j + 1], list[j + 2],
+ &pinfo->files[i]);
+ j += 3;
+ }
+
+ freeSplitString(list);
+
+ return 0;
+}
+
+void rpmdbFreePackageInfo(struct rpmdbPackageInfo 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.distribution);
+ free(package.preamble);
+
+ for (i = 0; i < package.fileCount; i++) {
+ rpmfileFree(&package.files[i]);
+ }
+
+ free(package.files);
+}
+
+int rpmdbLabelCmp(struct rpmdbLabel * one, struct rpmdbLabel * 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 rpmdbSetPrefix(char * new) {
+ prefix = new;
+}
--- /dev/null
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "messages.h"
+
+static minLevel = MESS_NORMAL;
+
+void increaseVerbosity(void) {
+ minLevel--;
+}
+
+void setVerbosity(int level) {
+ minLevel = level;
+}
+
+void message(int level, char * format, ...) {
+ va_list args;
+
+ va_start(args, format);
+ if (level >= minLevel) {
+ switch (level) {
+ case MESS_VERBOSE:
+ case MESS_NORMAL:
+ vfprintf(stdout, format, args);
+ break;
+
+ case MESS_DEBUG:
+ fprintf(stdout, "D: ");
+ vfprintf(stdout, format, args);
+ break;
+
+ case MESS_WARNING:
+ fprintf(stderr, "warning: ");
+ vfprintf(stderr, format, args);
+ break;
+
+ case MESS_ERROR:
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, format, args);
+ break;
+
+ case MESS_FATALERROR:
+ fprintf(stderr, "fatal error: ");
+ vfprintf(stderr, format, args);
+ exit(1);
+ break;
+ }
+ }
+}
--- /dev/null
+#include <stdio.h>
+
+#include "rpmerr.h"
+
+void error(int code, ...)
+{
+ fprintf(stderr, "error, error, error\n");
+}