Support new types for MD5 and SHA1 checksums (stored in binary, but with
authorMichael Matz <matz@suse.de>
Wed, 19 Mar 2008 22:28:06 +0000 (22:28 +0000)
committerMichael Matz <matz@suse.de>
Wed, 19 Mar 2008 22:28:06 +0000 (22:28 +0000)
support functions to deal with them being strings).  Generate them from the
susetags parser for the =Cks tags.

src/knownid.h
src/repo_solv.c
src/repodata.c
src/repodata.h
src/repopack.h
tools/dumpsolv.c
tools/repo_susetags.c
tools/repo_write.c

index 2346fc2..4817451 100644 (file)
@@ -72,6 +72,8 @@ KNOWNID(REPOKEY_TYPE_IDARRAY,         "repokey:type:idarray"),
 KNOWNID(REPOKEY_TYPE_REL_IDARRAY,      "repokey:type:relidarray"),
 KNOWNID(REPOKEY_TYPE_DIRSTRARRAY,      "repokey:type:dirstrarray"),
 KNOWNID(REPOKEY_TYPE_DIRNUMNUMARRAY,   "repokey:type:dirnumnumarray"),
+KNOWNID(REPOKEY_TYPE_MD5,              "repokey:type:md5"),
+KNOWNID(REPOKEY_TYPE_SHA1,             "repokey:type:sha1"),
 
 KNOWNID(SOLVABLE_SUMMARY,              "solvable:summary"),
 KNOWNID(SOLVABLE_DESCRIPTION,          "solvable:description"),
@@ -95,6 +97,7 @@ KNOWNID(SOLVABLE_SOURCEARCH,          "solvable:sourcearch"),
 KNOWNID(SOLVABLE_SOURCENAME,           "solvable:sourcename"),
 KNOWNID(SOLVABLE_SOURCEEVR,            "solvable:sourceevr"),
 KNOWNID(SOLVABLE_ISVISIBLE,            "solvable:isvisible"),
+KNOWNID(SOLVABLE_CHECKSUM,             "solvable:checksum"),
 
 KNOWNID(SOLVABLE_PATCHCATEGORY,                "solvable:patchcategory"),
 KNOWNID(SOLVABLE_HEADEREND,            "solvable:headerend"),
index 11767e8..da3340e 100644 (file)
@@ -423,6 +423,20 @@ skip_item(Repodata *data, unsigned type, unsigned numid, unsigned numrel)
        while (read_u8(data) != 0)
          ;
        break;
+      case REPOKEY_TYPE_MD5:
+        {
+         int i;
+         for (i = 0; i < SIZEOF_MD5; i++)
+           read_u8(data);
+         break;
+       }
+      case REPOKEY_TYPE_SHA1:
+        {
+         int i;
+         for (i = 0; i < SIZEOF_SHA1; i++)
+           read_u8(data);
+         break;
+       }
       case REPOKEY_TYPE_IDARRAY:
       case REPOKEY_TYPE_REL_IDARRAY:
        while ((read_u8(data) & 0xc0) != 0)
@@ -1100,7 +1114,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent)
        type = idmap[type];
       else if (parent)
         type = str2id(pool, stringpool_id2str(spool, type), 1);
