Imported Upstream version 0.7.10 upstream/0.7.10
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:44:40 +0000 (14:44 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 27 Nov 2020 05:44:40 +0000 (14:44 +0900)
CMakeLists.txt
NEWS
VERSION.cmake
ext/libsolvext.ver
ext/repo_rpmdb.c
ext/repo_rpmdb.h
ext/repo_rpmdb_bdb.h
ext/repo_rpmdb_librpm.h
package/libsolv.changes

index b39fd99..b7e5d7a 100644 (file)
@@ -238,6 +238,8 @@ IF (ENABLE_RPMDB OR ENABLE_RPMPKG_LIBRPM)
   ENDIF (NOT ENABLE_RPMDB_LIBRPM)
   INCLUDE (CheckLibraryExists)
   CHECK_LIBRARY_EXISTS(rpmio pgpDigGetParams "" HAVE_PGPDIGGETPARAMS)
+  CHECK_LIBRARY_EXISTS(rpm rpmdbNextIteratorHeaderBlob "" HAVE_RPMDBNEXTITERATORHEADERBLOB)
+  CHECK_LIBRARY_EXISTS(rpm rpmdbFStat "" HAVE_RPMDBFSTAT)
 ENDIF (ENABLE_RPMDB OR ENABLE_RPMPKG_LIBRPM)
 
 IF (ENABLE_PUBKEY)
@@ -270,7 +272,8 @@ ENDIF (${CMAKE_MAJOR_VERSION} GREATER 2)
 
 # should create config.h with #cmakedefine instead...
 FOREACH (VAR HAVE_STRCHRNUL HAVE_FOPENCOOKIE HAVE_FUNOPEN WORDS_BIGENDIAN
-  HAVE_RPM_DB_H HAVE_PGPDIGGETPARAMS WITH_LIBXML2 WITHOUT_COOKIEOPEN)
+  HAVE_RPM_DB_H HAVE_PGPDIGGETPARAMS HAVE_RPMDBNEXTITERATORHEADERBLOB HAVE_RPMDBFSTAT
+  WITH_LIBXML2 WITHOUT_COOKIEOPEN)
   IF(${VAR})
     ADD_DEFINITIONS (-D${VAR}=1)
     SET (SWIG_FLAGS ${SWIG_FLAGS} -D${VAR})
diff --git a/NEWS b/NEWS
index ace34bd..ed9be3b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@
 This file contains the major changes between
 libsolv versions:
 
+Version 0.7.10
+- new features:
+  * new rpm_stat_database() function
+  * new rpm_hash_database_state() function
+
 Version 0.7.9
 - new features:
   * support conda constrains dependencies
index 0ec5582..7707dfc 100644 (file)
@@ -49,5 +49,5 @@ SET(LIBSOLVEXT_SOVERSION "1")
 
 SET(LIBSOLV_MAJOR "0")
 SET(LIBSOLV_MINOR "7")
-SET(LIBSOLV_PATCH "9")
+SET(LIBSOLV_PATCH "10")
 
index 02cf6d1..6423837 100644 (file)
@@ -47,10 +47,12 @@ SOLV_1.0 {
                rpm_byfp;
                rpm_byrpmdbid;
                rpm_byrpmh;
+               rpm_hash_database_state;
                rpm_installedrpmdbids;
                rpm_iterate_filelist;
                rpm_query;
                rpm_query_num;
+               rpm_stat_database;
                rpm_state_create;
                rpm_state_free;
                solv_verify_sig;
index e49188d..67aa97c 100644 (file)
@@ -1329,8 +1329,6 @@ freestate(struct rpmdbstate *state)
 {
   /* close down */
 #ifdef ENABLE_RPMDB
-  if (state->pkgdbopened)
-    closepkgdb(state);
   if (state->dbenvopened)
     closedbenv(state);
 #endif
@@ -1624,11 +1622,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);
@@ -2394,6 +2387,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)
 {
index 554d48a..22aab88 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "queue.h"
 #include "repo.h"
+#include "chksum.h"
 
 struct headerToken_s;
 
@@ -39,7 +40,11 @@ extern void *rpm_state_create(Pool *pool, const char *rootdir);
 extern void *rpm_state_free(void *rpmstate);
 
 /* return all matching rpmdbids */
-extern int  rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queue *rpmdbidq);
+extern int rpm_installedrpmdbids(void *rpmstate, const char *index, const char *match, Queue *rpmdbidq);
+/* stat the package database */
+extern int rpm_stat_database(void *rpmstate, void *stb);
+/* hash the state of the package database */
+extern int rpm_hash_database_state(void *rpmstate, Chksum *chk);
 
 /* return handles to a rpm header */
 extern void *rpm_byrpmdbid(void *rpmstate, Id rpmdbid);
