char *rootdir;
RpmHead *rpmhead; /* header storage space */
- int rpmheadsize;
+ unsigned int rpmheadsize;
int dbenvopened; /* database environment opened */
- int pkgdbopened; /* package database openend */
- int is_ostree; /* read-only db that lives in /usr/share/rpm */
+ const char *dbpath; /* path to the database */
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_dbpath(struct rpmdbstate *state)
+{
+ state->dbpath = access_rootdir(state, "/var/lib/rpm", W_OK) == -1
+ && access_rootdir(state, "/usr/share/rpm/Packages", R_OK) == 0
+ ? "/usr/share/rpm" : "/var/lib/rpm";
+}
+
static int
-stat_database(struct rpmdbstate *state, char *dbname, struct stat *statbuf, int seterror)
+stat_database(struct rpmdbstate *state, struct stat *statbuf)
{
- char *dbpath;
- dbpath = solv_dupjoin(state->rootdir, state->is_ostree ? "/usr/share/rpm/" : "/var/lib/rpm/", dbname);
- if (stat(dbpath, statbuf))
+ static const char *dbname[] = {
+ "/Packages",
+ "/Packages.db",
+ "/rpmdb.sqlite",
+ "/data.mdb",
+ "/Packages", /* for error reporting */
+ 0,
+ };
+ int i;
+
+#ifdef HAVE_RPMDBFSTAT
+ if (state->dbenvopened == 1)
+ return rpmdbFStat(rpmtsGetRdb(state->ts), statbuf);
+#endif
+ if (!state->dbpath)
+ detect_dbpath(state);
+ for (i = 0; ; i++)
{
- if (seterror)
- pool_error(state->pool, -1, "%s: %s", dbpath, strerror(errno));
- free(dbpath);
- return -1;
+ char *dbpath = solv_dupjoin(state->rootdir, state->dbpath, dbname[i]);
+ if (!stat(dbpath, statbuf))
+ {
+ free(dbpath);
+ return 0;
+ }
+ 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);
}
- free(dbpath);
return 0;
}
static int
opendbenv(struct rpmdbstate *state)
{
- 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");
- }
+
+ if (!state->dbpath)
+ detect_dbpath(state);
+ dbpath = solv_dupjoin("_dbpath ", state->rootdir, state->dbpath);
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 headfromhdrblob(struct rpmdbstate *state, const unsigned char *data, unsigned int size);
+#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 (!headfromhdrblob(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 (!headfromhdrblob(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;
}