From: Michael Matz Date: Wed, 19 Mar 2008 22:28:06 +0000 (+0000) Subject: Support new types for MD5 and SHA1 checksums (stored in binary, but with X-Git-Tag: BASE-SuSE-Code-12_1-Branch~799 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=eb7916da1418f09af7504f34dc1e379eb8e6b2ee;p=platform%2Fupstream%2Flibsolv.git Support new types for MD5 and SHA1 checksums (stored in binary, but with support functions to deal with them being strings). Generate them from the susetags parser for the =Cks tags. --- diff --git a/src/knownid.h b/src/knownid.h index 2346fc2..4817451 100644 --- a/src/knownid.h +++ b/src/knownid.h @@ -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"), diff --git a/src/repo_solv.c b/src/repo_solv.c index 11767e8..da3340e 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -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; diff --git a/src/repodata.c b/src/repodata.c index 8ab53fa..456b055 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -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: diff --git a/src/repodata.h b/src/repodata.h index b7c5b61..e581035 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -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); diff --git a/src/repopack.h b/src/repopack.h index fa4e69d..4ce8991 100644 --- a/src/repopack.h +++ b/src/repopack.h @@ -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) diff --git a/tools/dumpsolv.c b/tools/dumpsolv.c index 69b84c7..7398f8d 100644 --- a/tools/dumpsolv.c +++ b/tools/dumpsolv.c @@ -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; diff --git a/tools/repo_susetags.c b/tools/repo_susetags.c index 4a417d7..a6d590b 100644 --- a/tools/repo_susetags.c +++ b/tools/repo_susetags.c @@ -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'): diff --git a/tools/repo_write.c b/tools/repo_write.c index b8249dd..42e2352 100644 --- a/tools/repo_write.c +++ b/tools/repo_write.c @@ -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;