index 574e9a8..a8b8500 100644 (file)
@@ -56,11 +56,31 @@ struct rpmdbstate {
 };
 
 
+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)
@@ -75,6 +95,8 @@ stat_database_name(struct rpmdbstate *state, char *dbname, struct stat *statbuf,
 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);
 }
 
@@ -160,6 +182,7 @@ opendbenv(struct rpmdbstate *state)
   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);
@@ -167,7 +190,7 @@ opendbenv(struct rpmdbstate *state)
       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
@@ -209,6 +232,12 @@ closedbenv(struct rpmdbstate *state)
   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)
@@ -264,16 +293,6 @@ openpkgdb(struct rpmdbstate *state)
   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 *
@@ -464,6 +483,8 @@ count_headers(struct rpmdbstate *state)
 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;
@@ -497,3 +518,20 @@ pkgdb_cursor_getrpm(struct rpmdbstate *state)
   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;
+}
+
+
index 6fdcfb0..b50a4b5 100644 (file)
@@ -23,13 +23,32 @@ struct rpmdbstate {
   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)
 {
@@ -43,9 +62,15 @@ 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);
@@ -53,8 +78,10 @@ stat_database(struct rpmdbstate *state, struct stat *statbuf)
        }
       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);
@@ -68,16 +95,8 @@ 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");
-    }
+  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();
@@ -98,7 +117,6 @@ opendbenv(struct rpmdbstate *state)
   rpmtsSetVSFlags(ts, _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | _RPMVSF_NOHEADER);
   state->ts = ts;
   state->dbenvopened = 1;
-  state->pkgdbopened = 1;
   return 1;
 }
 
@@ -108,22 +126,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 *
@@ -139,7 +144,6 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
   int nentries = 0;
 
   rpmdbIndexIterator ii;
-  int i;
 
   *nentriesp = 0;
   if (namedatap)
@@ -154,6 +158,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)
@@ -169,7 +174,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);
@@ -187,17 +193,67 @@ getinstalledrpmdbids(struct rpmdbstate *state, const char *index, const char *ma
   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)
     {
@@ -209,8 +265,9 @@ getrpm_dbid(struct rpmdbstate *state, Id rpmdbid)
       rpmdbFreeIterator(mi);
       return -1;
     }
+#endif
   mi = rpmdbFreeIterator(mi);
-  return 1;
+  return rpmdbid;
 }
 
 static int
@@ -221,7 +278,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;
@@ -230,7 +287,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;
 }
 
@@ -244,6 +301,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 (!rpm_byrpmhdrblob(state, uh, uhlen))
+       continue;
+      return dbid;
+    }
+#else
   Header h;
   while ((h = rpmdbNextIterator(state->mi)))
     {
@@ -252,6 +320,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;
 }
 
index 9ae1511..b638864 100644 (file)
@@ -1,4 +1,11 @@
 -------------------------------------------------------------------
+Tue Dec 10 14:18:36 CET 2019 - mls@suse.de
+
+- added two new function to make libzypp independent of the rpm
+  database format
+- bump version to 0.7.10
+
+-------------------------------------------------------------------
 Thu Nov 21 16:34:52 CET 2019 - mls@suse.de
 
 - support conda constrains dependencies