};
+static inline int
+access_rootdir(struct rpmdbstate *state, const char *dir, int mode)
+{
+ if (state->rootdir)
+ {
+ char *path = solv_dupjoin(state->rootdir, dir, 0);
+ int r = access(path, mode);
+ free(path);
+ return r;
+ }
+ return access(dir, mode);
+}
+
+static void
+detect_ostree(struct rpmdbstate *state)
+{
+ state->is_ostree = access_rootdir(state, "/var/lib/rpm", W_OK) == -1 &&
+ access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0 ? 1 : -1;
+}
+
static int
stat_database_name(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int seterror)
{
char *dbpath;
- dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
+ dbpath = solv_dupjoin(state->rootdir, state->is_ostree > 0 ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
if (stat(dbpath, statbuf))
{
if (seterror)
static int
stat_database(struct rpmdbstate *state, struct stat *statbuf)
{
+ if (!state->is_ostree)
+ detect_ostree(state);
return stat_database_name(state, "Packages", statbuf, 1);
}
dbenv->set_thread_count(dbenv, 8);
#endif
dbpath = solv_dupjoin(rootdir, "/var/lib/rpm", 0);
+ state->is_ostree = -1;
if (access(dbpath, W_OK) == -1)
{
free(dbpath);
if (access(dbpath, R_OK) == 0)
state->is_ostree = 1;
free(dbpath);
- dbpath = solv_dupjoin(rootdir, state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm", 0);
+ dbpath = solv_dupjoin(rootdir, state->is_ostree > 0 ? "/usr/share/rpm" : "/var/lib/rpm", 0);
r = dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0);
}
else
uint32_t eflags = 0;
#endif
+ if (state->db)
+ {
+ state->db->close(state->db, 0);
+ state->db = 0;
+ }
+ state->pkgdbopened = 0;
if (!state->dbenv)
return;
#if defined(FEDORA) || defined(MAGEIA)
return 1;
}
-static void
-closepkgdb(struct rpmdbstate *state)
-{
- if (!state->db)
- return;
- state->db->close(state->db, 0);
- state->db = 0;
- state->pkgdbopened = 0;
-}
-
/* get the rpmdbids of all installed packages from the Name index database.
* This is much faster then querying the big Packages database */
static struct rpmdbentry *
static int
pkgdb_cursor_open(struct rpmdbstate *state)
{
+ if (state->pkgdbopened != 1 && !openpkgdb(state))
+ return -1;
if (state->db->cursor(state->db, NULL, &state->dbc, 0))
return pool_error(state->pool, -1, "db->cursor failed");
return 0;
return 0; /* no more entries */
}
+static int
+hash_name_index(struct rpmdbstate *state, Chksum *chk)
+{
+ char *dbpath;
+ int fd, l;
+ char buf[4096];
+
+ dbpath = solv_dupjoin(state->rootdir, state->is_ostree > 0 ? "/usr/share/rpm/" : "/var/lib/rpm/", "Name");
+ if ((fd = open(dbpath, O_RDONLY)) < 0)
+ return -1;
+ while ((l = read(fd, buf, sizeof(buf))) > 0)
+ solv_chksum_add(chk, buf, l);
+ close(fd);
+ return 0;
+}
+
+
int rpmheadsize;
int dbenvopened; /* database environment opened */
- int pkgdbopened; /* package database openend */
int is_ostree; /* read-only db that lives in /usr/share/rpm */
rpmts ts;
rpmdbMatchIterator mi; /* iterator over packages database */
};
+static inline int
+access_rootdir(struct rpmdbstate *state, const char *dir, int mode)
+{
+ if (state->rootdir)
+ {
+ char *path = solv_dupjoin(state->rootdir, dir, 0);
+ int r = access(path, mode);
+ free(path);
+ return r;
+ }
+ return access(dir, mode);
+}
+
+static void
+detect_ostree(struct rpmdbstate *state)
+{
+ state->is_ostree = access_rootdir(state, "/var/lib/rpm", W_OK) == -1 &&
+ access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0 ? 1 : -1;
+}
+
static int
stat_database(struct rpmdbstate *state, struct stat *statbuf)
{
};
int i;
+#ifdef HAVE_RPMDBFSTAT
+ if (state->dbenvopened == 1)
+ return rpmdbFStat(rpmtsGetRdb(state->ts), statbuf);
+#endif
+ if (!state->is_ostree)
+ detect_ostree(state);
for (i = 0; ; i++)
{
- char *dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname[i]);
+ char *dbpath = solv_dupjoin(state->rootdir, state->is_ostree > 0 ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname[i]);
if (!stat(dbpath, statbuf))
{
free(dbpath);
}
if (errno != ENOENT || !dbname[i + 1])
{
+ int saved_errno = errno;
pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
solv_free(dbpath);
+ errno = saved_errno;
return -1;
}
solv_free(dbpath);
const char *rootdir = state->rootdir;
rpmts ts;
char *dbpath;
- dbpath = solv_dupjoin("_dbpath ", rootdir, "/var/lib/rpm");
- if (access(dbpath + 8, W_OK) == -1)
- {
- free(dbpath);
- dbpath = solv_dupjoin(rootdir, "/usr/share/rpm/Packages", 0);
- if (access(dbpath, R_OK) == 0)
- state->is_ostree = 1;
- free(dbpath);
- dbpath = solv_dupjoin("_dbpath ", rootdir, state->is_ostree ? "/usr/share/rpm" : "/var/lib/rpm");
- }
+ detect_ostree(state);
+ dbpath = solv_dupjoin("_dbpath ", rootdir, state->is_ostree > 0 ? "/usr/share/rpm" : "/var/lib/rpm");
rpmDefineMacro(NULL, dbpath, 0);
solv_free(dbpath);
ts = rpmtsCreate();
rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | _RPMVSF_NOHEADER);
state->ts = ts;
state->dbenvopened = 1;
- state->pkgdbopened = 1;
return 1;
}
if (state->ts)
rpmtsFree(state->ts);
state->ts = 0;
- state->pkgdbopened = 0;
state->dbenvopened = 0;
}
-static int
-openpkgdb(struct rpmdbstate *state)
-{
- /* already done in opendbenv */
- return 1;
-}
-
-static void
-closepkgdb(struct rpmdbstate *state)
-{
-}
-
/* get the rpmdbids of all installed packages from the Name index database.
* This is much faster then querying the big Packages database */
static struct rpmdbentry *
int nentries = 0;
rpmdbIndexIterator ii;
- int i;
*nentriesp = 0;
if (namedatap)
while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
{
+ unsigned int i, npkgs;
if (match)
{
if (keylen != matchl || memcmp(key, match, keylen) != 0)
namedata[namedatal + keylen] = 0;
namedatal += keylen + 1;
}
- for (i = 0; i < rpmdbIndexIteratorNumPkgs(ii); i++)
+ npkgs = rpmdbIndexIteratorNumPkgs(ii);
+ for (i = 0; i < npkgs; i++)
{
entries = solv_extend(entries, nentries, 1, sizeof(*entries), ENTRIES_BLOCK);
entries[nentries].rpmdbid = rpmdbIndexIteratorPkgOffset(ii, i);
return entries;
}
+#if defined(HAVE_RPMDBNEXTITERATORHEADERBLOB) && !defined(ENABLE_RPMPKG_LIBRPM)
+static int
+rpm_byrpmhdrblob(struct rpmdbstate *state, const unsigned char *data, unsigned int size)
+{
+ unsigned int dsize, cnt, len;
+ RpmHead *rpmhead;
+ 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;
+ 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, data + 8, len);
+ rpmhead->data[len] = 0;
+ rpmhead->cnt = cnt;
+ rpmhead->dcnt = dsize;
+ rpmhead->dp = rpmhead->data + cnt * 16;
+ return 1;
+}
+#endif
+
/* retrive header by rpmdbid, returns 0 if not found, -1 on error */
static int
getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
{
+#if defined(HAVE_RPMDBNEXTITERATORHEADERBLOB) && !defined(ENABLE_RPMPKG_LIBRPM)
+ const unsigned char *uh;
+ unsigned int uhlen;
+#else
Header h;
+#endif
rpmdbMatchIterator mi;
unsigned int offset = rpmdbid;
+ if (rpmdbid <= 0)
+ return pool_error(state->pool, -1, "illegal rpmdbid %d", rpmdbid);
if (state->dbenvopened != 1 && !opendbenv(state))
return -1;
- mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, &offset, sizeof(offset));
+ mi = rpmdbInitIterator(rpmtsGetRdb(state->ts), RPMDBI_PACKAGES, &offset, sizeof(offset));
+#if defined(HAVE_RPMDBNEXTITERATORHEADERBLOB) && !defined(ENABLE_RPMPKG_LIBRPM)
+ uh = rpmdbNextIteratorHeaderBlob(mi, &uhlen);
+ if (!uh)
+ {
+ rpmdbFreeIterator(mi);
+ return 0;
+ }
+ if (!rpm_byrpmhdrblob(state, uh, uhlen))
+ {
+ rpmdbFreeIterator(mi);
+ return -1;
+ }
+#else
h = rpmdbNextIterator(mi);
if (!h)
{
rpmdbFreeIterator(mi);
return -1;
}
+#endif
mi = rpmdbFreeIterator(mi);
- return 1;
+ return rpmdbid;
}
static int
if (state->dbenvopened != 1 && !opendbenv(state))
return 0;
- mi = rpmtsInitIterator(state->ts, RPMDBI_NAME, NULL, 0);
+ mi = rpmdbInitIterator(rpmtsGetRdb(state->ts), RPMDBI_NAME, NULL, 0);
count = rpmdbGetIteratorCount(mi);
rpmdbFreeIterator(mi);
return count;
static int
pkgdb_cursor_open(struct rpmdbstate *state)
{
- state->mi = rpmtsInitIterator(state->ts, RPMDBI_PACKAGES, NULL, 0);
+ state->mi = rpmdbInitIterator(rpmtsGetRdb(state->ts), RPMDBI_PACKAGES, NULL, 0);
return 0;
}
static Id
pkgdb_cursor_getrpm(struct rpmdbstate *state)
{
+#if defined(HAVE_RPMDBNEXTITERATORHEADERBLOB) && !defined(ENABLE_RPMPKG_LIBRPM)
+ const unsigned char *uh;
+ unsigned int uhlen;
+ while ((uh = rpmdbNextIteratorHeaderBlob(state->mi, &uhlen)) != 0)
+ {
+ Id dbid = rpmdbGetIteratorOffset(state->mi);
+ if (!rpm_byrpmhdrblob(state, uh, uhlen))
+ continue;
+ return dbid;
+ }
+#else
Header h;
while ((h = rpmdbNextIterator(state->mi)))
{
continue;
return dbid;
}
+#endif
+ return 0;
+}
+
+static int
+hash_name_index(struct rpmdbstate *state, Chksum *chk)
+{
+ rpmdbIndexIterator ii;
+ const void *key;
+ size_t keylen;
+
+ if (state->dbenvopened != 1 && !opendbenv(state))
+ return -1;
+ ii = rpmdbIndexIteratorInit(rpmtsGetRdb(state->ts), RPMDBI_NAME);
+ if (!ii)
+ return -1;
+ while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
+ {
+ unsigned int i, npkgs = rpmdbIndexIteratorNumPkgs(ii);
+ solv_chksum_add(chk, key, (int)keylen);
+ for (i = 0; i < npkgs; i++)
+ {
+ unsigned int offset = rpmdbIndexIteratorPkgOffset(ii, i);
+ solv_chksum_add(chk, &offset, sizeof(offset));
+ }
+ }
+ rpmdbIndexIteratorFree(ii);
return 0;
}