Deprecate Berkeley DB

This commit is contained in:
panxiaohe 2021-01-11 18:44:49 +08:00
parent 6560e2761e
commit 9aabff85da
33 changed files with 3549 additions and 33 deletions

View File

@ -0,0 +1,164 @@
From 243041f5fb68b68102243d713a1c5a3dc52698a2 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 3 Feb 2020 14:20:19 +0100
Subject: [PATCH] Add a --salvagedb option to the rpmdb tool
URL:https://github.com/rpm-software-management/rpm/commit/243041f5fb68b68102243d713a1c5a3dc52698a2
---
lib/backend/dbi.h | 1 +
lib/backend/ndb/glue.c | 7 +++++--
lib/rpmdb.c | 7 +++++--
lib/rpmdb_internal.h | 8 +++++++-
lib/rpmts.c | 8 ++++++--
rpmdb.c | 6 ++++++
6 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index c4bf387..f70eb33 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -10,6 +10,7 @@ enum rpmdbFlags {
RPMDB_FLAG_JUSTCHECK = (1 << 0),
RPMDB_FLAG_REBUILD = (1 << 1),
RPMDB_FLAG_VERIFYONLY = (1 << 2),
+ RPMDB_FLAG_SALVAGE = (1 << 3),
};
typedef enum dbCtrlOp_e {
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index d19da7c..ae30ceb 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -128,8 +128,11 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
rpmpkgdb pkgdb = 0;
char *path = rstrscat(NULL, dbhome, "/", rdb->db_ops->path, NULL);
rpmlog(RPMLOG_DEBUG, "opening db index %s mode=0x%x\n", path, rdb->db_mode);
- rc = rpmpkgOpen(&pkgdb, path, oflags, 0666);
- if (rc && errno == ENOENT) {
+ if ((rdb->db_flags & RPMDB_FLAG_SALVAGE) == 0)
+ rc = rpmpkgOpen(&pkgdb, path, oflags, 0666);
+ else
+ rc = rpmpkgSalvage(&pkgdb, path);
+ if (rc && errno == ENOENT && (rdb->db_flags & RPMDB_FLAG_SALVAGE) == 0) {
oflags = O_RDWR|O_CREAT;
dbi->dbi_flags |= DBI_CREATED;
rc = rpmpkgOpen(&pkgdb, path, oflags, 0666);
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 91543eb..a072813 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -2479,7 +2479,8 @@ static int rpmdbSetPermissions(char * src, char * dest)
}
int rpmdbRebuild(const char * prefix, rpmts ts,
- rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg))
+ rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg),
+ int rebuildflags)
{
rpmdb olddb;
char * dbpath = NULL;
@@ -2519,7 +2520,9 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
}
if (openDatabase(prefix, dbpath, &olddb,
- O_RDONLY, 0644, RPMDB_FLAG_REBUILD)) {
+ O_RDONLY, 0644, RPMDB_FLAG_REBUILD |
+ (rebuildflags & RPMDB_REBUILD_FLAG_SALVAGE ?
+ RPMDB_FLAG_SALVAGE : 0))) {
rc = 1;
goto exit;
}
diff --git a/lib/rpmdb_internal.h b/lib/rpmdb_internal.h
index 5ad844c..d7446e5 100644
--- a/lib/rpmdb_internal.h
+++ b/lib/rpmdb_internal.h
@@ -23,6 +23,10 @@ extern "C" {
#undef HTKEYTYPE
#undef HTDATATYPE
+enum rpmdbRebuildFlags_e {
+ RPMDB_REBUILD_FLAG_SALVAGE = (1 << 0),
+};
+
/** \ingroup rpmdb
* Reference a database instance.
* @param db rpm database
@@ -63,11 +67,13 @@ int rpmdbClose (rpmdb db);
* @param prefix path to top of install tree
* @param ts transaction set (or NULL)
* @param (*hdrchk) headerCheck() vector (or NULL)
+ * @param rebuildflags flags
* @return 0 on success
*/
RPM_GNUC_INTERNAL
int rpmdbRebuild(const char * prefix, rpmts ts,
- rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg));
+ rpmRC (*hdrchk) (rpmts ts, const void *uh, size_t uc, char ** msg),
+ int rebuildflags);
/** \ingroup rpmdb
* Verify database components.
diff --git a/lib/rpmts.c b/lib/rpmts.c
index d0fdfbe..eb98da7 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -135,17 +135,21 @@ int rpmtsRebuildDB(rpmts ts)
{
int rc = -1;
rpmtxn txn = NULL;
+ int rebuildflags = 0;
/* Cannot do this on a populated transaction set */
if (rpmtsNElements(ts) > 0)
return -1;
+ if (rpmExpandNumeric("%{?_rebuilddb_salvage}"))
+ rebuildflags |= RPMDB_REBUILD_FLAG_SALVAGE;
+
txn = rpmtxnBegin(ts, RPMTXN_WRITE);
if (txn) {
if (!(ts->vsflags & RPMVSF_NOHDRCHK))
- rc = rpmdbRebuild(ts->rootDir, ts, headerCheck);
+ rc = rpmdbRebuild(ts->rootDir, ts, headerCheck, rebuildflags);
else
- rc = rpmdbRebuild(ts->rootDir, NULL, NULL);
+ rc = rpmdbRebuild(ts->rootDir, NULL, NULL, rebuildflags);
rpmtxnEnd(txn);
}
return rc;
diff --git a/rpmdb.c b/rpmdb.c
index 25c088d..b72f0a5 100644
--- a/rpmdb.c
+++ b/rpmdb.c
@@ -12,6 +12,7 @@ enum modes {
MODE_VERIFYDB = (1 << 2),
MODE_EXPORTDB = (1 << 3),
MODE_IMPORTDB = (1 << 4),
+ MODE_SALVAGEDB = (1 << 5),
};
static int mode = 0;
@@ -24,6 +25,8 @@ static struct poptOption dbOptsTable[] = {
NULL},
{ "verifydb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
&mode, MODE_VERIFYDB, N_("verify database files"), NULL},
+ { "salvagedb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR|POPT_ARGFLAG_DOC_HIDDEN),
+ &mode, MODE_SALVAGEDB, N_("salvage database"), NULL},
{ "exportdb", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_EXPORTDB,
N_("export database to stdout header list"),
NULL},
@@ -108,8 +111,11 @@ int main(int argc, char *argv[])
ec = rpmtsInitDB(ts, 0644);
break;
case MODE_REBUILDDB:
+ case MODE_SALVAGEDB:
{ rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
+ if (mode == MODE_SALVAGEDB)
+ rpmDefineMacro(NULL, "_rebuilddb_salvage 1", 0);
ec = rpmtsRebuildDB(ts);
rpmtsSetVSFlags(ts, ovsflags);
} break;
--
1.8.3.1

View File

