diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..81a929e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +SOURCES/db-5.3.28.tar.gz +SOURCES/db.1.85.tar.gz +SOURCES/libdb-5.3.28-manpages.tar.gz diff --git a/.libdb.metadata b/.libdb.metadata new file mode 100644 index 0000000..e8c2e4e --- /dev/null +++ b/.libdb.metadata @@ -0,0 +1,3 @@ +fa3f8a41ad5101f43d08bc0efb6241c9b6fc1ae9 SOURCES/db-5.3.28.tar.gz +ccb057b07761d1b2b34626e748c7392c749d5e6d SOURCES/db.1.85.tar.gz +c90635ffef230707c87f1353495972f8041882bd SOURCES/libdb-5.3.28-manpages.tar.gz diff --git a/SOURCES/007-mt19937db.c_license.patch b/SOURCES/007-mt19937db.c_license.patch new file mode 100644 index 0000000..eab05d7 --- /dev/null +++ b/SOURCES/007-mt19937db.c_license.patch @@ -0,0 +1,49 @@ +Description: mt19937db.c license should include the GPL + This file is distributed from upstream Berkeley DB under the Artistic + License (no version specified), althouth it was later released by the + original author under both GPL2+ and BSD. + . + References: + http://web.archive.org/web/20010806225716/http://www.math.keio.ac.jp/matumoto/mt19937int.c + http://web.archive.org/web/20130127064020/http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c + https://bugzilla.redhat.com/show_bug.cgi?format=multiple&id=886838 + https://lists.nongnu.org/archive/html/gnu-linux-libre/2010-05/msg00000.html + . +Author: Ruben Rodriguez + + +--- db-5.3.21/src/crypto/mersenne/mt19937db.c.licensefix ++++ db-5.3.21/src/crypto/mersenne/mt19937db.c +@@ -16,16 +16,27 @@ + /* Coded by Takuji Nishimura, considering the suggestions by */ + /* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ + +-/* This library is free software under the Artistic license: */ +-/* see the file COPYING distributed together with this code. */ +-/* For the verification of the code, its output sequence file */ +-/* mt19937int.out is attached (2001/4/2) */ +- + /* Copyright (C) 1997, 1999 Makoto Matsumoto and Takuji Nishimura. */ + /* Any feedback is very welcome. For any question, comments, */ + /* see http://www.math.keio.ac.jp/matumoto/emt.html or email */ + /* matumoto@math.keio.ac.jp */ + ++/* This library is free software; you can redistribute it and/or */ ++/* modify it under the terms of the GNU Library General Public */ ++/* License as published by the Free Software Foundation; either */ ++/* version 2 of the License, or (at your option) any later */ ++/* version. */ ++/* This library is distributed in the hope that it will be useful, */ ++/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ ++/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ ++/* See the GNU Library General Public License for more details. */ ++/* You should have received a copy of the GNU Library General */ ++/* Public License along with this library; if not, write to the */ ++/* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ ++/* 02111-1307 USA */ ++ ++/* This library is free software under the Artistic license: */ ++ + /* REFERENCE */ + /* M. Matsumoto and T. Nishimura, */ + /* "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform */ diff --git a/SOURCES/checkpoint-opd-deadlock.patch b/SOURCES/checkpoint-opd-deadlock.patch new file mode 100644 index 0000000..7aab6e1 --- /dev/null +++ b/SOURCES/checkpoint-opd-deadlock.patch @@ -0,0 +1,14 @@ +--- db-5.3.21/src/db/db_cam.c.opd_deadlock 2017-10-31 12:20:54.118979690 +0100 ++++ db-5.3.21/src/db/db_cam.c 2017-10-31 12:21:06.828739341 +0100 +@@ -868,6 +868,11 @@ + flags == DB_PREV || flags == DB_PREV_DUP)) { + if (tmp_rmw && (ret = dbc->am_writelock(dbc)) != 0) + goto err; ++ /* Latch the primary tree page here in order to not deadlock later. */ ++ if (cp->page == NULL && ++ (ret = __memp_fget(mpf, &cp->pgno, ++ dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) ++ goto err; + if (F_ISSET(dbc, DBC_TRANSIENT)) + opd = cp->opd; + else if ((ret = __dbc_idup(cp->opd, &opd, DB_POSITION)) != 0) diff --git a/SOURCES/db-1.85-errno.patch b/SOURCES/db-1.85-errno.patch new file mode 100644 index 0000000..ccc9ddf --- /dev/null +++ b/SOURCES/db-1.85-errno.patch @@ -0,0 +1,89 @@ +glibc doesn't like errno as the name of a field. +--- db.1.85/hash/hash.h Mon Feb 18 19:12:14 2002 ++++ db.1.85/hash/hash.h Mon Feb 18 19:12:20 2002 +@@ -103,7 +103,7 @@ + BUFHEAD *cpage; /* Current page */ + int cbucket; /* Current bucket */ + int cndx; /* Index of next item on cpage */ +- int errno; /* Error Number -- for DBM ++ int err; /* Error Number -- for DBM + * compatability */ + int new_file; /* Indicates if fd is backing store + * or no */ +--- db.1.85/hash/hash.c Mon Feb 18 19:12:24 2002 ++++ db.1.85/hash/hash.c Mon Feb 18 19:12:44 2002 +@@ -505,7 +505,7 @@ + else + if (wsize != sizeof(HASHHDR)) { + errno = EFTYPE; +- hashp->errno = errno; ++ hashp->err = errno; + return (-1); + } + for (i = 0; i < NCACHED; i++) +@@ -536,7 +536,7 @@ + + hashp = (HTAB *)dbp->internal; + if (flag) { +- hashp->errno = errno = EINVAL; ++ hashp->err = errno = EINVAL; + return (ERROR); + } + return (hash_access(hashp, HASH_GET, (DBT *)key, data)); +@@ -553,11 +553,11 @@ + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_NOOVERWRITE) { +- hashp->errno = errno = EINVAL; ++ hashp->err = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { +- hashp->errno = errno = EPERM; ++ hashp->err = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, flag == R_NOOVERWRITE ? +@@ -574,11 +574,11 @@ + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_CURSOR) { +- hashp->errno = errno = EINVAL; ++ hashp->err = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { +- hashp->errno = errno = EPERM; ++ hashp->err = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL)); +@@ -729,7 +729,7 @@ + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_FIRST && flag != R_NEXT) { +- hashp->errno = errno = EINVAL; ++ hashp->err = errno = EINVAL; + return (ERROR); + } + #ifdef HASH_STATISTICS +--- db.1.85/hash/ndbm.c Mon Feb 18 19:12:58 2002 ++++ db.1.85/hash/ndbm.c Mon Feb 18 19:13:05 2002 +@@ -180,7 +180,7 @@ + HTAB *hp; + + hp = (HTAB *)db->internal; +- return (hp->errno); ++ return (hp->err); + } + + extern int +@@ -190,7 +190,7 @@ + HTAB *hp; + + hp = (HTAB *)db->internal; +- hp->errno = 0; ++ hp->err = 0; + return (0); + } + diff --git a/SOURCES/db-4.5.20-jni-include-dir.patch b/SOURCES/db-4.5.20-jni-include-dir.patch new file mode 100644 index 0000000..b0881c3 --- /dev/null +++ b/SOURCES/db-4.5.20-jni-include-dir.patch @@ -0,0 +1,12 @@ +diff -up db-4.7.25/dist/configure.ac.jni db-4.7.25/dist/configure.ac +--- db-4.7.25/dist/configure.ac.jni 2008-08-20 14:22:59.000000000 +0200 ++++ db-4.7.25/dist/configure.ac 2008-08-20 14:23:39.000000000 +0200 +@@ -418,7 +418,7 @@ if test "$db_cv_java" = "yes"; then + AC_PROG_JAVAC + AC_PROG_JAR + AC_PROG_JAVA +- AC_JNI_INCLUDE_DIR ++ JNI_INCLUDE_DIRS="/usr/lib/jvm/java/include /usr/lib/jvm/java/include/linux" + + AC_MSG_CHECKING(java version) + case "$JAVA" in diff --git a/SOURCES/db-4.6.21-1.85-compat.patch b/SOURCES/db-4.6.21-1.85-compat.patch new file mode 100644 index 0000000..62ae950 --- /dev/null +++ b/SOURCES/db-4.6.21-1.85-compat.patch @@ -0,0 +1,14 @@ +diff -up db-5.1.19/dist/Makefile.in.185compat db-5.1.19/dist/Makefile.in +--- db-5.1.19/dist/Makefile.in.185compat 2010-08-27 17:08:03.000000000 +0200 ++++ db-5.1.19/dist/Makefile.in 2010-09-10 10:02:32.974640425 +0200 +@@ -193,8 +193,8 @@ libtso_major= $(libtcl_base)-$(LIBMAJOR) + # local libraries, for example. Do that by adding -I options to the DB185INC + # line, and -l options to the DB185LIB line. + ################################################## +-DB185INC= -c @CFLAGS@ -I$(topdir) @CPPFLAGS@ +-DB185LIB= ++DB185INC= -c @CFLAGS@ -I$(srcdir) -I$(srcdir)/db.1.85/PORT/linux/include @CPPFLAGS@ ++DB185LIB= ${srcdir}/db.1.85/PORT/linux/libdb.a + + ################################################## + # Performance Event Monitoring definitions diff --git a/SOURCES/db-5.3.21-memp_stat-upstream-fix.patch b/SOURCES/db-5.3.21-memp_stat-upstream-fix.patch new file mode 100644 index 0000000..9e3d52b --- /dev/null +++ b/SOURCES/db-5.3.21-memp_stat-upstream-fix.patch @@ -0,0 +1,183 @@ +diff -r -u db-5.3.21_orig/src/mp/mp_stat.c db-5.3.21/src/mp/mp_stat.c +--- db-5.3.21_orig/src/mp/mp_stat.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_stat.c 2015-05-19 15:07:09.000000000 +0800 +@@ -87,6 +87,13 @@ + u_int32_t i; + uintmax_t tmp_wait, tmp_nowait; + ++ /* ++ * The array holding the lengths related to the buffer allocated for *fspp. ++ * The first element of the array holds the number of entries allocated. ++ * The second element of the array holds the total number of bytes allocated. ++ */ ++ u_int32_t fsp_len[2]; ++ + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + +@@ -193,32 +200,53 @@ + if (fspp != NULL) { + *fspp = NULL; + +- /* Count the MPOOLFILE structures. */ +- i = 0; +- len = 0; +- if ((ret = __memp_walk_files(env, +- mp, __memp_count_files, &len, &i, flags)) != 0) +- return (ret); ++ while (*fspp == NULL) { ++ /* Count the MPOOLFILE structures. */ ++ i = 0; ++ /* ++ * Allow space for the first __memp_get_files() to align the ++ * structure array to uintmax_t, DB_MPOOL_STAT's most ++ * restrictive field. [#23150] ++ */ ++ len = sizeof(uintmax_t); ++ if ((ret = __memp_walk_files(env, ++ mp, __memp_count_files, &len, &i, flags)) != 0) ++ return (ret); ++ ++ if (i == 0) ++ return (0); ++ ++ /* ++ * Copy the number of DB_MPOOL_FSTAT entries and the number of ++ * bytes allocated for them into fsp_len. Do not count the space ++ * reserved for allignment. ++ */ ++ fsp_len[0] = i; ++ fsp_len[1] = len - sizeof(uintmax_t); + +- if (i == 0) +- return (0); +- len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */ ++ len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */ + +- /* Allocate space */ +- if ((ret = __os_umalloc(env, len, fspp)) != 0) +- return (ret); ++ /* Allocate space */ ++ if ((ret = __os_umalloc(env, len, fspp)) != 0) ++ return (ret); + +- tfsp = *fspp; +- *tfsp = NULL; +- +- /* +- * Files may have been opened since we counted, don't walk +- * off the end of the allocated space. +- */ +- if ((ret = __memp_walk_files(env, +- mp, __memp_get_files, &tfsp, &i, flags)) != 0) +- return (ret); ++ tfsp = *fspp; ++ *tfsp = NULL; + ++ /* ++ * Files may have been opened since we counted, if we walk off ++ * the end of the allocated space specified in fsp_len, retry. ++ */ ++ if ((ret = __memp_walk_files(env, ++ mp, __memp_get_files, &tfsp, fsp_len, flags)) != 0) { ++ if (ret == DB_BUFFER_SMALL) { ++ __os_ufree(env, *fspp); ++ *fspp = NULL; ++ tfsp = NULL; ++ } else ++ return (ret); ++ } ++ } + *++tfsp = NULL; + } + +@@ -286,28 +314,35 @@ + * for the text file names. + */ + static int +-__memp_get_files(env, mfp, argp, countp, flags) ++__memp_get_files(env, mfp, argp, fsp_len, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; +- u_int32_t *countp; ++ u_int32_t fsp_len[]; + u_int32_t flags; + { + DB_MPOOL *dbmp; + DB_MPOOL_FSTAT **tfsp, *tstruct; + char *name, *tname; +- size_t nlen; ++ size_t nlen, tlen; + +- if (*countp == 0) +- return (0); ++ /* We walked through more files than argp was allocated for. */ ++ if (fsp_len[0] == 0) ++ return DB_BUFFER_SMALL; + + dbmp = env->mp_handle; + tfsp = *(DB_MPOOL_FSTAT ***)argp; + + if (*tfsp == NULL) { +- /* Add 1 to count because we need to skip over the NULL. */ +- tstruct = (DB_MPOOL_FSTAT *)(tfsp + *countp + 1); +- tname = (char *)(tstruct + *countp); ++ /* ++ * Add 1 to count because to skip over the NULL end marker. ++ * Align it further for DB_MPOOL_STAT's most restrictive field ++ * because uintmax_t might require stricter alignment than ++ * pointers; e.g., IP32 LL64 SPARC. [#23150] ++ */ ++ tstruct = (DB_MPOOL_FSTAT *)&tfsp[fsp_len[0] + 1]; ++ tstruct = ALIGNP_INC(tstruct, sizeof(uintmax_t)); ++ tname = (char *)&tstruct[fsp_len[0]]; + *tfsp = tstruct; + } else { + tstruct = *tfsp + 1; +@@ -317,6 +352,15 @@ + + name = __memp_fns(dbmp, mfp); + nlen = strlen(name) + 1; ++ ++ /* The space required for file names is larger than argp was allocated for. */ ++ tlen = sizeof(DB_MPOOL_FSTAT *) + sizeof(DB_MPOOL_FSTAT) + nlen; ++ if (fsp_len[1] < tlen) ++ return DB_BUFFER_SMALL; ++ else ++ /* Count down the number of bytes left in argp. */ ++ fsp_len[1] -= tlen; ++ + memcpy(tname, name, nlen); + memcpy(tstruct, &mfp->stat, sizeof(mfp->stat)); + tstruct->file_name = tname; +@@ -325,7 +369,9 @@ + tstruct->st_pagesize = mfp->pagesize; + + *(DB_MPOOL_FSTAT ***)argp = tfsp; +- (*countp)--; ++ ++ /* Count down the number of entries left in argp. */ ++ fsp_len[0]--; + + if (LF_ISSET(DB_STAT_CLEAR)) + memset(&mfp->stat, 0, sizeof(mfp->stat)); +diff -r -u db-5.3.21_orig/src/mp/mp_sync.c db-5.3.21/src/mp/mp_sync.c +--- db-5.3.21_orig/src/mp/mp_sync.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_sync.c 2015-05-19 15:08:05.000000000 +0800 +@@ -57,11 +57,13 @@ + if ((t_ret = func(env, + mfp, arg, countp, flags)) != 0 && ret == 0) + ret = t_ret; +- if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR)) ++ if (ret != 0 && ++ (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL)) + break; + } + MUTEX_UNLOCK(env, hp->mtx_hash); +- if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR)) ++ if (ret != 0 && ++ (!LF_ISSET(DB_STAT_MEMP_NOERROR) || ret == DB_BUFFER_SMALL)) + break; + } + return (ret); diff --git a/SOURCES/db-5.3.21-mutex_leak.patch b/SOURCES/db-5.3.21-mutex_leak.patch new file mode 100644 index 0000000..0738dab --- /dev/null +++ b/SOURCES/db-5.3.21-mutex_leak.patch @@ -0,0 +1,718 @@ +diff -U 5 -r db-5.3.21.old/src/dbinc_auto/int_def.in db-5.3.21/src/dbinc_auto/int_def.in +--- db-5.3.21.old/src/dbinc_auto/int_def.in 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/dbinc_auto/int_def.in 2016-10-25 22:40:58.000000000 +0800 +@@ -1371,10 +1371,11 @@ + #define __memp_failchk __memp_failchk@DB_VERSION_UNIQUE_NAME@ + #define __memp_bhwrite __memp_bhwrite@DB_VERSION_UNIQUE_NAME@ + #define __memp_pgread __memp_pgread@DB_VERSION_UNIQUE_NAME@ + #define __memp_pg __memp_pg@DB_VERSION_UNIQUE_NAME@ + #define __memp_bhfree __memp_bhfree@DB_VERSION_UNIQUE_NAME@ ++#define __memp_bh_clear_dirty __memp_bh_clear_dirty@DB_VERSION_UNIQUE_NAME@ + #define __memp_fget_pp __memp_fget_pp@DB_VERSION_UNIQUE_NAME@ + #define __memp_fget __memp_fget@DB_VERSION_UNIQUE_NAME@ + #define __memp_fcreate_pp __memp_fcreate_pp@DB_VERSION_UNIQUE_NAME@ + #define __memp_fcreate __memp_fcreate@DB_VERSION_UNIQUE_NAME@ + #define __memp_set_clear_len __memp_set_clear_len@DB_VERSION_UNIQUE_NAME@ +@@ -1395,10 +1396,11 @@ + #define __memp_fopen __memp_fopen@DB_VERSION_UNIQUE_NAME@ + #define __memp_fclose_pp __memp_fclose_pp@DB_VERSION_UNIQUE_NAME@ + #define __memp_fclose __memp_fclose@DB_VERSION_UNIQUE_NAME@ + #define __memp_mf_discard __memp_mf_discard@DB_VERSION_UNIQUE_NAME@ + #define __memp_inmemlist __memp_inmemlist@DB_VERSION_UNIQUE_NAME@ ++#define __memp_mf_mark_dead __memp_mf_mark_dead@DB_VERSION_UNIQUE_NAME@ + #define __memp_fput_pp __memp_fput_pp@DB_VERSION_UNIQUE_NAME@ + #define __memp_fput __memp_fput@DB_VERSION_UNIQUE_NAME@ + #define __memp_unpin_buffers __memp_unpin_buffers@DB_VERSION_UNIQUE_NAME@ + #define __memp_dirty __memp_dirty@DB_VERSION_UNIQUE_NAME@ + #define __memp_shared __memp_shared@DB_VERSION_UNIQUE_NAME@ +@@ -1453,10 +1455,11 @@ + #define __memp_fsync_pp __memp_fsync_pp@DB_VERSION_UNIQUE_NAME@ + #define __memp_fsync __memp_fsync@DB_VERSION_UNIQUE_NAME@ + #define __mp_xxx_fh __mp_xxx_fh@DB_VERSION_UNIQUE_NAME@ + #define __memp_sync_int __memp_sync_int@DB_VERSION_UNIQUE_NAME@ + #define __memp_mf_sync __memp_mf_sync@DB_VERSION_UNIQUE_NAME@ ++#define __memp_purge_dead_files __memp_purge_dead_files@DB_VERSION_UNIQUE_NAME@ + #define __memp_trickle_pp __memp_trickle_pp@DB_VERSION_UNIQUE_NAME@ + #define __mutex_alloc __mutex_alloc@DB_VERSION_UNIQUE_NAME@ + #define __mutex_alloc_int __mutex_alloc_int@DB_VERSION_UNIQUE_NAME@ + #define __mutex_free __mutex_free@DB_VERSION_UNIQUE_NAME@ + #define __mutex_free_int __mutex_free_int@DB_VERSION_UNIQUE_NAME@ +diff -U 5 -r db-5.3.21.old/src/dbinc_auto/mp_ext.h db-5.3.21/src/dbinc_auto/mp_ext.h +--- db-5.3.21.old/src/dbinc_auto/mp_ext.h 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/dbinc_auto/mp_ext.h 2016-10-25 22:40:58.000000000 +0800 +@@ -14,10 +14,11 @@ + int __memp_failchk __P((ENV *)); + int __memp_bhwrite __P((DB_MPOOL *, DB_MPOOL_HASH *, MPOOLFILE *, BH *, int)); + int __memp_pgread __P((DB_MPOOLFILE *, BH *, int)); + int __memp_pg __P((DB_MPOOLFILE *, db_pgno_t, void *, int)); + int __memp_bhfree __P((DB_MPOOL *, REGINFO *, MPOOLFILE *, DB_MPOOL_HASH *, BH *, u_int32_t)); ++void __memp_bh_clear_dirty __P((ENV*, DB_MPOOL_HASH *, BH *)); + int __memp_fget_pp __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *)); + int __memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, DB_THREAD_INFO *, DB_TXN *, u_int32_t, void *)); + int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); + int __memp_fcreate __P((ENV *, DB_MPOOLFILE **)); + int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t)); +@@ -38,10 +39,11 @@ + int __memp_fopen __P((DB_MPOOLFILE *, MPOOLFILE *, const char *, const char **, u_int32_t, int, size_t)); + int __memp_fclose_pp __P((DB_MPOOLFILE *, u_int32_t)); + int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t)); + int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *, int)); + int __memp_inmemlist __P((ENV *, char ***, int *)); ++void __memp_mf_mark_dead __P((DB_MPOOL *, MPOOLFILE *, int*)); + int __memp_fput_pp __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t)); + int __memp_fput __P((DB_MPOOLFILE *, DB_THREAD_INFO *, void *, DB_CACHE_PRIORITY)); + int __memp_unpin_buffers __P((ENV *, DB_THREAD_INFO *)); + int __memp_dirty __P((DB_MPOOLFILE *, void *, DB_THREAD_INFO *, DB_TXN *, DB_CACHE_PRIORITY, u_int32_t)); + int __memp_shared __P((DB_MPOOLFILE *, void *)); +@@ -96,10 +98,11 @@ + int __memp_fsync_pp __P((DB_MPOOLFILE *)); + int __memp_fsync __P((DB_MPOOLFILE *)); + int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_FH **)); + int __memp_sync_int __P((ENV *, DB_MPOOLFILE *, u_int32_t, u_int32_t, u_int32_t *, int *)); + int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *, int)); ++int __memp_purge_dead_files __P((ENV *)); + int __memp_trickle_pp __P((DB_ENV *, int, int *)); + + #if defined(__cplusplus) + } + #endif +diff -U 5 -r db-5.3.21.old/src/mp/mp_bh.c db-5.3.21/src/mp/mp_bh.c +--- db-5.3.21.old/src/mp/mp_bh.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_bh.c 2016-10-25 17:09:35.000000000 +0800 +@@ -472,15 +472,12 @@ + * a shared latch. + */ + if (F_ISSET(bhp, BH_DIRTY | BH_TRASH)) { + MUTEX_LOCK(env, hp->mtx_hash); + DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc)); +- if (ret == 0 && F_ISSET(bhp, BH_DIRTY)) { +- F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); +- DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0); +- atomic_dec(env, &hp->hash_page_dirty); +- } ++ if (ret == 0) ++ __memp_bh_clear_dirty(env, hp, bhp); + + /* put the page back if necessary. */ + if ((ret != 0 || BH_REFCOUNT(bhp) > 1) && + F_ISSET(bhp, BH_TRASH)) { + ret = __memp_pg(dbmfp, bhp->pgno, bhp->buf, 1); +@@ -686,5 +683,31 @@ + } else + MUTEX_UNLOCK(env, mfp->mutex); + + return (ret); + } ++ ++/* ++ * __memp_bh_clear_dirty -- ++ * Clear the dirty flag of of a buffer. Calls on the same buffer must be ++ * serialized to get the accounting correct. This can be achieved by ++ * acquiring an exclusive lock on the buffer, a shared lock on the ++ * buffer plus an exclusive lock on the hash bucket, or some other ++ * mechanism that guarantees single-thread access to the entire region ++ * (e.g. during __memp_region_bhfree()). ++ * ++ * PUBLIC: void __memp_bh_clear_dirty __P((ENV*, DB_MPOOL_HASH *, BH *)); ++ */ ++void ++__memp_bh_clear_dirty(env, hp, bhp) ++ ENV *env; ++ DB_MPOOL_HASH *hp; ++ BH *bhp; ++{ ++ COMPQUIET(env, env); ++ if (F_ISSET(bhp, BH_DIRTY)) { ++ F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); ++ DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0); ++ (void)atomic_dec(env, &hp->hash_page_dirty); ++ } ++} ++ +diff -U 5 -r db-5.3.21.old/src/mp/mp_fget.c db-5.3.21/src/mp/mp_fget.c +--- db-5.3.21.old/src/mp/mp_fget.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_fget.c 2016-10-25 17:11:08.000000000 +0800 +@@ -437,16 +437,11 @@ + * complain and get out. + */ + if (flags == DB_MPOOL_FREE) { + freebuf: MUTEX_LOCK(env, hp->mtx_hash); + h_locked = 1; +- if (F_ISSET(bhp, BH_DIRTY)) { +- F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); +- DB_ASSERT(env, +- atomic_read(&hp->hash_page_dirty) > 0); +- atomic_dec(env, &hp->hash_page_dirty); +- } ++ __memp_bh_clear_dirty(env, hp, bhp); + + /* + * If the buffer we found is already freed, we're done. + * If the ref count is not 1 then someone may be + * peeking at the buffer. We cannot free it until they +diff -U 5 -r db-5.3.21.old/src/mp/mp_fopen.c db-5.3.21/src/mp/mp_fopen.c +--- db-5.3.21.old/src/mp/mp_fopen.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_fopen.c 2016-10-25 22:31:05.000000000 +0800 +@@ -12,10 +12,11 @@ + #include "dbinc/log.h" + #include "dbinc/mp.h" + #include "dbinc/db_page.h" + #include "dbinc/hash.h" + ++static int __memp_count_dead_mutex __P((DB_MPOOL *, u_int32_t *)); + static int __memp_mpf_alloc __P((DB_MPOOL *, + DB_MPOOLFILE *, const char *, u_int32_t, u_int32_t, MPOOLFILE **)); + static int __memp_mpf_find __P((ENV *, + DB_MPOOLFILE *, DB_MPOOL_HASH *, const char *, u_int32_t, MPOOLFILE **)); + +@@ -709,11 +710,15 @@ + * We should be able to set mfp to NULL and break out of the + * loop, but I like the idea of checking all the entries. + */ + if (LF_ISSET(DB_TRUNCATE)) { + MUTEX_LOCK(env, mfp->mutex); +- mfp->deadfile = 1; ++ /* ++ * We cannot purge dead files here, because the caller ++ * is holding the mutex of the hash bucket of mfp. ++ */ ++ __memp_mf_mark_dead(dbmp, mfp, NULL); + MUTEX_UNLOCK(env, mfp->mutex); + continue; + } + + /* +@@ -907,14 +912,15 @@ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + char *rpath; + u_int32_t ref; +- int deleted, ret, t_ret; ++ int deleted, purge_dead, ret, t_ret; + + env = dbmfp->env; + dbmp = env->mp_handle; ++ purge_dead = 0; + ret = 0; + + /* + * Remove the DB_MPOOLFILE from the process' list. + * +@@ -1004,11 +1010,11 @@ + } + DB_ASSERT(env, mfp->neutral_cnt < mfp->mpf_cnt); + if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) { + if (LF_ISSET(DB_MPOOL_DISCARD) || + F_ISSET(mfp, MP_TEMP) || mfp->unlink_on_close) { +- mfp->deadfile = 1; ++ __memp_mf_mark_dead(dbmp, mfp, &purge_dead); + } + if (mfp->unlink_on_close) { + if ((t_ret = __db_appname(dbmp->env, DB_APP_DATA, + R_ADDR(dbmp->reginfo, mfp->path_off), NULL, + &rpath)) != 0 && ret == 0) +@@ -1037,10 +1043,12 @@ + deleted = 1; + } + } + if (!deleted && !LF_ISSET(DB_MPOOL_NOLOCK)) + MUTEX_UNLOCK(env, mfp->mutex); ++ if (purge_dead) ++ (void)__memp_purge_dead_files(env); + + done: /* Discard the DB_MPOOLFILE structure. */ + if (dbmfp->pgcookie != NULL) { + __os_free(env, dbmfp->pgcookie->data); + __os_free(env, dbmfp->pgcookie); +@@ -1091,11 +1099,11 @@ + /* + * We have to release the MPOOLFILE mutex before acquiring the region + * mutex so we don't deadlock. Make sure nobody ever looks at this + * structure again. + */ +- mfp->deadfile = 1; ++ __memp_mf_mark_dead(dbmp, mfp, NULL); + + /* Discard the mutex we're holding and return it too the pool. */ + MUTEX_UNLOCK(env, mfp->mutex); + if ((t_ret = __mutex_free(env, &mfp->mutex)) != 0 && ret == 0) + ret = t_ret; +@@ -1216,5 +1224,106 @@ + /* Make sure we don't return any garbage. */ + *cntp = 0; + *namesp = NULL; + return (ret); + } ++ ++/* ++ * __memp_mf_mark_dead -- ++ * Mark an MPOOLFILE as dead because its contents are no longer necessary. ++ * This happens when removing, truncation, or closing an unnamed in-memory ++ * database. Return, in the purgep parameter, whether the caller should ++ * call __memp_purge_dead_files() after the lock on mfp is released. The ++ * caller must hold an exclusive lock on the mfp handle. ++ * ++ * PUBLIC: void __memp_mf_mark_dead __P((DB_MPOOL *, MPOOLFILE *, int*)); ++ */ ++void ++__memp_mf_mark_dead(dbmp, mfp, purgep) ++ DB_MPOOL *dbmp; ++ MPOOLFILE *mfp; ++ int *purgep; ++{ ++ ENV *env; ++#ifdef HAVE_MUTEX_SUPPORT ++ REGINFO *infop; ++ DB_MUTEXREGION *mtxregion; ++ u_int32_t mutex_max, mutex_inuse, dead_mutex; ++#endif ++ ++ if (purgep != NULL) ++ *purgep = 0; ++ ++ env = dbmp->env; ++ ++#ifdef HAVE_MUTEX_SUPPORT ++ MUTEX_REQUIRED(env, mfp->mutex); ++ ++ if (MUTEX_ON(env) && mfp->deadfile == 0) { ++ infop = &env->mutex_handle->reginfo; ++ mtxregion = infop->primary; ++ ++ mutex_inuse = mtxregion->stat.st_mutex_inuse; ++ if ((mutex_max = env->dbenv->mutex_max) == 0) ++ mutex_max = infop->rp->max / mtxregion->mutex_size; ++ ++ /* ++ * Purging dead pages requires a full scan of the entire cache ++ * buffer, so it is a slow operation. We only want to do it ++ * when it is necessary and provides enough benefits. Below is ++ * a simple heuristic that determines when to purge all dead ++ * pages. ++ */ ++ if (purgep != NULL && mutex_inuse > mutex_max - 200) { ++ /* ++ * If the mutex region is almost full and there are ++ * many mutexes held by dead files, purge dead files. ++ */ ++ (void)__memp_count_dead_mutex(dbmp, &dead_mutex); ++ dead_mutex += mfp->block_cnt + 1; ++ ++ if (dead_mutex > mutex_inuse / 20) ++ *purgep = 1; ++ } ++ } ++#endif ++ ++ mfp->deadfile = 1; ++} ++ ++/* ++ * __memp_count_dead_mutex -- ++ * Estimate the number of mutexes held by dead files. ++ */ ++static int ++__memp_count_dead_mutex(dbmp, dead_mutex) ++ DB_MPOOL *dbmp; ++ u_int32_t *dead_mutex; ++{ ++ ENV *env; ++ DB_MPOOL_HASH *hp; ++ MPOOL *mp; ++ MPOOLFILE *mfp; ++ u_int32_t mutex_per_file; ++ int busy, i; ++ ++ env = dbmp->env; ++ *dead_mutex = 0; ++ mutex_per_file = 1; ++#ifndef HAVE_ATOMICFILEREAD ++ mutex_per_file = 2; ++#endif ++ mp = dbmp->reginfo[0].primary; ++ hp = R_ADDR(dbmp->reginfo, mp->ftab); ++ for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) { ++ busy = MUTEX_TRYLOCK(env, hp->mtx_hash); ++ if (busy) ++ continue; ++ SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) { ++ if (mfp->deadfile) ++ *dead_mutex += mfp->block_cnt + mutex_per_file; ++ } ++ MUTEX_UNLOCK(env, hp->mtx_hash); ++ } ++ ++ return (0); ++} +diff -U 5 -r db-5.3.21.old/src/mp/mp_method.c db-5.3.21/src/mp/mp_method.c +--- db-5.3.21.old/src/mp/mp_method.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_method.c 2016-10-25 17:22:23.000000000 +0800 +@@ -638,11 +638,11 @@ + DB_MPOOL_HASH *hp, *nhp; + MPOOL *mp; + MPOOLFILE *mfp; + roff_t newname_off; + u_int32_t bucket; +- int locked, ret; ++ int locked, purge_dead, ret; + size_t nlen; + void *p; + + #undef op_is_remove + #define op_is_remove (newname == NULL) +@@ -655,10 +655,11 @@ + dbmp = NULL; + mfp = NULL; + nhp = NULL; + p = NULL; + locked = ret = 0; ++ purge_dead = 0; + + if (!MPOOL_ON(env)) + goto fsop; + + dbmp = env->mp_handle; +@@ -747,11 +748,11 @@ + * they do not get reclaimed as long as they exist. Since we + * are now deleting the database, we need to dec that count. + */ + if (mfp->no_backing_file) + mfp->mpf_cnt--; +- mfp->deadfile = 1; ++ __memp_mf_mark_dead(dbmp, mfp, &purge_dead); + MUTEX_UNLOCK(env, mfp->mutex); + } else { + /* + * Else, it's a rename. We've allocated memory for the new + * name. Swap it with the old one. If it's in memory we +@@ -806,10 +807,16 @@ + if (locked == 1) { + MUTEX_UNLOCK(env, hp->mtx_hash); + if (nhp != NULL && nhp != hp) + MUTEX_UNLOCK(env, nhp->mtx_hash); + } ++ /* ++ * __memp_purge_dead_files() must be called when the hash bucket is ++ * unlocked. ++ */ ++ if (purge_dead) ++ (void)__memp_purge_dead_files(env); + return (ret); + } + + /* + * __memp_ftruncate __ +diff -U 5 -r db-5.3.21.old/src/mp/mp_sync.c db-5.3.21/src/mp/mp_sync.c +--- db-5.3.21.old/src/mp/mp_sync.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_sync.c 2016-10-25 17:26:58.000000000 +0800 +@@ -24,10 +24,11 @@ + static int __bhcmp __P((const void *, const void *)); + static int __memp_close_flush_files __P((ENV *, int)); + static int __memp_sync_files __P((ENV *)); + static int __memp_sync_file __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); ++static inline void __update_err_ret(int, int*); + + /* + * __memp_walk_files -- + * PUBLIC: int __memp_walk_files __P((ENV *, MPOOL *, + * PUBLIC: int (*) __P((ENV *, MPOOLFILE *, void *, +@@ -961,5 +962,125 @@ + return (-1); + if (bhp1->track_pgno > bhp2->track_pgno) + return (1); + return (0); + } ++ ++/* ++ * __memp_purge_dead_files -- ++ * Remove all dead files and their buffers from the mpool. The caller ++ * cannot hold any lock on the dead MPOOLFILE handles, their buffers ++ * or their hash buckets. ++ * ++ * PUBLIC: int __memp_purge_dead_files __P((ENV *)); ++ */ ++int ++__memp_purge_dead_files(env) ++ ENV *env; ++{ ++ BH *bhp; ++ DB_MPOOL *dbmp; ++ DB_MPOOL_HASH *hp, *hp_end; ++ REGINFO *infop; ++ MPOOL *c_mp, *mp; ++ MPOOLFILE *mfp; ++ u_int32_t i_cache; ++ int ret, t_ret, h_lock; ++ ++ if (!MPOOL_ON(env)) ++ return (0); ++ ++ dbmp = env->mp_handle; ++ mp = dbmp->reginfo[0].primary; ++ ret = t_ret = h_lock = 0; ++ ++ /* ++ * Walk each cache's list of buffers and free all buffers whose ++ * MPOOLFILE is marked as dead. ++ */ ++ for (i_cache = 0; i_cache < mp->nreg; i_cache++) { ++ infop = &dbmp->reginfo[i_cache]; ++ c_mp = infop->primary; ++ ++ hp = R_ADDR(infop, c_mp->htab); ++ hp_end = &hp[c_mp->htab_buckets]; ++ for (; hp < hp_end; hp++) { ++ /* Skip empty buckets. */ ++ if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) ++ continue; ++ ++ /* ++ * Search for a dead buffer. Other places that call ++ * __memp_bhfree() acquire the buffer lock before the ++ * hash bucket lock. Even though we acquire the two ++ * locks in reverse order, we cannot deadlock here ++ * because we don't block waiting for the locks. ++ */ ++ t_ret = MUTEX_TRYLOCK(env, hp->mtx_hash); ++ if (t_ret != 0) { ++ __update_err_ret(t_ret, &ret); ++ continue; ++ } ++ h_lock = 1; ++ SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) { ++ /* Skip buffers that are being used. */ ++ if (BH_REFCOUNT(bhp) > 0) ++ continue; ++ ++ mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); ++ if (!mfp->deadfile) ++ continue; ++ ++ /* Found a dead buffer. Prepare to free it. */ ++ t_ret = MUTEX_TRYLOCK(env, bhp->mtx_buf); ++ if (t_ret != 0) { ++ __update_err_ret(t_ret, &ret); ++ continue; ++ } ++ ++ DB_ASSERT(env, (!F_ISSET(bhp, BH_EXCLUSIVE) && ++ BH_REFCOUNT(bhp) == 0)); ++ F_SET(bhp, BH_EXCLUSIVE); ++ (void)atomic_inc(env, &bhp->ref); ++ ++ __memp_bh_clear_dirty(env, hp, bhp); ++ ++ /* ++ * Free the buffer. The buffer and hash bucket ++ * are unlocked by __memp_bhfree. ++ */ ++ if ((t_ret = __memp_bhfree(dbmp, infop, mfp, ++ hp, bhp, BH_FREE_FREEMEM)) == 0) ++ /* ++ * Decrement hp, so the next turn will ++ * search the same bucket again. ++ */ ++ hp--; ++ else ++ __update_err_ret(t_ret, &ret); ++ ++ /* ++ * The hash bucket is unlocked, we need to ++ * start over again. ++ */ ++ h_lock = 0; ++ break; ++ } ++ ++ if (h_lock) { ++ MUTEX_UNLOCK(env, hp->mtx_hash); ++ h_lock = 0; ++ } ++ } ++ } ++ ++ return (ret); ++} ++ ++static inline void ++__update_err_ret(t_ret, retp) ++ int t_ret; ++ int *retp; ++{ ++ if (t_ret != 0 && t_ret != DB_LOCK_NOTGRANTED && *retp == 0) ++ *retp = t_ret; ++} +diff -U 5 -r db-5.3.21.old/src/mp/mp_trickle.c db-5.3.21/src/mp/mp_trickle.c +--- db-5.3.21.old/src/mp/mp_trickle.c 2012-05-12 01:57:53.000000000 +0800 ++++ db-5.3.21/src/mp/mp_trickle.c 2016-10-25 17:27:57.000000000 +0800 +@@ -65,10 +65,14 @@ + "DB_ENV->memp_trickle: %d: percent must be between 1 and 100", + "%d"), pct); + return (EINVAL); + } + ++ /* First we purge all dead files and their buffers. */ ++ if ((ret = __memp_purge_dead_files(env)) != 0) ++ return (ret); ++ + /* + * Loop through the caches counting total/dirty buffers. + * + * XXX + * Using hash_page_dirty is our only choice at the moment, but it's not +diff -U 5 -r db-5.3.21.old/src/mutex/mut_region.c db-5.3.21/src/mutex/mut_region.c +--- db-5.3.21.old/src/mutex/mut_region.c 2012-05-12 01:57:54.000000000 +0800 ++++ db-5.3.21/src/mutex/mut_region.c 2016-10-25 17:34:22.000000000 +0800 +@@ -15,11 +15,11 @@ + #include "dbinc/txn.h" + + static db_size_t __mutex_align_size __P((ENV *)); + static int __mutex_region_init __P((ENV *, DB_MUTEXMGR *)); + static size_t __mutex_region_size __P((ENV *)); +-static size_t __mutex_region_max __P((ENV *)); ++static size_t __mutex_region_max __P((ENV *, u_int32_t)); + + /* + * __mutex_open -- + * Open a mutex region. + * +@@ -32,11 +32,11 @@ + { + DB_ENV *dbenv; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + size_t size; +- u_int32_t cpu_count; ++ u_int32_t cpu_count, mutex_needed; + int ret; + #ifndef HAVE_ATOMIC_SUPPORT + u_int i; + #endif + +@@ -59,23 +59,24 @@ + cpu_count : cpu_count * MUTEX_SPINS_PER_PROCESSOR)) != 0) + return (ret); + } + + /* +- * If the user didn't set an absolute value on the number of mutexes +- * we'll need, figure it out. We're conservative in our allocation, +- * we need mutexes for DB handles, group-commit queues and other things +- * applications allocate at run-time. The application may have kicked +- * up our count to allocate its own mutexes, add that in. ++ * Figure out the number of mutexes we'll need. We're conservative in ++ * our allocation, we need mutexes for DB handles, group-commit queues ++ * and other things applications allocate at run-time. The application ++ * may have kicked up our count to allocate its own mutexes, add that ++ * in. + */ ++ mutex_needed = ++ __lock_region_mutex_count(env) + ++ __log_region_mutex_count(env) + ++ __memp_region_mutex_count(env) + ++ __txn_region_mutex_count(env); + if (dbenv->mutex_cnt == 0 && + F_ISSET(env, ENV_PRIVATE | ENV_THREAD) != ENV_PRIVATE) +- dbenv->mutex_cnt = +- __lock_region_mutex_count(env) + +- __log_region_mutex_count(env) + +- __memp_region_mutex_count(env) + +- __txn_region_mutex_count(env); ++ dbenv->mutex_cnt = mutex_needed; + + if (dbenv->mutex_max != 0 && dbenv->mutex_cnt > dbenv->mutex_max) + dbenv->mutex_cnt = dbenv->mutex_max; + + /* Create/initialize the mutex manager structure. */ +@@ -88,12 +89,12 @@ + mtxmgr->reginfo.id = INVALID_REGION_ID; + mtxmgr->reginfo.flags = REGION_JOIN_OK; + size = __mutex_region_size(env); + if (create_ok) + F_SET(&mtxmgr->reginfo, REGION_CREATE_OK); +- if ((ret = __env_region_attach(env, +- &mtxmgr->reginfo, size, size + __mutex_region_max(env))) != 0) ++ if ((ret = __env_region_attach(env, &mtxmgr->reginfo, ++ size, size + __mutex_region_max(env, mutex_needed))) != 0) + goto err; + + /* If we created the region, initialize it. */ + if (F_ISSET(&mtxmgr->reginfo, REGION_CREATE)) + if ((ret = __mutex_region_init(env, mtxmgr)) != 0) +@@ -350,44 +351,62 @@ + + dbenv = env->dbenv; + + s = sizeof(DB_MUTEXMGR) + 1024; + +- /* We discard one mutex for the OOB slot. */ ++ /* ++ * We discard one mutex for the OOB slot. Make sure mutex_cnt doesn't ++ * overflow. ++ */ + s += __env_alloc_size( +- (dbenv->mutex_cnt + 1) *__mutex_align_size(env)); ++ (dbenv->mutex_cnt + (dbenv->mutex_cnt == UINT32_MAX ? 0 : 1)) * ++ __mutex_align_size(env)); + + return (s); + } + + /* + * __mutex_region_max -- + * Return the amount of space needed to reach the maximum size. + */ + static size_t +-__mutex_region_max(env) ++__mutex_region_max(env, mutex_needed) + ENV *env; ++ u_int32_t mutex_needed; + { + DB_ENV *dbenv; +- u_int32_t max; ++ u_int32_t max, mutex_cnt; + + dbenv = env->dbenv; ++ mutex_cnt = dbenv->mutex_cnt; + +- if ((max = dbenv->mutex_max) == 0) { ++ /* ++ * We want to limit the region size to accommodate at most UINT32_MAX ++ * mutexes. If mutex_cnt is UINT32_MAX, no more space is allowed. ++ */ ++ if ((max = dbenv->mutex_max) == 0 && mutex_cnt != UINT32_MAX) + if (F_ISSET(env, ENV_PRIVATE | ENV_THREAD) == ENV_PRIVATE) +- max = dbenv->mutex_inc + 1; +- else ++ if (dbenv->mutex_inc + 1 < UINT32_MAX - mutex_cnt) ++ max = dbenv->mutex_inc + 1 + mutex_cnt; ++ else ++ max = UINT32_MAX; ++ else { + max = __lock_region_mutex_max(env) + + __txn_region_mutex_max(env) + + __log_region_mutex_max(env) + + dbenv->mutex_inc + 100; +- } else if (max <= dbenv->mutex_cnt) ++ if (max < UINT32_MAX - mutex_needed) ++ max += mutex_needed; ++ else ++ max = UINT32_MAX; ++ } ++ ++ if (max <= mutex_cnt) + return (0); + else +- max -= dbenv->mutex_cnt; +- +- return ( __env_alloc_size(max * __mutex_align_size(env))); ++ return (__env_alloc_size( ++ (max - mutex_cnt) * __mutex_align_size(env))); + } + + #ifdef HAVE_MUTEX_SYSTEM_RESOURCES + /* + * __mutex_resource_return + diff --git a/SOURCES/db-5.3.28-atomic_compare_exchange.patch b/SOURCES/db-5.3.28-atomic_compare_exchange.patch new file mode 100644 index 0000000..4eab02c --- /dev/null +++ b/SOURCES/db-5.3.28-atomic_compare_exchange.patch @@ -0,0 +1,20 @@ +--- db-5.3.28/src/dbinc/atomic.h.old 2018-05-23 09:20:04.216914922 +0200 ++++ db-5.3.28/src/dbinc/atomic.h 2018-05-23 09:20:49.510057897 +0200 +@@ -144,7 +144,7 @@ + #define atomic_inc(env, p) __atomic_inc(p) + #define atomic_dec(env, p) __atomic_dec(p) + #define atomic_compare_exchange(env, p, o, n) \ +- __atomic_compare_exchange((p), (o), (n)) ++ __db_atomic_compare_exchange((p), (o), (n)) + static inline int __atomic_inc(db_atomic_t *p) + { + int temp; +@@ -176,7 +176,7 @@ + * http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html + * which configure could be changed to use. + */ +-static inline int __atomic_compare_exchange( ++static inline int __db_atomic_compare_exchange( + db_atomic_t *p, atomic_value_t oldval, atomic_value_t newval) + { + atomic_value_t was; diff --git a/SOURCES/db-5.3.28-condition-variable-ppc.patch b/SOURCES/db-5.3.28-condition-variable-ppc.patch new file mode 100644 index 0000000..0e9ef6b --- /dev/null +++ b/SOURCES/db-5.3.28-condition-variable-ppc.patch @@ -0,0 +1,135 @@ +diff -up db-5.3.28/src/dbinc_auto/int_def.in.pthreads_ppc db-5.3.28/src/dbinc_auto/int_def.in +--- db-5.3.28/src/dbinc_auto/int_def.in.pthreads_ppc 2017-06-26 15:06:09.282020804 +0200 ++++ db-5.3.28/src/dbinc_auto/int_def.in 2017-06-26 15:06:22.238771039 +0200 +@@ -1572,6 +1572,7 @@ + #define __os_strerror __os_strerror@DB_VERSION_UNIQUE_NAME@ + #define __os_posix_err __os_posix_err@DB_VERSION_UNIQUE_NAME@ + #define __os_fileid __os_fileid@DB_VERSION_UNIQUE_NAME@ ++#define __check_lock_fn __check_lock_fn@DB_VERSION_UNIQUE_NAME@ + #define __os_fdlock __os_fdlock@DB_VERSION_UNIQUE_NAME@ + #define __os_fsync __os_fsync@DB_VERSION_UNIQUE_NAME@ + #define __os_getenv __os_getenv@DB_VERSION_UNIQUE_NAME@ +diff -up db-5.3.28/src/dbinc_auto/os_ext.h.pthreads_ppc db-5.3.28/src/dbinc_auto/os_ext.h +--- db-5.3.28/src/dbinc_auto/os_ext.h.pthreads_ppc 2017-06-26 15:05:23.792897700 +0200 ++++ db-5.3.28/src/dbinc_auto/os_ext.h 2017-06-26 15:06:22.172772311 +0200 +@@ -41,6 +41,7 @@ void __os_set_errno __P((int)); + char *__os_strerror __P((int, char *, size_t)); + int __os_posix_err __P((int)); + int __os_fileid __P((ENV *, const char *, int, u_int8_t *)); ++int __check_lock_fn __P((char *, pid_t)); + int __os_fdlock __P((ENV *, DB_FH *, off_t, db_lockmode_t, int)); + int __os_fsync __P((ENV *, DB_FH *)); + int __os_getenv __P((ENV *, const char *, char **, size_t)); +diff -up db-5.3.28/src/env/env_region.c.pthreads_ppc db-5.3.28/src/env/env_region.c +--- db-5.3.28/src/env/env_region.c.pthreads_ppc 2017-06-26 15:04:40.805726365 +0200 ++++ db-5.3.28/src/env/env_region.c 2017-06-26 15:04:40.807726326 +0200 +@@ -305,14 +305,6 @@ user_map_functions: + goto creation; + } + +- /* We have an old environment but cannot rebuild it safely. */ +- if (ret == DB_OLD_VERSION) { +- __db_errx(env, DB_STR("1539", +- "Build signature doesn't match environment")); +- ret = DB_VERSION_MISMATCH; +- goto err; +- } +- + if (renv->majver != DB_VERSION_MAJOR || + renv->minver != DB_VERSION_MINOR) { + /* +@@ -337,6 +329,20 @@ user_map_functions: + goto err; + } + ++ /* ++ * We have an old environment but cannot rebuild it safely. ++ * The environment might still be readable by the current process ++ * (only the libpthread timestamp changed) if this process is the one ++ * that is holding the lock on the region file as we can be sure ++ * the environment did not get rebuilt under our feet. ++ */ ++ if (ret == DB_OLD_VERSION && __check_lock_fn(env->lockfhp->name, getpid()) ) { ++ __db_errx(env, DB_STR("1539", ++ "Build signature doesn't match environment")); ++ ret = DB_VERSION_MISMATCH; ++ goto err; ++ } ++ + /* + * Check if the environment has had a catastrophic failure. + * +diff -up db-5.3.28/src/os/os_flock.c.pthreads_ppc db-5.3.28/src/os/os_flock.c +--- db-5.3.28/src/os/os_flock.c.pthreads_ppc 2017-06-26 15:04:40.806726346 +0200 ++++ db-5.3.28/src/os/os_flock.c 2017-06-26 15:04:40.807726326 +0200 +@@ -15,6 +15,70 @@ static int __os_filelocking_notsup __P(( + #endif + + /* ++ * __check_lock_fn -- ++ * Parse /proc/locks to see if the file described by 'fn' is locked. ++ * Additionally (if 'pid' is not 0) check if the process holding ++ * the lock has the same pid value as 'pid'. ++ * ++ * Returns 0 if a lock on fn is found, 1 if it is not found and -1 on error. ++ * PUBLIC: int __check_lock_fn __P((char *, pid_t)); ++ */ ++ ++int __check_lock_fn(fn, pid) ++ char *fn; ++ pid_t pid; ++{ ++ FILE* fp; ++ char buffer[PATH_MAX]; ++ char *token; ++ int i, inode; ++ struct stat st; ++ pid_t lpid = 0; ++ ++ if (!fn) ++ return -1; ++ ++ fp = fopen("/proc/locks", "r"); ++ if (!fp) ++ return -1; ++ ++ /* Get the file's inode */ ++ if (stat(fn, &st)) { ++ fclose(fp); ++ return -1; ++ } ++ ++ while (fgets(buffer, sizeof(buffer), fp)) ++ for (token = strtok(buffer, " "), i = 0; token; token = strtok(NULL, " "), i++) { ++ /* Do not parse any other fields */ ++ if (i > 5) ++ break; ++ /* Save the PID */ ++ if (i == 4) ++ lpid = atoi(token); ++ /* Check the inode */ ++ else if (i == 5) { ++ inode = 0; ++ sscanf(token, "%*02x:%*02x:%d", &inode); ++ /* Not the inode we are looking for */ ++ if (inode != st.st_ino) ++ continue; ++ /* ++ * We have the correct file. ++ * We are either looking for a specific process or we do not care at all. ++ */ ++ if (!pid || lpid == pid) { ++ fclose(fp); ++ return 0; ++ } ++ /* Not the lock we are looking for */ ++ } ++ } ++ fclose(fp); ++ return 1; ++} ++ ++/* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + * diff --git a/SOURCES/db-5.3.28-condition_variable.patch b/SOURCES/db-5.3.28-condition_variable.patch new file mode 100644 index 0000000..ca947e6 --- /dev/null +++ b/SOURCES/db-5.3.28-condition_variable.patch @@ -0,0 +1,759 @@ +diff -up db-5.3.28/dist/android/android_config.in.pthreads db-5.3.28/dist/android/android_config.in +--- db-5.3.28/dist/android/android_config.in.pthreads 2013-09-09 17:35:02.000000000 +0200 ++++ db-5.3.28/dist/android/android_config.in 2017-06-13 11:15:15.323215161 +0200 +@@ -123,6 +123,9 @@ + /* Define to 1 if allocated filesystem blocks are not zeroed. */ + /* #undef HAVE_FILESYSTEM_NOTZERO */ + ++/* Define to 1 if you have the `flock' function. */ ++#undef HAVE_FLOCK ++ + /* Define to 1 if you have the `fopen' function. */ + #define HAVE_FOPEN 1 + +diff -up db-5.3.28/dist/config.hin.pthreads db-5.3.28/dist/config.hin +--- db-5.3.28/dist/config.hin.pthreads 2013-09-09 17:35:02.000000000 +0200 ++++ db-5.3.28/dist/config.hin 2017-06-13 11:15:15.000000000 +0200 +@@ -92,6 +92,9 @@ + /* Define to 1 if you have the header file. */ + #undef HAVE_DLFCN_H + ++/* Define to 1 if you have the `dl_iterate_phdr' function. */ ++#undef HAVE_DL_ITERATE_PHDR ++ + /* Define to 1 to use dtrace for performance monitoring. */ + #undef HAVE_DTRACE + +@@ -125,6 +128,9 @@ + /* Define to 1 if allocated filesystem blocks are not zeroed. */ + #undef HAVE_FILESYSTEM_NOTZERO + ++/* Define to 1 if you have the `flock' function. */ ++#undef HAVE_FLOCK ++ + /* Define to 1 if you have the `fopen' function. */ + #undef HAVE_FOPEN + +@@ -360,6 +366,9 @@ + /* Define to 1 if you have the `pstat_getdynamic' function. */ + #undef HAVE_PSTAT_GETDYNAMIC + ++/* Define to 1 if you have dl_iterate_phdr and use pthread-based mutexes. */ ++#undef HAVE_PTHREADS_TIMESTAMP ++ + /* Define to 1 if it is OK to initialize an already initialized + pthread_cond_t. */ + #undef HAVE_PTHREAD_COND_REINIT_OKAY +@@ -620,6 +629,11 @@ + /* Define to 1 to mask harmless uninitialized memory read/writes. */ + #undef UMRW + ++/* Enable large inode numbers on Mac OS X 10.5. */ ++#ifndef _DARWIN_USE_64_BIT_INODE ++# define _DARWIN_USE_64_BIT_INODE 1 ++#endif ++ + /* Number of bits in a file offset, on hosts where this is settable. */ + #undef _FILE_OFFSET_BITS + +diff -up db-5.3.28/dist/configure.ac.pthreads db-5.3.28/dist/configure.ac +--- db-5.3.28/dist/configure.ac.pthreads 2017-06-13 11:15:15.309215434 +0200 ++++ db-5.3.28/dist/configure.ac 2017-06-13 11:15:15.323215161 +0200 +@@ -698,7 +698,7 @@ AC_REPLACE_FUNCS(\ + # Check for system functions we optionally use. + AC_CHECK_FUNCS(\ + _fstati64 backtrace backtrace_symbols directio fchmod fclose\ +- fcntl fdatasync fgetc fgets fopen fwrite getgid\ ++ fcntl fdatasync fgetc fgets flock fopen fwrite getgid\ + getrusage getuid hstrerror mprotect pstat_getdynamic\ + pthread_self pthread_yield random sched_yield select setgid setuid\ + sigaction snprintf stat sysconf vsnprintf yield) +@@ -1042,6 +1042,34 @@ if test "$db_cv_localization" = "yes"; t + [Define to 1 if you have localization function to support globalization.]) + fi + ++# Check for dl_iterate_phdr; do the test explicitly instead of using ++# AC_CHECK_FUNCS because isn't a standard include file. ++AC_CACHE_CHECK([for dl_iterate_phdr], db_cv_dl_iterate_phdr, [ ++AC_TRY_LINK([ ++#include ++#include ], [ ++ dl_iterate_phdr(0, 0); ++], [db_cv_dl_iterate_phdr=yes], [db_cv_dl_iterate_phdr=no])]) ++if test "$db_cv_dl_iterate_phdr" = "yes"; then ++ AC_DEFINE(HAVE_DL_ITERATE_PHDR) ++ AH_TEMPLATE(HAVE_DL_ITERATE_PHDR, ++ [Define to 1 if you have the `dl_iterate_phdr' function.]) ++fi ++ ++# If we are using pthread mutex or condition variables, and dl_iterate_phdr() is ++# available, then we try to detect when libpthread is updated -- which can ++# render existing environment invalid. DB_ENV->open() tries to rebuild such ++# environments when they are idle. ++case "$db_cv_mutex" in ++ *pthreads*) ++ if test "$db_cv_dl_iterate_phdr" = "yes" ; then ++ AC_DEFINE(HAVE_PTHREADS_TIMESTAMP) ++ AH_TEMPLATE(HAVE_PTHREADS_TIMESTAMP, ++ [Define to 1 if you have dl_iterate_phdr and use pthread-based mutexes.]) ++ fi ++ ;; ++esac ++ + # We need to add the additional object files into the Makefile with the correct + # suffix. We can't use $LTLIBOBJS itself, because that variable has $U encoded + # in it for automake, and that's not what we want. See SR #7227 for additional +diff -up db-5.3.28/src/db/db_meta.c.pthreads db-5.3.28/src/db/db_meta.c +--- db-5.3.28/src/db/db_meta.c.pthreads 2013-09-09 17:35:07.000000000 +0200 ++++ db-5.3.28/src/db/db_meta.c 2017-06-13 11:15:15.323215161 +0200 +@@ -1330,8 +1330,9 @@ __db_haslock(env, locker, dbmfp, pgno, m + } + /* + * __db_has_pagelock -- +- * Determine if this locker holds a particular page lock. +- * Returns 0 if lock is held, non-zero otherwise. ++ * Determine if this locker holds a particular page lock, and return an ++ * error if it is missing a page lock that it should have. ++ * Otherwise (TDS with the page locked, or DS or CDS) return 0. + * + * PUBLIC: #ifdef DIAGNOSTIC + * PUBLIC: int __db_has_pagelock __P((ENV *, DB_LOCKER *, +@@ -1348,6 +1349,9 @@ __db_has_pagelock(env, locker, dbmfp, pa + { + int ret; + ++ if (!FLD_ISSET(env->open_flags, DB_INIT_TXN)) ++ return (0); ++ + switch (pagep->type) { + case P_OVERFLOW: + case P_INVALID: +diff -up db-5.3.28/src/dbinc_auto/int_def.in.pthreads db-5.3.28/src/dbinc_auto/int_def.in +--- db-5.3.28/src/dbinc_auto/int_def.in.pthreads 2017-06-13 11:15:15.317215278 +0200 ++++ db-5.3.28/src/dbinc_auto/int_def.in 2017-06-13 11:15:15.324215141 +0200 +@@ -1545,6 +1545,7 @@ + #if defined(HAVE_REPLICATION_THREADS) + #define __os_freeaddrinfo __os_freeaddrinfo@DB_VERSION_UNIQUE_NAME@ + #endif ++#define __os_pthreads_timestamp __os_pthreads_timestamp@DB_VERSION_UNIQUE_NAME@ + #define __os_umalloc __os_umalloc@DB_VERSION_UNIQUE_NAME@ + #define __os_urealloc __os_urealloc@DB_VERSION_UNIQUE_NAME@ + #define __os_ufree __os_ufree@DB_VERSION_UNIQUE_NAME@ +diff -up db-5.3.28/src/dbinc_auto/os_ext.h.pthreads db-5.3.28/src/dbinc_auto/os_ext.h +--- db-5.3.28/src/dbinc_auto/os_ext.h.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/dbinc_auto/os_ext.h 2017-06-13 11:15:15.324215141 +0200 +@@ -14,6 +14,7 @@ int __os_getaddrinfo __P((ENV *, const c + #if defined(HAVE_REPLICATION_THREADS) + void __os_freeaddrinfo __P((ENV *, ADDRINFO *)); + #endif ++time_t __os_pthreads_timestamp __P((ENV *)); + int __os_umalloc __P((ENV *, size_t, void *)); + int __os_urealloc __P((ENV *, size_t, void *)); + void __os_ufree __P((ENV *, void *)); +@@ -40,7 +41,7 @@ void __os_set_errno __P((int)); + char *__os_strerror __P((int, char *, size_t)); + int __os_posix_err __P((int)); + int __os_fileid __P((ENV *, const char *, int, u_int8_t *)); +-int __os_fdlock __P((ENV *, DB_FH *, off_t, int, int)); ++int __os_fdlock __P((ENV *, DB_FH *, off_t, db_lockmode_t, int)); + int __os_fsync __P((ENV *, DB_FH *)); + int __os_getenv __P((ENV *, const char *, char **, size_t)); + int __os_openhandle __P((ENV *, const char *, int, int, DB_FH **)); +diff -up db-5.3.28/src/dbinc/region.h.pthreads db-5.3.28/src/dbinc/region.h +--- db-5.3.28/src/dbinc/region.h.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/dbinc/region.h 2017-06-13 11:15:15.324215141 +0200 +@@ -178,6 +178,16 @@ typedef struct __db_reg_env { /* SHARED + u_int32_t envid; /* Unique environment ID. */ + + u_int32_t signature; /* Structure signatures. */ ++#if defined(HAVE_PTHREADS_TIMESTAMP) && defined(HAVE_MUTEX_PTHREADS) ++ /* ++ * Updates to glibc/libpthread can change its pthreads implementation ++ * and invalidate on-disk environments, even without changing the ++ * version number. If using POSIX mutexes and a change in this ++ * timestamp is detecting when opening an environment with DB_CREATE, ++ * __env_attach recreates any existing on-disk environment. ++ */ ++ time_t pthreads_timestamp; ++#endif + + time_t timestamp; /* Creation time. */ + +diff -up db-5.3.28/src/env/env_open.c.pthreads db-5.3.28/src/env/env_open.c +--- db-5.3.28/src/env/env_open.c.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/env/env_open.c 2017-06-13 11:15:15.324215141 +0200 +@@ -1031,11 +1031,11 @@ __env_attach_regions(dbenv, flags, orig_ + goto err; + + /* +- * __env_attach will return the saved init_flags field, which contains ++ * __env_attach has returned the saved init_flags field, which contains + * the DB_INIT_* flags used when the environment was created. + * +- * We may be joining an environment -- reset our flags to match the +- * ones in the environment. ++ * We may be joining an existing environment -- reset our flags to match ++ * the ones in the environment. + */ + if (FLD_ISSET(init_flags, DB_INITENV_CDB)) + LF_SET(DB_INIT_CDB); +diff -up db-5.3.28/src/env/env_region.c.pthreads db-5.3.28/src/env/env_region.c +--- db-5.3.28/src/env/env_region.c.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/env/env_region.c 2017-06-13 11:16:02.159299222 +0200 +@@ -18,13 +18,49 @@ static int __env_des_get __P((ENV *, RE + static int __env_faultmem __P((ENV *, void *, size_t, int)); + static int __env_sys_attach __P((ENV *, REGINFO *, REGION *)); + static int __env_sys_detach __P((ENV *, REGINFO *, int)); ++static int __env_check_recreate __P((ENV *, REGENV *, u_int32_t)); + static void __env_des_destroy __P((ENV *, REGION *)); + static void __env_remove_file __P((ENV *)); + ++ ++/* ++ * If the system supports flock()-like file locking, then the primary region ++ * file __db.001 is exclusively locked during creation, and is read-locked while ++ * the environment is open. Most Unix-like systems have flock(), with the ++ * notable exception of Solaris. ++ * Note: fcntl cannot be used for this locking because of the unfortunate ++ * definition of its interaction with close(2). A process's fcntl locks are ++ * released whenever it closes any file descriptor for that file. So, if an ++ * environment is opened more than once, closing one of the DB_ENV handles would ++ * release the read lock that protects the other handle. ++ */ ++#ifdef HAVE_FLOCK ++#define ENV_PRIMARY_LOCK(env, lockmode, async) \ ++ ((env)->lockfhp == NULL ? 0 : \ ++ __os_fdlock((env), (env)->lockfhp, -1, lockmode, async)) ++#define ENV_PRIMARY_UNLOCK(env) \ ++ ((env)->lockfhp == NULL ? 0 : \ ++ __os_fdlock((env), (env)->lockfhp, -1, DB_LOCK_NG, 0)) ++#else ++#define ENV_PRIMARY_LOCK(env, lockmode, async) (0) ++#define ENV_PRIMARY_UNLOCK(env) (0) ++#endif ++ + /* + * __env_attach + * Join/create the environment + * ++ * Safely detecting and managing multiple processes' environment handles: ++ * BDB uses a shared or exclusive fcntl()-style lock on the first byte ++ * of the primary region file (__db.001) to detect whether other processes ++ * have the environment open, and to single-thread attempts to create the ++ * environment. If the open includes DB_CREATE, an exclusive lock is ++ * obtained during the open call. After the creation is finished, and ++ * anytime during a non-DB_CREATE env open, the process holds a shared ++ * lock. ++ * - single-thread creation of the environment ++ * - detect whether any other processes are currently attached to it. ++ * + * PUBLIC: int __env_attach __P((ENV *, u_int32_t *, int, int)); + */ + int +@@ -122,7 +158,11 @@ loop: renv = NULL; + if ((ret = __os_open( + env, infop->name, 0, DB_OSO_REGION, 0, &env->lockfhp)) != 0) + goto err; +- ++ /* Wait to get shared access to the primary region. */ ++ if ((ret = ENV_PRIMARY_LOCK(env, DB_LOCK_READ, 0)) != 0) { ++ __db_err(env, ret, "__env_attach: existing: shared lock error"); ++ goto err; ++ } + /* + * !!! + * The region may be in system memory not backed by the filesystem +@@ -218,11 +258,10 @@ loop: renv = NULL; + segid = ref.segid; + } + +-#ifndef HAVE_MUTEX_FCNTL ++#if !defined(HAVE_FCNTL) && !defined(HAVE_PTHREADS_TIMESTAMP) + /* +- * If we're not doing fcntl locking, we can close the file handle. We +- * no longer need it and the less contact between the buffer cache and +- * the VM, the better. ++ * Without fcntl-like support, we no longer need the file handle. Close ++ * it to limit the interaction between the buffer cache and the VM. + */ + (void)__os_closehandle(env, env->lockfhp); + env->lockfhp = NULL; +@@ -233,6 +272,8 @@ loop: renv = NULL; + tregion.size = (roff_t)size; + tregion.max = (roff_t)max; + tregion.segid = segid; ++ /* Attach to the existing primary region. */ ++ /* The leaking db.001 gets open inside of here, in __os_attach(). */ + if ((ret = __env_sys_attach(env, infop, &tregion)) != 0) + goto err; + +@@ -245,21 +286,48 @@ user_map_functions: + infop->primary = infop->addr; + infop->head = (u_int8_t *)infop->addr + sizeof(REGENV); + renv = infop->primary; ++ ret = __env_check_recreate(env, renv, signature); ++ ++ if (create_ok && ++ ret == DB_OLD_VERSION && ++ ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1) == 0) { ++ if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) ++ __db_msg(env, "Recreating idle environment"); ++ F_SET(infop, REGION_CREATE_OK); ++ ++ /* ++ * Detach from the environment region; we need to unmap it (and ++ * close any file handle) so that we don't leak memory or files. ++ */ ++ DB_ASSERT(env, infop->rp == NULL); ++ infop->rp = &tregion; ++ (void)__env_sys_detach(env, infop, 0); ++ goto creation; ++ } ++ ++ /* We have an old environment but cannot rebuild it safely. */ ++ if (ret == DB_OLD_VERSION) { ++ __db_errx(env, DB_STR("1539", ++ "Build signature doesn't match environment")); ++ ret = DB_VERSION_MISMATCH; ++ goto err; ++ } + +- /* +- * Make sure the region matches our build. Special case a region +- * that's all nul bytes, just treat it like any other corruption. +- */ + if (renv->majver != DB_VERSION_MAJOR || + renv->minver != DB_VERSION_MINOR) { +- if (renv->majver != 0 || renv->minver != 0) { ++ /* ++ * Special case a region that's all nul bytes, just treat it ++ * like any other corruption. ++ */ ++ if (renv->majver == 0 && renv->minver == 0) ++ ret = EINVAL; ++ else { + __db_errx(env, DB_STR_A("1538", +- "Program version %d.%d doesn't match environment version %d.%d", ++ "Program version %d.%d doesn't match in-use environment version %d.%d", + "%d %d %d %d"), DB_VERSION_MAJOR, DB_VERSION_MINOR, + renv->majver, renv->minver); + ret = DB_VERSION_MISMATCH; +- } else +- ret = EINVAL; ++ } + goto err; + } + if (renv->signature != signature) { +@@ -289,6 +357,18 @@ user_map_functions: + } + if (renv->magic != DB_REGION_MAGIC) + goto retry; ++ /* ++ * A bad magic number means that the env is new and not yet available: ++ * wait a while and try again. If the magic number says recovery is in ++ * process, remember the env creation time to record that recovery was ++ * the reason that the open failed. ++ */ ++ if (renv->magic != DB_REGION_MAGIC) { ++ __db_msg(env, "attach sees bad region magic 0x%lx", ++ (u_long)renv->magic); ++ goto retry; ++ } ++ + + /* + * Get a reference to the underlying REGION information for this +@@ -346,6 +426,12 @@ user_map_functions: + return (0); + + creation: ++ /* Should this wait for the lock (passing 0 instead of 1)? */ ++ if ((ret = ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1)) != 0) { ++ __db_err(env, ret, "__env_attach: creation could not lock %s", ++ env->lockfhp->name); ++ goto err; ++ } + /* Create the environment region. */ + F_SET(infop, REGION_CREATE); + +@@ -437,7 +523,14 @@ creation: + renv->minver = (u_int32_t)minver; + renv->patchver = (u_int32_t)patchver; + renv->signature = signature; +- ++#ifdef HAVE_PTHREADS_TIMESTAMP ++ renv->pthreads_timestamp = __os_pthreads_timestamp(env); ++ { ++ char *s = getenv("TS_ADJUST"); ++ if (s != NULL) ++ renv->pthreads_timestamp -= atoi(s); ++ } ++#endif + (void)time(&renv->timestamp); + __os_unique_id(env, &renv->envid); + +@@ -513,16 +606,24 @@ find_err: __db_errx(env, DB_STR_A("1544" + } + } + +-#ifndef HAVE_MUTEX_FCNTL +- /* +- * If we're not doing fcntl locking, we can close the file handle. We +- * no longer need it and the less contact between the buffer cache and +- * the VM, the better. +- */ ++#ifdef HAVE_FCNTL ++ if ((ret = ENV_PRIMARY_UNLOCK(env)) != 0) { ++ __db_err(env, ret, "__env_attach: release exclusive lock"); ++ goto err; ++ } ++ if ((ret = ENV_PRIMARY_LOCK(env, DB_LOCK_READ, 0)) != 0) { ++ __db_err(env, ret, "__env_attach: new: acquire shared lock"); ++ goto err; ++ } ++#else ++ /* ++ * We no longer need the primary region file's handle and the less ++ * contact between the buffer cache and the VM, the better. ++ */ + if (env->lockfhp != NULL) { + (void)__os_closehandle(env, env->lockfhp); + env->lockfhp = NULL; +- } ++ } + #endif + + /* Everything looks good, we're done. */ +@@ -562,9 +663,9 @@ retry: /* Close any open file handle. */ + /* If we had a temporary error, wait awhile and try again. */ + if (ret == 0) { + if (!retry_ok || ++retry_cnt > 3) { ++ ret = EAGAIN; + __db_errx(env, DB_STR("1546", + "unable to join the environment")); +- ret = EAGAIN; + } else { + __os_yield(env, retry_cnt * 3, 0); + goto loop; +@@ -575,6 +676,59 @@ retry: /* Close any open file handle. */ + } + + /* ++ * __env_check_recreate -- ++ * Determine whether an existing on-disk environment should be recreated ++ * because it is not compatible with this compiled BDB library. ++ * ++ * Returns: ++ * 0 - ++ * The env was generated by this library. No recreation needed. ++ * DB_OLD_VERSION - ++ * It was created by an earlier BDB version, or by an earlier ++ * version of libpthreads (on certain Linux systems). The caller ++ * will try to recreate it with the currently configured settings. ++ * DB_VERSION_MISMATCH - ++ * It was created by a newer version of BDB. Do not attempt to ++ * fix it, something is probably wrong with the application setup. ++ */ ++static int ++__env_check_recreate(env, renv, signature) ++ ENV *env; ++ REGENV *renv; ++ u_int32_t signature; ++{ ++#ifdef HAVE_PTHREADS_TIMESTAMP ++ time_t pthreads_time; ++ char envtime[CTIME_BUFLEN], libtime[CTIME_BUFLEN]; ++#endif ++ ++ /* First, bail out if the env is too new for this code to handle. */ ++ if (renv->majver > DB_VERSION_MAJOR || ++ (renv->majver == DB_VERSION_MAJOR && ++ renv->minver > DB_VERSION_MINOR)) ++ return (DB_VERSION_MISMATCH); ++ ++#ifdef HAVE_PTHREADS_TIMESTAMP ++ pthreads_time = __os_pthreads_timestamp(env); ++ if (pthreads_time != renv->pthreads_timestamp) { ++ if (FLD_ISSET(env->dbenv->verbose, DB_VERB_RECOVERY)) ++ __db_msg(env, ++ "Pthreads timestamp changed: env %.24s current %.24s", ++ __os_ctime(&renv->pthreads_timestamp, envtime), ++ __os_ctime(&pthreads_time, libtime)); ++ return (DB_OLD_VERSION); ++ } ++#endif ++ if (renv->signature != signature || renv->majver != DB_VERSION_MAJOR || ++ renv->minver != DB_VERSION_MINOR) { ++ if (FLD_ISSET(env->dbenv->verbose, DB_VERB_RECOVERY)) ++ __db_msg(env, "Signature or version changed"); ++ return (DB_OLD_VERSION); ++ } ++ return (0); ++} ++ ++/* + * __env_turn_on -- + * Turn on the created environment. + * +diff -up db-5.3.28/src/env/env_register.c.pthreads db-5.3.28/src/env/env_register.c +--- db-5.3.28/src/env/env_register.c.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/env/env_register.c 2017-06-13 11:15:15.325215121 +0200 +@@ -19,9 +19,9 @@ + #define PID_LEN (25) /* PID entry length */ + + #define REGISTRY_LOCK(env, pos, nowait) \ +- __os_fdlock(env, (env)->dbenv->registry, (off_t)(pos), 1, nowait) ++ __os_fdlock(env, (env)->dbenv->registry, (off_t)(pos), DB_LOCK_WRITE, nowait) + #define REGISTRY_UNLOCK(env, pos) \ +- __os_fdlock(env, (env)->dbenv->registry, (off_t)(pos), 0, 0) ++ __os_fdlock(env, (env)->dbenv->registry, (off_t)(pos), DB_LOCK_NG, 0) + #define REGISTRY_EXCL_LOCK(env, nowait) \ + REGISTRY_LOCK(env, 1, nowait) + #define REGISTRY_EXCL_UNLOCK(env) \ +diff -up db-5.3.28/src/env/env_stat.c.pthreads db-5.3.28/src/env/env_stat.c +--- db-5.3.28/src/env/env_stat.c.pthreads 2013-09-09 17:35:08.000000000 +0200 ++++ db-5.3.28/src/env/env_stat.c 2017-06-13 11:15:15.325215121 +0200 +@@ -177,6 +177,10 @@ __env_print_stats(env, flags) + STAT_LONG("Txn version", DB_TXNVERSION); + __db_msg(env, + "%.24s\tCreation time", __os_ctime(&renv->timestamp, time_buf)); ++#if defined(HAVE_PTHREADS_TIMESTAMP) && defined(HAVE_MUTEX_PTHREADS) ++ __db_msg(env, ++ "%.24s\tlibpthread timestamp", __os_ctime(&renv->pthreads_timestamp, time_buf)); ++#endif + STAT_HEX("Environment ID", renv->envid); + __mutex_print_debug_single(env, + "Primary region allocation and reference count mutex", +diff -up db-5.3.28/src/os/os_addrinfo.c.pthreads db-5.3.28/src/os/os_addrinfo.c +--- db-5.3.28/src/os/os_addrinfo.c.pthreads 2013-09-09 17:35:09.000000000 +0200 ++++ db-5.3.28/src/os/os_addrinfo.c 2017-06-13 11:15:15.325215121 +0200 +@@ -10,6 +10,10 @@ + + #include "db_int.h" + ++#ifdef HAVE_PTHREADS_TIMESTAMP ++#include ++#endif ++ + /* + * __os_getaddrinfo and __os_freeaddrinfo wrap the getaddrinfo and freeaddrinfo + * calls, as well as the associated platform dependent error handling, mapping +@@ -177,3 +181,48 @@ __os_freeaddrinfo(env, ai) + } + #endif + } ++ ++#ifdef HAVE_PTHREADS_TIMESTAMP ++/* ++ * callback_find_pthreads -- ++ * dl_iterate_phdr() calls this once for each loaded library. ++ * ++ * Returns: ++ * 0 - the library does not appear to be libpthreads. ++ * 1 - the library *does* seem to be libpthreads. Its modification time is ++ * stored into into the last argument's location. ++ */ ++static int ++callback_find_pthreads(struct dl_phdr_info *info, size_t size, void *data) ++{ ++ struct stat stbuf; ++ ++ /* Stop (return non-zero) when libc is found. */ ++ if (strstr(info->dlpi_name, "libpthread") != NULL && ++ stat(info->dlpi_name, &stbuf) == 0) { ++ *(time_t *)data = stbuf.st_mtime; ++ return (1); ++ } ++ COMPQUIET(size, 0); ++ COMPQUIET(data, NULL); ++ return (0); ++} ++ ++/* ++ * __os_pthreads_timestamp -- ++ * ++ * PUBLIC: time_t __os_pthreads_timestamp __P((ENV *)); ++ */ ++time_t ++__os_pthreads_timestamp(env) ++ ENV *env; ++{ ++ time_t timestamp; ++ ++ timestamp = 0; ++ dl_iterate_phdr(callback_find_pthreads, ×tamp); ++ ++ COMPQUIET(env, 0); ++ return (timestamp); ++} ++#endif +diff -up db-5.3.28/src/os/os_flock.c.pthreads db-5.3.28/src/os/os_flock.c +--- db-5.3.28/src/os/os_flock.c.pthreads 2013-09-09 17:35:09.000000000 +0200 ++++ db-5.3.28/src/os/os_flock.c 2017-06-13 11:15:15.325215121 +0200 +@@ -10,41 +10,98 @@ + + #include "db_int.h" + ++#if !defined(HAVE_FCNTL) || !defined(HAVE_FLOCK) ++static int __os_filelocking_notsup __P((ENV *)); ++#endif ++ + /* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + * +- * PUBLIC: int __os_fdlock __P((ENV *, DB_FH *, off_t, int, int)); ++ * The lock modes supported here are: ++ * DB_LOCK_NG - release the lock ++ * DB_LOCK_READ - get shared access ++ * DB_LOCK_WRITE - get exclusive access ++ * ++ * Use fcntl()-like semantics most of the time (DB_REGISTER support). Fcntl ++ * supports range locking, but has the additional broken semantics that ++ * closing any of the file's descriptors releases any locks, even if its ++ * other file descriptors remain open. Thanks SYSV & POSIX. ++ * However, if the offset is negative (which is allowed, because POSIX ++ * off_t a signed integer) then use flock() instead. It has only whole- ++ * file locks, but they persist until explicitly unlocked or the process ++ * exits. ++ * PUBLIC: int __os_fdlock __P((ENV *, DB_FH *, off_t, db_lockmode_t, int)); + */ + int +-__os_fdlock(env, fhp, offset, acquire, nowait) ++__os_fdlock(env, fhp, offset, lockmode, nowait) + ENV *env; + DB_FH *fhp; +- int acquire, nowait; + off_t offset; ++ db_lockmode_t lockmode; ++ int nowait; + { + #ifdef HAVE_FCNTL + DB_ENV *dbenv; + struct flock fl; + int ret, t_ret; ++ static char *mode_string[DB_LOCK_WRITE + 1] = { ++ "unlock", ++ "read", ++ "write" ++ }; ++ short mode_fcntl[DB_LOCK_WRITE + 1] = { ++ F_UNLCK, ++ F_RDLCK, ++ F_WRLCK ++ }; ++#ifdef HAVE_FLOCK ++ short mode_flock[DB_LOCK_WRITE + 1] = { ++ LOCK_UN, ++ LOCK_SH, ++ LOCK_EX ++ }; ++#endif + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); ++ DB_ASSERT(env, lockmode <= DB_LOCK_WRITE); + +- if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) +- __db_msg(env, DB_STR_A("0138", +- "fileops: flock %s %s offset %lu", "%s %s %lu"), fhp->name, +- acquire ? DB_STR_P("acquire"): DB_STR_P("release"), +- (u_long)offset); +- +- fl.l_start = offset; +- fl.l_len = 1; +- fl.l_type = acquire ? F_WRLCK : F_UNLCK; +- fl.l_whence = SEEK_SET; +- +- RETRY_CHK_EINTR_ONLY( +- (fcntl(fhp->fd, nowait ? F_SETLK : F_SETLKW, &fl)), ret); ++ if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) { ++ if (offset < 0) ++ __db_msg(env, DB_STR_A("####", ++ "fileops: flock %s %s %s", "%s %s %s"), ++ fhp->name, mode_string[lockmode], ++ nowait ? "nowait" : ""); ++ else ++ __db_msg(env, DB_STR_A("0020", ++ "fileops: fcntls %s %s offset %lu", "%s %s %lu"), ++ fhp->name, mode_string[lockmode], (u_long)offset); ++ } ++ ++ if (offset < 0) { ++#ifdef HAVE_FLOCK ++ RETRY_CHK_EINTR_ONLY(flock(fhp->fd, ++ mode_flock[lockmode] | (nowait ? LOCK_NB : 0)), ret); ++#else ++ ret = __os_filelocking_notsup(env); ++#endif ++ } else { ++ fl.l_start = offset; ++ fl.l_len = 1; ++ fl.l_whence = SEEK_SET; ++ fl.l_type = mode_fcntl[lockmode]; ++ RETRY_CHK_EINTR_ONLY( ++ fcntl(fhp->fd, nowait ? F_SETLK : F_SETLKW, &fl), ret); ++ } ++ ++ if (offset < 0 && dbenv != NULL && ++ FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) ++ __db_msg(env, DB_STR_A("####", ++ "fileops: flock %s %s %s returns %s", "%s %s %s"), ++ fhp->name, mode_string[lockmode], ++ nowait ? "nowait" : "", db_strerror(ret)); + + if (ret == 0) + return (0); +@@ -53,12 +110,29 @@ __os_fdlock(env, fhp, offset, acquire, n + __db_syserr(env, ret, DB_STR("0139", "fcntl")); + return (t_ret); + #else ++ ret = __os_filelocking_notsup(env); + COMPQUIET(fhp, NULL); +- COMPQUIET(acquire, 0); ++ COMPQUIET(lockmode, 0); + COMPQUIET(nowait, 0); + COMPQUIET(offset, 0); ++ return (ret) ++#endif ++} ++ ++ ++#if !defined(HAVE_FCNTL) || !defined(HAVE_FLOCK) ++/* ++ * __os_filelocking_notsup -- ++ * Generate an error message if fcntl() or flock() is requested on a ++ * platform that does not support it. ++ * ++ */ ++static int ++__os_filelocking_notsup(env) ++ ENV *env; ++{ + __db_syserr(env, DB_OPNOTSUP, DB_STR("0140", + "advisory file locking unavailable")); + return (DB_OPNOTSUP); +-#endif + } ++#endif +diff -up db-5.3.28/src/os/os_map.c.pthreads db-5.3.28/src/os/os_map.c +--- db-5.3.28/src/os/os_map.c.pthreads 2013-09-09 17:35:09.000000000 +0200 ++++ db-5.3.28/src/os/os_map.c 2017-06-13 11:15:15.325215121 +0200 +@@ -32,7 +32,7 @@ static int __no_system_mem __P((ENV *)); + + /* + * __os_attach -- +- * Create/join a shared memory region. ++ * Create/join a 'shared' region of Berkeley DB memory. + * + * PUBLIC: int __os_attach __P((ENV *, REGINFO *, REGION *)); + */ +@@ -50,6 +50,7 @@ __os_attach(env, infop, rp) + * so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); ++ DB_ASSERT(env, infop->fhp == NULL); + dbenv = env->dbenv; + + if (DB_GLOBAL(j_region_map) != NULL) { diff --git a/SOURCES/db-5.3.28-cwd-db_config.patch b/SOURCES/db-5.3.28-cwd-db_config.patch new file mode 100644 index 0000000..652e962 --- /dev/null +++ b/SOURCES/db-5.3.28-cwd-db_config.patch @@ -0,0 +1,11 @@ +--- db-5.3.28/src/env/env_open.c.old 2017-06-26 10:32:11.011419981 +0200 ++++ db-5.3.28/src/env/env_open.c 2017-06-26 10:32:46.893721233 +0200 +@@ -473,7 +473,7 @@ + env->db_mode = mode == 0 ? DB_MODE_660 : mode; + + /* Read the DB_CONFIG file. */ +- if ((ret = __env_read_db_config(env)) != 0) ++ if (env->db_home != NULL && (ret = __env_read_db_config(env)) != 0) + return (ret); + + /* diff --git a/SOURCES/db-5.3.28-fix-CWE-686-398.patch b/SOURCES/db-5.3.28-fix-CWE-686-398.patch new file mode 100644 index 0000000..840c050 --- /dev/null +++ b/SOURCES/db-5.3.28-fix-CWE-686-398.patch @@ -0,0 +1,54 @@ +This patch fixes: CWE-686,CWE-398 + +diff -ur db-5.3.28/src/log/log_verify_int.c new/src/log/log_verify_int.c +--- db-5.3.28/src/log/log_verify_int.c 2013-09-09 17:35:08.000000000 +0200 ++++ new/src/log/log_verify_int.c 2021-08-05 13:33:06.378608924 +0200 +@@ -433,9 +433,9 @@ + putflag = DB_CURRENT; + doput = 1; + } ++ if (doput) ++ ret = __dbc_put(csr, &key, &data, putflag); + +- if (doput && (ret = __dbc_put(csr, &key, &data, putflag)) != 0) +- goto err; + err: + if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0) + ret = tret; +diff -ur db-5.3.28/src/log/log_verify_util.c new/src/log/log_verify_util.c +--- db-5.3.28/src/log/log_verify_util.c 2013-09-09 17:35:08.000000000 +0200 ++++ new/src/log/log_verify_util.c 2021-08-04 15:10:07.900854238 +0200 +@@ -2140,8 +2140,7 @@ + for (ret = __dbc_pget(csr, &key, &data2, &data, DB_SET); ret == 0; + ret = __dbc_pget(csr, &key, &data2, &data, DB_NEXT_DUP)) + BDBOP(__db_put(pdb, lvh->ip, NULL, &data2, &key2, 0)); +- if ((ret = __del_txn_pages(lvh, ctxn)) != 0 && ret != DB_NOTFOUND) +- goto err; ++ ret = __del_txn_pages(lvh, ctxn); + err: + if (csr != NULL && (tret = __dbc_close(csr)) != 0 && ret == 0) + ret = tret; +diff -ur db-5.3.28/src/rep/rep_backup.c new/src/rep/rep_backup.c +--- db-5.3.28/src/rep/rep_backup.c 2013-09-09 17:35:09.000000000 +0200 ++++ new/src/rep/rep_backup.c 2021-08-04 14:47:51.967782566 +0200 +@@ -542,8 +542,6 @@ + + ret = __memp_fput(dbp->mpf, ip, pagep, dbc->priority); + pagep = NULL; +- if (ret != 0) +- goto err; + err: + /* + * Check status of pagep in case any new error paths out leave +diff -ur db-5.3.28/util/db_dump185.c new/util/db_dump185.c +--- db-5.3.28/util/db_dump185.c 2013-09-09 17:35:12.000000000 +0200 ++++ new/util/db_dump185.c 2021-08-04 14:45:37.592794678 +0200 +@@ -19,7 +19,7 @@ + #include + #include + #include +- ++#include + #ifdef HAVE_DB_185_H + #include + #else diff --git a/SOURCES/db-5.3.28-lemon_hash.patch b/SOURCES/db-5.3.28-lemon_hash.patch new file mode 100644 index 0000000..1556d5d --- /dev/null +++ b/SOURCES/db-5.3.28-lemon_hash.patch @@ -0,0 +1,20 @@ +--- db-5.3.28/lang/sql/sqlite/tool/lemon.c.lemon_hash 2013-09-09 17:35:07.000000000 +0200 ++++ db-5.3.28/lang/sql/sqlite/tool/lemon.c 2017-02-22 13:12:08.564106051 +0100 +@@ -3428,7 +3428,7 @@ + int maxdtlength; /* Maximum length of any ".datatype" field. */ + char *stddt; /* Standardized name for a datatype */ + int i,j; /* Loop counters */ +- int hash; /* For hashing the name of a type */ ++ unsigned hash; /* For hashing the name of a type */ + const char *name; /* Name of the parser */ + + /* Allocate and initialize types[] and allocate stddt[] */ +@@ -3491,7 +3491,7 @@ + break; + } + hash++; +- if( hash>=arraysize ) hash = 0; ++ if( hash>=(unsigned)arraysize ) hash = 0; + } + if( types[hash]==0 ){ + sp->dtnum = hash + 1; diff --git a/SOURCES/db-5.3.28-mmap-high-cpu-usage.patch b/SOURCES/db-5.3.28-mmap-high-cpu-usage.patch new file mode 100644 index 0000000..b11ce08 --- /dev/null +++ b/SOURCES/db-5.3.28-mmap-high-cpu-usage.patch @@ -0,0 +1,19 @@ +Author: Filip Januš +Date: 6 Sep 2021 +Related: https://bugzilla.redhat.com/show_bug.cgi?id=1992402 +Patch was created based on the discussion in the previous link +diff -ur db-5.3.28/src/os/os_map.c db_patch/src/os/os_map.c +--- db-5.3.28/src/os/os_map.c 2013-09-09 17:35:09.000000000 +0200 ++++ db_patch/src/os/os_map.c 2021-09-09 07:33:12.027328265 +0200 +@@ -213,7 +213,10 @@ + if (rp->max < rp->size) + rp->max = rp->size; + if (ret == 0 && F_ISSET(infop, REGION_CREATE)) { +- if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) ++ ++ rp->size = rp->max; ++ ++ if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) + ret = __db_file_write(env, infop->fhp, + rp->size / MEGABYTE, rp->size % MEGABYTE, 0x00); + else diff --git a/SOURCES/db-5.3.28-rpm-lock-check.patch b/SOURCES/db-5.3.28-rpm-lock-check.patch new file mode 100644 index 0000000..2a27898 --- /dev/null +++ b/SOURCES/db-5.3.28-rpm-lock-check.patch @@ -0,0 +1,99 @@ +diff -up db-5.3.28/src/dbinc_auto/int_def.in.rpmlock db-5.3.28/src/dbinc_auto/int_def.in +--- db-5.3.28/src/dbinc_auto/int_def.in.rpmlock 2017-06-26 15:09:17.883356255 +0200 ++++ db-5.3.28/src/dbinc_auto/int_def.in 2017-06-26 15:09:27.421170401 +0200 +@@ -1573,6 +1573,7 @@ + #define __os_posix_err __os_posix_err@DB_VERSION_UNIQUE_NAME@ + #define __os_fileid __os_fileid@DB_VERSION_UNIQUE_NAME@ + #define __check_lock_fn __check_lock_fn@DB_VERSION_UNIQUE_NAME@ ++#define __rpm_lock_free __rpm_lock_free@DB_VERSION_UNIQUE_NAME@ + #define __os_fdlock __os_fdlock@DB_VERSION_UNIQUE_NAME@ + #define __os_fsync __os_fsync@DB_VERSION_UNIQUE_NAME@ + #define __os_getenv __os_getenv@DB_VERSION_UNIQUE_NAME@ +diff -up db-5.3.28/src/dbinc_auto/os_ext.h.rpmlock db-5.3.28/src/dbinc_auto/os_ext.h +--- db-5.3.28/src/dbinc_auto/os_ext.h.rpmlock 2017-06-26 15:09:21.940277203 +0200 ++++ db-5.3.28/src/dbinc_auto/os_ext.h 2017-06-26 15:09:27.354171707 +0200 +@@ -42,6 +42,7 @@ char *__os_strerror __P((int, char *, si + int __os_posix_err __P((int)); + int __os_fileid __P((ENV *, const char *, int, u_int8_t *)); + int __check_lock_fn __P((char *, pid_t)); ++int __rpm_lock_free __P((ENV *)); + int __os_fdlock __P((ENV *, DB_FH *, off_t, db_lockmode_t, int)); + int __os_fsync __P((ENV *, DB_FH *)); + int __os_getenv __P((ENV *, const char *, char **, size_t)); +diff -up db-5.3.28/src/env/env_region.c.rpmlock db-5.3.28/src/env/env_region.c +--- db-5.3.28/src/env/env_region.c.rpmlock 2017-06-26 15:09:12.479461558 +0200 ++++ db-5.3.28/src/env/env_region.c 2017-06-26 15:09:12.481461519 +0200 +@@ -291,18 +291,23 @@ user_map_functions: + if (create_ok && + ret == DB_OLD_VERSION && + ENV_PRIMARY_LOCK(env, DB_LOCK_WRITE, 1) == 0) { +- if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) +- __db_msg(env, "Recreating idle environment"); +- F_SET(infop, REGION_CREATE_OK); ++ /* If the rpm transaction lock is taken we cannot safely rebuild */ ++ if (!__rpm_lock_free(env)) ++ ENV_PRIMARY_UNLOCK(env); ++ else { ++ if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) ++ __db_msg(env, "Recreating idle environment"); ++ F_SET(infop, REGION_CREATE_OK); + +- /* +- * Detach from the environment region; we need to unmap it (and +- * close any file handle) so that we don't leak memory or files. +- */ +- DB_ASSERT(env, infop->rp == NULL); +- infop->rp = &tregion; +- (void)__env_sys_detach(env, infop, 0); +- goto creation; ++ /* ++ * Detach from the environment region; we need to unmap it (and ++ * close any file handle) so that we don't leak memory or files. ++ */ ++ DB_ASSERT(env, infop->rp == NULL); ++ infop->rp = &tregion; ++ (void)__env_sys_detach(env, infop, 0); ++ goto creation; ++ } + } + + if (renv->majver != DB_VERSION_MAJOR || +diff -up db-5.3.28/src/os/os_flock.c.rpmlock db-5.3.28/src/os/os_flock.c +--- db-5.3.28/src/os/os_flock.c.rpmlock 2017-06-26 15:09:12.480461538 +0200 ++++ db-5.3.28/src/os/os_flock.c 2017-06-26 15:09:12.481461519 +0200 +@@ -79,6 +79,35 @@ int __check_lock_fn(fn, pid) + } + + /* ++ * __rpm_lock_free -- ++ * Try to look at a lock used by rpm to see if libdb is being ++ * updated and it is safe to access its environment files. ++ * PUBLIC: int __rpm_lock_free __P((ENV *)); ++ */ ++ ++#define RPM_PATH SHAREDSTATEDIR "/rpm" ++#define RPMLOCK_PATH RPM_PATH "/.rpm.lock" ++ ++int __rpm_lock_free(env) ++ ENV *env; ++{ ++ int ret; ++ ++ /* No need to check the transaction lock if not in rpm */ ++ if (strstr(env->db_home, RPM_PATH) == NULL) ++ return 1; ++ ++ /* Assume it is safe to rebuild if the lock file does not exist */ ++ if (access(RPMLOCK_PATH, F_OK) && errno == ENOENT) ++ return 1; ++ ++ ret = __check_lock_fn(RPMLOCK_PATH, 0); ++ /* __check_lock_fn can return -1 on failure - return 0 (taken) instead */ ++ return ret == -1 ? 0: ret; ++ ++} ++ ++/* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + * diff --git a/SOURCES/db-5.3.28_cve-2019-2708.patch b/SOURCES/db-5.3.28_cve-2019-2708.patch new file mode 100644 index 0000000..341cb4b --- /dev/null +++ b/SOURCES/db-5.3.28_cve-2019-2708.patch @@ -0,0 +1,694 @@ +--- db-18.1.32/src/btree/bt_cursor.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/btree/bt_cursor.c 2020-05-29 23:28:22.000000000 +0530 +@@ -282,6 +282,8 @@ + * + * Recno uses the btree bt_ovflsize value -- it's close enough. + */ ++ if (t->bt_minkey == 0) ++ return (DB_RECOVER); + cp->ovflsize = B_MINKEY_TO_OVFLSIZE( + dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize); + +--- db-18.1.32/src/btree/bt_verify.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/btree/bt_verify.c 2020-05-29 23:28:22.000000000 +0530 +@@ -700,7 +700,11 @@ + isbad = 1; + goto err; + default: ++ if (ret == 0) { ++ isbad = 1; ++ ret = DB_VERIFY_FATAL; ++ goto err; ++ } +- DB_ASSERT(env, ret != 0); + break; + } + +@@ -1074,7 +1078,7 @@ + DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp; + ENV *env; + PAGE *child; ++ db_pgno_t cpgno, grandparent; +- db_pgno_t cpgno; + VRFY_PAGEINFO *pip; + db_indx_t i, *inp; + int adj, cmp, freedup_1, freedup_2, isbad, ret, t_ret; +@@ -1106,7 +1110,8 @@ + + buf1 = buf2 = NULL; + ++ if (LF_ISSET(DB_NOORDERCHK)) ++ return (EINVAL); +- DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK)); + + dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare; + if (TYPE(h) == P_LDUP) +@@ -1115,6 +1120,7 @@ + func = __bam_defcmp; + if (dbp->bt_internal != NULL) { + bt = (BTREE *)dbp->bt_internal; ++ grandparent = bt->bt_root; + if (TYPE(h) == P_IBTREE && (bt->bt_compare != NULL || + dupfunc != __bam_defcmp)) { + /* +@@ -974,8 +980,24 @@ + */ + mpf = dbp->mpf; + child = h; ++ cpgno = pgno; + while (TYPE(child) == P_IBTREE) { ++ if (NUM_ENT(child) == 0) { ++ EPRINT((env, DB_STR_A("1088", ++ "Page %lu: internal page is empty and should not be", ++ "%lu"), (u_long)cpgno)); ++ ret = DB_VERIFY_BAD; ++ goto err; ++ } + bi = GET_BINTERNAL(dbp, child, 0); ++ if (grandparent == bi->pgno) { ++ EPRINT((env, DB_STR_A("5552", ++ "Page %lu: found twice in the btree", ++ "%lu"), (u_long)grandparent)); ++ ret = DB_VERIFY_FATAL; ++ goto err; ++ } else ++ grandparent = cpgno; + cpgno = bi->pgno; + if (child != h && + (ret = __memp_fput(mpf, +@@ -1402,7 +1416,10 @@ + */ + if (dup_1.data == NULL || + dup_2.data == NULL) { ++ if (ovflok) { ++ isbad = 1; ++ goto err; ++ } +- DB_ASSERT(env, !ovflok); + if (pip != NULL) + F_SET(pip, + VRFY_INCOMPLETE); +@@ -1747,9 +1764,10 @@ + (ret = __db_vrfy_ovfl_structure(dbp, vdp, + child->pgno, child->tlen, + flags | DB_ST_OVFL_LEAF)) != 0) { ++ if (ret == DB_VERIFY_BAD) { +- if (ret == DB_VERIFY_BAD) + isbad = 1; ++ break; ++ } else +- else + goto done; + } + +@@ -1823,9 +1841,10 @@ + stflags | DB_ST_TOPLEVEL, + NULL, NULL, NULL)) != 0) { + if (ret == ++ DB_VERIFY_BAD) { +- DB_VERIFY_BAD) + isbad = 1; ++ break; ++ } else +- else + goto err; + } + } +@@ -1969,7 +1988,10 @@ + */ + + /* Otherwise, __db_vrfy_childput would be broken. */ ++ if (child->refcnt < 1) { ++ isbad = 1; ++ goto err; ++ } +- DB_ASSERT(env, child->refcnt >= 1); + + /* + * An overflow referenced more than twice here +@@ -1986,9 +2008,10 @@ + if ((ret = __db_vrfy_ovfl_structure(dbp, + vdp, child->pgno, child->tlen, + flags)) != 0) { ++ if (ret == DB_VERIFY_BAD) { +- if (ret == DB_VERIFY_BAD) + isbad = 1; ++ break; ++ } else +- else + goto done; + } + } +@@ -2026,9 +2049,10 @@ + if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno, + i == 0 ? NULL : li, ri, flags, &child_level, + &child_nrecs, NULL)) != 0) { ++ if (ret == DB_VERIFY_BAD) { +- if (ret == DB_VERIFY_BAD) + isbad = 1; ++ break; ++ } else +- else + goto done; + } + +@@ -2929,7 +2953,11 @@ + db_pgno_t current, p; + int err_ret, ret; + ++ if (pgset == NULL) { ++ EPRINT((dbp->env, DB_STR("5542", ++ "Error, database contains no visible pages."))); ++ return (DB_RUNRECOVERY); ++ } +- DB_ASSERT(dbp->env, pgset != NULL); + + mpf = dbp->mpf; + h = NULL; +--- db-18.1.32/src/db/db_conv.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/db/db_conv.c 2020-05-29 23:28:22.000000000 +0530 +@@ -493,8 +493,11 @@ + db_indx_t i, *inp, len, tmp; + u_int8_t *end, *p, *pgend; + +- if (pagesize == 0) +- return (0); ++ /* This function is also used to byteswap logs, so ++ * the pagesize might not be an actual page size. ++ */ ++ if (!(pagesize >= 24 && pagesize <= DB_MAX_PGSIZE)) ++ return (EINVAL); + + if (pgin) { + M_32_SWAP(h->lsn.file); +@@ -513,26 +516,41 @@ + pgend = (u_int8_t *)h + pagesize; + + inp = P_INP(dbp, h); +- if ((u_int8_t *)inp >= pgend) +- goto out; ++ if ((u_int8_t *)inp > pgend) ++ return (__db_pgfmt(env, pg)); + + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + for (i = 0; i < NUM_ENT(h); i++) { ++ if ((u_int8_t*)(inp + i) >= pgend) ++ return (__db_pgfmt(env, pg)); ++ if (inp[i] == 0) ++ continue; + if (pgin) + M_16_SWAP(inp[i]); ++ if (inp[i] >= pagesize) ++ return (__db_pgfmt(env, pg)); + +- if (P_ENTRY(dbp, h, i) >= pgend) +- continue; ++ if (P_ENTRY(dbp, h, i) >= pgend) ++ return (__db_pgfmt(env, pg)); + + switch (HPAGE_TYPE(dbp, h, i)) { + case H_KEYDATA: + break; + case H_DUPLICATE: ++ if (LEN_HITEM(dbp, h, pagesize, i) < ++ HKEYDATA_SIZE(0)) ++ return (__db_pgfmt(env, pg)); ++ + len = LEN_HKEYDATA(dbp, h, pagesize, i); + p = HKEYDATA_DATA(P_ENTRY(dbp, h, i)); +- for (end = p + len; p < end;) { ++ ++ end = p + len; ++ if (end > pgend) ++ return (__db_pgfmt(env, pg)); ++ ++ while (p < end) { + if (pgin) { + P_16_SWAP(p); + memcpy(&tmp, +@@ -544,14 +562,20 @@ + SWAP16(p); + } + p += tmp; ++ if (p >= end) ++ return (__db_pgfmt(env, pg)); + SWAP16(p); + } + break; + case H_OFFDUP: ++ if ((inp[i] + HOFFDUP_SIZE) > pagesize) ++ return (__db_pgfmt(env, pg)); + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); + SWAP32(p); /* pgno */ + break; + case H_OFFPAGE: ++ if ((inp[i] + HOFFPAGE_SIZE) > pagesize) ++ return (__db_pgfmt(env, pg)); + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); + SWAP32(p); /* pgno */ + SWAP32(p); /* tlen */ +@@ -559,7 +583,6 @@ + default: + return (__db_pgfmt(env, pg)); + } +- + } + + /* +@@ -576,8 +599,12 @@ + case P_LDUP: + case P_LRECNO: + for (i = 0; i < NUM_ENT(h); i++) { ++ if ((u_int8_t *)(inp + i) >= pgend) ++ return (__db_pgfmt(env, pg)); + if (pgin) + M_16_SWAP(inp[i]); ++ if (inp[i] >= pagesize) ++ return (__db_pgfmt(env, pg)); + + /* + * In the case of on-page duplicates, key information +@@ -597,7 +624,7 @@ + + bk = GET_BKEYDATA(dbp, h, i); + if ((u_int8_t *)bk >= pgend) +- continue; ++ return (__db_pgfmt(env, pg)); + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + M_16_SWAP(bk->len); +@@ -605,6 +632,8 @@ + case B_DUPLICATE: + case B_OVERFLOW: + bo = (BOVERFLOW *)bk; ++ if (((u_int8_t *)bo + BOVERFLOW_SIZE) > pgend) ++ return (__db_pgfmt(env, pg)); + M_32_SWAP(bo->pgno); + M_32_SWAP(bo->tlen); + break; +@@ -618,12 +647,17 @@ + break; + case P_IBTREE: + for (i = 0; i < NUM_ENT(h); i++) { ++ if ((u_int8_t *)(inp + i) > pgend) ++ return (__db_pgfmt(env, pg)); + if (pgin) + M_16_SWAP(inp[i]); ++ if ((u_int16_t)(inp[i] + ++ BINTERNAL_SIZE(0) - 1) > pagesize) ++ break; + + bi = GET_BINTERNAL(dbp, h, i); +- if ((u_int8_t *)bi >= pgend) +- continue; ++ if (((u_int8_t *)bi + BINTERNAL_SIZE(0)) > pgend) ++ return (__db_pgfmt(env, pg)); + + M_16_SWAP(bi->len); + M_32_SWAP(bi->pgno); +@@ -634,6 +668,10 @@ + break; + case B_DUPLICATE: + case B_OVERFLOW: ++ if ((u_int16_t)(inp[i] + ++ BINTERNAL_SIZE(BOVERFLOW_SIZE) - 1) > ++ pagesize) ++ goto out; + bo = (BOVERFLOW *)bi->data; + M_32_SWAP(bo->pgno); + M_32_SWAP(bo->tlen); +@@ -648,12 +686,16 @@ + break; + case P_IRECNO: + for (i = 0; i < NUM_ENT(h); i++) { ++ if ((u_int8_t *)(inp + i) >= pgend) ++ return (__db_pgfmt(env, pg)); + if (pgin) + M_16_SWAP(inp[i]); ++ if (inp[i] >= pagesize) ++ return (__db_pgfmt(env, pg)); + + ri = GET_RINTERNAL(dbp, h, i); +- if ((u_int8_t *)ri >= pgend) +- continue; ++ if ((((u_int8_t *)ri) + RINTERNAL_SIZE) > pgend) ++ return (__db_pgfmt(env, pg)); + + M_32_SWAP(ri->pgno); + M_32_SWAP(ri->nrecs); +--- db-18.1.32/src/db/db_vrfy.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/db/db_vrfy.c 2020-05-29 23:28:22.000000000 +0530 +@@ -381,8 +381,10 @@ + vdp, name, 0, lp, rp, flags)) != 0) { + if (t_ret == DB_VERIFY_BAD) + isbad = 1; ++ else { ++ ret = t_ret; ++ goto err; ++ } +- else +- goto err; + } + + /* +@@ -771,9 +773,10 @@ + */ + if ((t_ret = __memp_fget(mpf, &i, + vdp->thread_info, NULL, 0, &h)) != 0) { ++ if ((dbp->type == DB_HASH || +- if (dbp->type == DB_HASH || + (dbp->type == DB_QUEUE && ++ F_ISSET(dbp, DB_AM_INMEM))) && ++ t_ret != DB_RUNRECOVERY) { +- F_ISSET(dbp, DB_AM_INMEM))) { + if ((t_ret = + __db_vrfy_getpageinfo(vdp, i, &pip)) != 0) + goto err1; +@@ -945,6 +948,8 @@ + return (ret == 0 ? t_ret : ret); + } + ++ if (ret == DB_PAGE_NOTFOUND && isbad == 1) ++ ret = 0; + return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret); + } + +@@ -1581,7 +1586,7 @@ + if (pgno == PGNO_BASE_MD && + dbtype != DB_QUEUE && meta->last_pgno != vdp->last_pgno) { + #ifdef HAVE_FTRUNCATE ++ ret = DB_VERIFY_FATAL; +- isbad = 1; + EPRINT((env, DB_STR_A("0552", + "Page %lu: last_pgno is not correct: %lu != %lu", + "%lu %lu %lu"), (u_long)pgno, +@@ -1622,7 +1627,11 @@ + + env = dbp->env; + pgset = vdp->pgset; ++ if (pgset == NULL) { ++ EPRINT((env, DB_STR("5543", ++ "Error, database contains no visible pages."))); ++ return (DB_RUNRECOVERY); ++ } +- DB_ASSERT(env, pgset != NULL); + + if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0) + return (ret); +@@ -2014,7 +2023,8 @@ + int keyflag, ret, t_ret; + + env = dbp->env; ++ if (!LF_ISSET(DB_SALVAGE)) ++ return (EINVAL); +- DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); + + /* + * !!! +@@ -2126,10 +2136,8 @@ + int (*callback) __P((void *, const void *)); + u_int32_t flags; + { +- ENV *env; +- +- env = dbp->env; +- DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); ++ if (!LF_ISSET(DB_SALVAGE)) ++ return (EINVAL); + + /* If we got this page in the subdb pass, we can safely skip it. */ + if (__db_salvage_isdone(vdp, pgno)) +@@ -2242,8 +2253,8 @@ + ret = t_ret; + break; + case SALVAGE_OVERFLOW: ++ EPRINT((env, DB_STR("5544", "Invalid page type to salvage."))); ++ return (EINVAL); +- DB_ASSERT(env, 0); /* Shouldn't ever happen. */ +- break; + case SALVAGE_HASH: + if ((t_ret = __ham_salvage(dbp, vdp, + pgno, h, handle, callback, flags)) != 0 && ret == 0) +@@ -2256,8 +2267,8 @@ + * Shouldn't happen, but if it does, just do what the + * nice man says. + */ ++ EPRINT((env, DB_STR("5545", "Invalid page type to salvage."))); ++ return (EINVAL); +- DB_ASSERT(env, 0); +- break; + } + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) +@@ -2303,8 +2314,8 @@ + ret = t_ret; + break; + default: ++ EPRINT((env, DB_STR("5546", "Invalid page type to salvage."))); ++ return (EINVAL); +- DB_ASSERT(env, 0); /* Shouldn't ever happen. */ +- break; + } + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) +@@ -2361,7 +2372,10 @@ + + env = dbp->env; + ++ if (himarkp == NULL) { ++ __db_msg(env, "Page %lu index has no end.", (u_long)pgno); ++ return (DB_VERIFY_FATAL); ++ } +- DB_ASSERT(env, himarkp != NULL); + inp = P_INP(dbp, h); + + /* +@@ -2783,7 +2797,11 @@ + goto err; + ovfl_bufsz = bkkey->len + 1; + } ++ if (subdbname == NULL) { ++ EPRINT((env, DB_STR("5547", "Subdatabase cannot be null."))); ++ ret = EINVAL; ++ goto err; ++ } +- DB_ASSERT(env, subdbname != NULL); + memcpy(subdbname, bkkey->data, bkkey->len); + subdbname[bkkey->len] = '\0'; + } +--- db-18.1.32/src/db/db_vrfyutil.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/db/db_vrfyutil.c 2020-05-29 23:28:22.000000000 +0530 +@@ -214,7 +214,8 @@ + if ((ret = __db_get(pgdbp, + vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) { + /* Found it. */ ++ if (data.size != sizeof(VRFY_PAGEINFO)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(env, data.size == sizeof(VRFY_PAGEINFO)); + pip = data.data; + LIST_INSERT_HEAD(&vdp->activepips, pip, links); + goto found; +@@ -342,7 +343,8 @@ + F_SET(&data, DB_DBT_USERMEM); + + if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { ++ if (data.size != sizeof(int)) ++ return (EINVAL); +- DB_ASSERT(dbp->env, data.size == sizeof(int)); + } else if (ret == DB_NOTFOUND) + val = 0; + else +@@ -382,7 +384,8 @@ + F_SET(&data, DB_DBT_USERMEM); + + if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { ++ if (data.size != sizeof(int)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbp->env, data.size == sizeof(int)); + } else if (ret != DB_NOTFOUND) + return (ret); + +@@ -419,7 +422,8 @@ + if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) != 0) + return (ret); + ++ if (key.size != sizeof(db_pgno_t)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbc->env, key.size == sizeof(db_pgno_t)); + *pgnop = pgno; + + return (0); +@@ -566,7 +570,8 @@ + if ((ret = __dbc_get(dbc, &key, &data, DB_SET)) != 0) + return (ret); + ++ if (data.size != sizeof(VRFY_CHILDINFO)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); + *cipp = (VRFY_CHILDINFO *)data.data; + + return (0); +@@ -594,7 +599,8 @@ + if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT_DUP)) != 0) + return (ret); + ++ if (data.size != sizeof(VRFY_CHILDINFO)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); + *cipp = (VRFY_CHILDINFO *)data.data; + + return (0); +@@ -721,7 +727,8 @@ + return (ret); + + while ((ret = __dbc_get(*dbcp, &key, &data, DB_NEXT)) == 0) { ++ if (data.size != sizeof(u_int32_t)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); + memcpy(&pgtype, data.data, sizeof(pgtype)); + + if (skip_overflow && pgtype == SALVAGE_OVERFLOW) +@@ -730,8 +737,9 @@ + if ((ret = __dbc_del(*dbcp, 0)) != 0) + return (ret); + if (pgtype != SALVAGE_IGNORE) { ++ if (key.size != sizeof(db_pgno_t) ++ || data.size != sizeof(u_int32_t)) ++ return (DB_VERIFY_FATAL); +- DB_ASSERT(dbp->env, key.size == sizeof(db_pgno_t)); +- DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); + + *pgnop = *(db_pgno_t *)key.data; + *pgtypep = *(u_int32_t *)data.data; +--- db-18.1.32/src/db/partition.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/db/partition.c 2020-05-29 23:28:22.000000000 +0530 +@@ -461,9 +461,19 @@ + } else + part->nparts = meta->nparts; + } else if (meta->nparts != 0 && part->nparts != meta->nparts) { ++ ret = EINVAL; + __db_errx(env, DB_STR("0656", + "Number of partitions does not match.")); +- ret = EINVAL; ++ goto err; ++ } ++ /* ++ * There is no limit on the number of partitions, but I cannot imagine a real ++ * database having more than 10000. ++ */ ++ if (meta->nparts > 10000) { ++ ret = EINVAL; ++ __db_errx(env, DB_STR_A("5553", ++ "Too many partitions %lu", "%lu"), (u_long)(meta->nparts)); + goto err; + } + +@@ -2106,10 +2116,13 @@ + memcpy(rp->data, key->data, key->size); + B_TSET(rp->type, B_KEYDATA); + } ++vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname, ++ NULL, handle, callback, ++ lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) { ++ ret = t_ret; ++ if (ret == ENOENT) ++ break; ++ } +-vrfy: if ((t_ret = __db_verify(*pdbp, ip, (*pdbp)->fname, +- NULL, handle, callback, +- lp, rp, flags | DB_VERIFY_PARTITION)) != 0 && ret == 0) +- ret = t_ret; + } + + err: if (lp != NULL) +--- db-18.1.32/src/hash/hash_page.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/hash/hash_page.c 2020-05-29 23:28:22.000000000 +0530 +@@ -869,7 +869,11 @@ + /* Validate that next, prev pointers are OK */ + n = NUM_ENT(p); + dbp = dbc->dbp; ++ if (n % 2 != 0) { ++ __db_errx(dbp->env, DB_STR_A("5549", ++ "Odd number of entries on page: %lu", "%lu"), (u_long)(p->pgno)); ++ return (DB_VERIFY_FATAL); ++ } +- DB_ASSERT(dbp->env, n%2 == 0 ); + + env = dbp->env; + t = dbp->h_internal; +@@ -940,7 +944,12 @@ + if ((ret = __db_prpage(dbp, p, DB_PR_PAGE)) != 0) + return (ret); + #endif ++ if (res >= 0) { ++ __db_errx(env, DB_STR_A("5550", ++ "Odd number of entries on page: %lu", "%lu"), ++ (u_long)p->pgno); ++ return (DB_VERIFY_FATAL); ++ } +- DB_ASSERT(dbp->env, res < 0); + } + + prev = curr; +--- db-18.1.32/src/hash/hash_verify.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/hash/hash_verify.c 2020-05-29 23:28:22.000000000 +0530 +@@ -615,7 +615,7 @@ + isbad = 1; + else + goto err; ++ } +- } + + /* + * There may be unused hash pages corresponding to buckets +@@ -746,7 +746,7 @@ + "Page %lu: impossible first page in bucket %lu", "%lu %lu"), + (u_long)pgno, (u_long)bucket)); + /* Unsafe to continue. */ ++ ret = DB_VERIFY_FATAL; +- isbad = 1; + goto err; + } + +@@ -776,7 +776,7 @@ + EPRINT((env, DB_STR_A("1116", + "Page %lu: hash page referenced twice", "%lu"), + (u_long)pgno)); ++ ret = DB_VERIFY_FATAL; +- isbad = 1; + /* Unsafe to continue. */ + goto err; + } else if ((ret = __db_vrfy_pgset_inc(vdp->pgset, +@@ -1307,7 +1307,11 @@ + COMPQUIET(flags, 0); + ip = vdp->thread_info; + ++ if (pgset == NULL) { ++ EPRINT((dbp->env, DB_STR("5548", ++ "Error, database contains no visible pages."))); ++ return (DB_VERIFY_FATAL); ++ } +- DB_ASSERT(dbp->env, pgset != NULL); + + mpf = dbp->mpf; + totpgs = 0; +--- db-18.1.32/src/qam/qam_verify.c 2019-02-20 03:21:20.000000000 +0530 ++++ db-18.1.40/src/qam/qam_verify.c 2020-05-29 23:28:22.000000000 +0530 +@@ -465,7 +465,14 @@ + /* Verify/salvage each page. */ + if ((ret = __db_cursor(dbp, vdp->thread_info, NULL, &dbc, 0)) != 0) + return (ret); +-begin: for (; i <= stop; i++) { ++begin: if ((stop - i) > 100000) { ++ EPRINT((env, DB_STR_A("5551", ++"Warning, many possible extends files (%lu), will take a long time to verify", ++ "%lu"), (u_long)(stop - i))); ++ } ++ for (; i <= stop; i++) { ++ if (i == UINT32_MAX) ++ break; + /* + * If DB_SALVAGE is set, we inspect our database of completed + * pages, and skip any we've already printed in the subdb pass. diff --git a/SOURCES/lgpl-2.1.txt b/SOURCES/lgpl-2.1.txt new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/SOURCES/lgpl-2.1.txt @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/SOURCES/libdb-5.3.21-region-size-check.patch b/SOURCES/libdb-5.3.21-region-size-check.patch new file mode 100644 index 0000000..77be25e --- /dev/null +++ b/SOURCES/libdb-5.3.21-region-size-check.patch @@ -0,0 +1,39 @@ +diff -up db-5.3.21/src/env/env_region.c.zero-region db-5.3.21/src/env/env_region.c +--- db-5.3.21/src/env/env_region.c.zero-region 2012-05-11 19:57:53.000000000 +0200 ++++ db-5.3.21/src/env/env_region.c 2017-09-06 08:50:45.310276385 +0200 +@@ -1060,6 +1060,7 @@ __env_region_attach(env, infop, init, ma + REGION *rp; + int ret; + char buf[sizeof(DB_REGION_FMT) + 20]; ++ struct stat st; + + /* + * Find or create a REGION structure for this region. If we create +@@ -1090,6 +1091,14 @@ __env_region_attach(env, infop, init, ma + if ((ret = __env_sys_attach(env, infop, rp)) != 0) + goto err; + ++ /* Check the size of the underlying file */ ++ if (infop->fhp != NULL && F_ISSET(infop->fhp, DB_FH_OPENED) && ++ infop->fhp->fd != -1 && fstat(infop->fhp->fd, &st) != -1 && ++ st.st_size == 0) { ++ ret = DB_RUNRECOVERY; ++ goto err; ++ } ++ + /* + * Fault the pages into memory. Note, do this BEFORE we initialize + * anything because we're writing pages in created regions, not just +diff -up db-5.3.21/src/os/os_map.c.zero-region db-5.3.21/src/os/os_map.c +--- db-5.3.21/src/os/os_map.c.zero-region 2012-05-11 19:57:54.000000000 +0200 ++++ db-5.3.21/src/os/os_map.c 2017-09-06 08:49:39.144546552 +0200 +@@ -265,6 +265,9 @@ __os_detach(env, infop, destroy) + dbenv = env->dbenv; + + rp = infop->rp; ++ /* Do not touch the region information if it no longer exists */ ++ if (rp == NULL) ++ return EINVAL; + + /* If the user replaced the unmap call, call through their interface. */ + if (DB_GLOBAL(j_region_unmap) != NULL) diff --git a/SOURCES/libdb-5.3.21-trickle_cpu.patch b/SOURCES/libdb-5.3.21-trickle_cpu.patch new file mode 100644 index 0000000..20b0e88 --- /dev/null +++ b/SOURCES/libdb-5.3.21-trickle_cpu.patch @@ -0,0 +1,150 @@ +diff -up db-5.3.21/src/dbinc_auto/int_def.in.trickle db-5.3.21/src/dbinc_auto/int_def.in +--- db-5.3.21/src/dbinc_auto/int_def.in.trickle 2018-08-21 10:54:06.066757392 +0200 ++++ db-5.3.21/src/dbinc_auto/int_def.in 2018-08-21 10:54:06.111756561 +0200 +@@ -1458,6 +1458,7 @@ + #define __memp_sync_int __memp_sync_int@DB_VERSION_UNIQUE_NAME@ + #define __memp_mf_sync __memp_mf_sync@DB_VERSION_UNIQUE_NAME@ + #define __memp_purge_dead_files __memp_purge_dead_files@DB_VERSION_UNIQUE_NAME@ ++#define __memp_purge_dead_and_count __memp_purge_dead_and_count@DB_VERSION_UNIQUE_NAME@ + #define __memp_trickle_pp __memp_trickle_pp@DB_VERSION_UNIQUE_NAME@ + #define __mutex_alloc __mutex_alloc@DB_VERSION_UNIQUE_NAME@ + #define __mutex_alloc_int __mutex_alloc_int@DB_VERSION_UNIQUE_NAME@ +diff -up db-5.3.21/src/dbinc_auto/mp_ext.h.trickle db-5.3.21/src/dbinc_auto/mp_ext.h +--- db-5.3.21/src/dbinc_auto/mp_ext.h.trickle 2018-08-21 10:54:06.103756709 +0200 ++++ db-5.3.21/src/dbinc_auto/mp_ext.h 2018-08-21 10:54:06.112756543 +0200 +@@ -101,6 +101,7 @@ int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_ + int __memp_sync_int __P((ENV *, DB_MPOOLFILE *, u_int32_t, u_int32_t, u_int32_t *, int *)); + int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *, int)); + int __memp_purge_dead_files __P((ENV *)); ++int __memp_purge_dead_and_count __P((ENV *, u_int32_t *, u_int32_t *)); + int __memp_trickle_pp __P((DB_ENV *, int, int *)); + + #if defined(__cplusplus) +diff -up db-5.3.21/src/mp/mp_sync.c.trickle db-5.3.21/src/mp/mp_sync.c +--- db-5.3.21/src/mp/mp_sync.c.trickle 2018-08-21 10:54:06.105756672 +0200 ++++ db-5.3.21/src/mp/mp_sync.c 2018-09-04 09:43:57.502992291 +0200 +@@ -965,17 +965,34 @@ __bhcmp(p1, p2) + return (0); + } + ++ + /* + * __memp_purge_dead_files -- ++ * Thin wrapper over __memp_purge_dead_and_count. Does not return any ++ * information about the number of total/dirty buffers. ++ * ++ * PUBLIC: int __memp_purge_dead_files __P((ENV *)); ++ */ ++int ++__memp_purge_dead_files(env) ++ ENV *env; ++{ ++ return __memp_purge_dead_and_count(env, NULL, NULL); ++} ++ ++/* ++ * __memp_purge_dead_and_count -- + * Remove all dead files and their buffers from the mpool. The caller + * cannot hold any lock on the dead MPOOLFILE handles, their buffers + * or their hash buckets. + * +- * PUBLIC: int __memp_purge_dead_files __P((ENV *)); ++ * PUBLIC: int __memp_purge_dead_and_count __P((ENV *, u_int32_t *, u_int32_t *)); + */ + int +-__memp_purge_dead_files(env) ++__memp_purge_dead_and_count(env, totalp, dirtyp) + ENV *env; ++ u_int32_t *totalp; ++ u_int32_t *dirtyp; + { + BH *bhp; + DB_MPOOL *dbmp; +@@ -983,7 +1000,7 @@ __memp_purge_dead_files(env) + REGINFO *infop; + MPOOL *c_mp, *mp; + MPOOLFILE *mfp; +- u_int32_t i_cache; ++ u_int32_t i_cache, dirty, total; + int ret, t_ret, h_lock; + + if (!MPOOL_ON(env)) +@@ -992,6 +1009,7 @@ __memp_purge_dead_files(env) + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ret = t_ret = h_lock = 0; ++ dirty = total = 0; + + /* + * Walk each cache's list of buffers and free all buffers whose +@@ -1000,6 +1018,7 @@ __memp_purge_dead_files(env) + for (i_cache = 0; i_cache < mp->nreg; i_cache++) { + infop = &dbmp->reginfo[i_cache]; + c_mp = infop->primary; ++ total += c_mp->pages; + + hp = R_ADDR(infop, c_mp->htab); + hp_end = &hp[c_mp->htab_buckets]; +@@ -1008,6 +1027,9 @@ __memp_purge_dead_files(env) + if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) + continue; + ++ /* Count dirty pages first as we do not wait on mutex locks */ ++ dirty += (u_int32_t)atomic_read(&hp->hash_page_dirty); ++ + /* + * Search for a dead buffer. Other places that call + * __memp_bhfree() acquire the buffer lock before the +@@ -1073,6 +1095,11 @@ __memp_purge_dead_files(env) + } + } + ++ if (dirtyp != NULL) ++ *dirtyp = dirty; ++ if (totalp != NULL) ++ *totalp = total; ++ + return (ret); + } + +diff -up db-5.3.21/src/mp/mp_trickle.c.trickle db-5.3.21/src/mp/mp_trickle.c +--- db-5.3.21/src/mp/mp_trickle.c.trickle 2018-08-21 10:54:06.105756672 +0200 ++++ db-5.3.21/src/mp/mp_trickle.c 2018-08-21 10:54:06.112756543 +0200 +@@ -56,6 +56,7 @@ __memp_trickle(env, pct, nwrotep) + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; ++ dirty = total = 0; + + if (nwrotep != NULL) + *nwrotep = 0; +@@ -67,12 +68,8 @@ __memp_trickle(env, pct, nwrotep) + return (EINVAL); + } + +- /* First we purge all dead files and their buffers. */ +- if ((ret = __memp_purge_dead_files(env)) != 0) +- return (ret); +- +- /* +- * Loop through the caches counting total/dirty buffers. ++ /* First we purge all dead files and their buffers and ++ * loop through the caches counting total/dirty buffers. + * + * XXX + * Using hash_page_dirty is our only choice at the moment, but it's not +@@ -80,12 +77,8 @@ __memp_trickle(env, pct, nwrotep) + * than one page size, as a free 512B buffer may not be equivalent to + * having a free 8KB buffer. + */ +- for (ret = 0, i = dirty = total = 0; i < mp->nreg; ++i) { +- c_mp = dbmp->reginfo[i].primary; +- total += c_mp->pages; +- __memp_stat_hash(&dbmp->reginfo[i], c_mp, &dtmp); +- dirty += dtmp; +- } ++ if ((ret = __memp_purge_dead_and_count(env, &total, &dirty)) != 0) ++ return (ret); + + /* + * If there are sufficient clean buffers, no buffers or no dirty diff --git a/SOURCES/libdb-cbd-race.patch b/SOURCES/libdb-cbd-race.patch new file mode 100644 index 0000000..ad56d06 --- /dev/null +++ b/SOURCES/libdb-cbd-race.patch @@ -0,0 +1,110 @@ +From 4ae2eb88fadc256ddf9862b2e72ed216ddbb919d Mon Sep 17 00:00:00 2001 +From: michael brey +Date: Tue, 20 May 2014 14:49:44 +0200 +Subject: [PATCH] Fix a CDB race + +Report and reproducer here: +https://community.oracle.com/thread/3514381 + +From: michael brey +To: Lubomir Rintel +Subject: Re: BDB crash +Date: Tue, 13 May 2014 09:07:45 -0600 (05/13/2014 05:07:45 PM) +Message-id: <53723541.7040203@oracle.com> + + attached are patches for each release. the 5.3.28 patch will apply on +top of 5.3.21. + +thanks +mike + +RHBZ: #1099509 +--- + src/env/env_failchk.c | 24 ++++++++++++++++++++++++ + src/mutex/mut_tas.c | 18 +++++++++++++++++- + 2 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/src/env/env_failchk.c b/src/env/env_failchk.c +index 05752f0..b09df96 100644 +--- a/src/env/env_failchk.c ++++ b/src/env/env_failchk.c +@@ -312,6 +312,7 @@ __env_in_api(env) + REGINFO *infop; + THREAD_INFO *thread; + u_int32_t i; ++ pid_t pid; + int unpin, ret; + + if ((htab = env->thr_hashtab) == NULL) +@@ -325,6 +326,7 @@ __env_in_api(env) + + for (i = 0; i < env->thr_nbucket; i++) + SH_TAILQ_FOREACH(ip, &htab[i], dbth_links, __db_thread_info) { ++ pid = ip->dbth_pid; + if (ip->dbth_state == THREAD_SLOT_NOT_IN_USE || + (ip->dbth_state == THREAD_OUT && + thread->thr_count < thread->thr_max)) +@@ -341,6 +343,28 @@ __env_in_api(env) + ip->dbth_state = THREAD_SLOT_NOT_IN_USE; + continue; + } ++ /* ++ * The above tests are not atomic, so it is possible that ++ * the process pointed by ip has changed during the tests. ++ * In particular, if the process pointed by ip when is_alive ++ * was executed terminated normally, a new process may reuse ++ * the same ip structure and change its dbth_state before the ++ * next two tests were performed. Therefore, we need to test ++ * here that all four tests above are done on the same process. ++ * If the process pointed by ip changed, all tests are invalid ++ * and can be ignored. ++ * Similarly, it's also possible for two processes racing to ++ * change the dbth_state of the same ip structure. For example, ++ * both process A and B reach the above test for the same ++ * terminated process C where C's dbth_state is THREAD_OUT. ++ * If A goes into the 'if' block and changes C's dbth_state to ++ * THREAD_SLOT_NOT_IN_USE before B checks the condition, B ++ * would incorrectly fail the test and run into this line. ++ * Therefore, we need to check C's dbth_state again and fail ++ * the db only if C's dbth_state is indeed THREAD_ACTIVE. ++ */ ++ if (ip->dbth_state != THREAD_ACTIVE || ip->dbth_pid != pid) ++ continue; + return (__db_failed(env, DB_STR("1507", + "Thread died in Berkeley DB library"), + ip->dbth_pid, ip->dbth_tid)); +diff --git a/src/mutex/mut_tas.c b/src/mutex/mut_tas.c +index 0899d23..db95030 100644 +--- a/src/mutex/mut_tas.c ++++ b/src/mutex/mut_tas.c +@@ -151,10 +151,26 @@ loop: /* Attempt to acquire the resource for N spins. */ + if (F_ISSET(dbenv, DB_ENV_FAILCHK) && + ip == NULL && dbenv->is_alive(dbenv, + mutexp->pid, mutexp->tid, 0) == 0) { ++ /* ++ * The process owing the mutex is "dead" now, but it may ++ * have already released the mutex. We need to check again ++ * by going back to the top of the loop ++ * if the mutex is still held by the "dead" process. We ++ * yield 10 us to increase the likelyhood of mutexp fields ++ * being up-to-date. Set spin so we spin one more time ++ * because no need to spin more if dead process owns mutex. ++ */ ++ if (nspins > 1) { ++ nspins = 2; ++ __os_yield(env, 0, 10); ++ continue; ++ } + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ret != 0 || +- ip->dbth_state == THREAD_FAILCHK) ++ ip->dbth_state == THREAD_FAILCHK) { ++ printf("mut_tas:172, pid: %d, flag: %d\n", mutexp->pid, mutexp->flags); + return (DB_RUNRECOVERY); ++ } + } + if (nowait) + return (DB_LOCK_NOTGRANTED); +-- +1.8.3.1 + diff --git a/SOURCES/libdb-limit-cpu.patch b/SOURCES/libdb-limit-cpu.patch new file mode 100644 index 0000000..475aa50 --- /dev/null +++ b/SOURCES/libdb-limit-cpu.patch @@ -0,0 +1,12 @@ +diff -Naurp db_old/src/os/os_cpu.c db_new/src/os/os_cpu.c +--- db_old/src/os/os_cpu.c 2012-05-11 12:57:54.000000000 -0500 ++++ db_new/src/os/os_cpu.c 2015-08-12 14:00:37.232498880 -0500 +@@ -40,6 +40,8 @@ __os_cpu_count() + long nproc; + + nproc = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nproc > 1024) ++ nproc = 1024; + return ((u_int32_t)(nproc > 1 ? nproc : 1)); + #else + return (1); diff --git a/SOURCES/libdb-multiarch.patch b/SOURCES/libdb-multiarch.patch new file mode 100644 index 0000000..f0e6ff6 --- /dev/null +++ b/SOURCES/libdb-multiarch.patch @@ -0,0 +1,12 @@ +diff -up db-5.3.15/dist/aclocal/sequence.m4.multiarch db-5.3.15/dist/aclocal/sequence.m4 +--- db-5.3.15/dist/aclocal/sequence.m4.multiarch 2010-06-25 17:50:36.000000000 +0200 ++++ db-5.3.15/dist/aclocal/sequence.m4 2011-12-20 02:00:49.000000000 +0100 +@@ -78,7 +78,7 @@ AC_DEFUN(AM_SEQUENCE_CONFIGURE, [ + fi + if test "$db_cv_build_sequence" = "yes"; then + AC_SUBST(db_seq_decl) +- db_seq_decl="typedef $db_cv_seq_type db_seq_t;"; ++ db_seq_decl="typedef int64_t db_seq_t;"; + + AC_DEFINE(HAVE_64BIT_TYPES) + AH_TEMPLATE(HAVE_64BIT_TYPES, diff --git a/SOURCES/patch.1.1 b/SOURCES/patch.1.1 new file mode 100644 index 0000000..fe3177d --- /dev/null +++ b/SOURCES/patch.1.1 @@ -0,0 +1,20 @@ +*** Makefile.orig Wed Jul 13 21:43:16 1994 +--- Makefile Wed Dec 31 19:00:00 1969 +*************** +*** 15,22 **** + + ${LIBDB}: ${OBJ1} ${OBJ2} ${OBJ3} ${OBJ4} ${OBJ5} ${MISC} + rm -f $@ +! ar cq $@ \ +! `lorder ${OBJ1} ${OBJ2} ${OBJ3} ${OBJ4} ${OBJ5} ${MISC} | tsort` + ranlib $@ + + clean: +--- 15,21 ---- + + ${LIBDB}: ${OBJ1} ${OBJ2} ${OBJ3} ${OBJ4} ${OBJ5} ${MISC} + rm -f $@ +! ar cq $@ ${OBJ1} ${OBJ2} ${OBJ3} ${OBJ4} ${OBJ5} ${MISC} + ranlib $@ + + clean: diff --git a/SOURCES/patch.1.2 b/SOURCES/patch.1.2 new file mode 100644 index 0000000..a343909 --- /dev/null +++ b/SOURCES/patch.1.2 @@ -0,0 +1,19 @@ +*** btree/bt_split.c Tue Jul 26 14:22:02 1994 +--- btree/bt_split.c Sat Jan 4 14:38:55 1997 +*************** +*** 673,679 **** + * where we decide to try and copy too much onto the left page. + * Make sure that doesn't happen. + */ +! if (skip <= off && used + nbytes >= full) { + --off; + break; + } +--- 673,679 ---- + * where we decide to try and copy too much onto the left page. + * Make sure that doesn't happen. + */ +! if (skip <= off && used + nbytes >= full || nxt == top - 1) { + --off; + break; + } diff --git a/SOURCES/patch.1.3 b/SOURCES/patch.1.3 new file mode 100644 index 0000000..5ca03df --- /dev/null +++ b/SOURCES/patch.1.3 @@ -0,0 +1,37 @@ +*** btree/bt_split.c.orig Sat Feb 8 10:14:10 1997 +--- btree/bt_split.c Sat Feb 8 10:14:51 1997 +*************** +*** 673,679 **** + * where we decide to try and copy too much onto the left page. + * Make sure that doesn't happen. + */ +! if (skip <= off && used + nbytes >= full || nxt == top - 1) { + --off; + break; + } +--- 673,680 ---- + * where we decide to try and copy too much onto the left page. + * Make sure that doesn't happen. + */ +! if (skip <= off && +! used + nbytes + sizeof(indx_t) >= full || nxt == top - 1) { + --off; + break; + } +*************** +*** 686,692 **** + memmove((char *)l + l->upper, src, nbytes); + } + +! used += nbytes; + if (used >= half) { + if (!isbigkey || bigkeycnt == 3) + break; +--- 687,693 ---- + memmove((char *)l + l->upper, src, nbytes); + } + +! used += nbytes + sizeof(indx_t); + if (used >= half) { + if (!isbigkey || bigkeycnt == 3) + break; diff --git a/SOURCES/patch.1.4 b/SOURCES/patch.1.4 new file mode 100644 index 0000000..cec5fbc --- /dev/null +++ b/SOURCES/patch.1.4 @@ -0,0 +1,22 @@ +*** btree/bt_page.c.orig Wed Jul 13 21:29:02 1994 +--- btree/bt_page.c Wed Jun 11 20:14:43 1997 +*************** +*** 65,70 **** +--- 65,71 ---- + h->prevpg = P_INVALID; + h->nextpg = t->bt_free; + t->bt_free = h->pgno; ++ F_SET(t, B_METADIRTY); + + /* Make sure the page gets written back. */ + return (mpool_put(t->bt_mp, h, MPOOL_DIRTY)); +*************** +*** 92,97 **** +--- 93,99 ---- + (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) { + *npg = t->bt_free; + t->bt_free = h->nextpg; ++ F_SET(t, B_METADIRTY); + return (h); + } + return (mpool_new(t->bt_mp, npg)); diff --git a/SPECS/libdb.spec b/SPECS/libdb.spec new file mode 100644 index 0000000..c81f443 --- /dev/null +++ b/SPECS/libdb.spec @@ -0,0 +1,690 @@ +%define __soversion_major 5 +%define __soversion %{__soversion_major}.3 +%define __tclversion 8.6 + +Summary: The Berkeley DB database library for C +Name: libdb +Version: 5.3.28 +Release: 53%{?dist} +Source0: http://download.oracle.com/berkeley-db/db-%{version}.tar.gz +Source1: http://download.oracle.com/berkeley-db/db.1.85.tar.gz +# For mt19937db.c +Source2: http://www.gnu.org/licenses/lgpl-2.1.txt +# libdb man pages generated from the 5.3.28 documentation +Source3: libdb-5.3.28-manpages.tar.gz +Patch0: libdb-multiarch.patch +# db-1.85 upstream patches +Patch10: http://www.oracle.com/technology/products/berkeley-db/db/update/1.85/patch.1.1 +Patch11: http://www.oracle.com/technology/products/berkeley-db/db/update/1.85/patch.1.2 +Patch12: http://www.oracle.com/technology/products/berkeley-db/db/update/1.85/patch.1.3 +Patch13: http://www.oracle.com/technology/products/berkeley-db/db/update/1.85/patch.1.4 +# other patches +Patch20: db-1.85-errno.patch +Patch22: db-4.6.21-1.85-compat.patch +Patch24: db-4.5.20-jni-include-dir.patch +# License clarification patch +# http://devel.trisquel.info/gitweb/?p=package-helpers.git;a=blob;f=helpers/DATA/db4.8/007-mt19937db.c_license.patch;h=1036db4d337ce4c60984380b89afcaa63b2ef88f;hb=df48d40d3544088338759e8bea2e7f832a564d48 +Patch25: 007-mt19937db.c_license.patch +# memp_stat fix provided by upstream (rhbz#1211871) +Patch27: db-5.3.21-memp_stat-upstream-fix.patch +# fix for mutexes not being released provided by upstream (rhbz#1277887) +Patch28: db-5.3.21-mutex_leak.patch +# fix for overflowing hash variable inside bundled lemon +Patch29: db-5.3.28-lemon_hash.patch +# upstream patch adding the ability to recreate libdb's environment on version mismatch +# or when libpthread.so is modified (rhbz#1394862) +Patch30: db-5.3.28-condition_variable.patch +# additional changes to the upstream patch to address rhbz#1460003 +Patch31: db-5.3.28-condition-variable-ppc.patch +# downstream patch that adds a check for rpm transaction lock in order to be able to update libdb +# FIXME: remove when able +Patch32: db-5.3.28-rpm-lock-check.patch +# downstream patch to hotfix rhbz#1464033, sent upstream +Patch33: db-5.3.28-cwd-db_config.patch +Patch34: libdb-5.3.21-region-size-check.patch +# Patch sent upstream +Patch35: checkpoint-opd-deadlock.patch +Patch36: db-5.3.28-atomic_compare_exchange.patch +# CDB race (rhbz #1099509) +Patch37: libdb-cbd-race.patch +# Limit concurrency to max 1024 CPUs (rhbz#1245410) +# A fix for the issue should be in an upstream release already +# https://community.oracle.com/message/13274780#13274780 +Patch38: libdb-limit-cpu.patch +# rhbz#1608749 Patch sent upstream +# Expects libdb-5.3.21-mutex_leak.patch applied +Patch39: libdb-5.3.21-trickle_cpu.patch +# cve-2019-2708 fixed by mmuzila +Patch40: db-5.3.28_cve-2019-2708.patch +# Downstream covscan patch +Patch41: db-5.3.28-fix-CWE-686-398.patch +Patch42: db-5.3.28-mmap-high-cpu-usage.patch + +URL: http://www.oracle.com/database/berkeley-db/ +License: BSD and LGPLv2 and Sleepycat +BuildRequires: gcc gcc-c++ +BuildRequires: perl-interpreter libtool +BuildRequires: tcl-devel >= %{__tclversion} +BuildRequires: chrpath +BuildRequires: zlib-devel +BuildRequires: make +Conflicts: filesystem < 3 + +%description +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. The Berkeley DB includes B+tree, Extended +Linear Hashing, Fixed and Variable-length record access methods, +transactions, locking, logging, shared memory caching, and database +recovery. The Berkeley DB supports C, C++, and Perl APIs. It is +used by many applications, including Python and Perl, so this should +be installed on all systems. + +%package utils +Summary: Command line tools for managing Berkeley DB databases +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description utils +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. Berkeley DB includes B+tree, Extended +Linear Hashing, Fixed and Variable-length record access methods, +transactions, locking, logging, shared memory caching, and database +recovery. DB supports C, C++ and Perl APIs. + +%package devel +Summary: C development files for the Berkeley DB library +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the header files, +libraries, and documentation for building programs which use the +Berkeley DB. + +%package devel-doc +Summary: C development documentation files for the Berkeley DB library +Requires: %{name} = %{version}-%{release} +Requires: %{name}-devel = %{version}-%{release} +BuildArch: noarch + +%description devel-doc +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the header files, +libraries, and documentation for building programs which use the +Berkeley DB. + +%package devel-static +Summary: Berkeley DB static libraries +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + +%description devel-static +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains static libraries +needed for applications that require static linking of +Berkeley DB. + +%package cxx +Summary: The Berkeley DB database library for C++ +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description cxx +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. The Berkeley DB includes B+tree, Extended +Linear Hashing, Fixed and Variable-length record access methods, +transactions, locking, logging, shared memory caching, and database +recovery. The Berkeley DB supports C, C++, and Perl APIs. It is +used by many applications, including Python and Perl, so this should +be installed on all systems. + +%package cxx-devel +Summary: The Berkeley DB database library for C++ +Requires: %{name}-cxx%{?_isa} = %{version}-%{release} +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + +%description cxx-devel +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. The Berkeley DB includes B+tree, Extended +Linear Hashing, Fixed and Variable-length record access methods, +transactions, locking, logging, shared memory caching, and database +recovery. The Berkeley DB supports C, C++, and Perl APIs. It is +used by many applications, including Python and Perl, so this should +be installed on all systems. + +%package tcl +Summary: Development files for using the Berkeley DB with tcl +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description tcl +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the libraries +for building programs which use the Berkeley DB in Tcl. + +%package tcl-devel +Summary: Development files for using the Berkeley DB with tcl +Requires: %{name}-tcl%{?_isa} = %{version}-%{release} + +%description tcl-devel +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the libraries +for building programs which use the Berkeley DB in Tcl. + +%package sql +Summary: Development files for using the Berkeley DB with sql +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description sql +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the libraries +for building programs which use the Berkeley DB in SQL. + +%package sql-devel +Summary: Development files for using the Berkeley DB with sql +Requires: %{name}-sql%{?_isa} = %{version}-%{release} + +%description sql-devel +The Berkeley Database (Berkeley DB) is a programmatic toolkit that +provides embedded database support for both traditional and +client/server applications. This package contains the libraries +for building programs which use the Berkeley DB in SQL. + +%prep +%setup -q -n db-%{version} -a 1 +cp %{SOURCE2} . +tar -xf %{SOURCE3} + +%patch0 -p1 +pushd db.1.85/PORT/linux +%patch10 -p0 +popd +pushd db.1.85 +%patch11 -p0 +%patch12 -p0 +%patch13 -p0 +%patch20 -p1 +popd + +%patch22 -p1 +%patch24 -p1 +%patch25 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 -b .cve-2019-2708 +%patch41 -p1 +%patch42 -p1 + +cd dist +./s_config +cd .. + +%build +CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" +CFLAGS="$CFLAGS -DSHAREDSTATEDIR='\"%{_sharedstatedir}\"' -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_DISABLE_DIRSYNC=1 -DSQLITE_ENABLE_FTS3=3 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 -I../../../lang/sql/sqlite/ext/fts3/" +export CFLAGS + +# Build the old db-185 libraries. +make -C db.1.85/PORT/%{_os} OORG="$CFLAGS" + +test -d dist/dist-tls || mkdir dist/dist-tls +# Static link db_dump185 with old db-185 libraries. +/bin/sh libtool --tag=CC --mode=compile %{__cc} $RPM_OPT_FLAGS -Idb.1.85/PORT/%{_os}/include -D_REENTRANT -c util/db_dump185.c -o dist/dist-tls/db_dump185.lo +/bin/sh libtool --tag=LD --mode=link %{__cc} $RPM_LD_FLAGS -o dist/dist-tls/db_dump185 dist/dist-tls/db_dump185.lo db.1.85/PORT/%{_os}/libdb.a + +# Update config files to understand aarch64 +for dir in dist lang/sql/sqlite lang/sql/jdbc lang/sql/odbc; do + cp /usr/lib/rpm/redhat/config.{guess,sub} "$dir" +done + +pushd dist/dist-tls +%define _configure ../configure +%configure -C \ + --enable-compat185 --enable-dump185 \ + --enable-shared --enable-static \ + --enable-tcl --with-tcl=%{_libdir} \ + --enable-cxx --enable-sql \ + --enable-test \ + --disable-rpath \ + --with-cryptography=no \ + --with-tcl=%{_libdir}/tcl%{__tclversion} + +# Remove libtool predep_objects and postdep_objects wonkiness so that +# building without -nostdlib doesn't include them twice. Because we +# already link with g++, weird stuff happens if you don't let the +# compiler handle this. +perl -pi -e 's/^predep_objects=".*$/predep_objects=""/' libtool +perl -pi -e 's/^postdep_objects=".*$/postdep_objects=""/' libtool +perl -pi -e 's/-shared -nostdlib/-shared/' libtool + +%make_build + +# Run some quick subsystem checks +echo "source ../../test/tcl/test.tcl; r env; r mut; r memp" | tclsh +popd + +%install +rm -rf ${RPM_BUILD_ROOT} +mkdir -p ${RPM_BUILD_ROOT}%{_includedir} +mkdir -p ${RPM_BUILD_ROOT}%{_libdir} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man1 + +%make_install STRIP=/bin/true -C dist/dist-tls + +# XXX Nuke non-versioned archives and symlinks +rm -f ${RPM_BUILD_ROOT}%{_libdir}/{libdb.a,libdb_cxx.a,libdb_tcl.a,libdb_sql.a} + +chmod +x ${RPM_BUILD_ROOT}%{_libdir}/*.so* + +# Move the header files to a subdirectory, in case we're deploying on a +# system with multiple versions of DB installed. +mkdir -p ${RPM_BUILD_ROOT}%{_includedir}/%{name} +mv ${RPM_BUILD_ROOT}%{_includedir}/*.h ${RPM_BUILD_ROOT}%{_includedir}/%{name}/ + +# Create symlinks to includes so that "use and link with -ldb" works. +for i in db.h db_cxx.h db_185.h; do + ln -s %{name}/$i ${RPM_BUILD_ROOT}%{_includedir} +done + +# Eliminate installed doco +rm -rf ${RPM_BUILD_ROOT}%{_prefix}/docs + +# XXX Avoid Permission denied. strip when building as non-root. +chmod u+w ${RPM_BUILD_ROOT}%{_bindir} ${RPM_BUILD_ROOT}%{_bindir}/* + +# remove unneeded .la files (#225675) +rm -f ${RPM_BUILD_ROOT}%{_libdir}/*.la + +# remove RPATHs +chrpath -d ${RPM_BUILD_ROOT}%{_libdir}/*.so ${RPM_BUILD_ROOT}%{_bindir}/* + +# unify documentation and examples, remove stuff we don't need +rm -rf docs/csharp +rm -rf examples/csharp +rm -rf docs/installation +mv examples docs +mv man/* ${RPM_BUILD_ROOT}%{_mandir}/man1 + +%ldconfig_scriptlets +%ldconfig_scriptlets cxx +%ldconfig_scriptlets sql +%ldconfig_scriptlets tcl + +%files +%license LICENSE lgpl-2.1.txt +%doc README +%{_libdir}/libdb-%{__soversion}.so +%{_libdir}/libdb-%{__soversion_major}.so + +%files devel +%{_libdir}/libdb.so +%dir %{_includedir}/%{name} +%{_includedir}/%{name}/db.h +%{_includedir}/%{name}/db_185.h +%{_includedir}/db.h +%{_includedir}/db_185.h + +%files devel-doc +%doc docs/* + +%files devel-static +%{_libdir}/libdb-%{__soversion}.a +%{_libdir}/libdb_cxx-%{__soversion}.a +%{_libdir}/libdb_tcl-%{__soversion}.a +%{_libdir}/libdb_sql-%{__soversion}.a + +%files utils +%{_bindir}/db*_archive +%{_bindir}/db*_checkpoint +%{_bindir}/db*_deadlock +%{_bindir}/db*_dump* +%{_bindir}/db*_hotbackup +%{_bindir}/db*_load +%{_bindir}/db*_printlog +%{_bindir}/db*_recover +%{_bindir}/db*_replicate +%{_bindir}/db*_stat +%{_bindir}/db*_upgrade +%{_bindir}/db*_verify +%{_bindir}/db*_tuner +%{_mandir}/man1/db_* + +%files cxx +%{_libdir}/libdb_cxx-%{__soversion}.so +%{_libdir}/libdb_cxx-%{__soversion_major}.so + +%files cxx-devel +%{_includedir}/%{name}/db_cxx.h +%{_includedir}/db_cxx.h +%{_libdir}/libdb_cxx.so + +%files tcl +%{_libdir}/libdb_tcl-%{__soversion}.so +%{_libdir}/libdb_tcl-%{__soversion_major}.so + +%files tcl-devel +%{_libdir}/libdb_tcl.so + +%files sql +%{_libdir}/libdb_sql-%{__soversion}.so +%{_libdir}/libdb_sql-%{__soversion_major}.so + +%files sql-devel +%{_bindir}/dbsql +%{_libdir}/libdb_sql.so +%{_includedir}/%{name}/dbsql.h + +%changelog +* Wed Nov 24 2021 Filip Januš - 5.3.28-53 +- Add missing RPM_LD_FLAGS for db_dump185 +- Resolves: #2026417 + +* Mon Sep 13 2021 Filip Januš - 5.3.28-52 +- Bad order of sys calls cause high CPU usage +- Related: #2002186 +- Patch no. 42 was added + +* Mon Aug 09 2021 Mohan Boddu - 5.3.28-51 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Thu Aug 05 2021 Filip Januš - 5.3.28-50 +- fix static analyzer issues CWE-686-398 +- Resolves: #1938760 + +* Mon Jul 12 2021 Filip Januš - 5.3.28-49 +- Rebuild due to glibc +- Resolves: #1980975 + +* Fri Jun 25 2021 Filip Januš - 5.3.28-48 +- Disable crypto support +- Resolves: #1974657 + +* Fri Apr 16 2021 Mohan Boddu - 5.3.28-47 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Tue Jan 26 2021 Fedora Release Engineering - 5.3.28-46 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Dec 02 2020 Matej Mužila 5.3.28-45 +- Resolves: CVE-2019-2708 (#1853243) + +* Tue Jul 28 2020 Fedora Release Engineering - 5.3.28-44 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 21 2020 Tom Stellard - 5.3.28-43 +- Use make macros +- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro + +* Tue Jul 14 2020 Ondrej Dubaj - 5.3.28-42 +- Remove java subpackage due to jdk-11 (#1846398) + +* Sat Jul 11 2020 Jiri Vanek - 5.3.28-41 +- Rebuilt for JDK-11, see https://fedoraproject.org/wiki/Changes/Java11 + +* Wed Jan 29 2020 Fedora Release Engineering - 5.3.28-40 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Aug 22 2019 Petr Kubat 5.3.28-39 +- Set correct tcl-devel version for BuildRequires (#1712532) + +* Thu Jul 25 2019 Fedora Release Engineering - 5.3.28-38 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Fri Feb 01 2019 Fedora Release Engineering - 5.3.28-37 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jan 30 2019 Petr Kubat 5.3.28-36 +- Optimize trickle thread CPU usage (#1608749) + +* Wed Jan 16 2019 Petr Kubat - 5.3.28-35 +- Add patch to workaround issues on large systems (>1024 CPU) + Resolves: #1245410 + +* Wed Sep 05 2018 Petr Kubat - 5.3.28-34 +- Add patch for CDB race issue (#1099509) + +* Tue Jul 24 2018 Petr Kubat - 5.3.28-33 +- Add BuildRequires for gcc and gcc-c++ (#1604566) + +* Fri Jul 13 2018 Fedora Release Engineering - 5.3.28-32 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Wed May 23 2018 Petr Kubat - 5.3.28-31 +- Rename __atomic_compare_exchange to not clash with gcc built-in + +* Wed Feb 07 2018 Fedora Release Engineering - 5.3.28-30 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Oct 31 2017 Petr Kubat 5.3.28-29 +- Fix deadlocks when reading/writing off-page duplicate tree (#1349779) + +* Tue Oct 24 2017 Petr Kubat 5.3.28-28 +- Run a number of quick subsystem checks on build + +* Thu Sep 07 2017 Petr Kubat 5.3.28-27 +- Fail properly when encountering removed or 0-byte regions (#1471011) + +* Thu Aug 03 2017 Fedora Release Engineering - 5.3.28-26 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 5.3.28-25 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Mon Jun 26 2017 Petr Kubat - 5.3.28-24 +- Fix some defects found by covscan + +* Mon Jun 26 2017 Petr Kubat - 5.3.28-23 +- Try looking at env lock via /proc/locks during env_attach (#1460003) +- Check rpm's transaction lock via /proc/locks +- Do not access DB_CONFIG when db_home is not set (#1464033) + +* Tue Jun 13 2017 Petr Kubat - 5.3.28-23 +- Reintroduce patches removed in 5.3.28-22 +- Modify upstream patch to fail on pthread version mismatch (#1460003) + +* Fri Jun 09 2017 Adam Williamson - 5.3.28-22 +- Drop rhbz#1394862 patches again, DB corruption still being reported + +* Thu Jun 01 2017 Petr Kubat - 5.3.28-21 +- Reintroduce upstream patch for rhbz#1394862 +- Do not rebuild rpm's environment during a rpm transaction + +* Fri May 26 2017 Adam Williamson - 5.3.28-20 +- Drop rhbz#1394862 patch for now, it has serious issues + +* Wed May 24 2017 Petr Kubat - 5.3.28-19 +- Fix some issues present in the upstream patch for rhbz#1394862 + +* Tue May 23 2017 Adam Williamson - 5.3.28-18 +- Fix issue causing RPM to hang when glibc/libpthread change (#1394862) + +* Wed Feb 22 2017 Petr Kubat - 5.3.28-17 +- Fix overflowing integer in bundled-in lemon.c (#1423842) + +* Fri Feb 10 2017 Fedora Release Engineering - 5.3.28-17 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Dec 08 2016 Petr Kubat 5.3.28-16 +- Add man pages for libdb-utils + +* Mon Nov 14 2016 Petr Kubat 5.3.28-15 +- Fix mutexes not being released properly (#1272680) + +* Thu Feb 04 2016 Fedora Release Engineering - 5.3.28-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Wed Jun 17 2015 Fedora Release Engineering - 5.3.28-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue May 19 2015 Jan Stanek - 5.3.28-12 +- Add upstream patch for a memp_stat issue. +- Resolves: rhbz#1211871 + +* Sat May 02 2015 Kalev Lember - 5.3.28-11 +- Rebuilt for GCC 5 C++11 ABI change + +* Sat Feb 21 2015 Till Maas - 5.3.28-10 +- Rebuilt for Fedora 23 Change + https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code + +* Sun Aug 17 2014 Fedora Release Engineering - 5.3.28-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Thu Jul 17 2014 Tom Callaway - 5.3.28-8 +- fix license handling + +* Mon Jul 14 2014 Jakub Čajka - 5.3.28-7 +- Fixed build with Java 8 + +* Tue Jun 10 2014 Jan Stanek - 5.3.28-6 +- Fixed search path for new tcl, new BuildRequires for zlib + +* Sat Jun 07 2014 Fedora Release Engineering - 5.3.28-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Sat Feb 22 2014 Peter Robinson 5.3.28-4 +- Add some of the previous aarch64 bits back as the sub configure don't use the macro + +* Sun Jan 26 2014 Peter Robinson 5.3.28-3 +- Fix configure macro usage for better aarch64 build fix + +* Wed Nov 06 2013 Jan Stanek - 5.3.28-2 +- Updated config files to allow build on aarch64 (#1022970) + +* Tue Oct 08 2013 Jan Stanek - 5.3.28-1 +- Added Sleepycat to the license list (#1013841) +- Updated to 5.3.28 (#1013233) + +* Sat Aug 03 2013 Fedora Release Engineering - 5.3.21-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Tue May 28 2013 Tom Callaway - 5.3.21-12 +- add copy of lgpl-2.1.txt + +* Thu May 16 2013 Jan Stanek - 5.3.21-11 +- Fix missing debuginfo issue for utils subpackage + +* Thu May 9 2013 Tom Callaway - 5.3.21-10 +- add license clarification fix + +* Wed Apr 03 2013 Jan Stanek 5.3.21-9 +- Added sqlite compability CFLAGS (#788496) + +* Wed Mar 27 2013 Jan Stanek 5.3.21-8 +- Cleaning the specfile - removed gcc-java dependecy other way + +* Wed Mar 27 2013 Jan Stanek 5.3.21-7 +- Removed dependency on obsolete gcc-java package (#927742) + +* Thu Mar 7 2013 Jindrich Novy 5.3.21-6 +- add LGPLv2+ and remove Sleepycat in license tag (#886838) + +* Thu Feb 14 2013 Fedora Release Engineering - 5.3.21-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Tue Nov 27 2012 Tom Callaway - 5.3.21-4 +- fix license tag + +* Thu Jul 19 2012 Fedora Release Engineering - 5.3.21-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Jul 14 2012 Peter Robinson - 5.3.21-2 +- Specify tag for libtool (fixes FTBFS # 838334 ) + +* Thu Jul 5 2012 Jindrich Novy 5.3.21-1 +- update to 5.3.21 +http://download.oracle.com/otndocs/products/berkeleydb/html/changelog_5_3.html + +* Tue Jul 3 2012 Jindrich Novy 5.3.15-5 +- move C++ header files to cxx-devel + +* Tue Jul 3 2012 Jindrich Novy 5.3.15-4 +- fix -devel packages dependencies yet more (#832225) + +* Sun May 6 2012 Jindrich Novy 5.3.15-3 +- package -devel packages correctly + +* Sat Apr 21 2012 Jindrich Novy 5.3.15-2 +- fix multiarch conflict in libdb-devel (#812901) +- remove unneeded dos2unix BR + +* Thu Mar 15 2012 Jindrich Novy 5.3.15-1 +- update to 5.3.15 + http://download.oracle.com/otndocs/products/berkeleydb/html/changelog_5_3.html + +* Fri Feb 17 2012 Deepak Bhole 5.2.36-5 +- Resolves rhbz#794472 +- Patch from Omair Majid to remove explicit Java 6 req. + +* Wed Jan 25 2012 Harald Hoyer 5.2.36-4 +- add filesystem guard + +* Wed Jan 25 2012 Harald Hoyer 5.2.36-3 +- install everything in /usr + https://fedoraproject.org/wiki/Features/UsrMove + +* Fri Jan 13 2012 Fedora Release Engineering - 5.2.36-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Jun 15 2011 Jindrich Novy 5.2.36-1 +- update to 5.2.36, + http://download.oracle.com/otndocs/products/berkeleydb/html/changelog_5_2.html#id3647664 + +* Wed Jun 15 2011 Jindrich Novy 5.2.28-2 +- move development documentation to devel-doc subpackage (#705386) + +* Tue Jun 14 2011 Jindrich Novy 5.2.28-1 +- update to 5.2.28 + +* Mon Feb 07 2011 Fedora Release Engineering - 5.1.25-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Feb 3 2011 Jindrich Novy 5.1.25-1 +- update to 5.1.25 + +* Wed Sep 29 2010 jkeating - 5.1.19-2 +- Rebuilt for gcc bug 634757 + +* Fri Sep 10 2010 Jindrich Novy 5.1.19-1 +- update to 5.1.19 +- rename -devel-static to -static subpackage (#617800) +- build java on all arches + +* Wed Jul 7 2010 Jindrich Novy 5.0.26-1 +- update to 5.0.26 +- drop BR: ed + +* Thu Jun 17 2010 Jindrich Novy 5.0.21-2 +- add Requires: libdb-cxx to libdb-devel + +* Wed Apr 21 2010 Jindrich Novy 5.0.21-1 +- initial build + +* Thu Apr 15 2010 Jindrich Novy 5.0.21-0.2 +- remove C# documentation +- disable/remove rpath +- fix description +- tighten dependencies +- run ldconfig for cxx and sql subpackages + +* Fri Apr 9 2010 Jindrich Novy 5.0.21-0.1 +- enable sql +- package 5.0.21