File ndb-backport.diff of Package rpm-ndb.21495

--- ./lib/backend/ndb/glue.c.orig	2020-01-16 15:11:26.181880288 +0000
+++ ./lib/backend/ndb/glue.c	2020-01-16 15:11:26.181880288 +0000
@@ -30,6 +30,7 @@ struct ndbEnv_s {
     rpmpkgdb pkgdb;
     rpmxdb xdb;
     int refs;
+    int dofsync;
 
     unsigned int hdrNum;
     void *data;
@@ -58,8 +59,10 @@ static void closeEnv(rpmdb rdb)
 static struct ndbEnv_s *openEnv(rpmdb rdb)
 {
     struct ndbEnv_s *ndbenv = rdb->db_dbenv;
-    if (!ndbenv)
+    if (!ndbenv) {
 	rdb->db_dbenv = ndbenv = xcalloc(1, sizeof(struct ndbEnv_s));
+	ndbenv->dofsync = 1;
+    }
     ndbenv->refs++;
     return ndbenv;
 }
@@ -77,6 +80,31 @@ static int ndb_Close(dbiIndex dbi, unsig
     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);
@@ -114,6 +142,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag
 	}
 	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;
@@ -126,6 +155,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag
 	}
 	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 */
@@ -140,6 +170,7 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag
 	    } 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");
@@ -148,6 +179,9 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag
 		return 1;
 	    }
 	    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;
@@ -174,11 +208,25 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag
 
 static int ndb_Verify(dbiIndex dbi, unsigned int flags)
 {
-    return 1;
+    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)
 {
+    struct ndbEnv_s *ndbenv = rdb->db_dbenv;
+    if (ndbenv) {
+	ndbenv->dofsync = enable;
+	if (ndbenv->pkgdb)
+	    rpmpkgSetFsync(ndbenv->pkgdb, enable);
+	if (ndbenv->xdb)
+	    rpmxdbSetFsync(ndbenv->xdb, enable);
+    }
 }
 
 static int indexSync(rpmpkgdb pkgdb, rpmxdb xdb)
@@ -383,15 +431,15 @@ static rpmRC ndb_idxdbIter(dbiIndex dbi,
 	}
 	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);