@ -0,0 +1,33 @@
From de3f36acc91bf13e694bb479e8dbe0502a4cc4e1 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 11:09:29 +0200
Subject: [PATCH] Add an index sync call at the end of a database rebuild
This is normally unneeded because an index sync is already done
after each package is added to the database. But rebuilding an
empty database lead to no index sync being done and a mismatch
between the generation count. This in turn will trigger a
index regeneration.
Found by using ndb when running the test suite.
URL:https://github.com/rpm-software-management/rpm/commit/de3f36acc91bf13e694bb479e8dbe0502a4cc4e1
---
lib/rpmdb.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 57a3c3d..4c10156 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -2578,6 +2578,7 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
}
rpmdbClose(olddb);
+ dbCtrl(newdb, DB_CTRL_INDEXSYNC);
rpmdbClose(newdb);
if (failed) {
--
1.8.3.1

View File

@ -0,0 +1,98 @@
From bc00f99cb0c6bc367bd198b3b0fdc7cd445737c5 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 21 Oct 2019 13:37:22 +0300
Subject: [PATCH] Add backend name and path of main database file to db_ops
struct
URL:https://github.com/rpm-software-management/rpm/commit/bc00f99cb0c6bc367bd198b3b0fdc7cd445737c5
Conflict:delete the contents of lib/backend/sqlite.c, because we have no sqlite database.
---
lib/backend/db3.c | 3 +++
lib/backend/dbi.h | 5 ++++-
lib/backend/dummydb.c | 3 +++
lib/backend/lmdb.c | 3 +++
lib/backend/ndb/glue.c | 3 +++
5 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index ff1fc26..ab2f11f 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -1365,6 +1365,9 @@ static unsigned int db3_pkgdbKey(dbiIndex dbi, dbiCursor dbc)
}
struct rpmdbOps_s db3_dbops = {
+ .name = "bdb",
+ .path = "Packages",
+
.open = db3_dbiOpen,
.close = db3_dbiClose,
.verify = db3_dbiVerify,
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index e9e42d8..a618ea2 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -59,7 +59,7 @@ struct rpmdb_s {
dbiIndex * db_indexes; /*!< Tag indices. */
int db_buildindex; /*!< Index rebuild indicator */
- struct rpmdbOps_s * db_ops; /*!< backend ops */
+ const struct rpmdbOps_s * db_ops; /*!< backend ops */
/* dbenv and related parameters */
void * db_dbenv; /*!< Backend private handle */
@@ -245,6 +245,9 @@ RPM_GNUC_INTERNAL
const void * idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen);
struct rpmdbOps_s {
+ const char *name; /* backend name */
+ const char *path; /* main database name */
+
int (*open)(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags);
int (*close)(dbiIndex dbi, unsigned int flags);
int (*verify)(dbiIndex dbi, unsigned int flags);
diff --git a/lib/backend/dummydb.c b/lib/backend/dummydb.c
index 6137675..631b635 100644
--- a/lib/backend/dummydb.c
+++ b/lib/backend/dummydb.c
@@ -88,6 +88,9 @@ static const void * dummydb_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *
struct rpmdbOps_s dummydb_dbops = {
+ .name = "dummy",
+ .path = NULL,
+
.open = dummydb_Open,
.close = dummydb_Close,
.verify = dummydb_Verify,
diff --git a/lib/backend/lmdb.c b/lib/backend/lmdb.c
index f63fcb7..801f50e 100644
--- a/lib/backend/lmdb.c
+++ b/lib/backend/lmdb.c
@@ -922,6 +922,9 @@ static unsigned int lmdb_pkgdbKey(dbiIndex dbi, dbiCursor dbc)
}
struct rpmdbOps_s lmdb_dbops = {
+ .name = "lmdb",
+ .path = "data.mdb",
+
.open = lmdb_dbiOpen,
.close = lmdb_dbiClose,
.verify = lmdb_dbiVerify,
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index b088a0b..d679ed1 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -496,6 +496,9 @@ static const void * ndb_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keyl
struct rpmdbOps_s ndb_dbops = {
+ .name = "ndb",
+ .path = "Packages.db",
+
.open = ndb_Open,
.close = ndb_Close,
.verify = ndb_Verify,
--
1.8.3.1

View File

@ -0,0 +1,924 @@
From 7cc9eb84a3b2baa0109be599572d78870e0dd3fe Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Thu, 19 Dec 2019 14:08:50 +0100
Subject: [PATCH] Add support for reading BDB without the library
This commit implements a read-only backend that allows accessing
of BerkeleyDB databases without using the BerkeleyDB library.
The code supports btree version 9-10 and hash version 8-10.
There are two use cases for this:
1) Conversion of an existing BerkeleyDB to a different
backend.
2) Allowing package scriptlets to do database queries while
in a transaction that replaced rpm with a version that
no longer links against BerkeleyDB.
If both BerkeleyDB and the read-only backend are enabled, rpm will
default to BerkeleyDB.
URL:https://github.com/rpm-software-management/rpm/commit/7cc9eb84a3b2baa0109be599572d78870e0dd3fe
Conflict:delete the contents of ci/Dockerfile
---
configure.ac | 14 +
lib/Makefile.am | 4 +
lib/backend/bdb_ro.c | 813 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib/backend/dbi.c | 3 +
lib/backend/dbi.h | 5 +
5 files changed, 839 insertions(+)
create mode 100644 lib/backend/bdb_ro.c
diff --git a/configure.ac b/configure.ac
index 2801b13..0257dde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -595,6 +595,20 @@ AS_IF([test "$enable_ndb" = yes],[
AM_CONDITIONAL([NDB], [test "$enable_ndb" = yes])
#=================
+# Process --enable-bdb-ro
+AC_ARG_ENABLE([bdb-ro], [AS_HELP_STRING([--enable-bdb-ro (EXPERIMENTAL)],[enable the read-only Berkeley DB code])],
+[case "$enable_bdb_ro" in
+yes|no) ;;
+*) AC_MSG_ERROR([invalid argument to --enable-bdb-ro])
+ ;;
+esac],
+[enable_bdb_ro=no])
+AS_IF([test "$enable_bdb_ro" = yes],[
+ AC_DEFINE(WITH_BDB_RO, 1, [Build with read-only Berkeley DB])
+])
+AM_CONDITIONAL([BDB_RO], [test "$enable_bdb_ro" = yes])
+
+#=================
# Check for LMDB support
AC_ARG_ENABLE([lmdb],
[AS_HELP_STRING([--enable-lmdb=@<:@yes/no/auto@:>@ (EXPERIMENTAL)],
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 349b5ca..2006d70 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -68,6 +68,10 @@ librpm_la_LIBADD += @WITH_DB_LIB@
endif
endif
+if BDB_RO
+librpm_la_SOURCES += backend/bdb_ro.c
+endif
+
if NDB
librpm_la_SOURCES += \
backend/ndb/glue.c \
diff --git a/lib/backend/bdb_ro.c b/lib/backend/bdb_ro.c
new file mode 100644
index 0000000..74569cb
--- /dev/null
+++ b/lib/backend/bdb_ro.c
@@ -0,0 +1,813 @@
+#include "system.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "lib/rpmdb_internal.h"
+#include <rpm/rpmstring.h>
+#include <rpm/rpmlog.h>
+
+#define BDB_HASH 0
+#define BDB_BTREE 1
+
+struct dbiCursor_s;
+
+struct bdb_kv {
+ unsigned char *kv;
+ unsigned int len;
+};
+
+struct bdb_db {
+ int fd; /* file descriptor of database */
+ int type; /* BDB_HASH / BDB_BTREE */
+ unsigned int pagesize;
+ unsigned int lastpage;
+ int swapped; /* different endianess? */
+ /* btree */
+ unsigned int root; /* root page of the b-tree */
+ /* hash */
+ unsigned int maxbucket;
+ unsigned int highmask;
+ unsigned int lowmask;
+ unsigned int spares[32]; /* spare pages for each splitpoint */
+};
+
+struct bdb_cur {
+ struct bdb_db *db;
+
+ struct bdb_kv key; /* key and value from the db entry */
+ struct bdb_kv val;
+
+ unsigned char *page; /* the page we're looking at */
+
+ unsigned char *ovpage;
+ struct bdb_kv keyov; /* space to store oversized keys/values */
+ struct bdb_kv valov;
+
+ int state; /* 1: onpage, -1: error */
+ int idx; /* entry index */
+ int numidx; /* number of entries on the page */
+ int islookup; /* we're doing a lookup operation */
+
+ /* hash */
+ unsigned int bucket; /* current bucket */
+};
+
+
+static void swap16(unsigned char *p)
+{
+ int a = p[0];
+ p[0] = p[1];
+ p[1] = a;
+}
+
+static void swap32(unsigned char *p)
+{
+ int a = p[0];
+ p[0] = p[3];
+ p[3] = a;
+ a = p[1];
+ p[1] = p[2];
+ p[2] = a;
+}
+
+static void swap32_2(unsigned char *p)
+{
+ swap32(p);
+ swap32(p + 4);
+}
+
+static void bdb_swapmetapage(struct bdb_db *db, unsigned char *page)
+{
+ int i, maxi = db->type == BDB_HASH ? 224 : 92;
+ for (i = 8; i < maxi; i += 4)
+ swap32((unsigned char *)(page + i));
+ swap32((unsigned char *)(page + 24));
+}
+
+static void bdb_swappage(struct bdb_db *db, unsigned char *page)
+{
+ unsigned int pagesize = db->pagesize;
+ int type, i, nent, off;
+ swap32(page + 8); /* page number */
+ swap32_2(page + 12); /* prev/next page */
+ swap16(page + 20); /* nitems */
+ swap16(page + 22); /* highfree */
+
+ type = page[25];
+ if (type != 2 && type != 13 && type != 3 && type != 5)
+ return;
+ nent = *(uint16_t *)(page + 20);
+ if (nent > (pagesize - 26) / 2)
+ nent = (pagesize - 26) / 2;
+ for (i = 0; i < nent; i++) {
+ int minoff = 26 + nent * 2;
+ swap16(page + 26 + i * 2); /* offset */
+ off = *(uint16_t *)(page + 26 + i * 2);
+ if (off < minoff || off >= pagesize)
+ continue;
+ if (type == 2 || type == 13) { /* hash */
+ if (page[off] == 3 && off + 12 <= pagesize)
+ swap32_2(page + off + 4); /* page no/length */
+ } else if (type == 3) { /* btree internal */
+ if (off + 12 > pagesize)
+ continue;
+ swap16(page + off); /* length */
+ swap32_2(page + off + 4); /* page no/num recs */
+ if (page[off + 2] == 3 && off + 24 <= pagesize)
+ swap32_2(page + off + 16); /* with overflow page/length */
+ } else if (type == 5) { /* btree leaf */
+ if (off + 3 <= pagesize && page[off + 2] == 1)
+ swap16(page + off); /* length */
+ else if (off + 12 <= pagesize && page[off + 2] == 3)
+ swap32_2(page + off + 4); /* overflow page/length */
+ }
+ }
+}
+
+static int bdb_getpage(struct bdb_db *db, unsigned char *page, unsigned int pageno)
+{
+ if (!pageno || pageno > db->lastpage)
+ return -1;
+ if (pread(db->fd, page, db->pagesize, (off_t)pageno * db->pagesize) != db->pagesize) {
+ rpmlog(RPMLOG_ERR, "pread: %s\n", strerror(errno));
+ return -1;
+ }
+ if (db->swapped)
+ bdb_swappage(db, page);
+ if (pageno != *(uint32_t *)(page + 8))
+ return -1;
+ return 0;
+}
+
+static void bdb_close(struct bdb_db *db)
+{
+ if (db->fd >= 0)
+ close(db->fd);
+ free(db);
+}
+
+static struct bdb_db *bdb_open(const char *name)
+{
+ uint32_t meta[512 / 4];
+ int i, fd;
+ struct bdb_db *db;
+
+ fd = open(name, O_RDONLY);
+ if (!fd) {
+ rpmlog(RPMLOG_ERR, "%s: %s\n", name, strerror(errno));
+ return NULL;
+ }
+ db = xcalloc(1, sizeof(*db));
+ db->fd = fd;
+ if (pread(fd, meta, 512, 0) != 512) {
+ rpmlog(RPMLOG_ERR, "%s: pread: %s\n", name, strerror(errno));
+ bdb_close(db);
+ return NULL;
+ }
+ if (meta[3] == 0x00061561 || meta[3] == 0x61150600) {
+ db->type = BDB_HASH;
+ db->swapped = meta[3] == 0x61150600;
+ } else if (meta[3] == 0x00053162 || meta[3] == 0x62310500) {
+ db->type = BDB_BTREE;
+ db->swapped = meta[3] == 0x62310500;
+ } else {
+ rpmlog(RPMLOG_ERR, "%s: not a berkeley db hash/btree database\n", name);
+ bdb_close(db);
+ return NULL;
+ }
+ if (db->swapped)
+ bdb_swapmetapage(db, (unsigned char *)meta);
+ db->pagesize = meta[5];
+ db->lastpage = meta[8];
+ if (db->type == BDB_HASH) {
+ if (meta[4] < 8 || meta[4] > 10) {
+ rpmlog(RPMLOG_ERR, "%s: unsupported hash version %d\n", name, meta[4]);
+ bdb_close(db);
+ return NULL;
+ }
+ db->maxbucket = meta[18];
+ db->highmask = meta[19];
+ db->lowmask = meta[20];
+ for (i = 0; i < 32; i++)
+ db->spares[i] = meta[24 + i];
+ }
+ if (db->type == BDB_BTREE) {
+ if (meta[4] < 9 || meta[4] > 10) {
+ rpmlog(RPMLOG_ERR, "%s: unsupported btree version %d\n", name, meta[4]);
+ bdb_close(db);
+ return NULL;
+ }
+ db->root = meta[22];
+ }
+ return db;
+}
+
+
+/****** overflow handling ******/
+
+static int ovfl_get(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, uint32_t *pagenolen)
+{
+ unsigned int pageno = pagenolen[0];
+ unsigned int len = pagenolen[1];
+ unsigned int plen;
+ unsigned char *p;
+
+ if (len == 0)
+ return -1;
+ if (len > ov->len) {
+ if (ov->kv)
+ ov->kv = xrealloc(ov->kv, len);
+ else
+ ov->kv = xmalloc(len);
+ ov->len = len;
+ }
+ if (!cur->ovpage)
+ cur->ovpage = xmalloc(cur->db->pagesize);
+ p = ov->kv;
+ while (len > 0) {
+ if (bdb_getpage(cur->db, cur->ovpage, pageno))
+ return -1;
+ if (cur->ovpage[25] != 7)
+ return -1;
+ plen = *(uint16_t *)(cur->ovpage + 22);
+ if (plen + 26 > cur->db->pagesize || plen > len)
+ return -1;
+ memcpy(p, cur->ovpage + 26, plen);
+ p += plen;
+ len -= plen;
+ pageno = *(uint32_t *)(cur->ovpage + 16);
+ }
+ if (kv) {
+ kv->kv = ov->kv;
+ kv->len = pagenolen[1];
+ }
+ return 0;
+}
+
+
+/****** hash implementation ******/
+
+static int hash_bucket_to_page(struct bdb_db *db, unsigned int bucket)
+{
+ unsigned int b;
+ int i = 0;
+ for (b = bucket; b; b >>= 1)
+ i++;
+ return bucket + db->spares[i];
+}
+
+static int hash_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl)
+{
+ uint32_t bucket;
+ unsigned int pg, i;
+ cur->state = -1;
+ for (bucket = 0, i = 0; i < keyl; i++)
+ bucket = (bucket * 16777619) ^ key[i];
+ bucket &= cur->db->highmask;
+ if (bucket > cur->db->maxbucket)
+ bucket &= cur->db->lowmask;
+ cur->bucket = bucket;
+ pg = hash_bucket_to_page(cur->db, bucket);
+ if (bdb_getpage(cur->db, cur->page, pg))
+ return -1;
+ if (cur->page[25] != 8 && cur->page[25] != 13)
+ return -1;
+ cur->idx = (unsigned int)-2;
+ cur->numidx = *(uint16_t *)(cur->page + 20);
+ cur->state = 1;
+ return 0;
+}
+
+static int hash_getkv(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, int off, int len)
+{
+ if (len <= 0 || off + len > cur->db->pagesize)
+ return -1;
+ if (cur->page[off] == 1) {
+ kv->kv = cur->page + off + 1;
+ kv->len = len - 1;
+ } else if (cur->page[off] == 3) {
+ uint32_t ovlpage[2];
+ if (len != 12)
+ return -1;
+ memcpy(ovlpage, cur->page + off + 4, 8); /* off is unaligned */
+ if (ovfl_get(cur, kv, ov, ovlpage))
+ return -1;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int hash_next(struct bdb_cur *cur)
+{
+ int pagesize = cur->db->pagesize;
+ int koff, klen, voff, vlen;
+ if (!cur->state && hash_lookup(cur, 0, 0))
+ return -1;
+ cur->idx += 2;
+ for (;;) {
+ if (cur->idx + 1 >= cur->numidx) {
+ unsigned int pg;
+ cur->idx = cur->numidx = 0;
+ pg = *(uint32_t *)(cur->page + 16);
+ if (!pg) {
+ if (cur->islookup || cur->bucket >= cur->db->maxbucket)
+ return 1;
+ pg = hash_bucket_to_page(cur->db, ++cur->bucket);
+ }
+ if (bdb_getpage(cur->db, cur->page, pg))
+ return -1;
+ if (cur->page[25] != 8 && cur->page[25] != 13)
+ return -1;
+ cur->numidx = *(uint16_t *)(cur->page + 20);
+ continue;
+ }
+ koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx);
+ voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx);
+ if (koff >= pagesize || voff >= pagesize)
+ return -1;
+ if (cur->idx == 0)
+ klen = pagesize - koff;
+ else
+ klen = *(uint16_t *)(cur->page + 24 + 2 * cur->idx) - koff;
+ vlen = koff - voff;
+ if (hash_getkv(cur, &cur->key, &cur->keyov, koff, klen))
+ return -1;
+ if (!cur->islookup && hash_getkv(cur, &cur->val, &cur->valov, voff, vlen))
+ return -1;
+ return 0;
+ }
+}
+
+static int hash_getval(struct bdb_cur *cur)
+{
+ int koff, voff;
+ if (cur->state != 1 || cur->idx + 1 >= cur->numidx)
+ return -1;
+ koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx);
+ voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx);
+ return hash_getkv(cur, &cur->val, &cur->valov, voff, koff - voff);
+}
+
+
+/****** btree implementation ******/
+
+static int btree_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keylen)
+{
+ int pagesize = cur->db->pagesize;
+ int off, lastoff, idx, numidx;
+ unsigned int pg;
+ unsigned char *ekey;
+ unsigned int ekeylen;
+ int cmp;
+
+ cur->state = -1;
+ pg = cur->db->root;
+ for (;;) {
+ if (bdb_getpage(cur->db, cur->page, pg))
+ return -1;
+ if (cur->page[25] == 5)
+ break; /* found leaf page */
+ if (cur->page[25] != 3)
+ return -1;
+ numidx = *(uint16_t *)(cur->page + 20);
+ if (!numidx)
+ return -1;
+ for (lastoff = 0, idx = 0; idx < numidx; idx++, lastoff = off) {
+ off = *(uint16_t *)(cur->page + 26 + 2 * idx);
+ if ((off & 3) != 0 || off + 3 > pagesize)
+ return -1;
+ ekeylen = *(uint16_t *)(cur->page + off);
+ if (off + 12 + ekeylen > pagesize)
+ return -1;
+ if (!keylen) {
+ lastoff = off;
+ break;
+ }
+ if (idx == 0)
+ continue;
+ ekey = cur->page + off + 12;
+ if ((cur->page[off + 2] & 0x7f) == 3) {
+ if (ekeylen != 12)
+ return -1;
+ if (ovfl_get(cur, 0, &cur->keyov, (uint32_t *)(ekey + 4)))
+ return -1;
+ ekeylen = *(uint32_t *)(ekey + 8);
+ ekey = cur->keyov.kv;
+ } else if ((cur->page[off + 2] & 0x7f) != 1) {
+ return -1;
+ }
+ cmp = memcmp(ekey, key, keylen < ekeylen ? keylen : ekeylen);
+ if (cmp > 0 || (cmp == 0 && ekeylen > keylen))
+ break;
+ }
+ pg = *(uint32_t *)(cur->page + lastoff + 4);
+ }
+ cur->idx = (unsigned int)-2;
+ cur->numidx = *(uint16_t *)(cur->page + 20);
+ cur->state = 1;
+ return 0;
+}
+
+static int btree_getkv(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, int off)
+{
+ if ((off & 3) != 0)
+ return -1;
+ if (cur->page[off + 2] == 1) {
+ int len = *(uint16_t *)(cur->page + off);
+ if (off + 3 + len > cur->db->pagesize)
+ return -1;
+ kv->kv = cur->page + off + 3;
+ kv->len = len;
+ } else if (cur->page[off + 2] == 3) {
+ if (off + 12 > cur->db->pagesize)
+ return -1;
+ if (ovfl_get(cur, kv, ov, (uint32_t *)(cur->page + off + 4)))
+ return -1;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+static int btree_next(struct bdb_cur *cur)
+{
+ int pagesize = cur->db->pagesize;
+ int koff, voff;
+ if (!cur->state && btree_lookup(cur, 0, 0))
+ return -1;
+ cur->idx += 2;
+ for (;;) {
+ if (cur->idx + 1 >= cur->numidx) {
+ unsigned int pg;
+ cur->idx = cur->numidx = 0;
+ pg = *(uint32_t *)(cur->page + 16);
+ if (cur->islookup || !pg)
+ return 1;
+ if (bdb_getpage(cur->db, cur->page, pg))
+ return -1;
+ if (cur->page[25] != 5)
+ return -1;
+ cur->numidx = *(uint16_t *)(cur->page + 20);
+ continue;
+ }
+ koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx);
+ voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx);
+ if (koff + 3 > pagesize || voff + 3 > pagesize)
+ return -1;
+ if ((cur->page[koff + 2] & 0x80) != 0 || (cur->page[voff + 2] & 0x80) != 0)
+ continue; /* ignore deleted */
+ if (btree_getkv(cur, &cur->key, &cur->keyov, koff))
+ return -1;
+ if (!cur->islookup && btree_getkv(cur, &cur->val, &cur->valov, voff))
+ return -1;
+ return 0;
+ }
+}
+
+static int btree_getval(struct bdb_cur *cur)
+{
+ int voff;
+ if (cur->state != 1 || cur->idx + 1 >= cur->numidx)
+ return -1;
+ voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx);
+ return btree_getkv(cur, &cur->val, &cur->valov, voff);
+}
+
+
+/****** cursor functions ******/
+
+static struct bdb_cur *cur_open(struct bdb_db *db)
+{
+ struct bdb_cur *cur = xcalloc(1, sizeof(*cur));
+ cur->db = db;
+ cur->page = xmalloc(db->pagesize);
+ return cur;
+}
+
+static void cur_close(struct bdb_cur *cur)
+{
+ if (cur->page)
+ free(cur->page);
+ if (cur->ovpage)
+ free(cur->ovpage);
+ if (cur->keyov.kv)
+ free(cur->keyov.kv);
+ if (cur->valov.kv)
+ free(cur->valov.kv);
+ free(cur);
+}
+
+static int cur_next(struct bdb_cur *cur)
+{
+ if (cur->state < 0)
+ return -1;
+ if (cur->db->type == BDB_HASH)
+ return hash_next(cur);
+ if (cur->db->type == BDB_BTREE)
+ return btree_next(cur);
+ return -1;
+}
+
+static int cur_getval(struct bdb_cur *cur)
+{
+ if (cur->state < 0)
+ return -1;
+ if (cur->db->type == BDB_HASH)
+ return hash_getval(cur);
+ if (cur->db->type == BDB_BTREE)
+ return btree_getval(cur);
+ return -1;
+}
+
+static int cur_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl)
+{
+ int r = -1;
+ if (cur->db->type == BDB_HASH)
+ r = hash_lookup(cur, key, keyl);
+ if (cur->db->type == BDB_BTREE)
+ r = btree_lookup(cur, key, keyl);
+ if (r != 0)
+ return r;
+ cur->islookup = 1;
+ while ((r = cur_next(cur)) == 0)
+ if (keyl == cur->key.len && !memcmp(key, cur->key.kv, keyl))
+ break;
+ cur->islookup = 0;
+ if (r == 0)
+ r = cur_getval(cur);
+ return r;
+}
+
+static int cur_lookup_ge(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl)
+{
+ int r = -1;
+ if (cur->db->type == BDB_BTREE)
+ r = btree_lookup(cur, key, keyl);
+ if (r != 0)
+ return r;
+ cur->islookup = 1;
+ while ((r = cur_next(cur)) == 0) {
+ unsigned int ekeyl = cur->key.len;
+ int cmp = memcmp(cur->key.kv, key, keyl < ekeyl ? keyl : ekeyl);
+ if (cmp > 0 || (cmp == 0 && ekeyl >= keyl))
+ break;
+ }
+ cur->islookup = 0;
+ if (r == 0)
+ r = cur_getval(cur);
+ else if (r == 1)
+ r = cur_next(cur);
+ return r;
+}
+
+/****** glue code ******/
+
+static unsigned int getui32(unsigned char *x, int swapped)
+{
+ union _dbswap bs;
+ memcpy(bs.uc, x, 4);
+ if (swapped)
+ _DBSWAP(bs);
+ return bs.ui;
+}
+
+static void setui32(unsigned char *x, uint32_t v, int swapped)
+{
+ union _dbswap bs;
+ bs.ui = v;
+ if (swapped)
+ _DBSWAP(bs);
+ memcpy(x, bs.uc, 4);
+}
+
+static void log_error(dbiIndex dbi)
+{
+ rpmlog(RPMLOG_ERR, "bdb_ro error reading %s database\n", dbi->dbi_file);
+}
+
+static int bdbro_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
+{
+ const char *dbhome = rpmdbHome(rdb);
+ dbiIndex dbi = NULL;
+ char *path;
+
+ if (dbip)
+ *dbip = NULL;
+ if ((rdb->db_mode & O_ACCMODE) != O_RDONLY)
+ return EPERM;
+ if ((dbi = dbiNew(rdb, rpmtag)) == NULL)
+ return 1;
+ path = rstrscat(NULL, dbhome, "/", dbi->dbi_file, NULL);
+ rpmlog(RPMLOG_DEBUG, "opening db index %s\n", path);
+ dbi->dbi_db = bdb_open(path);
+ if (!dbi->dbi_db) {
+ rpmlog(RPMLOG_ERR, "could not open %s: %s\n", path, strerror(errno));
+ free(path);
+ dbiFree(dbi);
+ return 1;
+ }
+ free(path);
+ dbi->dbi_flags |= DBI_RDONLY;
+ if (dbip)
+ *dbip = dbi;
+ else
+ (void) dbiClose(dbi, 0);
+ return 0;
+}
+
+static int bdbro_Close(dbiIndex dbi, unsigned int flags)
+{
+ if (dbi->dbi_db)
+ bdb_close(dbi->dbi_db);
+ dbiFree(dbi);
+ return 0;
+}
+
+static int bdbro_Verify(dbiIndex dbi, unsigned int flags)
+{
+ return 0;
+}
+
+static void bdbro_SetFSync(rpmdb rdb, int enable)
+{
+}
+
+static int bdbro_Ctrl(rpmdb rdb, dbCtrlOp ctrl)
+{
+ return 0;
+}
+
+static dbiCursor bdbro_CursorInit(dbiIndex dbi, unsigned int flags)
+{
+ return dbi ? (void *)cur_open(dbi->dbi_db) : NULL;
+}
+
+static dbiCursor bdbro_CursorFree(dbiIndex dbi, dbiCursor dbc)
+{
+ if (dbc)
+ cur_close((void *)dbc);
+ return NULL;
+}
+
+static void appenddbt(dbiCursor dbc, unsigned char *val, unsigned int vallen, dbiIndexSet *setp)
+{
+ struct bdb_cur *cur = (void *)dbc;
+ dbiIndexSet set;
+ unsigned int i;
+
+ set = dbiIndexSetNew(vallen / (2 * sizeof(uint32_t)));
+ set->count = vallen / (2 * sizeof(uint32_t));
+
+ for (i = 0; i < set->count; i++, val += 8) {
+ set->recs[i].hdrNum = getui32(val, cur->db->swapped);
+ set->recs[i].tagNum = getui32(val + 4, cur->db->swapped);
+ }
+ if (*setp == NULL) {
+ *setp = set;
+ } else {
+ dbiIndexSetAppendSet(*setp, set, 0);
+ dbiIndexSetFree(set);
+ }
+}
+
+static rpmRC bdbro_idxdbPut(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC bdbro_idxdbDel(dbiIndex dbi, rpmTagVal rpmtag, unsigned int hdrNum, Header h)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC bdbro_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen,
+ dbiIndexSet *set, int searchType)
+{
+ struct bdb_cur *cur = (void *)dbc;
+ int r;
+
+ if (!cur)
+ return RPMRC_FAIL;
+ if (searchType == DBC_PREFIX_SEARCH) {
+ rpmRC rc = RPMRC_NOTFOUND;
+ if (!keyp)
+ return RPMRC_FAIL;
+ r = cur_lookup_ge(cur, (const unsigned char *)keyp, keylen);
+ for (; r == 0; r = cur_next(cur)) {
+ if (cur->key.len < keylen || memcmp(cur->key.kv, keyp, keylen) != 0)
+ break;
+ if (set)
+ appenddbt(dbc, cur->val.kv, cur->val.len, set);
+ rc = RPMRC_OK;
+ }
+ if (r == -1)
+ log_error(dbi);
+ cur->key.kv = 0;
+ return r == -1 ? RPMRC_FAIL : rc;
+ }
+ if (keyp) {
+ if (keylen == 0) {
+ keyp = "";
+ keylen = 1;
+ }
+ r = cur_lookup(cur, (const unsigned char *)keyp, keylen);
+ } else {
+ r = cur_next(cur);
+ }
+ if (r == 0) {
+ if (set)
+ appenddbt(dbc, cur->val.kv, cur->val.len, set);
+ return RPMRC_OK;
+ }
+ if (r == -1)
+ log_error(dbi);
+ cur->key.kv = 0;
+ return r == 1 ? RPMRC_NOTFOUND : RPMRC_FAIL;
+}
+
+static const void *bdbro_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen)
+{
+ struct bdb_cur *cur = (void *)dbc;
+ if (!cur || !cur->key.kv)
+ return 0;
+ if (keylen)
+ *keylen = cur->key.len;
+ return cur->key.kv;
+}
+
+static rpmRC bdbro_pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum,
+ unsigned char *hdrBlob, unsigned int hdrLen)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC bdbro_pkgdbDel(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC bdbro_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum,
+ unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ struct bdb_cur *cur = (void *)dbc;
+ int r;
+ if (hdrNum) {
+ unsigned char hdrkey[4];
+ setui32(hdrkey, hdrNum, cur->db->swapped);
+ r = cur_lookup(cur, hdrkey, 4);
+ } else {
+ r = cur_next(cur);
+ }
+ if (r == 0) {
+ if (hdrBlob)
+ *hdrBlob = cur->val.kv;
+ if (hdrLen)
+ *hdrLen = cur->val.len;
+ return RPMRC_OK;
+ }
+ if (r == -1)
+ log_error(dbi);
+ cur->key.kv = 0;
+ return r == 1 ? RPMRC_NOTFOUND : RPMRC_FAIL;
+}
+
+static unsigned int bdbro_pkgdbKey(dbiIndex dbi, dbiCursor dbc)
+{
+ struct bdb_cur *cur = (void *)dbc;
+ if (!cur || !cur->key.kv || cur->key.len != 4)
+ return 0;
+ return getui32(cur->key.kv, cur->db->swapped);
+}
+
+struct rpmdbOps_s bdbro_dbops = {
+ .name = "bdb_ro",
+ .path = "Packages",
+
+ .open = bdbro_Open,
+ .close = bdbro_Close,
+ .verify = bdbro_Verify,
+ .setFSync = bdbro_SetFSync,
+ .ctrl = bdbro_Ctrl,
+
+ .cursorInit = bdbro_CursorInit,
+ .cursorFree = bdbro_CursorFree,
+
+ .pkgdbPut = bdbro_pkgdbPut,
+ .pkgdbDel = bdbro_pkgdbDel,
+ .pkgdbGet = bdbro_pkgdbGet,
+ .pkgdbKey = bdbro_pkgdbKey,
+
+ .idxdbGet = bdbro_idxdbGet,
+ .idxdbPut = bdbro_idxdbPut,
+ .idxdbDel = bdbro_idxdbDel,
+ .idxdbKey = bdbro_idxdbKey
+};
+
diff --git a/lib/backend/dbi.c b/lib/backend/dbi.c
index 9b6c0a9..7841440 100644
--- a/lib/backend/dbi.c
+++ b/lib/backend/dbi.c
@@ -25,6 +25,9 @@ const struct rpmdbOps_s *backends[] = {
#if defined(WITH_BDB)
&db3_dbops,
#endif
+#if defined(WITH_BDB_RO)
+ &bdbro_dbops,
+#endif
&dummydb_dbops,
NULL
};
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index b2b9717..c4bf387 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -274,6 +274,11 @@ RPM_GNUC_INTERNAL
extern struct rpmdbOps_s db3_dbops;
#endif
+#if defined(WITH_BDB_RO)
+RPM_GNUC_INTERNAL
+extern struct rpmdbOps_s bdbro_dbops;
+#endif
+
#ifdef ENABLE_NDB
RPM_GNUC_INTERNAL
extern struct rpmdbOps_s ndb_dbops;
--
1.8.3.1

