Add the first bits of rpm file parser.
authorKristian Høgsberg <krh@redhat.com>
Wed, 7 Nov 2007 05:33:56 +0000 (00:33 -0500)
committerKristian Høgsberg <krh@redhat.com>
Wed, 7 Nov 2007 05:33:56 +0000 (00:33 -0500)
Makefile
TODO
main.c
razor.h
rpm.c [new file with mode: 0644]

index 76d2e5a..6a3d630 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
--- 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 (file)
index 0000000..4424fd1
--- /dev/null
+++ b/rpm.c
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <rpm/rpmlib.h>
+
+#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);
+}