X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Frepo_rpmdb.c;h=67ce81daf1e4ef2e5b6f7bdf8e4a03d393b72991;hb=b712cabb59f7155205489f15a37addb4ac8b0069;hp=daf22e979afdb8c0a19cdedc6529b724f3a0ccd4;hpb=0e46e80434781d1acbc4f5716827bf8688450a30;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index daf22e9..67ce81d 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -172,6 +172,15 @@ typedef struct rpmhead { } RpmHead; +static inline void +headinit(RpmHead *h, unsigned int cnt, unsigned int dcnt) +{ + h->cnt = (int)cnt; + h->dcnt = dcnt; + h->dp = h->data + 16 * cnt; + h->dp[dcnt] = 0; +} + static inline unsigned char * headfindtag(RpmHead *h, int tag) { @@ -1180,6 +1189,9 @@ rpmhead2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhe u32 = headint32(rpmhead, TAG_BUILDTIME); if (u32) repodata_set_num(data, handle, SOLVABLE_BUILDTIME, u32); + str = headstring(rpmhead, TAG_BUILDHOST); + if (str) + repodata_set_str(data, handle, SOLVABLE_BUILDHOST, str); u32 = headint32(rpmhead, TAG_INSTALLTIME); if (u32) repodata_set_num(data, handle, SOLVABLE_INSTALLTIME, u32); @@ -1240,7 +1252,7 @@ struct rpmdbstate { char *rootdir; RpmHead *rpmhead; /* header storage space */ - int rpmheadsize; + unsigned int rpmheadsize; }; #endif @@ -1248,49 +1260,55 @@ struct rpmdbstate { #ifndef ENABLE_RPMPKG_LIBRPM -static int -headfromfp(struct rpmdbstate *state, const char *name, FILE *fp, unsigned char *lead, unsigned int cnt, unsigned int dsize, unsigned int pad, Chksum *chk1, Chksum *chk2) +static inline RpmHead * +realloc_head(struct rpmdbstate *state, unsigned int len) { - RpmHead *rpmhead; - unsigned int len = 16 * cnt + dsize + pad; - if (len + 1 > state->rpmheadsize) + if (len > state->rpmheadsize) { state->rpmheadsize = len + 128; state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize); } - rpmhead = state->rpmhead; + return state->rpmhead; +} + +static int +headfromfp(struct rpmdbstate *state, const char *name, FILE *fp, unsigned char *lead, unsigned int cnt, unsigned int dsize, unsigned int pad, Chksum *chk1, Chksum *chk2) +{ + unsigned int len = 16 * cnt + dsize + pad; + RpmHead *rpmhead = realloc_head(state, len + 1); if (fread(rpmhead->data, len, 1, fp) != 1) return pool_error(state->pool, 0, "%s: unexpected EOF", name); if (chk1) solv_chksum_add(chk1, rpmhead->data, len); if (chk2) solv_chksum_add(chk2, rpmhead->data, len); - rpmhead->data[len] = 0; - rpmhead->cnt = cnt; - rpmhead->dcnt = dsize; - rpmhead->dp = rpmhead->data + cnt * 16; + headinit(rpmhead, cnt, dsize); return 1; } -#if defined(ENABLE_RPMDB_BYRPMHEADER) -static void -headfromblob(struct rpmdbstate *state, const unsigned char *blob, unsigned int cnt, unsigned int dsize) +# if defined(ENABLE_RPMDB) && (!defined(ENABLE_RPMDB_LIBRPM) || defined(HAVE_RPMDBNEXTITERATORHEADERBLOB)) + +static int +headfromhdrblob(struct rpmdbstate *state, const unsigned char *data, unsigned int size) { + unsigned int dsize, cnt, len; RpmHead *rpmhead; - unsigned int len = 16 * cnt + dsize; - if (len + 1 > state->rpmheadsize) - { - state->rpmheadsize = len + 128; - state->rpmhead = solv_realloc(state->rpmhead, sizeof(*state->rpmhead) + state->rpmheadsize); - } - rpmhead = state->rpmhead; - memcpy(rpmhead->data, blob, len); - rpmhead->data[len] = 0; - rpmhead->cnt = cnt; - rpmhead->dcnt = dsize; - rpmhead->dp = rpmhead->data + cnt * 16; + if (size < 8) + return pool_error(state->pool, 0, "corrupt rpm database (size)"); + cnt = getu32(data); + dsize = getu32(data + 4); + if (cnt >= MAX_HDR_CNT || dsize >= MAX_HDR_DSIZE) + return pool_error(state->pool, 0, "corrupt rpm database (cnt/dcnt)"); + if (8 + cnt * 16 + dsize > size) + return pool_error(state->pool, 0, "corrupt rpm database (data size)"); + len = 16 * cnt + dsize; + rpmhead = realloc_head(state, len + 1); + memcpy(rpmhead->data, data + 8, len); + headinit(rpmhead, cnt, dsize); + return 1; } -#endif + +# endif #else @@ -1329,8 +1347,6 @@ freestate(struct rpmdbstate *state) { /* close down */ #ifdef ENABLE_RPMDB - if (state->pkgdbopened) - closepkgdb(state); if (state->dbenvopened) closedbenv(state); #endif @@ -1385,49 +1401,12 @@ copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo) return ido; } -#define COPYDIR_DIRCACHE_SIZE 512 - -static Id copydir_complex(Repodata *data, Repodata *fromdata, Id did, Id *cache); - -static inline Id -copydir(Repodata *data, Repodata *fromdata, Id did, Id *cache) -{ - if (cache && did && cache[did & 255] == did) - return cache[(did & 255) + 256]; - return copydir_complex(data, fromdata, did, cache); -} - -static Id -copydir_complex(Repodata *data, Repodata *fromdata, Id did, Id *cache) -{ - Id parent, compid; - if (!did) - { - /* make sure that the dirpool has an entry */ - if (!data->dirpool.ndirs) - dirpool_add_dir(&data->dirpool, 0, 0, 1); - return 0; - } - parent = dirpool_parent(&fromdata->dirpool, did); - compid = dirpool_compid(&fromdata->dirpool, did); - if (parent) - parent = copydir(data, fromdata, parent, cache); - if (data->localpool || fromdata->localpool) - compid = repodata_translate_id(data, fromdata, compid, 1); - compid = dirpool_add_dir(&data->dirpool, parent, compid, 1); - if (cache) - { - cache[did & 255] = did; - cache[(did & 255) + 256] = compid; - } - return compid; -} - struct solvable_copy_cbdata { Repodata *data; Id handle; Id subhandle; Id *dircache; + int bad; }; static int @@ -1447,23 +1426,24 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K break; case REPOKEY_TYPE_DIRNUMNUMARRAY: case REPOKEY_TYPE_DIRSTRARRAY: - kv->id = copydir(data, fromdata, kv->id, cbdata->dircache); - break; - case REPOKEY_TYPE_FLEXARRAY: - if (kv->eof == 2) + kv->id = repodata_translate_dir(data, fromdata, kv->id, 1, fromdata->repodataid == 1 ? cbdata->dircache : 0); + if (!kv->id) { - assert(cbdata->subhandle); - cbdata->handle = cbdata->subhandle; - cbdata->subhandle = 0; - break; - } - if (!kv->entry) - { - assert(!cbdata->subhandle); - cbdata->subhandle = cbdata->handle; + cbdata->bad = 1; /* oops, cannot copy this */ + return 0; } + break; + case REPOKEY_TYPE_FIXARRAY: cbdata->handle = repodata_new_handle(data); - repodata_add_flexarray(data, cbdata->subhandle, key->name, cbdata->handle); + repodata_add_fixarray(data, handle, key->name, cbdata->handle); + repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); + cbdata->handle = handle; + return 0; + case REPOKEY_TYPE_FLEXARRAY: + cbdata->handle = repodata_new_handle(data); + repodata_add_flexarray(data, handle, key->name, cbdata->handle); + repodata_search_arrayelement(fromdata, 0, 0, 0, kv, &solvable_copy_cb, cbdata); + cbdata->handle = handle; return 0; default: break; @@ -1472,14 +1452,15 @@ solvable_copy_cb(void *vcbdata, Solvable *r, Repodata *fromdata, Repokey *key, K return 0; } -static void -solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) +static int +solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache, Id **oldkeyskip) { int p, i; Repo *repo = s->repo; Pool *pool = repo->pool; Repo *fromrepo = r->repo; struct solvable_copy_cbdata cbdata; + Id *keyskip; /* copy solvable data */ s->name = r->name; @@ -1497,29 +1478,36 @@ solvable_copy(Solvable *s, Solvable *r, Repodata *data, Id *dircache) /* copy all attributes */ if (!data || fromrepo->nrepodata < 2) - return; + return 1; cbdata.data = data; cbdata.handle = s - pool->solvables; cbdata.subhandle = 0; cbdata.dircache = dircache; + cbdata.bad = 0; p = r - fromrepo->pool->solvables; if (fromrepo->nrepodata == 2) { Repodata *fromdata = repo_id2repodata(fromrepo, 1); if (p >= fromdata->start && p < fromdata->end) - repodata_search(fromdata, p, 0, SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); - return; + repodata_search(fromdata, p, 0, 0, solvable_copy_cb, &cbdata); } -#if 0 - repo_search(fromrepo, p, 0, 0, SEARCH_NO_STORAGE_SOLVABLE | SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); -#else - FOR_REPODATAS(fromrepo, i, data) + else { - if (p >= data->start && p < data->end) - repodata_search(data, p, 0, SEARCH_SUB | SEARCH_ARRAYSENTINEL, solvable_copy_cb, &cbdata); - cbdata.dircache = 0; /* only for first repodata */ + keyskip = repo_create_keyskip(repo, p, oldkeyskip); + FOR_REPODATAS(fromrepo, i, data) + { + if (p >= data->start && p < data->end) + repodata_search_keyskip(data, p, 0, 0, keyskip, solvable_copy_cb, &cbdata); + } } -#endif + if (cbdata.bad) + { + repodata_unset_uninternalized(data, cbdata.handle, 0); + memset(s, 0, sizeof(*s)); + s->repo = repo; + return 0; + } + return 1; } /* used to sort entries by package name that got returned in some database order */ @@ -1633,7 +1621,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) } /* XXX: should get ro lock of Packages database! */ - if (stat_database(&state, "Packages", &packagesstat, 1)) + if (stat_database(&state, &packagesstat)) { freestate(&state); return -1; @@ -1652,11 +1640,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) repo_empty(ref, 1); /* get it out of the way */ if ((flags & RPMDB_REPORT_PROGRESS) != 0) count = count_headers(&state); - if (!openpkgdb(&state)) - { - freestate(&state); - return -1; - } if (pkgdb_cursor_open(&state)) { freestate(&state); @@ -1706,9 +1689,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) if (s) { /* oops, could not reuse. free it instead */ - repo_free_solvable(repo, s - pool->solvables, 1); + s = solvable_free(s, 1); solvend--; - s = 0; } /* now sort all solvables in the new solvstart..solvend block */ if (solvend - solvstart > 1) @@ -1731,7 +1713,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) } else { - Id dircache[COPYDIR_DIRCACHE_SIZE]; /* see copydir */ + Id *dircache; + Id *oldkeyskip = 0; struct rpmdbentry *entries = 0, *rp; int nentries = 0; char *namedata = 0; @@ -1739,8 +1722,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) Id id, *refhash; int res; - memset(dircache, 0, sizeof(dircache)); - /* get ids of installed rpms */ entries = getinstalledrpmdbids(&state, "Name", 0, &nentries, &namedata, flags & RPMDB_KEEP_GPG_PUBKEY); if (!entries) @@ -1795,10 +1776,11 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) if (!repo->rpmdbid) repo->rpmdbid = repo_sidedata_create(repo, sizeof(Id)); + dircache = repodata_create_dirtranscache(data); for (i = 0, rp = entries; i < nentries; i++, rp++, s++) { Id dbid = rp->rpmdbid; - repo->rpmdbid[(s - pool->solvables) - repo->start] = rp->rpmdbid; + repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid; if (refhash) { h = dbid & refmask; @@ -1811,11 +1793,8 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) if (id) { Solvable *r = ref->pool->solvables + ref->start + (id - 1); - if (r->repo == ref) - { - solvable_copy(s, r, data, dircache); - continue; - } + if (r->repo == ref && solvable_copy(s, r, data, dircache, &oldkeyskip)) + continue; } } res = getrpm_dbid(&state, dbid); @@ -1827,6 +1806,7 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) solv_free(entries); solv_free(namedata); solv_free(refhash); + dircache = repodata_free_dirtranscache(dircache); return -1; } rpmhead2solv(pool, repo, data, s, state.rpmhead, flags | RPM_ADD_TRIGGERS); @@ -1838,7 +1818,9 @@ repo_add_rpmdb(Repo *repo, Repo *ref, int flags) pool_debug(pool, SOLV_ERROR, "%%%% %d\n", done * 100 / count); } } + dircache = repodata_free_dirtranscache(dircache); + solv_free(oldkeyskip); solv_free(entries); solv_free(namedata); solv_free(refhash); @@ -2102,7 +2084,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) s = pool_id2solvable(pool, repo_add_solvable(repo)); if (!rpmhead2solv(pool, repo, data, s, state.rpmhead, flags & ~(RPM_ADD_WITH_HDRID | RPM_ADD_WITH_PKGID))) { - repo_free_solvable(repo, s - pool->solvables, 1); + s = solvable_free(s, 1); solv_chksum_free(chksumh, 0); headfree(state.rpmhead); return 0; @@ -2154,7 +2136,7 @@ repo_add_rpm_handle(Repo *repo, void *rpmhandle, int flags) s = pool_id2solvable(pool, repo_add_solvable(repo)); if (!rpmhead2solv(pool, repo, data, s, rpmhead, flags)) { - repo_free_solvable(repo, s - pool->solvables, 1); + s = solvable_free(s, 1); return 0; } if (!(flags & REPO_NO_INTERNALIZE)) @@ -2423,6 +2405,28 @@ rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queu return nentries; } +int +rpm_hash_database_state(void *rpmstate, Chksum *chk) +{ + struct rpmdbstate *state = rpmstate; + struct stat stb; + if (stat_database(state, &stb)) + return -1; + if (state->dbenvopened != 1 && !opendbenv(state)) + return -1; + solv_chksum_add(chk, &stb.st_mtime, sizeof(stb.st_mtime)); + solv_chksum_add(chk, &stb.st_size, sizeof(stb.st_size)); + solv_chksum_add(chk, &stb.st_ino, sizeof(stb.st_ino)); + hash_name_index(rpmstate, chk); + return 0; +} + +int +rpm_stat_database(void *rpmstate, void *stb) +{ + return stat_database((struct rpmdbstate *)rpmstate, (struct stat *)stb) ? -1 : 0; +} + void * rpm_byrpmdbid(void *rpmstate, Id rpmdbid) { @@ -2511,7 +2515,8 @@ rpm_byrpmh(void *rpmstate, Header h) struct rpmdbstate *state = rpmstate; #ifndef ENABLE_RPMPKG_LIBRPM const unsigned char *uh; - unsigned int dsize, cnt; + unsigned int dsize, cnt, len; + RpmHead *rpmhead; if (!h) return 0; @@ -2529,7 +2534,10 @@ rpm_byrpmh(void *rpmstate, Header h) free((void *)uh); return 0; } - headfromblob(state, uh + 8, cnt, dsize); + len = 16 * cnt + dsize; + rpmhead = realloc_head(state, len + 1);; + memcpy(rpmhead->data, uh + 8, len); + headinit(rpmhead, cnt, dsize); free((void *)uh); #else if (!h)