From 3bf73c639f7e8c5825024a889597b8abc1eb64fa Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Fri, 29 Feb 2008 22:01:20 +0000 Subject: [PATCH] - change solv format in an incompatible way, breaking compatibility to all older versions. sorry. * new fastlz from Matz * maxsize/allsize data for faster reading * types are stored as Id to make extensions possible * new type CONSTANTID * new file repopack.h * kill unused vertical/packedsizes flags - switch to pread for paging so that we don't have to mess with file offsets - define more standard IDs - add new solver_calc_installsizechange() function - add repo_add_rpms() function - change location storage method a bit, now VOID means ommited (adapt zypp code, please) - re-added support for source rpm name to susetags parser --- src/fastlz.c | 198 ++++++++++++++----- src/pool.c | 55 +++++- src/pool.h | 81 ++++---- src/pooltypes.h | 3 +- src/repo.c | 48 +++-- src/repo_solv.c | 526 ++++++++++++++++++++++++++------------------------ src/repodata.c | 332 ++++++++++--------------------- src/repodata.h | 4 +- src/repopack.h | 234 ++++++++++++++++++++++ src/solver.c | 39 +++- src/solver.h | 1 + tools/CMakeLists.txt | 4 + tools/dumpsolv.c | 51 +++-- tools/repo_patchxml.c | 19 +- tools/repo_rpmdb.c | 230 ++++++++++++++++++++-- tools/repo_rpmdb.h | 1 + tools/repo_rpmmd.c | 29 ++- tools/repo_susetags.c | 156 +++++---------- tools/repo_write.c | 443 +++++++++++++++++++++++++----------------- tools/tools_util.h | 82 +------- 20 files changed, 1487 insertions(+), 1049 deletions(-) create mode 100644 src/repopack.h diff --git a/src/fastlz.c b/src/fastlz.c index 0dae818..8d3ffdf 100644 --- a/src/fastlz.c +++ b/src/fastlz.c @@ -32,9 +32,13 @@ typedef __uint32_t Ref; d 110lllll <8o> - back ref of length l+2+8, at offset -(o+1) (o < 1 << 8) e 1110llll <8o> <8o> - - back ref of length l+2, at offset -(o+1) (o < 1 << 16) - f 1111llll <8o> <8o> <8l> - - back ref, length l+18 (l < 1<<12), offset -(o+1) (o < 1<<16) + - back ref of length l+3, at offset -(o+1) (o < 1 << 16) + f1 1111llll <8l> <8o> <8o> + - back ref, length l+19 (l < 1<<12), offset -(o+1) (o < 1<<16) + f2 11110lll <8l> <8o> <8o> + - back ref, length l+19 (l < 1<<11), offset -(o+1) (o < 1<<16) + g 11111lll <8l> <8o> <8o> <8o> + - back ref, length l+5 (l < 1<<11), offset -(o+1) (o < 1<<24) Generally for a literal of length L we need L+1 bytes, hence it is better to encode also very short backrefs (2 chars) as backrefs if @@ -50,8 +54,9 @@ typedef __uint32_t Ref; L >= 2, L <= 9, O < 1024 : encode as c L >= 10, L <= 41, O < 256 : encode as d else we have either O >= 1024, or L >= 42: - L >= 2, L <= 17, O < 65536 : encode as e - L >= 18, L <= 4095+18, O < 65536 : encode as f + L < 3 : encode as 1-literal + L >= 3, L <= 18, O < 65536 : encode as e + L >= 19, L <= 4095+18, O < 65536 : encode as f else we have either L >= 4096+18 or O >= 65536. O >= 65536: encode as 1-literal, too bad (with the current block size this can't happen) @@ -66,10 +71,10 @@ compress_buf (const unsigned char *in, unsigned int in_len, unsigned int oo = 0; //out-offset unsigned int io = 0; //in-offset #define HS (65536) - unsigned int htab[HS]; - unsigned int hnext[BLOCK_SIZE]; - memset (htab, 0, sizeof (htab)); - memset (hnext, 0, sizeof (hnext)); + Ref htab[HS]; + Ref hnext[BLOCK_SIZE]; + memset (htab, -1, sizeof (htab)); + memset (hnext, -1, sizeof (hnext)); unsigned int litofs = 0; while (io + 2 < in_len) { @@ -85,7 +90,7 @@ compress_buf (const unsigned char *in, unsigned int in_len, mlen = 0; mofs = 0; - for (tries = 0; tries < 4; tries++) + for (tries = 0; try != -1 && tries < 12; tries++) { if (try < io && in[try] == in[io] && in[try + 1] == in[io + 1]) @@ -96,7 +101,7 @@ compress_buf (const unsigned char *in, unsigned int in_len, } try = hnext[try]; } - for (; tries < 4; tries++) + for (; try != -1 && tries < 12; tries++) { //assert (mlen >= 2); //assert (io + mlen < in_len); @@ -139,20 +144,36 @@ compress_buf (const unsigned char *in, unsigned int in_len, } no_match: try = hnext[try]; - if (io - try - 1 >= 65536) - break; + /*if (io - try - 1 >= 65536) + break;*/ } match_done: if (mlen) { - if (mlen == 2 && (0 || litofs || mofs >= 1024)) + //fprintf (stderr, "%d %d\n", mlen, mofs); + if (mlen == 2 && (litofs || mofs >= 1024)) mlen = 0; + /*else if (mofs >= 65536) + mlen = 0;*/ else if (mofs >= 65536) + { + if (mlen >= 2048 + 5) + mlen = 2047 + 5; + else if (mlen < 5) + mlen = 0; + } + else if (mlen < 3) mlen = 0; - else if (mlen >= 4096 + 18) - mlen = 4095 + 18; - if (mlen && io + 3 < in_len) + /*else if (mlen >= 4096 + 19) + mlen = 4095 + 19;*/ + else if (mlen >= 2048 + 19) + mlen = 2047 + 19; + /* Skip this match if the next character would deliver a better one, + but only do this if we have the chance to really extend the + length (i.e. our current length isn't yet the (conservative) + maximum). */ + if (mlen && mlen < (2048 + 5) && io + 3 < in_len) { unsigned int hval = in[io + 1] | in[io + 2] << 8 | in[io + 3] << 16; @@ -250,24 +271,35 @@ match_done: out[oo++] = 0xc0 | (mlen - 10); out[oo++] = mofs; } - else if (mlen >= 2 && mlen <= 17) + else if (mofs >= 65536) + { + assert (mlen >= 5 && mlen < 2048 + 5); + if (oo + 5 >= out_len) + return 0; + out[oo++] = 0xf8 | ((mlen - 5) >> 8); + out[oo++] = (mlen - 5) & 0xff; + out[oo++] = mofs & 0xff; + out[oo++] = (mofs >> 8) & 0xff; + out[oo++] = mofs >> 16; + } + else if (mlen >= 3 && mlen <= 18) { assert (mofs < 65536); if (oo + 3 >= out_len) return 0; - out[oo++] = 0xe0 | (mlen - 2); - out[oo++] = mofs >> 8; + out[oo++] = 0xe0 | (mlen - 3); out[oo++] = mofs & 0xff; + out[oo++] = mofs >> 8; } else { - assert (mlen >= 18 && mlen <= 4095 + 18 && mofs < 65536); + assert (mlen >= 19 && mlen <= 4095 + 19 && mofs < 65536); if (oo + 4 >= out_len) return 0; - out[oo++] = 0xf0 | ((mlen - 18) >> 8); - out[oo++] = mofs >> 8; + out[oo++] = 0xf0 | ((mlen - 19) >> 8); + out[oo++] = (mlen - 19) & 0xff; out[oo++] = mofs & 0xff; - out[oo++] = (mlen - 18) & 0xff; + out[oo++] = mofs >> 8; } /* Insert the hashes for the compressed run [io..io+mlen-1]. For [io] we have it already done at the start of the loop. @@ -357,27 +389,34 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len, while (in < in_end) { unsigned int first = *in++; - unsigned int o = o; - switch (first >> 5) + unsigned int o; + switch (first >> 4) { - case 0: - case 1: - case 2: - case 3: + default: + /* This default case can't happen, but GCCs VRP is not strong + enough to see this, so make this explicitely not fall to + the end of the switch, so that we don't have to initialize + o above. */ + continue; + case 0: case 1: + case 2: case 3: + case 4: case 5: + case 6: case 7: //a 0LLLLLLL //fprintf (stderr, "lit: 1\n"); *out++ = first; continue; - case 4: + case 8: case 9: //b 100lllll { - unsigned int l = (first & 31) + 1; + unsigned int l = first & 31; //fprintf (stderr, "lit: %d\n", l); - while (l--) + do *out++ = *in++; + while (l--); continue; } - case 5: + case 10: case 11: //c 101oolll <8o> { o = first & (3 << 3); @@ -385,29 +424,47 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len, first = (first & 7) + 2; break; } - case 6: + case 12: case 13: //d 110lllll <8o> { o = *in++; first = (first & 31) + 10; break; } - case 7: - //e 1110llll <8o> <8o> - //f 1111llll <8o> <8o> <8l> + case 14: + // e 1110llll <8o> <8o> { - o = *in++ << 8; - o |= *in++; + o = in[0] | (in[1] << 8); + in += 2; first = first & 31; - if (first >= 16) - first = (((first - 16) << 8) | *in++) + 18; + first += 3; + break; + } + case 15: + //f1 1111llll <8o> <8o> <8l> + //f2 11110lll <8o> <8o> <8l> + // g 11111lll <8o> <8o> <8o> <8l> + { + first = first & 15; + if (first >= 8) + { + first = (((first - 8) << 8) | in[0]) + 5; + o = in[1] | (in[2] << 8) | (in[3] << 16); + in += 4; + } else - first += 2; + { + first = ((first << 8) | in[0]) + 19; + o = in[1] | (in[2] << 8); + in += 3; + } break; } } //fprintf (stderr, "ref: %d @ %d\n", first, o); o++; + o = -o; +#if 0 /* We know that first will not be zero, and this loop structure is better optimizable. */ do @@ -416,6 +473,56 @@ unchecked_decompress_buf (const unsigned char *in, unsigned int in_len, out++; } while (--first); +#else + switch (first) + { + case 18: *out = *(out + o); out++; + case 17: *out = *(out + o); out++; + case 16: *out = *(out + o); out++; + case 15: *out = *(out + o); out++; + case 14: *out = *(out + o); out++; + case 13: *out = *(out + o); out++; + case 12: *out = *(out + o); out++; + case 11: *out = *(out + o); out++; + case 10: *out = *(out + o); out++; + case 9: *out = *(out + o); out++; + case 8: *out = *(out + o); out++; + case 7: *out = *(out + o); out++; + case 6: *out = *(out + o); out++; + case 5: *out = *(out + o); out++; + case 4: *out = *(out + o); out++; + case 3: *out = *(out + o); out++; + case 2: *out = *(out + o); out++; + case 1: *out = *(out + o); out++; + case 0: break; + default: + /* Duff duff :-) */ + switch (first & 15) + { + do + { + case 0: *out = *(out + o); out++; + case 15: *out = *(out + o); out++; + case 14: *out = *(out + o); out++; + case 13: *out = *(out + o); out++; + case 12: *out = *(out + o); out++; + case 11: *out = *(out + o); out++; + case 10: *out = *(out + o); out++; + case 9: *out = *(out + o); out++; + case 8: *out = *(out + o); out++; + case 7: *out = *(out + o); out++; + case 6: *out = *(out + o); out++; + case 5: *out = *(out + o); out++; + case 4: *out = *(out + o); out++; + case 3: *out = *(out + o); out++; + case 2: *out = *(out + o); out++; + case 1: *out = *(out + o); out++; + } + while ((int)(first -= 16) > 0); + } + break; + } +#endif } return out - orig_out; } @@ -503,7 +610,9 @@ benchmark (FILE * from) unsigned int per_loop; unsigned int i, j; clock_t start, end; + float seconds; +#if 0 calib_loop = 1; per_loop = 0; start = clock (); @@ -523,9 +632,10 @@ benchmark (FILE * from) for (j = 0; j < per_loop; j++) dumb_memcpy (outb, inb, in_len); end = clock (); - float seconds = (end - start) / (float) CLOCKS_PER_SEC; + seconds = (end - start) / (float) CLOCKS_PER_SEC; fprintf (stderr, "%.2f seconds == %.2f MB/s\n", seconds, ((long long) in_len * per_loop * 10) / (1024 * 1024 * seconds)); +#endif calib_loop = 1; per_loop = 0; diff --git a/src/pool.c b/src/pool.c index ff10d2b..8dc56c2 100644 --- a/src/pool.c +++ b/src/pool.c @@ -64,6 +64,50 @@ static const char *initpool_data[] = { "repodata:external", "repodata:keys", "repodata:location", + "repokey:type:void", + "repokey:type:constant", + "repokey:type:constantid", + "repokey:type:id", + "repokey:type:num", + "repokey:type:num32", + "repokey:type:dir", + "repokey:type:str", + "repokey:type:idarray", + "repokey:type:relidarray", + "repokey:type:dirstrarray", + "repokey:type:dirnumnumarray", + + "solvable:summary", + "solvable:description", + "solvable:authors", + "solvable:group", + "solvable:keywords", + "solvable:license", + "solvable:buildtime", + + "solvable:eula", + "solvable:messageins", + "solvable:messagedel", + + "solvable:installsize", + "solvable:diskusage", + "solvable:filelist", + + "solvable:installtime", + + "solvable:mediadir", + "solvable:mediafile", + "solvable:medianr", + "solvable:downloadsize", + + "solvable:sourcearch", + "solvable:sourcename", + "solvable:sourceevr", + + "solvable:isvisible", /* from susetags */ + + "solvable:patchcategory", + 0 }; @@ -521,7 +565,7 @@ pool_addrelproviders(Pool *pool, Id d) /* convert to whatprovides id */ #if 0 - POOL_DEBUG(DEBUG_1, "addrelproviders: what provides %s?\n", id2str(pool, name)); + POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: what provides %s?\n", dep2str(pool, name)); #endif if (flags && flags < 8) { @@ -582,7 +626,7 @@ pool_addrelproviders(Pool *pool, Id d) } /* add providers to whatprovides */ #if 0 - POOL_DEBUG(DEBUG_1, "addrelproviders: adding %d packages to %d\n", plist.count, d); + POOL_DEBUG(SAT_DEBUG_STATS, "addrelproviders: adding %d packages to %d\n", plist.count, d); #endif pool->whatprovides_rel[d] = pool_queuetowhatprovides(pool, &plist); queue_free(&plist); @@ -765,9 +809,6 @@ pool_addfileprovides(Pool *pool, Repo *installed) struct searchfiles sf, isf; struct addfileprovides_cbdata cbd; int i; - Id id_filelist; - - id_filelist = str2id(pool, "filelist", 1); memset(&sf, 0, sizeof(sf)); map_init(&sf.seen, pool->ss.nstrings + pool->nrels); @@ -814,7 +855,7 @@ pool_addfileprovides(Pool *pool, Repo *installed) cbd.names = sf.names; cbd.olddata = 0; cbd.dids = sat_realloc2(cbd.dids, sf.nfiles, sizeof(Id)); - pool_search(pool, 0, id_filelist, 0, 0, addfileprovides_cb, &cbd); + pool_search(pool, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd); sat_free(sf.ids); for (i = 0; i < sf.nfiles; i++) { @@ -836,7 +877,7 @@ pool_addfileprovides(Pool *pool, Repo *installed) cbd.names = isf.names; cbd.olddata = 0; cbd.dids = sat_realloc2(cbd.dids, isf.nfiles, sizeof(Id)); - repo_search(installed, 0, id_filelist, 0, 0, addfileprovides_cb, &cbd); + repo_search(installed, 0, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, &cbd); sat_free(isf.ids); for (i = 0; i < isf.nfiles; i++) { diff --git a/src/pool.h b/src/pool.h index e28ce8c..99d1e57 100644 --- a/src/pool.h +++ b/src/pool.h @@ -59,7 +59,51 @@ extern "C" { #define REPODATA_KEYS 27 #define REPODATA_LOCATION 28 -#define ID_NUM_INTERNAL 29 +/* The void type is usable to encode one-valued attributes, they have + no associated data. This is useful to encode values which many solvables + have in common, and whose overall set is relatively limited. A prime + example would be the media number. The actual value is encoded in the + SIZE member of the key structure. Be warned: careless use of this + leads to combinatoric explosion of number of schemas. */ +#define REPOKEY_TYPE_VOID 29 +#define REPOKEY_TYPE_CONSTANT 30 +#define REPOKEY_TYPE_CONSTANTID 31 +#define REPOKEY_TYPE_ID 32 +#define REPOKEY_TYPE_NUM 33 +#define REPOKEY_TYPE_U32 34 +#define REPOKEY_TYPE_DIR 35 +#define REPOKEY_TYPE_STR 36 +#define REPOKEY_TYPE_IDARRAY 37 +#define REPOKEY_TYPE_REL_IDARRAY 38 +#define REPOKEY_TYPE_DIRSTRARRAY 39 +#define REPOKEY_TYPE_DIRNUMNUMARRAY 40 + +#define SOLVABLE_SUMMARY 41 +#define SOLVABLE_DESCRIPTION 42 +#define SOLVABLE_AUTHORS 43 +#define SOLVABLE_GROUP 44 +#define SOLVABLE_KEYWORDS 45 +#define SOLVABLE_LICENSE 46 +#define SOLVABLE_BUILDTIME 47 +#define SOLVABLE_EULA 48 +#define SOLVABLE_MESSAGEINS 49 +#define SOLVABLE_MESSAGEDEL 50 +#define SOLVABLE_INSTALLSIZE 51 +#define SOLVABLE_DISKUSAGE 52 +#define SOLVABLE_FILELIST 53 +#define SOLVABLE_INSTALLTIME 54 +#define SOLVABLE_MEDIADIR 55 +#define SOLVABLE_MEDIAFILE 56 +#define SOLVABLE_MEDIANR 57 +#define SOLVABLE_DOWNLOADSIZE 58 +#define SOLVABLE_SOURCEARCH 59 +#define SOLVABLE_SOURCENAME 60 +#define SOLVABLE_SOURCEEVR 61 +#define SOLVABLE_ISVISIBLE 62 + +#define SOLVABLE_PATCHCATEGORY 63 + +#define ID_NUM_INTERNAL 64 /* well known solvable */ @@ -143,41 +187,6 @@ struct _Pool { #define SAT_DEBUG_JOB (1<<11) #define SAT_DEBUG_SCHUBI (1<<12) -/* The void type is usable to encode one-valued attributes, they have - no associated data. This is useful to encode values which many solvables - have in common, and whose overall set is relatively limited. A prime - example would be the media number. The actual value is encoded in the - SIZE member of the key structure. Be warned: careless use of this - leads to combinatoric explosion of number of schemas. */ - -/* FIXME: Should be 'enum' */ -#define TYPE_VOID 0 -#define TYPE_ID 1 -#define TYPE_IDARRAY 2 -#define TYPE_STR 3 -#define TYPE_U32 4 -#define TYPE_REL_IDARRAY 5 - -#define TYPE_ATTR_INT 6 -#define TYPE_ATTR_CHUNK 7 -#define TYPE_ATTR_STRING 8 -#define TYPE_ATTR_INTLIST 9 -#define TYPE_ATTR_LOCALIDS 10 - -#define TYPE_COUNT_NAMED 11 -#define TYPE_COUNTED 12 - -#define TYPE_IDVALUEARRAY 13 - -#define TYPE_DIR 14 -#define TYPE_DIRNUMNUMARRAY 15 -#define TYPE_DIRSTRARRAY 16 - -#define TYPE_CONSTANT 17 -#define TYPE_NUM 18 - -#define TYPE_ATTR_TYPE_MAX 18 - //----------------------------------------------- diff --git a/src/pooltypes.h b/src/pooltypes.h index 9681f9d..cfe837d 100644 --- a/src/pooltypes.h +++ b/src/pooltypes.h @@ -20,9 +20,8 @@ #define SOLV_VERSION_3 3 #define SOLV_VERSION_4 4 #define SOLV_VERSION_5 5 +#define SOLV_VERSION_6 6 -#define SOLV_FLAG_PACKEDSIZES 1 -#define SOLV_FLAG_VERTICAL 2 #define SOLV_FLAG_PREFIX_POOL 4 struct _Stringpool; diff --git a/src/repo.c b/src/repo.c index dff8840..208d954 100644 --- a/src/repo.c +++ b/src/repo.c @@ -495,14 +495,14 @@ repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValu { switch (key->type) { - case TYPE_ID: - case TYPE_IDARRAY: + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: if (data && data->localpool) kv->str = stringpool_id2str(&data->spool, kv->id); else kv->str = id2str(s->repo->pool, kv->id); break; - case TYPE_STR: + case REPOKEY_TYPE_STR: break; default: return 0; @@ -552,20 +552,20 @@ repo_matchvalue(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValu static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = { - { SOLVABLE_NAME, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_ARCH, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_EVR, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_VENDOR, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_PROVIDES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_OBSOLETES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_CONFLICTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_REQUIRES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_RECOMMENDS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_SUGGESTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_SUPPLEMENTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_ENHANCES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_FRESHENS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { RPM_RPMDBID, TYPE_U32, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_FRESHENS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE }, }; static void @@ -767,7 +767,7 @@ repo_lookup_str(Solvable *s, Id key) continue; for (j = 1; j < data->nkeys; j++) { - if (data->keys[j].name == key && (data->keys[j].type == TYPE_ID || data->keys[j].type == TYPE_STR)) + if (data->keys[j].name == key && (data->keys[j].type == REPOKEY_TYPE_ID || data->keys[j].type == REPOKEY_TYPE_CONSTANTID || data->keys[j].type == REPOKEY_TYPE_STR)) return repodata_lookup_str(data, n - data->start, j); } } @@ -782,6 +782,12 @@ repo_lookup_num(Solvable *s, Id key) Repodata *data; int i, j, n; + if (key == RPM_RPMDBID) + { + if (repo->rpmdbid) + return repo->rpmdbid[(s - pool->solvables) - repo->start]; + return 0; + } n = s - pool->solvables; for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++) { @@ -790,9 +796,9 @@ repo_lookup_num(Solvable *s, Id key) for (j = 1; j < data->nkeys; j++) { if (data->keys[j].name == key - && (data->keys[j].type == TYPE_U32 - || data->keys[j].type == TYPE_NUM - || data->keys[j].type == TYPE_CONSTANT)) + && (data->keys[j].type == REPOKEY_TYPE_U32 + || data->keys[j].type == REPOKEY_TYPE_NUM + || data->keys[j].type == REPOKEY_TYPE_CONSTANT)) { unsigned value; if (repodata_lookup_num(data, n - data->start, j, &value)) diff --git a/src/repo_solv.c b/src/repo_solv.c index 2fafd52..2723465 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -26,6 +26,8 @@ #include "repo_solv.h" #include "util.h" +#include "repopack.h" + #define INTERESTED_START SOLVABLE_NAME #define INTERESTED_END SOLVABLE_FRESHENS @@ -134,6 +136,7 @@ read_id(Repodata *data, Id max) * read array of Ids */ +#if 0 static Id * read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker) { @@ -158,7 +161,7 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker) continue; } x = (x << 6) | (c & 63); - if (x == 0 && c == 0x40) + if (x == 0) { /* marker hack */ if (store == end) @@ -167,6 +170,11 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker) data->error = SOLV_ERROR_OVERFLOW; return 0; } + if (c != 0x40) + { + *store++ = 0; + return store; + } *store++ = marker; /* do not map! */ old = 0; x = 0; @@ -204,6 +212,99 @@ read_rel_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end, Id marker) x = 0; } } +#endif + +static inline unsigned char * +data_read_id_max(unsigned char *dp, Id *ret, Id *map, int max, int *error) +{ + Id x; + dp = data_read_id(dp, &x); + if (max && x >= max) + { + pool_debug(mypool, SAT_ERROR, "data_read_idarray: id too large (%u/%u)\n", x, max); + *error = SOLV_ERROR_ID_RANGE; + x = 0; + } + *ret = map ? map[x] : x; + return dp; +} + +unsigned char * +data_read_idarray(unsigned char *dp, Id **storep, Id *map, int max, int *error) +{ + Id *store = *storep; + unsigned int x = 0; + int c; + + for (;;) + { + c = *dp++; + if ((c & 128) != 0) + { + x = (x << 7) ^ c ^ 128; + continue; + } + x = (x << 6) | (c & 63); + if (max && x >= max) + { + pool_debug(mypool, SAT_ERROR, "data_read_idarray: id too large (%u/%u)\n", x, max); + *error = SOLV_ERROR_ID_RANGE; + break; + } + *store++ = x; + if ((c & 64) == 0) + break; + x = 0; + } + *store++ = 0; + *storep = store; + return dp; +} + +unsigned char * +data_read_rel_idarray(unsigned char *dp, Id **storep, Id *map, int max, int *error, Id marker) +{ + Id *store = *storep; + Id old = 0; + unsigned int x = 0; + int c; + + for (;;) + { + c = *dp++; + if ((c & 128) != 0) + { + x = (x << 7) ^ c ^ 128; + continue; + } + x = (x << 6) | (c & 63); + if (x == 0) + { + if (!(c & 64)) + break; + if (marker) + *store++ = marker; + old = 0; + continue; + } + x = old + (x - 1); + old = x; + if (max && x >= max) + { + pool_debug(mypool, SAT_ERROR, "data_read_rel_idarray: id too large (%u/%u)\n", x, max); + *error = SOLV_ERROR_ID_RANGE; + break; + } + *store++ = map ? map[x] : x; + if (!(c & 64)) + break; + x = 0; + } + *store++ = 0; + *storep = store; + return dp; +} + static Id * read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end) @@ -298,37 +399,36 @@ read_str(Repodata *data, char **inbuf, unsigned *len) } static void -skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel) +skip_item(Repodata *data, unsigned type, unsigned numid, unsigned numrel) { switch (type) { - case TYPE_VOID: - case TYPE_CONSTANT: + case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_CONSTANT: + case REPOKEY_TYPE_CONSTANTID: break; - case TYPE_ID: + case REPOKEY_TYPE_ID: read_id(data, numid + numrel); /* just check Id */ break; - case TYPE_DIR: + case REPOKEY_TYPE_DIR: read_id(data, numid + data->dirpool.ndirs); /* just check Id */ break; - case TYPE_NUM: + case REPOKEY_TYPE_NUM: read_id(data, 0); break; - case TYPE_U32: + case REPOKEY_TYPE_U32: read_u32(data); break; - case TYPE_ATTR_STRING: - case TYPE_STR: + case REPOKEY_TYPE_STR: while (read_u8(data) != 0) ; break; - case TYPE_IDARRAY: - case TYPE_REL_IDARRAY: - case TYPE_ATTR_INTLIST: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_REL_IDARRAY: while ((read_u8(data) & 0xc0) != 0) ; break; - case TYPE_DIRNUMNUMARRAY: + case REPOKEY_TYPE_DIRNUMNUMARRAY: for (;;) { read_id(data, numid + data->dirpool.ndirs); /* just check Id */ @@ -337,7 +437,7 @@ skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel) break; } break; - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_DIRSTRARRAY: for (;;) { Id id = read_id(data, 0); @@ -347,35 +447,6 @@ skip_item (Repodata *data, unsigned type, unsigned numid, unsigned numrel) break; } break; - case TYPE_COUNT_NAMED: - { - unsigned count = read_id(data, 0); - while (count--) - { - read_id(data, numid); /* Name */ - unsigned t = read_id(data, TYPE_ATTR_TYPE_MAX + 1); - skip_item(data, t, numid, numrel); - } - } - break; - case TYPE_COUNTED: - { - unsigned count = read_id(data, 0); - unsigned t = read_id(data, TYPE_ATTR_TYPE_MAX + 1); - while (count--) - skip_item(data, t, numid, numrel); - } - break; - case TYPE_ATTR_CHUNK: - read_id(data, 0); - /* Fallthrough. */ - case TYPE_ATTR_INT: - read_id(data, 0); - break; - case TYPE_ATTR_LOCALIDS: - while (read_id(data, 0) != 0) - ; - break; default: pool_debug(mypool, SAT_ERROR, "unknown type %d\n", type); data->error = SOLV_ERROR_CORRUPT; @@ -413,10 +484,10 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned id = keys[key].name; switch (keys[key].type) { - case TYPE_IDVALUEARRAY: + case REPOKEY_TYPE_IDARRAY: if (id != REPODATA_KEYS) { - skip_item(maindata, TYPE_IDVALUEARRAY, numid, numrel); + skip_item(maindata, REPOKEY_TYPE_IDARRAY, numid, numrel); break; } /* read_idarray writes a terminating 0, that's why the + 1 */ @@ -441,7 +512,7 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned return; } data->keys[i].name = idmap ? idmap[*ide++] : *ide++; - data->keys[i].type = *ide++; + data->keys[i].type = idmap ? idmap[*ide++] : *ide++; data->keys[i].size = 0; data->keys[i].storage = 0; } @@ -449,9 +520,9 @@ parse_repodata(Repodata *maindata, Id *keyp, Repokey *keys, Id *idmap, unsigned if (data->nkeys > 2) qsort(data->keys + 1, data->nkeys - 1, sizeof(data->keys[0]), key_cmp); break; - case TYPE_STR: + case REPOKEY_TYPE_STR: if (id != REPODATA_LOCATION) - skip_item(maindata, TYPE_STR, numid, numrel); + skip_item(maindata, REPOKEY_TYPE_STR, numid, numrel); else { char buf[1024]; @@ -512,6 +583,19 @@ incore_add_id(Repodata *data, Id x) } static void +incore_add_blob(Repodata *data, unsigned char *buf, int len) +{ + if (data->incoredatafree < len) + { + data->incoredata = sat_realloc(data->incoredata, data->incoredatalen + 1024 + len); + data->incoredatafree = 1024 + len; + } + memcpy(data->incoredata + data->incoredatalen, buf, len); + data->incoredatafree -= len; + data->incoredatalen += len; +} + +static void incore_add_u32(Repodata *data, unsigned int x) { unsigned char *dp; @@ -530,6 +614,7 @@ incore_add_u32(Repodata *data, unsigned int x) data->incoredatalen += 4; } +#if 0 static void incore_add_u8(Repodata *data, unsigned int x) { @@ -545,6 +630,7 @@ incore_add_u8(Repodata *data, unsigned int x) data->incoredatafree--; data->incoredatalen++; } +#endif @@ -569,7 +655,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) char *strsp; /* repo string space */ char *sp; /* pointer into string space */ Id *idmap; /* map of repo Ids to pool Ids */ - Id id; + Id id, type; unsigned int hashmask, h; int hh; Id *hashtbl; @@ -587,6 +673,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) Id *schemata, key; int have_xdata; unsigned oldnrepodata; + int maxsize, allsize; + unsigned char *buf, *dp, *dps; + int left; struct _Stringpool *spool; @@ -595,6 +684,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) memset(&data, 0, sizeof(data)); data.repo = repo; data.fp = fp; + data.pagefd = -1; mypool = pool; @@ -606,14 +696,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) solvversion = read_u32(&data); switch (solvversion) { - case SOLV_VERSION_1: - case SOLV_VERSION_2: - case SOLV_VERSION_3: - case SOLV_VERSION_4: - case SOLV_VERSION_5: - /* Version 6 existed only intermittantly. It's equivalent to - version 5. */ - case 6: + case SOLV_VERSION_6: break; default: pool_debug(pool, SAT_ERROR, "unsupported SOLV version\n"); @@ -624,29 +707,18 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) numid = read_u32(&data); numrel = read_u32(&data); - if (solvversion >= SOLV_VERSION_4) - numdir = read_u32(&data); - else - numdir = 0; + numdir = read_u32(&data); numsolv = read_u32(&data); numkeys = read_u32(&data); numschemata = read_u32(&data); numinfo = read_u32(&data); solvflags = read_u32(&data); - if (solvversion < SOLV_VERSION_5) - numschemata++; - if (numdir && numdir < 2) { pool_debug(pool, SAT_ERROR, "bad number of dirs\n"); return SOLV_ERROR_CORRUPT; } - if (numinfo && solvversion < SOLV_VERSION_3) - { - pool_debug(pool, SAT_ERROR, "unsupported SOLV format (has info)\n"); - return SOLV_ERROR_UNSUPPORTED; - } if (parent) { @@ -956,63 +1028,36 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) id = idmap[id]; else if (parent) id = str2id(pool, stringpool_id2str(spool, id), 1); - keys[i].name = id; - keys[i].type = read_id(&data, 0); - keys[i].size = read_id(&data, 0); -#if 0 - fprintf (stderr, "key %d %s %d %d\n", i, id2str(pool,id), keys[i].type, - keys[i].size); -#endif - if (solvversion >= SOLV_VERSION_5) + type = read_id(&data, numid); + if (idmap) + type = idmap[type]; + else if (parent) + type = str2id(pool, stringpool_id2str(spool, type), 1); + if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_DIRNUMNUMARRAY) { - keys[i].storage = read_id(&data, 0); - continue; + pool_debug(pool, SAT_ERROR, "unsupported data type '%s'\n", id2str(pool, type)); + data.error = SOLV_ERROR_UNSUPPORTED; + type = REPOKEY_TYPE_VOID; } - keys[i].storage = KEY_STORAGE_DROPPED; - if (parent) + keys[i].name = id; + keys[i].type = type; + keys[i].size = read_id(&data, keys[i].type == REPOKEY_TYPE_CONSTANTID ? numid + numrel : 0); + keys[i].storage = read_id(&data, 0); + if (id >= SOLVABLE_NAME && id <= RPM_RPMDBID) + keys[i].storage = KEY_STORAGE_SOLVABLE; + else if (keys[i].storage == KEY_STORAGE_SOLVABLE) + keys[i].storage = KEY_STORAGE_INCORE; + if (keys[i].type == REPOKEY_TYPE_CONSTANTID) { - keys[i].storage = KEY_STORAGE_INCORE; - continue; - } - switch (keys[i].type) - { - case TYPE_VOID: - case TYPE_CONSTANT: - case TYPE_STR: - case TYPE_NUM: - case TYPE_DIRNUMNUMARRAY: - keys[i].storage = KEY_STORAGE_INCORE; - break; - case TYPE_ID: - switch(id) - { - case SOLVABLE_NAME: - case SOLVABLE_ARCH: - case SOLVABLE_EVR: - case SOLVABLE_VENDOR: - keys[i].storage = KEY_STORAGE_SOLVABLE; - break; - default: - keys[i].storage = KEY_STORAGE_INCORE; - break; - } - break; - case TYPE_IDARRAY: - case TYPE_REL_IDARRAY: - if (id >= INTERESTED_START && id <= INTERESTED_END) - keys[i].storage = KEY_STORAGE_SOLVABLE; - else - keys[i].storage = KEY_STORAGE_INCORE; - break; - case TYPE_U32: - if (id == RPM_RPMDBID) - keys[i].storage = KEY_STORAGE_SOLVABLE; - else - keys[i].storage = KEY_STORAGE_INCORE; - break; - default: - break; + if (idmap) + keys[i].size = idmap[keys[i].size]; + else if (parent) + keys[i].size = str2id(pool, stringpool_id2str(spool, keys[i].size), 1); } +#if 0 + fprintf(stderr, "key %d %s %s %d %d\n", i, id2str(pool,id), id2str(pool, keys[i].type), + keys[i].size, keys[i].storage); +#endif } have_xdata = parent ? 1 : 0; @@ -1050,6 +1095,11 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) /******* Part 6: Info ***********************************************/ oldnrepodata = repo->nrepodata; + if (numinfo) + { + id = read_id(&data, 0); + id = read_id(&data, 0); + } for (i = 0; i < numinfo; i++) { /* for now we're just interested in data that starts with @@ -1057,11 +1107,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) */ Id *keyp; id = read_id(&data, numschemata); - if (solvversion < SOLV_VERSION_5) - id++; keyp = schemadata + schemata[id]; key = *keyp; - if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == TYPE_VOID) + if (keys[key].name == REPODATA_EXTERNAL && keys[key].type == REPOKEY_TYPE_VOID) { /* external data for some ids */ parse_repodata(&data, keyp, keys, idmap, numid, numrel, repo); @@ -1071,42 +1119,38 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) } - /******* Part 7: packed sizes (optional) ****************************/ - char *exists = 0; - if ((solvflags & SOLV_FLAG_PACKEDSIZES) != 0) - { - exists = sat_malloc (numsolv); - for (i = 0; i < numsolv; i++) - exists[i] = read_id(&data, 0) != 0; - } - - - /******* Part 8: item data *******************************************/ + /******* Part 7: item data *******************************************/ /* calculate idarray size */ size_idarray = 0; for (i = 1; i < numkeys; i++) { id = keys[i].name; - if ((keys[i].type == TYPE_IDARRAY || keys[i].type == TYPE_REL_IDARRAY) + if ((keys[i].type == REPOKEY_TYPE_IDARRAY || keys[i].type == REPOKEY_TYPE_REL_IDARRAY) && id >= INTERESTED_START && id <= INTERESTED_END) size_idarray += keys[i].size; } - /* allocate needed space in repo */ - if (size_idarray) + if (numsolv) { - repo_reserve_ids(repo, 0, size_idarray); - idarraydatap = repo->idarraydata + repo->idarraysize; - repo->idarraysize += size_idarray; - idarraydataend = idarraydatap + size_idarray; - repo->lastoff = 0; + maxsize = read_id(&data, 0); + allsize = read_id(&data, 0); + if (maxsize > allsize) + { + pool_debug(pool, SAT_ERROR, "maxsize %d is greater then allsize %d\n", maxsize, allsize); + data.error = SOLV_ERROR_CORRUPT; + } } else - { - idarraydatap = 0; - idarraydataend = 0; - } + maxsize = allsize = 0; + + /* allocate needed space in repo */ + /* we add maxsize because it is an upper limit for all idarrays */ + repo_reserve_ids(repo, 0, size_idarray + maxsize + 1); + idarraydatap = repo->idarraydata + repo->idarraysize; + repo->idarraysize += size_idarray; + idarraydataend = idarraydatap + size_idarray; + repo->lastoff = 0; /* read solvables */ if (numsolv) @@ -1132,16 +1176,38 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) if (have_xdata) repodata_extend_block(&data, data.start, numsolv); + left = 0; + buf = sat_calloc(maxsize + 4, 1); + dp = buf; for (i = 0; i < numsolv; i++, s++) { Id *keyp; if (data.error) break; - if (exists && !exists[i]) - continue; - id = read_id(&data, numschemata); - if (solvversion < SOLV_VERSION_5) - id++; + + left -= (dp - buf); + if (left < 0) + { + pool_debug(mypool, SAT_ERROR, "buffer overrun\n"); + data.error = SOLV_ERROR_EOF; + break; + } + if (left) + memmove(buf, dp, left); + l = maxsize - left; + if (l > allsize) + l = allsize; + if (l && fread(buf + left, l, 1, data.fp) != 1) + { + pool_debug(mypool, SAT_ERROR, "unexpected EOF\n"); + data.error = SOLV_ERROR_EOF; + break; + } + allsize -= l; + left += l; + dp = buf; + + dp = data_read_id_max(dp, &id, 0, numschemata, &data.error); if (have_xdata) { data.incoreoffset[i] = data.incoredatalen; @@ -1150,6 +1216,9 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) keyp = schemadata + schemata[id]; while ((key = *keyp++) != 0) { + if (data.error) + break; + id = keys[key].name; #if 0 fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, keys[key].storage); @@ -1157,21 +1226,16 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key if (keys[key].storage == KEY_STORAGE_VERTICAL_OFFSET) { /* copy offset/length into incore */ - did = read_id(&data, 0); - incore_add_id(&data, did); - did = read_id(&data, 0); - incore_add_id(&data, did); + dps = dp; + dp = data_skip(dp, REPOKEY_TYPE_ID); + dp = data_skip(dp, REPOKEY_TYPE_ID); + incore_add_blob(&data, dps, dp - dps); continue; } switch (keys[key].type) { - case TYPE_VOID: - case TYPE_CONSTANT: - break; - case TYPE_ID: - did = read_id(&data, numid + numrel); - if (idmap) - did = idmap[did]; + case REPOKEY_TYPE_ID: + dp = data_read_id_max(dp, &did, idmap, numid + numrel, &data.error); if (id == SOLVABLE_NAME) s->name = did; else if (id == SOLVABLE_ARCH) @@ -1186,16 +1250,8 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %s\n", id2str(pool, id), id2str(pool, did)); #endif break; - case TYPE_NUM: - did = read_id(&data, 0); - if (keys[key].storage == KEY_STORAGE_INCORE) - incore_add_id(&data, did); -#if 0 - POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %d\n", id2str(pool, id), did); -#endif - break; - case TYPE_U32: - h = read_u32(&data); + case REPOKEY_TYPE_U32: + dp = data_read_u32(dp, &h); #if 0 POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %u\n", id2str(pool, id), h); #endif @@ -1208,53 +1264,33 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key else if (keys[key].storage == KEY_STORAGE_INCORE) incore_add_u32(&data, h); break; - case TYPE_STR: - if (keys[key].storage == KEY_STORAGE_INCORE) - { - while ((h = read_u8(&data)) != 0) - incore_add_u8(&data, h); - incore_add_u8(&data, 0); - } - else - { - while (read_u8(&data) != 0) - ; - } - break; - case TYPE_IDARRAY: - case TYPE_REL_IDARRAY: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_REL_IDARRAY: if (id < INTERESTED_START || id > INTERESTED_END) { + dps = dp; + dp = data_skip(dp, REPOKEY_TYPE_IDARRAY); + if (keys[key].storage == KEY_STORAGE_INCORE && idmap) + abort(); if (keys[key].storage == KEY_STORAGE_INCORE) - { - if (idmap) - { - abort(); /* implement me! */ - } - else - { - while (((h = read_u8(&data)) & 0xc0) != 0) - incore_add_u8(&data, h); - break; - } - } - else - { - while ((read_u8(&data) & 0xc0) != 0) - ; - break; - } + incore_add_blob(&data, dps, dp - dps); break; } ido = idarraydatap - repo->idarraydata; - if (keys[key].type == TYPE_IDARRAY) - idarraydatap = read_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend); + if (keys[key].type == REPOKEY_TYPE_IDARRAY) + dp = data_read_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error); else if (id == SOLVABLE_REQUIRES) - idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, SOLVABLE_PREREQMARKER); + dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, SOLVABLE_PREREQMARKER); else if (id == SOLVABLE_PROVIDES) - idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, SOLVABLE_FILEMARKER); + dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, SOLVABLE_FILEMARKER); else - idarraydatap = read_rel_idarray(&data, numid + numrel, idmap, idarraydatap, idarraydataend, 0); + dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data.error, 0); + if (idarraydatap > idarraydataend) + { + pool_debug(pool, SAT_ERROR, "idarray overflow\n"); + data.error = SOLV_ERROR_OVERFLOW; + break; + } if (id == SOLVABLE_PROVIDES) s->provides = ido; else if (id == SOLVABLE_OBSOLETES) @@ -1279,52 +1315,29 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key POOL_DEBUG(SAT_DEBUG_STATS," %s\n", dep2str(pool, repo->idarraydata[ido])); #endif break; - case TYPE_DIRNUMNUMARRAY: - for (;;) - { - Id num, num2; - did = read_id(&data, numdir); - num = read_id(&data, 0); - num2 = read_id(&data, 0); - if (keys[key].storage == KEY_STORAGE_INCORE) - { -#if 0 - POOL_DEBUG(SAT_DEBUG_STATS, "%s -> %d %d %d\n", id2str(pool, id), did, num, num2); -#endif - incore_add_id(&data, did); - incore_add_id(&data, num); - incore_add_id(&data, num2); - } - if (!(num2 & 0x40)) - break; - } - break; - case TYPE_DIRSTRARRAY: - for (;;) - { - did = read_id(&data, 0); - if (keys[key].storage == KEY_STORAGE_INCORE) - { - incore_add_id(&data, did); - while ((h = read_u8(&data)) != 0) - incore_add_u8(&data, h); - incore_add_u8(&data, 0); - } - else - { - while (read_u8(&data) != 0) - ; - } - if (!(did & 0x40)) - break; - } - break; default: - skip_item(&data, keys[key].type, numid, numrel); + dps = dp; + dp = data_skip(dp, keys[key].type); + if (keys[key].storage == KEY_STORAGE_INCORE) + incore_add_blob(&data, dps, dp - dps); + break; } } } + /* should shrink idarraydata again */ + + if (!data.error) + { + left -= (dp - buf); + if (left < 0) + { + pool_debug(mypool, SAT_ERROR, "buffer overrun\n"); + data.error = SOLV_ERROR_EOF; + } + } + sat_free(buf); + if (data.error) { /* free solvables */ @@ -1369,7 +1382,7 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key data.fp = 0; } - if (parent) + if (parent && !data.error) { /* we're a store */ sat_free(parent->schemata); @@ -1378,7 +1391,7 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key sat_free(parent->location); *parent = data; } - else if (data.incoredatalen || data.fp) + else if ((data.incoredatalen || data.fp) && !data.error) { /* we got some data, make it available */ repo->repodata = sat_realloc2(repo->repodata, repo->nrepodata + 1, sizeof(data)); @@ -1394,7 +1407,6 @@ fprintf(stderr, "solv %d name %d type %d class %d\n", i, id, keys[key].type, key sat_free(keys); } - sat_free(exists); sat_free(idmap); mypool = 0; return data.error; diff --git a/src/repodata.c b/src/repodata.c index 31d1e67..60fc61f 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -26,6 +26,8 @@ #include "poolid_private.h" #include "util.h" +#include "repopack.h" + extern unsigned int compress_buf (const unsigned char *in, unsigned int in_len, unsigned char *out, unsigned int out_len); extern unsigned int unchecked_decompress_buf (const unsigned char *in, @@ -63,142 +65,8 @@ repodata_free(Repodata *data) sat_free(data->attrdata); sat_free(data->attriddata); - if (data->fp) - fclose(data->fp); -} - -static unsigned char * -data_read_id(unsigned char *dp, Id *idp) -{ - Id x = 0; - unsigned char c; - for (;;) - { - c = *dp++; - if (!(c & 0x80)) - { - *idp = (x << 7) ^ c; - return dp; - } - x = (x << 7) ^ c ^ 128; - } -} - -static unsigned char * -data_read_ideof(unsigned char *dp, Id *idp, int *eof) -{ - Id x = 0; - unsigned char c; - for (;;) - { - c = *dp++; - if (!(c & 0x80)) - { - if (c & 0x40) - { - c ^= 0x40; - *eof = 0; - } - else - *eof = 1; - *idp = (x << 6) ^ c; - return dp; - } - x = (x << 7) ^ c ^ 128; - } -} - -static unsigned char * -data_skip(unsigned char *dp, int type) -{ - unsigned char x; - switch (type) - { - case TYPE_VOID: - case TYPE_CONSTANT: - return dp; - case TYPE_ID: - case TYPE_NUM: - case TYPE_DIR: - while ((*dp & 0x80) != 0) - dp++; - return dp + 1; - case TYPE_IDARRAY: - while ((*dp & 0xc0) != 0) - dp++; - return dp + 1; - case TYPE_STR: - while ((*dp) != 0) - dp++; - return dp + 1; - case TYPE_DIRSTRARRAY: - for (;;) - { - while ((*dp & 0x80) != 0) - dp++; - x = *dp++; - while ((*dp) != 0) - dp++; - dp++; - if (!(x & 0x40)) - return dp; - } - case TYPE_DIRNUMNUMARRAY: - for (;;) - { - while ((*dp & 0x80) != 0) - dp++; - dp++; - while ((*dp & 0x80) != 0) - dp++; - dp++; - while ((*dp & 0x80) != 0) - dp++; - if (!(*dp & 0x40)) - return dp + 1; - dp++; - } - default: - fprintf(stderr, "unknown type in data_skip\n"); - exit(1); - } -} - -static unsigned char * -data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) -{ - kv->eof = 1; - if (!dp) - return 0; - switch (key->type) - { - case TYPE_VOID: - return dp; - case TYPE_CONSTANT: - kv->num = key->size; - return dp; - case TYPE_STR: - kv->str = (const char *)dp; - return dp + strlen(kv->str) + 1; - case TYPE_ID: - return data_read_id(dp, &kv->id); - case TYPE_NUM: - return data_read_id(dp, &kv->num); - case TYPE_IDARRAY: - return data_read_ideof(dp, &kv->id, &kv->eof); - case TYPE_DIR: - return data_read_id(dp, &kv->id); - case TYPE_DIRSTRARRAY: - dp = data_read_ideof(dp, &kv->id, &kv->eof); - kv->str = (const char *)dp; - return dp + strlen(kv->str) + 1; - case TYPE_DIRNUMNUMARRAY: - dp = data_read_id(dp, &kv->id); - dp = data_read_id(dp, &kv->num); - return data_read_ideof(dp, &kv->num2, &kv->eof); - default: - return 0; - } + if (data->pagefd != -1) + close(data->pagefd); } static unsigned char * @@ -213,8 +81,8 @@ forward_to_key(Repodata *data, Id key, Id schemaid, unsigned char *dp) return dp; if (data->keys[k].storage == KEY_STORAGE_VERTICAL_OFFSET) { - dp = data_skip(dp, TYPE_ID); /* skip that offset */ - dp = data_skip(dp, TYPE_ID); /* skip that length */ + dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip that offset */ + dp = data_skip(dp, REPOKEY_TYPE_ID); /* skip that length */ continue; } if (data->keys[k].storage != KEY_STORAGE_INCORE) @@ -354,27 +222,20 @@ load_page_range(Repodata *data, unsigned int pstart, unsigned int pend) #ifdef DEBUG_PAGING fprintf (stderr, "PAGEIN: %d to %d", i, pnum); #endif - /* Not mapped, so read in this page. */ - if (fseek(data->fp, p->file_offset, SEEK_SET) < 0) - { - perror ("mapping fseek"); - exit (1); - } - if (fread(compressed ? buf : dest, in_len, 1, data->fp) != 1) + if (pread(data->pagefd, compressed ? buf : dest, in_len, p->file_offset) != in_len) { - perror ("mapping fread"); - exit (1); + perror ("mapping pread"); + return 0; } if (compressed) { unsigned int out_len; out_len = unchecked_decompress_buf(buf, in_len, dest, BLOB_PAGESIZE); - if (out_len != BLOB_PAGESIZE - && i < data->num_pages - 1) + if (out_len != BLOB_PAGESIZE && i < data->num_pages - 1) { - fprintf (stderr, "can't decompress\n"); - exit (1); + fprintf(stderr, "can't decompress\n"); + return 0; } #ifdef DEBUG_PAGING fprintf (stderr, " (expand %d to %d)", in_len, out_len); @@ -394,7 +255,7 @@ static unsigned char * make_vertical_available(Repodata *data, Repokey *key, Id off, Id len) { unsigned char *dp; - if (key->type == TYPE_VOID) + if (key->type == REPOKEY_TYPE_VOID) return 0; if (off >= data->lastverticaloffset) { @@ -403,7 +264,7 @@ make_vertical_available(Repodata *data, Repokey *key, Id off, Id len) return 0; return data->vincore + off; } - if (!data->fp) + if (data->pagefd == -1) return 0; if (off + len > key->size) return 0; @@ -477,12 +338,14 @@ repodata_lookup_str(Repodata *data, Id entry, Id keyid) dp = get_data(data, key, &dp); if (!dp) return 0; - if (key->type == TYPE_STR) + if (key->type == REPOKEY_TYPE_STR) return (const char *)dp; - if (key->type != TYPE_ID) + if (key->type == REPOKEY_TYPE_CONSTANTID) + return id2str(data->repo->pool, key->size); + if (key->type == REPOKEY_TYPE_ID) + dp = data_read_id(dp, &id); + else return 0; - /* id type, must either use global or local string store*/ - dp = data_read_id(dp, &id); if (data->localpool) return data->spool.stringspace + data->spool.strings[id]; return id2str(data->repo->pool, id); @@ -513,9 +376,9 @@ repodata_lookup_num(Repodata *data, Id entry, Id keyid, unsigned *value) dp = get_data(data, key, &dp); if (!dp) return 0; - if (key->type == TYPE_NUM - || key->type == TYPE_U32 - || key->type == TYPE_CONSTANT) + if (key->type == REPOKEY_TYPE_NUM + || key->type == REPOKEY_TYPE_U32 + || key->type == REPOKEY_TYPE_CONSTANT) { dp = data_fetch(dp, &kv, key); *value = kv.num; @@ -672,14 +535,14 @@ dataiterator_match(Dataiterator *di, KeyValue *kv) { switch (di->key->type) { - case TYPE_ID: - case TYPE_IDARRAY: + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: if (di->data && di->data->localpool) kv->str = stringpool_id2str(&di->data->spool, kv->id); else kv->str = id2str(di->repo->pool, kv->id); break; - case TYPE_STR: + case REPOKEY_TYPE_STR: break; default: return 0; @@ -727,20 +590,20 @@ dataiterator_match(Dataiterator *di, KeyValue *kv) } static Repokey solvablekeys[RPM_RPMDBID - SOLVABLE_NAME + 1] = { - { SOLVABLE_NAME, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_ARCH, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_EVR, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_VENDOR, TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_PROVIDES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_OBSOLETES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_CONFLICTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_REQUIRES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_RECOMMENDS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_SUGGESTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_SUPPLEMENTS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_ENHANCES, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { SOLVABLE_FRESHENS, TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, - { RPM_RPMDBID, TYPE_U32, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_NAME, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_ARCH, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_EVR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_VENDOR, REPOKEY_TYPE_ID, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_PROVIDES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_OBSOLETES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_CONFLICTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_REQUIRES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_RECOMMENDS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_SUGGESTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_SUPPLEMENTS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_ENHANCES, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { SOLVABLE_FRESHENS, REPOKEY_TYPE_IDARRAY, 0, KEY_STORAGE_SOLVABLE }, + { RPM_RPMDBID, REPOKEY_TYPE_U32, 0, KEY_STORAGE_SOLVABLE }, }; int @@ -921,6 +784,7 @@ repodata_init(Repodata *data, Repo *repo, int localpool) data->start = repo->start; data->end = repo->end; data->incoreoffset = sat_extend_resize(0, data->end - data->start, sizeof(Id), REPODATA_BLOCK); + data->pagefd = -1; } /* extend repodata so that it includes solvables p */ @@ -1026,7 +890,7 @@ repodata_set(Repodata *data, Id entry, Repokey *key, Id val) for (keyid = 1; keyid < data->nkeys; keyid++) if (data->keys[keyid].name == key->name && data->keys[keyid].type == key->type) { - if (key->type == TYPE_CONSTANT && key->size != data->keys[keyid].size) + if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != data->keys[keyid].size) continue; break; } @@ -1049,7 +913,7 @@ repodata_set_id(Repodata *data, Id entry, Id keyname, Id id) { Repokey key; key.name = keyname; - key.type = TYPE_ID; + key.type = REPOKEY_TYPE_ID; key.size = 0; key.storage = KEY_STORAGE_INCORE; repodata_set(data, entry, &key, id); @@ -1060,7 +924,7 @@ repodata_set_num(Repodata *data, Id entry, Id keyname, Id num) { Repokey key; key.name = keyname; - key.type = TYPE_NUM; + key.type = REPOKEY_TYPE_NUM; key.size = 0; key.storage = KEY_STORAGE_INCORE; repodata_set(data, entry, &key, num); @@ -1076,7 +940,7 @@ repodata_set_poolstr(Repodata *data, Id entry, Id keyname, const char *str) else id = str2id(data->repo->pool, str, 1); key.name = keyname; - key.type = TYPE_ID; + key.type = REPOKEY_TYPE_ID; key.size = 0; key.storage = KEY_STORAGE_INCORE; repodata_set(data, entry, &key, id); @@ -1087,18 +951,29 @@ repodata_set_constant(Repodata *data, Id entry, Id keyname, Id constant) { Repokey key; key.name = keyname; - key.type = TYPE_CONSTANT; + key.type = REPOKEY_TYPE_CONSTANT; key.size = constant; key.storage = KEY_STORAGE_INCORE; repodata_set(data, entry, &key, 0); } void +repodata_set_constantid(Repodata *data, Id entry, Id keyname, Id id) +{ + Repokey key; + key.name = keyname; + key.type = REPOKEY_TYPE_CONSTANTID; + key.size = id; + key.storage = KEY_STORAGE_INCORE; + repodata_set(data, entry, &key, 0); +} + +void repodata_set_void(Repodata *data, Id entry, Id keyname) { Repokey key; key.name = keyname; - key.type = TYPE_VOID; + key.type = REPOKEY_TYPE_VOID; key.size = 0; key.storage = KEY_STORAGE_INCORE; repodata_set(data, entry, &key, 0); @@ -1112,7 +987,7 @@ repodata_set_str(Repodata *data, Id entry, Id keyname, const char *str) l = strlen(str) + 1; key.name = keyname; - key.type = TYPE_STR; + key.type = REPOKEY_TYPE_STR; key.size = 0; key.storage = KEY_STORAGE_INCORE; data->attrdata = sat_extend(data->attrdata, data->attrdatalen, l, 1, REPODATA_ATTRDATA_BLOCK); @@ -1133,7 +1008,7 @@ fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", entry, dir, num, nu if (data->attrs && data->attrs[entry]) { for (pp = data->attrs[entry]; *pp; pp += 2) - if (data->keys[*pp].name == keyname && data->keys[*pp].type == TYPE_DIRNUMNUMARRAY) + if (data->keys[*pp].name == keyname && data->keys[*pp].type == REPOKEY_TYPE_DIRNUMNUMARRAY) break; if (*pp) { @@ -1162,7 +1037,7 @@ fprintf(stderr, "repodata_add_dirnumnum %d %d %d %d (%d)\n", entry, dir, num, nu } } key.name = keyname; - key.type = TYPE_DIRNUMNUMARRAY; + key.type = REPOKEY_TYPE_DIRNUMNUMARRAY; key.size = 0; key.storage = KEY_STORAGE_INCORE; data->attriddata = sat_extend(data->attriddata, data->attriddatalen, 4, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK); @@ -1192,7 +1067,7 @@ fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", entry, dir, str, data->a if (data->attrs && data->attrs[entry]) { for (pp = data->attrs[entry]; *pp; pp += 2) - if (data->keys[*pp].name == keyname && data->keys[*pp].type == TYPE_DIRSTRARRAY) + if (data->keys[*pp].name == keyname && data->keys[*pp].type == REPOKEY_TYPE_DIRSTRARRAY) break; if (*pp) { @@ -1220,7 +1095,7 @@ fprintf(stderr, "repodata_add_dirstr %d %d %s (%d)\n", entry, dir, str, data->a } } key.name = keyname; - key.type = TYPE_DIRSTRARRAY; + key.type = REPOKEY_TYPE_DIRSTRARRAY; key.size = 0; key.storage = KEY_STORAGE_INCORE; data->attriddata = sat_extend(data->attriddata, data->attriddatalen, 3, sizeof(Id), REPODATA_ATTRIDDATA_BLOCK); @@ -1439,8 +1314,8 @@ fprintf(stderr, "schemadata %p\n", data->schemadata); /* Skip the data associated with this old key. */ if (key->storage == KEY_STORAGE_VERTICAL_OFFSET) { - ndp = data_skip(dp, TYPE_ID); - ndp = data_skip(ndp, TYPE_ID); + ndp = data_skip(dp, REPOKEY_TYPE_ID); + ndp = data_skip(ndp, REPOKEY_TYPE_ID); } else if (key->storage == KEY_STORAGE_INCORE) ndp = data_skip(dp, key->type); @@ -1471,18 +1346,19 @@ fprintf(stderr, "schemadata %p\n", data->schemadata); id = seen[*keyp] - 1; switch (key->type) { - case TYPE_VOID: - case TYPE_CONSTANT: + case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_CONSTANT: + case REPOKEY_TYPE_CONSTANTID: break; - case TYPE_STR: + case REPOKEY_TYPE_STR: data_addblob(xd, data->attrdata + id, strlen((char *)(data->attrdata + id)) + 1); break; - case TYPE_ID: - case TYPE_NUM: - case TYPE_DIR: + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_DIR: data_addid(xd, id); break; - case TYPE_DIRNUMNUMARRAY: + case REPOKEY_TYPE_DIRNUMNUMARRAY: for (ida = data->attriddata + id; *ida; ida += 3) { data_addid(xd, ida[0]); @@ -1490,7 +1366,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata); data_addideof(xd, ida[2], ida[3] ? 0 : 1); } break; - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_DIRSTRARRAY: for (ida = data->attriddata + id; *ida; ida += 2) { data_addideof(xd, ida[0], ida[2] ? 0 : 1); @@ -1587,10 +1463,12 @@ read_u32(FILE *fp) return x; } +#define SOLV_ERROR_EOF 3 +#define SOLV_ERROR_CORRUPT 6 + /* Try to either setup on-demand paging (using FP as backing file), or in case that doesn't work (FP not seekable) slurps in all pages and deactivates paging. */ - void repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int blobsz) { @@ -1600,16 +1478,22 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b unsigned int can_seek; long cur_file_ofs; unsigned char buf[BLOB_PAGESIZE]; + if (pagesz != BLOB_PAGESIZE) { /* We could handle this by slurping in everything. */ - fprintf (stderr, "non matching page size\n"); - exit (1); + data->error = SOLV_ERROR_CORRUPT; + return; } can_seek = 1; if ((cur_file_ofs = ftell(fp)) < 0) can_seek = 0; - clearerr (fp); + clearerr(fp); + if (can_seek) + data->pagefd = dup(fileno(fp)); + if (data->pagefd == -1) + can_seek = 0; + #ifdef DEBUG_PAGING fprintf (stderr, "can %sseek\n", can_seek ? "" : "NOT "); #endif @@ -1643,7 +1527,10 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b fprintf (stderr, "can't seek after we thought we can\n"); /* We can't fall back to non-seeking behaviour as we already read over some data pages without storing them away. */ - exit (1); + data->error = SOLV_ERROR_EOF; + close(data->pagefd); + data->pagefd = -1; + return; } cur_file_ofs += in_len; } @@ -1657,48 +1544,23 @@ repodata_read_or_setup_pages(Repodata *data, unsigned int pagesz, unsigned int b /* We can't seek, so suck everything in. */ if (fread(compressed ? buf : dest, in_len, 1, fp) != 1) { - perror ("fread"); - exit (1); + perror("fread"); + data->error = SOLV_ERROR_EOF; + return; } if (compressed) { out_len = unchecked_decompress_buf(buf, in_len, dest, BLOB_PAGESIZE); - if (out_len != BLOB_PAGESIZE - && i < npages - 1) + if (out_len != BLOB_PAGESIZE && i < npages - 1) { - fprintf (stderr, "can't decompress\n"); - exit (1); + data->error = SOLV_ERROR_CORRUPT; + return; } } } } - - if (can_seek) - { - /* If we are here we were able to seek to all page - positions, so activate paging by copying FP into our structure. - We dup() the file, so that our callers can fclose() it and we - still have it open. But this means that we share file positions - with the input filedesc. So in case our caller reads it after us, - and calls back into us we might change the file position unexpectedly - to him. */ - int fd = dup (fileno (fp)); - if (fd < 0) - { - /* Jeez! What a bloody system, we can't dup() anymore. */ - perror ("dup"); - exit (1); - } - /* XXX we don't close this yet anywhere. */ - data->fp = fdopen (fd, "r"); - if (!data->fp) - { - /* My God! What happened now? */ - perror ("fdopen"); - exit (1); - } - } } + /* vim:cinoptions={.5s,g0,p5,t0,(0,^-0.5s,n-0.5s:tw=78:cindent:sw=4: */ diff --git a/src/repodata.h b/src/repodata.h index f3fafb2..cb81793 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -57,6 +57,7 @@ typedef struct _Repodata { FILE *fp; /* file pointer of solv file */ int error; /* corrupt solv file */ + struct _Repokey *keys; /* keys, first entry is always zero */ unsigned int nkeys; /* length of keys array */ @@ -80,8 +81,8 @@ typedef struct _Repodata { Id *verticaloffset; /* offset for all verticals, nkeys elements */ Id lastverticaloffset; /* end of verticals */ + int pagefd; /* file descriptor of page file */ unsigned char *blob_store; - Attrblobpage *pages; unsigned int num_pages; @@ -127,6 +128,7 @@ void repodata_set_id(Repodata *data, Id entry, Id keyname, Id id); void repodata_set_num(Repodata *data, Id entry, Id keyname, Id num); void repodata_set_poolstr(Repodata *data, Id entry, Id keyname, const char *str); 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_add_dirnumnum(Repodata *data, Id entry, Id keyname, Id dir, Id num, Id num2); diff --git a/src/repopack.h b/src/repopack.h new file mode 100644 index 0000000..fa4e69d --- /dev/null +++ b/src/repopack.h @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2007, Novell Inc. + * + * This program is licensed under the BSD license, read LICENSE.BSD + * for further information + */ + +/* pack/unpack functions for key data */ + +#ifndef SATSOLVER_REPOPACK_H +#define SATSOLVER_REPOPACK_H + +static inline unsigned char * +data_read_id(unsigned char *dp, Id *idp) +{ + Id x = 0; + unsigned char c; + for (;;) + { + c = *dp++; + if (!(c & 0x80)) + { + *idp = (x << 7) ^ c; + return dp; + } + x = (x << 7) ^ c ^ 128; + } +} + +static inline unsigned char * +data_read_ideof(unsigned char *dp, Id *idp, int *eof) +{ + Id x = 0; + unsigned char c; + for (;;) + { + c = *dp++; + if (!(c & 0x80)) + { + if (c & 0x40) + { + c ^= 0x40; + *eof = 0; + } + else + *eof = 1; + *idp = (x << 6) ^ c; + return dp; + } + x = (x << 7) ^ c ^ 128; + } +} + +static inline unsigned char * +data_read_u32(unsigned char *dp, unsigned int *nump) +{ + *nump = (dp[0] << 24) | (dp[1] << 16) | (dp[2] << 8) | dp[3]; + return dp + 4; +} + +static inline unsigned char * +data_fetch(unsigned char *dp, KeyValue *kv, Repokey *key) +{ + kv->eof = 1; + if (!dp) + return 0; + switch (key->type) + { + case REPOKEY_TYPE_VOID: + return dp; + case REPOKEY_TYPE_CONSTANT: + kv->num = key->size; + return dp; + case REPOKEY_TYPE_CONSTANTID: + kv->id = key->size; + return dp; + case REPOKEY_TYPE_STR: + kv->str = (const char *)dp; + return dp + strlen(kv->str) + 1; + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_DIR: + return data_read_id(dp, &kv->id); + case REPOKEY_TYPE_NUM: + return data_read_id(dp, &kv->num); + case REPOKEY_TYPE_U32: + return data_read_u32(dp, (unsigned int *)&kv->num); + case REPOKEY_TYPE_IDARRAY: + return data_read_ideof(dp, &kv->id, &kv->eof); + case REPOKEY_TYPE_DIRSTRARRAY: + dp = data_read_ideof(dp, &kv->id, &kv->eof); + kv->str = (const char *)dp; + return dp + strlen(kv->str) + 1; + case REPOKEY_TYPE_DIRNUMNUMARRAY: + dp = data_read_id(dp, &kv->id); + dp = data_read_id(dp, &kv->num); + return data_read_ideof(dp, &kv->num2, &kv->eof); + default: + return 0; + } +} + +static inline unsigned char * +data_skip(unsigned char *dp, int type) +{ + unsigned char x; + switch (type) + { + case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_CONSTANT: + case REPOKEY_TYPE_CONSTANTID: + return dp; + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_DIR: + while ((*dp & 0x80) != 0) + dp++; + return dp + 1; + case REPOKEY_TYPE_U32: + return dp + 4; + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_REL_IDARRAY: + while ((*dp & 0xc0) != 0) + dp++; + return dp + 1; + case REPOKEY_TYPE_STR: + while ((*dp) != 0) + dp++; + return dp + 1; + case REPOKEY_TYPE_DIRSTRARRAY: + for (;;) + { + while ((*dp & 0x80) != 0) + dp++; + x = *dp++; + while ((*dp) != 0) + dp++; + dp++; + if (!(x & 0x40)) + return dp; + } + case REPOKEY_TYPE_DIRNUMNUMARRAY: + for (;;) + { + while ((*dp & 0x80) != 0) + dp++; + dp++; + while ((*dp & 0x80) != 0) + dp++; + dp++; + while ((*dp & 0x80) != 0) + dp++; + if (!(*dp & 0x40)) + return dp + 1; + dp++; + } + default: + return 0; + } +} + +static inline unsigned char * +data_skip_verify(unsigned char *dp, int type, int maxid, int maxdir) +{ + Id id; + int eof; + + switch (type) + { + case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_CONSTANT: + case REPOKEY_TYPE_CONSTANTID: + return dp; + case REPOKEY_TYPE_NUM: + while ((*dp & 0x80) != 0) + dp++; + return dp + 1; + case REPOKEY_TYPE_U32: + return dp + 4; + case REPOKEY_TYPE_ID: + dp = data_read_id(dp, &id); + if (id >= maxid) + return 0; + return dp; + case REPOKEY_TYPE_DIR: + dp = data_read_id(dp, &id); + if (id >= maxdir) + return 0; + return dp; + case REPOKEY_TYPE_IDARRAY: + for (;;) + { + dp = data_read_ideof(dp, &id, &eof); + if (id >= maxid) + return 0; + if (eof) + return dp; + } + case REPOKEY_TYPE_STR: + while ((*dp) != 0) + dp++; + return dp + 1; + case REPOKEY_TYPE_DIRSTRARRAY: + for (;;) + { + dp = data_read_ideof(dp, &id, &eof); + if (id >= maxdir) + return 0; + while ((*dp) != 0) + dp++; + dp++; + if (eof) + return dp; + } + case REPOKEY_TYPE_DIRNUMNUMARRAY: + for (;;) + { + dp = data_read_id(dp, &id); + if (id >= maxdir) + return 0; + while ((*dp & 0x80) != 0) + dp++; + dp++; + while ((*dp & 0x80) != 0) + dp++; + if (!(*dp & 0x40)) + return dp + 1; + dp++; + } + default: + return 0; + } +} + +#endif /* SATSOLVER_REPOPACK */ diff --git a/src/solver.c b/src/solver.c index 3ffe4ab..977cd28 100644 --- a/src/solver.c +++ b/src/solver.c @@ -3964,7 +3964,6 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps) { Pool *pool = solv->pool; Solvable *s; - Id id_diskusage; char *p; const char *path, *compstr; struct mptree *mptree; @@ -3974,8 +3973,6 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps) Map installmap; struct ducbdata cbd; - id_diskusage = str2id(pool, "diskusage", 1); - cbd.mps = mps; cbd.addsub = 0; cbd.dirmap = 0; @@ -4074,20 +4071,50 @@ solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps) if (!MAPTST(&installmap, i)) continue; s = pool->solvables + i; - repo_search(s->repo, i, id_diskusage, 0, 0, solver_fill_DU_cb, &cbd); + repo_search(s->repo, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); } map_free(&installmap); /* run through erase solvable dudata */ if (solv->installed) { cbd.addsub = -1; - for (i = solv->installed->start; i < solv->installed->end; i++) + FOR_REPO_SOLVABLES(solv->installed, i, s) { if (solv->decisionmap[i] >= 0) continue; - repo_search(solv->installed, i, id_diskusage, 0, 0, solver_fill_DU_cb, &cbd); + repo_search(solv->installed, i, SOLVABLE_DISKUSAGE, 0, 0, solver_fill_DU_cb, &cbd); } } sat_free(cbd.dirmap); sat_free(mptree); } + +int +solver_calc_installsizechange(Solver *solv) +{ + Pool *pool = solv->pool; + int i, change; + Id p; + Solvable *s; + + change = 0; + for (i = 1; i < solv->decisionq.count; i++) + { + Id p = solv->decisionq.elements[i]; + if (p < 0) + continue; + s = pool->solvables + p; + if (!s->repo) + continue; + if (solv->installed && s->repo == solv->installed) + continue; + change += repo_lookup_num(s, SOLVABLE_INSTALLSIZE); + } + if (solv->installed) + { + FOR_REPO_SOLVABLES(solv->installed, p, s) + if (solv->decisionmap[p] < 0) + change -= repo_lookup_num(s, SOLVABLE_INSTALLSIZE); + } + return change; +} diff --git a/src/solver.h b/src/solver.h index 423f4ec..b446d53 100644 --- a/src/solver.h +++ b/src/solver.h @@ -286,6 +286,7 @@ typedef struct _duchanges { } DUChanges; void solver_calc_duchanges(Solver *solv, DUChanges *mps, int nmps); +int solver_calc_installsizechange(Solver *solv); #endif /* SATSOLVER_SOLVER_H */ diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 5dfdb82..5485737 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -10,6 +10,10 @@ SET(rpmdb2solv_REPOS ADD_EXECUTABLE( rpmdb2solv ${rpmdb2solv_REPOS} ) TARGET_LINK_LIBRARIES( rpmdb2solv satsolver ${RPMDB_LIBRARY}) +SET(rpms2solv_REPOS rpms2solv.c repo_rpmdb.h repo_rpmdb.c repo_write.c common_write.c ) +ADD_EXECUTABLE( rpms2solv ${rpms2solv_REPOS} ) +TARGET_LINK_LIBRARIES( rpms2solv satsolver ${RPMDB_LIBRARY}) + SET(rpmmd2solv_REPOS rpmmd2solv.c repo_rpmmd.h repo_rpmmd.c repo_write.c common_write.c ) ADD_EXECUTABLE( rpmmd2solv ${rpmmd2solv_REPOS} ) TARGET_LINK_LIBRARIES( rpmmd2solv satsolver ${EXPAT_LIBRARY}) diff --git a/tools/dumpsolv.c b/tools/dumpsolv.c index 04af673..1d644b6 100644 --- a/tools/dumpsolv.c +++ b/tools/dumpsolv.c @@ -26,9 +26,9 @@ dump_repodata (Repo *repo) for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++) { unsigned int j; - printf("%s has %d keys", data->location ? data->location : "**EMBED**", data->nkeys); + printf("%s has %d keys, %d schemata", data->location ? data->location : "**EMBED**", data->nkeys, data->nschemata); for (j = 1; j < data->nkeys; j++) - printf("\n %s (type %d size %d storage %d)", id2str(repo->pool, data->keys[j].name), data->keys[j].type, data->keys[j].size, data->keys[j].storage); + printf("\n %s (type %s size %d storage %d)", id2str(repo->pool, data->keys[j].name), id2str(repo->pool, data->keys[j].type), data->keys[j].size, data->keys[j].storage); printf("\n"); } printf("\n"); @@ -72,36 +72,39 @@ dump_repoattrs_cb(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyV keyname = id2str(s->repo->pool, key->name); switch(key->type) { - case TYPE_ID: + case REPOKEY_TYPE_ID: if (data && data->localpool) kv->str = stringpool_id2str(&data->spool, kv->id); else kv->str = id2str(s->repo->pool, kv->id); printf("%s: %s\n", keyname, kv->str); break; - case TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + printf("%s: %s\n", keyname, dep2str(s->repo->pool, kv->id)); + break; + case REPOKEY_TYPE_IDARRAY: if (data && data->localpool) printf("%s: %s\n", keyname, stringpool_id2str(&data->spool, kv->id)); else printf("%s: %s\n", keyname, dep2str(s->repo->pool, kv->id)); break; - case TYPE_STR: + case REPOKEY_TYPE_STR: printf("%s: %s\n", keyname, kv->str); break; - case TYPE_VOID: - printf("%s\n", keyname); + case REPOKEY_TYPE_VOID: + printf("%s: (void)\n", keyname); break; - case TYPE_U32: - case TYPE_NUM: - case TYPE_CONSTANT: + case REPOKEY_TYPE_U32: + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_CONSTANT: printf("%s: %d\n", keyname, kv->num); break; - case TYPE_DIRNUMNUMARRAY: + case REPOKEY_TYPE_DIRNUMNUMARRAY: printf("%s: ", keyname); printdir(data, kv->id); printf(" %d %d\n", kv->num, kv->num2); break; - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_DIRSTRARRAY: printf("%s: ", keyname); printdir(data, kv->id); printf("/%s\n", kv->str); @@ -135,19 +138,13 @@ dump_repoattrs(Repo *repo, Id p) void dump_some_attrs(Repo *repo, Solvable *s) { - Id name = str2id (repo->pool, "summary", 0); const char *summary = 0; unsigned int medianr = -1, downloadsize = -1; unsigned int time = -1; - if (name) - summary = repo_lookup_str (s, name); - if ((name = str2id (repo->pool, "medianr", 0))) - medianr = repo_lookup_num (s, name); - if ((name = str2id (repo->pool, "downloadsize", 0))) - downloadsize = repo_lookup_num (s, name); - if ((name = str2id (repo->pool, "time", 0))) - time = repo_lookup_num (s, name); - + summary = repo_lookup_str(s, SOLVABLE_SUMMARY); + medianr = repo_lookup_num(s, SOLVABLE_MEDIANR); + downloadsize = repo_lookup_num (s, SOLVABLE_DOWNLOADSIZE); + time = repo_lookup_num(s, SOLVABLE_BUILDTIME); printf (" XXX %d %d %u %s\n", medianr, downloadsize, time, summary); } #endif @@ -190,15 +187,15 @@ tryme (Repo *repo, Id p, Id keyname, const char *match, int flags) { switch (di.key->type) { - case TYPE_ID: - case TYPE_IDARRAY: + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: if (di.data && di.data->localpool) di.kv.str = stringpool_id2str(&di.data->spool, di.kv.id); else di.kv.str = id2str(repo->pool, di.kv.id); break; - case TYPE_STR: - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_STR: + case REPOKEY_TYPE_DIRSTRARRAY: break; default: di.kv.str = 0; @@ -285,7 +282,7 @@ int main(int argc, char **argv) n++; } #if 0 - tryme(repo, 0, str2id (repo->pool, "medianr", 0), 0, 0); + tryme(repo, 0, SOLVABLE_MEDIANR, 0, 0); printf("\n"); tryme(repo, 0, 0, 0, 0); printf("\n"); diff --git a/tools/repo_patchxml.c b/tools/repo_patchxml.c index f7edd1e..20761c4 100644 --- a/tools/repo_patchxml.c +++ b/tools/repo_patchxml.c @@ -154,12 +154,6 @@ struct parsedata { struct deltarpm delta; }; -/* repo data attribute ids */ -static Id id_timestamp; -static Id id_summary; -static Id id_description; -static Id id_category; - #if 0 static void append_str(struct parsedata *pd, const char *s) @@ -414,7 +408,7 @@ startElement(void *userData, const char *name, const char **atts) { pd->datanum = (pd->solvable - pool->solvables) - pd->repo->start; repodata_extend(pd->data, pd->solvable - pool->solvables); - repodata_set_num(pd->data, pd->datanum, id_timestamp, pd->timestamp); + repodata_set_num(pd->data, pd->datanum, SOLVABLE_BUILDTIME, pd->timestamp); } #if 0 fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables); @@ -622,13 +616,13 @@ endElement(void *userData, const char *name) s->arch = str2id(pool, pd->content, 1); break; case STATE_SUMMARY: - repodata_set_str(pd->data, pd->datanum, id_summary, pd->content); + repodata_set_str(pd->data, pd->datanum, SOLVABLE_SUMMARY, pd->content); break; case STATE_DESCRIPTION: - repodata_set_str(pd->data, pd->datanum, id_description, pd->content); + repodata_set_str(pd->data, pd->datanum, SOLVABLE_DESCRIPTION, pd->content); break; case STATE_CATEGORY: - repodata_set_str(pd->data, pd->datanum, id_category, pd->content); + repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, pd->content); break; case STATE_DELTARPM: #ifdef TESTMM @@ -724,11 +718,6 @@ repo_add_patchxml(Repo *repo, FILE *fp, int flags) pd.repo = repo; pd.data = repo_add_repodata(pd.repo); - id_timestamp = str2id(pool, "patch:timestamp", 1); - id_summary = str2id(pool, "summary", 1); - id_description = str2id(pool, "description", 1); - id_category = str2id(pool, "patch:category", 1); - pd.content = malloc(256); pd.acontent = 256; pd.lcontent = 0; diff --git a/tools/repo_rpmdb.c b/tools/repo_rpmdb.c index 8b50970..3001f5e 100644 --- a/tools/repo_rpmdb.c +++ b/tools/repo_rpmdb.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -28,8 +29,6 @@ #include "util.h" #include "repo_rpmdb.h" -#include "tools_util.h" - #define TAG_NAME 1000 #define TAG_VERSION 1001 @@ -44,10 +43,13 @@ #define TAG_ARCH 1022 #define TAG_FILESIZES 1028 #define TAG_FILEMODES 1030 +#define TAG_SOURCERPM 1044 #define TAG_PROVIDENAME 1047 #define TAG_REQUIREFLAGS 1048 #define TAG_REQUIRENAME 1049 #define TAG_REQUIREVERSION 1050 +#define TAG_NOSOURCE 1051 +#define TAG_NOPATCH 1052 #define TAG_CONFLICTFLAGS 1053 #define TAG_CONFLICTNAME 1054 #define TAG_CONFLICTVERSION 1055 @@ -88,6 +90,23 @@ typedef struct rpmhead { unsigned char data[1]; } RpmHead; +static int +headexists(RpmHead *h, int tag) +{ + unsigned int i; + unsigned char *d, taga[4]; + + d = h->dp - 16; + taga[0] = tag >> 24; + taga[1] = tag >> 16; + taga[2] = tag >> 8; + taga[3] = tag; + for (i = 0; i < h->cnt; i++, d -= 16) + if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0]) + return 1; + return 0; +} + static unsigned int * headint32array(RpmHead *h, int tag, int *cnt) { @@ -484,8 +503,11 @@ adddudata(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmh { if (!fn[i]) continue; - did = repodata_str2dir(repodata, dn[i], 1); - repodata_add_dirnumnum(repodata, entry, id_diskusage, did, fkb[i], fn[i]); + if (!*dn[i] && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)) + did = repodata_str2dir(repodata, "/usr/src", 1); + else + did = repodata_str2dir(repodata, dn[i], 1); + repodata_add_dirnumnum(repodata, entry, SOLVABLE_DISKUSAGE, did, fkb[i], fn[i]); } sat_free(fn); sat_free(fkb); @@ -581,7 +603,7 @@ addfileprovides(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead repodata_extend(repodata, s - pool->solvables); entry = (s - pool->solvables) - repodata->start; did = repodata_str2dir(repodata, dn[di[i]], 1); - repodata_add_dirstr(repodata, entry, id_filelist, did, bn[i]); + repodata_add_dirstr(repodata, entry, SOLVABLE_FILELIST, did, bn[i]); } } if (fn) @@ -607,7 +629,15 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe fprintf(stderr, "package has no name\n"); exit(1); } - s->arch = str2id(pool, headstring(rpmhead, TAG_ARCH), 1); + if (headstring(rpmhead, TAG_SOURCERPM)) + s->arch = str2id(pool, headstring(rpmhead, TAG_ARCH), 1); + else + { + if (headexists(rpmhead, TAG_NOSOURCE) || headexists(rpmhead, TAG_NOPATCH)) + s->arch = ARCH_NOSRC; + else + s->arch = ARCH_SRC; + } if (!s->arch) s->arch = ARCH_NOARCH; evr = headtoevr(rpmhead); @@ -639,7 +669,7 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe entry = (s - pool->solvables) - repodata->start; str = headstring(rpmhead, TAG_SUMMARY); if (str) - repodata_set_str(repodata, entry, id_summary, str); + repodata_set_str(repodata, entry, SOLVABLE_SUMMARY, str); str = headstring(rpmhead, TAG_DESCRIPTION); if (str) { @@ -657,7 +687,7 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe while (l > 0 && str[l - 1] == '\n') str[--l] = 0; if (l) - repodata_set_str(repodata, entry, id_description, str); + repodata_set_str(repodata, entry, SOLVABLE_DESCRIPTION, str); p = aut + 19; aut = str; /* copy over */ while (*p == ' ' || *p == '\n') @@ -677,22 +707,21 @@ rpm2solv(Pool *pool, Repo *repo, Repodata *repodata, Solvable *s, RpmHead *rpmhe aut--; *aut = 0; if (*str) - repodata_set_str(repodata, entry, id_authors, str); + repodata_set_str(repodata, entry, SOLVABLE_AUTHORS, str); free(str); } else if (*str) - repodata_set_str(repodata, entry, id_description, str); + repodata_set_str(repodata, entry, SOLVABLE_DESCRIPTION, str); } str = headstring(rpmhead, TAG_GROUP); if (str) - repodata_set_poolstr(repodata, entry, id_group, str); + repodata_set_poolstr(repodata, entry, SOLVABLE_GROUP, str); u32 = headint32(rpmhead, TAG_BUILDTIME); if (u32) - repodata_set_num(repodata, entry, id_time, u32); + repodata_set_num(repodata, entry, SOLVABLE_BUILDTIME, u32); u32 = headint32(rpmhead, TAG_SIZE); if (u32) - repodata_set_num(repodata, entry, id_installsize, (u32 + 1023) / 1024); - + repodata_set_num(repodata, entry, SOLVABLE_INSTALLSIZE, (u32 + 1023) / 1024); } return 1; } @@ -729,7 +758,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir) abort(); /* FIXME: rpmdbid */ repodata = repo_add_repodata(repo); - init_attr_ids(repo->pool); if (ref && !(ref->nsolvables && ref->rpmdbid)) ref = 0; @@ -1032,9 +1060,173 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir) repodata_internalize(repodata); } -/* XXX: delete me! */ -void rpmdb_dummy() +static inline unsigned int +getu32(unsigned char *dp) +{ + return dp[0] << 24 | dp[1] << 16 | dp[2] << 8 | dp[3]; +} + +static void +add_location(Repodata *data, Solvable *s, const char *location) { - makeevr(0, 0); - split(0, 0, 0); + Pool *pool = s->repo->pool; + const char *name, *n1, *n2; + int l; + Id entry; + + repodata_extend(data, s - pool->solvables); + entry = (s - pool->solvables) - data->start; + + /* skip ./ prefix */ + if (location[0] == '.' && location[1] == '/' && location[2] != '/') + location += 2; + + name = strrchr(location, '/'); + if (!name) + name = location; + else + { + name++; + n2 = id2str(pool, s->arch); + l = strlen(n2); + if (strncmp(location, n2, l) != 0 || location + l + 1 != name) + { + /* too bad, need to store directory */ + char *dir = strdup(location); + dir[name - location - 1] = 0; + repodata_set_str(data, entry, SOLVABLE_MEDIADIR, dir); + free(dir); + } + else + repodata_set_void(data, entry, SOLVABLE_MEDIADIR); + } + n1 = name; + for (n2 = id2str(pool, s->name); *n2; n1++, n2++) + if (*n1 != *n2) + break; + if (*n2 || *n1 != '-') + goto nontrivial; + n1++; + for (n2 = id2str (pool, s->evr); *n2; n1++, n2++) + if (*n1 != *n2) + break; + if (*n2 || *n1 != '.') + goto nontrivial; + n1++; + for (n2 = id2str (pool, s->arch); *n2; n1++, n2++) + if (*n1 != *n2) + break; + if (*n2 || strcmp (n1, ".rpm")) + goto nontrivial; + repodata_set_void(data, entry, SOLVABLE_MEDIAFILE); + return; + +nontrivial: + repodata_set_str(data, entry, SOLVABLE_MEDIAFILE, name); + return; +} + + +void +repo_add_rpms(Repo *repo, const char **rpms, int nrpms) +{ + int i, sigdsize, sigcnt, l; + Pool *pool = repo->pool; + Solvable *s; + Repodata *repodata; + RpmHead *rpmhead = 0; + int rpmheadsize = 0; + FILE *fp; + unsigned char lead[4096]; + + if (nrpms <= 0) + return; + repodata = repo_add_repodata(repo); + for (i = 0; i < nrpms; i++) + { + if ((fp = fopen(rpms[i], "r")) == 0) + { + perror(rpms[i]); + continue; + } + if (fread(lead, 96 + 16, 1, fp) != 1 || getu32(lead) != 0xedabeedb) + { + fprintf(stderr, "%s: not a rpm\n", rpms[i]); + fclose(fp); + continue; + } + if (lead[78] != 0 || lead[79] != 5) + { + fprintf(stderr, "%s: not a V5 header\n", rpms[i]); + fclose(fp); + continue; + } + if (getu32(lead + 96) != 0x8eade801) + { + fprintf(stderr, "%s: bad signature header\n", rpms[i]); + fclose(fp); + continue; + } + sigcnt = getu32(lead + 96 + 8); + sigdsize = getu32(lead + 96 + 12); + if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) + { + fprintf(stderr, "%s: bad signature header\n", rpms[i]); + fclose(fp); + continue; + } + sigdsize += sigcnt * 16; + sigdsize = (sigdsize + 7) & ~7; + while (sigdsize) + { + l = sigdsize > 4096 ? 4096 : sigdsize; + if (fread(lead, l, 1, fp) != 1) + { + fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); + fclose(fp); + continue; + } + sigdsize -= l; + } + if (fread(lead, 16, 1, fp) != 1) + { + fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); + fclose(fp); + continue; + } + if (getu32(lead) != 0x8eade801) + { + fprintf(stderr, "%s: bad header\n", rpms[i]); + fclose(fp); + continue; + } + sigcnt = getu32(lead + 8); + sigdsize = getu32(lead + 12); + if (sigcnt >= 0x4000000 || sigdsize >= 0x40000000) + { + fprintf(stderr, "%s: bad header\n", rpms[i]); + fclose(fp); + continue; + } + l = sigdsize + sigcnt * 16; + if (l > rpmheadsize) + rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + l); + if (fread(rpmhead->data, l, 1, fp) != 1) + { + fprintf(stderr, "%s: unexpected EOF\n", rpms[i]); + fclose(fp); + continue; + } + rpmhead->cnt = sigcnt; + rpmhead->dcnt = sigdsize; + rpmhead->dp = rpmhead->data + rpmhead->cnt * 16; + fclose(fp); + s = pool_id2solvable(pool, repo_add_solvable(repo)); + rpm2solv(pool, repo, repodata, s, rpmhead); + add_location(repodata, s, rpms[i]); + } + if (rpmhead) + sat_free(rpmhead); + if (repodata) + repodata_internalize(repodata); } diff --git a/tools/repo_rpmdb.h b/tools/repo_rpmdb.h index 1ce138d..42e31c0 100644 --- a/tools/repo_rpmdb.h +++ b/tools/repo_rpmdb.h @@ -6,3 +6,4 @@ */ extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir); +extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms); diff --git a/tools/repo_rpmmd.c b/tools/repo_rpmmd.c index e38a42a..ef62056 100644 --- a/tools/repo_rpmmd.c +++ b/tools/repo_rpmmd.c @@ -448,7 +448,7 @@ set_desciption_author(Repodata *data, Id entry, char *str) while (l > 0 && str[l - 1] == '\n') str[--l] = 0; if (l) - repodata_set_str(data, entry, id_description, str); + repodata_set_str(data, entry, SOLVABLE_DESCRIPTION, str); p = aut + 19; aut = str; /* copy over */ while (*p == ' ' || *p == '\n') @@ -468,10 +468,10 @@ set_desciption_author(Repodata *data, Id entry, char *str) aut--; *aut = 0; if (*str) - repodata_set_str(data, entry, id_authors, str); + repodata_set_str(data, entry, SOLVABLE_AUTHORS, str); } else if (*str) - repodata_set_str(data, entry, id_description, str); + repodata_set_str(data, entry, SOLVABLE_DESCRIPTION, str); } static void XMLCALL @@ -612,14 +612,14 @@ startElement(void *userData, const char *name, const char **atts) const char *str2 = strrchr(str, '/'); if (str2) { - char *str3 = strdup (str); + char *str3 = strdup(str); str3[str2 - str] = 0; - repodata_set_poolstr(pd->data, entry, id_mediadir, str3); + repodata_set_poolstr(pd->data, entry, SOLVABLE_MEDIADIR, str3); free(str3); - repodata_set_str(pd->data, entry, id_mediafile, str2 + 1); + repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, str2 + 1); } else - repodata_set_str(pd->data, entry, id_mediafile, str); + repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, str); } break; case STATE_CHECKSUM: @@ -630,7 +630,7 @@ startElement(void *userData, const char *name, const char **atts) unsigned t; str = find_attr("build", atts); if (str && (t = atoi(str)) != 0) - repodata_set_num(pd->data, entry, id_time, t); + repodata_set_num(pd->data, entry, SOLVABLE_BUILDTIME, t); break; } case STATE_SIZE: @@ -638,14 +638,14 @@ startElement(void *userData, const char *name, const char **atts) unsigned k; str = find_attr("installed", atts); if (str && (k = atoi(str)) != 0) - repodata_set_num(pd->data, entry, id_installsize, (k + 1023) / 1024); + repodata_set_num(pd->data, entry, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024); /* XXX the "package" attribute gives the size of the rpm file, i.e. the download size. Except on packman, there it seems to be something else entirely, it has a value near to the other two values, as if the rpm is uncompressed. */ str = find_attr("package", atts); if (str && (k = atoi(str)) != 0) - repodata_set_num(pd->data, entry, id_downloadsize, (k + 1023) / 1024); + repodata_set_num(pd->data, entry, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024); break; } default: @@ -698,10 +698,10 @@ endElement(void *userData, const char *name) s->vendor = str2id(pool, pd->content, 1); break; case STATE_RPM_GROUP: - repodata_set_poolstr(pd->data, entry, id_group, pd->content); + repodata_set_poolstr(pd->data, entry, SOLVABLE_GROUP, pd->content); break; case STATE_RPM_LICENSE: - repodata_set_poolstr(pd->data, entry, id_license, pd->content); + repodata_set_poolstr(pd->data, entry, SOLVABLE_LICENSE, pd->content); break; case STATE_FILE: #if 0 @@ -715,7 +715,7 @@ endElement(void *userData, const char *name) id = 1; p = pd->content; } - repodata_add_dirstr(pd->data, entry, id_filelist, id, p); + repodata_add_dirstr(pd->data, entry, SOLVABLE_FILELIST, id, p); break; // xml store capabilities case STATE_CAP_PROVIDES: @@ -747,7 +747,7 @@ endElement(void *userData, const char *name) break; case STATE_SUMMARY: pd->lang = 0; - repodata_set_str(pd->data, entry, id_summary, pd->content); + repodata_set_str(pd->data, entry, SOLVABLE_SUMMARY, pd->content); break; case STATE_DESCRIPTION: pd->lang = 0; @@ -806,7 +806,6 @@ repo_add_rpmmd(Repo *repo, FILE *fp, int flags) pd.common.repo = repo; pd.data = repo_add_repodata(repo); - init_attr_ids(pool); pd.content = sat_malloc(256); pd.acontent = 256; diff --git a/tools/repo_susetags.c b/tools/repo_susetags.c index 5b29b71..0c5b76d 100644 --- a/tools/repo_susetags.c +++ b/tools/repo_susetags.c @@ -22,8 +22,6 @@ struct parsedata { Repo *repo; Repodata *data; struct parsedata_common common; - char **sources; - int nsources; int last_found_source; char **share_with; int nshare; @@ -105,9 +103,9 @@ add_location(struct parsedata *pd, char *line, Solvable *s, unsigned entry) { /* medianr filename dir don't optimize this one */ - repodata_set_constant(pd->data, entry, id_medianr, atoi(sp[0])); - repodata_set_poolstr(pd->data, entry, id_mediadir, sp[2]); - repodata_set_str(pd->data, entry, id_mediafile, sp[1]); + repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, atoi(sp[0])); + repodata_set_poolstr(pd->data, entry, SOLVABLE_MEDIADIR, sp[2]); + repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, sp[1]); return; } else @@ -137,26 +135,24 @@ add_location(struct parsedata *pd, char *line, Solvable *s, unsigned entry) if (*n2 || strcmp (n1, ".rpm")) goto nontrivial; - repodata_set_constant(pd->data, entry, id_medianr, medianr); - repodata_set_void(pd->data, entry, id_mediafile); + repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, medianr); + repodata_set_void(pd->data, entry, SOLVABLE_MEDIAFILE); return; nontrivial: - repodata_set_constant(pd->data, entry, id_medianr, medianr); - repodata_set_str(pd->data, entry, id_mediafile, sp[1]); + repodata_set_constant(pd->data, entry, SOLVABLE_MEDIANR, medianr); + repodata_set_str(pd->data, entry, SOLVABLE_MEDIAFILE, sp[1]); return; } } -#if 0 - /* * add_source * */ static void -add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry, int first) +add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry) { Repo *repo = s->repo; Pool *pool = repo->pool; @@ -169,68 +165,20 @@ add_source(struct parsedata *pd, char *line, Solvable *s, unsigned entry, int fi } Id name = str2id(pool, sp[0], 1); - Id evr = makeevr(pool, join(pd, sp[1], "-", sp[2])); + Id evr = makeevr(pool, join2(sp[1], "-", sp[2])); Id arch = str2id(pool, sp[3], 1); - - /* Now, if the source of a package only differs in architecture - (src or nosrc), code only that fact. */ - if (s->name == name && s->evr == evr - && (arch == ARCH_SRC || arch == ARCH_NOSRC)) - { - add_attr_void (attr, entry, arch == ARCH_SRC ? id_source : id_nosource); - } - else if (first) - { - if (entry >= pd->nsources) - { - if (pd->nsources) - { - pd->sources = realloc (pd->sources, (entry + 256) * sizeof (*pd->sources)); - memset (pd->sources + pd->nsources, 0, (entry + 256 - pd->nsources) * sizeof (*pd->sources)); - } - else - pd->sources = calloc (entry + 256, sizeof (*pd->sources)); - pd->nsources = entry + 256; - } - /* Uarrr. Unsplit. */ - sp[0][strlen (sp[0])] = ' '; - sp[1][strlen (sp[1])] = ' '; - sp[2][strlen (sp[2])] = ' '; - pd->sources[entry] = strdup (sp[0]); - } + /* XXX: could record a dep here, depends on where we want to store the data */ + if (name == s->name) + repodata_set_void(pd->data, entry, SOLVABLE_SOURCENAME); else - { - unsigned n, nn; - Solvable *found = 0; - /* Otherwise we may find a solvable with exactly matching name, evr, arch - in the repository already. In that case encode its ID. */ - for (n = repo->start, nn = repo->start + pd->last_found_source; - n < repo->end; n++, nn++) - { - if (nn >= repo->end) - nn = repo->start; - found = pool->solvables + nn; - if (found->repo == repo - && found->name == name - && found->evr == evr - && found->arch == arch) - { - pd->last_found_source = nn - repo->start; - break; - } - } - if (n != repo->end) - add_attr_int (attr, entry, id_sourceid, nn - repo->start); - else - { - add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[0], 1)); - add_attr_localids_id (attr, entry, id_source, str2localid (attr, join (pd, sp[1], "-", sp[2]), 1)); - add_attr_localids_id (attr, entry, id_source, str2localid (attr, sp[3], 1)); - } - } + repodata_set_id(pd->data, entry, SOLVABLE_SOURCENAME, name); + if (evr == s->evr) + repodata_set_void(pd->data, entry, SOLVABLE_SOURCEEVR); + else + repodata_set_id(pd->data, entry, SOLVABLE_SOURCEEVR, evr); + repodata_set_constantid(pd->data, entry, SOLVABLE_SOURCEARCH, arch); } -#endif - + /* * add_dirline * add a line with directory information @@ -336,7 +284,7 @@ commit_diskusage (struct parsedata *pd, unsigned entry) for (i = 0; i < pd->ndirs; i++) if (pd->dirs[i][1] || pd->dirs[i][2]) { - repodata_add_dirnumnum(pd->data, entry, id_diskusage, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]); + repodata_add_dirnumnum(pd->data, entry, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]); } pd->ndirs = 0; } @@ -401,7 +349,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) Repodata *data = 0; data = repo_add_repodata(repo); - init_attr_ids(pool); memset(&pd, 0, sizeof(pd)); line = malloc(1024); @@ -627,12 +574,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) s->requires = adddep(pool, &pd, s->requires, line, -SOLVABLE_PREREQMARKER, pd.kind); continue; case CTAG('=', 'P', 'r', 'q'): /* pre-requires / packages required */ - if (pd.kind) { - if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, last_found_pack, id_must, line + 6); - else - s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */ - } + if (pd.kind) + { + if (flags & SUSETAGS_KINDS_SEPARATELY) + repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:must", 1), line + 6); + else + s->requires = adddep(pool, &pd, s->requires, line, 0, 0); /* patterns: a required package */ + } else s->requires = adddep(pool, &pd, s->requires, line, SOLVABLE_PREREQMARKER, 0); /* package: pre-requires */ continue; @@ -659,13 +607,13 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) continue; case CTAG('=', 'P', 'r', 'c'): /* packages recommended */ if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, last_found_pack, id_should, line + 6); + repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:should", 1), line + 6); else s->recommends = adddep(pool, &pd, s->recommends, line, 0, 0); continue; case CTAG('=', 'P', 's', 'g'): /* packages suggested */ if (flags & SUSETAGS_KINDS_SEPARATELY) - repodata_set_poolstr(data, last_found_pack, id_may, line + 6); + repodata_set_poolstr(data, last_found_pack, str2id(pool, "solvable:may", 1), line + 6); else s->suggests = adddep(pool, &pd, s->suggests, line, 0, 0); continue; @@ -706,55 +654,51 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) /* From here it's the attribute tags. */ case CTAG('=', 'G', 'r', 'p'): - repodata_set_poolstr(data, last_found_pack, id_group, line + 6); + repodata_set_poolstr(data, last_found_pack, SOLVABLE_GROUP, line + 6); continue; case CTAG('=', 'L', 'i', 'c'): - repodata_set_poolstr(data, last_found_pack, id_license, line + 6); + repodata_set_poolstr(data, last_found_pack, SOLVABLE_LICENSE, line + 6); continue; case CTAG('=', 'L', 'o', 'c'): add_location(&pd, line + 6, s, last_found_pack); continue; -#if 0 case CTAG('=', 'S', 'r', 'c'): - add_source(&pd, line + 6, s, last_found_pack, 1); + add_source(&pd, line + 6, s, last_found_pack); continue; -#endif case CTAG('=', 'S', 'i', 'z'): if (split (line + 6, sp, 3) == 2) { - repodata_set_num(data, last_found_pack, id_downloadsize, (atoi(sp[0]) + 1023) / 1024); - repodata_set_num(data, last_found_pack, id_installsize, (atoi(sp[1]) + 1023) / 1024); + repodata_set_num(data, last_found_pack, SOLVABLE_DOWNLOADSIZE, (atoi(sp[0]) + 1023) / 1024); + repodata_set_num(data, last_found_pack, SOLVABLE_INSTALLSIZE, (atoi(sp[1]) + 1023) / 1024); } continue; case CTAG('=', 'T', 'i', 'm'): { unsigned int t = atoi (line + 6); if (t) - { - repodata_set_num(data, last_found_pack, id_time, t); - } + repodata_set_num(data, last_found_pack, SOLVABLE_BUILDTIME, t); } continue; case CTAG('=', 'K', 'w', 'd'): - repodata_set_poolstr(data, last_found_pack, id_keywords, line + 6); + repodata_set_poolstr(data, last_found_pack, SOLVABLE_KEYWORDS, line + 6); continue; case CTAG('=', 'A', 'u', 't'): - repodata_set_str(data, last_found_pack, id_authors, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_AUTHORS, line + 6); continue; case CTAG('=', 'S', 'u', 'm'): - repodata_set_str(data, last_found_pack, id_summary, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_SUMMARY, line + 6); continue; case CTAG('=', 'D', 'e', 's'): - repodata_set_str(data, last_found_pack, id_description, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_DESCRIPTION, line + 6); continue; case CTAG('=', 'E', 'u', 'l'): - repodata_set_str(data, last_found_pack, id_eula, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_EULA, line + 6); continue; case CTAG('=', 'I', 'n', 's'): - repodata_set_str(data, last_found_pack, id_messageins, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_MESSAGEINS, line + 6); continue; case CTAG('=', 'D', 'e', 'l'): - repodata_set_str(data, last_found_pack, id_messagedel, line + 6); + repodata_set_str(data, last_found_pack, SOLVABLE_MESSAGEDEL, line + 6); continue; case CTAG('=', 'V', 'i', 's'): { @@ -762,7 +706,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) unsigned k; k = atoi (line + 6); if (k || !strcasecmp (line + 6, "true")) - repodata_set_constant(data, last_found_pack, id_isvisible, 1); + repodata_set_constant(data, last_found_pack, SOLVABLE_ISVISIBLE, 1); } continue; case CTAG('=', 'S', 'h', 'r'): @@ -799,20 +743,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id vendor, int flags) if (s && pd.ndirs) commit_diskusage(&pd, last_found_pack); -#if 0 - if (pd.sources) - { - int i, last_found; - for (i = 0; i < pd.nsources; i++) - if (pd.sources[i]) - { - add_source(&pd, pd.sources[i], pool->solvables + repo->start + i, i, 0); - free (pd.sources[i]); - } - free (pd.sources); - } -#endif - /* Shared attributes * (e.g. multiple binaries built from same source) */ diff --git a/tools/repo_write.c b/tools/repo_write.c index 978d573..6d958da 100644 --- a/tools/repo_write.c +++ b/tools/repo_write.c @@ -165,15 +165,13 @@ write_u8(FILE *fp, unsigned int x) static void write_blob(FILE *fp, void *data, int len) { - if (fwrite(data, len, 1, fp) != 1) + if (len && fwrite(data, len, 1, fp) != 1) { perror("write error blob"); exit(1); } } -static unsigned id_bytes; - /* * Id */ @@ -198,7 +196,17 @@ write_id(FILE *fp, Id x) } } -#if 1 +static inline void +write_id_eof(FILE *fp, Id x, int eof) +{ + if (x >= 64) + x = (x & 63) | ((x & ~63) << 1); + write_id(fp, x | (eof ? 0 : 64)); +} + + + +#if 0 static void write_str(FILE *fp, const char *str) { @@ -249,6 +257,7 @@ cmp_ids (const void *pa, const void *pb) return a - b; } +#if 0 static void write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker) { @@ -337,17 +346,7 @@ write_idarray_sort(FILE *fp, Pool *pool, NeedId *needid, Id *ids, Id marker) if (sids != lids) sat_free(sids); } - -static inline void -write_id_value(FILE *fp, Id id, Id value, int eof) -{ - if (id >= 64) - id = (id & 63) | ((id & ~63) << 1); - write_id(fp, id | 64); - if (value >= 64) - value = (value & 63) | ((value & ~63) << 1); - write_id(fp, value | (eof ? 0 : 64)); -} +#endif struct extdata { @@ -382,7 +381,6 @@ struct cbdata { Id schematacache[256]; Id *solvschemata; - Id *incorelen; struct extdata *extdata; @@ -394,9 +392,9 @@ struct cbdata { #define NEEDED_BLOCK 1023 #define SCHEMATA_BLOCK 31 #define SCHEMATADATA_BLOCK 255 -#define EXTDATA_BLOCK 1023 +#define EXTDATA_BLOCK 4095 -static void +static inline void data_addid(struct extdata *xd, Id x) { unsigned char *dp; @@ -417,7 +415,7 @@ data_addid(struct extdata *xd, Id x) xd->len = dp - xd->buf; } -static void +static inline void data_addideof(struct extdata *xd, Id x, int eof) { if (x >= 64) @@ -426,6 +424,95 @@ data_addideof(struct extdata *xd, Id x, int eof) } static void +data_addidarray_sort(struct extdata *xd, Pool *pool, NeedId *needid, Id *ids, Id marker) +{ + int len, i; + Id lids[64], *sids; + + if (!ids) + return; + if (!*ids) + { + data_addid(xd, 0); + return; + } + for (len = 0; len < 64 && ids[len]; len++) + { + Id id = ids[len]; + if (needid) + id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + lids[len] = id; + } + if (ids[len]) + { + for (i = len + 1; ids[i]; i++) + ; + sids = sat_malloc2(i, sizeof(Id)); + memcpy(sids, lids, 64 * sizeof(Id)); + for (; ids[len]; len++) + { + Id id = ids[len]; + if (needid) + id = needid[ISRELDEP(id) ? RELOFF(id) : id].need; + sids[len] = id; + } + } + else + sids = lids; + + /* That bloody solvable:prereqmarker needs to stay in position :-( */ + if (needid) + marker = needid[marker].need; + for (i = 0; i < len; i++) + if (sids[i] == marker) + break; + if (i > 1) + qsort(sids, i, sizeof (Id), cmp_ids); + if ((len - i) > 2) + qsort(sids + i + 1, len - i - 1, sizeof(Id), cmp_ids); + + Id id, old = 0; + + /* The differencing above produces many runs of ones and twos. I tried + fairly elaborate schemes to RLE those, but they give only very mediocre + improvements in compression, as coding the escapes costs quite some + space. Even if they are coded only as bits in IDs. The best improvement + was about 2.7% for the whole .solv file. It's probably better to + invest some complexity into sharing idarrays, than RLEing. */ + for (i = 0; i < len - 1; i++) + { + id = sids[i]; + /* Ugly PREREQ handling. A "difference" of 0 is the prereq marker, + hence all real differences are offsetted by 1. Otherwise we would + have to handle negative differences, which would cost code space for + the encoding of the sign. We loose the exact mapping of prereq here, + but we know the result, so we can recover from that in the reader. */ + if (id == marker) + id = old = 0; + else + { + id = id - old + 1; + old = sids[i]; + } + /* XXX If difference is zero we have multiple equal elements, + we might want to skip writing them out. */ + if (id >= 64) + id = (id & 63) | ((id & ~63) << 1); + data_addid(xd, id | 64); + } + id = sids[i]; + if (id == marker) + id = 0; + else + id = id - old + 1; + if (id >= 64) + id = (id & 63) | ((id & ~63) << 1); + data_addid(xd, id); + if (sids != lids) + sat_free(sids); +} + +static inline void data_addblob(struct extdata *xd, unsigned char *blob, int len) { xd->buf = sat_extend(xd->buf, xd->len, len, 1, EXTDATA_BLOCK); @@ -433,6 +520,17 @@ data_addblob(struct extdata *xd, unsigned char *blob, int len) xd->len += len; } +static inline void +data_addu32(struct extdata *xd, unsigned int num) +{ + unsigned char d[4]; + d[0] = num >> 24; + d[1] = num >> 16; + d[2] = num >> 8; + d[3] = num; + data_addblob(xd, d, 4); +} + static Id addschema(struct cbdata *cbdata, Id *schema) { @@ -539,20 +637,21 @@ repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, K rm = cbdata->keymap[cbdata->keymapstart[data - data->repo->repodata] + (key - data->keys)]; if (!rm) return SEARCH_NEXT_KEY; /* we do not want this one */ + /* record key in schema */ if (cbdata->sp == cbdata->schema || cbdata->sp[-1] != rm) *cbdata->sp++ = rm; switch(key->type) { - case TYPE_ID: - case TYPE_IDARRAY: + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: id = kv->id; if (!ISRELDEP(id) && cbdata->ownspool && id > 1) id = putinownpool(cbdata, data->localpool ? &data->spool : &repo->pool->ss, id); incneedid(repo->pool, id, cbdata->needid); break; - case TYPE_DIR: - case TYPE_DIRNUMNUMARRAY: - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_DIR: + case REPOKEY_TYPE_DIRNUMNUMARRAY: + case REPOKEY_TYPE_DIRSTRARRAY: id = kv->id; if (cbdata->owndirpool) putinowndirpool(cbdata, data, &data->dirpool, id); @@ -566,7 +665,7 @@ repo_write_cb_needed(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, K } static int -repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) +repo_write_cb_adddata(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) { struct cbdata *cbdata = vcbdata; int rm; @@ -589,27 +688,28 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke xd = cbdata->extdata + 0; /* incore buffer */ switch(key->type) { - case TYPE_VOID: - case TYPE_CONSTANT: + case REPOKEY_TYPE_VOID: + case REPOKEY_TYPE_CONSTANT: + case REPOKEY_TYPE_CONSTANTID: break; - case TYPE_ID: + case REPOKEY_TYPE_ID: id = kv->id; if (!ISRELDEP(id) && cbdata->ownspool && id > 1) id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); id = cbdata->needid[id].need; data_addid(xd, id); break; - case TYPE_IDARRAY: + case REPOKEY_TYPE_IDARRAY: id = kv->id; if (cbdata->ownspool && id > 1) id = putinownpool(cbdata, data->localpool ? &data->spool : &data->repo->pool->ss, id); id = cbdata->needid[id].need; data_addideof(xd, id, kv->eof); break; - case TYPE_STR: + case REPOKEY_TYPE_STR: data_addblob(xd, (unsigned char *)kv->str, strlen(kv->str) + 1); break; - case TYPE_U32: + case REPOKEY_TYPE_U32: u32 = kv->num; v[0] = u32 >> 24; v[1] = u32 >> 16; @@ -617,17 +717,17 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke v[3] = u32; data_addblob(xd, v, 4); break; - case TYPE_NUM: + case REPOKEY_TYPE_NUM: data_addid(xd, kv->num); break; - case TYPE_DIR: + case REPOKEY_TYPE_DIR: id = kv->id; if (cbdata->owndirpool) id = putinowndirpool(cbdata, data, &data->dirpool, id); id = cbdata->dirused[id]; data_addid(xd, id); break; - case TYPE_DIRNUMNUMARRAY: + case REPOKEY_TYPE_DIRNUMNUMARRAY: id = kv->id; if (cbdata->owndirpool) id = putinowndirpool(cbdata, data, &data->dirpool, id); @@ -636,7 +736,7 @@ repo_write_cb_sizes(void *vcbdata, Solvable *s, Repodata *data, Repokey *key, Ke data_addid(xd, kv->num); data_addideof(xd, kv->num2, kv->eof); break; - case TYPE_DIRSTRARRAY: + case REPOKEY_TYPE_DIRSTRARRAY: id = kv->id; if (cbdata->owndirpool) id = putinowndirpool(cbdata, data, &data->dirpool, id); @@ -674,7 +774,6 @@ traverse_dirs(Dirpool *dp, Id *dirmap, Id n, Id dir, Id *used) continue; if (sib == 1 && parent == 1) continue; /* already did that one above */ -assert (sib < dp->ndirs); dirmap[n++] = sib; } lastn = n; @@ -737,15 +836,14 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void Id *dirmap; int ndirmap; Id *keyused; - int ext0len; unsigned char *repodataused; + int anyrepodataused; struct cbdata cbdata; int needrels; Repokey *key; int poolusage, dirpoolusage, idused, dirused; int reloff; - unsigned char *incoredata; Repodata *data; Stringpool ownspool, *spool; @@ -755,6 +853,12 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void Id repodataschema = 0; Id repodataschema_internal = 0; + struct extdata *xd; + + int entrysize; + Id maxentrysize; + Id type_constantid = 0; + /* If we're given a fileinfo structure, but have no subfiles, then we're writing a subfile and our callers wants info about it. */ if (fileinfo && nsubfiles == 0) @@ -787,11 +891,11 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void key = cbdata.mykeys + i; key->name = i; if (i < SOLVABLE_PROVIDES) - key->type = TYPE_ID; + key->type = REPOKEY_TYPE_ID; else if (i < RPM_RPMDBID) - key->type = TYPE_REL_IDARRAY; + key->type = REPOKEY_TYPE_REL_IDARRAY; else - key->type = TYPE_U32; + key->type = REPOKEY_TYPE_U32; key->size = 0; key->storage = KEY_STORAGE_SOLVABLE; if (keyfilter) @@ -802,7 +906,7 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void key->storage = KEY_STORAGE_SOLVABLE; } poolusage = 1; - if (key->type == TYPE_IDARRAY || key->type == TYPE_REL_IDARRAY) + if (key->type == REPOKEY_TYPE_IDARRAY || key->type == REPOKEY_TYPE_REL_IDARRAY) needrels = 1; cbdata.keymap[i] = i; } @@ -813,21 +917,21 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void { key = cbdata.mykeys + cbdata.nmykeys; key->name = REPODATA_EXTERNAL; - key->type = TYPE_VOID; + key->type = REPOKEY_TYPE_VOID; key->size = 0; key->storage = KEY_STORAGE_SOLVABLE; cbdata.keymap[key->name] = key - cbdata.mykeys; key++; key->name = REPODATA_KEYS; - key->type = TYPE_IDVALUEARRAY; + key->type = REPOKEY_TYPE_IDARRAY; key->size = 0; key->storage = KEY_STORAGE_SOLVABLE; cbdata.keymap[key->name] = key - cbdata.mykeys; key++; key->name = REPODATA_LOCATION; - key->type = TYPE_STR; + key->type = REPOKEY_TYPE_STR; key->size = 0; key->storage = KEY_STORAGE_SOLVABLE; cbdata.keymap[key->name] = key - cbdata.mykeys; @@ -856,22 +960,20 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void { if (key->name == cbdata.mykeys[k].name && key->type == cbdata.mykeys[k].type) { - if (key->type == TYPE_CONSTANT && key->size != cbdata.mykeys[k].size) + if ((key->type == REPOKEY_TYPE_CONSTANT || key->type == REPOKEY_TYPE_CONSTANTID) && key->size != cbdata.mykeys[k].size) continue; break; } } if (k < cbdata.nmykeys) - { - repodataused[i] = 1; - cbdata.keymap[n] = k; - } + cbdata.keymap[n] = k; else { + /* found a new key! */ cbdata.mykeys[cbdata.nmykeys] = *key; key = cbdata.mykeys + cbdata.nmykeys; key->storage = KEY_STORAGE_INCORE; - if (key->type != TYPE_CONSTANT) + if (key->type != REPOKEY_TYPE_CONSTANT && key->type != REPOKEY_TYPE_CONSTANTID) key->size = 0; if (keyfilter) { @@ -907,9 +1009,10 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void } repodataused[i] = 1; - if (key->type != TYPE_STR && key->type != TYPE_U32) + anyrepodataused = 1; + if (key->type != REPOKEY_TYPE_STR && key->type != REPOKEY_TYPE_U32) idused = 1; - if (key->type == TYPE_DIR || key->type == TYPE_DIRNUMNUMARRAY || key->type == TYPE_DIRSTRARRAY) + if (key->type == REPOKEY_TYPE_DIR || key->type == REPOKEY_TYPE_DIRNUMNUMARRAY || key->type == REPOKEY_TYPE_DIRSTRARRAY) dirused = 1; } if (idused) @@ -966,18 +1069,6 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void poolusage = 1; spool = &repo->pool->ss; } - - if (poolusage > 1) - { - /* convert global keys to new pool names */ - for (i = 0; i < cbdata.nmykeys; i++) - { - if (cbdata.mykeys[i].storage == KEY_STORAGE_DROPPED) - continue; - cbdata.mykeys[i].name = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[i].name), 1); - } - } - if (dirpoolusage == 3) { dirpool = &owndirpool; @@ -994,7 +1085,7 @@ fprintf(stderr, "poolusage: %d\n", poolusage); fprintf(stderr, "dirpoolusage: %d\n", dirpoolusage); fprintf(stderr, "nmykeys: %d\n", cbdata.nmykeys); for (i = 1; i < cbdata.nmykeys; i++) - fprintf(stderr, " %2d: %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].storage); + fprintf(stderr, " %2d: %d %d %d %d\n", i, cbdata.mykeys[i].name, cbdata.mykeys[i].type, cbdata.mykeys[i].size, cbdata.mykeys[i].storage); #endif /********************************************************************/ @@ -1097,14 +1188,17 @@ for (i = 1; i < cbdata.nmykeys; i++) } cbdata.sp = sp; - for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) + if (anyrepodataused) { - if (!repodataused[j]) - continue; - if (i < data->start || i >= data->end) - continue; - repodata_search(data, i - data->start, 0, repo_write_cb_needed, &cbdata); - needid = cbdata.needid; + for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) + { + if (!repodataused[j]) + continue; + if (i < data->start || i >= data->end) + continue; + repodata_search(data, i - data->start, 0, repo_write_cb_needed, &cbdata); + needid = cbdata.needid; + } } *cbdata.sp = 0; cbdata.solvschemata[n] = addschema(&cbdata, cbdata.schema); @@ -1139,7 +1233,10 @@ for (i = 1; i < cbdata.nmykeys; i++) if (2 * fileinfo[i].nkeys > cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size) cbdata.mykeys[cbdata.keymap[REPODATA_KEYS]].size = 2 * fileinfo[i].nkeys; for (j = 1; j < fileinfo[i].nkeys; j++) - needid[fileinfo[i].keys[j].name].need++; + { + needid[fileinfo[i].keys[j].type].need++; + needid[fileinfo[i].keys[j].name].need++; + } #if 0 fprintf (stderr, " %d nkeys: %d:", i, fileinfo[i].nkeys); for (j = 1; j < fileinfo[i].nkeys; j++) @@ -1156,7 +1253,7 @@ for (i = 1; i < cbdata.nmykeys; i++) /********************************************************************/ - /* remove unused keys, also increment needid for key names */ + /* remove unused keys, convert ids to local ids and increment their needid */ keyused = sat_calloc(cbdata.nmykeys, sizeof(Id)); for (i = 0; i < cbdata.myschemadatalen; i++) keyused[cbdata.myschemadata[i]] = 1; @@ -1168,7 +1265,21 @@ for (i = 1; i < cbdata.nmykeys; i++) keyused[i] = n; if (i != n) cbdata.mykeys[n] = cbdata.mykeys[i]; + if (cbdata.mykeys[n].type == REPOKEY_TYPE_CONSTANTID) + { + if (!type_constantid) + type_constantid = poolusage > 1 ? stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1) : REPOKEY_TYPE_CONSTANTID; + if (poolusage > 1) + cbdata.mykeys[n].size = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].size), 1); + needid[cbdata.mykeys[n].size].need++; + } + if (poolusage > 1) + { + cbdata.mykeys[n].name = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].name), 1); + cbdata.mykeys[n].type = stringpool_str2id(spool, id2str(repo->pool, cbdata.mykeys[n].type), 1); + } needid[cbdata.mykeys[n].name].need++; + needid[cbdata.mykeys[n].type].need++; n++; } cbdata.nmykeys = n; @@ -1282,32 +1393,58 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); /********************************************************************/ cbdata.extdata = sat_calloc(cbdata.nmykeys, sizeof(struct extdata)); - cbdata.incorelen = sat_calloc(repo->nsolvables, sizeof(Id)); - /* calculate incore/vertical data and sizes */ - ext0len = 0; - - for (i = 1; i < cbdata.nmykeys; i++) - if (cbdata.mykeys[i].storage != KEY_STORAGE_SOLVABLE) - break; - if (i < cbdata.nmykeys) + + xd = cbdata.extdata; + maxentrysize = 0; + for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) { - /* we need incore/vertical data */ - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) + if (s->repo != repo) + continue; + entrysize = xd->len; + data_addid(xd, cbdata.solvschemata[n]); + if (cbdata.keymap[SOLVABLE_NAME]) + data_addid(xd, needid[s->name].need); + if (cbdata.keymap[SOLVABLE_ARCH]) + data_addid(xd, needid[s->arch].need); + if (cbdata.keymap[SOLVABLE_EVR]) + data_addid(xd, needid[s->evr].need); + if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) + data_addid(xd, needid[s->vendor].need); + if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); + if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->obsoletes, 0); + if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->conflicts, 0); + if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); + if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->recommends, 0); + if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->suggests, 0); + if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->supplements, 0); + if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->enhances, 0); + if (s->freshens && cbdata.keymap[SOLVABLE_FRESHENS]) + data_addidarray_sort(xd, pool, needid, idarraydata + s->freshens, 0); + if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) + data_addu32(xd, repo->rpmdbid[i - repo->start]); + if (anyrepodataused) { - if (s->repo != repo) - continue; for (j = 0, data = repo->repodata; j < repo->nrepodata; j++, data++) { if (!repodataused[j]) continue; if (i < data->start || i >= data->end) continue; - repodata_search(data, i - data->start, 0, repo_write_cb_sizes, &cbdata); + repodata_search(data, i - data->start, 0, repo_write_cb_adddata, &cbdata); } - cbdata.incorelen[n] = cbdata.extdata[0].len - ext0len; - ext0len = cbdata.extdata[0].len; - n++; } + entrysize = xd->len - entrysize; + if (entrysize > maxentrysize) + maxentrysize = entrysize; + n++; } /********************************************************************/ @@ -1316,7 +1453,7 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); /* write file header */ write_u32(fp, 'S' << 24 | 'O' << 16 | 'L' << 8 | 'V'); - write_u32(fp, SOLV_VERSION_5); + write_u32(fp, SOLV_VERSION_6); /* write counts */ write_u32(fp, nstrings); @@ -1328,9 +1465,6 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); write_u32(fp, nsubfiles); /* info blocks. */ solv_flags = 0; solv_flags |= SOLV_FLAG_PREFIX_POOL; -#if 0 - solv_flags |= SOLV_FLAG_VERTICAL; -#endif write_u32(fp, solv_flags); /* Build the prefix-encoding of the string pool. We need to know @@ -1406,9 +1540,14 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); for (i = 1; i < cbdata.nmykeys; i++) { write_id(fp, needid[cbdata.mykeys[i].name].need); - write_id(fp, cbdata.mykeys[i].type); + write_id(fp, needid[cbdata.mykeys[i].type].need); if (cbdata.mykeys[i].storage != KEY_STORAGE_VERTICAL_OFFSET) - write_id(fp, cbdata.mykeys[i].size); + { + if (cbdata.mykeys[i].type == type_constantid) + write_id(fp, needid[cbdata.mykeys[i].size].need); + else + write_id(fp, cbdata.mykeys[i].size); + } else write_id(fp, cbdata.extdata[i].len); write_id(fp, cbdata.mykeys[i].storage); @@ -1429,90 +1568,51 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); /* * write info block */ - for (i = 0; i < nsubfiles; i++) + if (nsubfiles) { - int j; + struct extdata xd; + xd.buf = 0; + xd.len = 0; + int max = 0; + int cur; - if (fileinfo[i].location) - write_id(fp, repodataschema); - else - write_id(fp, repodataschema_internal); - /* keys + location, write idarray */ - for (j = 1; j < fileinfo[i].nkeys; j++) - { - - Id id = needid[fileinfo[i].keys[j].name].need; -#if 0 - fprintf (stderr, "writing %d(%s) %d\n", id, - id2str(pool, needid[id].map), - fileinfo[i].keys[j].type); -#endif - write_id_value(fp, id, fileinfo[i].keys[j].type, j == fileinfo[i].nkeys - 1); - } - if (fileinfo[i].location) - write_str(fp, fileinfo[i].location); - } + for (i = 0; i < nsubfiles; i++) + { + int j; + cur = xd.len; + if (fileinfo[i].location) + data_addid(&xd, repodataschema); + else + data_addid(&xd, repodataschema_internal); + /* key,type array + location, write idarray */ + for (j = 1; j < fileinfo[i].nkeys; j++) + { + data_addideof(&xd, needid[fileinfo[i].keys[j].name].need, 0); + data_addideof(&xd, needid[fileinfo[i].keys[j].type].need, j == fileinfo[i].nkeys - 1); + } + if (fileinfo[i].location) + data_addblob(&xd, (unsigned char *)fileinfo[i].location, strlen(fileinfo[i].location) + 1); + cur = xd.len - cur; + if (cur > max) + max = cur; + } + write_id(fp, max); + write_id(fp, xd.len); + write_blob(fp, xd.buf, xd.len); + } /********************************************************************/ /* - * write Solvables + * write Solvable data */ - incoredata = cbdata.extdata[0].buf; - for (i = repo->start, s = pool->solvables + i, n = 0; i < repo->end; i++, s++) + if (repo->nsolvables) { - if (s->repo != repo) - continue; - id_bytes = 0; - /* keep in sync with schema generation! */ - write_id(fp, cbdata.solvschemata[n]); -#if 0 -{ - Id *sp; - fprintf(stderr, "write solvable %d (%s): \n", n, id2str(pool, s->name)); - sp = cbdata.myschemadata + cbdata.myschemata[cbdata.solvschemata[n]]; - for (; *sp; sp++) - fprintf(stderr, " (%d,%d)", cbdata.mykeys[*sp].name, cbdata.mykeys[*sp].type); - fprintf(stderr, "\n"); -} -#endif - if (cbdata.keymap[SOLVABLE_NAME]) - write_id(fp, needid[s->name].need); - if (cbdata.keymap[SOLVABLE_ARCH]) - write_id(fp, needid[s->arch].need); - if (cbdata.keymap[SOLVABLE_EVR]) - write_id(fp, needid[s->evr].need); - if (s->vendor && cbdata.keymap[SOLVABLE_VENDOR]) - write_id(fp, needid[s->vendor].need); - if (s->provides && cbdata.keymap[SOLVABLE_PROVIDES]) - write_idarray_sort(fp, pool, needid, idarraydata + s->provides, SOLVABLE_FILEMARKER); - if (s->obsoletes && cbdata.keymap[SOLVABLE_OBSOLETES]) - write_idarray_sort(fp, pool, needid, idarraydata + s->obsoletes, 0); - if (s->conflicts && cbdata.keymap[SOLVABLE_CONFLICTS]) - write_idarray_sort(fp, pool, needid, idarraydata + s->conflicts, 0); - if (s->requires && cbdata.keymap[SOLVABLE_REQUIRES]) - write_idarray_sort(fp, pool, needid, idarraydata + s->requires, SOLVABLE_PREREQMARKER); - if (s->recommends && cbdata.keymap[SOLVABLE_RECOMMENDS]) - write_idarray_sort(fp, pool, needid, idarraydata + s->recommends, 0); - if (s->suggests && cbdata.keymap[SOLVABLE_SUGGESTS]) - write_idarray_sort(fp, pool, needid, idarraydata + s->suggests, 0); - if (s->supplements && cbdata.keymap[SOLVABLE_SUPPLEMENTS]) - write_idarray_sort(fp, pool, needid, idarraydata + s->supplements, 0); - if (s->enhances && cbdata.keymap[SOLVABLE_ENHANCES]) - write_idarray_sort(fp, pool, needid, idarraydata + s->enhances, 0); - if (s->freshens && cbdata.keymap[SOLVABLE_FRESHENS]) - write_idarray_sort(fp, pool, needid, idarraydata + s->freshens, 0); - if (repo->rpmdbid && cbdata.keymap[RPM_RPMDBID]) - write_u32(fp, repo->rpmdbid[i - repo->start]),id_bytes+=4; - if (cbdata.incorelen[n]) - { - write_blob(fp, incoredata, cbdata.incorelen[n]); - incoredata += cbdata.incorelen[n]; - id_bytes += cbdata.incorelen[n]; - } - n++; + write_id(fp, maxentrysize); + write_id(fp, cbdata.extdata[0].len); + write_blob(fp, cbdata.extdata[0].buf, cbdata.extdata[0].len); } sat_free(cbdata.extdata[0].buf); @@ -1594,6 +1694,5 @@ fprintf(stderr, "dir %d used %d\n", i, cbdata.dirused ? cbdata.dirused[i] : 1); sat_free(cbdata.keymap); sat_free(cbdata.keymapstart); sat_free(cbdata.dirused); - sat_free(cbdata.incorelen); sat_free(repodataused); } diff --git a/tools/tools_util.h b/tools/tools_util.h index a7f30e2..34878ba 100644 --- a/tools/tools_util.h +++ b/tools/tools_util.h @@ -24,7 +24,7 @@ struct parsedata_common { Repo *repo; }; -static Id +static inline Id makeevr(Pool *pool, char *s) { if (!strncmp(s, "0:", 2) && s[2]) @@ -134,88 +134,12 @@ join2(const char *s1, const char *s2, const char *s3) // return pd->tmp; // } -/* key Ids */ - -/* packages */ -static Id id_authors; -static Id id_description; -static Id id_diskusage; -static Id id_eula; -static Id id_group; -static Id id_installsize; -static Id id_keywords; -static Id id_license; -static Id id_messagedel; -static Id id_messageins; -static Id id_mediadir; -static Id id_mediafile; -static Id id_medianr; -static Id id_nosource; -static Id id_source; -static Id id_sourceid; -static Id id_time; -static Id id_filelist; - -/* resobject */ -static Id id_summary; -static Id id_description; -// static Id id_insnotify; -// static Id id_delnotify; -static Id id_size; -static Id id_downloadsize; -static Id id_installtime; -static Id id_installonly; - -static Id id_isvisible; - -/* experimental */ -static Id id_must; -static Id id_should; -static Id id_may; - -static void init_attr_ids(Pool *pool) -{ - id_size = str2id(pool, "size", 1);; - id_downloadsize = str2id(pool, "downloadsize", 1);; - id_installtime = str2id(pool, "installtime", 1);; - id_installonly = str2id(pool, "installonly", 1);; - id_summary = str2id(pool, "summary", 1); - - // package - id_authors = str2id(pool, "authors", 1); - id_summary = str2id(pool, "summary", 1); - id_description = str2id(pool, "description", 1); - id_diskusage = str2id(pool, "diskusage", 1); - id_downloadsize = str2id(pool, "downloadsize", 1); - id_eula = str2id(pool, "eula", 1); - id_group = str2id(pool, "group", 1); - id_installsize = str2id(pool, "installsize", 1); - id_keywords = str2id(pool, "keywords", 1); - id_license = str2id(pool, "license", 1); - id_messagedel = str2id(pool, "messagedel", 1); - id_messageins = str2id(pool, "messageins", 1); - id_mediadir = str2id(pool, "mediadir", 1); - id_mediafile = str2id(pool, "mediafile", 1); - id_medianr = str2id(pool, "medianr", 1); - id_nosource = str2id(pool, "nosource", 1); - id_source = str2id(pool, "source", 1); - id_sourceid = str2id(pool, "sourceid", 1); - id_time = str2id(pool, "time", 1); - id_filelist = str2id(pool, "filelist", 1); - - id_isvisible = str2id(pool, "isvisible", 1); - - id_must = str2id(pool, "must", 1); - id_should = str2id(pool, "should", 1); - id_may = str2id(pool, "may", 1); - -} /* util function to set a translated string */ -void repodata_set_tstr(Repodata *data, Id rid, const char *attrname, const char *lang, const char *str) +static inline void repodata_set_tstr(Repodata *data, Id rid, const char *attrname, const char *lang, const char *str) { Id attrid; - attrid = str2id(data->repo->pool, join2( attrname, ":", lang), 1); + attrid = str2id(data->repo->pool, join2(attrname, ":", lang), 1); repodata_set_str(data, rid, attrid, str); } -- 2.7.4