Initial commit.
authorKristian Høgsberg <krh@redhat.com>
Mon, 3 Sep 2007 18:36:59 +0000 (14:36 -0400)
committerKristian Høgsberg <krh@redhat.com>
Mon, 3 Sep 2007 18:36:59 +0000 (14:36 -0400)
Makefile [new file with mode: 0644]
import-rpm.sh [new file with mode: 0755]
razor.c [new file with mode: 0644]
sha1.c [new file with mode: 0644]
sha1.h [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6b61ae8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+CFLAGS = -Wall -g
+LDLIBS = -lexpat -g
+
+razor : razor.o sha1.o
+
+clean :
+       rm -f *.o razor
diff --git a/import-rpm.sh b/import-rpm.sh
new file mode 100755 (executable)
index 0000000..0d71fa1
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+import_rpm() {
+    echo "<package name=\"$p\" version=\"3.2\" build=\"9\">"
+    echo "  <properties>"
+
+    rpm -q --provides $p | sort -u | while read name ignore version; do
+       echo "    <provides name=\"$name\"/>"
+    done
+
+    rpm -q --requires $p | sort -u | while read name ignore version; do
+       echo "    <requires name=\"$name\"/>"
+    done
+
+    echo "  </properties>"
+    echo "</package>"
+}
+
+mkdir pkgs
+rpm -qa | while read p; do
+    base=${p%-*-*}
+    echo $base
+    import_rpm $base > pkgs/$base.rzr
+done
diff --git a/razor.c b/razor.c
new file mode 100644 (file)
index 0000000..2ccbc98
--- /dev/null
+++ b/razor.c
@@ -0,0 +1,495 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <expat.h>
+#include "sha1.h"
+
+static int
+write_to_fd(int fd, void *p, size_t size)
+{
+       int rest, len;
+
+       rest = size;
+       while (rest > 0) {
+               len = write(fd, p, rest);
+               if (len < 0)
+                       return -1;
+               rest -= len;
+       }
+
+       return 0;
+}
+
+static int
+write_to_file(const char *filename, void *p, size_t size)
+{
+       int fd, err;
+
+       fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+       if (fd < 0)
+               return -1;
+       err = write_to_fd(fd, p, size);
+       close(fd);
+
+       return err;
+}
+
+struct hashtable_header {
+       unsigned int magic;
+       unsigned int version;
+       struct { unsigned int type, offset; } sections[0];
+};
+
+#define HASHTABLE_MAGIC 0x7a7a7a7a
+#define HASHTABLE_VERSION 1
+#define HASHTABLE_BUCKETS 1
+#define HASHTABLE_STRINGS 2
+
+struct hashtable {
+       unsigned long *buckets;
+       int bucket_count, bucket_alloc;
+       char *string_pool;
+       int pool_size, pool_alloc;
+       struct hashtable_header *header;
+};
+
+static void *
+zalloc(size_t size)
+{
+       void *p;
+
+       p = malloc(size);
+       memset(p, 0, size);
+
+       return p;
+}
+
+struct hashtable *
+hashtable_create(void)
+{
+       struct hashtable *ht;
+
+       ht = zalloc(sizeof *ht);
+       ht->buckets = zalloc(4096 * sizeof *ht->buckets);
+       ht->bucket_count = 0;
+       ht->bucket_alloc = 4096;
+
+       ht->string_pool = zalloc(4096);
+       ht->pool_size = 1;
+       ht->pool_alloc = 4096;
+
+       return ht;
+}
+
+struct hashtable *
+hashtable_create_from_file(const char *filename)
+{
+       struct hashtable *ht;
+       struct stat stat;
+       unsigned int size, offset;
+       int fd, i;
+
+       ht = zalloc(sizeof *ht);
+       fd = open(filename, O_RDONLY);
+       if (fstat(fd, &stat) < 0)
+               return NULL;
+       ht->header = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+       if (ht->header == MAP_FAILED) {
+               free(ht);
+               return NULL;
+       }
+
+       for (i = 0; i < ht->header->sections[i].type; i++) {
+               offset = ht->header->sections[i].offset;
+               size = ht->header->sections[i + 1].offset - offset;
+
+               switch (ht->header->sections[i].type) {
+               case HASHTABLE_BUCKETS:
+                       ht->buckets = (void *) ht->header + offset;
+                       ht->bucket_count = size / sizeof *ht->buckets;
+                       ht->bucket_alloc = ht->bucket_count;
+                       break;
+               case HASHTABLE_STRINGS:
+                       ht->string_pool = (void *) ht->header + offset;
+                       ht->pool_size = size;
+                       ht->pool_alloc = size;
+                       break;
+               }
+       }
+       close(fd);
+
+       return ht;
+}
+
+void
+hashtable_destroy(struct hashtable *ht)
+{
+       unsigned int size;
+       int i;
+
+       if (ht->header) {
+               for (i = 0; ht->header->sections[i].type; i++)
+                       ;
+               size = ht->header->sections[i].type;
+               munmap(ht->header, size);
+       } else {
+               free(ht->buckets);
+               free(ht->string_pool);
+       }
+
+       free(ht);
+}
+
+static int
+hashtable_write(struct hashtable *ht, const char *filename)
+{
+       int fd;
+       char data[4096];
+       struct hashtable_header *header = (struct hashtable_header *) data;
+
+       memset(data, 0, sizeof data);
+       header->magic = HASHTABLE_MAGIC;
+       header->version = HASHTABLE_VERSION;
+
+       header->sections[0].type = HASHTABLE_BUCKETS;
+       header->sections[0].offset = sizeof data;
+
+       header->sections[1].type = HASHTABLE_STRINGS;
+       header->sections[1].offset =
+               sizeof data + ht->bucket_alloc * sizeof *ht->buckets;
+
+       header->sections[2].type = 0;
+       header->sections[2].offset =
+               header->sections[1].offset + ht->pool_size;
+
+       fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+       if (fd < 0)
+               return -1;
+
+       write_to_fd(fd, data, sizeof data);
+       write_to_fd(fd, ht->buckets, ht->bucket_alloc * sizeof *ht->buckets);
+       write_to_fd(fd, ht->string_pool, ht->pool_size);
+
+       return 0;
+}
+
+static unsigned int
+hash_string(const char *key)
+{
+       const char *p;
+       unsigned int hash = 0;
+
+       for (p = key; *p; p++)
+               hash = (hash << 2) ^ *p;
+
+       return hash;
+}
+
+unsigned long
+hashtable_lookup(struct hashtable *ht, const char *key)
+{
+       unsigned int start;
+       unsigned int mask;
+       unsigned long value;
+       int i;
+
+       mask = ht->bucket_alloc - 1;
+       start = hash_string(key) & mask;
+       i = start;
+       do {
+               value = ht->buckets[i];
+
+               if (value == 0)
+                       return 0;
+
+               if (strcmp(key, &ht->string_pool[value]) == 0)
+                       return value;
+
+               i = (i + 1) & mask;
+       } while (i != start);
+
+       return 0;
+}
+
+static unsigned long
+add_to_string_pool(struct hashtable *ht, const char *key)
+{
+       int len, alloc;
+       char *pool;
+       unsigned long value;
+
+       len = strlen(key) + 1;
+       alloc = ht->pool_alloc;
+       while (alloc < ht->pool_size + len)
+               alloc *= 2;
+       if (ht->pool_alloc < alloc) {
+               pool = realloc(ht->string_pool, alloc);
+               if (pool == NULL)
+                       return 0;
+               ht->string_pool = pool;
+               ht->pool_alloc = alloc;
+       }
+
+       memcpy(ht->string_pool + ht->pool_size, key, len);
+       value = ht->pool_size;
+       ht->pool_size += len;
+
+       return value;
+}
+
+static void
+do_insert(struct hashtable *ht, unsigned long value)
+{
+       unsigned int mask;
+       const char *key;
+       int i, start;
+
+       key = &ht->string_pool[value];
+       mask = ht->bucket_alloc - 1;
+       start = hash_string(key) & mask;
+       i = start;
+       do {
+               if (ht->buckets[i] == 0) {
+                       ht->buckets[i] = value;
+                       break;
+               }
+               i = (i + 1) & mask;
+       } while (i != start);
+}
+
+unsigned long
+hashtable_insert(struct hashtable *ht, const char *key)
+{
+       unsigned long value, *buckets, *old_buckets;
+       int i, alloc, old_alloc;
+
+       alloc = ht->bucket_alloc;
+       while (alloc < 4 * ht->bucket_count)
+               alloc *= 2;
+
+       if (alloc != ht->bucket_alloc) {
+               buckets = zalloc(alloc * sizeof *ht->buckets);
+               if (buckets == NULL)
+                       return 0;
+               old_buckets = ht->buckets;
+               ht->buckets = buckets;
+               old_alloc = ht->bucket_alloc;
+               ht->bucket_alloc = alloc;
+               
+               for (i = 0; i < old_alloc; i++) {
+                       value = old_buckets[i];
+                       if (value != 0)
+                               do_insert(ht, value);
+               }
+               free(old_buckets);
+       }
+
+       value = add_to_string_pool(ht, key);
+       do_insert (ht, value);
+       ht->bucket_count++;
+
+       return value;
+}
+
+struct razor_context {
+       struct hashtable *global_ht;
+};
+
+struct razor_context *
+razor_context_create (void)
+{
+       struct razor_context *ctx;
+
+       ctx = malloc(sizeof *ctx);
+       ctx->global_ht = hashtable_create();
+
+       return ctx;
+}
+
+struct razor_context *
+razor_context_create_from_file (const char *filename)
+{
+       struct razor_context *ctx;
+
+       ctx = malloc(sizeof *ctx);
+       ctx->global_ht = hashtable_create_from_file(filename);
+
+       return ctx;
+}
+
+unsigned long
+razor_context_tokenize(struct razor_context *ctx, const char *string)
+{
+       unsigned long token;
+
+       token = hashtable_lookup(ctx->global_ht, string);
+       if (token != 0)
+               return token;
+
+       return hashtable_insert(ctx->global_ht, string);
+}
+
+struct razor_set {
+       struct razor_context *ctx;
+};
+
+struct parsing_context {
+       struct razor_context *ctx;
+};
+
+static void
+start_element(void *data, const char *name, const char **atts)
+{
+       struct parsing_context *ctx = data;
+       int i;
+
+       for (i = 0; atts[i]; i += 2)
+               razor_context_tokenize(ctx->ctx, atts[i + 1]);
+}
+
+static void
+end_element (void *data, const char *name)
+{
+}
+
+static char *
+sha1_to_hex(const unsigned char *sha1)
+{
+       static int bufno;
+       static char hexbuffer[4][50];
+       static const char hex[] = "0123456789abcdef";
+       char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
+       int i;
+
+       for (i = 0; i < 20; i++) {
+               unsigned int val = *sha1++;
+               *buf++ = hex[val >> 4];
+               *buf++ = hex[val & 0xf];
+       }
+       *buf = '\0';
+
+       return buffer;
+}
+
+static int
+razor_context_read_file(struct razor_context *ctx, const char *filename)
+{
+       SHA_CTX sha1;
+       XML_Parser parser;
+       struct parsing_context pctx;
+       int fd;
+       void *p;
+       struct stat stat;
+       char buf[128];
+       unsigned char hash[20];
+
+       fd = open(filename, O_RDONLY);
+       if (fstat(fd, &stat) < 0)
+               return -1;
+       p = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+       if (p == MAP_FAILED)
+               return -1;
+
+       parser = XML_ParserCreate(NULL);
+       pctx.ctx = ctx;
+       XML_SetUserData(parser, &pctx);
+       XML_SetElementHandler(parser, start_element, end_element);
+       if (XML_Parse(parser, p, stat.st_size, 1) == XML_STATUS_ERROR) {
+               fprintf(stderr,
+                       "%s at line %d, %s\n",
+                       XML_ErrorString(XML_GetErrorCode(parser)),
+                       XML_GetCurrentLineNumber(parser),
+                       filename);
+               return 1;
+       }
+
+       XML_ParserFree(parser);
+
+       SHA1_Init(&sha1);
+       SHA1_Update(&sha1, p, stat.st_size);
+       SHA1_Final(hash, &sha1);
+
+       close(fd);
+
+       snprintf(buf, sizeof buf, "set/%s", sha1_to_hex(hash));
+       if (write_to_file(buf, p, stat.st_size) < 0)
+               return -1;
+       munmap(p, stat.st_size);
+
+       return 0;
+}
+
+int
+razor_context_write(struct razor_context *ctx, const char *filename)
+{
+       return hashtable_write(ctx->global_ht, filename);
+}
+
+void
+razor_context_destroy(struct razor_context *ctx)
+{
+       hashtable_destroy(ctx->global_ht);
+       free(ctx);
+}
+
+static int
+usage(void)
+{
+       printf("usage: razor [ import FILES | lookup <key> ]\n");
+       exit(1);
+}
+
+static const char repo_filename[] = "system.repo";
+
+int
+main(int argc, char *argv[])
+{
+       int i;
+       struct razor_context *ctx;
+       struct stat statbuf;
+
+       if (argc < 3) {
+               usage();
+       } else if (strcmp(argv[1], "import") == 0) {
+               if (stat("set", &statbuf) && mkdir("set", 0777)) {
+                       fprintf(stderr, "could not create directory 'set'\n");
+                       exit(-1);
+               }
+                       
+               ctx = razor_context_create();
+
+               for (i = 2; i < argc; i++) {
+                       if (razor_context_read_file(ctx, argv[i]) < 0) {
+                               fprintf(stderr, "failed to import %s\n",
+                                       argv[i]);
+                               exit(-1);
+                       }
+               }
+
+               printf("number of buckets: %d\n",
+                      ctx->global_ht->bucket_count);
+               printf("bucket allocation: %d\n",
+                      ctx->global_ht->bucket_alloc);
+               printf("pool size: %d\n", ctx->global_ht->pool_size);
+               printf("pool allocation: %d\n", ctx->global_ht->pool_alloc);
+
+               razor_context_write(ctx, repo_filename);
+
+               razor_context_destroy(ctx);
+       } else if (strcmp(argv[1], "lookup") == 0) {
+               ctx = razor_context_create_from_file(repo_filename);
+               printf("%s is %lu\n", argv[2],
+                      hashtable_lookup(ctx->global_ht, argv[2]));
+               razor_context_destroy(ctx);
+       } else {
+               usage();
+       }
+
+       return 0;
+}
diff --git a/sha1.c b/sha1.c
new file mode 100644 (file)
index 0000000..3f06b83
--- /dev/null
+++ b/sha1.c
@@ -0,0 +1,151 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is SHA 180-1 Reference Implementation (Compact version)
+ *
+ * The Initial Developer of the Original Code is Paul Kocher of
+ * Cryptography Research.  Portions created by Paul Kocher are
+ * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ *     Paul Kocher
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL.  If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+#include "sha1.h"
+
+static void shaHashBlock(SHA_CTX *ctx);
+
+void SHA1_Init(SHA_CTX *ctx) {
+  int i;
+
+  ctx->lenW = 0;
+  ctx->sizeHi = ctx->sizeLo = 0;
+
+  /* Initialize H with the magic constants (see FIPS180 for constants)
+   */
+  ctx->H[0] = 0x67452301;
+  ctx->H[1] = 0xefcdab89;
+  ctx->H[2] = 0x98badcfe;
+  ctx->H[3] = 0x10325476;
+  ctx->H[4] = 0xc3d2e1f0;
+
+  for (i = 0; i < 80; i++)
+    ctx->W[i] = 0;
+}
+
+
+void SHA1_Update(SHA_CTX *ctx, const void *_dataIn, int len) {
+  const unsigned char *dataIn = _dataIn;
+  int i;
+
+  /* Read the data into W and process blocks as they get full
+   */
+  for (i = 0; i < len; i++) {
+    ctx->W[ctx->lenW / 4] <<= 8;
+    ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i];
+    if ((++ctx->lenW) % 64 == 0) {
+      shaHashBlock(ctx);
+      ctx->lenW = 0;
+    }
+    ctx->sizeLo += 8;
+    ctx->sizeHi += (ctx->sizeLo < 8);
+  }
+}
+
+
+void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx) {
+  unsigned char pad0x80 = 0x80;
+  unsigned char pad0x00 = 0x00;
+  unsigned char padlen[8];
+  int i;
+
+  /* Pad with a binary 1 (e.g. 0x80), then zeroes, then length
+   */
+  padlen[0] = (unsigned char)((ctx->sizeHi >> 24) & 255);
+  padlen[1] = (unsigned char)((ctx->sizeHi >> 16) & 255);
+  padlen[2] = (unsigned char)((ctx->sizeHi >> 8) & 255);
+  padlen[3] = (unsigned char)((ctx->sizeHi >> 0) & 255);
+  padlen[4] = (unsigned char)((ctx->sizeLo >> 24) & 255);
+  padlen[5] = (unsigned char)((ctx->sizeLo >> 16) & 255);
+  padlen[6] = (unsigned char)((ctx->sizeLo >> 8) & 255);
+  padlen[7] = (unsigned char)((ctx->sizeLo >> 0) & 255);
+  SHA1_Update(ctx, &pad0x80, 1);
+  while (ctx->lenW != 56)
+    SHA1_Update(ctx, &pad0x00, 1);
+  SHA1_Update(ctx, padlen, 8);
+
+  /* Output hash
+   */
+  for (i = 0; i < 20; i++) {
+    hashout[i] = (unsigned char)(ctx->H[i / 4] >> 24);
+    ctx->H[i / 4] <<= 8;
+  }
+
+  /*
+   *  Re-initialize the context (also zeroizes contents)
+   */
+  SHA1_Init(ctx);
+}
+
+
+#define SHA_ROT(X,n) (((X) << (n)) | ((X) >> (32-(n))))
+
+static void shaHashBlock(SHA_CTX *ctx) {
+  int t;
+  unsigned int A,B,C,D,E,TEMP;
+
+  for (t = 16; t <= 79; t++)
+    ctx->W[t] =
+      SHA_ROT(ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], 1);
+
+  A = ctx->H[0];
+  B = ctx->H[1];
+  C = ctx->H[2];
+  D = ctx->H[3];
+  E = ctx->H[4];
+
+  for (t = 0; t <= 19; t++) {
+    TEMP = SHA_ROT(A,5) + (((C^D)&B)^D)     + E + ctx->W[t] + 0x5a827999;
+    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
+  }
+  for (t = 20; t <= 39; t++) {
+    TEMP = SHA_ROT(A,5) + (B^C^D)           + E + ctx->W[t] + 0x6ed9eba1;
+    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
+  }
+  for (t = 40; t <= 59; t++) {
+    TEMP = SHA_ROT(A,5) + ((B&C)|(D&(B|C))) + E + ctx->W[t] + 0x8f1bbcdc;
+    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
+  }
+  for (t = 60; t <= 79; t++) {
+    TEMP = SHA_ROT(A,5) + (B^C^D)           + E + ctx->W[t] + 0xca62c1d6;
+    E = D; D = C; C = SHA_ROT(B, 30); B = A; A = TEMP;
+  }
+
+  ctx->H[0] += A;
+  ctx->H[1] += B;
+  ctx->H[2] += C;
+  ctx->H[3] += D;
+  ctx->H[4] += E;
+}
diff --git a/sha1.h b/sha1.h
new file mode 100644 (file)
index 0000000..16f2d3d
--- /dev/null
+++ b/sha1.h
@@ -0,0 +1,45 @@
+/*
+ * The contents of this file are subject to the Mozilla Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is SHA 180-1 Header File
+ *
+ * The Initial Developer of the Original Code is Paul Kocher of
+ * Cryptography Research.  Portions created by Paul Kocher are
+ * Copyright (C) 1995-9 by Cryptography Research, Inc.  All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ *     Paul Kocher
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License Version 2 or later (the
+ * "GPL"), in which case the provisions of the GPL are applicable
+ * instead of those above.  If you wish to allow use of your
+ * version of this file only under the terms of the GPL and not to
+ * allow others to use your version of this file under the MPL,
+ * indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by
+ * the GPL.  If you do not delete the provisions above, a recipient
+ * may use your version of this file under either the MPL or the
+ * GPL.
+ */
+
+typedef struct {
+  unsigned int H[5];
+  unsigned int W[80];
+  int lenW;
+  unsigned int sizeHi,sizeLo;
+} SHA_CTX;
+
+void SHA1_Init(SHA_CTX *ctx);
+void SHA1_Update(SHA_CTX *ctx, const void *dataIn, int len);
+void SHA1_Final(unsigned char hashout[20], SHA_CTX *ctx);