From: Kristian Høgsberg Date: Wed, 7 Nov 2007 05:33:56 +0000 (-0500) Subject: Add the first bits of rpm file parser. X-Git-Tag: 0.1~286 X-Git-Url: http://project.juiblex.co.uk/git/?a=commitdiff_plain;h=1b2b945a07af3cbc802edb92e7ae67835ac1f343;p=razor.git Add the first bits of rpm file parser. --- diff --git a/Makefile b/Makefile index 76d2e5a..6a3d630 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CFLAGS = -Wall -g -O2 LDLIBS = -lexpat -lz -g -lrpm -lcurl -razor : razor.o import.o sha1.o main.o +razor : razor.o import.o sha1.o main.o rpm.o clean : rm -f *.o razor diff --git a/TODO b/TODO index 58f17d2..746d240 100644 --- a/TODO +++ b/TODO @@ -21,6 +21,11 @@ Towards replacing rpm + yum (0.1): - pre-link changing binaries and libs on disk screwing up checksum? +- nail down byte-order and word sizes of repo file. + +- version the sections in the file, put the element size in the header + so we can add stuff to elements in a backwards compatible way. + Misc ideas: - eliminate duplicate entries in package property lists. @@ -72,9 +77,6 @@ Misc ideas: idiom for iteration of directories. -- version the sections in the file, put the element size in the header - so we can add stuff to elements in a backwards compatible way. - - overlay package sets? mount a read-only /usr over nfs or from the virt-host and have a local package set overlaid over the read-only one. shouldn't need new features in the core package set data @@ -89,3 +91,6 @@ Misc ideas: - incremental rawhide repo updates? instead of downloading 10MB zipped repo every time, download a diff repo? + +- use hash tables for dirs when importing files to avoid qsorting all + files in rawhide. diff --git a/main.c b/main.c index e6c9e9c..00ce88a 100644 --- a/main.c +++ b/main.c @@ -291,6 +291,14 @@ command_diff(int argc, const char *argv[]) return 0; } +static int +command_dump_rpm(int argc, const char *argv[]) +{ + razor_rpm_dump(argv[0]); + + return 0; +} + static struct { const char *name; const char *description; @@ -310,7 +318,8 @@ static struct { { "import-rpmdb", "import the system rpm database", command_import_rpmdb }, { "validate", "validate a package set", command_validate }, { "update", "update all or specified packages", command_update }, - { "diff", "show diff between two package sets", command_diff } + { "diff", "show diff between two package sets", command_diff }, + { "dump", "dump rpm file contents", command_dump_rpm } }; static int diff --git a/razor.h b/razor.h index efd405c..44872d6 100644 --- a/razor.h +++ b/razor.h @@ -61,4 +61,8 @@ struct razor_set *razor_import_rzr_files(int count, const char **files); struct razor_set *razor_set_create_from_yum(void); struct razor_set *razor_set_create_from_rpmdb(void); +/* RPM functions */ +void +razor_rpm_dump(const char *filename); + #endif /* _RAZOR_H_ */ diff --git a/rpm.c b/rpm.c new file mode 100644 index 0000000..4424fd1 --- /dev/null +++ b/rpm.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define RPM_LEAD_SIZE 96 + +struct rpm_lead { + unsigned char magic[4]; + unsigned char major; + unsigned char minor; + short type; + short archnum; + char name[66]; + short osnum; + short signature_type; + char reserved[16]; +}; + +struct rpm_header { + unsigned char magic[4]; + unsigned char reserved[4]; + int nindex; + int hsize; +}; + +struct rpm_header_index { + int tag; + int type; + int offset; + int count; +}; + +#define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1)) + +static void dump_header(struct rpm_header *header) +{ + struct rpm_header_index *base, *index; + int i, j, nindex, tag, offset, type, count; + char *pool, *name; + + nindex = ntohl(header->nindex); + printf("header index records: %d\n", nindex); + printf("header storage size: %d\n", ntohl(header->hsize)); + base = (struct rpm_header_index *) (header + 1); + pool = (void *) (header + 1) + nindex * sizeof *index; + + printf("headers:\n"); + for (i = 0; i < nindex; i++) { + index = base + i; + tag = ntohl(index->tag); + offset = ntohl(index->offset); + type = ntohl(index->type); + count = ntohl(index->count); + printf(" 0x%08x 0x%08x 0x%08x 0x%08x\n", + tag, type, offset, count); + + switch (tag) { + case RPMTAG_NAME: + name = "name"; + break; + case RPMTAG_VERSION: + name = "version"; + break; + case RPMTAG_RELEASE: + name = "release"; + break; + case RPMTAG_REQUIRENAME: + name = "requires"; + break; + default: + name = "unknown"; + break; + } + + switch (type) { + case RPM_STRING_TYPE: + printf(" (%s %s)\n", name, pool + offset); + break; + case RPM_STRING_ARRAY_TYPE: + printf(" (%s", name); + for (j = 0; j < count; j++) { + printf(" %s", pool + offset); + offset += strlen(pool + offset) + 1; + } + printf(")\n"); + break; + } + } +} + +void +razor_rpm_dump(const char *filename) +{ + struct stat buf; + void *p; + int fd, nindex, hsize; + struct rpm_header *signature, *header; + struct rpm_header_index *index; + + if (stat(filename, &buf) < 0) { + fprintf(stderr, "no such file %s\n", filename); + return; + } + + fd = open(filename, O_RDONLY); + p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + + printf("%s: %ldkB\n", filename, buf.st_size / 1024); + signature = p + RPM_LEAD_SIZE; + + nindex = ntohl(signature->nindex); + hsize = ntohl(signature->hsize); + header = (void *) (signature + 1) + + ALIGN(nindex * sizeof *index + hsize, 8); + + dump_header(signature); + dump_header(header); + + munmap(p, buf.st_size); +}