X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Frepo_solv.c;h=2460e30a8576c43b2eae7d471315cdebe44ac1dd;hb=e1659dc4ce74d3c47f465103951dafff8fc0cf9f;hp=307811c42792f815540ad4debf58bc381109758e;hpb=4cb98b886bde6788ac7c413630f038e11857e224;p=platform%2Fupstream%2Flibsolv.git diff --git a/src/repo_solv.c b/src/repo_solv.c index 307811c..2460e30 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -7,9 +7,9 @@ /* * repo_solv.c - * + * * Add a repo in solv format - * + * */ @@ -60,8 +60,7 @@ read_u32(Repodata *data) c = getc(data->fp); if (c == EOF) { - pool_debug(data->repo->pool, SOLV_ERROR, "unexpected EOF\n"); - data->error = SOLV_ERROR_EOF; + data->error = pool_error(data->repo->pool, SOLV_ERROR_EOF, "unexpected EOF"); return 0; } x = (x << 8) | c; @@ -84,8 +83,7 @@ read_u8(Repodata *data) c = getc(data->fp); if (c == EOF) { - pool_debug(data->repo->pool, SOLV_ERROR, "unexpected EOF\n"); - data->error = SOLV_ERROR_EOF; + data->error = pool_error(data->repo->pool, SOLV_ERROR_EOF, "unexpected EOF"); return 0; } return c; @@ -109,25 +107,22 @@ read_id(Repodata *data, Id max) c = getc(data->fp); if (c == EOF) { - pool_debug(data->repo->pool, SOLV_ERROR, "unexpected EOF\n"); - data->error = SOLV_ERROR_EOF; + data->error = pool_error(data->repo->pool, SOLV_ERROR_EOF, "unexpected EOF"); return 0; } if (!(c & 128)) { x = (x << 7) | c; - if (max && x >= max) + if (max && x >= (unsigned int)max) { - pool_debug(data->repo->pool, SOLV_ERROR, "read_id: id too large (%u/%u)\n", x, max); - data->error = SOLV_ERROR_ID_RANGE; + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_id: id too large (%u/%u)", x, max); return 0; } return x; } x = (x << 7) ^ c ^ 128; } - pool_debug(data->repo->pool, SOLV_ERROR, "read_id: id too long\n"); - data->error = SOLV_ERROR_CORRUPT; + data->error = pool_error(data->repo->pool, SOLV_ERROR_CORRUPT, "read_id: id too long"); return 0; } @@ -145,8 +140,7 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end) c = getc(data->fp); if (c == EOF) { - pool_debug(data->repo->pool, SOLV_ERROR, "unexpected EOF\n"); - data->error = SOLV_ERROR_EOF; + data->error = pool_error(data->repo->pool, SOLV_ERROR_EOF, "unexpected EOF"); return 0; } if ((c & 128) != 0) @@ -155,17 +149,16 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end) continue; } x = (x << 6) | (c & 63); - if (max && x >= max) + if (max && x >= (unsigned int)max) { - pool_debug(data->repo->pool, SOLV_ERROR, "read_idarray: id too large (%u/%u)\n", x, max); - data->error = SOLV_ERROR_ID_RANGE; + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "read_idarray: id too large (%u/%u)", x, max); return 0; } if (map) x = map[x]; if (store == end) { - pool_debug(data->repo->pool, SOLV_ERROR, "read_idarray: array overflow\n"); + data->error = pool_error(data->repo->pool, SOLV_ERROR_OVERFLOW, "read_idarray: array overflow"); return 0; } *store++ = x; @@ -175,8 +168,7 @@ read_idarray(Repodata *data, Id max, Id *map, Id *store, Id *end) return store; if (store == end) { - pool_debug(data->repo->pool, SOLV_ERROR, "read_idarray: array overflow\n"); - data->error = SOLV_ERROR_OVERFLOW; + data->error = pool_error(data->repo->pool, SOLV_ERROR_OVERFLOW, "read_idarray: array overflow"); return 0; } *store++ = 0; @@ -202,8 +194,7 @@ data_read_id_max(unsigned char *dp, Id *ret, Id *map, int max, Repodata *data) dp = data_read_id(dp, &x); if (x < 0 || (max && x >= max)) { - pool_debug(data->repo->pool, SOLV_ERROR, "data_read_id_max: id too large (%u/%u)\n", x, max); - data->error = SOLV_ERROR_ID_RANGE; + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "data_read_id_max: id too large (%u/%u)", x, max); x = 0; } *ret = map ? map[x] : x; @@ -226,9 +217,9 @@ data_read_idarray(unsigned char *dp, Id **storep, Id *map, int max, Repodata *da continue; } x = (x << 6) | (c & 63); - if (max && x >= max) + if (max && x >= (unsigned int)max) { - pool_debug(data->repo->pool, SOLV_ERROR, "data_read_idarray: id too large (%u/%u)\n", x, max); + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "data_read_idarray: id too large (%u/%u)", x, max); data->error = SOLV_ERROR_ID_RANGE; break; } @@ -270,10 +261,9 @@ data_read_rel_idarray(unsigned char *dp, Id **storep, Id *map, int max, Repodata } x = old + (x - 1); old = x; - if (max && x >= max) + if (max && x >= (unsigned int)max) { - pool_debug(data->repo->pool, SOLV_ERROR, "data_read_rel_idarray: id too large (%u/%u)\n", x, max); - data->error = SOLV_ERROR_ID_RANGE; + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "data_read_rel_idarray: id too large (%u/%u)", x, max); break; } *store++ = map ? map[x] : x; @@ -324,6 +314,23 @@ incore_add_id(Repodata *data, Id sx) } static void +incore_add_sizek(Repodata *data, unsigned int sx) +{ + if (sx < (1 << 22)) + incore_add_id(data, (Id)(sx << 10)); + else + { + if ((sx >> 25) != 0) + { + incore_add_id(data, (Id)(sx >> 25)); + data->incoredata[data->incoredatalen - 1] |= 128; + } + incore_add_id(data, (Id)((sx << 10) | 0x80000000)); + data->incoredata[data->incoredatalen - 5] = (sx >> 18) | 128; + } +} + +static void incore_add_ideof(Repodata *data, Id sx, int eof) { unsigned int x = (unsigned int)sx; @@ -353,7 +360,7 @@ incore_add_ideof(Repodata *data, Id sx, int eof) static void incore_add_blob(Repodata *data, unsigned char *buf, int len) { - if (data->incoredatafree < len) + if (data->incoredatafree < (unsigned int)len) { data->incoredata = solv_realloc(data->incoredata, data->incoredatalen + INCORE_ADD_CHUNK + len); data->incoredatafree = INCORE_ADD_CHUNK + len; @@ -376,8 +383,7 @@ incore_map_idarray(Repodata *data, unsigned char *dp, Id *map, Id max) dp = data_read_ideof(dp, &id, &eof); if (id < 0 || (max && id >= max)) { - pool_debug(data->repo->pool, SOLV_ERROR, "incore_map_idarray: id too large (%u/%u)\n", id, max); - data->error = SOLV_ERROR_ID_RANGE; + data->error = pool_error(data->repo->pool, SOLV_ERROR_ID_RANGE, "incore_map_idarray: id too large (%u/%u)", id, max); break; } id = map[id]; @@ -438,8 +444,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; int i, l; - unsigned int numid, numrel, numdir, numsolv; - unsigned int numkeys, numschemata; + int numid, numrel, numdir, numsolv; + int numkeys, numschemata; Offset sizeid; Offset *str; /* map Id -> Offset into string space */ @@ -447,9 +453,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) char *sp; /* pointer into string space */ Id *idmap; /* map of repo Ids to pool Ids */ Id id, type; - unsigned int hashmask, h; - int hh; - Id *hashtbl; + Hashval hashmask, h, hh; + Hashtable hashtbl; Id name, evr, did; int relflags; Reldep *ran; @@ -463,7 +468,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) Id *schemadata, *schemadatap, *schemadataend; Id *schemata, key, *keyp; int nentries; - int have_xdata; + int have_incoredata; int maxsize, allsize; unsigned char *buf, *bufend, *dp, *dps; Id stack[3 * 5]; @@ -478,6 +483,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) Repodata *parent = 0; Repodata data; + int extendstart = 0, extendend = 0; /* set in case we're extending */ + now = solv_timems(0); if ((flags & REPO_USE_LOADING) != 0) @@ -486,111 +493,118 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) flags |= REPO_EXTEND_SOLVABLES; /* use REPO_REUSE_REPODATA hack so that the old repodata is kept */ parent = repo_add_repodata(repo, flags | REPO_REUSE_REPODATA); + extendstart = parent->start; + extendend = parent->end; } - + else if (flags & REPO_EXTEND_SOLVABLES) + { + /* extend all solvables of this repo */ + extendstart = repo->start; + extendend = repo->end; + } + memset(&data, 0, sizeof(data)); data.repo = repo; data.fp = fp; repopagestore_init(&data.store); if (read_u32(&data) != ('S' << 24 | 'O' << 16 | 'L' << 8 | 'V')) - { - pool_debug(pool, SOLV_ERROR, "not a SOLV file\n"); - return SOLV_ERROR_NOT_SOLV; - } + return pool_error(pool, SOLV_ERROR_NOT_SOLV, "not a SOLV file"); solvversion = read_u32(&data); switch (solvversion) { case SOLV_VERSION_8: break; default: - pool_debug(pool, SOLV_ERROR, "unsupported SOLV version\n"); - return SOLV_ERROR_UNSUPPORTED; + return pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported SOLV version"); } - numid = read_u32(&data); - numrel = read_u32(&data); - numdir = read_u32(&data); - numsolv = read_u32(&data); - numkeys = read_u32(&data); - numschemata = read_u32(&data); + numid = (int)read_u32(&data); + numrel = (int)read_u32(&data); + numdir = (int)read_u32(&data); + numsolv = (int)read_u32(&data); + numkeys = (int)read_u32(&data); + numschemata = (int)read_u32(&data); solvflags = read_u32(&data); - if (numdir && numdir < 2) - { - pool_debug(pool, SOLV_ERROR, "bad number of dirs\n"); - return SOLV_ERROR_CORRUPT; - } + if (numid < 0 || numid >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of ids"); + if (numrel < 0 || numrel >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of rels"); + if (numdir && (numdir < 2 || numdir >= 0x20000000)) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of dirs"); + if (numsolv < 0 || numsolv >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of solvables"); + if (numkeys < 0 || numkeys >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of keys"); + if (numschemata < 0 || numschemata >= 0x20000000) + return pool_error(pool, SOLV_ERROR_CORRUPT, "bad number of schematas"); if (numrel && (flags & REPO_LOCALPOOL) != 0) - { - pool_debug(pool, SOLV_ERROR, "relations are forbidden in a local pool\n"); - return SOLV_ERROR_CORRUPT; - } - if (parent && numsolv) + return pool_error(pool, SOLV_ERROR_CORRUPT, "relations are forbidden in a local pool"); + if ((flags & REPO_EXTEND_SOLVABLES) && numsolv) { /* make sure that we exactly replace the stub repodata */ - if (parent->end - parent->start != numsolv) - { - pool_debug(pool, SOLV_ERROR, "sub-repository solvable number does not match main repository (%d - %d)\n", parent->end - parent->start, numsolv); - return SOLV_ERROR_CORRUPT; - } + if (extendend - extendstart != numsolv) + return pool_error(pool, SOLV_ERROR_CORRUPT, "sub-repository solvable number does not match main repository (%d - %d)", extendend - extendstart, numsolv); for (i = 0; i < numsolv; i++) - if (pool->solvables[parent->start + i].repo != repo) - { - pool_debug(pool, SOLV_ERROR, "main repository contains holes\n"); - return SOLV_ERROR_CORRUPT; - } + if (pool->solvables[extendstart + i].repo != repo) + return pool_error(pool, SOLV_ERROR_CORRUPT, "main repository contains holes, cannot extend"); } /******* Part 1: string IDs *****************************************/ - sizeid = read_u32(&data); /* size of string+Id space */ + sizeid = read_u32(&data); /* size of string space */ /* * read strings and Ids - * + * */ - + /* * alloc buffers */ if (!(flags & REPO_LOCALPOOL)) - spool = &pool->ss; + { + spool = &pool->ss; + /* alloc max needed string buffer and string pointers, will shrink again later */ +#if 0 + spool->stringspace = solv_realloc(spool->stringspace, spool->sstrings + sizeid + 1); + spool->strings = solv_realloc2(spool->strings, spool->nstrings + numid, sizeof(Offset)); +#else + spool->sstrings += sizeid + 1; + spool->nstrings += numid; + stringpool_shrink(spool); /* we misuse stringpool_shrink so that the correct BLOCK factor is used */ + spool->sstrings -= sizeid + 1; + spool->nstrings -= numid; +#endif + } else { data.localpool = 1; spool = &data.spool; - spool->stringspace = solv_malloc(7); + spool->stringspace = solv_malloc(7 + sizeid + 1); + spool->strings = solv_malloc2(numid < 2 ? 2 : numid, sizeof(Offset)); strcpy(spool->stringspace, ""); spool->sstrings = 7; - spool->nstrings = 0; + spool->nstrings = 1; + spool->strings[0] = 0; /* */ } - /* alloc string buffer */ - spool->stringspace = solv_realloc(spool->stringspace, spool->sstrings + sizeid + 1); - /* alloc string offsets (Id -> Offset into string space) */ - spool->strings = solv_realloc2(spool->strings, spool->nstrings + numid, sizeof(Offset)); - - strsp = spool->stringspace; - str = spool->strings; /* array of offsets into strsp, indexed by Id */ - - /* point to _BEHIND_ already allocated string/Id space */ - strsp += spool->sstrings; - /* - * read new repo at end of pool + * read string data and append to old string space */ - + + strsp = spool->stringspace + spool->sstrings; /* append new entries */ if ((solvflags & SOLV_FLAG_PREFIX_POOL) == 0) { if (sizeid && fread(strsp, sizeid, 1, fp) != 1) { - pool_debug(pool, SOLV_ERROR, "read error while reading strings\n"); - return SOLV_ERROR_EOF; + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings"); } } else @@ -603,10 +617,10 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) int freesp = sizeid; if (pfsize && fread(prefix, pfsize, 1, fp) != 1) - { - pool_debug(pool, SOLV_ERROR, "read error while reading strings\n"); + { solv_free(prefix); - return SOLV_ERROR_EOF; + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_EOF, "read error while reading strings"); } for (i = 1; i < numid; i++) { @@ -615,9 +629,9 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) freesp -= same + len; if (freesp < 0) { - pool_debug(pool, SOLV_ERROR, "overflow while expanding strings\n"); solv_free(prefix); - return SOLV_ERROR_OVERFLOW; + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_OVERFLOW, "overflow while expanding strings"); } if (same) memcpy(dest, old_str, same); @@ -629,31 +643,32 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) solv_free(prefix); if (freesp != 0) { - pool_debug(pool, SOLV_ERROR, "expanding strings size mismatch\n"); - return SOLV_ERROR_CORRUPT; + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_CORRUPT, "expanding strings size mismatch"); } } strsp[sizeid] = 0; /* make string space \0 terminated */ sp = strsp; + /* now merge */ + str = spool->strings; /* array of offsets into strsp, indexed by Id */ if ((flags & REPO_LOCALPOOL) != 0) { - /* no shared pool, thus no idmap and no unification */ + /* no shared pool, thus no idmap and no unification needed */ idmap = 0; - spool->nstrings = numid; - str[0] = 0; + spool->nstrings = numid < 2 ? 2 : numid; /* make sure we have at least id 0 and 1 */ if (*sp) { - /* we need the '' for directories */ - pool_debug(pool, SOLV_ERROR, "store strings don't start with ''\n"); - return SOLV_ERROR_CORRUPT; + /* we need id 1 to be '' for directories */ + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_CORRUPT, "store strings don't start with an empty string"); } for (i = 1; i < spool->nstrings; i++) { - if (sp >= strsp + sizeid) + if (sp >= strsp + sizeid && numid >= 2) { - pool_debug(pool, SOLV_ERROR, "not enough strings\n"); - return SOLV_ERROR_OVERFLOW; + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_OVERFLOW, "not enough strings"); } str[i] = sp - spool->stringspace; sp += strlen(sp) + 1; @@ -662,6 +677,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) } else { + Offset oldsstrings = spool->sstrings; + /* alloc id map for name and rel Ids. this maps ids in the solv files * to the ids in our pool */ idmap = solv_calloc(numid + numrel, sizeof(Id)); @@ -700,10 +717,12 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) { if (sp >= strsp + sizeid) { - solv_free(hashtbl); solv_free(idmap); - pool_debug(pool, SOLV_ERROR, "not enough strings %d %d\n", i, numid); - return SOLV_ERROR_OVERFLOW; + spool->nstrings = oldnstrings; + spool->sstrings = oldsstrings; + stringpool_freehash(spool); + repodata_freedata(&data); + return pool_error(pool, SOLV_ERROR_OVERFLOW, "not enough strings %d %d", i, numid); } if (!*sp) /* empty string */ { @@ -744,17 +763,17 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) spool->stringhashtbl = solv_free(spool->stringhashtbl); spool->stringhashmask = 0; } + stringpool_shrink(spool); /* vacuum */ } - pool_shrink_strings(pool); /* vacuum */ - + /******* Part 2: Relation IDs ***************************************/ /* * read RelDeps - * + * */ - + if (numrel) { /* extend rels */ @@ -854,11 +873,20 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) { id = read_id(&data, i + numid); if (id >= numid) - data.dirpool.dirs[i] = -(id - numid); - else if (idmap) - data.dirpool.dirs[i] = idmap[id]; - else - data.dirpool.dirs[i] = id; + { + data.dirpool.dirs[i++] = -(id - numid); + if (i >= numdir) + { + data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "last dir entry is not a component"); + break; + } + id = read_id(&data, numid); + } + if (idmap) + id = idmap[id]; + data.dirpool.dirs[i] = id; + if (id <= 0) + data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "bad dir component"); } } @@ -880,8 +908,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) type = pool_str2id(pool, stringpool_id2str(spool, type), 1); if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_FLEXARRAY) { - pool_debug(pool, SOLV_ERROR, "unsupported data type '%s'\n", pool_id2str(pool, type)); - data.error = SOLV_ERROR_UNSUPPORTED; + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported data type '%s'", pool_id2str(pool, type)); type = REPOKEY_TYPE_VOID; } keys[i].name = id; @@ -892,32 +919,20 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) if (keys[i].storage == KEY_STORAGE_SOLVABLE) keys[i].storage = KEY_STORAGE_INCORE; if (keys[i].storage != KEY_STORAGE_INCORE && keys[i].storage != KEY_STORAGE_VERTICAL_OFFSET) - { - pool_debug(pool, SOLV_ERROR, "unsupported storage type %d\n", keys[i].storage); - data.error = SOLV_ERROR_UNSUPPORTED; - } + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "unsupported storage type %d", keys[i].storage); if (id >= SOLVABLE_NAME && id <= RPM_RPMDBID) { if (keys[i].storage != KEY_STORAGE_INCORE) - { - pool_debug(pool, SOLV_ERROR, "main solvable data must use incore storage%d\n", keys[i].storage); - data.error = SOLV_ERROR_UNSUPPORTED; - } + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "main solvable data must use incore storage %d", keys[i].storage); keys[i].storage = KEY_STORAGE_SOLVABLE; } /* cannot handle rel idarrays in incore/vertical */ if (type == REPOKEY_TYPE_REL_IDARRAY && keys[i].storage != KEY_STORAGE_SOLVABLE) - { - pool_debug(pool, SOLV_ERROR, "type REL_IDARRAY is only supported for STORAGE_SOLVABLE\n"); - data.error = SOLV_ERROR_UNSUPPORTED; - } + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "type REL_IDARRAY is only supported for STORAGE_SOLVABLE"); /* cannot handle mapped ids in vertical */ if (!(flags & REPO_LOCALPOOL) && keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET && (type == REPOKEY_TYPE_ID || type == REPOKEY_TYPE_IDARRAY)) - { - pool_debug(pool, SOLV_ERROR, "mapped ids are not supported for STORAGE_VERTICAL_OFFSET\n"); - data.error = SOLV_ERROR_UNSUPPORTED; - } - + data.error = pool_error(pool, SOLV_ERROR_UNSUPPORTED, "mapped ids are not supported for STORAGE_VERTICAL_OFFSET"); + if (keys[i].type == REPOKEY_TYPE_CONSTANTID && idmap) keys[i].size = idmap[keys[i].size]; #if 0 @@ -926,10 +941,10 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) #endif } - have_xdata = parent ? 1 : 0; + have_incoredata = 0; for (i = 1; i < numkeys; i++) if (keys[i].storage == KEY_STORAGE_INCORE || keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) - have_xdata = 1; + have_incoredata = 1; data.keys = keys; data.nkeys = numkeys; @@ -940,7 +955,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) } /******* Part 5: Schemata ********************************************/ - + id = read_id(&data, 0); schemadata = solv_calloc(id + 1, sizeof(Id)); schemadatap = schemadata + 1; @@ -985,8 +1000,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) l = allsize; if (!l || fread(buf, l, 1, data.fp) != 1) { - pool_debug(pool, SOLV_ERROR, "unexpected EOF\n"); - data.error = SOLV_ERROR_EOF; + data.error = pool_error(pool, SOLV_ERROR_EOF, "unexpected EOF"); id = 0; } else @@ -996,8 +1010,8 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) dp = data_read_id_max(dp, &id, 0, numschemata, &data); } - incore_add_id(&data, 0); /* XXX? */ - incore_add_id(&data, id); + incore_add_id(&data, 0); /* so that incoreoffset 0 means schema 0 */ + incore_add_id(&data, id); /* main schema id */ keyp = schemadata + schemata[id]; data.mainschema = id; for (i = 0; keyp[i]; i++) @@ -1020,8 +1034,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) break; if (left < 0) { - pool_debug(pool, SOLV_ERROR, "buffer overrun\n"); - data.error = SOLV_ERROR_EOF; + data.error = pool_error(pool, SOLV_ERROR_EOF, "buffer overrun"); break; } if (left < maxsize) @@ -1035,8 +1048,7 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) l = allsize; if (l && fread(buf + left, l, 1, data.fp) != 1) { - pool_debug(pool, SOLV_ERROR, "unexpected EOF\n"); - data.error = SOLV_ERROR_EOF; + data.error = pool_error(pool, SOLV_ERROR_EOF, "unexpected EOF"); break; } allsize -= l; @@ -1062,7 +1074,7 @@ printf("key %d at %d\n", key, (int)(keyp - 1 - schemadata)); if (s && keydepth == 3) { s++; /* next solvable */ - if (have_xdata) + if (have_incoredata) data.incoreoffset[(s - pool->solvables) - data.start] = data.incoredatalen; } id = stack[keydepth - 1]; @@ -1108,13 +1120,13 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key case REPOKEY_TYPE_ID: dp = data_read_id_max(dp, &did, idmap, numid + numrel, &data); if (s && id == SOLVABLE_NAME) - s->name = did; + s->name = did; else if (s && id == SOLVABLE_ARCH) - s->arch = did; + s->arch = did; else if (s && id == SOLVABLE_EVR) - s->evr = did; + s->evr = did; else if (s && id == SOLVABLE_VENDOR) - s->vendor = did; + s->vendor = did; else if (keys[key].storage == KEY_STORAGE_INCORE) incore_add_id(&data, did); #if 0 @@ -1146,8 +1158,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key dp = data_read_rel_idarray(dp, &idarraydatap, idmap, numid + numrel, &data, 0); if (idarraydatap > idarraydataend) { - pool_debug(pool, SOLV_ERROR, "idarray overflow\n"); - data.error = SOLV_ERROR_OVERFLOW; + data.error = pool_error(pool, SOLV_ERROR_OVERFLOW, "idarray overflow"); break; } if (id == SOLVABLE_PROVIDES) @@ -1178,8 +1189,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key needchunk = 1; if (keydepth == sizeof(stack)/sizeof(*stack)) { - pool_debug(pool, SOLV_ERROR, "array stack overflow\n"); - data.error = SOLV_ERROR_CORRUPT; + data.error = pool_error(pool, SOLV_ERROR_OVERFLOW, "array stack overflow"); break; } stack[keydepth++] = nentries; @@ -1199,18 +1209,16 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key /* horray! here come the solvables */ if (nentries != numsolv) { - pool_debug(pool, SOLV_ERROR, "inconsistent number of solvables: %d %d\n", nentries, numsolv); - data.error = SOLV_ERROR_CORRUPT; + data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "inconsistent number of solvables: %d %d", nentries, numsolv); break; } if (idarraydatap) { - pool_debug(pool, SOLV_ERROR, "more than one solvable block\n"); - data.error = SOLV_ERROR_CORRUPT; + data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "more than one solvable block"); break; } - if (parent) - s = pool_id2solvable(pool, parent->start); + if ((flags & REPO_EXTEND_SOLVABLES) != 0) + s = pool_id2solvable(pool, extendstart); else s = pool_id2solvable(pool, repo_add_solvable_block(repo, numsolv)); data.start = s - pool->solvables; @@ -1230,7 +1238,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key repo->idarraysize += size_idarray; idarraydataend = idarraydatap + size_idarray; repo->lastoff = 0; - if (have_xdata) + if (have_incoredata) data.incoreoffset[(s - pool->solvables) - data.start] = data.incoredatalen; } nentries--; @@ -1239,14 +1247,21 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key if (keys[key].type == REPOKEY_TYPE_FIXARRAY) { if (!id) - { - pool_debug(pool, SOLV_ERROR, "illegal fixarray\n"); - data.error = SOLV_ERROR_CORRUPT; - } + data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "illegal fixarray"); stack[keydepth - 1] = id; } keyp = schemadata + schemata[id]; break; + case REPOKEY_TYPE_NUM: + if (!(solvflags & SOLV_FLAG_SIZE_BYTES) && keys[key].storage == KEY_STORAGE_INCORE && + (id == SOLVABLE_INSTALLSIZE || id == SOLVABLE_DOWNLOADSIZE || id == DELTA_DOWNLOADSIZE)) + { + /* old solv file with sizes in kilos. transcode. */ + dp = data_read_id(dp, &id); + incore_add_sizek(&data, (unsigned int)id); + break; + } + /* FALLTHROUGH */ default: if (id == RPM_RPMDBID && s && (keys[key].type == REPOKEY_TYPE_U32 || keys[key].type == REPOKEY_TYPE_NUM)) { @@ -1269,17 +1284,11 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key /* should shrink idarraydata again */ if (keydepth) - { - pool_debug(pool, SOLV_ERROR, "unexpected EOF, depth = %d\n", keydepth); - data.error = SOLV_ERROR_CORRUPT; - } + data.error = pool_error(pool, SOLV_ERROR_EOF, "unexpected EOF, depth = %d", keydepth); if (!data.error) { if (dp > bufend) - { - pool_debug(pool, SOLV_ERROR, "buffer overrun\n"); - data.error = SOLV_ERROR_EOF; - } + data.error = pool_error(pool, SOLV_ERROR_EOF, "buffer overrun"); } solv_free(buf); @@ -1300,6 +1309,12 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key data.incoredata = solv_realloc(data.incoredata, data.incoredatalen); data.incoredatafree = 0; } + solv_free(idmap); + + /* fixup the special idarray type */ + for (i = 1; i < numkeys; i++) + if (keys[i].type == REPOKEY_TYPE_REL_IDARRAY) + keys[i].type = REPOKEY_TYPE_IDARRAY; for (i = 1; i < numkeys; i++) if (keys[i].storage == KEY_STORAGE_VERTICAL_OFFSET) @@ -1308,7 +1323,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key { Id fileoffset = 0; unsigned int pagesize; - + /* we have vertical data, make it available */ data.verticaloffset = solv_calloc(numkeys, sizeof(Id)); for (i = 1; i < numkeys; i++) @@ -1319,19 +1334,22 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key } data.lastverticaloffset = fileoffset; pagesize = read_u32(&data); - data.error = repopagestore_read_or_setup_pages(&data.store, data.fp, pagesize, fileoffset); - } - else - { - /* no longer needed */ - data.fp = 0; + if (!data.error) + { + data.error = repopagestore_read_or_setup_pages(&data.store, data.fp, pagesize, fileoffset); + if (data.error == SOLV_ERROR_EOF) + pool_error(pool, data.error, "repopagestore setup: unexpected EOF"); + else if (data.error) + pool_error(pool, data.error, "repopagestore setup failed"); + } } - solv_free(idmap); + data.fp = 0; /* no longer needed */ if (data.error) { - /* XXX: free repodata? */ - return data.error; + i = data.error; + repodata_freedata(&data); + return i; } if (parent)