--- ./lib/backend/ndb/glue.c.orig 2020-01-23 12:47:46.527816289 +0000 +++ ./lib/backend/ndb/glue.c 2020-01-23 12:48:20.915728982 +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-23 12:48:59.739630414 +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,14 +965,15 @@ 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; } + /* update nextpkgidx if needed */ + if (pkgidx >= pkgdb->nextpkgidx) { + pkgdb->nextpkgidx = pkgidx + 1; + } /* write slot */ slotno = oldslot ? oldslot->slotno : pkgdb->freeslot; - if (!slotno) { - return RPMRC_FAIL; - } if (rpmpkgWriteslot(pkgdb, slotno, pkgidx, blkoff, blkcnt)) { free(pkgdb->slots); pkgdb->slots = 0; @@ -1006,7 +991,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 +1008,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 +1034,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 +1051,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 +1090,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 +1101,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 +1129,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 +1141,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 +1173,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 +1232,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-23 12:48:20.919728972 +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-23 12:48:20.919728972 +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-23 12:48:20.919728972 +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);