diff --git a/rpm-5.4.10-debugedit-saner-error-msg.patch b/rpm-5.4.10-debugedit-saner-error-msg.patch new file mode 100644 index 0000000..c577ba1 --- /dev/null +++ b/rpm-5.4.10-debugedit-saner-error-msg.patch @@ -0,0 +1,11 @@ +--- rpm-5.4.10/tools/debugedit.c.debugedit_errmsg~ 2013-01-03 09:24:01.764153125 +0100 ++++ rpm-5.4.10/tools/debugedit.c 2013-01-03 09:31:33.485896571 +0100 +@@ -696,7 +696,7 @@ edit_dwarf2_line (DSO *dso, rpmuint32_t + { + if (--shrank == 0) + error (EXIT_FAILURE, 0, +- "canonicalization unexpectedly shrank by one character"); ++ "canonicalization unexpectedly shrank by one character ('%s' vs '%s')", base_dir, dest_dir); + else + { + memset (ptr, 'X', shrank); diff --git a/rpm-5.4.10-enable-nofsync-for-rpm-rebuilddb.patch b/rpm-5.4.10-enable-nofsync-for-rpm-rebuilddb.patch new file mode 100644 index 0000000..3ee51e6 --- /dev/null +++ b/rpm-5.4.10-enable-nofsync-for-rpm-rebuilddb.patch @@ -0,0 +1,11 @@ +--- rpm-5.4.10/macros/mandriva.in~ 2013-04-02 08:31:46.123220885 +0200 ++++ rpm-5.4.10/macros/mandriva.in 2013-04-02 08:33:23.468152733 +0200 +@@ -187,6 +187,8 @@ export CFLAGS="%{optflags} -fPIE"; expor + # 0x00f00 (_RPMVSF_NOHEADER) --nohdrchk if set, don't check rpmdb headers + %_vsflags_query 0xc0c00 + ++# enable nofsync when rebuilding rpmdb ++%__dbi_rebuild nofsync + + # Open all indices before doing chroot(2). + # diff --git a/rpm-5.4.10-fix-a-couple-of-debugedit-memleaks.patch b/rpm-5.4.10-fix-a-couple-of-debugedit-memleaks.patch new file mode 100644 index 0000000..db62c3d --- /dev/null +++ b/rpm-5.4.10-fix-a-couple-of-debugedit-memleaks.patch @@ -0,0 +1,11 @@ +--- rpm-5.4.10/tools/debugedit.c.debugedit_memleaks~ 2012-05-19 22:14:30.000000000 +0200 ++++ rpm-5.4.10/tools/debugedit.c 2013-01-03 09:24:01.764153125 +0100 +@@ -1689,6 +1689,8 @@ main (int argc, char *argv[]) + /* Restore old access rights */ + chmod (file, stat_buf.st_mode); + ++ _free(dso->filename); ++ _free(dso); + poptFreeContext (optCon); + + return 0; diff --git a/rpm-5.4.10-rpmdb-typecasts.patch b/rpm-5.4.10-rpmdb-typecasts.patch new file mode 100644 index 0000000..ea81cac --- /dev/null +++ b/rpm-5.4.10-rpmdb-typecasts.patch @@ -0,0 +1,56 @@ +--- rpm-5.4.10/rpmdb/rpmdb.h.typecast~ 2013-01-16 18:43:33.115896979 +0100 ++++ rpm-5.4.10/rpmdb/rpmdb.h 2013-01-16 18:43:37.789965686 +0100 +@@ -938,7 +938,7 @@ fprintf(stderr, "<-- %s(%p,%p,0x%x) logc + /*@unused@*/ static inline + int rpmlgcGet(rpmdb rpmdb, DB_LSN * _lsn, DBT * data, uint32_t flags) + { +- DB_LOGC * _logc = rpmdb->db_logc; ++ DB_LOGC * _logc = (DB_LOGC*)rpmdb->db_logc; + int rc = (_logc ? _logc->get(_logc, _lsn, data, flags) : ENOTSUP); + if (_rpmdb_debug) + fprintf(stderr, "<-- %s(%p,%p,%p,0x%x) rc %d\n", "logc->get", _logc, _lsn, data, flags, rc); +@@ -948,7 +948,7 @@ fprintf(stderr, "<-- %s(%p,%p,%p,0x%x) r + /*@unused@*/ static inline + int rpmlgcClose(rpmdb rpmdb) + { +- DB_LOGC * _logc = rpmdb->db_logc; ++ DB_LOGC * _logc = (DB_LOGC*)rpmdb->db_logc; + uint32_t _flags = 0; + int rc = (_logc ? _logc->close(_logc, _flags) : ENOTSUP); + rpmdb->db_logc = NULL; +@@ -1026,7 +1026,7 @@ fprintf(stderr, "<-- %s(%p,%d) nwrote %d + /*@unused@*/ static inline + int rpmmpfClose(rpmdb rpmdb) + { +- DB_MPOOLFILE * mpf = rpmdb->db_mpf; ++ DB_MPOOLFILE * mpf = (DB_MPOOLFILE*)rpmdb->db_mpf; + uint32_t _flags = 0; + int rc = (mpf ? mpf->close(mpf, _flags) : ENOTSUP); + rpmdb->db_mpf = NULL; +@@ -1038,7 +1038,7 @@ fprintf(stderr, "<-- %s(%p) rc %d\n", "m + /*@unused@*/ static inline + int rpmmpfGet(rpmdb rpmdb, uint32_t * _pgnop, uint32_t _flags, void ** _pagep) + { +- DB_MPOOLFILE * mpf = rpmdb->db_mpf; ++ DB_MPOOLFILE * mpf = (DB_MPOOLFILE*)rpmdb->db_mpf; + DB_TXN * _txnid = (DB_TXN*)rpmdb->db_txn; + int rc = mpf->get(mpf, _pgnop, _txnid, _flags, _pagep); + if (_rpmdb_debug) +@@ -1072,7 +1072,7 @@ exit: + /*@unused@*/ static inline + int rpmmpfPut(rpmdb rpmdb, void * _page, uint32_t flags) + { +- DB_MPOOLFILE * mpf = rpmdb->db_mpf; ++ DB_MPOOLFILE * mpf = (DB_MPOOLFILE*) rpmdb->db_mpf; + uint32_t _priority = DB_PRIORITY_DEFAULT; + int rc = mpf->put(mpf, _page, (DB_CACHE_PRIORITY)_priority, flags); + if (_rpmdb_debug) +@@ -1083,7 +1083,7 @@ fprintf(stderr, "<-- %s(%p,%p,0x%x,0x%x) + /*@unused@*/ static inline + int rpmmpfSync(rpmdb rpmdb) + { +- DB_MPOOLFILE * mpf = rpmdb->db_mpf; ++ DB_MPOOLFILE * mpf = (DB_MPOOLFILE*)rpmdb->db_mpf; + int rc = (mpf ? mpf->sync(mpf) : ENOTSUP); + if (_rpmdb_debug) + fprintf(stderr, "<-- %s(%p) rc %d\n", "mpf->close", mpf, rc); diff --git a/rpm-5.4.10-rpmdbchk.patch b/rpm-5.4.10-rpmdbchk.patch new file mode 100644 index 0000000..70e6a39 --- /dev/null +++ b/rpm-5.4.10-rpmdbchk.patch @@ -0,0 +1,333 @@ +--- rpm-5.4.10/tools/Makefile.am.rpmdbchk~ 2012-05-04 17:58:08.000000000 +0200 ++++ rpm-5.4.10/tools/Makefile.am 2013-04-02 09:11:56.264985289 +0200 +@@ -29,7 +29,7 @@ EXTRA_PROGRAMS = augtool cudftool dbconv + nix-env nix-hash nix-install-package nix-instantiate \ + nix-log2xml nix-prefetch-url nix-pull nix-push nix-store nix-worker \ + xiu-echo xiu-hash xiu-instantiate xiu-store \ +- roto rpmkey sandbox semodule spooktool ++ roto rpmdbchk rpmkey sandbox semodule spooktool + + RPMMISC_LDADD_COMMON = \ + $(top_builddir)/misc/librpmmisc.la \ +@@ -60,7 +60,7 @@ pkgbin_PROGRAMS = \ + rpmcache rpmdigest rpmrepo rpmspecdump \ + rpmcmp rpmdeps sqlite3 @WITH_KEYUTILS_RPMKEY@ @WITH_LIBELF_DEBUGEDIT@ + if WITH_DB +-pkgbin_PROGRAMS += dbconvert ++pkgbin_PROGRAMS += dbconvert rpmdbchk + endif + dist_man_MANS = rpmgrep.1 + +@@ -230,6 +230,13 @@ rpm2cpio_LDFLAGS = @LDFLAGS_STATIC@ $(LD + rpm2cpio_LDADD = $(LDFLAGS) $(RPM_LDADD_COMMON) + + ## ++## rpmdbchk tool for finding and fixing broken headers ++## ++rpmdbchk_SOURCES = rpmdbchk.c ++rpmdbchk_LDFLAGS = @LDFLAGS_STATIC@ $(LDFLAGS) ++rpmdbchk_LDADD = $(LDFLAGS) $(RPM_LDADD_COMMON) ++ ++## + ## keyctl(1) clone + ## + rpmkey_SOURCES = rpmkey.c +--- rpm-5.4.10/tools/rpmdbchk.c.rpmdbchk~ 2013-04-02 09:11:56.264985289 +0200 ++++ rpm-5.4.10/tools/rpmdbchk.c 2013-04-06 01:03:20.082982283 +0200 +@@ -0,0 +1,296 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define _RPMTAG_INTERNAL ++#define _RPMDB_INTERNAL ++#define WITH_DB ++#include ++ ++#include ++#include ++#include ++#include ++ ++static char *rootPath = NULL; ++static char *rpmdbPath = NULL; ++static int checkOnly = 0; ++ ++struct node { ++ uint32_t state; ++ uint32_t keysize; ++ void *keydata; ++ struct node *next; ++}; ++ ++static int ++rpmdb_check(const char *prefix, const char *path, uint32_t **state, uint32_t *nkeys, struct node **broken) ++{ ++ rpmts ts = NULL; ++ ++ const char * dbpath = path ? path : rpmExpand("%{?_dbpath}", NULL); ++ ++ DBC *dbcp = NULL; ++ dbiIndex dbi = NULL; ++ DBT key; ++ DBT data; ++ DB_TXN *txnid = NULL; ++ DB *bdb; ++ ++ uint32_t hdrNum = 0; ++ uint32_t damaged = 0; ++ float pct = 0; ++ uint8_t tmp; ++ ++ int xx; ++ ++ ts = rpmtsCreate(); ++ ++ addMacro(NULL, "_dbpath", NULL, dbpath, -1); ++ rpmtsSetRootDir(ts, prefix && prefix[0] ? prefix : NULL); ++ if(rpmtsOpenDB(ts, O_RDONLY)) ++ goto exit; ++ ++ dbi = dbiOpen(rpmtsGetRdb(ts), RPMDBI_PACKAGES, 0); ++ ++ if ((xx = dbiCopen(dbi, NULL, NULL, 0))) ++ goto exit; ++ ++ txnid = dbiTxnid(dbi); ++ *nkeys = 0; ++ ++ memset(&key, 0, sizeof(key)); ++ memset(&data, 0, sizeof(data)); ++ bdb = dbi->dbi_db; ++ ++ /* Acquire a cursor for the database. */ ++ xx = bdb->cursor(bdb, NULL, &dbcp, 0); ++ if (xx) ++ bdb->err(bdb, xx, "DB->cursor"); ++ ++ xx = bdb->stat(bdb, txnid, &dbi->dbi_stats, 0); ++ if (xx) ++ goto exit; ++ ++ switch (bdb->type) { ++ case DB_BTREE: ++ case DB_RECNO:{ ++ DB_BTREE_STAT *db_stat = dbi->dbi_stats; ++ *nkeys = db_stat->bt_nkeys; ++ } break; ++ case DB_HASH:{ ++ DB_HASH_STAT *db_stat = dbi->dbi_stats; ++ *nkeys = db_stat->hash_nkeys; ++ } break; ++ case DB_QUEUE:{ ++ DB_QUEUE_STAT *db_stat = dbi->dbi_stats; ++ *nkeys = db_stat->qs_nkeys; ++ } break; ++ case DB_UNKNOWN: ++ default: ++ xx = -1; ++ goto exit; ++ break; ++ } ++ uint32_t *status = calloc(*nkeys, sizeof(uint32_t)); ++ struct node *curr; ++ ++ hdrNum = 0; ++ pct = 0; ++ ++ while ((xx = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0) { ++ tmp = pct; ++ pct = (100 * (float) ++hdrNum / *nkeys) + 0.5; ++ /* TODO: callbacks for status output? */ ++ if (tmp < (int) (pct + 0.5)) { ++ fprintf(stderr, "\rchecking %s%s/Packages: %u/%u %d%%", ++ prefix && prefix[0] ? prefix : "", ++ dbpath, hdrNum, *nkeys, (int) pct); ++ } ++ const char *msg = NULL; ++ int lvl = headerCheck(rpmtsDig(ts), data.data, data.size, &msg); ++ rpmtsCleanDig(ts); ++ if (lvl == RPMRC_FAIL) { ++ status[hdrNum-1] = htonl(*(uint32_t*)(dbcp->rkey->data)); ++ damaged++; ++ fprintf(stderr, "\n%d (%d): %s\n", hdrNum-1, status[hdrNum-1], msg); ++ } else if (key.size != sizeof(hdrNum)) { ++ curr = malloc(sizeof(struct node)); ++ curr->state = htonl(*(uint32_t*)(dbcp->rkey->data)); ++ curr->keysize = key.size; ++ curr->keydata = malloc(key.size); ++ memcpy(curr->keydata, key.data, key.size); ++ curr->next = *broken; ++ *broken = curr; ++ status[hdrNum-1] = -1; ++ damaged++; ++ fprintf(stderr, "\n%d: %s (key.size(%d) != %d)\n", hdrNum-1, msg, key.size, sizeof(hdrNum)); ++ } else ++ status[hdrNum-1] = -1; ++ fflush(stderr); ++ } ++ ++ fprintf(stderr, "\n"); ++ ++ ++ *state = status; ++ xx = dbiCclose(dbi, dbcp, 0); ++ ++exit: ++ xx = rpmtsCloseDB(ts); ++ ts = rpmtsFree(ts); ++ ++ return damaged; ++} ++ ++static int ++rpmdb_dump_delete(DB *dbp, const char *db, const char *lost, DBT *key, uint32_t n) { ++ int gotrec; ++ int ret = 0; ++ DBT data; ++ ++ memset(&data, 0, sizeof(data)); ++ ++ if ((ret = dbp->get(dbp, NULL, key, &data, 0)) == 0) { ++ char copy[1024]; ++ snprintf(copy, sizeof(copy), "%s/header.%d", lost, n); ++ FILE *fp = fopen(copy, "w"); ++ fwrite(data.data, data.size, 1, fp); ++ fclose(fp); ++ gotrec = 0; ++ memcpy(&gotrec, key->data, sizeof(gotrec)); ++ printf("db: get key: %p[%d] = 0x%x, data at %p[%d].\n", ++ (char *)key->data, key->size, gotrec, ++ (char *)data.data, data.size); ++ printf("Dumping broken header to disk: %s\n", copy); ++ } else { ++ dbp->err(dbp, ret, "DB->get"); ++ if (ret == DB_NOTFOUND) ++ return 0; ++ return ret; ++ } ++ ++ if ((ret = dbp->del(dbp, NULL, key, 0)) == 0) { ++ gotrec = 0; ++ memcpy(&gotrec, key->data, sizeof(gotrec)); ++ printf("db: del key: %p[%d] = 0x%x, data at %p[%d].\n", ++ (char *)key->data, key->size, gotrec, ++ (char *)data.data, data.size); ++ } else { ++ dbp->err(dbp, ret, "DB->del"); ++ return ret; ++ } ++ return 0; ++} ++ ++static int ++rpmdb_fix(const char *prefix, const char *path, uint32_t *state, uint32_t nkeys, struct node *broken) ++{ ++ DB * dbp; ++ DBT key; ++ struct stat sb; ++ const char * db = rpmGetPath(prefix && prefix[0] ? prefix : "", path, "/Packages", NULL); ++ const char * lost = rpmGetPath(prefix && prefix[0] ? prefix : "", path, "/broken", NULL); ++ int ret, t_ret; ++ uint32_t i; ++ ++ ++ if ((ret = db_create(&dbp, NULL, 0)) != 0) { ++ fprintf(stderr, "db_create: %s\n", db_strerror(ret)); ++ exit (1); ++ } ++ ++ if (Stat(lost, &sb)) ++ Mkdir(lost, 0700); ++ ++ if ((ret = dbp->open(dbp, NULL, db, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) { ++ dbp->err(dbp, ret, "%s", db); ++ goto err; ++ } ++ ++ for (i = 0; i < nkeys; i++) { ++ if (state[i] == -1) continue; ++ int badrec, badrec2; ++ memset(&key, 0, sizeof(key)); ++ badrec2 = state[i]; ++ badrec = htonl(badrec2); ++ printf("fix record[%d] at #%d/#%d --\n", i, badrec2, badrec); ++ key.data = &badrec; ++ key.size = sizeof(badrec); ++ ++ ret = rpmdb_dump_delete(dbp, db, lost, &key, state[i]); ++ } ++ ++ while (broken) { ++ memset(&key, 0, sizeof(key)); ++ key.size = broken->keysize; ++ key.data = broken->keydata; ++ ret = rpmdb_dump_delete(dbp, db, lost, &key, broken->state); ++ free(broken->keydata); ++ free(broken); ++ broken = broken->next; ++ } ++ ++ ++err: ++ if ((t_ret = dbp->close(dbp, 0)) != 0 && ret == 0) ++ ret = t_ret; ++ _free(db); ++ _free(lost); ++ ++ return 0; ++} ++ ++static struct poptOption optionsTable[] = { ++ { "root", '\0', POPT_ARG_STRING, &rootPath, 0, ++ "rpm root path", "path"}, ++ { "dbpath", '\0', POPT_ARG_STRING, &rpmdbPath, 0, ++ "rpmdb path", "path"}, ++ { "checkonly", '\0', POPT_ARG_VAL, &checkOnly, 1, ++ "only check, don't fix anything", NULL}, ++ ++ POPT_AUTOALIAS ++ POPT_AUTOHELP ++ POPT_TABLEEND ++}; ++ ++int main(int argc, char *argv[]) ++{ ++ poptContext optCon = rpmcliInit(argc, argv, optionsTable); ++ ARGV_t av = poptGetArgs(optCon); ++ int ac = argvCount(av); ++ int rc = 2; /* assume failure */ ++ uint32_t nkeys = 0; ++ uint32_t *state = NULL; ++ struct node *broken = NULL; ++ ++ if (ac) { ++ poptPrintUsage(optCon, stderr, 0); ++ goto exit; ++ } ++ ++ rc = rpmReadConfigFiles(NULL, NULL); ++ ++ ++ rc = rpmdb_check(rootPath, rpmdbPath, &state, &nkeys, &broken); ++ printf("%d/%d (%f%%) headers damaged", rc, nkeys, (float)rc/nkeys); ++ printf("\n"); ++ if (!checkOnly && rc) { ++ printf("fixing...\n"); ++ rc = rpmdb_fix(rootPath, rpmdbPath, state, nkeys, broken); ++ } ++ ++exit: ++ _free(state); ++ optCon = rpmcliFini(optCon); ++ return rc; ++} diff --git a/rpm.spec b/rpm.spec index f05f8c2..294c1a0 100644 --- a/rpm.spec +++ b/rpm.spec @@ -59,7 +59,7 @@ Summary: The RPM package management system Name: rpm Epoch: 1 Version: %{libver}.%{minorver} -Release: %{?prereldate:0.%{prereldate}.}13 +Release: %{?prereldate:0.%{prereldate}.}14 License: LGPLv2.1+ Group: System/Configuration/Packaging URL: http://rpm5.org/ @@ -364,12 +364,28 @@ Patch170: rpm-5.4.10-dbconvert-5.2.patch # Do not generate pythonegg provides for python3 until we find a better solution Patch171: rpm-5.4.10-python3-egg-reqs.patch +# just fix a couple of minor memleaks at exit.. +# status: ready +Patch173: rpm-5.4.10-fix-a-couple-of-debugedit-memleaks.patch +# make "canonicalization(...)shrank by one character" error message more useful +# status: ready +Patch174: rpm-5.4.10-debugedit-saner-error-msg.patch + +# tool for automatically checking and fixing broken rpmdb +# status: probably' worth merging upstream +Patch179: rpm-5.4.10-rpmdbchk.patch +# adds casts for C++ compatibility +# status: ready +Patch180: rpm-5.4.10-rpmdb-typecasts.patch + # adds ability for printing parsed version of spec file with 'rpm -q --specfile --printspec' # status: very simple, non-intrusive, while quite convenient, should be okay to merge Patch181: rpm-5.4.10-printspec.patch Patch191: rpm-5.4.10-enhance-rename-macro-to-accept-optional-second-version-arg.patch +Patch198: rpm-5.4.10-enable-nofsync-for-rpm-rebuilddb.patch + # ROSA stuff Patch501: rpm-5.3.12.vendor.ROSA.patch # Restore RPM_PACKAGE_NAME export as it's still used by aot-compile-rpm @@ -446,7 +462,7 @@ BuildRequires: squirrel-devel %if %{with docs} BuildRequires: doxygen BuildRequires: graphviz -BuildRequires: texlive +#BuildRequires: texlive %endif %if %{with sqlite} BuildRequires: pkgconfig(sqlite3) @@ -744,9 +760,16 @@ This package contains the RPM API documentation generated in HTML format. %patch170 -p1 -b .dbconvert52~ %patch171 -p1 -b .python3~ +%patch173 -p1 -b .debugedit_memleaks~ +%patch174 -p1 -b .debugedit_errmsg~ + +%patch179 -p1 -b .rpmdbchk~ +%patch180 -p1 -b .typecast~ %patch181 -p1 -b .printspec~ %patch191 -p1 -b .rename~ +%patch198 -p1 -b .rpmdbnofsync~ + %patch501 -p1 -b .rosa_vendor~ %patch502 -p1 -b .package_name~ %patch503 -p1 -b .specspo~ @@ -973,6 +996,7 @@ ln -f %{buildroot}%{_rpmhome}/bin/{rpmluac,luac} %{_rpmhome}/bin/mtree %{_rpmhome}/bin/mgo #%%{_rpmhome}/bin/rc +%{_rpmhome}/bin/rpmdbchk %{_rpmhome}/bin/rpmspecdump %{_rpmhome}/bin/wget %if %{with xar}