-      if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_DIRNUMNUMARRAY)
+      if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_SHA1)
        {
          pool_debug(pool, SAT_ERROR, "unsupported data type '%s'\n", id2str(pool, type));
          data.error = SOLV_ERROR_UNSUPPORTED;
index 8ab53fa..456b055 100644 (file)
@@ -1083,6 +1083,97 @@ repoadata_add_array(Repodata *data, Id entry, Id keyname, Id keytype, int entrys
 }
 
 void
+repodata_set_bin_checksum(Repodata *data, Id entry, Id keyname, Id type,
+                     const unsigned char *str)
+{
+  Repokey key;
+  int l;
+  switch (type)
+    {
+      case REPOKEY_TYPE_MD5: l = SIZEOF_MD5; break;
+      case REPOKEY_TYPE_SHA1: l = SIZEOF_SHA1; break;
+      default: return;
+    }
+  key.name = keyname;
+  key.type = type;
+  key.size = 0;
+  key.storage = KEY_STORAGE_INCORE;
+  data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK);
+  memcpy(data->attrdata + data->attrdatalen, str, l);
+  repodata_set(data, entry, &key, data->attrdatalen);
+  data->attrdatalen += l;
+}
+
+static int
+hexstr2bytes(unsigned char *buf, const char *str, int buflen)
+{
+  int i;
+  for (i = 0; i < buflen; i++)
+    {
+#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0')     \
+               : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
+               : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
+               : -1)
+      int v = c2h(*str);
+      str++;
+      if (v < 0)
+       return 0;
+      buf[i] = v;
+      v = c2h(*str);
+      str++;
+      if (v < 0)
+       return 0;
+      buf[i] = (buf[i] << 4) | v;
+#undef c2h
+    }
+  return buflen;
+}
+
+void
+repodata_set_checksum(Repodata *data, Id entry, Id keyname, Id type,
+                     const char *str)
+{
+  int l;
+  switch (type)
+    {
+      case REPOKEY_TYPE_MD5: l = SIZEOF_MD5; break;
+      case REPOKEY_TYPE_SHA1: l = SIZEOF_SHA1; break;
+      default: return;
+    }
+  unsigned char buf[l];
+  if (hexstr2bytes(buf, str, l) != l)
+    {
+      fprintf(stderr, "Invalid hex character in %s\n", str);
+      return;
+    }
+  repodata_set_bin_checksum(data, entry, keyname, type, buf);
+}
+
+const char *
+repodata_chk2str(Repodata *data, Id type, const char *buf)
+{
+  int i, l;
+  char *str, *s;
+  switch (type)
+    {
+      case REPOKEY_TYPE_MD5: l = SIZEOF_MD5; break;
+      case REPOKEY_TYPE_SHA1: l = SIZEOF_SHA1; break;
+      default: return id2str(data->repo->pool, ID_EMPTY);
+    }
+  s = str = pool_alloctmpspace(data->repo->pool, 2*l + 1);
+  for (i = 0; i < l; i++, s+=2)
+    {
+      unsigned char v = buf[i];
+      unsigned char w = v >> 4;
+      s[0] = w >= 10 ? (w-10)+'a' : w + '0';
+      w = v & 15;
+      s[1] = w >= 10 ? (w-10)+'a' : w + '0';
+    }
+  *s = 0;
+  return str;
+}
+
+void
 repodata_add_dirnumnum(Repodata *data, Id entry, Id keyname, Id dir, Id num, Id num2)
 {
 
@@ -1391,6 +1482,12 @@ fprintf(stderr, "schemadata %p\n", data->schemadata);
                case REPOKEY_TYPE_STR:
                  data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1);
                  break;
+               case REPOKEY_TYPE_MD5:
+                 data_addblob(xd, data->attrdata + id, SIZEOF_MD5);
+                 break;
+               case REPOKEY_TYPE_SHA1:
+                 data_addblob(xd, data->attrdata + id, SIZEOF_SHA1);
+                 break;
                case REPOKEY_TYPE_ID:
                case REPOKEY_TYPE_NUM:
                case REPOKEY_TYPE_DIR:
index b7c5b61..e581035 100644 (file)
@@ -19,6 +19,9 @@
 #include "pool.h"
 #include "dirpool.h"
 
+#define SIZEOF_MD5 16
+#define SIZEOF_SHA1 20
+
 struct _Repo;
 struct _Repokey;
 struct _KeyValue;
@@ -133,6 +136,10 @@ void repodata_set_constant(Repodata *data, Id entry, Id keyname, Id constant);
 void repodata_set_constantid(Repodata *data, Id entry, Id keyname, Id id);
 void repodata_set_void(Repodata *data, Id entry, Id keyname);
 void repodata_set_str(Repodata *data, Id entry, Id keyname, const char *str);
+void repodata_set_bin_checksum(Repodata *data, Id entry, Id keyname, Id type,
+                              const unsigned char *buf);
+void repodata_set_checksum(Repodata *data, Id entry, Id keyname, Id type,
+                          const char *str);
 void repodata_add_dirnumnum(Repodata *data, Id entry, Id keyname, Id dir, Id num, Id num2);
 void repodata_add_dirstr(Repodata *data, Id entry, Id keyname, Id dir, const char *str);
 void repodata_add_idarray(Repodata *data, Id entry, Id keyname, Id id);
@@ -145,6 +152,7 @@ void repodata_disable_paging(Repodata *data);
 
 Id repodata_str2dir(Repodata *data, const char *dir, int create);
 const char *repodata_dir2str(Repodata *data, Id did, const char *suf);
+const char *repodata_chk2str(Repodata *data, Id type, const char *buf);
 
 unsigned int repodata_compress_page(unsigned char *, unsigned int, unsigned char *, unsigned int);
 void repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int blobsz);
index fa4e69d..4ce8991 100644 (file)
@@ -84,6 +84,12 @@ data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key)
       return data_read_id(dp, &kv->num);
     case REPOKEY_TYPE_U32:
       return data_read_u32(dp, (unsigned int *)&kv->num);
+    case REPOKEY_TYPE_MD5:
+      kv->str = (const char *)dp;
+      return dp + SIZEOF_MD5;
+    case REPOKEY_TYPE_SHA1:
+      kv->str = (const char *)dp;
+      return dp + SIZEOF_SHA1;
     case REPOKEY_TYPE_IDARRAY:
       return data_read_ideof(dp, &kv->id, &kv->eof);
     case REPOKEY_TYPE_DIRSTRARRAY:
