Imported Upstream version 0.7.12
[platform/upstream/libsolv.git] / ext / repo_rpmdb_librpm.h
index 79983d3..34e6698 100644 (file)
@@ -20,48 +20,85 @@ struct rpmdbstate {
   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();
@@ -82,7 +119,6 @@ opendbenv(struct rpmdbstate *state)
   rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | _RPMVSF_NOHEADER);
   state->ts = ts;
   state->dbenvopened = 1;
-  state->pkgdbopened = 1;
   return 1;
 }
 
@@ -92,22 +128,9 @@ closedbenv(struct rpmdbstate *state)
   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 *
@@ -123,7 +146,6 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
   int nentries = 0;
 
   rpmdbIndexIterator ii;
-  int i;
 
   *nentriesp = 0;
   if (namedatap)
@@ -138,6 +160,7 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
 
   while (rpmdbIndexIteratorNext(ii, &key, &keylen) == 0)
     {
+      unsigned int i, npkgs;
       if (match)
        {
          if (keylen != matchl || memcmp(key, match, keylen) != 0)
@@ -153,7 +176,8 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
          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);
@@ -171,17 +195,41 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
   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)
     {
@@ -193,8 +241,9 @@ getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
       rpmdbFreeIterator(mi);
       return -1;
     }
+#endif
   mi = rpmdbFreeIterator(mi);
-  return 1;
+  return rpmdbid;
 }
 
 static int
@@ -205,7 +254,7 @@ count_headers(struct rpmdbstate *state)
 
   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;
@@ -214,7 +263,7 @@ count_headers(struct rpmdbstate *state)
 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;
 }
 
@@ -228,6 +277,17 @@ pkgdb_cursor_close(struct rpmdbstate *state)
 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)))
     {
@@ -236,6 +296,33 @@ pkgdb_cursor_getrpm(struct rpmdbstate *state)
        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;
 }