--- ./lib/backend/ndb/rpmidx.c.orig	2020-01-16 15:11:26.181880288 +0000
+++ ./lib/backend/ndb/rpmidx.c	2020-01-16 15:11:26.181880288 +0000
@@ -66,8 +66,6 @@
 typedef struct rpmidxdb_s {
     rpmpkgdb pkgdb;		/* master database */
 
-    char *filename;
-    int fd;			/* our file descriptor */
     int flags;
     int mode;
 
@@ -166,36 +164,13 @@ static void mapcb(rpmxdb xdb, void *data
     set_mapped((rpmidxdb)data, newaddr, (unsigned int)newsize);
 }
 
-static int rpmidxReadHeader(rpmidxdb idxdb);
-
 static int rpmidxMap(rpmidxdb idxdb)
 {
-    if (idxdb->xdb) {
-	if (rpmxdbMapBlob(idxdb->xdb, idxdb->xdbid, idxdb->rdonly ? O_RDONLY : O_RDWR, mapcb, idxdb))
-	    return RPMRC_FAIL;
-	if (idxdb->file_size < 4096) {
-	    rpmxdbUnmapBlob(idxdb->xdb, idxdb->xdbid);
-	    return RPMRC_FAIL;
-	}
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	struct stat stb;
-	size_t size;
-	void *mapped;
-	if (fstat(idxdb->fd, &stb))
-	    return RPMRC_FAIL;
-	size = stb.st_size;
-	if (size < 4096)
-	    return RPMRC_FAIL;
-	/* round up for mmap */
-	size = (size + idxdb->pagesize - 1) & ~(idxdb->pagesize - 1);
-	mapped = mmap(0, size, idxdb->rdonly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, idxdb->fd, 0);
-	if (mapped == MAP_FAILED)
-	    return RPMRC_FAIL;
-	set_mapped(idxdb, mapped, (unsigned int)stb.st_size);
-#else
+    if (rpmxdbMapBlob(idxdb->xdb, idxdb->xdbid, idxdb->rdonly ? O_RDONLY : O_RDWR, mapcb, idxdb))
+	return RPMRC_FAIL;
+    if (idxdb->file_size < 4096) {
+	rpmxdbUnmapBlob(idxdb->xdb, idxdb->xdbid);
 	return RPMRC_FAIL;
-#endif
     }
     return RPMRC_OK;
 }
@@ -204,47 +179,8 @@ static void rpmidxUnmap(rpmidxdb idxdb)
 {
     if (!idxdb->head_mapped)
 	return;
-    if (idxdb->xdb) {
-	rpmxdbUnmapBlob(idxdb->xdb, idxdb->xdbid);
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	size_t size = idxdb->file_size;
-	/* round up for munmap */
-	size = (size + idxdb->pagesize - 1) & ~(idxdb->pagesize - 1);
-	munmap(idxdb->head_mapped, size);
-	set_mapped(idxdb, 0, 0);
-#else
-	return;
-#endif
-    }
-}
-
-#ifdef IDXDB_FILESUPPORT
-static int rpmidxReadHeader(rpmidxdb idxdb);
-
-/* re-open file to get the new version */
-static int rpmidxHandleObsolete(rpmidxdb idxdb)
-{
-    int nfd;
-    struct stat stb1, stb2;
-
-    if (fstat(idxdb->fd, &stb1))
-	return RPMRC_FAIL;
-    nfd = open(idxdb->filename, idxdb->rdonly ? O_RDONLY : O_RDWR, 0);
-    if (nfd == -1)
-	return RPMRC_FAIL;
-    if (fstat(nfd, &stb2)) {
-	close(nfd);
-	return RPMRC_FAIL;
-    }
-    if (stb1.st_dev == stb2.st_dev && stb1.st_ino == stb2.st_ino)
-	return RPMRC_FAIL;		/* openend the same obsolete file */
-    rpmidxUnmap(idxdb);
-    close(idxdb->fd);
-    idxdb->fd = nfd;
-    return rpmidxReadHeader(idxdb);	/* re-try with new file */
+    rpmxdbUnmapBlob(idxdb->xdb, idxdb->xdbid);
 }
-#endif
 
 static int rpmidxReadHeader(rpmidxdb idxdb)
 {
@@ -270,10 +206,6 @@ static int rpmidxReadHeader(rpmidxdb idx
 	rpmidxUnmap(idxdb);
 	return RPMRC_FAIL;
     }
-#ifdef IDXDB_FILESUPPORT
-    if (!idxdb->xdb && le2ha(idxdb->head_mapped + IDXDB_OFFSET_OBSOLETE))
-	return rpmidxHandleObsolete(idxdb);
-#endif
     idxdb->generation = le2ha(idxdb->head_mapped + IDXDB_OFFSET_GENERATION);
     idxdb->nslots     = le2ha(idxdb->head_mapped + IDXDB_OFFSET_NSLOTS);
     idxdb->usedslots  = le2ha(idxdb->head_mapped + IDXDB_OFFSET_USEDSLOTS);
@@ -336,23 +268,6 @@ static inline void bumpGeneration(rpmidx
     h2lea(idxdb->generation, idxdb->head_mapped + IDXDB_OFFSET_GENERATION);
 }
 
-#ifdef IDXDB_FILESUPPORT
-static int createempty(rpmidxdb idxdb, off_t off, size_t size)
-{
-    char buf[4096];
-    memset(buf, 0, sizeof(buf));
-    while (size >= 4096) {
-	if (pwrite(idxdb->fd, buf, 4096, off) != 4096)
-	    return RPMRC_FAIL;
-	off += 4096;
-	size -= 4096;
-    }
-    if (size > 0 && pwrite(idxdb->fd, buf, size , off) != size)
-	return RPMRC_FAIL;
-    return RPMRC_OK;
-}
-#endif
-
 /*** Key management ***/
 
 #define MURMUR_M 0x5bd1e995
@@ -452,29 +367,8 @@ static inline int equalkey(rpmidxdb idxd
 static int addkeypage(rpmidxdb idxdb) {
     unsigned int addsize = idxdb->pagesize > IDXDB_KEY_CHUNKSIZE ? idxdb->pagesize : IDXDB_KEY_CHUNKSIZE;
 
-    if (idxdb->xdb) {
-	if (rpmxdbResizeBlob(idxdb->xdb, idxdb->xdbid, idxdb->file_size + addsize))
-	    return RPMRC_FAIL;
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	/* don't use ftruncate because we want to create a "backed" page */
-	void *newaddr;
-	size_t oldsize, newsize;
-	if (createempty(idxdb, idxdb->file_size, addsize))
-	    return RPMRC_FAIL;
-	oldsize = idxdb->file_size;
-	newsize = idxdb->file_size + addsize;
-	/* round up for mremap */
-	oldsize = (oldsize + idxdb->pagesize - 1) & ~(idxdb->pagesize - 1);
-	newsize = (newsize + idxdb->pagesize - 1) & ~(idxdb->pagesize - 1);
-	newaddr = mremap(idxdb->head_mapped, oldsize, newsize, MREMAP_MAYMOVE);
-	if (newaddr == MAP_FAILED)
-	    return RPMRC_FAIL;
-	set_mapped(idxdb, newaddr, idxdb->file_size + addsize);
-#else
+    if (rpmxdbResizeBlob(idxdb->xdb, idxdb->xdbid, idxdb->file_size + addsize))
 	return RPMRC_FAIL;
-#endif
-    }
     return RPMRC_OK;
 }
 
@@ -589,7 +483,7 @@ static int rpmidxRebuildInternal(rpmidxd
 
     nidxdb = &nidxdb_s;
     memset(nidxdb, 0, sizeof(*nidxdb));
-    nidxdb->pagesize = sysconf(_SC_PAGE_SIZE);
+    nidxdb->pagesize = rpmxdbPagesize(idxdb->xdb);
 
     /* calculate nslots the hard way, don't trust usedslots */
     nslots = 0;
@@ -627,60 +521,20 @@ static int rpmidxRebuildInternal(rpmidxd
     nidxdb->xmask = xmask;
 
     /* create new database */
-    if (idxdb->xdb) {
-	nidxdb->xdb = idxdb->xdb;
-	nidxdb->xdbtag = idxdb->xdbtag;
-	if (rpmxdbLookupBlob(nidxdb->xdb, &nidxdb->xdbid, idxdb->xdbtag, IDXDB_XDB_SUBTAG_REBUILD, O_CREAT|O_TRUNC)) {
-	    return RPMRC_FAIL;
-	}
-	if (rpmxdbResizeBlob(nidxdb->xdb, nidxdb->xdbid, file_size)) {
-	    return RPMRC_FAIL;
-	}
-	if (rpmidxMap(nidxdb)) {
-	    return RPMRC_FAIL;
-	}
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	void *mapped;
-	nidxdb->filename = malloc(strlen(idxdb->filename) + 8);
-	if (!nidxdb->filename)
-	    return RPMRC_FAIL;
-	sprintf(nidxdb->filename, "%s-XXXXXX", idxdb->filename);
-	nidxdb->fd = mkstemp(nidxdb->filename);
-	if (nidxdb->fd == -1) {
-	    free(nidxdb->filename);
-	    return RPMRC_FAIL;
-	}
-	if (createempty(nidxdb, 0, file_size)) {
-	    close(nidxdb->fd);
-	    unlink(nidxdb->filename);
-	    free(nidxdb->filename);
-	    return RPMRC_FAIL;
-	}
-	mapped = mmap(0, file_size, idxdb->rdonly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, nidxdb->fd, 0);
-	if (mapped == MAP_FAILED) {
-	    close(nidxdb->fd);
-	    unlink(nidxdb->filename);
-	    free(nidxdb->filename);
-	    return RPMRC_FAIL;
-	}
-	set_mapped(nidxdb, mapped, file_size);
-#else
+    nidxdb->xdb = idxdb->xdb;
+    nidxdb->xdbtag = idxdb->xdbtag;
+    if (rpmxdbLookupBlob(nidxdb->xdb, &nidxdb->xdbid, idxdb->xdbtag, IDXDB_XDB_SUBTAG_REBUILD, O_CREAT|O_TRUNC)) {
 	return RPMRC_FAIL;
-#endif
     }
-
-    /* copy all entries */
-    done = calloc(idxdb->nslots / 8 + 1, 1);
-    if (!done) {
-	rpmidxUnmap(nidxdb);
-	if (!idxdb->xdb) {
-	    close(nidxdb->fd);
-	    unlink(nidxdb->filename);
-	    free(nidxdb->filename);
-	}
+    if (rpmxdbResizeBlob(nidxdb->xdb, nidxdb->xdbid, file_size)) {
 	return RPMRC_FAIL;
     }
+    if (rpmidxMap(nidxdb)) {
+	return RPMRC_FAIL;
+    }
+
+    /* copy all entries */
+    done = xcalloc(idxdb->nslots / 8 + 1, 1);
     keyend = 1;
     for (i = 0, ent = idxdb->slot_mapped; i < idxdb->nslots; i++, ent += 8) {
 	unsigned int x = le2ha(ent);
@@ -709,42 +563,14 @@ static int rpmidxRebuildInternal(rpmidxd
     /* shrink if we have allocated excessive key space */
     xfile_size = file_size - key_size + keyend + IDXDB_KEY_CHUNKSIZE;
     xfile_size = (xfile_size + nidxdb->pagesize - 1) & ~(nidxdb->pagesize - 1);
-    if (xfile_size < file_size) {
-	if (nidxdb->xdb) {
-	    rpmxdbResizeBlob(nidxdb->xdb, nidxdb->xdbid, xfile_size);
-	} else {
-	    if (ftruncate(nidxdb->fd, xfile_size)) {
-		rpmlog(RPMLOG_WARNING, _("truncate failed: %s\n"), strerror(errno));
-	    }
-	}
-    }
+    if (xfile_size < file_size)
+	rpmxdbResizeBlob(nidxdb->xdb, nidxdb->xdbid, xfile_size);
 
     /* now switch over to new database */
-    if (idxdb->xdb) {
-	rpmidxUnmap(idxdb);
-	if (rpmxdbRenameBlob(nidxdb->xdb, &nidxdb->xdbid, idxdb->xdbtag, IDXDB_XDB_SUBTAG))
-	    return RPMRC_FAIL;
-	idxdb->xdbid = nidxdb->xdbid;
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	if (rename(nidxdb->filename, idxdb->filename)) {
-	    close(nidxdb->fd);
-	    unlink(nidxdb->filename);
-	    free(nidxdb->filename);
-	    return RPMRC_FAIL;
-	}
-	if (idxdb->head_mapped) {
-	    h2lea(1, idxdb->head_mapped + IDXDB_OFFSET_OBSOLETE);
-	    bumpGeneration(idxdb);
-	    rpmidxUnmap(idxdb);
-	}
-	free(nidxdb->filename);
-	close(idxdb->fd);
-	idxdb->fd = nidxdb->fd;
-#else
+    rpmidxUnmap(idxdb);
+    if (rpmxdbRenameBlob(nidxdb->xdb, &nidxdb->xdbid, idxdb->xdbtag, IDXDB_XDB_SUBTAG))
 	return RPMRC_FAIL;
-#endif
-    }
+    idxdb->xdbid = nidxdb->xdbid;
     if (rpmidxReadHeader(idxdb))
 	return RPMRC_FAIL;
     return RPMRC_OK;
@@ -929,12 +755,10 @@ static int rpmidxGetInternal(rpmidxdb id
 	    continue;
 	if ((nhits & 15) == 0) {
 	    if (!hits) {
-		hits = malloc(16 * sizeof(unsigned int));
+		hits = xmalloc(16 * sizeof(unsigned int));
 	    } else {
-		hits = realloc(hits, (nhits + 16) * sizeof(unsigned int));
+		hits = xrealloc(hits, (nhits + 16) * sizeof(unsigned int));
 	    }
-	    if (!hits)
-		return RPMRC_FAIL;
 	}
 	data = le2ha(ent + 4);
 	ovldata = (data & 0x80000000) ? le2ha(idxdb->slot_mapped + idxdb->nslots * 8 + 4 * h) : 0;
@@ -957,9 +781,7 @@ static void rpmidxListSort(rpmidxdb idxd
     unsigned int i, *arr;
     if (nkeylist < 2 * 2)
 	return;
-    arr = malloc(nkeylist * sizeof(unsigned int));
-    if (!arr)
-	return;
+    arr = xmalloc(nkeylist * sizeof(unsigned int));
     for (i = 0; i < nkeylist; i += 2) {
 	arr[i] = i;
 	arr[i + 1] = murmurhash(data + keylist[i], keylist[i + 1]) & idxdb->hmask;
@@ -980,15 +802,9 @@ static int rpmidxListInternal(rpmidxdb i
     unsigned int nkeylist = 0;
     unsigned char *data, *terminate, *key, *keyendp;
 
-    data = malloc(idxdb->keyend + 1);	/* +1 so we can terminate the last key */
-    if (!data)
-	return RPMRC_FAIL;
+    data = xmalloc(idxdb->keyend + 1);	/* +1 so we can terminate the last key */
     memcpy(data, idxdb->key_mapped, idxdb->keyend);
-    keylist = malloc(16 * sizeof(*keylist));
-    if (!keylist) {
-	free(data);
-	return RPMRC_FAIL;
-    }
+    keylist = xmalloc(16 * sizeof(*keylist));
     terminate = 0;
     for (key = data + 1, keyendp = data + idxdb->keyend; key < keyendp; ) {
 	unsigned int hl, keyl;
@@ -997,12 +813,7 @@ static int rpmidxListInternal(rpmidxdb i
 	    continue;
 	}
 	if ((nkeylist & 15) == 0) {
-	    unsigned int *kl = realloc(keylist, (nkeylist + 16) * sizeof(*keylist));
-	    if (!kl) {
-		free(keylist);
-		free(data);
-		return RPMRC_FAIL;
-	    }
+	    unsigned int *kl = xrealloc(keylist, (nkeylist + 16) * sizeof(*keylist));
 	    keylist = kl;
 	}
 	keyl = decodekeyl(key, &hl);
@@ -1025,26 +836,14 @@ static int rpmidxListInternal(rpmidxdb i
 
 static int rpmidxInitInternal(rpmidxdb idxdb)
 {
-    if (idxdb->xdb) {
-	unsigned int id;
-	int rc = rpmxdbLookupBlob(idxdb->xdb, &id, idxdb->xdbtag, IDXDB_XDB_SUBTAG, 0);
-	if (rc == RPMRC_OK && id) {
-	    idxdb->xdbid = id;
-	    return RPMRC_OK;	/* somebody else was faster */
-	}
-	if (rc && rc != RPMRC_NOTFOUND)
-	    return rc;
-    } else {
-#ifdef IDXDB_FILESUPPORT
-	struct stat stb; 
-	if (stat(idxdb->filename, &stb))
-	    return RPMRC_FAIL;
-	if (stb.st_size)	/* somebody else was faster */
-	    return rpmidxHandleObsolete(idxdb);
-#else
-	return RPMRC_FAIL;
-#endif
+    unsigned int id;
+    int rc = rpmxdbLookupBlob(idxdb->xdb, &id, idxdb->xdbtag, IDXDB_XDB_SUBTAG, 0);
+    if (rc == RPMRC_OK && id) {
+	idxdb->xdbid = id;
+	return RPMRC_OK;	/* somebody else was faster */
     }
+    if (rc && rc != RPMRC_NOTFOUND)
+	return rc;
     return rpmidxRebuildInternal(idxdb);
 }
 
@@ -1052,18 +851,12 @@ static int rpmidxLock(rpmidxdb idxdb, in
 {
     if (excl && idxdb->rdonly)
 	return RPMRC_FAIL;
-    if (idxdb->xdb)
-	return rpmxdbLock(idxdb->xdb, excl);
-    else
-	return rpmpkgLock(idxdb->pkgdb, excl);
+    return rpmxdbLock(idxdb->xdb, excl);
 }
 
 static int rpmidxUnlock(rpmidxdb idxdb, int excl)
 {
-    if (idxdb->xdb)
-	return rpmxdbUnlock(idxdb->xdb, excl);
-    else
-	return rpmpkgUnlock(idxdb->pkgdb, excl);
+    return rpmxdbUnlock(idxdb->xdb, excl);
 }
 
 static int rpmidxLockReadHeader(rpmidxdb idxdb, int excl)
@@ -1089,49 +882,7 @@ static int rpmidxInit(rpmidxdb idxdb)
 
 int rpmidxOpen(rpmidxdb *idxdbp, rpmpkgdb pkgdb, const char *filename, int flags, int mode)
 {
-#ifdef IDXDB_FILESUPPORT
-    struct stat stb;
-    rpmidxdb idxdb;
-
-    *idxdbp = 0;
-    idxdb = calloc(1, sizeof(*idxdb));
-    if (!idxdb)
-	return RPMRC_FAIL;
-    idxdb->filename = strdup(filename);
-    if (!idxdb->filename) {
-	free(idxdb);
-	return RPMRC_FAIL;
-    }   
-    if ((flags & (O_RDONLY|O_RDWR)) == O_RDONLY)
-	idxdb->rdonly = 1;
-    if ((idxdb->fd = open(filename, flags, mode)) == -1) {
-	free(idxdb->filename);
-	free(idxdb);
-	return RPMRC_FAIL;
-    }   
-    if (fstat(idxdb->fd, &stb)) {
-	close(idxdb->fd);
-	free(idxdb->filename);
-	free(idxdb);
-	return RPMRC_FAIL;
-    }   
-    idxdb->pkgdb = pkgdb;
-    idxdb->flags = flags;
-    idxdb->mode = mode;
-    idxdb->pagesize = sysconf(_SC_PAGE_SIZE);
-    if (stb.st_size == 0) {
-	if (rpmidxInit(idxdb)) {
-	    close(idxdb->fd);
-	    free(idxdb->filename);
-	    free(idxdb);
-	    return RPMRC_FAIL;
-	}
-    }
-    *idxdbp = idxdb;
-    return RPMRC_OK;
-#else
     return RPMRC_FAIL;
-#endif
 }
 
 int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmpkgdb pkgdb, rpmxdb xdb, unsigned int xdbtag)
@@ -1150,19 +901,13 @@ int rpmidxOpenXdb(rpmidxdb *idxdbp, rpmp
 	rpmxdbUnlock(xdb, 0);
 	return RPMRC_FAIL;
     }
-    idxdb = calloc(1, sizeof(*idxdb));
-    if (!idxdb) {
-	rpmxdbUnlock(xdb, 0);
-	return RPMRC_FAIL;
-    }
-    idxdb->fd = -1;
+    idxdb = xcalloc(1, sizeof(*idxdb));
     idxdb->xdb = xdb;
     idxdb->xdbtag = xdbtag;
     idxdb->xdbid = id;
     idxdb->pkgdb = pkgdb;
-    idxdb->pagesize = sysconf(_SC_PAGE_SIZE);
-    if (rpmxdbIsRdonly(xdb))
-	idxdb->rdonly = 1;
+    idxdb->pagesize = rpmxdbPagesize(xdb);
+    idxdb->rdonly = rpmxdbIsRdonly(xdb) ? 1 : 0;
     if (!id) {
 	if (rpmidxInit(idxdb)) {
 	    free(idxdb);
@@ -1199,12 +944,6 @@ int rpmidxDelXdb(rpmpkgdb pkgdb, rpmxdb
 void rpmidxClose(rpmidxdb idxdb)
 {
     rpmidxUnmap(idxdb);
-    if (idxdb->fd >= 0) {
-	close(idxdb->fd);
-	idxdb->fd = -1; 
-    }   
-    if (idxdb->filename)
-	free(idxdb->filename);
     free(idxdb);
 }
 
@@ -1263,11 +1002,7 @@ int rpmidxStats(rpmidxdb idxdb)
     if (rpmidxLockReadHeader(idxdb, 0))
 	return RPMRC_FAIL;
     printf("--- IndexDB Stats\n");
-    if (idxdb->xdb) {
-	printf("Xdb tag: %d, id: %d\n", idxdb->xdbtag, idxdb->xdbid);
-    } else {
-	printf("Filename: %s\n", idxdb->filename);
-    }
+    printf("Xdb tag: %d, id: %d\n", idxdb->xdbtag, idxdb->xdbid);
     printf("Generation: %u\n", idxdb->generation);
     printf("Slots: %u\n", idxdb->nslots);
     printf("Used slots: %u\n", idxdb->usedslots);
--- ./lib/backend/ndb/rpmpkg.c.orig	2020-01-16 15:11:26.181880288 +0000
+++ ./lib/backend/ndb/rpmpkg.c	2020-01-16 15:11:26.181880288 +0000
@@ -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>
@@ -19,10 +18,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);
 
@@ -49,23 +44,19 @@ typedef struct rpmpkgdb_s {
     unsigned int nextpkgidx;
 
     struct pkgslot_s *slots;
-    unsigned int aslots;	/* allocated slots */
     unsigned int nslots;	/* used slots */
 
     unsigned int *slothash;
     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) 
 {
@@ -144,10 +135,6 @@ static int rpmpkgReadHeader(rpmpkgdb pkg
     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;
@@ -156,6 +143,15 @@ static int rpmpkgReadHeader(rpmpkgdb pkg
     return RPMRC_OK;
 }
 
+static int rpmpkgFsync(rpmpkgdb pkgdb)
+{
+#ifdef HAVE_FDATASYNC
+    return fdatasync(pkgdb->fd);
+#else
+    return fsync(pkgdb->fd);
+#endif
+}
+
 static int rpmpkgWriteHeader(rpmpkgdb pkgdb)
 {
     unsigned char header[PKGDB_HEADER_SIZE];
@@ -168,7 +164,7 @@ static int rpmpkgWriteHeader(rpmpkgdb pk
     if (pwrite(pkgdb->fd, header, sizeof(header), 0) != sizeof(header)) {
 	return RPMRC_FAIL;
     }
-    if (pkgdb->dofsync && fsync(pkgdb->fd))
+    if (pkgdb->dofsync && rpmpkgFsync(pkgdb))
 	return RPMRC_FAIL;	/* write error */
     return RPMRC_OK;
 }
@@ -191,6 +187,7 @@ static inline unsigned int hashpkgidx(un
     return h;
 }
 
+/* (re-)create a hash mapping pkgidx numbers to slots */
 static int rpmpkgHashSlots(rpmpkgdb pkgdb)
 {
     unsigned int nslots, num;
@@ -199,17 +196,15 @@ static int rpmpkgHashSlots(rpmpkgdb pkgd
     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);
-	hash = pkgdb->slothash = calloc(num, sizeof(unsigned int));
-	if (!hash)
-	    return RPMRC_FAIL;
+	if (hash)
+	    free(hash);
+	hash = pkgdb->slothash = xcalloc(num, sizeof(unsigned int));
 	pkgdb->nslothash = num;
     } else {
 	memset(hash, 0, num * sizeof(unsigned int));
@@ -221,8 +216,6 @@ static int rpmpkgHashSlots(rpmpkgdb pkgd
 	    ;
 	hash[h] = i + 1;
     }
-    pkgdb->slothash = hash;
-    pkgdb->nslothash = num;
     return RPMRC_OK;
 }
 
@@ -240,10 +233,6 @@ static int rpmpkgReadSlots(rpmpkgdb pkgd
 	free(pkgdb->slots);
 	pkgdb->slots = 0;
     }
-    if (pkgdb->slothash) {
-	free(pkgdb->slothash);
-	pkgdb->slothash = 0;
-    }
     pkgdb->nslots = 0;
     pkgdb->freeslot = 0;
 
@@ -255,11 +244,7 @@ static int rpmpkgReadSlots(rpmpkgdb pkgd
     fileblks = stb.st_size / BLK_SIZE;
 
     /* read (and somewhat verify) all slots */
-    pkgdb->aslots = slotnpages * (PAGE_SIZE / SLOT_SIZE);
-    pkgdb->slots = calloc(pkgdb->aslots, sizeof(*pkgdb->slots));
-    if (!pkgdb->slots) {
-	return RPMRC_FAIL;
-    }
+    pkgdb->slots = xcalloc(slotnpages * (PAGE_SIZE / SLOT_SIZE), sizeof(*pkgdb->slots));
     i = 0;
     slot = pkgdb->slots;
     minblkoff = slotnpages * (PAGE_SIZE / BLK_SIZE);
@@ -295,7 +280,7 @@ static int rpmpkgReadSlots(rpmpkgdb pkgd
 	}
     }
     pkgdb->nslots = i;
-    pkgdb->slotorder = SLOTORDER_UNORDERED;	/* XXX: always order? */
+    pkgdb->ordered = 0;
     pkgdb->fileblks = fileblks;
     pkgdb->freeslot = freeslot;
     if (rpmpkgHashSlots(pkgdb)) {
@@ -313,15 +298,13 @@ static int orderslots_blkoff_cmp(const v
     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);
 }
 
@@ -336,6 +319,8 @@ static inline pkgslot *rpmpkgFindSlot(rp
     return 0;
 }
 
+/* Find an empty space for blkcnt blocks. If dontprepend is true, ignore
+   the space between the slot area and the first blob */
 static int rpmpkgFindEmptyOffset(rpmpkgdb pkgdb, unsigned int pkgidx, unsigned int blkcnt, unsigned *blkoffp, pkgslot **oldslotp, int dontprepend)
 {
     unsigned int i, nslots = pkgdb->nslots;
@@ -344,8 +329,8 @@ static int rpmpkgFindEmptyOffset(rpmpkgd
     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;
@@ -378,14 +363,15 @@ static int rpmpkgFindEmptyOffset(rpmpkgd
     return RPMRC_OK;
 }
 
+/* verify the blobs to the left and right of a free area */
 static int rpmpkgNeighbourCheck(rpmpkgdb pkgdb, unsigned int blkoff, unsigned int blkcnt, unsigned int *newblkcnt)
 {
     unsigned int i, nslots = pkgdb->nslots;
     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++) {
@@ -409,7 +395,7 @@ static int rpmpkgNeighbourCheck(rpmpkgdb
     if (right && rpmpkgVerifyblob(pkgdb, right->pkgidx, right->blkoff, right->blkcnt) != RPMRC_OK)
 	return RPMRC_FAIL;
     *newblkcnt = right ? right->blkoff - blkoff : blkcnt;
-    /* bounds are intect. free area. */
+    /* bounds are intact. ok to zero area. */
     return RPMRC_OK;
 }
 
@@ -429,6 +415,7 @@ static int rpmpkgWriteslot(rpmpkgdb pkgd
 	return RPMRC_FAIL;
     }
     pkgdb->generation++;
+    /* rpmpkgFsync() is done by rpmpkgWriteHeader() */
     if (rpmpkgWriteHeader(pkgdb)) {
 	return RPMRC_FAIL;
     }
@@ -445,7 +432,7 @@ static int rpmpkgWriteEmptySlotpage(rpmp
     if (pwrite(pkgdb->fd, page, PAGE_SIZE - off, pageno * PAGE_SIZE + off) != PAGE_SIZE - off) {
 	return RPMRC_FAIL;
     }
-    if (pkgdb->dofsync && fsync(pkgdb->fd)) {
+    if (pkgdb->dofsync && rpmpkgFsync(pkgdb)) {
 	return RPMRC_FAIL;	/* write error */
     }
     return RPMRC_OK;
@@ -523,7 +510,7 @@ static int rpmpkgValidateZero(rpmpkgdb p
 
 /*** 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)
@@ -532,10 +519,10 @@ static int rpmpkgValidateZero(rpmpkgdb p
 #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;
@@ -551,7 +538,7 @@ static int rpmpkgReadBlob(rpmpkgdb pkgdb
 	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 */
@@ -596,8 +583,8 @@ static int rpmpkgReadBlob(rpmpkgdb pkgdb
     }
     if (bloblp)
 	*bloblp = bloblen;
-    if (tstampp)
-	*tstampp = tstamp;
+    if (generationp)
+	*generationp = generation;
     return RPMRC_OK;
 }
 
@@ -656,7 +643,7 @@ static int rpmpkgWriteBlob(rpmpkgdb pkgd
     /* update file length */
     if (blkoff + blkcnt > pkgdb->fileblks)
 	pkgdb->fileblks = blkoff + blkcnt;
-    if (pkgdb->dofsync && fsync(pkgdb->fd)) {
+    if (pkgdb->dofsync && rpmpkgFsync(pkgdb)) {
 	return RPMRC_FAIL;	/* write error */
     }
     return RPMRC_OK;
@@ -668,7 +655,7 @@ static int rpmpkgDelBlob(rpmpkgdb pkgdb,
 	return RPMRC_FAIL;
     if (rpmpkgZeroBlks(pkgdb, blkoff, blkcnt))
 	return RPMRC_FAIL;
-    if (pkgdb->dofsync && fsync(pkgdb->fd))
+    if (pkgdb->dofsync && rpmpkgFsync(pkgdb))
 	return RPMRC_FAIL;	/* write error */
     return RPMRC_OK;
 }
@@ -680,14 +667,14 @@ static int rpmpkgMoveBlob(rpmpkgdb pkgdb
     unsigned int blkoff = slot->blkoff;
     unsigned int blkcnt = slot->blkcnt;
     unsigned char *blob;
-    unsigned int tstamp, blobl;
+    unsigned int generation, blobl;
 
-    blob = malloc((size_t)blkcnt * BLK_SIZE);
-    if (rpmpkgReadBlob(pkgdb, pkgidx, blkoff, blkcnt, blob, &blobl, &tstamp)) {
+    blob = xmalloc((size_t)blkcnt * BLK_SIZE);
+    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;
     }
@@ -699,15 +686,15 @@ static int rpmpkgMoveBlob(rpmpkgdb pkgdb
 	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 */
@@ -725,7 +712,7 @@ static int rpmpkgAddSlotPage(rpmpkgdb pk
 	if (rpmpkgMoveBlob(pkgdb, slot, newblkoff)) {
 	    return RPMRC_FAIL;
 	}
-	rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+	rpmpkgOrderSlots(pkgdb);
     }
 
     /* make sure our new page is empty */
@@ -845,18 +832,31 @@ static int rpmpkgInit(rpmpkgdb pkgdb)
     return rc;
 }
 
+static int rpmpkgFsyncDir(const char *filename)
+{
+    int rc = RPMRC_OK;
+    DIR *pdir;
+    char *filenameCopy = xstrdup(filename);
+
+    if ((pdir = opendir(dirname(filenameCopy))) == NULL) {
+	free(filenameCopy);
+	return RPMRC_FAIL;
+    }    
+    if (fsync(dirfd(pdir)) == -1)
+	rc = RPMRC_FAIL;
+    closedir(pdir);
+    free(filenameCopy);
+    return rc;
+}
+
 int rpmpkgOpen(rpmpkgdb *pkgdbp, const char *filename, int flags, int mode)
 {
     struct stat stb;
     rpmpkgdb pkgdb;
 
     *pkgdbp = 0;
-    pkgdb = calloc(1, sizeof(*pkgdb));
-    pkgdb->filename = strdup(filename);
-    if (!pkgdb->filename) {
-	free(pkgdb);
-	return RPMRC_FAIL;
-    }
+    pkgdb = xcalloc(1, sizeof(*pkgdb));
+    pkgdb->filename = xstrdup(filename);
     if ((flags & (O_RDONLY|O_RDWR)) == O_RDONLY)
 	pkgdb->rdonly = 1;
     if ((pkgdb->fd = open(filename, flags, mode)) == -1) {
@@ -864,37 +864,6 @@ int rpmpkgOpen(rpmpkgdb *pkgdbp, const c
 	free(pkgdb);
         return RPMRC_FAIL;
     }
-    if (flags & O_CREAT) {
-	char *filenameCopy;
-	DIR *pdir;
-
-	if ((filenameCopy = strdup(pkgdb->filename)) == NULL) {
-	    close(pkgdb->fd);
-	    free(pkgdb->filename);
-	    free(pkgdb);
-	    return RPMRC_FAIL;
-	}
-
-	if ((pdir = opendir(dirname(filenameCopy))) == NULL) {
-	    free(filenameCopy);
-	    close(pkgdb->fd);
-	    free(pkgdb->filename);
-	    free(pkgdb);
-	    return RPMRC_FAIL;
-	}
-
-	if (fsync(dirfd(pdir)) == -1) {
-	    closedir(pdir);
-	    free(filenameCopy);
-	    close(pkgdb->fd);
-	    free(pkgdb->filename);
-	    free(pkgdb);
-	    return RPMRC_FAIL;
-	}
-	closedir(pdir);
-	free(filenameCopy);
-
-    }
     if (fstat(pkgdb->fd, &stb)) {
 	close(pkgdb->fd);
 	free(pkgdb->filename);
@@ -902,6 +871,13 @@ int rpmpkgOpen(rpmpkgdb *pkgdbp, const c
         return RPMRC_FAIL;
     }
     if (stb.st_size == 0) {
+	/* created new database */
+	if (rpmpkgFsyncDir(pkgdb->filename)) {
+	    close(pkgdb->fd);
+	    free(pkgdb->filename);
+	    free(pkgdb);
+	    return RPMRC_FAIL;
+	}
 	if (rpmpkgInit(pkgdb)) {
 	    close(pkgdb->fd);
 	    free(pkgdb->filename);
@@ -950,7 +926,7 @@ static int rpmpkgGetInternal(rpmpkgdb pk
     if (!slot) {
 	return RPMRC_NOTFOUND;
     }
-    blob = malloc((size_t)slot->blkcnt * BLK_SIZE);
+    blob = xmalloc((size_t)slot->blkcnt * BLK_SIZE);
     if (rpmpkgReadBlob(pkgdb, pkgidx, slot->blkoff, slot->blkcnt, blob, bloblp, (unsigned int *)0)) {
 	free(blob);
 	return RPMRC_FAIL;
@@ -965,6 +941,7 @@ static int rpmpkgPutInternal(rpmpkgdb pk
     pkgslot *oldslot;
 
     /* we always read all slots when writing, just in case */
+    /* this also will set pkgdb->freeslot */
     if (rpmpkgReadSlots(pkgdb)) {
 	return RPMRC_FAIL;
     }
@@ -988,7 +965,7 @@ static int rpmpkgPutInternal(rpmpkgdb pk
 	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 */
@@ -1013,7 +990,7 @@ static int rpmpkgPutInternal(rpmpkgdb pk
 	/* 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;
@@ -1030,7 +1007,7 @@ static int rpmpkgDelInternal(rpmpkgdb pk
     if (rpmpkgReadSlots(pkgdb)) {
 	return RPMRC_FAIL;
     }
-    rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+    rpmpkgOrderSlots(pkgdb);
     slot = rpmpkgFindSlot(pkgdb, pkgidx);
     if (!slot) {
 	return RPMRC_OK;
@@ -1056,9 +1033,10 @@ static int rpmpkgDelInternal(rpmpkgdb pk
 	}
 	slot->blkoff = 0;
 	slot->blkcnt = 0;
+	/* try to move the last two slots, the bigger one first */
 	slot = pkgdb->slots + pkgdb->nslots - 2;
 	if (slot->blkcnt < slot[1].blkcnt)
-	  slot++;	/* bigger slot first */
+	    slot++;	/* bigger slot first */
 	for (i = 0; i < 2; i++, slot++) {
 	    if (slot == pkgdb->slots + pkgdb->nslots)
 		slot -= 2;
@@ -1072,7 +1050,7 @@ static int rpmpkgDelInternal(rpmpkgdb pk
 	    blkoff += slot->blkcnt;
 	    blkcnt -= slot->blkcnt;
 	}
-	rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+	rpmpkgOrderSlots(pkgdb);
     } else {
 	slot->blkoff = 0;
 	slot->blkcnt = 0;
@@ -1111,9 +1089,9 @@ static int rpmpkgListInternal(rpmpkgdb p
 	*npkgidxlistp = pkgdb->nslots;
 	return RPMRC_OK;
     }
-    rpmpkgOrderSlots(pkgdb, SLOTORDER_BLKOFF);
+    rpmpkgOrderSlots(pkgdb);
     nslots = pkgdb->nslots;
-    pkgidxlist = calloc(nslots + 1, sizeof(unsigned int));
+    pkgidxlist = xcalloc(nslots + 1, sizeof(unsigned int));
     for (i = 0, slot = pkgdb->slots; i < nslots; i++, slot++) {
 	pkgidxlist[i] = slot->pkgidx;
     }
@@ -1122,6 +1100,22 @@ static int rpmpkgListInternal(rpmpkgdb p
     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;
@@ -1134,10 +1128,6 @@ int rpmpkgGet(rpmpkgdb pkgdb, unsigned i
 	return RPMRC_FAIL;
     rc = rpmpkgGetInternal(pkgdb, pkgidx, blobp, bloblp);
     rpmpkgUnlock(pkgdb, 0);
-#ifdef RPMPKG_LZO
-    if (!rc)
-	rc = rpmpkgLZODecompress(blobp, bloblp);
-#endif
     return rc;
 }
 
@@ -1150,16 +1140,7 @@ int rpmpkgPut(rpmpkgdb pkgdb, unsigned i
     }
     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;
 }
@@ -1191,6 +1172,16 @@ int rpmpkgList(rpmpkgdb pkgdb, unsigned
     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))
@@ -1240,73 +1231,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 = malloc(LZO1X_1_MEM_COMPRESS);
-    if (!workmem) {
-	return RPMRC_FAIL;
-    }
-    lzoblobl = 4 + 4 + blobl + blobl / 16 + 64 + 3;
-    lzoblob = malloc(lzoblobl);
-    if (!lzoblob) {
-	free(workmem);
-	return RPMRC_FAIL;
-    }
-    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 = malloc(blobl ? blobl : 1);
-    if (!blob)
-	return RPMRC_FAIL;
-    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
--- ./lib/backend/ndb/rpmpkg.h.orig	2020-01-28 10:57:30.224197080 +0000
+++ ./lib/backend/ndb/rpmpkg.h	2020-01-16 15:11:26.181880288 +0000
@@ -12,6 +12,7 @@ int rpmpkgGet(rpmpkgdb pkgdb, unsigned i
 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);
--- ./lib/backend/ndb/rpmxdb.c.orig	2020-01-16 15:11:26.181880288 +0000
+++ ./lib/backend/ndb/rpmxdb.c	2020-01-28 12:08:26.097237489 +0000
@@ -36,6 +36,7 @@ typedef struct rpmxdb_s {
     unsigned int usergeneration;
 
     unsigned char *mapped;
+    int mapflags;
     unsigned int mappedlen;
 
     struct xdb_slot {
@@ -95,12 +96,52 @@ static inline void h2lea(unsigned int x,
 
 #define SLOT_MAGIC     ('S' | 'l' << 8 | 'o' << 16)
 
-#define SLOT_SIZE 16
+#define SLOT_SIZE		16
 #define SLOT_START (XDB_HEADER_SIZE / SLOT_SIZE)
 
-static void rpmxdbUnmap(rpmxdb xdb)
+
+/* low level map/remap a file into memory */
+static void *mapmem(void *oldaddr, size_t oldsize, size_t newsize, int prot, int fd, off_t offset)
 {
-    munmap(xdb->mapped, xdb->mappedlen);
+    if (oldaddr) {
+#if HAVE_MREMAP
+	return mremap(oldaddr, oldsize, newsize, MREMAP_MAYMOVE);
+#else
+	void *mapped = mmap(0, newsize, prot, MAP_SHARED, fd, offset);
+	if (mapped != MAP_FAILED)
+	    munmap(oldaddr, oldsize);
+	return mapped;
+#endif
+    }
+    return mmap(0, newsize, prot, MAP_SHARED, fd, offset);
+}
+
+/* unmap a mapped region */
+static void unmapmem(void *addr, size_t size)
+{
+  munmap(addr, size);
+}
+
+#define ROUNDTOSYSTEMPAGE(xdb, size) (((size) + (xdb->systempagesize - 1)) & ~(xdb->systempagesize - 1))
+
+/* xdb header mapping functions */
+static int mapheader(rpmxdb xdb, unsigned int slotnpages)
+{
+    unsigned char *mapped;
+    size_t mappedlen = slotnpages * xdb->pagesize;
+
+    mappedlen = ROUNDTOSYSTEMPAGE(xdb, mappedlen);
+    mapped = mapmem(xdb->mapped, xdb->mappedlen, mappedlen, xdb->mapflags, xdb->fd, 0);
+    if ((void *)mapped == MAP_FAILED)
+	return RPMRC_FAIL;
+    xdb->mapped = mapped;
+    xdb->mappedlen = mappedlen;
+    return RPMRC_OK;
+}
+
+static void unmapheader(rpmxdb xdb)
+{
+    unmapmem(xdb->mapped, xdb->mappedlen);
     xdb->mapped = 0;
     xdb->mappedlen = 0;
 }
@@ -120,9 +161,9 @@ static int mapslot(rpmxdb xdb, struct xd
 	shift = off & (xdb->systempagesize - 1);
 	off -= shift;
 	size += shift;
-	size = (size + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
+	size = ROUNDTOSYSTEMPAGE(xdb, size);
     }
-    mapped = mmap(0, size, slot->mapflags, MAP_SHARED, xdb->fd, off);
+    mapped = mapmem(0, 0, size, slot->mapflags, xdb->fd, off);
     if (mapped == MAP_FAILED)
 	return RPMRC_FAIL;
     slot->mapped = (unsigned char *)mapped + shift;
@@ -131,44 +172,41 @@ static int mapslot(rpmxdb xdb, struct xd
 
 static void unmapslot(rpmxdb xdb, struct xdb_slot *slot)
 {
-    size_t size;
     unsigned char *mapped = slot->mapped;
+    size_t size;
     if (!mapped)
 	return;
     size = slot->pagecnt * xdb->pagesize;
     if (xdb->pagesize != xdb->systempagesize) {
 	size_t off = slot->startpage * xdb->pagesize;
 	size_t shift = off & (xdb->systempagesize - 1);
-	mapped -= shift;
 	size += shift;
-	size = (size + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
+	size = ROUNDTOSYSTEMPAGE(xdb, size);
+	mapped -= shift;
     }
-    munmap(mapped, size);
+    unmapmem(mapped, size);
     slot->mapped = 0;
 }
 
 static int remapslot(rpmxdb xdb, struct xdb_slot *slot, unsigned int newpagecnt)
 {
-    void *mapped;
+    unsigned char *mapped = slot->mapped;
     size_t off, oldsize, newsize, shift;
+
     oldsize = slot->pagecnt * xdb->pagesize;
     newsize = newpagecnt * xdb->pagesize;
     off = slot->startpage * xdb->pagesize;
     shift = 0;
     if (xdb->pagesize != xdb->systempagesize) {
-	off = slot->startpage * xdb->pagesize;
 	shift = off & (xdb->systempagesize - 1);
 	off -= shift;
 	oldsize += shift;
-	oldsize = (oldsize + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
 	newsize += shift;
-	newsize = (newsize + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
+	oldsize = ROUNDTOSYSTEMPAGE(xdb, oldsize);
+	newsize = ROUNDTOSYSTEMPAGE(xdb, newsize);
     }
-    if (slot->mapped)
-	mapped = mremap(slot->mapped - shift, oldsize, newsize, MREMAP_MAYMOVE);
-    else
-	mapped = mmap(0, newsize, slot->mapflags, MAP_SHARED, xdb->fd, off);
-    if (mapped == MAP_FAILED)
+    mapped = mapmem(mapped ? mapped - shift : 0, oldsize, newsize, slot->mapflags, xdb->fd, off);
+    if ((void *)mapped == MAP_FAILED)
 	return RPMRC_FAIL;
     slot->mapped = (unsigned char *)mapped + shift;
     slot->pagecnt = newpagecnt;
@@ -186,11 +224,33 @@ static int usedslots_cmp(const void *a,
     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;
@@ -198,61 +258,31 @@ static int rpmxdbReadHeader(rpmxdb xdb)
     unsigned int usedblobpages;
     int i, nused, slotno;
     struct stat stb;
-    size_t mapsize;
 
     if (xdb->mapped) {
 	if (le2ha(xdb->mapped + XDB_OFFSET_GENERATION) == xdb->generation) {
 	    return RPMRC_OK;
 	}
-	rpmxdbUnmap(xdb);
+	unmapheader(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)
-	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);
+    if (rpmxdbReadHeaderRaw(xdb, &generation, &slotnpages, &pagesize, &usergeneration))
 	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;
 
-    /* round up */
-    mapsize = slotnpages * pagesize;
-    mapsize = (mapsize + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
-    xdb->mapped = mmap(0, mapsize, xdb->rdonly ? PROT_READ : PROT_READ | PROT_WRITE, MAP_SHARED, xdb->fd, 0);
-    if ((void *)xdb->mapped == MAP_FAILED) {
-	xdb->mapped = 0;
+    if (mapheader(xdb, slotnpages))
 	return RPMRC_FAIL;
-    }
-    xdb->mappedlen = mapsize;
 
     /* read in all slots */
     xdb->firstfree = 0;
     nslots = slotnpages * (pagesize / SLOT_SIZE) - SLOT_START + 1;
-    slots = calloc(nslots + 1, sizeof(struct xdb_slot));
-    if (!slots) {
-	rpmxdbUnmap(xdb);
-	return RPMRC_FAIL;
-    }
-    usedslots = calloc(nslots + 1, sizeof(int));
-    if (!usedslots) {
-	rpmxdbUnmap(xdb);
-	free(slots);
-	return RPMRC_FAIL;
-    }
+    slots = xcalloc(nslots + 1, sizeof(struct xdb_slot));
+    usedslots = xcalloc(nslots + 1, sizeof(struct xdb_slot *));
     nused = 0;
     slotno = 1;
     slot = slots + 1;
@@ -267,7 +297,7 @@ static int rpmxdbReadHeader(rpmxdb xdb)
 	    if ((slot->subtag & 0x00ffffff) != SLOT_MAGIC) {
 		free(slots);
 		free(usedslots);
-		rpmxdbUnmap(xdb);
+		unmapheader(xdb);
 		return RPMRC_FAIL;
 	    }
 	    slot->subtag = (slot->subtag >> 24) & 255;
@@ -296,7 +326,7 @@ static int rpmxdbReadHeader(rpmxdb xdb)
 	if (lastslot->startpage + lastslot->pagecnt > slot->startpage) {
 	    free(slots);
 	    free(usedslots);
-	    rpmxdbUnmap(xdb);
+	    unmapheader(xdb);
 	    return RPMRC_FAIL;
 	}
 	lastslot->next = slot->slotno;
@@ -384,9 +414,7 @@ static int rpmxdbWriteEmptyPages(rpmxdb
     unsigned char *page;
     if (!count)
 	return RPMRC_OK;
-    page = malloc(xdb->pagesize);
-    if (!page)
-	return RPMRC_FAIL;
+    page = xmalloc(xdb->pagesize);
     memset(page, 0, xdb->pagesize);
     for (; count; count--, pageno++) {
 	if (pwrite(xdb->fd, page, xdb->pagesize, pageno * xdb->pagesize) != xdb->pagesize) {
@@ -402,9 +430,7 @@ static int rpmxdbWriteEmptySlotpage(rpmx
 {
     unsigned char *page;
     int i, spp;
-    page = malloc(xdb->pagesize);
-    if (!page)
-	return RPMRC_FAIL;
+    page = xmalloc(xdb->pagesize);
     memset(page, 0, xdb->pagesize);
     spp = xdb->pagesize / SLOT_SIZE;	/* slots per page */
     for (i = pageno ? 0 : SLOT_START; i < spp; i++)
@@ -493,20 +519,33 @@ static int rpmxdbInit(rpmxdb xdb)
     return rc;
 }
 
+static int rpmxdbFsyncDir(const char *filename)
+{
+    int rc = RPMRC_OK;
+    DIR *pdir;
+    char *filenameCopy = xstrdup(filename);
+
+    if ((pdir = opendir(dirname(filenameCopy))) == NULL) {
+	free(filenameCopy);
+	return RPMRC_FAIL;
+    }
+    if (fsync(dirfd(pdir)) == -1)
+	rc = RPMRC_FAIL;
+    closedir(pdir);
+    free(filenameCopy);
+    return rc;
+}
+
 int rpmxdbOpen(rpmxdb *xdbp, rpmpkgdb pkgdb, const char *filename, int flags, int mode)
 {
     struct stat stb;
     rpmxdb xdb;
 
     *xdbp = 0;
-    xdb = calloc(1, sizeof(*xdb));
+    xdb = xcalloc(1, sizeof(*xdb));
     xdb->pkgdb = pkgdb;
-    xdb->filename = strdup(filename);
+    xdb->filename = xstrdup(filename);
     xdb->systempagesize = sysconf(_SC_PAGE_SIZE);
-    if (!xdb->filename) {
-	free(xdb);
-	return RPMRC_FAIL;
-    }
     if ((flags & (O_RDONLY|O_RDWR)) == O_RDONLY)
 	xdb->rdonly = 1;
     if ((xdb->fd = open(filename, flags, mode)) == -1) {
@@ -514,36 +553,6 @@ int rpmxdbOpen(rpmxdb *xdbp, rpmpkgdb pk
 	free(xdb);
 	return RPMRC_FAIL;
     }
-    if (flags & O_CREAT) {
-	char *filenameCopy;
-	DIR *pdir;
-
-	if ((filenameCopy = strdup(xdb->filename)) == NULL) {
-	    close(xdb->fd);
-	    free(xdb->filename);
-	    free(xdb);
-	    return RPMRC_FAIL;
-	}
-
-	if ((pdir = opendir(dirname(filenameCopy))) == NULL) {
-	    free(filenameCopy);
-	    close(xdb->fd);
-	    free(xdb->filename);
-	    free(xdb);
-	    return RPMRC_FAIL;
-	}
-
-	if (fsync(dirfd(pdir)) == -1) {
-	    closedir(pdir);
-	    free(filenameCopy);
-	    close(xdb->fd);
-	    free(xdb->filename);
-	    free(xdb);
-	    return RPMRC_FAIL;
-	}
-	closedir(pdir);
-	free(filenameCopy);
-    }
     if (fstat(xdb->fd, &stb)) {
 	close(xdb->fd);
 	free(xdb->filename);
@@ -551,6 +560,13 @@ int rpmxdbOpen(rpmxdb *xdbp, rpmpkgdb pk
 	return RPMRC_FAIL;
     }
     if (stb.st_size == 0) {
+	/* created new database */
+	if (rpmxdbFsyncDir(xdb->filename)) {
+	    close(xdb->fd);
+	    free(xdb->filename);
+	    free(xdb);
+	    return RPMRC_FAIL;
+	}
 	if (rpmxdbInit(xdb)) {
 	    close(xdb->fd);
 	    free(xdb->filename);
@@ -607,6 +623,7 @@ static int moveblobto(rpmxdb xdb, struct
     didmap = 0;
     oldpagecnt = oldslot->pagecnt;
     if (!oldslot->mapped && oldpagecnt) {
+	oldslot->mapflags = PROT_READ;
 	if (mapslot(xdb, oldslot))
 	    return RPMRC_FAIL;
         didmap = 1;
@@ -728,10 +745,8 @@ static int moveblobstofront(rpmxdb xdb,
 /* add a single page containing empty slots */
 static int addslotpage(rpmxdb xdb)
 {
-    unsigned char *newaddr;
     struct xdb_slot *slot;
     int i, spp, nslots;
-    size_t newmappedlen;
 
     if (xdb->firstfree)
 	return RPMRC_FAIL;
@@ -750,22 +765,15 @@ static int addslotpage(rpmxdb xdb)
     }
 
     spp = xdb->pagesize / SLOT_SIZE;	/* slots per page */
-    slot = realloc(xdb->slots, (nslots + 1 + spp) * sizeof(*slot));
-    if (!slot)
-	return RPMRC_FAIL;
+    slot = xrealloc(xdb->slots, (nslots + 1 + spp) * sizeof(*slot));
     xdb->slots = slot;
 
-    if (rpmxdbWriteEmptySlotpage(xdb, xdb->slotnpages)) {
+    if (rpmxdbWriteEmptySlotpage(xdb, xdb->slotnpages))
 	return RPMRC_FAIL;
-    }
-    /* remap slots */
-    newmappedlen = xdb->slotnpages * xdb->pagesize + xdb->pagesize;
-    newmappedlen = (newmappedlen + xdb->systempagesize - 1) & ~(xdb->systempagesize - 1);
-    newaddr = mremap(xdb->mapped, xdb->mappedlen, newmappedlen, MREMAP_MAYMOVE);
-    if (newaddr == MAP_FAILED)
+
+    /* remap the header */
+    if (mapheader(xdb, xdb->slotnpages + 1))
 	return RPMRC_FAIL;
-    xdb->mapped = newaddr;
-    xdb->mappedlen = newmappedlen;
 
     /* update the header */
     xdb->slotnpages++;
@@ -787,13 +795,16 @@ static int addslotpage(rpmxdb xdb)
     *slot = xdb->slots[nslots];
     slot->slotno = nslots + spp;
     xdb->slots[slot->prev].next = slot->slotno;
+
+    /* we have a new slotpage */
     xdb->nslots += spp;
+    xdb->slots[0].pagecnt++;
 
     /* add new free slots to the firstfree chain */
     memset(xdb->slots + nslots, 0, sizeof(*slot) * spp);
     for (i = 0; i < spp - 1; i++) {
 	xdb->slots[nslots + i].slotno = nslots + i;
-	xdb->slots[nslots + i].next = i + 1;
+	xdb->slots[nslots + i].next = nslots + i + 1;
     }
     xdb->slots[nslots + i].slotno = nslots + i;
     xdb->firstfree = nslots;
@@ -920,6 +931,45 @@ int rpmxdbDelBlob(rpmxdb xdb, unsigned i
     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;
+    }
+    if (ftruncate(xdb->fd, xdb->pagesize)) {
+	/* ftruncate failed, but that is not a problem */
+    }
+    rpmxdbUnlock(xdb, 1);
+    return RPMRC_OK;
+}
+
 int rpmxdbResizeBlob(rpmxdb xdb, unsigned int id, size_t newsize)
 {
     struct xdb_slot *slot;
@@ -946,11 +996,7 @@ int rpmxdbResizeBlob(rpmxdb xdb, unsigne
 	    if (slot->mapped) {
 		memset(slot->mapped + pg, 0, xdb->pagesize - pg);
 	    } else {
-		char *empty = calloc(1, xdb->pagesize - pg);
-		if (!empty) {
-		    rpmxdbUnlock(xdb, 1);
-		    return RPMRC_FAIL;
-		}
+		char *empty = xcalloc(1, xdb->pagesize - pg);
                 if (pwrite(xdb->fd, empty, xdb->pagesize - pg, (slot->startpage + newpagecnt - 1) * xdb->pagesize + pg ) != xdb->pagesize - pg) {
 		    free(empty);
 		    rpmxdbUnlock(xdb, 1);
@@ -1156,12 +1202,26 @@ int rpmxdbIsRdonly(rpmxdb xdb)
     return xdb->rdonly;
 }
 
+unsigned int rpmxdbPagesize(rpmxdb xdb)
+{
+    return xdb->pagesize;
+}
+
+static int rpmxdbFsync(rpmxdb xdb)
+{
+#ifdef HAVE_FDATASYNC
+    return fdatasync(xdb->fd);
+#else
+    return fsync(xdb->fd);
+#endif
+}
+
 int rpmxdbSetUserGeneration(rpmxdb xdb, unsigned int usergeneration)
 {
     if (rpmxdbLockReadHeader(xdb, 1))
         return RPMRC_FAIL;
     /* sync before the update */
-    if (xdb->dofsync && fsync(xdb->fd)) {
+    if (xdb->dofsync && rpmxdbFsync(xdb)) {
 	rpmxdbUnlock(xdb, 1);
 	return RPMRC_FAIL;
     }
--- ./lib/backend/ndb/rpmxdb.h.orig	2020-01-16 15:11:26.181880288 +0000
+++ ./lib/backend/ndb/rpmxdb.h	2020-01-16 15:11:26.181880288 +0000
@@ -7,12 +7,14 @@ int rpmxdbOpen(rpmxdb *xdbp, rpmpkgdb pk
 void rpmxdbClose(rpmxdb xdb);
 void rpmxdbSetFsync(rpmxdb xdb, int dofsync);
 int rpmxdbIsRdonly(rpmxdb xdb);
+unsigned int rpmxdbPagesize(rpmxdb xdb);
 
 int rpmxdbLock(rpmxdb xdb, int excl);
 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);
openSUSE Build Service is sponsored by