@@ -117,6 +123,10 @@ data_skip(unsigned char *dp, int type)
       return dp + 1;
     case REPOKEY_TYPE_U32:
       return dp + 4;
+    case REPOKEY_TYPE_MD5:
+      return dp + SIZEOF_MD5;
+    case REPOKEY_TYPE_SHA1:
+      return dp + SIZEOF_SHA1;
     case REPOKEY_TYPE_IDARRAY:
     case REPOKEY_TYPE_REL_IDARRAY:
       while ((*dp & 0xc0) != 0)
@@ -176,6 +186,10 @@ data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir)
       return dp + 1;
     case REPOKEY_TYPE_U32:
       return dp + 4;
+    case REPOKEY_TYPE_MD5:
+      return dp + SIZEOF_MD5;
+    case REPOKEY_TYPE_SHA1:
+      return dp + SIZEOF_SHA1;
     case REPOKEY_TYPE_ID:
       dp = data_read_id(dp, &id);
       if (id >= maxid)
index 69b84c7..7398f8d 100644 (file)
@@ -84,6 +84,10 @@ dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV
     case REPOKEY_TYPE_STR:
       printf("%s: %s\n", keyname, kv->str);
       break;
+    case REPOKEY_TYPE_MD5:
+    case REPOKEY_TYPE_SHA1:
+      printf("%s: %s\n", keyname, repodata_chk2str(data, key->type, kv->str));
+      break;
     case REPOKEY_TYPE_VOID:
       printf("%s: (void)\n", keyname);
       break;
index 4a417d7..a6d590b 100644 (file)
@@ -232,6 +232,33 @@ fprintf(stderr, "%s -> %d\n", sp[0], dirid);
   pd->ndirs++;
 }
 
+static void
+set_checksum(Repodata *data, int last_found_pack, Id keyname, char *line)
+{
+  char *sp[3];
+  int l;
+  Id type;
+  if (split(line, sp, 3) != 2)
+    {
+      fprintf(stderr, "Bad source line: %s\n", line);
+      exit(1);
+    }
+  if (!strcasecmp (sp[0], "sha1"))
+    l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
+  else if (!strcasecmp (sp[0], "md5"))
+    l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
+  else
+    {
+      fprintf(stderr, "Unknown checksum type: %s\n", sp[0]);
+      exit(1);
+    }
+  if (strlen(sp[1]) != l)
+    {
+      fprintf(stderr, "Invalid checksum length for %s: %s\n", sp[0], sp[1]);
+      exit(1);
+    }
+  repodata_set_checksum(data, last_found_pack, keyname, type, sp[1]);
+}
 
 /*
  * id3_cmp
@@ -820,6 +847,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, const char *language, int fla
          case CTAG('=', 'I', 'n', 'c'):
            repodata_add_poolstr_array(data, last_found_pack, SOLVABLE_INCLUDES, line + 6);
            break;
+         case CTAG('=', 'C', 'k', 's'):
+           set_checksum(data, last_found_pack, SOLVABLE_CHECKSUM, line + 6);
+           break;
 
          case CTAG('=', 'P', 'a', 't'):
          case CTAG('=', 'P', 'k', 'g'):
index b8249dd..42e2352 100644 (file)
@@ -709,6 +709,12 @@ repo_write_cb_adddata(void *vcbdata, Solvable *s, Repodata *data, Repokey *key,
       case REPOKEY_TYPE_STR:
        data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1);
        break;
+      case REPOKEY_TYPE_MD5:
+       data_addblob(xd, (unsigned char *)kv->str, SIZEOF_MD5);
+       break;
+      case REPOKEY_TYPE_SHA1:
+       data_addblob(xd, (unsigned char *)kv->str, SIZEOF_SHA1);
+       break;
       case REPOKEY_TYPE_U32:
        u32 = kv->num;
        v[0] = u32 >> 24;
@@ -1022,7 +1028,10 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void
 
          repodataused[i] = 1;
          anyrepodataused = 1;
-         if (key->type != REPOKEY_TYPE_STR && key->type != REPOKEY_TYPE_U32)
+         if (key->type != REPOKEY_TYPE_STR
+             && key->type != REPOKEY_TYPE_U32
+             && key->type != REPOKEY_TYPE_MD5
+             && key->type != REPOKEY_TYPE_SHA1)
            idused = 1;
          if (key->type == REPOKEY_TYPE_DIR || key->type == REPOKEY_TYPE_DIRNUMNUMARRAY || key->type == REPOKEY_TYPE_DIRSTRARRAY)
            dirused = 1;