Initial revision
authorroot <devnull@localhost>
Mon, 27 Nov 1995 22:31:21 +0000 (22:31 +0000)
committerroot <devnull@localhost>
Mon, 27 Nov 1995 22:31:21 +0000 (22:31 +0000)
CVS patchset: 1
CVS date: 1995/11/27 22:31:21

19 files changed:
Makefile.in [new file with mode: 0644]
build/build.c [new file with mode: 0644]
build/spec.c [new file with mode: 0644]
build/spec.h [new file with mode: 0644]
convertdb.c [new file with mode: 0644]
lib/Makefile.in [new file with mode: 0644]
lib/header.c [new file with mode: 0644]
lib/header.h [new file with mode: 0644]
lib/messages.c [new file with mode: 0644]
lib/messages.h [new file with mode: 0644]
lib/misc.c [new file with mode: 0644]
lib/misc.h [new file with mode: 0644]
lib/oldrpmdb.h [new file with mode: 0644]
lib/rpm_malloc.h [new file with mode: 0644]
lib/rpmerr.c [new file with mode: 0644]
lib/test.c [new file with mode: 0644]
oldrpmdb.c [new file with mode: 0644]
rpmio/messages.c [new file with mode: 0644]
rpmio/rpmerr.c [new file with mode: 0644]

diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..9576f58
--- /dev/null
@@ -0,0 +1,25 @@
+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)
diff --git a/build/build.c b/build/build.c
new file mode 100644 (file)
index 0000000..23cd917
--- /dev/null
@@ -0,0 +1,12 @@
+#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);
+}
diff --git a/build/spec.c b/build/spec.c
new file mode 100644 (file)
index 0000000..f0d0353
--- /dev/null
@@ -0,0 +1,118 @@
+/* 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;
+}
diff --git a/build/spec.h b/build/spec.h
new file mode 100644 (file)
index 0000000..e61a6e6
--- /dev/null
@@ -0,0 +1,14 @@
+/* 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
diff --git a/convertdb.c b/convertdb.c
new file mode 100644 (file)
index 0000000..c33991b
--- /dev/null
@@ -0,0 +1,7 @@
+/* This converts an old style (rpm 1.x) database to the new style */
+
+#include <oldrpmdb.h>
+
+int convertDB(char * dbprefix) {
+    
+}
diff --git a/lib/Makefile.in b/lib/Makefile.in
new file mode 100644 (file)
index 0000000..e62a041
--- /dev/null
@@ -0,0 +1,31 @@
+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
diff --git a/lib/header.c b/lib/header.c
new file mode 100644 (file)
index 0000000..1164965
--- /dev/null
@@ -0,0 +1,464 @@
+/* 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;
+}
diff --git a/lib/header.h b/lib/header.h
new file mode 100644 (file)
index 0000000..517663e
--- /dev/null
@@ -0,0 +1,85 @@
+/* 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
diff --git a/lib/messages.c b/lib/messages.c
new file mode 100644 (file)
index 0000000..81ba019
--- /dev/null
@@ -0,0 +1,49 @@
+#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;
+       }
+    }
+}
diff --git a/lib/messages.h b/lib/messages.h
new file mode 100644 (file)
index 0000000..4de2cd8
--- /dev/null
@@ -0,0 +1,17 @@
+#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
diff --git a/lib/misc.c b/lib/misc.c
new file mode 100644 (file)
index 0000000..a08da13
--- /dev/null
@@ -0,0 +1,42 @@
+#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);
+}
diff --git a/lib/misc.h b/lib/misc.h
new file mode 100644 (file)
index 0000000..c82a9a9
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef H_MISC
+#define H_MISC
+
+char ** splitString(char * str, int length, char sep);
+void freeSplitString(char ** list);
+
+#endif
diff --git a/lib/oldrpmdb.h b/lib/oldrpmdb.h
new file mode 100644 (file)
index 0000000..f28a450
--- /dev/null
@@ -0,0 +1,70 @@
+#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
diff --git a/lib/rpm_malloc.h b/lib/rpm_malloc.h
new file mode 100644 (file)
index 0000000..63c9246
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef H_RPM_MALLOC
+#define H_RPM_MALLOC
+
+#ifndef __linux__
+#error malloc definition needed for non Linux OS
+#endif
+
+#endif
diff --git a/lib/rpmerr.c b/lib/rpmerr.c
new file mode 100644 (file)
index 0000000..84f743c
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+#include "rpmerr.h"
+
+void error(int code, ...)
+{
+    fprintf(stderr, "error, error, error\n");
+}
diff --git a/lib/test.c b/lib/test.c
new file mode 100644 (file)
index 0000000..7e93a96
--- /dev/null
@@ -0,0 +1,32 @@
+#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);
+}
+
+  
diff --git a/oldrpmdb.c b/oldrpmdb.c
new file mode 100644 (file)
index 0000000..ba2f398
--- /dev/null
@@ -0,0 +1,498 @@
+#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;
+}
diff --git a/rpmio/messages.c b/rpmio/messages.c
new file mode 100644 (file)
index 0000000..81ba019
--- /dev/null
@@ -0,0 +1,49 @@
+#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;
+       }
+    }
+}
diff --git a/rpmio/rpmerr.c b/rpmio/rpmerr.c
new file mode 100644 (file)
index 0000000..84f743c
--- /dev/null
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+#include "rpmerr.h"
+
+void error(int code, ...)
+{
+    fprintf(stderr, "error, error, error\n");
+}