commit 7153c160969d70a083f791bf75f9b4d09d2f2a45 Author: Unknown Author Date: Mon Nov 27 22:31:21 1995 +0000 Initial revision CVS patchset: 1 CVS date: 1995/11/27 22:31:21 diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..9576f5805 --- /dev/null +++ b/Makefile.in @@ -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 index 000000000..23cd917ec --- /dev/null +++ b/build/build.c @@ -0,0 +1,12 @@ +#include +#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 index 000000000..f0d035383 --- /dev/null +++ b/build/spec.c @@ -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 +#include + +#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 index 000000000..e61a6e6d3 --- /dev/null +++ b/build/spec.h @@ -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 index 000000000..c33991b91 --- /dev/null +++ b/convertdb.c @@ -0,0 +1,7 @@ +/* This converts an old style (rpm 1.x) database to the new style */ + +#include + +int convertDB(char * dbprefix) { + +} diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 000000000..e62a0416e --- /dev/null +++ b/lib/Makefile.in @@ -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 index 000000000..116496527 --- /dev/null +++ b/lib/header.c @@ -0,0 +1,464 @@ +/* RPM - Copyright (C) 1995 Red Hat Software + * + * header.c - routines for managing rpm headers + */ + +#include +#include +#include +#include +#include +#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 index 000000000..517663ecd --- /dev/null +++ b/lib/header.h @@ -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 + +#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 index 000000000..81ba0196b --- /dev/null +++ b/lib/messages.c @@ -0,0 +1,49 @@ +#include +#include + +#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 index 000000000..4de2cd8be --- /dev/null +++ b/lib/messages.h @@ -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 index 000000000..a08da132d --- /dev/null +++ b/lib/misc.c @@ -0,0 +1,42 @@ +#include + +#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 index 000000000..c82a9a9a1 --- /dev/null +++ b/lib/misc.h @@ -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 index 000000000..f28a45057 --- /dev/null +++ b/lib/oldrpmdb.h @@ -0,0 +1,70 @@ +#ifndef _H_RPMDB +#define _H_RPMDB + +#include + +#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 index 000000000..63c924693 --- /dev/null +++ b/lib/rpm_malloc.h @@ -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 index 000000000..84f743ceb --- /dev/null +++ b/lib/rpmerr.c @@ -0,0 +1,8 @@ +#include + +#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 index 000000000..7e93a96ae --- /dev/null +++ b/lib/test.c @@ -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 index 000000000..ba2f39879 --- /dev/null +++ b/oldrpmdb.c @@ -0,0 +1,498 @@ +#include +#include +#include + +#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 index 000000000..81ba0196b --- /dev/null +++ b/rpmio/messages.c @@ -0,0 +1,49 @@ +#include +#include + +#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 index 000000000..84f743ceb --- /dev/null +++ b/rpmio/rpmerr.c @@ -0,0 +1,8 @@ +#include + +#include "rpmerr.h" + +void error(int code, ...) +{ + fprintf(stderr, "error, error, error\n"); +}