diff --git a/db_conversion.diff b/db_conversion.diff new file mode 100644 index 0000000..79da591 --- /dev/null +++ b/db_conversion.diff @@ -0,0 +1,86 @@ +--- ./lib/backend/bdb_ro.c.orig 2020-01-17 12:42:10.916701298 +0000 ++++ ./lib/backend/bdb_ro.c 2020-01-17 12:42:50.924603470 +0000 +@@ -790,6 +790,7 @@ static unsigned int bdbro_pkgdbKey(dbiIn + struct rpmdbOps_s bdbro_dbops = { + .name = "bdb_ro", + .path = "Packages", ++ .readonly = 1, + + .open = bdbro_Open, + .close = bdbro_Close, +--- ./lib/backend/dbi.c.orig 2020-01-17 12:42:10.916701298 +0000 ++++ ./lib/backend/dbi.c 2020-01-17 12:42:50.924603470 +0000 +@@ -105,11 +105,20 @@ dbDetectBackend(rpmdb rdb) + } + + rdb->db_descr = rdb->db_ops->name; ++ rdb->db_ops_config = ops_config; + + if (db_backend) + free(db_backend); + } + ++int dbiNeedConversion(rpmdb rdb) ++{ ++ if (!rdb->db_ops) ++ dbDetectBackend(rdb); ++ return rdb->db_ops->readonly && rdb->db_ops_config ++ && rdb->db_ops_config->path && !rdb->db_ops_config->readonly; ++} ++ + const char * dbiName(dbiIndex dbi) + { + return dbi->dbi_file; +--- ./lib/backend/dbi.h.orig 2020-01-17 12:42:10.916701298 +0000 ++++ ./lib/backend/dbi.h 2020-01-17 12:42:50.924603470 +0000 +@@ -62,6 +62,7 @@ struct rpmdb_s { + int db_buildindex; /*!< Index rebuild indicator */ + + const struct rpmdbOps_s * db_ops; /*!< backend ops */ ++ const struct rpmdbOps_s * db_ops_config; /*!< configured backend ops */ + + /* dbenv and related parameters */ + void * db_dbenv; /*!< Backend private handle */ +@@ -201,6 +202,14 @@ RPM_GNUC_INTERNAL + const char * dbiName(dbiIndex dbi); + + /** \ingroup dbi ++ * Check if the database needs to be converted to a different format ++ * @param db rpm database ++ * @return boolean ++ */ ++RPM_GNUC_INTERNAL ++int dbiNeedConversion(rpmdb rdb); ++ ++/** \ingroup dbi + * Open a database cursor. + * @param dbi index database handle + * @param flags DBC_WRITE if writing, or 0 (DBC_READ) for reading +@@ -246,6 +255,7 @@ const void * idxdbKey(dbiIndex dbi, dbiC + struct rpmdbOps_s { + const char *name; /* backend name */ + const char *path; /* main database name */ ++ int readonly; /* cannot modify database */ + + int (*open)(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags); + int (*close)(dbiIndex dbi, unsigned int flags); +--- ./lib/rpmdb.c.orig 2020-01-17 12:42:10.916701298 +0000 ++++ ./lib/rpmdb.c 2020-01-17 12:42:50.924603470 +0000 +@@ -513,8 +513,16 @@ static int openDatabase(const char * pre + rpmsqActivate(1); + } + ++ /* Convert the database if needed */ ++ if (!db->db_pkgs && !justCheck && (mode & O_ACCMODE) == O_RDWR && dbiNeedConversion(db)) { ++ rpmlog(RPMLOG_WARNING, _("Converting database from %s to %s format\n"), db->db_ops->name, db->db_ops_config->name); ++ rc = rpmdbRebuild(prefix, NULL, NULL); ++ db->db_ops = NULL; /* force re-detection of backend */ ++ } ++ + /* Just the primary Packages database opened here */ +- rc = pkgdbOpen(db, db->db_flags, NULL); ++ if (!rc) ++ rc = pkgdbOpen(db, db->db_flags, NULL); + if (!db->db_descr) + db->db_descr = "unknown db"; + } diff --git a/disable_bdb.diff b/disable_bdb.diff new file mode 100644 index 0000000..ec419d9 --- /dev/null +++ b/disable_bdb.diff @@ -0,0 +1,15 @@ +--- configure.ac.orig 2020-01-17 12:25:06.451387587 +0000 ++++ configure.ac 2020-01-17 12:25:17.707357939 +0000 +@@ -537,11 +537,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([ diff --git a/ndb_backport.diff b/ndb_backport.diff new file mode 100644 index 0000000..89a3050 --- /dev/null +++ b/ndb_backport.diff @@ -0,0 +1,715 @@ +--- ./lib/backend/ndb/glue.c.orig 2020-01-17 12:40:07.393014566 +0000 ++++ ./lib/backend/ndb/glue.c 2020-01-17 12:40:21.244978080 +0000 +@@ -52,8 +52,8 @@ static void closeEnv(rpmdb rdb) + if (ndbenv->data) + free(ndbenv->data); + free(ndbenv); ++ rdb->db_dbenv = 0; + } +- rdb->db_dbenv = 0; + } + + static struct ndbEnv_s *openEnv(rpmdb rdb) +@@ -80,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); +@@ -130,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 */ +@@ -144,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"); +@@ -153,6 +180,8 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag + } + 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; +@@ -179,7 +208,13 @@ static int ndb_Open(rpmdb rdb, rpmDbiTag + + 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) +@@ -396,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/rpmpkg.c.orig 2019-11-13 09:19:29.306710577 +0000 ++++ ./lib/backend/ndb/rpmpkg.c 2020-01-17 12:40:21.244978080 +0000 +@@ -7,7 +7,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -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; +@@ -200,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; +@@ -208,14 +196,14 @@ 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); ++ if (hash) ++ free(hash); + hash = pkgdb->slothash = xcalloc(num, sizeof(unsigned int)); + pkgdb->nslothash = num; + } else { +@@ -228,8 +216,6 @@ static int rpmpkgHashSlots(rpmpkgdb pkgd + ; + hash[h] = i + 1; + } +- pkgdb->slothash = hash; +- pkgdb->nslothash = num; + return RPMRC_OK; + } + +@@ -247,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; + +@@ -262,8 +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 = 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); +@@ -299,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)) { +@@ -317,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); + } + +@@ -340,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; +@@ -348,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; +@@ -382,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++) { +@@ -413,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; + } + +@@ -433,6 +415,7 @@ static int rpmpkgWriteslot(rpmpkgdb pkgd + return RPMRC_FAIL; + } + pkgdb->generation++; ++ /* rpmpkgFsync() is done by rpmpkgWriteHeader() */ + if (rpmpkgWriteHeader(pkgdb)) { + return RPMRC_FAIL; + } +@@ -527,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) +@@ -536,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; +@@ -555,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 */ +@@ -600,8 +583,8 @@ static int rpmpkgReadBlob(rpmpkgdb pkgdb + } + if (bloblp) + *bloblp = bloblen; +- if (tstampp) +- *tstampp = tstamp; ++ if (generationp) ++ *generationp = generation; + return RPMRC_OK; + } + +@@ -684,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 = 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; + } +@@ -703,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 */ +@@ -729,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 */ +@@ -958,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; + } +@@ -981,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 */ +@@ -1006,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; +@@ -1023,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; +@@ -1049,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; +@@ -1065,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; +@@ -1104,7 +1089,7 @@ static int rpmpkgListInternal(rpmpkgdb p + *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++) { +@@ -1115,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; +@@ -1127,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; + } + +@@ -1143,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; + } +@@ -1184,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)) +@@ -1233,64 +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 = 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 +--- ./lib/backend/ndb/rpmpkg.h.orig 2019-06-26 14:17:31.406985703 +0000 ++++ ./lib/backend/ndb/rpmpkg.h 2020-01-17 12:40:21.244978080 +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 2019-11-13 09:19:29.307710583 +0000 ++++ ./lib/backend/ndb/rpmxdb.c 2020-01-17 12:41:30.268800690 +0000 +@@ -224,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; +@@ -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) +- 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; +@@ -922,6 +930,43 @@ int rpmxdbDelBlob(rpmxdb xdb, unsigned i + rpmxdbUnlock(xdb, 1); + 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) + { +--- ./lib/backend/ndb/rpmxdb.h.orig 2019-11-13 09:19:29.307710583 +0000 ++++ ./lib/backend/ndb/rpmxdb.h 2020-01-17 12:40:23.712971581 +0000 +@@ -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); diff --git a/rpm.changes b/rpm.changes index 22a2bca..bb7bf9a 100644 --- a/rpm.changes +++ b/rpm.changes @@ -11,6 +11,12 @@ Fri Jan 17 11:27:17 CET 2020 - mls@suse.de - Backport read-only BerkeleyDB code new patch: bdb_ro.diff - Enable ndb backend +- Backport bdb disabling fix + new patch: disable_bdb.diff +- Backport ndb improvements + new patch: ndb_backport.diff +- Backport automatic db conversion + new patch: db_conversion.diff ------------------------------------------------------------------- Fri Dec 6 15:30:48 CET 2019 - mls@suse.de diff --git a/rpm.spec b/rpm.spec index 70f57c0..105fae3 100644 --- a/rpm.spec +++ b/rpm.spec @@ -127,6 +127,9 @@ Patch109: pythondistdeps.diff Patch117: findsupplements.diff Patch118: db_ops_name.diff Patch119: bdb_ro.diff +Patch120: disable_bdb.diff +Patch121: ndb_backport.diff +Patch122: db_conversion.diff Patch6464: auto-config-update-aarch64-ppc64le.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build # @@ -232,7 +235,7 @@ rm -f rpmdb/db.h %patch -P 93 -P 94 -P 99 %patch -P 100 -P 102 -P 103 %patch -P 109 -P 117 -%patch -P 118 -P 119 +%patch -P 118 -P 119 -P 120 -P 121 -P 122 %ifarch aarch64 ppc64le riscv64 %patch6464