View File

@ -0,0 +1,107 @@
From 8cd161b5bb9b639f5b729063272115436caab545 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 12 Mar 2020 11:42:15 +0200
Subject: [PATCH] Always open (and initialize) the entire database at once
In some scenarios we previously only created some of the indexes only
lazy db init through query. Partially initialized databases don't make
sense and are only asking for trouble, in particular this was causing
issues with sqlite backend which is stricter about readonly-mode.
Except for the special case of reading a potentially damaged database
for rebuilding, always open all the indexes from openDatabase().
URL:https://github.com/rpm-software-management/rpm/commit/8cd161b5bb9b639f5b729063272115436caab545
Conflict:context adaptation about openDatabase
---
lib/rpmdb.c | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index c5d8f49..073800b 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -357,17 +357,22 @@ const char *rpmdbHome(rpmdb db)
return dbdir;
}
-int rpmdbOpenAll(rpmdb db)
+static int doOpen(rpmdb db, int justPkgs)
{
- int rc = 0;
+ int rc = pkgdbOpen(db, db->db_flags, NULL);
+ if (!justPkgs) {
+ for (int dbix = 0; dbix < db->db_ndbi; dbix++) {
+ rc += indexOpen(db, db->db_tags[dbix], db->db_flags, NULL);
+ }
+ }
+ return rc;
+}
+int rpmdbOpenAll(rpmdb db)
+{
if (db == NULL) return -2;
- rc = pkgdbOpen(db, db->db_flags, NULL);
- for (int dbix = 0; dbix < db->db_ndbi; dbix++) {
- rc += indexOpen(db, db->db_tags[dbix], db->db_flags, NULL);
- }
- return rc;
+ return doOpen(db, 0);
}
static int dbiForeach(dbiIndex *dbis, int ndbi,
@@ -510,13 +515,16 @@ static int openDatabase(const char * prefix,
/* Try to ensure db home exists, error out if we can't even create */
rc = rpmioMkpath(rpmdbHome(db), 0755, getuid(), getgid());
if (rc == 0) {
+ /* Open just bare minimum when rebuilding a potentially damaged db */
+ int justPkgs = (db->db_flags & RPMDB_FLAG_REBUILD) &&
+ ((db->db_mode & O_ACCMODE) == O_RDONLY);
/* Enable signal queue on the first db open */
if (db->db_next == NULL) {
rpmsqActivate(1);
}
- /* Just the primary Packages database opened here */
- rc = pkgdbOpen(db, db->db_flags, NULL);
+ rc = doOpen(db, justPkgs);
+
}
if (rc || justCheck || dbp == NULL)
@@ -554,10 +562,7 @@ int rpmdbInit (const char * prefix, int perms)
rc = openDatabase(prefix, NULL, &db, (O_CREAT | O_RDWR), perms, 0);
if (db != NULL) {
- int xx;
- xx = rpmdbOpenAll(db);
- if (xx && rc == 0) rc = xx;
- xx = rpmdbClose(db);
+ int xx = rpmdbClose(db);
if (xx && rc == 0) rc = xx;
db = NULL;
}
@@ -573,8 +578,6 @@ int rpmdbVerify(const char * prefix)
if (db != NULL) {
int xx;
- rc = rpmdbOpenAll(db);
-
if (db->db_pkgs)
rc += dbiVerify(db->db_pkgs, 0);
@@ -2551,10 +2554,6 @@ int rpmdbRebuild(const char * prefix, rpmts ts,
rc = 1;
goto exit;
}
- if (rpmdbOpenAll(newdb)) {
- rc = 1;
- goto exit;
- }
{ Header h = NULL;
rpmdbMatchIterator mi;
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From fc0169eb03c893d63dc44f2ada954d42e0e759ed Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 23 Mar 2020 11:22:31 +0200
Subject: [PATCH] Deprecate Berkeley DB database backend
Berkeley DB 5.x is dead upstream ever since the license change some
seven years ago. Mark as deprecated for later removal now that we're
starting to have viable alternatives.
URL:https://github.com/rpm-software-management/rpm/commit/fc0169eb03c893d63dc44f2ada954d42e0e759ed
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index d5ce5ef..bdfe2c6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -533,7 +533,7 @@ AM_CONDITIONAL(HAVE_LIBDW_STRTAB,[test "$HAVE_LIBDW_STRTAB" = yes])
#=================
# Check for BDB support
AC_ARG_ENABLE([bdb],
- [AS_HELP_STRING([--enable-bdb=@<:@yes/no/auto@:>@],
+ [AS_HELP_STRING([--enable-bdb=@<:@yes/no/auto@:>@ (DEPRECATED)],
[build with Berkeley DB rpm database format support (default=yes)])],
[enable_bdb="$enableval"],
[enable_bdb=yes])
--
1.8.3.1

View File

@ -0,0 +1,33 @@
From 4c7323f69b4fddf928245e9db2d1c9ca9b277ef2 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Wed, 18 Dec 2019 17:42:31 +0100
Subject: [PATCH] Fix building with no BerkeleyDB support
The configure script used to define BDB even if BerkeleyDB has
been disabled.
URL:https://github.com/rpm-software-management/rpm/commit/4c7323f69b4fddf928245e9db2d1c9ca9b277ef2
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index de6034c..7a90b2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -544,11 +544,11 @@ AC_ARG_ENABLE([bdb],
[enable_bdb="$enableval"],
[enable_bdb=yes])
+have_bdb="no"
AS_IF([test "x$enable_bdb" != "xno"], [
if [ test -x db/dist/configure ]; then
have_bdb="internal"
else
- have_bdb="no"
AC_CHECK_HEADERS([db.h],[
AC_PREPROC_IFELSE([
AC_LANG_SOURCE([
--
1.8.3.1

View File

@ -0,0 +1,143 @@
From 7630389dcd3494c13b74b119cca37f97d2d8445a Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 30 Mar 2020 11:29:19 +0300
Subject: [PATCH] Flush 1998 vintage dirent.h compatibility mess from system.h
dirent.h and struct dirent are actually standard on this millenium, the
only thing that isn't is d_type member for which we have and retain
a specific test in configure.ac. Include <dirent.h> where needed,
relatively few places do which makes it even a bigger insult to have
this included from system.h.
URL:https://github.com/rpm-software-management/rpm/commit/7630389dcd3494c13b74b119cca37f97d2d8445a
---
lib/backend/ndb/rpmpkg.c | 1 +
lib/backend/ndb/rpmxdb.c | 1 +
lib/rpmdb.c | 1 +
misc/fts.c | 1 +
rpmio/rpmglob.c | 5 ++---
rpmio/rpmio.c | 1 +
system.h | 17 -----------------
7 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index b9cd67c..64d0493 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -11,6 +11,7 @@
#include <string.h>
#include <stdlib.h>
#include <libgen.h>
+#include <dirent.h>
#include "rpmpkg.h"
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index dbd4942..5136fbc 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -16,6 +16,7 @@
#include <sys/mman.h>
#include <endian.h>
#include <libgen.h>
+#include <dirent.h>
#include "rpmxdb.h"
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 3035e63..57a3c3d 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -7,6 +7,7 @@
#include <sys/file.h>
#include <utime.h>
#include <errno.h>
+#include <dirent.h>
#ifndef DYING /* XXX already in "system.h" */
#include <fnmatch.h>
diff --git a/misc/fts.c b/misc/fts.c
index 5c6f53d..b43f261 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -68,6 +68,7 @@ static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
#include "system.h"
#include <stdlib.h>
#include <string.h>
+#include <dirent.h>
#include <errno.h>
#include "misc/rpmfts.h"
# define __set_errno(val) (*__errno_location ()) = (val)
diff --git a/rpmio/rpmglob.c b/rpmio/rpmglob.c
index 3c497cb..93f7fa5 100644
--- a/rpmio/rpmglob.c
+++ b/rpmio/rpmglob.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include <dirent.h>
#include <pwd.h>
#include <assert.h>
#include <sys/stat.h> /* S_ISDIR */
@@ -75,8 +76,6 @@ typedef struct {
int (*gl_stat)(const char *, struct stat *);
} glob_t;
-#define NAMLEN(_d) NLENGTH(_d)
-
#include <errno.h>
#ifndef __set_errno
#define __set_errno(val) errno = (val)
@@ -746,7 +745,7 @@ glob_in_dir(const char *pattern, const char *directory, int flags,
if (fnmatch(pattern, name, fnm_flags) == 0) {
struct globlink *new = (struct globlink *)
alloca(sizeof(struct globlink));
- len = NAMLEN(d);
+ len = strlen(d->d_name);
new->name = (char *) xmalloc(len + 1);
*((char *) mempcpy(new->name, name, len))
= '\0';
diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c
index 82c3302..aa1357c 100644
--- a/rpmio/rpmio.c
+++ b/rpmio/rpmio.c
@@ -6,6 +6,7 @@
#include <stdarg.h>
#include <errno.h>
#include <ctype.h>
+#include <dirent.h>
#if defined(__linux__)
#include <sys/personality.h>
#endif
diff --git a/system.h b/system.h
index 8854d70..f0122cb 100644
--- a/system.h
+++ b/system.h
@@ -49,23 +49,6 @@ char * stpncpy(char * dest, const char * src, size_t n);
#include <sys/file.h>
#endif
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-# define NLENGTH(direct) (strlen((direct)->d_name))
-#else /* not HAVE_DIRENT_H */
-# define dirent direct
-# define NLENGTH(direct) ((direct)->d_namlen)
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* HAVE_SYS_NDIR_H */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* HAVE_SYS_DIR_H */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif /* HAVE_NDIR_H */
-#endif /* HAVE_DIRENT_H */
-
#if HAVE_LIMITS_H
#include <limits.h>
#endif
--
1.8.3.1

View File

@ -0,0 +1,27 @@
From 3d63df622037796279514a4da3ddc6807a102c1d Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Fri, 27 Mar 2009 14:11:43 +0200
Subject: [PATCH] Handle XZ in %uncompress macro - should've been in commit
8078d0ba24662308b10d9eb0f0da978584b7e757
---
rpmio/macro.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/rpmio/macro.c b/rpmio/macro.c
index c55b9e2..32eb6ec 100644
--- a/rpmio/macro.c
+++ b/rpmio/macro.c
@@ -981,6 +981,9 @@ doFoo(MacroBuf mb, int negate, const char * f, size_t fn,
case COMPRESSED_LZMA:
sprintf(be, "%%__lzma -dc %s", b);
break;
+ case COMPRESSED_XZ:
+ sprintf(be, "%%__xz -dc %s", b);
+ break;
}
b = be;
} else if (STREQ("getenv", f, fn)) {
--
1.8.3.1

View File

@ -0,0 +1,191 @@
From 4eb7900d54609738d0d562ba7ac5f0d0f2ebf7e0 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Thu, 5 Dec 2019 14:22:08 +0200
Subject: [PATCH] Implement a key-only rpmdb index iterator
The regular index iterator grabs the associated data too, which we
don't always need. The data associated with indexes is relatively
lightweight, but as with everything, it adds up if in the millions scale.
Update all backends to allow for NULL set in the index retrieve to
signal key-only retrieval. Ndb actually had an earlier, abandoned
implementation of the same idea under slightly different API, lets
reuse the code-block.
URL:https://github.com/rpm-software-management/rpm/commit/4eb7900d54609738d0d562ba7ac5f0d0f2ebf7e0
Conflict: delete the contents of lib/backend/sqlite.c, because we have no sqlite database.
---
lib/backend/db3.c | 18 ++++++++++--------
lib/backend/lmdb.c | 18 ++++++++++--------
lib/backend/ndb/glue.c | 6 +++---
lib/rpmdb.c | 11 ++++++++++-
lib/rpmdb.h | 8 ++++++++
5 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/lib/backend/db3.c b/lib/backend/db3.c
index ff0fe43..3e6d198 100644
--- a/lib/backend/db3.c
+++ b/lib/backend/db3.c
@@ -1008,7 +1008,7 @@ static rpmRC db3_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
dbiIndexSet *set, int searchType)
{
rpmRC rc = RPMRC_FAIL; /* assume failure */
- if (dbi != NULL && dbc != NULL && set != NULL) {
+ if (dbi != NULL && dbc != NULL) {
int cflags = DB_NEXT;
int dbrc;
DBT data, key;
@@ -1033,12 +1033,14 @@ static rpmRC db3_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
if (searchType == DBC_PREFIX_SEARCH &&
(key.size < keylen || memcmp(key.data, keyp, keylen) != 0))
break;
- dbt2set(dbi, &data, &newset);
- if (*set == NULL) {
- *set = newset;
- } else {
- dbiIndexSetAppendSet(*set, newset, 0);
- dbiIndexSetFree(newset);
+ if (set) {
+ dbt2set(dbi, &data, &newset);
+ if (*set == NULL) {
+ *set = newset;
+ } else {
+ dbiIndexSetAppendSet(*set, newset, 0);
+ dbiIndexSetFree(newset);
+ }
}
if (searchType != DBC_PREFIX_SEARCH)
break;
@@ -1048,7 +1050,7 @@ static rpmRC db3_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
}
/* fixup result status for prefix search */
- if (searchType == DBC_PREFIX_SEARCH) {
+ if (searchType == DBC_PREFIX_SEARCH && set) {
if (dbrc == DB_NOTFOUND && *set != NULL && (*set)->count > 0)
dbrc = 0;
else if (dbrc == 0 && (*set == NULL || (*set)->count == 0))
diff --git a/lib/backend/lmdb.c b/lib/backend/lmdb.c
index badd317..f5b94ce 100644
--- a/lib/backend/lmdb.c
+++ b/lib/backend/lmdb.c
@@ -574,7 +574,7 @@ static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
dbiIndexSet *set, int searchType)
{
rpmRC rc = RPMRC_FAIL; /* assume failure */
- if (dbi != NULL && dbc != NULL && set != NULL) {
+ if (dbi != NULL && dbc != NULL) {
int cflags = MDB_NEXT;
int dbrc;
MDB_val key = { 0, NULL };
@@ -598,12 +598,14 @@ static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
if (searchType == DBC_PREFIX_SEARCH &&
(key.mv_size < keylen || memcmp(key.mv_data, keyp, keylen) != 0))
break;
- dbt2set(dbi, &data, &newset);
- if (*set == NULL) {
- *set = newset;
- } else {
- dbiIndexSetAppendSet(*set, newset, 0);
- dbiIndexSetFree(newset);
+ if (set) {
+ dbt2set(dbi, &data, &newset);
+ if (*set == NULL) {
+ *set = newset;
+ } else {
+ dbiIndexSetAppendSet(*set, newset, 0);
+ dbiIndexSetFree(newset);
+ }
}
if (searchType != DBC_PREFIX_SEARCH)
break;
@@ -613,7 +615,7 @@ static rpmRC lmdb_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t
}
/* fixup result status for prefix search */
- if (searchType == DBC_PREFIX_SEARCH) {
+ if (searchType == DBC_PREFIX_SEARCH && set) {
if (dbrc == MDB_NOTFOUND && *set != NULL && (*set)->count > 0)
dbrc = 0;
else if (dbrc == 0 && (*set == NULL || (*set)->count == 0))
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index 03aaaa8..07ddb0a 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -400,15 +400,15 @@ static rpmRC ndb_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set)
}
k = dbc->listdata + dbc->list[dbc->ilist];
kl = dbc->list[dbc->ilist + 1];
-#if 0
- if (searchType == DBC_KEY_SEARCH) {
+
+ if (set == NULL) {
dbc->ilist += 2;
dbc->key = k;
dbc->keylen = kl;
rc = RPMRC_OK;
break;
}
-#endif
+
pkglist = 0;
pkglistn = 0;
rc = rpmidxGet(dbc->dbi->dbi_db, k, kl, &pkglist, &pkglistn);
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 9cd50e7..6317dd0 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -298,6 +298,7 @@ struct rpmdbIndexIterator_s {
dbiCursor ii_dbc;
dbiIndexSet ii_set;
unsigned int *ii_hdrNums;
+ int ii_skipdata;
};
static rpmdb rpmdbRock;
@@ -1885,6 +1886,13 @@ rpmdbIndexIterator rpmdbIndexIteratorInit(rpmdb db, rpmDbiTag rpmtag)
return ii;
}
+rpmdbIndexIterator rpmdbIndexKeyIteratorInit(rpmdb db, rpmDbiTag rpmtag)
+{
+ rpmdbIndexIterator ki = rpmdbIndexIteratorInit(db, rpmtag);
+ ki->ii_skipdata = 1;
+ return ki;
+}
+
int rpmdbIndexIteratorNext(rpmdbIndexIterator ii, const void ** key, size_t * keylen)
{
int rc;
@@ -1899,7 +1907,8 @@ int rpmdbIndexIteratorNext(rpmdbIndexIterator ii, const void ** key, size_t * ke
/* free old data */
ii->ii_set = dbiIndexSetFree(ii->ii_set);
- rc = idxdbGet(ii->ii_dbi, ii->ii_dbc, NULL, 0, &ii->ii_set, DBC_NORMAL_SEARCH);
+ rc = idxdbGet(ii->ii_dbi, ii->ii_dbc, NULL, 0,
+ ii->ii_skipdata ? NULL : &ii->ii_set, DBC_NORMAL_SEARCH);
*key = idxdbKey(ii->ii_dbi, ii->ii_dbc, &iikeylen);
*keylen = iikeylen;
diff --git a/lib/rpmdb.h b/lib/rpmdb.h
index 75a722e..8e3ab5a 100644
--- a/lib/rpmdb.h
+++ b/lib/rpmdb.h
@@ -154,6 +154,14 @@ Header rpmdbNextIterator(rpmdbMatchIterator mi);
rpmdbMatchIterator rpmdbFreeIterator(rpmdbMatchIterator mi);
/** \ingroup rpmdb
+ * Get an iterator for index keys
+ * @param db rpm database
+ * @param rpmtag the index to iterate over
+ * @return the index iterator
+ */
+rpmdbIndexIterator rpmdbIndexKeyIteratorInit(rpmdb db, rpmDbiTag rpmtag);
+
+/** \ingroup rpmdb
* Get an iterator for an index
* @param db rpm database
* @param rpmtag the index to iterate over
--
1.8.3.1

View File

@ -0,0 +1,41 @@
From 3cb955b77f07c70ba01d765aa6377908847608f5 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 23 Nov 2020 13:46:14 +0200
Subject: [PATCH] Only attempt loading the keyring once the rpmdb is open
When we do lazy rpmdb open in rpmtsInitIterator(), we also do a lazy
keyring open. Except that since the keyring typically lives in the rpmdb,
we PROBABLY should try open the database first. One of those "WTF I've
been smoking" moments, lol.
Prevents an ugly if mostly harmless double error anything we can't open
the database for one reason or another.
URL:https://github.com/rpm-software-management/rpm/commit/3cb955b77f07c70ba01d765aa6377908847608f5
---
lib/rpmts.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/rpmts.c b/lib/rpmts.c
index 9fa9cb0..8c8ae42 100644
--- a/lib/rpmts.c
+++ b/lib/rpmts.c
@@ -177,12 +177,12 @@ rpmdbMatchIterator rpmtsInitIterator(const rpmts ts, rpmDbiTagVal rpmtag,
if (ts == NULL)
return NULL;
- if (ts && ts->keyring == NULL)
- loadKeyring(ts);
-
if (ts->rdb == NULL && rpmtsOpenDB(ts, ts->dbmode))
return NULL;
+ if (ts->keyring == NULL)
+ loadKeyring(ts);
+
/* Parse out "N(EVR)" tokens from a label key if present */
if (rpmtag == RPMDBI_LABEL && keyp != NULL && strchr(keyp, '(')) {
const char *se, *s = keyp;
--
1.8.3.1

View File

@ -0,0 +1,28 @@
From 2d63d5ee78963a8f90dcdf93c461f89d326a5a18 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 3 Feb 2020 11:37:30 +0100
Subject: [PATCH] Permit ndb database queries on read-only media
See also commit a429c99e13fbe9926243f29b78df8d64222c4469 for db3.
URL:https://github.com/rpm-software-management/rpm/commit/2d63d5ee78963a8f90dcdf93c461f89d326a5a18
---
lib/backend/ndb/glue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index 90c10f8..d19da7c 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -161,7 +161,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
/* Open indexes readwrite if possible */
ioflags = O_RDWR;
rc = rpmxdbOpen(&ndbenv->xdb, rdb->db_pkgs->dbi_db, path, ioflags, 0666);
- if (rc && errno == EACCES) {
+ if (rc && (errno == EACCES || errno == EROFS)) {
/* If it is not asked for rw explicitly, try to open ro */
if (!(oflags & O_RDWR)) {
ioflags = O_RDONLY;
--
1.8.3.1

View File

@ -0,0 +1,26 @@
From 7949d290b80aaebf7213e0b70a614d0d00585577 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 15:56:59 +0100
Subject: [PATCH] Remove the experimental status from the ndb database
URL:https://github.com/rpm-software-management/rpm/commit/7949d290b80aaebf7213e0b70a614d0d00585577
---
configure.ac | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/configure.ac b/configure.ac
index 7a90b2f..2801b13 100644
--- a/configure.ac
+++ b/configure.ac
@@ -581,7 +581,7 @@ fi
#=================
# Process --enable-ndb
-AC_ARG_ENABLE([ndb], [AS_HELP_STRING([--enable-ndb (EXPERIMENTAL)],[enable the new rpm database format])],
+AC_ARG_ENABLE([ndb], [AS_HELP_STRING([--enable-ndb],[enable the new rpm database format])],
[case "$enable_ndb" in
yes|no) ;;
*) AC_MSG_ERROR([invalid argument to --enable-ndb])
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From fd054a40b2ba005571455d749de0423975e77651 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 18 Nov 2020 13:56:14 +0200
Subject: [PATCH] Stop on first failure when trying to open a database
(RhBug:1898301)
If an index open fails there's no point trying to go on, things are
not going to work and at least BDB will segfault in some cases...
URL:https://github.com/rpm-software-management/rpm/commit/fd054a40b2ba005571455d749de0423975e77651
---
lib/rpmdb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 874f079..41da9da 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -355,7 +355,7 @@ static int doOpen(rpmdb db, int justPkgs)
{
int rc = pkgdbOpen(db, db->db_flags, NULL);
if (!justPkgs) {
- for (int dbix = 0; dbix < db->db_ndbi; dbix++) {
+ for (int dbix = 0; rc == 0 && dbix < db->db_ndbi; dbix++) {
rc += indexOpen(db, db->db_tags[dbix], db->db_flags, NULL);
}
}
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From 108adfc4d10b2158d38d599430275b149ad236c5 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 21 Oct 2019 14:50:22 +0300
Subject: [PATCH] Use paths from db_ops in the backends too where possible
ndb and sqlite have control of their own paths, BDB and LMDB do things
differently and dummydb doesn't have a path at all.
URL:https://github.com/rpm-software-management/rpm/commit/108adfc4d10b2158d38d599430275b149ad236c5
Conflict: delete the contents of lib/backend/sqlite.c, because we have no sqlite database.
---
lib/backend/ndb/glue.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index d679ed1..03aaaa8 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -101,7 +101,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
if (dbi->dbi_type == DBI_PRIMARY) {
rpmpkgdb pkgdb = 0;
- char *path = rstrscat(NULL, dbhome, "/Packages.db", NULL);
+ char *path = rstrscat(NULL, dbhome, "/", rdb->db_ops->path, NULL);
rpmlog(RPMLOG_DEBUG, "opening db index %s mode=0x%x\n", path, rdb->db_mode);
rc = rpmpkgOpen(&pkgdb, path, oflags, 0666);
if (rc && errno == ENOENT) {
--
1.8.3.1

View File

@ -0,0 +1,118 @@
From bc236cc369b8af9995dd50ba5263d354f47421ce Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Mon, 21 Oct 2019 14:39:50 +0300
Subject: [PATCH] Use the new backend struct data for backend configuration and
detection
Refactor the hand-written separate tests into an array walk now that we can.
No functional changes, except that there's no more special fallback for BDB.
URL:https://github.com/rpm-software-management/rpm/commit/bc236cc369b8af9995dd50ba5263d354f47421ce
Conflict:delete the contents of sqlite, because we have no sqlite database.
---
lib/backend/dbi.c | 77 +++++++++++++++++++++++++------------------------------
1 file changed, 35 insertions(+), 42 deletions(-)
diff --git a/lib/backend/dbi.c b/lib/backend/dbi.c
index 5e00310..a4a40a8 100644
--- a/lib/backend/dbi.c
+++ b/lib/backend/dbi.c
@@ -12,6 +12,19 @@
#include "lib/rpmdb_internal.h"
#include "debug.h"
+const struct rpmdbOps_s *backends[] = {
+#if defined(WITH_LMDB)
+ &lmdb_dbops,
+#endif
+#ifdef ENABLE_NDB
+ &ndb_dbops,
+#endif
+#if defined(WITH_BDB)
+ &db3_dbops,
+#endif
+ &dummydb_dbops,
+ NULL
+};
dbiIndex dbiFree(dbiIndex dbi)
{
@@ -38,53 +51,33 @@ dbDetectBackend(rpmdb rdb)
const char *dbhome = rpmdbHome(rdb);
char *db_backend = rpmExpand("%{?_db_backend}", NULL);
char *path = NULL;
+ const struct rpmdbOps_s **ops;
-#if defined(WITH_LMDB)
- if (!strcmp(db_backend, "lmdb")) {
- rdb->db_ops = &lmdb_dbops;
- } else
-#endif
-#ifdef ENABLE_NDB
- if (!strcmp(db_backend, "ndb")) {
- rdb->db_ops = &ndb_dbops;
- } else
-#endif
-#if defined(WITH_BDB)
- {
- rdb->db_ops = &db3_dbops;
- if (*db_backend == '\0') {
- free(db_backend);
- db_backend = xstrdup("bdb");
+ for (ops = backends; ops && *ops; ops++) {
+ if (rstreq(db_backend, (*ops)->name)) {
+ rdb->db_ops = *ops;
+ break;
}
}
-#endif
-#if defined(WITH_LMDB)
- path = rstrscat(NULL, dbhome, "/data.mdb", NULL);
- if (access(path, F_OK) == 0 && rdb->db_ops != &lmdb_dbops) {
- rdb->db_ops = &lmdb_dbops;
- rpmlog(RPMLOG_WARNING, _("Found LMDB data.mdb database while attempting %s backend: using lmdb backend.\n"), db_backend);
- }
- free(path);
-#endif
-
-#ifdef ENABLE_NDB
- path = rstrscat(NULL, dbhome, "/Packages.db", NULL);
- if (access(path, F_OK) == 0 && rdb->db_ops != &ndb_dbops) {
- rdb->db_ops = &ndb_dbops;
- rpmlog(RPMLOG_WARNING, _("Found NDB Packages.db database while attempting %s backend: using ndb backend.\n"), db_backend);
- }
- free(path);
-#endif
-
-#if defined(WITH_BDB)
- path = rstrscat(NULL, dbhome, "/Packages", NULL);
- if (access(path, F_OK) == 0 && rdb->db_ops != &db3_dbops) {
- rdb->db_ops = &db3_dbops;
- rpmlog(RPMLOG_WARNING, _("Found BDB Packages database while attempting %s backend: using bdb backend.\n"), db_backend);
+ for (ops = backends; ops && *ops; ops++) {
+ int stop = 0;
+ if ((*ops)->path == NULL)
+ continue;
+
+ path = rstrscat(NULL, dbhome, "/", (*ops)->path, NULL);
+ if (access(path, F_OK) == 0 && rdb->db_ops != *ops) {
+ rpmlog(RPMLOG_WARNING,
+ _("Found %s %s database while attempting %s backend: "
+ "using %s backend.\n"),
+ (*ops)->name, (*ops)->path, db_backend, (*ops)->name);
+ rdb->db_ops = *ops;
+ stop = 1;
+ }
+ free(path);
+ if (stop)
+ break;
}
- free(path);
-#endif
if (rdb->db_ops == NULL) {
rdb->db_ops = &dummydb_dbops;
--
1.8.3.1

View File

@ -0,0 +1,219 @@
From 6489957449fec63ddf330330e9435b4ee0c388b0 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Mon, 3 Feb 2020 14:18:23 +0100
Subject: [PATCH] ndb: add a rpmpkgSalvage() method
This can be used to recover as much data as possibly from a
terminally broken database. It works by scanning the database
file for entries that are not corrupt.
URL:https://github.com/rpm-software-management/rpm/commit/6489957449fec63ddf330330e9435b4ee0c388b0
---
lib/backend/ndb/rpmpkg.c | 157 +++++++++++++++++++++++++++++++++++++++++++++--
lib/backend/ndb/rpmpkg.h | 1 +
2 files changed, 153 insertions(+), 5 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index 922ae11..b9cd67c 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -30,8 +30,6 @@ typedef struct pkgslot_s {
typedef struct rpmpkgdb_s {
int fd; /* our file descriptor */
- int flags;
- int mode;
int rdonly;
@@ -885,8 +883,6 @@ int rpmpkgOpen(rpmpkgdb *pkgdbp, const char *filename, int flags, int mode)
return RPMRC_FAIL;
}
}
- pkgdb->flags = flags;
- pkgdb->mode = mode;
pkgdb->dofsync = 1;
*pkgdbp = pkgdb;
return RPMRC_OK;
@@ -908,6 +904,157 @@ void rpmpkgClose(rpmpkgdb pkgdb)
free(pkgdb);
}
+
+static unsigned int salvage_latest_blob(unsigned int *salvaged, unsigned int cnt)
+{
+ unsigned int i, max = 0, maxi = 0;
+ for (i = 0; i < cnt - 1; i++) {
+ if (salvaged[i * 4 + 7] - salvaged[i * 4 + 3] > max) {
+ max = salvaged[i * 4 + 7] - salvaged[i * 4 + 3];
+ maxi = i;
+ }
+ }
+ if ((unsigned int)(salvaged[3] - salvaged[i * 4 + 3]) > max)
+ maxi = cnt - 1;
+ return maxi;
+}
+
+static int salvage_cmp(const void *av, const void *bv)
+{
+ const unsigned int *a = av, *b = bv;
+ if (a[0] != b[0])
+ return a[0] > b[0] ? 1 : -1;
+ if (a[3] != b[3])
+ return a[3] > b[3] ? 1 : -1;
+ if (a[1] != b[1])
+ return a[1] > b[1] ? 1 : -1;
+ return 0;
+}
+
+#define SALVAGE_PAGESIZE 4096
+#define SALVAGE_BLKCHUNK (SALVAGE_PAGESIZE / BLK_SIZE)
+
+int rpmpkgSalvage(rpmpkgdb *pkgdbp, const char *filename)
+{
+ struct stat stb;
+ rpmpkgdb pkgdb;
+ unsigned int blk, iblk, blkskip;
+ unsigned int blkoff, blkcnt, pkgidx, generation, bloblen;
+ unsigned int nfound, nslots, i, j;
+ unsigned char page[SALVAGE_PAGESIZE];
+ unsigned int *salvaged;
+
+ *pkgdbp = 0;
+ pkgdb = xcalloc(1, sizeof(*pkgdb));
+ pkgdb->filename = xstrdup(filename);
+ pkgdb->rdonly = 1;
+ if ((pkgdb->fd = open(filename, O_RDONLY)) == -1) {
+ rpmpkgClose(pkgdb);
+ return RPMRC_FAIL;
+ }
+ if (rpmpkgGetLock(pkgdb, LOCK_SH)) {
+ rpmpkgClose(pkgdb);
+ return RPMRC_FAIL;
+ }
+ pkgdb->locked_shared++;
+ if (fstat(pkgdb->fd, &stb)) {
+ rpmpkgClose(pkgdb);
+ return RPMRC_FAIL;
+ }
+ if (stb.st_size < BLK_SIZE) {
+ rpmpkgClose(pkgdb);
+ return RPMRC_FAIL;
+ }
+ pkgdb->fileblks = stb.st_size / BLK_SIZE;
+ blkskip = 1;
+ nfound = 0;
+ salvaged = xmalloc(64 * (4 * sizeof(unsigned int)));
+ for (blk = 0; blk < pkgdb->fileblks; blk += SALVAGE_BLKCHUNK) {
+ unsigned int size;
+ unsigned char *bp = page;
+ if (pkgdb->fileblks - blk > SALVAGE_BLKCHUNK)
+ size = SALVAGE_PAGESIZE;
+ else
+ size = (pkgdb->fileblks - blk) * BLK_SIZE;
+ if (pread(pkgdb->fd, page, size, (off_t)blk * BLK_SIZE) != size)
+ continue;
+ if (size != SALVAGE_PAGESIZE)
+ memset(page + size, 0, SALVAGE_PAGESIZE - size);
+ if (blkskip) {
+ memset(page, 0, blkskip * BLK_SIZE);
+ blkskip = 0;
+ }
+ for (iblk = 0; iblk < SALVAGE_BLKCHUNK; iblk++, bp += BLK_SIZE) {
+ if (le2h(bp) != BLOBHEAD_MAGIC)
+ continue;
+ pkgidx = le2h(bp + 4);
+ if (!pkgidx)
+ continue;
+ generation = le2h(bp + 8);
+ bloblen = le2h(bp + 12);
+ blkoff = blk + iblk;
+ blkcnt = (BLOBHEAD_SIZE + bloblen + BLOBTAIL_SIZE + BLK_SIZE - 1) / BLK_SIZE;
+ if (blkoff + blkcnt > pkgdb->fileblks)
+ continue;
+ if (rpmpkgVerifyblob(pkgdb, pkgidx, blkoff, blkcnt))
+ continue;
+ /* found a valid blob, add to salvaged list */
+ if (nfound && (nfound & 63) == 0)
+ salvaged = xrealloc(salvaged, (nfound + 64) * (4 * sizeof(unsigned int)));
+ salvaged[nfound * 4 + 0] = pkgidx;
+ salvaged[nfound * 4 + 1] = blkoff;
+ salvaged[nfound * 4 + 2] = blkcnt;
+ salvaged[nfound * 4 + 3] = generation;
+ nfound++;
+ /* advance to after the blob! */
+ blkoff += blkcnt;
+ if (blkoff >= blk + SALVAGE_BLKCHUNK) {
+ blkskip = blkoff % SALVAGE_BLKCHUNK;
+ blk = blkoff - blkskip - SALVAGE_BLKCHUNK;
+ break;
+ } else {
+ iblk = blkoff - blk - 1;
+ bp = page + iblk * BLK_SIZE;
+ }
+ }
+ }
+ /* now strip duplicate entries */
+ nslots = 0;
+ if (nfound > 1) {
+ qsort(salvaged, nfound, sizeof(unsigned int) * 4, salvage_cmp);
+ for (i = 0; i < nfound; i++) {
+ pkgidx = salvaged[i * 4];
+ for (j = i + 1; j < nfound; j++)
+ if (salvaged[j * 4] != pkgidx)
+ break;
+ if (j != i + 1)
+ i += salvage_latest_blob(salvaged + i * 4, j - i);
+ if (i != nslots)
+ memcpy(salvaged + nslots * 4, salvaged + i * 4, sizeof(unsigned int) * 4);
+ nslots++;
+ i = j - 1;
+ }
+ }
+ pkgdb->slots = xcalloc(nslots + 1, sizeof(*pkgdb->slots));
+ for (i = 0; i < nslots; i++) {
+ pkgdb->slots[i].pkgidx = salvaged[i * 4 + 0];
+ pkgdb->slots[i].blkoff = salvaged[i * 4 + 1];
+ pkgdb->slots[i].blkcnt = salvaged[i * 4 + 2];
+ pkgdb->slots[i].slotno = 0;
+ }
+ free(salvaged);
+ pkgdb->header_ok = 1;
+ pkgdb->nslots = nslots;
+ pkgdb->ordered = 0;
+ rpmpkgOrderSlots(pkgdb);
+ if (rpmpkgHashSlots(pkgdb)) {
+ rpmpkgClose(pkgdb);
+ return RPMRC_FAIL;
+ }
+ *pkgdbp = pkgdb;
+ return RPMRC_OK;
+}
+
void rpmpkgSetFsync(rpmpkgdb pkgdb, int dofsync)
{
pkgdb->dofsync = dofsync;
@@ -1184,7 +1331,7 @@ int rpmpkgVerify(rpmpkgdb pkgdb)
int rpmpkgNextPkgIdx(rpmpkgdb pkgdb, unsigned int *pkgidxp)
{
- if (rpmpkgLockReadHeader(pkgdb, 1))
+ if (rpmpkgLockReadHeader(pkgdb, 1) || !pkgdb->nextpkgidx)
return RPMRC_FAIL;
*pkgidxp = pkgdb->nextpkgidx++;
if (rpmpkgWriteHeader(pkgdb)) {
diff --git a/lib/backend/ndb/rpmpkg.h b/lib/backend/ndb/rpmpkg.h
index 72d05c4..6466818 100644
--- a/lib/backend/ndb/rpmpkg.h
+++ b/lib/backend/ndb/rpmpkg.h
@@ -2,6 +2,7 @@ struct rpmpkgdb_s;
typedef struct rpmpkgdb_s *rpmpkgdb;
int rpmpkgOpen(rpmpkgdb *pkgdbp, const char *filename, int flags, int mode);
+int rpmpkgSalvage(rpmpkgdb *pkgdbp, const char *filename);
void rpmpkgClose(rpmpkgdb pkgdbp);
void rpmpkgSetFsync(rpmpkgdb pkgdbp, int dofsync);
--
1.8.3.1

View File

@ -0,0 +1,143 @@
From 49d43a334572199088ecc24ce6fc0e86c8699d2e Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 15:49:16 +0100
Subject: [PATCH] ndb: add a rpmxdbDelAllBlobs method
This will delete all blobs (i.e. index databases) from the
ndb master index database. We do this kind of low-level on purpose,
so that it even works if the index database is corrupt.
This will be used in the next commit which implements automatic
index regeneration if the index is out of sync.
URL:https://github.com/rpm-software-management/rpm/commit/49d43a334572199088ecc24ce6fc0e86c8699d2e
---
lib/backend/ndb/rpmxdb.c | 81 +++++++++++++++++++++++++++++++++++++-----------
lib/backend/ndb/rpmxdb.h | 1 +
2 files changed, 64 insertions(+), 18 deletions(-)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index 2f94491..3baafa6 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -224,11 +224,33 @@ static int usedslots_cmp(const void *a, const void *b)
return sa->startpage > sb->startpage ? 1 : -1;
}
+static int rpmxdbReadHeaderRaw(rpmxdb xdb, unsigned int *generationp, unsigned int *slotnpagesp, unsigned int *pagesizep, unsigned int *usergenerationp)
+{
+ unsigned int header[XDB_HEADER_SIZE / sizeof(unsigned int)];
+ unsigned int version;
+ if (pread(xdb->fd, header, sizeof(header), 0) != sizeof(header))
+ return RPMRC_FAIL;
+ if (le2ha((unsigned char *)header + XDB_OFFSET_MAGIC) != XDB_MAGIC)
+ return RPMRC_FAIL;
+ version = le2ha((unsigned char *)header + XDB_OFFSET_VERSION);
+ if (version != XDB_VERSION) {
+ rpmlog(RPMLOG_ERR, _("rpmxdb: Version mismatch. Expected version: %u. "
+ "Found version: %u\n"), XDB_VERSION, version);
+ return RPMRC_FAIL;
+ }
+ *generationp = le2ha((unsigned char *)header + XDB_OFFSET_GENERATION);
+ *slotnpagesp = le2ha((unsigned char *)header + XDB_OFFSET_SLOTNPAGES);
+ *pagesizep = le2ha((unsigned char *)header + XDB_OFFSET_PAGESIZE);
+ *usergenerationp = le2ha((unsigned char *)header + XDB_OFFSET_USERGENERATION);
+ if (!*slotnpagesp || !*pagesizep)
+ return RPMRC_FAIL;
+ return RPMRC_OK;
+}
+
static int rpmxdbReadHeader(rpmxdb xdb)
{
struct xdb_slot *slot;
- unsigned int header[XDB_HEADER_SIZE / sizeof(unsigned int)];
- unsigned int slotnpages, pagesize, generation, usergeneration, version;
+ unsigned int slotnpages, pagesize, generation, usergeneration;
unsigned int page, *lastfreep;
unsigned char *pageptr;
struct xdb_slot *slots, **usedslots, *lastslot;
@@ -246,23 +268,9 @@ static int rpmxdbReadHeader(rpmxdb xdb)
if (fstat(xdb->fd, &stb)) {
return RPMRC_FAIL;
}
- if (pread(xdb->fd, header, sizeof(header), 0) != sizeof(header)) {
- return RPMRC_FAIL;
- }
- if (le2ha((unsigned char *)header + XDB_OFFSET_MAGIC) != XDB_MAGIC)
+ if (rpmxdbReadHeaderRaw(xdb, &generation, &slotnpages, &pagesize, &usergeneration))
return RPMRC_FAIL;
- version = le2ha((unsigned char *)header + XDB_OFFSET_VERSION);
- if (version != XDB_VERSION) {
- rpmlog(RPMLOG_ERR, _("rpmxdb: Version mismatch. Expected version: %u. "
- "Found version: %u\n"), XDB_VERSION, version);
- return RPMRC_FAIL;
- }
-
- generation = le2ha((unsigned char *)header + XDB_OFFSET_GENERATION);
- slotnpages = le2ha((unsigned char *)header + XDB_OFFSET_SLOTNPAGES);
- pagesize = le2ha((unsigned char *)header + XDB_OFFSET_PAGESIZE);
- usergeneration = le2ha((unsigned char *)header + XDB_OFFSET_USERGENERATION);
- if (!slotnpages || !pagesize || stb.st_size % pagesize != 0)
+ if (stb.st_size % pagesize != 0)
return RPMRC_FAIL;
xdb->pagesize = pagesize;
xdb->mapflags = xdb->rdonly ? PROT_READ : PROT_READ | PROT_WRITE;
@@ -923,6 +931,43 @@ int rpmxdbDelBlob(rpmxdb xdb, unsigned int id)
return RPMRC_OK;
}
+int rpmxdbDelAllBlobs(rpmxdb xdb)
+{
+ unsigned int slotnpages, pagesize, generation, usergeneration;
+ if (rpmxdbLockOnly(xdb, 1))
+ return RPMRC_FAIL;
+ /* unmap all blobs */
+ if (xdb->slots) {
+ int i;
+ struct xdb_slot *slot;
+ for (i = 1, slot = xdb->slots + i; i < xdb->nslots; i++, slot++) {
+ if (slot->startpage && slot->mapped) {
+ unmapslot(xdb, slot);
+ slot->mapcallback(xdb, slot->mapcallbackdata, 0, 0);
+ }
+ }
+ free(xdb->slots);
+ xdb->slots = 0;
+ }
+ if (xdb->mapped)
+ unmapheader(xdb);
+ if (rpmxdbReadHeaderRaw(xdb, &generation, &slotnpages, &pagesize, &usergeneration)) {
+ rpmxdbUnlock(xdb, 1);
+ return RPMRC_FAIL;
+ }
+ xdb->generation = generation + 1;
+ xdb->slotnpages = 1;
+ xdb->pagesize = pagesize;
+ xdb->usergeneration = usergeneration;
+ if (rpmxdbWriteEmptySlotpage(xdb, 0)) {
+ rpmxdbUnlock(xdb, 1);
+ return RPMRC_FAIL;
+ }
+ ftruncate(xdb->fd, xdb->pagesize);
+ rpmxdbUnlock(xdb, 1);
+ return RPMRC_OK;
+}
+
int rpmxdbResizeBlob(rpmxdb xdb, unsigned int id, size_t newsize)
{
struct xdb_slot *slot;
diff --git a/lib/backend/ndb/rpmxdb.h b/lib/backend/ndb/rpmxdb.h
index 88a3e61..ddf02c1 100644
--- a/lib/backend/ndb/rpmxdb.h
+++ b/lib/backend/ndb/rpmxdb.h
@@ -14,6 +14,7 @@ int rpmxdbUnlock(rpmxdb xdb, int excl);
int rpmxdbLookupBlob(rpmxdb xdb, unsigned int *idp, unsigned int blobtag, unsigned int subtag, int flags);
int rpmxdbDelBlob(rpmxdb xdb, unsigned int id) ;
+int rpmxdbDelAllBlobs(rpmxdb xdb);
int rpmxdbMapBlob(rpmxdb xdb, unsigned int id, int flags, void (*mapcallback)(rpmxdb xdb, void *data, void *newaddr, size_t newsize), void *mapcallbackdata);
int rpmxdbUnmapBlob(rpmxdb xdb, unsigned int id);
--
1.8.3.1

View File

@ -0,0 +1,93 @@
From 3feb7993a800525395dca5a173ade5f8e4fbd8d5 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 11:55:32 +0100
Subject: [PATCH] ndb: add a verify method
This adds a verify method for ndb's Packages.db database. The
Index.db database is currently not verified.
URL:https://github.com/rpm-software-management/rpm/commit/3feb7993a800525395dca5a173ade5f8e4fbd8d5
---
lib/backend/ndb/glue.c | 8 +++++++-
lib/backend/ndb/rpmpkg.c | 26 ++++++++++++++++++++++++++
lib/backend/ndb/rpmpkg.h | 1 +
3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index 07ddb0a..376e360 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -179,7 +179,13 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
static int ndb_Verify(dbiIndex dbi, unsigned int flags)
{
- return 0;
+ int rc;
+ if (dbi->dbi_type == DBI_PRIMARY) {
+ rc = rpmpkgVerify(dbi->dbi_db);
+ } else {
+ rc = 0; /* cannot verify the index databases */
+ }
+ return rc;
}
static void ndb_SetFSync(rpmdb rdb, int enable)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index b95f29f..2213872 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -1101,6 +1101,22 @@ static int rpmpkgListInternal(rpmpkgdb pkgdb, unsigned int **pkgidxlistp, unsign
return RPMRC_OK;
}
+static int rpmpkgVerifyInternal(rpmpkgdb pkgdb)
+{
+ unsigned int i, nslots;
+ pkgslot *slot;
+
+ if (rpmpkgReadSlots(pkgdb))
+ return RPMRC_FAIL;
+ rpmpkgOrderSlots(pkgdb);
+ nslots = pkgdb->nslots;
+ for (i = 0, slot = pkgdb->slots; i < nslots; i++, slot++) {
+ if (rpmpkgVerifyblob(pkgdb, slot->pkgidx, slot->blkoff, slot->blkcnt))
+ return RPMRC_FAIL;
+ }
+ return RPMRC_OK;
+}
+
int rpmpkgGet(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char **blobp, unsigned int *bloblp)
{
int rc;
@@ -1157,6 +1173,16 @@ int rpmpkgList(rpmpkgdb pkgdb, unsigned int **pkgidxlistp, unsigned int *npkgidx
return rc;
}
+int rpmpkgVerify(rpmpkgdb pkgdb)
+{
+ int rc;
+ if (rpmpkgLockReadHeader(pkgdb, 0))
+ return RPMRC_FAIL;
+ rc = rpmpkgVerifyInternal(pkgdb);
+ rpmpkgUnlock(pkgdb, 0);
+ return rc;
+}
+
int rpmpkgNextPkgIdx(rpmpkgdb pkgdb, unsigned int *pkgidxp)
{
if (rpmpkgLockReadHeader(pkgdb, 1))
diff --git a/lib/backend/ndb/rpmpkg.h b/lib/backend/ndb/rpmpkg.h
index 7e5d0c6..72d05c4 100644
--- a/lib/backend/ndb/rpmpkg.h
+++ b/lib/backend/ndb/rpmpkg.h
@@ -12,6 +12,7 @@ int rpmpkgGet(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char **blobp, unsign
int rpmpkgPut(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char *blob, unsigned int blobl);
int rpmpkgDel(rpmpkgdb pkgdb, unsigned int pkgidx);
int rpmpkgList(rpmpkgdb pkgdb, unsigned int **pkgidxlistp, unsigned int *npkgidxlistp);
+int rpmpkgVerify(rpmpkgdb pkgdb);
int rpmpkgNextPkgIdx(rpmpkgdb pkgdb, unsigned int *pkgidxp);
int rpmpkgGeneration(rpmpkgdb pkgdb, unsigned int *generationp);
--
1.8.3.1

View File

@ -0,0 +1,45 @@
From 85b51e2dcf2a0a6393d2fbc51b78d5398e5ffeed Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 10:44:11 +0200
Subject: [PATCH] ndb: also copy the mapped pointer when keeping a slot
We forgot to copy the mapped pointer if a slot was kept when
re-syncing after a generation mismatch. This led to the mapped
pointer being zero even if the map callback was set.
Also add an extra test for the map callback before setting the
protection flag to PROT_READ.
Found by testing the code with different mapping protection flags.
See the next commits.
URL:https://github.com/rpm-software-management/rpm/commit/85b51e2dcf2a0a6393d2fbc51b78d5398e5ffeed
---
lib/backend/ndb/rpmxdb.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index 5136fbc..354a098 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -369,6 +369,8 @@ static int rpmxdbReadHeader(rpmxdb xdb)
nslot->mapcallback(xdb, nslot->mapcallbackdata, 0, 0);
}
}
+ } else {
+ nslot->mapped = slot->mapped;
}
}
}
@@ -624,7 +626,8 @@ static int moveblobto(rpmxdb xdb, struct xdb_slot *oldslot, struct xdb_slot *aft
didmap = 0;
oldpagecnt = oldslot->pagecnt;
if (!oldslot->mapped && oldpagecnt) {
- oldslot->mapflags = PROT_READ;
+ if (!oldslot->mapcallback)
+ oldslot->mapflags = PROT_READ;
if (mapslot(xdb, oldslot))
return RPMRC_FAIL;
didmap = 1;
--
1.8.3.1

View File

@ -0,0 +1,106 @@
From 3cfd298e9d03a7867118326fc60cc86fd7ea9b73 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 10:58:34 +0200
Subject: [PATCH] ndb: do not map the index databases read-write all the time
Pass the flags to rpmidxOpenXdb and use read only mode if the
user specified O_RDONLY. We already did that for rpmidxOpen in
the past but we always used read-write mode when using the Xdb.
We still open the Xdb itself in read-write mode so that we can
regenerate missing index databases.
URL:https://github.com/rpm-software-management/rpm/commit/3cfd298e9d03a7867118326fc60cc86fd7ea9b73
---
lib/backend/ndb/glue.c | 11 ++++-------
lib/backend/ndb/rpmidx.c | 8 ++++++--
lib/backend/ndb/rpmidx.h | 2 +-
3 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index f69a46e..2bdfecc 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -147,9 +147,6 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
free(path);
dbi->dbi_db = ndbenv->pkgdb = pkgdb;
rpmpkgSetFsync(pkgdb, ndbenv->dofsync);
-
- if ((oflags & (O_RDWR | O_RDONLY)) == O_RDONLY)
- dbi->dbi_flags |= DBI_RDONLY;
} else {
unsigned int id;
rpmidxdb idxdb = 0;
@@ -188,20 +185,20 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
ndb_CheckIndexSync(ndbenv->pkgdb, ndbenv->xdb);
}
if (rpmxdbLookupBlob(ndbenv->xdb, &id, rpmtag, 0, 0) == RPMRC_NOTFOUND) {
+ oflags = O_RDWR|O_CREAT;
dbi->dbi_flags |= DBI_CREATED;
}
rpmlog(RPMLOG_DEBUG, "opening db index %s tag=%d\n", dbiName(dbi), rpmtag);
- if (rpmidxOpenXdb(&idxdb, rdb->db_pkgs->dbi_db, ndbenv->xdb, rpmtag)) {
+ if (rpmidxOpenXdb(&idxdb, rdb->db_pkgs->dbi_db, ndbenv->xdb, rpmtag, oflags)) {
perror("rpmidxOpenXdb");
ndb_Close(dbi, 0);
return 1;
}
dbi->dbi_db = idxdb;
-
- if (rpmxdbIsRdonly(ndbenv->xdb))
- dbi->dbi_flags |= DBI_RDONLY;
}
+ if ((oflags & (O_RDWR | O_RDONLY)) == O_RDONLY)
+ dbi->dbi_flags |= DBI_RDONLY;
if (dbip != NULL)
*dbip = dbi;
diff --git a/lib/backend/ndb/rpmidx.c b/lib/backend/ndb/rpmidx.c
index 0ec8c8d..90b22d5 100644
--- a/lib/backend/ndb/rpmidx.c
+++ b/lib/backend/ndb/rpmidx.c
@@ -885,13 +885,17 @@ int rpmidxOpen(rpmidxdb *idxdbp, rpmpkgdb pkgdb, const char *filename, int flags
return RPMRC_FAIL;
}
-int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag)
+int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag, int flags)
{
rpmidxdb idxdb;
unsigned int id;
*idxdbp = 0;
int rc;
+ if (rpmxdbIsRdonly(xdb) && (flags & (O_RDONLY|O_RDWR)) != O_RDONLY) {
+ errno = EACCES;
+ return RPMRC_FAIL;
+ }
if (rpmxdbLock(xdb, 0))
return RPMRC_FAIL;
rc = rpmxdbLookupBlob(xdb, &id, xdbtag, IDXDB_XDB_SUBTAG, 0);
@@ -907,7 +911,7 @@ int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdb
idxdb->xdbid = id;
idxdb->pkgdb = pkgdb;
idxdb->pagesize = rpmxdbPagesize(xdb);
- idxdb->rdonly = rpmxdbIsRdonly(xdb) ? 1 : 0;
+ idxdb->rdonly = (flags & (O_RDONLY|O_RDWR)) == O_RDONLY ? 1 : 0;
if (!id) {
if (rpmidxInit(idxdb)) {
free(idxdb);
diff --git a/lib/backend/ndb/rpmidx.h b/lib/backend/ndb/rpmidx.h
index e89bd82..9b01fb9 100644
--- a/lib/backend/ndb/rpmidx.h
+++ b/lib/backend/ndb/rpmidx.h
@@ -5,7 +5,7 @@ struct rpmidxdb_s;
typedef struct rpmidxdb_s *rpmidxdb;
int rpmidxOpen(rpmidxdb *idxdbp, rpmpkgdb pkgdb, const char *filename, int flags, int mode);
-int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag);
+int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag, int flags);
int rpmidxDelXdb(rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag);
void rpmidxClose(rpmidxdb idxdbp);
--
1.8.3.1

View File

@ -0,0 +1,190 @@
From aea8c86ec8a73d34f26c77ad40179df92970260f Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 11:07:31 +0200
Subject: [PATCH] ndb: do not map xdb's header read-write all the time
Instead just map it read-write if one of the functions request
exclusive access. We keep track of the number of exclusive
locks and fall back to read-only mapping if the count reaches
zero again.
URL:https://github.com/rpm-software-management/rpm/commit/aea8c86ec8a73d34f26c77ad40179df92970260f
---
lib/backend/ndb/rpmxdb.c | 55 +++++++++++++++++++++++++++++++++++-------------
1 file changed, 40 insertions(+), 15 deletions(-)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index 354a098..ec408f8 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -37,7 +37,7 @@ typedef struct rpmxdb_s {
unsigned int usergeneration;
unsigned char *mapped;
- int mapflags;
+ int mappedrw;
unsigned int mappedlen;
struct xdb_slot {
@@ -58,6 +58,7 @@ typedef struct rpmxdb_s {
unsigned int usedblobpages;
unsigned int systempagesize;
int dofsync;
+ unsigned int locked_excl;
} *rpmxdb;
@@ -126,17 +127,19 @@ static void unmapmem(void *addr, size_t size)
#define ROUNDTOSYSTEMPAGE(xdb, size) (((size) + (xdb->systempagesize - 1)) & ~(xdb->systempagesize - 1))
/* xdb header mapping functions */
-static int mapheader(rpmxdb xdb, unsigned int slotnpages)
+static int mapheader(rpmxdb xdb, unsigned int slotnpages, int rw)
{
unsigned char *mapped;
size_t mappedlen = slotnpages * xdb->pagesize;
+ int mapflags = rw ? PROT_READ | PROT_WRITE : PROT_READ;
mappedlen = ROUNDTOSYSTEMPAGE(xdb, mappedlen);
- mapped = mapmem(xdb->mapped, xdb->mappedlen, mappedlen, xdb->mapflags, xdb->fd, 0);
+ mapped = mapmem(xdb->mapped, xdb->mappedlen, mappedlen, mapflags, xdb->fd, 0);
if ((void *)mapped == MAP_FAILED)
return RPMRC_FAIL;
xdb->mapped = mapped;
xdb->mappedlen = mappedlen;
+ xdb->mappedrw = rw;
return RPMRC_OK;
}
@@ -248,7 +251,7 @@ static int rpmxdbReadHeaderRaw(rpmxdb xdb, unsigned int *generationp, unsigned i
return RPMRC_OK;
}
-static int rpmxdbReadHeader(rpmxdb xdb)
+static int rpmxdbReadHeader(rpmxdb xdb, int rw)
{
struct xdb_slot *slot;
unsigned int slotnpages, pagesize, generation, usergeneration;
@@ -262,6 +265,11 @@ static int rpmxdbReadHeader(rpmxdb xdb)
if (xdb->mapped) {
if (le2ha(xdb->mapped + XDB_OFFSET_GENERATION) == xdb->generation) {
+ if (rw && !xdb->mappedrw) {
+ unmapheader(xdb);
+ if (mapheader(xdb, xdb->slotnpages, rw))
+ return RPMRC_FAIL;
+ }
return RPMRC_OK;
}
unmapheader(xdb);
@@ -274,9 +282,8 @@ static int rpmxdbReadHeader(rpmxdb xdb)
if (stb.st_size % pagesize != 0)
return RPMRC_FAIL;
xdb->pagesize = pagesize;
- xdb->mapflags = xdb->rdonly ? PROT_READ : PROT_READ | PROT_WRITE;
- if (mapheader(xdb, slotnpages))
+ if (mapheader(xdb, slotnpages, rw))
return RPMRC_FAIL;
/* read in all slots */
@@ -476,19 +483,25 @@ static int rpmxdbInitInternal(rpmxdb xdb)
/* we use the master pdb for locking */
static int rpmxdbLockOnly(rpmxdb xdb, int excl)
{
+ int rc;
if (excl && xdb->rdonly)
return RPMRC_FAIL;
- return rpmpkgLock(xdb->pkgdb, excl);
+ rc = rpmpkgLock(xdb->pkgdb, excl);
+ if (!rc && excl)
+ xdb->locked_excl++;
+ return rc;
}
-/* this is the same as rpmxdbLockReadHeader. It does the
+/* This is similar to rpmxdbLockReadHeader. It does the
* ReadHeader to sync the mappings if xdb moved some blobs.
+ * Note that we just ask for rad-only access in the
+ * rpmxdbReadHeader call.
*/
int rpmxdbLock(rpmxdb xdb, int excl)
{
if (rpmxdbLockOnly(xdb, excl))
return RPMRC_FAIL;
- if (rpmxdbReadHeader(xdb)) {
+ if (rpmxdbReadHeader(xdb, 0)) {
rpmxdbUnlock(xdb, excl);
return RPMRC_FAIL;
}
@@ -497,14 +510,25 @@ int rpmxdbLock(rpmxdb xdb, int excl)
int rpmxdbUnlock(rpmxdb xdb, int excl)
{
+ if (excl && xdb->locked_excl) {
+ xdb->locked_excl--;
+ if (!xdb->locked_excl && xdb->mapped && xdb->mappedrw) {
+ unmapheader(xdb);
+ mapheader(xdb, xdb->slotnpages, 0);
+ }
+ }
return rpmpkgUnlock(xdb->pkgdb, excl);
}
+/* Like rpmxdbLock, but map the header rw if excl is set.
+ * This is what the functions in this module use, whereas
+ * rpmidx uses rpmxdbLock.
+ */
static int rpmxdbLockReadHeader(rpmxdb xdb, int excl)
{
if (rpmxdbLockOnly(xdb, excl))
return RPMRC_FAIL;
- if (rpmxdbReadHeader(xdb)) {
+ if (rpmxdbReadHeader(xdb, excl)) {
rpmxdbUnlock(xdb, excl);
return RPMRC_FAIL;
}
@@ -776,7 +800,7 @@ static int addslotpage(rpmxdb xdb)
return RPMRC_FAIL;
/* remap the header */
- if (mapheader(xdb, xdb->slotnpages + 1))
+ if (mapheader(xdb, xdb->slotnpages + 1, xdb->mappedrw))
return RPMRC_FAIL;
/* update the header */
@@ -856,7 +880,8 @@ int rpmxdbLookupBlob(rpmxdb xdb, unsigned int *idp, unsigned int blobtag, unsign
{
struct xdb_slot *slot;
unsigned int i, nslots;
- if (rpmxdbLockReadHeader(xdb, flags ? 1 : 0))
+ int excl = flags ? 1 : 0;
+ if (rpmxdbLockReadHeader(xdb, excl))
return RPMRC_FAIL;
nslots = xdb->nslots;
slot = 0;
@@ -869,18 +894,18 @@ int rpmxdbLookupBlob(rpmxdb xdb, unsigned int *idp, unsigned int blobtag, unsign
i = 0;
if (i && (flags & O_TRUNC) != 0) {
if (rpmxdbResizeBlob(xdb, i, 0)) {
- rpmxdbUnlock(xdb, flags ? 1 : 0);
+ rpmxdbUnlock(xdb, excl);
return RPMRC_FAIL;
}
}
if (!i && (flags & O_CREAT) != 0) {
if (createblob(xdb, &i, blobtag, subtag)) {
- rpmxdbUnlock(xdb, flags ? 1 : 0);
+ rpmxdbUnlock(xdb, excl);
return RPMRC_FAIL;
}
}
*idp = i;
- rpmxdbUnlock(xdb, flags ? 1 : 0);
+ rpmxdbUnlock(xdb, excl);
return i ? RPMRC_OK : RPMRC_NOTFOUND;
}
--
1.8.3.1

View File

@ -0,0 +1,38 @@
From 8e39098fa991b097ec0c746f0b4e3d8ab19a69ee Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 11:45:52 +0100
Subject: [PATCH] ndb: drop unused number of allocated slots
This is not used as we re-read all slots everytime a package
is added or deleted.
URL:https://github.com/rpm-software-management/rpm/commit/8e39098fa991b097ec0c746f0b4e3d8ab19a69ee
---
lib/backend/ndb/rpmpkg.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index eb65049..b613fa5 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -45,7 +45,6 @@ typedef struct rpmpkgdb_s {
unsigned int nextpkgidx;
struct pkgslot_s *slots;
- unsigned int aslots; /* allocated slots */
unsigned int nslots; /* used slots */
unsigned int *slothash;
@@ -256,8 +255,7 @@ static int rpmpkgReadSlots(rpmpkgdb pkgdb)
fileblks = stb.st_size / BLK_SIZE;
/* read (and somewhat verify) all slots */
- pkgdb->aslots = slotnpages * (PAGE_SIZE / SLOT_SIZE);
- pkgdb->slots = xcalloc(pkgdb->aslots, sizeof(*pkgdb->slots));
+ pkgdb->slots = xcalloc(slotnpages * (PAGE_SIZE / SLOT_SIZE), sizeof(*pkgdb->slots));
i = 0;
slot = pkgdb->slots;
minblkoff = slotnpages * (PAGE_SIZE / BLK_SIZE);
--
1.8.3.1

View File

@ -0,0 +1,28 @@
From bc13afbbfdfa33b10bb87e9503b3b06a0d65bfd2 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Jan 2020 17:05:27 +0100
Subject: [PATCH] ndb: fix ftruncate return value warning
URL:https://github.com/rpm-software-management/rpm/commit/bc13afbbfdfa33b10bb87e9503b3b06a0d65bfd2
---
lib/backend/ndb/rpmxdb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index 3baafa6..dbd4942 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -963,7 +963,9 @@ int rpmxdbDelAllBlobs(rpmxdb xdb)
rpmxdbUnlock(xdb, 1);
return RPMRC_FAIL;
}
- ftruncate(xdb->fd, xdb->pagesize);
+ if (ftruncate(xdb->fd, xdb->pagesize)) {
+ /* ftruncate failed, but that is not a problem */
+ }
rpmxdbUnlock(xdb, 1);
return RPMRC_OK;
}
--
1.8.3.1

View File

@ -0,0 +1,80 @@
From 40269d4b3f960e6cb73db1cea0bcc5973f9ce72c Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 15:51:38 +0100
Subject: [PATCH] ndb: implement index regeneration if the index is out of sync
We compare the user generation stored in the index database with
the generation count from the package database. In case there
is a mismatch, we delete all the index databases and rely on the
already existing missing index creation code to rebuild the
database.
URL:https://github.com/rpm-software-management/rpm/commit/40269d4b3f960e6cb73db1cea0bcc5973f9ce72c
---
lib/backend/ndb/glue.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index 841c2fe..90c10f8 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -80,6 +80,31 @@ static int ndb_Close(dbiIndex dbi, unsigned int flags)
return 0;
}
+static void ndb_CheckIndexSync(rpmpkgdb pkgdb, rpmxdb xdb)
+{
+ unsigned int generation, xdb_generation;
+ if (!pkgdb || !xdb)
+ return;
+ if (rpmpkgLock(pkgdb, 0))
+ return;
+ if (rpmpkgGeneration(pkgdb, &generation)) {
+ rpmpkgUnlock(pkgdb, 0);
+ return;
+ }
+ if (!rpmxdbGetUserGeneration(xdb, &xdb_generation) && generation == xdb_generation) {
+ rpmpkgUnlock(pkgdb, 0);
+ return;
+ }
+ rpmpkgUnlock(pkgdb, 0);
+ /* index corrupt or with different generation */
+ if (rpmxdbIsRdonly(xdb)) {
+ rpmlog(RPMLOG_WARNING, _("Detected outdated index databases\n"));
+ } else {
+ rpmlog(RPMLOG_WARNING, _("Rebuilding outdated index databases\n"));
+ rpmxdbDelAllBlobs(xdb);
+ }
+}
+
static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
{
const char *dbhome = rpmdbHome(rdb);
@@ -130,6 +155,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
}
if (!ndbenv->xdb) {
char *path = rstrscat(NULL, dbhome, "/Index.db", NULL);
+ int created = 0;
rpmlog(RPMLOG_DEBUG, "opening db index %s mode=0x%x\n", path, rdb->db_mode);
/* Open indexes readwrite if possible */
@@ -144,6 +170,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
} else if (rc && errno == ENOENT) {
ioflags = O_CREAT|O_RDWR;
rc = rpmxdbOpen(&ndbenv->xdb, rdb->db_pkgs->dbi_db, path, ioflags, 0666);
+ created = 1;
}
if (rc) {
perror("rpmxdbOpen");
@@ -153,6 +180,8 @@ static int ndb_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
}
free(path);
rpmxdbSetFsync(ndbenv->xdb, ndbenv->dofsync);
+ if (!created)
+ ndb_CheckIndexSync(ndbenv->pkgdb, ndbenv->xdb);
}
if (rpmxdbLookupBlob(ndbenv->xdb, &id, rpmtag, 0, 0) == RPMRC_NOTFOUND) {
dbi->dbi_flags |= DBI_CREATED;
--
1.8.3.1

View File

@ -0,0 +1,154 @@
From cbe9bcf954b2043dcefabbda6722ee3e149d8a8b Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 11:44:01 +0100
Subject: [PATCH] ndb: make "ordered slots" flag a boolean
We never needed to order by pkgid or slot number, so simplify
the code.
https://github.com/rpm-software-management/rpm/commit/cbe9bcf954b2043dcefabbda6722ee3e149d8a8b
---
lib/backend/ndb/rpmpkg.c | 43 +++++++++++++++++++------------------------
1 file changed, 19 insertions(+), 24 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index b8e33bf..eb65049 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -52,16 +52,13 @@ typedef struct rpmpkgdb_s {
unsigned int nslothash;
unsigned int freeslot; /* first free slot */
- int slotorder;
+ int ordered; /* slots are ordered by the blk offsets */
char *filename;
unsigned int fileblks; /* file size in blks */
int dofsync;
} * rpmpkgdb;
-#define SLOTORDER_UNORDERED 0
-#define SLOTORDER_BLKOFF 1
-
static inline unsigned int le2h(unsigned char *p)
{
@@ -296,7 +293,7 @@ static int rpmpkgReadSlots(rpmpkgdb pkgdb)
}
}
pkgdb->nslots = i;
- pkgdb->slotorder = SLOTORDER_UNORDERED; /* XXX: always order? */
+ pkgdb->ordered = 0;
pkgdb->fileblks = fileblks;
pkgdb->freeslot = freeslot;
if (rpmpkgHashSlots(pkgdb)) {
@@ -314,15 +311,13 @@ static int orderslots_blkoff_cmp(const void *a, const void *b)
return blkoffa > blkoffb ? 1 : blkoffa < blkoffb ? -1 : 0;
}
-static void rpmpkgOrderSlots(rpmpkgdb pkgdb, int slotorder)
+static void rpmpkgOrderSlots(rpmpkgdb pkgdb)
{
- if (pkgdb->slotorder == slotorder)
+ if (pkgdb->ordered)
return;
- if (slotorder == SLOTORDER_BLKOFF) {
- if (pkgdb->nslots > 1)
- qsort(pkgdb->slots, pkgdb->nslots, sizeof(*pkgdb->slots), orderslots_blkoff_cmp);
- }
- pkgdb->slotorder = slotorder;
+ if (pkgdb->nslots > 1)
+ qsort(pkgdb->slots, pkgdb->nslots, sizeof(*pkgdb->slots), orderslots_blkoff_cmp);
+ pkgdb->ordered = 1;
rpmpkgHashSlots(pkgdb);
}
@@ -347,8 +342,8 @@ static int rpmpkgFindEmptyOffset(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned i
unsigned int lastblkend = pkgdb->slotnpages * (PAGE_SIZE / BLK_SIZE);
pkgslot *slot, *oldslot = 0;
- if (pkgdb->slotorder != SLOTORDER_BLKOFF)
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ if (!pkgdb->ordered)
+ rpmpkgOrderSlots(pkgdb);
if (dontprepend && nslots) {
lastblkend = pkgdb->slots[0].blkoff;
@@ -388,8 +383,8 @@ static int rpmpkgNeighbourCheck(rpmpkgdb pkgdb, unsigned int blkoff, unsigned in
unsigned int lastblkend = pkgdb->slotnpages * (PAGE_SIZE / BLK_SIZE);
pkgslot *slot, *left = 0, *right = 0;
- if (pkgdb->slotorder != SLOTORDER_BLKOFF)
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ if (!pkgdb->ordered)
+ rpmpkgOrderSlots(pkgdb);
if (blkoff < lastblkend)
return RPMRC_FAIL;
for (i = 0, slot = pkgdb->slots; i < nslots; i++, slot++) {
@@ -704,15 +699,15 @@ static int rpmpkgMoveBlob(rpmpkgdb pkgdb, pkgslot *slot, unsigned int newblkoff)
return RPMRC_FAIL;
}
slot->blkoff = newblkoff;
- pkgdb->slotorder = SLOTORDER_UNORDERED;
+ pkgdb->ordered = 0;
return RPMRC_OK;
}
static int rpmpkgAddSlotPage(rpmpkgdb pkgdb)
{
unsigned int cutoff;
- if (pkgdb->slotorder != SLOTORDER_BLKOFF)
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ if (!pkgdb->ordered)
+ rpmpkgOrderSlots(pkgdb);
cutoff = (pkgdb->slotnpages + 1) * (PAGE_SIZE / BLK_SIZE);
/* now move every blob before cutoff */
@@ -730,7 +725,7 @@ static int rpmpkgAddSlotPage(rpmpkgdb pkgdb)
if (rpmpkgMoveBlob(pkgdb, slot, newblkoff)) {
return RPMRC_FAIL;
}
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ rpmpkgOrderSlots(pkgdb);
}
/* make sure our new page is empty */
@@ -1008,7 +1003,7 @@ static int rpmpkgPutInternal(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char
/* just update the slot, no need to free the slot data */
oldslot->blkoff = blkoff;
oldslot->blkcnt = blkcnt;
- pkgdb->slotorder = SLOTORDER_UNORDERED;
+ pkgdb->ordered = 0;
} else {
free(pkgdb->slots);
pkgdb->slots = 0;
@@ -1025,7 +1020,7 @@ static int rpmpkgDelInternal(rpmpkgdb pkgdb, unsigned int pkgidx)
if (rpmpkgReadSlots(pkgdb)) {
return RPMRC_FAIL;
}
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ rpmpkgOrderSlots(pkgdb);
slot = rpmpkgFindSlot(pkgdb, pkgidx);
if (!slot) {
return RPMRC_OK;
@@ -1068,7 +1063,7 @@ static int rpmpkgDelInternal(rpmpkgdb pkgdb, unsigned int pkgidx)
blkoff += slot->blkcnt;
blkcnt -= slot->blkcnt;
}
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ rpmpkgOrderSlots(pkgdb);
} else {
slot->blkoff = 0;
slot->blkcnt = 0;
@@ -1107,7 +1102,7 @@ static int rpmpkgListInternal(rpmpkgdb pkgdb, unsigned int **pkgidxlistp, unsign
*npkgidxlistp = pkgdb->nslots;
return RPMRC_OK;
}
- rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+ rpmpkgOrderSlots(pkgdb);
nslots = pkgdb->nslots;
pkgidxlist = xcalloc(nslots + 1, sizeof(unsigned int));
for (i = 0, slot = pkgdb->slots; i < nslots; i++, slot++) {
--
1.8.3.1

View File

@ -0,0 +1,39 @@
From 6511823c97c6f40b8d99961767537f4f3bebc16e Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 11:27:46 +0200
Subject: [PATCH] ndb: make rpmxdbWriteHeader a void function
It's a static function and nobody tests the return code. It just
writes into mapped memory like rpmxdbUpdateSlot, which is also void.
URL:https://github.com/rpm-software-management/rpm/commit/6511823c97c6f40b8d99961767537f4f3bebc16e
---
lib/backend/ndb/rpmxdb.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index ab22746..be85fdc 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -392,17 +392,14 @@ static int rpmxdbReadHeader(rpmxdb xdb, int rw)
return RPMRC_OK;
}
-static int rpmxdbWriteHeader(rpmxdb xdb)
+static void rpmxdbWriteHeader(rpmxdb xdb)
{
- if (!xdb->mapped)
- return RPMRC_FAIL;
h2lea(XDB_MAGIC, xdb->mapped + XDB_OFFSET_MAGIC);
h2lea(XDB_VERSION, xdb->mapped + XDB_OFFSET_VERSION);
h2lea(xdb->generation, xdb->mapped + XDB_OFFSET_GENERATION);
h2lea(xdb->slotnpages, xdb->mapped + XDB_OFFSET_SLOTNPAGES);
h2lea(xdb->pagesize, xdb->mapped + XDB_OFFSET_PAGESIZE);
h2lea(xdb->usergeneration, xdb->mapped + XDB_OFFSET_USERGENERATION);
- return RPMRC_OK;
}
static void rpmxdbUpdateSlot(rpmxdb xdb, struct xdb_slot *slot)
--
1.8.3.1

View File

@ -0,0 +1,70 @@
From d435beb937ca38a3d3f1c6acb1b3ca06dcb3544d Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 11:51:07 +0100
Subject: [PATCH] ndb: no longer free the pkgid hash all the time
Reuse the hash if the size matches. This was actually the original
intention, but for some reason the code was disabled by always
freeing the hash.
URL:https://github.com/rpm-software-management/rpm/commit/d435beb937ca38a3d3f1c6acb1b3ca06dcb3544d
---
lib/backend/ndb/rpmpkg.c | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index b613fa5..b95f29f 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -136,10 +136,6 @@ static int rpmpkgReadHeader(rpmpkgdb pkgdb)
if (pkgdb->slots && (pkgdb->generation != generation || pkgdb->slotnpages != slotnpages)) {
free(pkgdb->slots);
pkgdb->slots = 0;
- if (pkgdb->slothash) {
- free(pkgdb->slothash);
- pkgdb->slothash = 0;
- }
}
pkgdb->generation = generation;
pkgdb->slotnpages = slotnpages;
@@ -201,14 +197,14 @@ static int rpmpkgHashSlots(rpmpkgdb pkgdb)
int i;
pkgslot *slot;
- pkgdb->nslothash = 0;
- num = pkgdb->nslots;
+ num = pkgdb->nslots + 32;
while (num & (num - 1))
num = num & (num - 1);
num *= 4;
hash = pkgdb->slothash;
if (!hash || pkgdb->nslothash != num) {
- free(pkgdb->slothash);
+ if (hash)
+ free(hash);
hash = pkgdb->slothash = xcalloc(num, sizeof(unsigned int));
pkgdb->nslothash = num;
} else {
@@ -221,8 +217,6 @@ static int rpmpkgHashSlots(rpmpkgdb pkgdb)
;
hash[h] = i + 1;
}
- pkgdb->slothash = hash;
- pkgdb->nslothash = num;
return RPMRC_OK;
}
@@ -240,10 +234,6 @@ static int rpmpkgReadSlots(rpmpkgdb pkgdb)
free(pkgdb->slots);
pkgdb->slots = 0;
}
- if (pkgdb->slothash) {
- free(pkgdb->slothash);
- pkgdb->slothash = 0;
- }
pkgdb->nslots = 0;
pkgdb->freeslot = 0;
--
1.8.3.1

View File

@ -5,12 +5,14 @@ Subject: [PATCH] ndb: only clear the dbenv in the rpmdb if the last reference
is gone
Otherwise we will segfault if just one index is closed.
URL:https://github.com/rpm-software-management/rpm/commit/52c3ee60a1ce0e7e527dc396dd1e1a0e29b7b0ed
---
lib/backend/ndb/glue.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/backend/ndb/glue.c b/lib/backend/ndb/glue.c
index 376e360e3..841c2fe42 100644
index 376e360..841c2fe 100644
--- a/lib/backend/ndb/glue.c
+++ b/lib/backend/ndb/glue.c
@@ -52,8 +52,8 @@ static void closeEnv(rpmdb rdb)
@ -24,5 +26,5 @@ index 376e360e3..841c2fe42 100644
static struct ndbEnv_s *openEnv(rpmdb rdb)
--
2.27.0
1.8.3.1

View File

@ -0,0 +1,121 @@
From dc0a504d3e893e40df60bd8a4a45852dcfca307a Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 11:26:49 +0100
Subject: [PATCH] ndb: remove unused lzo compression code
URL:https://github.com/rpm-software-management/rpm/commit/dc0a504d3e893e40df60bd8a4a45852dcfca307a
---
lib/backend/ndb/rpmpkg.c | 78 ------------------------------------------------
1 file changed, 78 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index 0809af1..94ecde1 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -19,10 +19,6 @@
#define RPMRC_NOTFOUND 1
#define RPMRC_OK 0
-#ifdef RPMPKG_LZO
-static int rpmpkgLZOCompress(unsigned char **blobp, unsigned int *bloblp);
-static int rpmpkgLZODecompress(unsigned char **blobp, unsigned int *bloblp);
-#endif
static int rpmpkgVerifyblob(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blkoff, unsigned int blkcnt);
@@ -1127,10 +1123,6 @@ int rpmpkgGet(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char **blobp, unsign
return RPMRC_FAIL;
rc = rpmpkgGetInternal(pkgdb, pkgidx, blobp, bloblp);
rpmpkgUnlock(pkgdb, 0);
-#ifdef RPMPKG_LZO
- if (!rc)
- rc = rpmpkgLZODecompress(blobp, bloblp);
-#endif
return rc;
}
@@ -1143,16 +1135,7 @@ int rpmpkgPut(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char *blob, unsigned
}
if (rpmpkgLockReadHeader(pkgdb, 1))
return RPMRC_FAIL;
-#ifdef RPMPKG_LZO
- if (rpmpkgLZOCompress(&blob, &blobl)) {
- rpmpkgUnlock(pkgdb, 1);
- return RPMRC_FAIL;
- }
-#endif
rc = rpmpkgPutInternal(pkgdb, pkgidx, blob, blobl);
-#ifdef RPMPKG_LZO
- free(blob);
-#endif
rpmpkgUnlock(pkgdb, 1);
return rc;
}
@@ -1233,64 +1216,3 @@ int rpmpkgStats(rpmpkgdb pkgdb)
return RPMRC_OK;
}
-#ifdef RPMPKG_LZO
-
-#include "lzo/lzoconf.h"
-#include "lzo/lzo1x.h"
-
-#define BLOBLZO_MAGIC ('L' | 'Z' << 8 | 'O' << 16 | 'B' << 24)
-
-static int rpmpkgLZOCompress(unsigned char **blobp, unsigned int *bloblp)
-{
- unsigned char *blob = *blobp;
- unsigned int blobl = *bloblp;
- unsigned char *lzoblob, *workmem;
- unsigned int lzoblobl;
- lzo_uint blobl2;
-
- if (lzo_init() != LZO_E_OK) {
- return RPMRC_FAIL;
- }
- workmem = xmalloc(LZO1X_1_MEM_COMPRESS);
- lzoblobl = 4 + 4 + blobl + blobl / 16 + 64 + 3;
- lzoblob = xmalloc(lzoblobl);
- h2le(BLOBLZO_MAGIC, lzoblob);
- h2le(blobl, lzoblob + 4);
- if (lzo1x_1_compress(blob, blobl, lzoblob + 8, &blobl2, workmem) != LZO_E_OK) {
- free(workmem);
- free(lzoblob);
- return RPMRC_FAIL;
- }
- free(workmem);
- *blobp = lzoblob;
- *bloblp = 8 + blobl2;
- return RPMRC_OK;
-}
-
-static int rpmpkgLZODecompress(unsigned char **blobp, unsigned int *bloblp)
-{
- unsigned char *lzoblob = *blobp;
- unsigned int lzoblobl = *bloblp;
- unsigned char *blob;
- unsigned int blobl;
- lzo_uint blobl2;
-
- if (!lzoblob || lzoblobl < 8)
- return RPMRC_FAIL;
- if (le2h(lzoblob) != BLOBLZO_MAGIC)
- return RPMRC_FAIL;
- if (lzo_init() != LZO_E_OK)
- return RPMRC_FAIL;
- blobl = le2h(lzoblob + 4);
- blob = xmalloc(blobl ? blobl : 1);
- if (lzo1x_decompress(lzoblob + 8, lzoblobl - 8, blob, &blobl2, 0) != LZO_E_OK || blobl2 != blobl) {
- free(blob);
- return RPMRC_FAIL;
- }
- free(lzoblob);
- *blobp = blob;
- *bloblp = blobl;
- return RPMRC_OK;
-}
-
-#endif
--
1.8.3.1

View File

@ -0,0 +1,30 @@
From 1187cf005a2821d5f239bec1a0ecddfef190a125 Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Tue, 14 Apr 2020 11:22:39 +0200
Subject: [PATCH] ndb: unmap xdb's header when closing the xdb database
Somehow I was under the impression that mapped regions are unmapped when
the corresponding file descriptor is closed, but that's not the case
for POSIX systems.
URL:https://github.com/rpm-software-management/rpm/commit/1187cf005a2821d5f239bec1a0ecddfef190a125
---
lib/backend/ndb/rpmxdb.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/backend/ndb/rpmxdb.c b/lib/backend/ndb/rpmxdb.c
index ec408f8..ab22746 100644
--- a/lib/backend/ndb/rpmxdb.c
+++ b/lib/backend/ndb/rpmxdb.c
@@ -621,6 +621,8 @@ void rpmxdbClose(rpmxdb xdb)
}
if (xdb->slots)
free(xdb->slots);
+ if (xdb->mapped)
+ unmapheader(xdb);
if (xdb->fd >= 0)
close(xdb->fd);
if (xdb->filename)
--
1.8.3.1

View File

@ -0,0 +1,99 @@
From f674af7efbeeb44d6c0f0da8c611e6cd7257ee4f Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Fri, 10 Jan 2020 12:00:49 +0100
Subject: [PATCH] ndb: use the generation instead of the current time in blobs
This seems to saner as the somewhat unreliable current time.
This element is not used in normal database operation, it is
for repair tools that need to decide which blob to take if two
blobs have the same pkgid.
URL:https://github.com/rpm-software-management/rpm/commit/f674af7efbeeb44d6c0f0da8c611e6cd7257ee4f
---
lib/backend/ndb/rpmpkg.c | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/lib/backend/ndb/rpmpkg.c b/lib/backend/ndb/rpmpkg.c
index 2213872..922ae11 100644
--- a/lib/backend/ndb/rpmpkg.c
+++ b/lib/backend/ndb/rpmpkg.c
@@ -7,7 +7,6 @@
#include <sys/file.h>
#include <fcntl.h>
#include <stdio.h>
-#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
@@ -511,7 +510,7 @@ static int rpmpkgValidateZero(rpmpkgdb pkgdb, unsigned int blkoff, unsigned int
/*** Blob primitives ***/
-/* head: magic + pkgidx + timestamp + bloblen */
+/* head: magic + pkgidx + generation + bloblen */
/* tail: adler32 + bloblen + magic */
#define BLOBHEAD_MAGIC ('B' | 'l' << 8 | 'b' << 16 | 'S' << 24)
@@ -520,10 +519,10 @@ static int rpmpkgValidateZero(rpmpkgdb pkgdb, unsigned int blkoff, unsigned int
#define BLOBHEAD_SIZE (4 + 4 + 4 + 4)
#define BLOBTAIL_SIZE (4 + 4 + 4)
-static int rpmpkgReadBlob(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blkoff, unsigned int blkcnt, unsigned char *blob, unsigned int *bloblp, unsigned int *tstampp)
+static int rpmpkgReadBlob(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blkoff, unsigned int blkcnt, unsigned char *blob, unsigned int *bloblp, unsigned int *generationp)
{
unsigned char buf[BLOBHEAD_SIZE > BLOBTAIL_SIZE ? BLOBHEAD_SIZE : BLOBTAIL_SIZE];
- unsigned int bloblen, toread, tstamp;
+ unsigned int bloblen, toread, generation;
off_t fileoff;
unsigned int adl;
int verifyadler = bloblp ? 0 : 1;
@@ -539,7 +538,7 @@ static int rpmpkgReadBlob(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blko
return RPMRC_FAIL; /* bad blob */
if (le2h(buf + 4) != pkgidx)
return RPMRC_FAIL; /* bad blob */
- tstamp = le2h(buf + 8);
+ generation = le2h(buf + 8);
bloblen = le2h(buf + 12);
if (blkcnt != (BLOBHEAD_SIZE + bloblen + BLOBTAIL_SIZE + BLK_SIZE - 1) / BLK_SIZE)
return RPMRC_FAIL; /* bad blob */
@@ -584,8 +583,8 @@ static int rpmpkgReadBlob(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blko
}
if (bloblp)
*bloblp = bloblen;
- if (tstampp)
- *tstampp = tstamp;
+ if (generationp)
+ *generationp = generation;
return RPMRC_OK;
}
@@ -668,14 +667,14 @@ static int rpmpkgMoveBlob(rpmpkgdb pkgdb, pkgslot *slot, unsigned int newblkoff)
unsigned int blkoff = slot->blkoff;
unsigned int blkcnt = slot->blkcnt;
unsigned char *blob;
- unsigned int tstamp, blobl;
+ unsigned int generation, blobl;
blob = xmalloc((size_t)blkcnt * BLK_SIZE);
- if (rpmpkgReadBlob(pkgdb, pkgidx, blkoff, blkcnt, blob, &blobl, &tstamp)) {
+ if (rpmpkgReadBlob(pkgdb, pkgidx, blkoff, blkcnt, blob, &blobl, &generation)) {
free(blob);
return RPMRC_FAIL;
}
- if (rpmpkgWriteBlob(pkgdb, pkgidx, newblkoff, blkcnt, blob, blobl, tstamp)) {
+ if (rpmpkgWriteBlob(pkgdb, pkgidx, newblkoff, blkcnt, blob, blobl, generation)) {
free(blob);
return RPMRC_FAIL;
}
@@ -966,7 +965,7 @@ static int rpmpkgPutInternal(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned char
return RPMRC_FAIL;
}
/* write new blob */
- if (rpmpkgWriteBlob(pkgdb, pkgidx, blkoff, blkcnt, blob, blobl, (unsigned int)time(0))) {
+ if (rpmpkgWriteBlob(pkgdb, pkgidx, blkoff, blkcnt, blob, blobl, pkgdb->generation)) {
return RPMRC_FAIL;
}
/* write slot */
--
1.8.3.1

View File

@ -1,6 +1,6 @@
Name: rpm
Version: 4.15.1
Release: 19
Release: 20
Summary: RPM Package Manager
License: GPLv2+
URL: http://www.rpm.org/
@ -28,31 +28,62 @@ Patch17: backport-Fix-resource-leaks-on-zstd-open-error-paths.patch
Patch18: backport-rpmio-initialise-libgcrypt.patch
Patch19: backport-fix-zstd-magic.patch
Patch20: backport-Don-t-require-signature-header-to-be-in-single-conti.patch
Patch21: backport-ndb-only-clear-the-dbenv-in-the-rpmdb-if-the-last-re.patch
Patch22: backport-Fix-regression-on-v3-package-handling-on-database-re.patch
Patch23: backport-Fix-a-minor-memory-leak-on-suppressed-inhibition-loc.patch
Patch24: backport-Fix-POPT_ARG_STRING-memleaks-in-librpmbuild.patch
Patch25: backport-Fix-build-regression-in-commit-307872f71b357a3839fd0.patch
Patch26: backport-Fix-isUnorderedReq-for-multiple-qualifiers.patch
Patch27: backport-If-fork-fails-in-getOutputFrom-close-opened-unused-p.patch
Patch28: backport-Fix-pointer-dereference-before-testing-for-NULL-in-r.patch
Patch29: backport-Don-t-look-into-source-package-provides-in-depsolvin.patch
Patch30: backport-rpmfiArchiveRead-use-signed-return-value-to-handle-1.patch
Patch31: backport-Fix-bump-up-the-limit-of-signature-header-to-64MB.patch
Patch32: backport-Remove-compare-of-global-array-tagsByName-to-NULL.patch
Patch33: backport-Always-close-libelf-handle-1313.patch
Patch34: backport-Add-missing-terminator-to-copyTagsFromMainDebug-arra.patch
Patch35: backport-Fix-possible-read-beyond-buffer-in-rstrnlenhash.patch
Patch36: backport-Make-fdSeek-return-0-on-success-1-on-error.patch
Patch37: backport-Fix-logic-error-in-grabArgs.patch
Patch38: backport-Use-libelf-for-determining-file-colors.patch
Patch21: backport-Fix-regression-on-v3-package-handling-on-database-re.patch
Patch22: backport-Fix-a-minor-memory-leak-on-suppressed-inhibition-loc.patch
Patch23: backport-Fix-POPT_ARG_STRING-memleaks-in-librpmbuild.patch
Patch24: backport-Fix-build-regression-in-commit-307872f71b357a3839fd0.patch
Patch25: backport-Fix-isUnorderedReq-for-multiple-qualifiers.patch
Patch26: backport-If-fork-fails-in-getOutputFrom-close-opened-unused-p.patch
Patch27: backport-Fix-pointer-dereference-before-testing-for-NULL-in-r.patch
Patch28: backport-Don-t-look-into-source-package-provides-in-depsolvin.patch
Patch29: backport-rpmfiArchiveRead-use-signed-return-value-to-handle-1.patch
Patch30: backport-Fix-bump-up-the-limit-of-signature-header-to-64MB.patch
Patch31: backport-Remove-compare-of-global-array-tagsByName-to-NULL.patch
Patch32: backport-Always-close-libelf-handle-1313.patch
Patch33: backport-Add-missing-terminator-to-copyTagsFromMainDebug-arra.patch
Patch34: backport-Fix-possible-read-beyond-buffer-in-rstrnlenhash.patch
Patch35: backport-Make-fdSeek-return-0-on-success-1-on-error.patch
Patch36: backport-Fix-logic-error-in-grabArgs.patch
Patch37: backport-Use-libelf-for-determining-file-colors.patch
BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel libdb-devel
Patch38: backport-Add-backend-name-and-path-of-main-database-file-to-d.patch
Patch39: backport-Use-paths-from-db_ops-in-the-backends-too-where-poss.patch
Patch40: backport-Use-the-new-backend-struct-data-for-backend-configur.patch
Patch41: backport-Add-support-for-reading-BDB-without-the-library.patch
Patch42: backport-Fix-building-with-no-BerkeleyDB-support.patch
Patch43: backport-Implement-a-key-only-rpmdb-index-iterator.patch
Patch44: backport-ndb-remove-unused-lzo-compression-code.patch
Patch45: backport-ndb-make-ordered-slots-flag-a-boolean.patch
Patch46: backport-ndb-drop-unused-number-of-allocated-slots.patch
Patch47: backport-ndb-no-longer-free-the-pkgid-hash-all-the-time.patch
Patch48: backport-ndb-add-a-verify-method.patch
Patch49: backport-ndb-use-the-generation-instead-of-the-current-time-i.patch
Patch50: backport-ndb-only-clear-the-dbenv-in-the-rpmdb-if-the-last-re.patch
Patch51: backport-ndb-add-a-rpmxdbDelAllBlobs-method.patch
Patch52: backport-ndb-implement-index-regeneration-if-the-index-is-out.patch
Patch53: backport-Remove-the-experimental-status-from-the-ndb-database.patch
Patch54: backport-ndb-fix-ftruncate-return-value-warning.patch
Patch55: backport-Permit-ndb-database-queries-on-read-only-media.patch
Patch56: backport-ndb-add-a-rpmpkgSalvage-method.patch
Patch57: backport-Add-a-salvagedb-option-to-the-rpmdb-tool.patch
Patch58: backport-Flush-1998-vintage-dirent.h-compatibility-mess-from-.patch
Patch59: backport-ndb-also-copy-the-mapped-pointer-when-keeping-a-slot.patch
Patch60: backport-ndb-do-not-map-the-index-databases-read-write-all-th.patch
Patch61: backport-ndb-do-not-map-xdb-s-header-read-write-all-the-time.patch
Patch62: backport-ndb-unmap-xdb-s-header-when-closing-the-xdb-database.patch
Patch63: backport-ndb-make-rpmxdbWriteHeader-a-void-function.patch
Patch64: backport-Add-an-index-sync-call-at-the-end-of-a-database-rebu.patch
Patch65: backport-Deprecate-Berkeley-DB-database-backend.patch
Patch66: backport-Always-open-and-initialize-the-entire-database-at-on.patch
Patch67: backport-Stop-on-first-failure-when-trying-to-open-a-database.patch
Patch68: backport-Only-attempt-loading-the-keyring-once-the-rpmdb-is-o.patch
BuildRequires: gcc autoconf automake libtool make gawk popt-devel openssl-devel readline-devel
BuildRequires: zlib-devel libzstd-devel xz-devel bzip2-devel libarchive-devel ima-evm-utils-devel
BuildRequires: dbus-devel fakechroot elfutils-devel elfutils-libelf-devel ima-evm-utils
BuildRequires: lua-devel libcap-devel libacl-devel libselinux-devel file-devel gettext-devel ncurses-devel
BuildRequires: system-rpm-config gdb dwz
Requires: coreutils popt curl zstd libcap gnupg2 crontabs logrotate libdb-utils %{name}-libs
Requires: coreutils popt curl zstd libcap gnupg2 crontabs logrotate %{name}-libs
Obsoletes: %{name}-build-libs %{name}-sign-libs %{name}-sign %{name}-cron
Provides: %{name}-build-libs %{name}-sign-libs %{name}-sign %{name}-cron
Obsoletes: %{name}-plugin-selinux %{name}-plugin-syslog %{name}-plugin-systemd-inhibit %{name}-plugin-ima %{name}-plugin-prioreset
@ -130,6 +161,7 @@ Obsoletes: apidocs
%autosetup -n %{name}-%{version} -p1
sed -ie 's:^python test:python2 test:g' tests/rpmtests tests/local.at
sed -i -e "/_db_backend/ s/ bdb/ ndb/g" macros.in
%build
CPPFLAGS="$CPPFLAGS -DLUA_COMPAT_APIINTCASTS"
@ -157,6 +189,9 @@ done;
--with-selinux \
--with-cap \
--with-acl \
--enable-ndb \
--enable-bdb-ro \
--enable-bdb=no \
--with-imaevm \
--enable-zstd \
--enable-python \
@ -190,14 +225,8 @@ mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/rpm
mkdir -p $RPM_BUILD_ROOT%{_rpmconfigdir}/macros.d
mkdir -p $RPM_BUILD_ROOT/var/lib/rpm
for dbi in \
Basenames Conflictname Dirnames Group Installtid Name Obsoletename \
Packages Providename Requirename Triggername Sha1header Sigmd5 \
__db.001 __db.002 __db.003 __db.004 __db.005 __db.006 __db.007 \
__db.008 __db.009
do
touch $RPM_BUILD_ROOT/var/lib/rpm/$dbi
done
./rpmdb --define "_db_backend ndb" --dbpath=${PWD}/ndb --initdb
cp -va ndb/. $RPM_BUILD_ROOT/var/lib/rpm/
#./rpmdb --dbpath=$RPM_BUILD_ROOT/var/lib/rpm --initdb
@ -234,7 +263,8 @@ make check || (cat tests/rpmtests.log; exit 0)
%config(noreplace) %{_sysconfdir}/logrotate.d/rpm
%dir %{_sysconfdir}/rpm
%dir /var/lib/rpm
%attr(0644, root, root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/lib/rpm/*
%attr(0644, root, root) %ghost %config(missingok,noreplace) /var/lib/rpm/*
%attr(0644, root, root) %ghost /var/lib/rpm/.*.lock
%lang(fr) %{_mandir}/fr/man[18]/*.[18]*
%lang(ko) %{_mandir}/ko/man[18]/*.[18]*
%lang(ja) %{_mandir}/ja/man[18]/*.[18]*
@ -314,7 +344,13 @@ make check || (cat tests/rpmtests.log; exit 0)
%{_mandir}/man1/gendiff.1*
%changelog
* Fri Jan 11 2021 Liquor <lirui130@huawei.com> - 4.15.1-19
* Tue Jan 12 2021 panxiaohe <panxiaohe@huawei.com> - 4.15.1-20
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:use ndb instead of Berkeley DB, and deprecate Berkeley DB.
* Mon Jan 11 2021 Liquor <lirui130@huawei.com> - 4.15.1-19
- Type:enhancement
- ID:NA
- SUG:NA