From 172c87fd39047439529e0f0c707df27b6887ecf9 Mon Sep 17 00:00:00 2001 From: Pierre Rogier Date: Wed, 11 Sep 2024 16:36:52 +0200 Subject: [PATCH 1/4] Issue 6430 - implement read-only bdb --- Makefile.am | 68 +- .../slapd/back-ldbm/db-bdb/bdb_bdbreader_db.h | 287 ++++++ .../back-ldbm/db-bdb/bdb_bdbreader_glue.c | 491 ++++++++++ .../slapd/back-ldbm/db-bdb/bdb_layer.h | 5 + ldap/servers/slapd/back-ldbm/dbimpl.c | 8 + ldap/servers/slapd/back-ldbm/dblayer.c | 17 +- lib/librobdb/COPYING | 8 + lib/librobdb/COPYING.RPM | 848 ++++++++++++++++++ lib/librobdb/README.md | 26 + lib/librobdb/lib/bdb_ro.c | 713 +++++++++++++++ lib/librobdb/lib/robdb.h | 51 ++ lib/librobdb/robdb.spec | 64 ++ lib/librobdb/tests/test.c | 168 ++++ lib/librobdb/tests/test.db | Bin 0 -> 24576 bytes m4/db.m4 | 42 +- rpm.mk | 34 +- rpm/389-ds-base.spec.in | 126 ++- 17 files changed, 2899 insertions(+), 57 deletions(-) create mode 100644 ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_db.h create mode 100644 ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c create mode 100644 lib/librobdb/COPYING create mode 100644 lib/librobdb/COPYING.RPM create mode 100644 lib/librobdb/README.md create mode 100644 lib/librobdb/lib/bdb_ro.c create mode 100644 lib/librobdb/lib/robdb.h create mode 100644 lib/librobdb/robdb.spec create mode 100644 lib/librobdb/tests/test.c create mode 100644 lib/librobdb/tests/test.db diff --git a/Makefile.am b/Makefile.am index 608c18041d..063439aa81 100644 --- a/Makefile.am +++ b/Makefile.am @@ -99,6 +99,9 @@ else DS_DEFINES = -DBUILD_NUM=$(BUILDNUM) -DVENDOR="\"$(vendor)\"" -DBRAND="\"$(brand)\"" -DCAPBRAND="\"$(capbrand)\"" \ -UPACKAGE_VERSION -UPACKAGE_TARNAME -UPACKAGE_STRING -UPACKAGE_BUGREPORT endif +if WITH_LIBBDB_RO +DS_DEFINES += -DWITH_LIBBDB_RO=1 +endif DS_INCLUDES = -I$(srcdir)/ldap/include -I$(srcdir)/ldap/servers/slapd -I$(srcdir)/include -I. @@ -184,11 +187,15 @@ endif ldaplib = @ldaplib@ ldaplib_defs = @ldaplib_defs@ +if WITH_LIBBDB_RO +DB_LINK = @db_lib@ -llmdb +else if BUNDLE_LIBDB DB_LINK = -llmdb else DB_LINK = @db_lib@ -ldb-@db_libver@ -llmdb endif +endif DB_INC = @db_inc@ DB_IMPL = libback-ldbm.la SASL_LINK = $(SASL_LIBS) @@ -325,7 +332,7 @@ bin_PROGRAMS = dbscan \ # based on defines # ---------------------------------------------------------------------------------------- -server_LTLIBRARIES = libslapd.la libldaputil.la libns-dshttpd.la librewriters.la +server_LTLIBRARIES = libslapd.la libldaputil.la libns-dshttpd.la librewriters.la librobdb.la lib_LTLIBRARIES = libsvrcore.la @@ -1193,19 +1200,25 @@ libslapd_la_LDFLAGS = $(AM_LDFLAGS) $(SLAPD_LDFLAGS) # libback-bdb #------------------------ DB_BDB_SRCS = \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_config.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_instance_config.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_verify.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_layer.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_misc.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_perfctrs.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_upgrade.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_version.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_monitor.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_ldif2db.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_import.c \ - ldap/servers/slapd/back-ldbm/db-bdb/bdb_import_threads.c - + @db_bdb_srcdir@/bdb_config.c \ + @db_bdb_srcdir@/bdb_instance_config.c \ + @db_bdb_srcdir@/bdb_verify.c \ + @db_bdb_srcdir@/bdb_layer.c \ + @db_bdb_srcdir@/bdb_misc.c \ + @db_bdb_srcdir@/bdb_perfctrs.c \ + @db_bdb_srcdir@/bdb_upgrade.c \ + @db_bdb_srcdir@/bdb_version.c \ + @db_bdb_srcdir@/bdb_monitor.c \ + @db_bdb_srcdir@/bdb_ldif2db.c \ + @db_bdb_srcdir@/bdb_import.c \ + @db_bdb_srcdir@/bdb_import_threads.c + + +if WITH_LIBBDB_RO + # db-bdb sources are compiled within libback-ldbm.so and linked to librobdb + DB_BDB_SRCS += @db_bdb_srcdir@/bdb_bdbreader_glue.c + DB_BDB_WITHIN_BACKLDBM = $(DB_BDB_SRCS) +else if BUNDLE_LIBDB # db-bdb sources are compiled within libback-bdb.so DB_BDB_WITHIN_BACKLDBM = @@ -1219,6 +1232,20 @@ else # db-bdb sources are compiled within libback-ldbm.so DB_BDB_WITHIN_BACKLDBM = $(DB_BDB_SRCS) endif +endif + +clean-bdb-ro-src: + /bin/rm -f $(DB_BDB_RO_BUILT_SRCS) + +build-src: $(BUILT_SOURCES) +echo-src: + @echo V2 @db_bdbro_srcdir@ + @echo V3 @db_bdb_srcdir@ + @echo V1 $(patsubst %-ro/,%,$(dir $(DB_BDB_RO_BUILT_SRCS))) + @echo V4 $(DB_BDB_RO_BUILT_SRCS) + @echo V5 $(DB_BDB_WITHIN_BACKLDBM) + @echo V6 $(libback_ldbm_la_SOURCES) + #------------------------ # libback-ldbm @@ -1300,6 +1327,19 @@ libback_ldbm_la_DEPENDENCIES = libslapd.la libback_ldbm_la_LIBADD = libslapd.la $(DB_LINK) $(LDAPSDK_LINK) $(NSPR_LINK) libback_ldbm_la_LDFLAGS = -avoid-version +if WITH_LIBBDB_RO +libback_ldbm_la_LIBADD += librobdb.la +libback_ldbm_la_DEPENDENCIES += librobdb.la + +#------------------------ +# librobdb +#------------------------ +librobdb_la_SOURCES = lib/librobdb/lib/bdb_ro.c +librobdb_la_CPPFLAGS = $(AM_CPPFLAGS) $(DB_INC) +librobdb_la_LDFLAGS = -avoid-version +librobdb_la_LIBADD = +endif + #------------------------ # libacctpolicy-plugin #------------------------ diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_db.h b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_db.h new file mode 100644 index 0000000000..30e978f866 --- /dev/null +++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_db.h @@ -0,0 +1,287 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright (C) 2024 Red Hat, Inc. + * All rights reserved. + * + * License: GPL (version 3 or any later version). + * See LICENSE for details. + * END COPYRIGHT BLOCK **/ + +/* + * This file provides the part of the Berkeley Datatabase 5.3 API + * definition that are refered within 389-ds-base project + */ + +#ifndef DB_H_ +#define DB_H_ + +/* Needed for configure */ +#define DB_VERSION_MAJOR 5 +#define DB_VERSION_MINOR 3 +#define DB_VERSION_PATCH 280 + + +#define DB_INIT_MPOOL 0x000001 +#define DB_INIT_TXN 0x000002 +#define DB_INIT_LOG 0x000004 +#define DB_INIT_LOCK 0x000008 +#define DB_REGION_INIT 0x000010 +#define DB_FREE_SPACE 0x000020 +#define DB_FREELIST_ONLY 0x000040 +#define DB_TXN_NOWAIT 0x000080 +#define DB_ARCH_ABS 0x000100 +#define DB_ARCH_LOG 0x000200 +#define DB_RDONLY 0x000400 +#define DB_STAT_CLEAR 0x000800 + + + +#define DB_DUP 0x000100 +#define DB_DUPSORT 0x000200 +#define DB_RECNUM 0x000400 +#define DB_FORCE 0x000800 +#define DB_SYSTEM_MEM 0x001000 +#define DB_THREAD 0x002000 +#define DB_CREATE 0x004000 +#define DB_PRIVATE 0x008000 +#define DB_MULTIPLE_KEY 0x010000 +#define DB_MULTIPLE 0x020000 +#define DB_RMW 0x040000 +#define DB_RECOVER 0x080000 +#define DB_TXN_WRITE_NOSYNC 0x100000 +#define DB_AUTO_COMMIT 0x200000 +#define DB_RECOVER_FATAL 0x400000 +#define DB_LOCKDOWN 0x800000 +#define DB_TRUNCATE 0x1000000 +#define XDB_RECOVER 0x000000 + +enum { + DB_FIRST = 1, + DB_CURRENT, + DB_GET_BOTH, + DB_GET_BOTH_RANGE, + DB_GET_RECNO, + DB_LAST, + DB_NEXT, + DB_NEXT_DUP, + DB_NEXT_NODUP, + DB_NODUPDATA, + DB_PREV, + DB_SET, + DB_SET_RANGE, + DB_SET_RECNO, + DB_UNKNOWN, + +}; + + + +#define OPEN_FLAGS_CLOSED 0x58585858 +#define OPEN_FLAGS_OPEN 0xdbdbdbdb + +#define DB_DBT_USERMEM 1 +#define DB_DBT_MALLOC 2 +#define DB_DBT_REALLOC 4 + +#define DB_MULTIPLE_INIT(pointer, dbt) +#define DB_MULTIPLE_NEXT(pointer, dbt, retdata, retdlen) +#define DB_MULTIPLE_KEY_NEXT(pointer, dbt, retkey, retklen, retdata, retdlen) + +typedef enum { + DB_SUCCESS, + DB_NOTFOUND, /* Should be 1 because btree_next returns 1 when there are no more records */ + DB_BUFFER_SMALL, + DB_KEYEXIST, + DB_RUNRECOVERY, + DB_NOTSUPPORTED, + DB_LOCK_DEADLOCK, + DB_OSERROR, +} db_error_t; + +enum { + DB_LOCK_DEFAULT, + DB_LOCK_NORUN, + DB_VERB_DEADLOCK, + DB_VERB_RECOVERY, + DB_VERB_WAITSFOR, + DB_LOCK_YOUNGEST=9, +}; + +typedef struct db DB; +typedef struct db_env DB_ENV; +typedef struct db_txn DB_TXN; +typedef struct db_cursor DBC; + +typedef enum { + DB_BTREE, + DB_HASH, + DB_RECNO, +} DBTYPE; + +typedef struct { + int compact_pages_free; +} DB_COMPACT; + +typedef struct { + int st_nactive; + int st_ncommits; + int st_naborts; + int st_region_wait; +} DB_TXN_STAT; + +typedef struct { + int st_maxnlocks; + int st_ndeadlocks; + int st_nlockers; + int st_region_wait; + int st_w_bytes; + int st_wc_bytes; + int st_wc_mbytes; + int st_w_mbytes; + +} DB_LOG_STAT; + +typedef struct { + int st_bytes; + int st_cache_hit; + int st_cache_miss; + int st_gbytes; + int st_hash_buckets; + int st_hash_longest; + int st_hash_searches; + int st_page_create; + int st_page_in; + int st_page_out; + int st_ro_evict; + int st_rw_evict; + int st_page_dirty; + int st_pagesize; + int st_page_clean; + int st_page_trickle; + int st_hash_examined; + int st_region_wait; + + +} DB_MPOOL_STAT; + +typedef struct { + int bt_ndata; +} DB_BTREE_STAT; + +typedef struct { + int st_nlocks; + int st_maxlocks; + int st_region_wait; + int st_ndeadlocks; + int st_maxnlocks; + int st_nlockers; + int st_lock_wait; + int st_nobjects; + int st_maxnobjects; + int st_nrequests; + +} DB_LOCK_STAT; + +typedef struct { + char *file_name; + int st_page_in; + int st_page_out; + int st_cache_hit; + int st_cache_miss; +} DB_MPOOL_FSTAT; + +typedef struct dbt { + u_int32_t flags; + u_int32_t size; + u_int32_t ulen; + void *data; +} DBT; + + +struct db_cursor { + DB *dbp; + int (*c_close)(DBC *); + int (*c_del)(DBC *, u_int32_t); + int (*c_get)(DBC *, DBT*, DBT*, u_int32_t); + int (*c_put)(DBC *, DBT*, DBT*, u_int32_t); + int (*c_count)(DBC *, void *, u_int32_t); + /* fields only used by the implementation */ + void *impl; +}; + +struct db_txn { + int (*id)(DB_TXN*); + int (*commit)(DB_TXN*, u_int32_t); + int (*abort)(DB_TXN*); +}; + +struct db_env { + int (*close)(DB_ENV*, int); + int (*lock_detect)(DB_ENV*, int, int, int*); + int (*open)(DB_ENV*, const char*, int, int); + int (*remove)(DB_ENV *, const char *, u_int32_t); + int (*set_flags)(DB_ENV*, u_int32_t, u_int32_t); + int (*set_verbose)(DB_ENV *, u_int32_t, int); + int (*txn_checkpoint)(const DB_ENV *, u_int32_t , u_int32_t , u_int32_t); + int (*txn_begin)(DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t); + void (*get_open_flags)(DB_ENV*, u_int32_t*); + void (*mutex_set_tas_spins)(DB_ENV *, u_int32_t); + void (*set_alloc)(DB_ENV *, void *, void *, void*); + void (*set_cachesize)(DB_ENV *, u_int32_t , u_int32_t , int); + void (*set_data_dir)(DB_ENV *, const char *); + void (*set_errcall)(DB_ENV *, void (*)(const DB_ENV *, const char *, const char *)); + void (*set_errpfx)(DB_ENV *, const char *); + void (*set_lg_bsize)(DB_ENV *, long); + void (*set_lg_dir)(DB_ENV *, const char*); + void (*set_lg_max)(DB_ENV *, u_int32_t); + void (*set_lg_regionmax)(DB_ENV *, u_int32_t); + void (*set_lk_max_lockers)(DB_ENV *, u_int32_t); + void (*set_lk_max_locks)(DB_ENV *, u_int32_t); + void (*set_lk_max_objects)(DB_ENV *, u_int32_t); + void (*set_shm_key)(DB_ENV *, long); + void (*set_tx_max)(DB_ENV *, u_int32_t); + void (*log_flush)(DB_ENV *, u_int32_t); + int (*lock_stat)(DB_ENV *, DB_LOCK_STAT**, u_int32_t); + int (*log_archive)(DB_ENV *, void*, u_int32_t); + int (*memp_stat)(DB_ENV *, void*, void *, u_int32_t); + int (*memp_trickle)(DB_ENV *, u_int32_t, int*); + int (*dbrename)(DB_ENV *, DB_TXN *, const char *, const char *, const char *, u_int32_t); + int (*stat)(DB_ENV *, DB_TXN *, void *, u_int32_t); + int (*log_stat)(DB_ENV *, DB_LOG_STAT **, u_int32_t); + int (*txn_stat)(DB_ENV *, DB_TXN_STAT **, u_int32_t); + /* fields only used by the implementation */ + char *db_home; +}; + +struct db { + int (*close)(DB*, u_int32_t); + int (*compact)(DB*, DB_TXN*, DBT*, DBT*, void *, u_int32_t, DBT*); + int (*cursor)(DB*, DB_TXN*, DBC**, u_int32_t); + int (*del)(DB*, DB_TXN*, DBT*, u_int32_t); + int (*get)(DB*, DB_TXN*, DBT*, DBT*, u_int32_t); + int (*get_type)(DB *, DBTYPE *); + int (*open)(DB*, DB_TXN*, const char*, const char *, DBTYPE, u_int32_t, int); + int (*put)(DB*, DB_TXN*, DBT*, DBT*, u_int32_t); + int (*remove)(DB*, const char*, const char*, u_int32_t); + int (*rename)(DB*, const char*, const char*, const char*, u_int32_t); + int (*set_bt_compare)(DB*, int (*)(DB *, const DBT *, const DBT *)); + int (*set_dup_compare)(DB*, int (*)(DB *, const DBT *, const DBT *)); + int (*set_flags)(DB*, u_int32_t); + int (*set_pagesize)(DB *, u_int32_t); + int (*stat)(DB *, DB_TXN *, void *, u_int32_t); + int (*verify)(DB *, const char *, const char *, FILE *, u_int32_t); + void *app_private; + u_int32_t open_flags; + char *fname; + int pgsize; + /* fields only used by the implementation */ + void *impl; + DB_ENV *env; + DBC *cur; +}; + +char * db_version(int *major, int *minor, int *patch); +int db_env_create(DB_ENV **, u_int32_t); +int db_create(DB **, DB_ENV *, u_int32_t); +char *db_strerror(int); + +#endif /* DB_H_ */ diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c new file mode 100644 index 0000000000..539bb9d73a --- /dev/null +++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c @@ -0,0 +1,491 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright (C) 2024 Red Hat, Inc. + * All rights reserved. + * + * License: GPL (version 3 or any later version). + * See LICENSE for details. + * END COPYRIGHT BLOCK **/ + +#include "bdb_layer.h" +#include + +#define DEBUG 1 + +/* + * This file contains the stub that transform usual bdb API (limited to the function 389-ds needs to export a db and a changelog + * to bdb_ro callbacks + */ + +#undef slapi_log_err + +#define LOGK(k) (((k)&&(k)->data && (k)->size) ? (k)->data : "") +#define LOGN(v, names) (((v)> sizeof names/sizeof names[0]) ? "Unexpected value" : names[v]) + +int db_cursor(DB *db, DB_TXN *txnid, DBC **cursorp, u_int32_t flags); +int dbc_close(DBC *dbc); + +void slapi_log_err(int loglvl, char *module, char *msg, ...) { +#ifdef DEBUG + static FILE *fd = NULL; + va_list ap; + va_start(ap, msg); + if (fd == NULL) { + fd = fopen("/tmp/mylog", "w"); + } + fprintf(fd, "[%s]:%d ", module, loglvl); + vfprintf(fd, msg, ap); + fflush(fd); +#endif +} + +/* + * Dump a memory buffer in hexa and ascii in error log + * + * addr - The memory buffer address. + * len - The memory buffer lenght. + */ +void +hexadump(char *msg, const void *addr, size_t offset, size_t len) +{ +#ifdef DEBUG +#define HEXADUMP_TAB 4 +/* 4 characters per bytes: 2 hexa digits, 1 space and the ascii */ +#define HEXADUMP_BUF_SIZE (4*16+HEXADUMP_TAB) + char hexdigit[] = "0123456789ABCDEF"; + + const unsigned char *pt = addr; + char buff[HEXADUMP_BUF_SIZE+1]; + memset (buff, ' ', HEXADUMP_BUF_SIZE); + buff[HEXADUMP_BUF_SIZE] = '\0'; + while (len > 0) { + int dpl; + for (dpl = 0; dpl < 16 && len>0; dpl++, len--) { + buff[3*dpl] = hexdigit[((*pt) >> 4) & 0xf]; + buff[3*dpl+1] = hexdigit[(*pt) & 0xf]; + buff[3*16+HEXADUMP_TAB+dpl] = (*pt>=0x20 && *pt<0x7f) ? *pt : '.'; + pt++; + } + for (;dpl < 16; dpl++) { + buff[3*dpl] = ' '; + buff[3*dpl+1] = ' '; + buff[3*16+HEXADUMP_TAB+dpl] = ' '; + } + slapi_log_err(0, msg, "[0x%08lx] %s\n", offset, buff); + offset += 16; + } +#endif +} + +char *db_version(int *major, int *minor, int *patch) +{ + static char version[200]; + sprintf(version, "Read-Only Berkeley Database Stub %d.%d.%d", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH); + if (major != NULL) { + *major = DB_VERSION_MAJOR; + } + if (minor != NULL) { + *minor = DB_VERSION_MINOR; + } + if (patch != NULL) { + *patch = DB_VERSION_PATCH; + } + return version; +} + +int nothing() +{ + return DB_SUCCESS; +} + +/* + * Define libbdbreader callbacks + * Note: slapi_ch_calloc, slapi_ch_malloc, slapi_ch_realloc + * are not directly used because their prototype is + * slightl + * slapi_ch_calloc are slithly different + */ +void* bdbreader_calloc(size_t nbelmt, size_t size) +{ + return slapi_ch_calloc(nbelmt, size); +} + +/* + * Redefines all the callback because bdbreader_malloc and + * slapi_ch_malloc prototypes are slithly different + */ +void* bdbreader_malloc(size_t size) +{ + return slapi_ch_malloc(size); +} + +void* bdbreader_realloc(void* pt, size_t size) +{ + return slapi_ch_realloc(pt, size); +} + +static void bdbreader_free(void *pt) +{ + slapi_ch_free(&pt); +} + +static void bdbreader_log(const char *msg, ...) +{ + char buffer[512]; + va_list ap; + + va_start(ap, msg); + PR_vsnprintf(buffer, (sizeof buffer), msg, ap); + va_end(ap); + slapi_log_err(SLAPI_LOG_ERR, "libbdbreader", "%s", buffer); +} + +int dbenv_open(DB_ENV *dbenv, const char *db_home, int flags, int mode) +{ + dbenv->db_home = slapi_ch_strdup(db_home); + /* Initialize libbdbreader callbacks */ + bdbreader_set_calloc_cb(bdbreader_calloc); + bdbreader_set_malloc_cb(bdbreader_malloc); + bdbreader_set_realloc_cb(bdbreader_realloc); + bdbreader_set_free_cb(bdbreader_free); + bdbreader_set_log_cb(bdbreader_log); + return DB_SUCCESS; +} + +int dbenv_close(DB_ENV *dbenv, int flags) +{ + slapi_ch_free_string(&dbenv->db_home); + slapi_ch_free((void**)&dbenv); + return DB_SUCCESS; +} + +char *db_strerror(int err) +{ + switch (err) { + case DB_SUCCESS: + return (char*)"DB_SUCCESS"; + case DB_LOCK_DEADLOCK: + return (char*)"DB_LOCK_DEADLOCK"; + case DB_NOTFOUND: + return (char*)"DB_NOTFOUND"; + case DB_BUFFER_SMALL: + return (char*)"DB_BUFFER_SMALL"; + case DB_KEYEXIST: + return (char*)"DB_KEYEXIST"; + case DB_RUNRECOVERY: + return (char*)"DB_RUNRECOVERY"; + case DB_NOTSUPPORTED: + return (char*)"DB_NOTSUPPORTED"; + default: + return (char*)"Unknonwn error"; + } +} + +int db_env_create(DB_ENV **penv, u_int32_t flags) +{ + DB_ENV *env = (void*)slapi_ch_calloc(1, sizeof *env); + + env->close = dbenv_close; + env->lock_detect = (void*)nothing; + env->open = dbenv_open; + env->remove = (void*)nothing; + env->set_flags = (void*)nothing; + env->set_verbose = (void*)nothing; + env->txn_checkpoint = (void*)nothing; + env->txn_begin = (void*)nothing; + env->get_open_flags = (void*)nothing; + env->mutex_set_tas_spins = (void*)nothing; + env->set_alloc = (void*)nothing; + env->set_cachesize = (void*)nothing; + env->set_data_dir = (void*)nothing; + env->set_errcall = (void*)nothing; + env->set_errpfx = (void*)nothing; + env->set_lg_bsize = (void*)nothing; + env->set_lg_dir = (void*)nothing; + env->set_lg_max = (void*)nothing; + env->set_lg_regionmax = (void*)nothing; + env->set_lk_max_lockers = (void*)nothing; + env->set_lk_max_locks = (void*)nothing; + env->set_lk_max_objects = (void*)nothing; + env->set_shm_key = (void*)nothing; + env->set_tx_max = (void*)nothing; + env->log_flush = (void*)nothing; + env->lock_stat = (void*)nothing; + env->log_archive = (void*)nothing; + env->memp_stat = (void*)nothing; + env->memp_trickle = (void*)nothing; + env->dbrename = (void*)nothing; + env->stat = (void*)nothing; + env->log_stat = (void*)nothing; + env->txn_stat = (void*)nothing; + *penv = env; + return DB_SUCCESS; +} + +int db_open(DB *db, DB_TXN *txnid, const char *file, + const char *database, DBTYPE type, u_int32_t flags, int mode) +{ + if (*file == '/') { + db->fname = slapi_ch_strdup(file); + } else { + db->fname = slapi_ch_smprintf("%s/%s", db->env->db_home, file); + } + db->impl = bdbreader_bdb_open(db->fname); + db->open_flags = OPEN_FLAGS_OPEN; + db_cursor(db, NULL, &db->cur, 0); + return (db->impl == NULL) ? DB_OSERROR : DB_SUCCESS; +} + +int db_close(DB *db, u_int32_t flags) +{ + bdbreader_bdb_close(db->impl); + db->impl = NULL; + db->open_flags = OPEN_FLAGS_CLOSED; + dbc_close(db->cur); + slapi_ch_free_string(&db->fname); + slapi_ch_free((void**)&db); + return DB_SUCCESS; +} + +int dbc_close(DBC *dbc) +{ + bdbreader_bdb_close(dbc->impl); + dbc->impl = NULL; + slapi_ch_free((void **)&dbc); + return DB_SUCCESS; +} + +int dbc_del(DBC *dbc, u_int32_t flags) +{ + return DB_NOTSUPPORTED; +} + +int copy_val(const DBT *from, DBT *to) +{ + switch (to->flags) { + case DB_DBT_MALLOC: + to->size = from->size; + if (from->data == NULL) { + to->data = NULL; + } else if (from->size > 0) { + to->data = slapi_ch_malloc(from->size); + memcpy(to->data, from->data, from->size); + } + return DB_SUCCESS; + case DB_DBT_REALLOC: + to->size = from->size; + if (from->data == NULL) { + to->data = NULL; + } else if (from->size > 0) { + to->data = slapi_ch_realloc(to->data, from->size); + memcpy(to->data, from->data, from->size); + } + return DB_SUCCESS; + case DB_DBT_USERMEM: + to->size = from->size; + if (from->size > to->ulen) { + return DB_BUFFER_SMALL; + } + memcpy(to->data, from->data, from->size); + return DB_SUCCESS; + } + return DB_NOTSUPPORTED; +} + + +int store_val(int rc, DBC *dbc, DBT *key, DBT *data) +{ + DBT k1 = {0}; + DBT d1 = {0}; + + if (rc == DB_SUCCESS) { + rc = bdbreader_cur_getcurval(dbc->impl, &k1.data, &k1.size, &d1.data, &d1.size); + } + if (rc == DB_SUCCESS) { + rc = copy_val(&k1, key); + } + if (rc == DB_SUCCESS) { + rc = copy_val(&d1, data); + } + return rc; +} + + +int dbc_get(DBC *dbc, DBT *key, DBT *data, u_int32_t flags) +{ + static const char *flagnames[] = { + "0", "DB_FIRST", "DB_CURRENT", "DB_GET_BOTH", "DB_GET_BOTH_RANGE", + "DB_GET_RECNO", "DB_LAST", "DB_NEXT", "DB_NEXT_DUP", "DB_NEXT_NODUP", + "DB_NODUPDATA", "DB_PREV", "DB_SET", "DB_SET_RANGE", "DB_SET_RECNO", + "DB_UNKNOWN" }; + static const char *errname[] = { + "DB_SUCCESS", "DB_NOTFOUND", "DB_BUFFER_SMALL", + "DB_KEYEXIST", "DB_RUNRECOVERY", "DB_NOTSUPPORTED", "DB_LOCK_DEADLOCK", "DB_OSERROR" }; + + slapi_log_err(SLAPI_LOG_ERR, "bdb_ro", "==> dbc_get(key=%s flags=%d:%s)\n", LOGK(key), flags, LOGN(flags, flagnames)); + + int rc = DB_NOTSUPPORTED; + DBT k1 = {0}; + DBT d1 = {0}; + + switch (flags) { + case DB_FIRST: + rc = bdbreader_cur_lookup(dbc->impl, NULL, 0); + if (rc == DB_NOTFOUND) { + rc = bdbreader_cur_next(dbc->impl); + } + rc = store_val(rc, dbc, key, data); + break; + case DB_CURRENT: + rc = store_val(rc, dbc, key, data); + break; + case DB_GET_BOTH: + break; + case DB_GET_BOTH_RANGE: + break; + case DB_GET_RECNO: + break; + case DB_LAST: + rc = DB_SUCCESS; + while (rc == DB_SUCCESS) { + rc = bdbreader_cur_next(dbc->impl); + if (rc == DB_SUCCESS) { + rc = bdbreader_cur_getcurval(dbc->impl, &k1.data, &k1.size, &d1.data, &d1.size); + } + if (rc == DB_NOTFOUND) { + rc = copy_val(&k1, key) | copy_val(&d1, data); + break; + } + } + break; + case DB_NEXT: + rc = bdbreader_cur_next(dbc->impl); + rc = store_val(rc, dbc, key, data); + break; + case DB_NEXT_DUP: + rc = bdbreader_cur_next(dbc->impl); + if (rc == DB_SUCCESS) { + rc = bdbreader_cur_getcurval(dbc->impl, &k1.data, &k1.size, NULL, NULL); + if (rc == DB_SUCCESS) { + if (k1.size == key->size && memcmp(k1.data, key->data, k1.size) == 0) { + rc = store_val(rc, dbc, key, data); + } else { + rc = DB_NOTFOUND; + } + } + } + break; + case DB_NEXT_NODUP: + rc = DB_SUCCESS; + while (rc == DB_SUCCESS) { + rc = bdbreader_cur_next(dbc->impl); + if (rc == DB_SUCCESS) { + rc = bdbreader_cur_getcurval(dbc->impl, &k1.data, &k1.size, NULL, NULL); + } + if (k1.size != key->size || memcmp(k1.data, key->data, k1.size) != 0) { + rc = store_val(rc, dbc, key, data); + break; + } + } + break; + case DB_NODUPDATA: + break; + case DB_PREV: + break; + case 0: + /* _get_and_add_parent_rdns set the flags ==> probably a bug + * (according BDB C API) + * But lets assume it is a DB_SET + */ + case DB_SET: + rc = bdbreader_cur_lookup(dbc->impl, key->data, key->size); + rc = store_val(rc, dbc, key, data); + break; + case DB_SET_RANGE: + rc = bdbreader_cur_lookup_ge(dbc->impl, key->data, key->size); + rc = store_val(rc, dbc, key, data); + break; + case DB_SET_RECNO: + break; + } + + slapi_log_err(SLAPI_LOG_ERR, "bdb_ro", "==> dbc_get(flags=%d:%s) rc=%d:%s\n", + flags, LOGN(flags, flagnames), rc, LOGN(rc, errname)); + if (key && key->data && key->size) { + hexadump("Key", key->data, 0, key->size); + } + if (data && data->data && data->size) { + hexadump("Data", data->data, 0, data->size); + } + return rc; +} + +int dbc_put(DBC *dbc, DBT *key, DBT *data, u_int32_t flags) +{ + return DB_NOTSUPPORTED; +} + +int dbc_count(DBC *dbc, void *countp, u_int32_t flags) +{ + return DB_NOTSUPPORTED; +} + +int db_cursor(DB *db, DB_TXN *txnid, DBC **cursorp, u_int32_t flags) +{ + DBC *dbc = (void*)slapi_ch_calloc(1, sizeof *dbc); + + *cursorp = dbc; + dbc->dbp = db; + + dbc->c_close = dbc_close; + dbc->c_del = dbc_del; + dbc->c_get = dbc_get; + dbc->c_put = dbc_put; + dbc->c_count = dbc_count; + dbc->impl = bdbreader_cur_open(db->impl); + + return (db->impl == NULL) ? DB_OSERROR : DB_SUCCESS; +} + +int db_del(DB *db, DB_TXN *txnid, DBT *key, u_int32_t flags) +{ + return DB_NOTSUPPORTED; +} + +int db_put(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) +{ + return DB_NOTSUPPORTED; +} + +int db_get(DB *db, DB_TXN *txnid, DBT *key, DBT *data, u_int32_t flags) +{ + int rc = bdbreader_cur_lookup(db->cur->impl, key->data, key->size); + if (rc == DB_SUCCESS) { + rc = dbc_get(db->cur, key, data, flags); + } + return rc; +} + +int db_create(DB **pdb, DB_ENV *env, u_int32_t flags) +{ + DB *db = (void*)slapi_ch_calloc(1, sizeof *db); + db->close = db_close; + db->compact = (void*)nothing; + db->cursor = db_cursor; + db->del = db_del; + db->get = db_get; + db->open = db_open; + db->put = db_put; + db->remove = (void*)nothing; + db->rename = (void*)nothing; + db->set_bt_compare = (void*)nothing; + db->set_dup_compare = (void*)nothing; + db->set_flags = (void*)nothing; + db->set_pagesize = (void*)nothing; + db->verify = (void*)nothing; + db->get_type = (void*)nothing; + db->stat = (void*)nothing; + db->env = env; + db->open_flags = OPEN_FLAGS_CLOSED; + *pdb = db; + return DB_SUCCESS; +} diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_layer.h b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_layer.h index 6e18db992b..9257742d83 100644 --- a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_layer.h +++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_layer.h @@ -10,7 +10,12 @@ #include "../back-ldbm.h" #include "../dblayer.h" #include "../import.h" +#ifdef WITH_LIBBDB_RO +#include "bdb_bdbreader_db.h" +#else #include +#endif + #define BDB_CONFIG(li) ((bdb_config *)(li)->li_dblayer_config) diff --git a/ldap/servers/slapd/back-ldbm/dbimpl.c b/ldap/servers/slapd/back-ldbm/dbimpl.c index f3bf68a9f4..487dc44d1e 100644 --- a/ldap/servers/slapd/back-ldbm/dbimpl.c +++ b/ldap/servers/slapd/back-ldbm/dbimpl.c @@ -397,6 +397,7 @@ const char *dblayer_op2str(dbi_op_t op) return str[idx]; } +<<<<<<< HEAD /* Get the li_directory directory from the database instance name - * Caller should free the returned value */ @@ -439,6 +440,8 @@ get_li_directory(const char *fname) } /* Open db env, db and db file privately (for dbscan) */ +======= +/* Open db env, db and db file privately (used by dbscan) */ int dblayer_private_open(const char *plgname, const char *dbfilename, int rw, Slapi_Backend **be, dbi_env_t **env, dbi_db_t **db) { struct ldbminfo *li; @@ -454,6 +457,7 @@ int dblayer_private_open(const char *plgname, const char *dbfilename, int rw, Sl li->li_plugin->plg_name = (char*) "back-ldbm-dbimpl"; li->li_plugin->plg_libpath = (char*) "libback-ldbm"; li->li_directory = get_li_directory(dbfilename); + li->li_flags = SLAPI_TASK_RUNNING_FROM_COMMANDLINE; /* Initialize database plugin */ rc = dbimpl_setup(li, plgname); @@ -541,6 +545,10 @@ dbi_dbslist_t *dblayer_list_dbs(const char *dbimpl_name, const char *dbhome) li->li_plugin->plg_name = (char*) "back-ldbm-dbimpl"; li->li_plugin->plg_libpath = (char*) "libback-ldbm"; li->li_directory = slapi_ch_strdup(dbhome); + /* Set SLAPI_TASK_RUNNING_FROM_COMMANDLINE to tell that + * read-only bdb is usable with dbscan + */ + li->li_flags |= SLAPI_TASK_RUNNING_FROM_COMMANDLINE; /* Initialize database plugin */ rc = dbimpl_setup(li, dbimpl_name); diff --git a/ldap/servers/slapd/back-ldbm/dblayer.c b/ldap/servers/slapd/back-ldbm/dblayer.c index feb33418e9..84a2a79c1f 100644 --- a/ldap/servers/slapd/back-ldbm/dblayer.c +++ b/ldap/servers/slapd/back-ldbm/dblayer.c @@ -177,6 +177,19 @@ backend_implement_get_libpath(struct ldbminfo *li, const char *plgname) /* mdb ==> lets use default (libback-ldbm.so) */ return li->li_plugin->plg_libpath; } + if (PR_FindSymbolAndLibrary("bdbro_getcb_vector", &lib)) { + /* read-only bdb is used ==> should be using dbscan or ns-slapd db2ldif + * bdb_init is within libback-ldbm.so ==> lets use default (libback-ldbm.so) + */ + if ((li->li_flags & SLAPI_TASK_RUNNING_FROM_COMMANDLINE) == 0) { + slapi_log_error(SLAPI_LOG_FATAL, "dblayer_setup", + "bdb implementation is no more supported." + " Directory server cannot be started without migrating to lmdb first." + " To migrate, please run: dsctl instanceName dblib bdb2mdb\n"); + exit(1); + } + return li->li_plugin->plg_libpath; + } if (PR_FindSymbolAndLibrary("bdb_init", &lib)) { /* bdb_init is within libback-ldbm.so ==> lets use default (libback-ldbm.so) */ return li->li_plugin->plg_libpath; @@ -1444,9 +1457,9 @@ dblayer_is_lmdb(Slapi_Backend *be) } /* - * Iterate on the provided curor starting at startingkey (or first key if + * Iterate on the provided curor starting at startingkey (or first key if * startingkey is NULL) and call action_cb for each records - * + * * action_cb callback returns: * DBI_RC_SUCCESS to iterate on next entry * DBI_RC_NOTFOUND to stop iteration with DBI_RC_SUCCESS code diff --git a/lib/librobdb/COPYING b/lib/librobdb/COPYING new file mode 100644 index 0000000000..ac042d4a40 --- /dev/null +++ b/lib/librobdb/COPYING @@ -0,0 +1,8 @@ + +The library code in +https://github.com/389ds/389-ds-base/lib/librobdb is derivated from RPM project + https://github.com/rpm-software-management/rpm project +As it is derivated from the RPM lib code, this code may be either distributed +under the terms of the GNU General Public License (GPL) or under the GNU +Library General Public License (LGPL). +The complete text of both licenses are in COPYING.RPM, the RPM license file diff --git a/lib/librobdb/COPYING.RPM b/lib/librobdb/COPYING.RPM new file mode 100644 index 0000000000..f153e80b7f --- /dev/null +++ b/lib/librobdb/COPYING.RPM @@ -0,0 +1,848 @@ +libbdbro is derived from RPM lib +(See https://github.com/rpm-software-management/rpm/) +so the following RPM license apply by replacing "RPM" by "libbdbreader" + +--------------------------------------------------------------------------- + + + +RPM is covered under two separate licenses. + +The entire code base may be distributed under the terms of the GNU General +Public License (GPL), which appears immediately below. Alternatively, +all of the source code in the lib and rpmio subdirectories of the RPM source +code distribution as well as any code derived from that code may instead be +distributed under the GNU Library General Public License (LGPL), at the +choice of the distributor. The complete text of the LGPL appears +at the bottom of this file. + +This alternative is provided to enable applications to be linked against +the RPM library (commonly called librpm) without forcing such applications +to be distributed under the GPL. + +Any questions regarding the licensing of RPM should be addressed to +rpm-maint@lists.rpm.org + +--------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Moe Ghoul, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + +--------------------------------------------------------------------------- + + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + + 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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 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, see . + +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 + Moe Ghoul, President of Vice + +That's all there is to it! diff --git a/lib/librobdb/README.md b/lib/librobdb/README.md new file mode 100644 index 0000000000..c2c87cf6e4 --- /dev/null +++ b/lib/librobdb/README.md @@ -0,0 +1,26 @@ +# DESCRIPTION + +This project provides basic functions to walk/lookup Berkeley Database records. +It is derived from [GitHub - rpm-software-management/rpm: The RPM package manager](https://github.com/rpm-software-management/rpm/) project. +It reuse a single file: https://github.com/rpm-software-management/rpm/blob/master/lib/backend/bdb_ro.cc + +renamed as a C file, suppressed librpm adherences and adding back a simple +interface to be able to use the relevant functions. + +# Build + +make clean rpmbuild lint + +# Example + +See test/test.c (Using a 389ds entries database as example, It shows how to dump the database and look for records) + +# Running tests + +dnf install -y dist/RPMS/*/*.rpm + +make test + +# LICENSE + +Same as lib part for rpm: GPLv2 or alternatively LGPL (See COPYING and COPYING.RPM for full details) diff --git a/lib/librobdb/lib/bdb_ro.c b/lib/librobdb/lib/bdb_ro.c new file mode 100644 index 0000000000..879ab2ef7d --- /dev/null +++ b/lib/librobdb/lib/bdb_ro.c @@ -0,0 +1,713 @@ +/* Part of this file content is derivated from: + * https://github.com/rpm-software-management/rpm/blob/master/lib/backend/bdb_ro.cc + * Commit: a45134e7d428ad4f40e629408f24de9a6b955200 + * i.e: + * git clone https://github.com/rpm-software-management/rpm.git + * git switch --detach a45134e7d428ad4f40e629408f24de9a6b955200 + * lib/backend/bdb_ro.cc + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "robdb.h" + +static void* (*bdbreader_calloc_cb)(size_t, size_t); +static void* (*bdbreader_malloc_cb)(size_t); +static void* (*bdbreader_realloc_cb)(void*, size_t); +static void (*bdbreader_free_cb)(void *); +static void (*bdbreader_log_cb)(const char*, ...); + +#define NEW(structname) bdbreader_calloc_cb(1, sizeof (struct structname)) +#define DELETE(var) bdbreader_free_cb((void*)var) +#define free(var) bdbreader_free_cb((void*)var) +#define xmalloc(size) bdbreader_malloc_cb(size) +#define xrealloc(ptr, size) bdbreader_realloc_cb((void*)(ptr),(size)) + +#define rpmlog(level, ...) bdbreader_log_cb("bdbro", __VA_ARGS__) + + +/* Note: the only changes in the following copied code is to convert back + * the C++ statments to C: + * new xxx is replaced by NEW(xxx) + * delete xxx is replaced by DELETE(xxx) + */ +/************************************************************************/ +/************** Start of code copied from librpm ************************/ +/************************************************************************/ + +#define BDB_HASH 0 +#define BDB_BTREE 1 + +union _dbswap { + unsigned int ui; + unsigned char uc[4]; +}; + +#define _DBSWAP(_a) \ +\ + { unsigned char _b, *_c = (_a).uc; \ + _b = _c[3]; _c[3] = _c[0]; _c[0] = _b; \ + _b = _c[2]; _c[2] = _c[1]; _c[1] = _b; \ +\ + } + +struct dbiCursor_s; + +struct bdb_kv { + unsigned char *kv; + unsigned int len; +}; + +struct bdb_db { + int fd; /* file descriptor of database */ + int type; /* BDB_HASH / BDB_BTREE */ + unsigned int pagesize; + unsigned int lastpage; + int swapped; /* different endianess? */ + /* btree */ + unsigned int root; /* root page of the b-tree */ + /* hash */ + unsigned int maxbucket; + unsigned int highmask; + unsigned int lowmask; + unsigned int spares[32]; /* spare pages for each splitpoint */ +}; + +struct bdb_cur { + struct bdb_db *db; + + struct bdb_kv key; /* key and value from the db entry */ + struct bdb_kv val; + + unsigned char *page; /* the page we're looking at */ + + unsigned char *ovpage; + struct bdb_kv keyov; /* space to store oversized keys/values */ + struct bdb_kv valov; + + int state; /* 1: onpage, -1: error */ + int idx; /* entry index */ + int numidx; /* number of entries on the page */ + int islookup; /* we're doing a lookup operation */ + + /* hash */ + unsigned int bucket; /* current bucket */ +}; + + +static void swap16(unsigned char *p) +{ + int a = p[0]; + p[0] = p[1]; + p[1] = a; +} + +static void swap32(unsigned char *p) +{ + int a = p[0]; + p[0] = p[3]; + p[3] = a; + a = p[1]; + p[1] = p[2]; + p[2] = a; +} + +static void swap32_2(unsigned char *p) +{ + swap32(p); + swap32(p + 4); +} + +static void bdb_swapmetapage(struct bdb_db *db, unsigned char *page) +{ + int i, maxi = db->type == BDB_HASH ? 224 : 92; + for (i = 8; i < maxi; i += 4) + swap32((unsigned char *)(page + i)); + swap32((unsigned char *)(page + 24)); +} + +static void bdb_swappage(struct bdb_db *db, unsigned char *page) +{ + unsigned int pagesize = db->pagesize; + int type, i, nent, off; + swap32(page + 8); /* page number */ + swap32_2(page + 12); /* prev/next page */ + swap16(page + 20); /* nitems */ + swap16(page + 22); /* highfree */ + + type = page[25]; + if (type != 2 && type != 13 && type != 3 && type != 5) + return; + nent = *(uint16_t *)(page + 20); + if (nent > (pagesize - 26) / 2) + nent = (pagesize - 26) / 2; + for (i = 0; i < nent; i++) { + int minoff = 26 + nent * 2; + swap16(page + 26 + i * 2); /* offset */ + off = *(uint16_t *)(page + 26 + i * 2); + if (off < minoff || off >= pagesize) + continue; + if (type == 2 || type == 13) { /* hash */ + if (page[off] == 3 && off + 12 <= pagesize) + swap32_2(page + off + 4); /* page no/length */ + } else if (type == 3) { /* btree internal */ + if (off + 12 > pagesize) + continue; + swap16(page + off); /* length */ + swap32_2(page + off + 4); /* page no/num recs */ + if (page[off + 2] == 3 && off + 24 <= pagesize) + swap32_2(page + off + 16); /* with overflow page/length */ + } else if (type == 5) { /* btree leaf */ + if (off + 3 <= pagesize && page[off + 2] == 1) + swap16(page + off); /* length */ + else if (off + 12 <= pagesize && page[off + 2] == 3) + swap32_2(page + off + 4); /* overflow page/length */ + } + } +} + +static int bdb_getpage(struct bdb_db *db, unsigned char *page, unsigned int pageno) +{ + if (!pageno || pageno > db->lastpage) + return -1; + if (pread(db->fd, page, db->pagesize, (off_t)pageno * db->pagesize) != db->pagesize) { + rpmlog(RPMLOG_ERR, "pread: %s\n", strerror(errno)); + return -1; + } + if (db->swapped) + bdb_swappage(db, page); + if (pageno != *(uint32_t *)(page + 8)) + return -1; + return 0; +} + +static void bdb_close(struct bdb_db *db) +{ + if (db->fd >= 0) + close(db->fd); + DELETE(db); +} + +static struct bdb_db *bdb_open(const char *name) +{ + uint32_t meta[512 / 4]; + int i, fd; + struct bdb_db *db; + + fd = open(name, O_RDONLY); + if (fd == -1) { + return NULL; + } + db = NEW(bdb_db); + db->fd = fd; + if (pread(fd, meta, 512, 0) != 512) { + rpmlog(RPMLOG_ERR, "%s: pread: %s\n", name, strerror(errno)); + bdb_close(db); + return NULL; + } + if (meta[3] == 0x00061561 || meta[3] == 0x61150600) { + db->type = BDB_HASH; + db->swapped = meta[3] == 0x61150600; + } else if (meta[3] == 0x00053162 || meta[3] == 0x62310500) { + db->type = BDB_BTREE; + db->swapped = meta[3] == 0x62310500; + } else { + rpmlog(RPMLOG_ERR, "%s: not a berkeley db hash/btree database\n", name); + bdb_close(db); + return NULL; + } + if (db->swapped) + bdb_swapmetapage(db, (unsigned char *)meta); + db->pagesize = meta[5]; + db->lastpage = meta[8]; + if (db->type == BDB_HASH) { + if (meta[4] < 8 || meta[4] > 10) { + rpmlog(RPMLOG_ERR, "%s: unsupported hash version %d\n", name, meta[4]); + bdb_close(db); + return NULL; + } + db->maxbucket = meta[18]; + db->highmask = meta[19]; + db->lowmask = meta[20]; + for (i = 0; i < 32; i++) + db->spares[i] = meta[24 + i]; + } + if (db->type == BDB_BTREE) { + if (meta[4] < 9 || meta[4] > 10) { + rpmlog(RPMLOG_ERR, "%s: unsupported btree version %d\n", name, meta[4]); + bdb_close(db); + return NULL; + } + db->root = meta[22]; + } + return db; +} + + +/****** overflow handling ******/ + +static int ovfl_get(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, uint32_t *pagenolen) +{ + unsigned int pageno = pagenolen[0]; + unsigned int len = pagenolen[1]; + unsigned int plen; + unsigned char *p; + + if (len == 0) + return -1; + if (len > ov->len) { + if (ov->kv) + ov->kv = xrealloc(ov->kv, len); + else + ov->kv = (unsigned char *)xmalloc(len); + ov->len = len; + } + if (!cur->ovpage) + cur->ovpage = (unsigned char *)xmalloc(cur->db->pagesize); + p = ov->kv; + while (len > 0) { + if (bdb_getpage(cur->db, cur->ovpage, pageno)) + return -1; + if (cur->ovpage[25] != 7) + return -1; + plen = *(uint16_t *)(cur->ovpage + 22); + if (plen + 26 > cur->db->pagesize || plen > len) + return -1; + memcpy(p, cur->ovpage + 26, plen); + p += plen; + len -= plen; + pageno = *(uint32_t *)(cur->ovpage + 16); + } + if (kv) { + kv->kv = ov->kv; + kv->len = pagenolen[1]; + } + return 0; +} + + +/****** hash implementation ******/ + +static int hash_bucket_to_page(struct bdb_db *db, unsigned int bucket) +{ + unsigned int b; + int i = 0; + for (b = bucket; b; b >>= 1) + i++; + return bucket + db->spares[i]; +} + +static int hash_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl) +{ + uint32_t bucket; + unsigned int pg, i; + cur->state = -1; + for (bucket = 0, i = 0; i < keyl; i++) + bucket = (bucket * 16777619) ^ key[i]; + bucket &= cur->db->highmask; + if (bucket > cur->db->maxbucket) + bucket &= cur->db->lowmask; + cur->bucket = bucket; + pg = hash_bucket_to_page(cur->db, bucket); + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; + if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2) + return -1; + cur->idx = (unsigned int)-2; + cur->numidx = *(uint16_t *)(cur->page + 20); + cur->state = 1; + return 0; +} + +static int hash_getkv(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, int off, int len) +{ + if (len <= 0 || off + len > cur->db->pagesize) + return -1; + if (cur->page[off] == 1) { + kv->kv = cur->page + off + 1; + kv->len = len - 1; + } else if (cur->page[off] == 3) { + uint32_t ovlpage[2]; + if (len != 12) + return -1; + memcpy(ovlpage, cur->page + off + 4, 8); /* off is unaligned */ + if (ovfl_get(cur, kv, ov, ovlpage)) + return -1; + } else { + return -1; + } + return 0; +} + +static int hash_next(struct bdb_cur *cur) +{ + int pagesize = cur->db->pagesize; + int koff, klen, voff, vlen; + if (!cur->state && hash_lookup(cur, 0, 0)) + return -1; + cur->idx += 2; + for (;;) { + if (cur->idx + 1 >= cur->numidx) { + unsigned int pg; + cur->idx = cur->numidx = 0; + pg = *(uint32_t *)(cur->page + 16); + if (!pg) { + if (cur->islookup || cur->bucket >= cur->db->maxbucket) + return 1; + pg = hash_bucket_to_page(cur->db, ++cur->bucket); + } + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; + if (cur->page[25] != 8 && cur->page[25] != 13 && cur->page[25] != 2) + return -1; + cur->numidx = *(uint16_t *)(cur->page + 20); + continue; + } + koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx); + voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx); + if (koff >= pagesize || voff >= pagesize) + return -1; + if (cur->idx == 0) + klen = pagesize - koff; + else + klen = *(uint16_t *)(cur->page + 24 + 2 * cur->idx) - koff; + vlen = koff - voff; + if (hash_getkv(cur, &cur->key, &cur->keyov, koff, klen)) + return -1; + if (!cur->islookup && hash_getkv(cur, &cur->val, &cur->valov, voff, vlen)) + return -1; + return 0; + } +} + +static int hash_getval(struct bdb_cur *cur) +{ + int koff, voff; + if (cur->state != 1 || cur->idx + 1 >= cur->numidx) + return -1; + koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx); + voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx); + return hash_getkv(cur, &cur->val, &cur->valov, voff, koff - voff); +} + + +/****** btree implementation ******/ + +static int btree_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keylen) +{ + int pagesize = cur->db->pagesize; + int off, lastoff, idx, numidx; + unsigned int pg; + unsigned char *ekey; + unsigned int ekeylen; + int cmp; + + cur->state = -1; + pg = cur->db->root; + for (;;) { + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; + if (cur->page[25] == 5) + break; /* found leaf page */ + if (cur->page[25] != 3) + return -1; + numidx = *(uint16_t *)(cur->page + 20); + if (!numidx) + return -1; + for (lastoff = 0, idx = 0; idx < numidx; idx++, lastoff = off) { + off = *(uint16_t *)(cur->page + 26 + 2 * idx); + if ((off & 3) != 0 || off + 3 > pagesize) + return -1; + ekeylen = *(uint16_t *)(cur->page + off); + if (off + 12 + ekeylen > pagesize) + return -1; + if (!keylen) { + lastoff = off; + break; + } + if (idx == 0) + continue; + ekey = cur->page + off + 12; + if ((cur->page[off + 2] & 0x7f) == 3) { + if (ekeylen != 12) + return -1; + if (ovfl_get(cur, 0, &cur->keyov, (uint32_t *)(ekey + 4))) + return -1; + ekeylen = *(uint32_t *)(ekey + 8); + ekey = cur->keyov.kv; + } else if ((cur->page[off + 2] & 0x7f) != 1) { + return -1; + } + cmp = memcmp(ekey, key, keylen < ekeylen ? keylen : ekeylen); + if (cmp > 0 || (cmp == 0 && ekeylen > keylen)) + break; + } + pg = *(uint32_t *)(cur->page + lastoff + 4); + } + cur->idx = (unsigned int)-2; + cur->numidx = *(uint16_t *)(cur->page + 20); + cur->state = 1; + return 0; +} + +static int btree_getkv(struct bdb_cur *cur, struct bdb_kv *kv, struct bdb_kv *ov, int off) +{ + if ((off & 3) != 0) + return -1; + if (cur->page[off + 2] == 1) { + int len = *(uint16_t *)(cur->page + off); + if (off + 3 + len > cur->db->pagesize) + return -1; + kv->kv = cur->page + off + 3; + kv->len = len; + } else if (cur->page[off + 2] == 3) { + if (off + 12 > cur->db->pagesize) + return -1; + if (ovfl_get(cur, kv, ov, (uint32_t *)(cur->page + off + 4))) + return -1; + } else { + return -1; + } + return 0; +} + +static int btree_next(struct bdb_cur *cur) +{ + int pagesize = cur->db->pagesize; + int koff, voff; + if (!cur->state && btree_lookup(cur, 0, 0)) + return -1; + cur->idx += 2; + for (;;) { + if (cur->idx + 1 >= cur->numidx) { + unsigned int pg; + cur->idx = cur->numidx = 0; + pg = *(uint32_t *)(cur->page + 16); + if (cur->islookup || !pg) + return 1; + if (bdb_getpage(cur->db, cur->page, pg)) + return -1; + if (cur->page[25] != 5) + return -1; + cur->numidx = *(uint16_t *)(cur->page + 20); + continue; + } + koff = *(uint16_t *)(cur->page + 26 + 2 * cur->idx); + voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx); + if (koff + 3 > pagesize || voff + 3 > pagesize) + return -1; + if ((cur->page[koff + 2] & 0x80) != 0 || (cur->page[voff + 2] & 0x80) != 0) + continue; /* ignore deleted */ + if (btree_getkv(cur, &cur->key, &cur->keyov, koff)) + return -1; + if (!cur->islookup && btree_getkv(cur, &cur->val, &cur->valov, voff)) + return -1; + return 0; + } +} + +static int btree_getval(struct bdb_cur *cur) +{ + int voff; + if (cur->state != 1 || cur->idx + 1 >= cur->numidx) + return -1; + voff = *(uint16_t *)(cur->page + 28 + 2 * cur->idx); + return btree_getkv(cur, &cur->val, &cur->valov, voff); +} + + +/****** cursor functions ******/ + +static struct bdb_cur *cur_open(struct bdb_db *db) +{ + struct bdb_cur *cur = NEW(bdb_cur); + cur->db = db; + cur->page = (unsigned char *)xmalloc(db->pagesize); + return cur; +} + +static void cur_close(struct bdb_cur *cur) +{ + if (cur->page) + free(cur->page); + if (cur->ovpage) + free(cur->ovpage); + if (cur->keyov.kv) + free(cur->keyov.kv); + if (cur->valov.kv) + free(cur->valov.kv); + DELETE(cur); +} + +static int cur_next(struct bdb_cur *cur) +{ + if (cur->state < 0) + return -1; + if (cur->db->type == BDB_HASH) + return hash_next(cur); + if (cur->db->type == BDB_BTREE) + return btree_next(cur); + return -1; +} + +static int cur_getval(struct bdb_cur *cur) +{ + if (cur->state < 0) + return -1; + if (cur->db->type == BDB_HASH) + return hash_getval(cur); + if (cur->db->type == BDB_BTREE) + return btree_getval(cur); + return -1; +} + +static int cur_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl) +{ + int r = -1; + if (cur->db->type == BDB_HASH) + r = hash_lookup(cur, key, keyl); + if (cur->db->type == BDB_BTREE) + r = btree_lookup(cur, key, keyl); + if (r != 0) + return r; + cur->islookup = 1; + while ((r = cur_next(cur)) == 0) + if (keyl == cur->key.len && !memcmp(key, cur->key.kv, keyl)) + break; + cur->islookup = 0; + if (r == 0) + r = cur_getval(cur); + return r; +} + +static int cur_lookup_ge(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl) +{ + int r = -1; + if (cur->db->type == BDB_BTREE) + r = btree_lookup(cur, key, keyl); + if (r != 0) + return r; + cur->islookup = 1; + while ((r = cur_next(cur)) == 0) { + unsigned int ekeyl = cur->key.len; + int cmp = memcmp(cur->key.kv, key, keyl < ekeyl ? keyl : ekeyl); + if (cmp > 0 || (cmp == 0 && ekeyl >= keyl)) + break; + } + cur->islookup = 0; + if (r == 0) + r = cur_getval(cur); + else if (r == 1) + r = cur_next(cur); + return r; +} + +/************************************************************************/ +/************** End of code copied from librpm **************************/ +/************************************************************************/ + +static int cur_getcurval(struct bdb_cur *cur, void **keyv, unsigned int *keyl, void **datav, unsigned int *datal) +{ + int ret = cur_getval(cur); + if (keyv) { + *keyv = cur->key.kv; + } + if (keyl) { + *keyl = cur->key.len; + } + if (datav) { + *datav = cur->val.kv; + } + if (datal) { + *datal = cur->val.len; + } + return ret; +} + +/************************************************************************/ +/********** exported symbols - see description in bdbreader.h ***********/ +/************************************************************************/ + +struct bdb_db *bdbreader_bdb_open(const char *name) +{ + return bdb_open(name); +} + +void bdbreader_bdb_close(struct bdb_db **db) +{ + if (*db) { + bdb_close(*db); + *db = NULL; + } +} + +struct bdb_cur *bdbreader_cur_open(struct bdb_db *db) +{ + return cur_open(db); +} + +void bdbreader_cur_close(struct bdb_cur **cur) +{ + if (*cur) { + cur_close(*cur); + *cur = NULL; + } +} + +int bdbreader_cur_next(struct bdb_cur *cur) +{ + return cur_next(cur); +} + +int bdbreader_cur_getval(struct bdb_cur *cur) +{ + return cur_getval(cur); +} + +int bdbreader_cur_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl) +{ + return cur_lookup(cur, key, keyl); +} + +int bdbreader_cur_lookup_ge(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl) +{ + return cur_lookup_ge(cur, key, keyl); +} + +int bdbreader_cur_getcurval(struct bdb_cur *cur, void **keyv, unsigned int *keyl, void **datav, unsigned int *datal) +{ + return cur_getcurval(cur, keyv, keyl, datav, datal); +} + +void bdbreader_set_calloc_cb(void* (*calloc_cb)(size_t, size_t)) +{ + bdbreader_calloc_cb = calloc_cb; +} + +void bdbreader_set_malloc_cb(void* (*malloc_cb)(size_t)) +{ + bdbreader_malloc_cb = malloc_cb; +} + +void bdbreader_set_realloc_cb(void* (*realloc_cb)(void*, size_t)) +{ + bdbreader_realloc_cb = realloc_cb; +} + +void bdbreader_set_free_cb(void (*free_cb)(void *)) +{ + bdbreader_free_cb = free_cb; +} + +void bdbreader_set_log_cb(void (*log_cb)(const char*, ...)) +{ + bdbreader_log_cb = log_cb; +} + diff --git a/lib/librobdb/lib/robdb.h b/lib/librobdb/lib/robdb.h new file mode 100644 index 0000000000..bc61f94ee7 --- /dev/null +++ b/lib/librobdb/lib/robdb.h @@ -0,0 +1,51 @@ +/* + * License: GPL (version 2 or any later version) or LGPL (version 2.1 or any later version). + */ + +struct bdb_db; +struct bdb_cur; + + +/* Callbacks - All callbacks must be set before used any other functions */ + +/* Set callback for the calloc function */ +void bdbreader_set_calloc_cb(void* (*calloc_cb)(size_t, size_t)); + +/* Set callback for the malloc function */ +void bdbreader_set_malloc_cb(void* (*malloc_cb)(size_t)); + +/* Set callback for the realloc function */ +void bdbreader_set_realloc_cb(void* (*realloc_cb)(void*, size_t)); + +/* Set callback for the free function */ +void bdbreader_set_free_cb(void (*free_cb)(void *)); + +/* Set callback for the log function */ +void bdbreader_set_log_cb(void (*log_cb)(const char*, ...)); + +/* Open a database instance and get a db handler */ +struct bdb_db *bdbreader_bdb_open(const char *name); + +/* Close a db handler */ +void bdbreader_bdb_close(struct bdb_db **db); + +/* Create a cursor on a db */ +struct bdb_cur *bdbreader_cur_open(struct bdb_db *db); + +/* Close a cusrsor */ +void bdbreader_cur_close(struct bdb_cur **cur); + +/* Move cursor to next item. returns -1 if no more records */ +int bdbreader_cur_next(struct bdb_cur *cur); + +/* Get cursor current status. returns -1 if no more records */ +int bdbreader_cur_getval(struct bdb_cur *cur); + +/* Position the cursor on the key. return -1 if not found */ +int bdbreader_cur_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl); + +/* Position the cursor on smallest key >= key. return -1 if not found */ +int bdbreader_cur_lookup_ge(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl); + +/* Get cursor current key/data pair. returns -1 if no more records */ +int bdbreader_cur_getcurval(struct bdb_cur *cur, void **keyv, unsigned int *keyl, void **datav, unsigned int *datal); diff --git a/lib/librobdb/robdb.spec b/lib/librobdb/robdb.spec new file mode 100644 index 0000000000..f7072d9b62 --- /dev/null +++ b/lib/librobdb/robdb.spec @@ -0,0 +1,64 @@ +Name: robdb +Version: 1.1 +Release: %{autorelease -n %{?dist}} +Summary: Provide basic functions to search and read Berkeley Database records + +License: GPL-2.0-or-later +URL: https://github.com/389ds/389-ds-base/lib/librobdb +Source0: %{name}-%{version}.tar.bz2 + +BuildRequires: gcc +# Requires: + +%description + + +%package devel +Summary: Development files for %{name} +License: GPL-2.0-or-later OR LGPL-2.1-or-later +Requires: %{name}-libs%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains the library and the header file for +developing applications that use %{name}: A library derived from +rpm lib project (https://github.com/rpm-software-management) that +provides some basic functions to search and read Berkeley Database records + + +%package libs +Summary: Library for %{name} +License: GPL-2.0-or-later OR LGPL-2.1-or-later + +%description libs +The %{name}-lib package contains a library derived from rpm lib +project (https://github.com/rpm-software-management) that provides +some basic functions to search and read Berkeley Database records + + +%prep +%autosetup + +%build +%make_build + +%install +%make_install + +%{?ldconfig_scriptlets} + + +%files libs +%license COPYING COPYING.RPM +%doc %{_defaultdocdir}/%{name}-libs/README.md +%{_libdir}/*.so.* + +%files devel +%license COPYING COPYING.RPM +%doc %{_defaultdocdir}/%{name}-devel/README.md +%{_libdir}/*.so +%{_includedir}/* + + +%changelog +%autochangelog + diff --git a/lib/librobdb/tests/test.c b/lib/librobdb/tests/test.c new file mode 100644 index 0000000000..65b7a69fdc --- /dev/null +++ b/lib/librobdb/tests/test.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include + +typedef struct { + void *data; + unsigned int len; +} DATA; + + +void print_record(const DATA *key, const DATA *data) +{ + unsigned int id = 0; + if (4 == key->len) { + unsigned char *pt = key->data; + /* In test.db the key is a big endian 4 bytes integer */ + id = pt[3] + (pt[2] << 8) + (pt[1] << 16) + (pt[0] << 24); + printf("Key: %3d Data:\n%s\n", id, (char*)data->data); + } else { + printf("ERROR: Unexpected record key size\n"); + } +} + +void mylog(const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + printf("bdbreader:" ); + vprintf(msg, ap); + va_end(ap); +} + + +int main() +{ + struct bdb_db *db = NULL; + struct bdb_cur *cur = NULL; + DATA key = {0}; + DATA data = {0}; + int rc = 0; + char keybuff[6]; + int fail = 0; + int count = 0; + int expected_count = 14; + + printf("HERE[%d]\n",__LINE__); + + /* Initialize all callbacks */ + bdbreader_set_calloc_cb(calloc); + bdbreader_set_malloc_cb(malloc); + bdbreader_set_realloc_cb(realloc); + bdbreader_set_free_cb(free); + bdbreader_set_log_cb(mylog); + + db = bdbreader_bdb_open("test.db"); + if (db == NULL) { + perror("Failed to open test.db"); + exit(1); + } + cur = bdbreader_cur_open(db); + if (cur == NULL) { + perror("Failed to open cursor"); + exit(1); + } + + printf(" ********* Dump the dtabase content: *******\n"); + + do { + rc = bdbreader_cur_next(cur); + if (rc !=0) { + break; + } + rc = bdbreader_cur_getcurval(cur, &key.data, &key.len, &data.data, &data.len); + if (rc == 0) { + print_record(&key, &data); + count++; + } + } while (rc == 0); + + printf("Found %d/%d records\n\n", count, expected_count); + if (count != expected_count) { + fail = 1; + } + + printf(" ********* Test lookup: *******\n"); + + keybuff[0] = 0; + keybuff[1] = 0; + keybuff[2] = 0; + keybuff[3] = 7; + keybuff[4] = '@'; + key.data = keybuff; + key.len = 5; + + printf(" Looking for key == 7@ ... Should not find it.\n"); + rc = bdbreader_cur_lookup(cur, key.data, key.len); + if (rc == 0) { + printf("ERROR: key == 7@ unexpectedly found.\n"); + fail = 1; + } else { + printf("OK: key == 7@ is not found (as expected).\n"); + } + + printf(" Looking for key >= 7@ ... Should not find record with key == 8.\n"); + rc = bdbreader_cur_lookup_ge(cur, key.data, key.len); + if (rc == 0) { + rc = bdbreader_cur_getcurval(cur, &key.data, &key.len, &data.data, &data.len); + if (rc != 0) { + printf("ERROR: key >= 7@ : unable to get the record.\n"); + fail = 1; + } else { + char *ptid = key.data; + if (ptid[3] != 8) { + printf("ERROR: key >= 7@ : found record %d instead of 8.\n", ptid[3]); + fail = 1; + } else { + printf("OK: key >= 7@ : found record 8 (as expected).\n"); + } + } + } else { + printf("ERROR: key >= 7@ is not found.\n"); + fail = 1; + } + + key.data = keybuff; + key.len = 4; + printf(" Looking for key == 7 ... Should find it.\n"); + rc = bdbreader_cur_lookup(cur, key.data, key.len); + if (rc == 0) { + rc = bdbreader_cur_getcurval(cur, &key.data, &key.len, &data.data, &data.len); + if (rc != 0) { + printf("ERROR: key == 7 : unable to get the record.\n"); + fail = 1; + } else { + char *ptid = key.data; + if (ptid[3] != 7) { + printf("ERROR: key == 7 : found record %d instead of 7.\n", ptid[3]); + fail = 1; + } else { + printf("OK: key == 7 : found record 7 (as expected).\n"); + } + } + } else { + printf("ERROR: key == 7 is not found.\n"); + fail = 1; + } + + bdbreader_cur_close(&cur); + bdbreader_bdb_close(&db); + printf("TEST: %s\n", fail ? "FAIL":"PASS"); + + return fail; +} + +#if 0 +/* Get cursor current status. returns -1 if no more records */ +int bdbreader_cur_getval(struct bdb_cur *cur); + +/* Position the cursor on the key. return -1 if not found */ +int bdbreader_cur_lookup(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl); + +/* Position the cursor on smallest key >= key. return -1 if not found */ +int bdbreader_cur_lookup_ge(struct bdb_cur *cur, const unsigned char *key, unsigned int keyl); +#endif + diff --git a/lib/librobdb/tests/test.db b/lib/librobdb/tests/test.db new file mode 100644 index 0000000000000000000000000000000000000000..abefbce1c3f909ae58a5ddf50cfbd16484332fc0 GIT binary patch literal 24576 zcmeHO&uE_e7|Z+(hJWIXVVvT}iPz(=7IO>#8ph8L+r{sXq7l7!7{=!k*XToy zfJQ(gpb^jrXaqC@8Uc-fMnEH=5zq)|1T+E~0gZr0KqH_L&&kDJf4%(T((_9j z7xBec7hYUAd)_$za^-mC>^bAytK}EVe=YsF^k`9jeLz3|e{-B^%NhZVfJR^*5cn>a z^DVcEO}Exz)IVtZ_A?UD1D_HLdG*KC3~oDwu__L{wtAxJd!6=f<34ForhekGd$d)j z{%!-AU^{Kt1oMICGk&eO_Z{1ZJ9&N=-y<$*QXjQE%Wl|o=on#!er>}90@7+%ae2L5 zS>Il-lr}1*a^;~k(j79uWe;5YX@`DpRq+@GjLb3Yr&qSvXlso%00vpts;Ewe_S!;Bru-0(a!x9loWvG92`BFuK_X6sdv>SFMrd-D zc_>ZJLph5FxzuqOkTJ1hJWb$Ftd{Lg6@F=PmeF6I9Q{%j`eLPHfG@E>XB) zY}F)l)LFy$ap67w`-Y$3cM%_-lA5+-TQy;b3s4p4lyGv{9%xN3v8A}|6VvoMZbEjs zY}apQjTgN3E`i%uaddyKgztds;0Js*md)A@=}G|{opxxGIEj;(A0x09cYtk_@Q7`6 z=(T8HM_2LMGvcq&Ry*h-$7|Z|{vmZ7I9<2hwFYq*Mg7%%>6uSJ;QJjq({5#s=T;k$ zTiuAemEsOE`Ff!OPm6KsS4+md(3ijqfwpJ1nXGkEp5*yW;@aPk0F*v)I<5`Q)2ZVA z)x@-`cr_q?lLjOR{8~O%X5r&wa2aO$cAH<%52F%=ADQA@D=e?@F~WRA=yIG#oG*mN z8@3ZrFuxkJUvp`|Owy+Nuo&tWU@-jQMG3Baw0;vKOiTyo@4BS!P)yve=hEKP;Uf_X znAe8+o0vF`cZ65@Q4z)v-#jd0sAYJKR9NLPXCds?@{UE?)wQ)XX)Ry4S$I2MRvuOV z!GH+dUj0|EkLP8j$ji3kUKVqdtTIpf)uKVe{X{JcMng zb+&p2%-kvzG zRML4xsg(QKAuFYXxn#k364eBi?VSUQ9k4D7Xlq0kcbVzA0kPerDCHX^>(oVGQ8Z3f ztFuhOjfp8p_Jx$SX2Krge#-bG)MV){YApCN8rGKA0@RUZR&gl!P%L;stEalMvkdvx zFvz3cG)kv4%jEk{Z0YcKgX-wCGprs z$VXnqjL134@}r`pO~tht=tfU|GJGXc&HO{CtHhXIMT=mE<|m@6GaM!BSAL*upiOFe zjGt8sSbjq6y9kFn{%(VxgAjK3UzhE(!@W-3vCS`NSDuNNK`?}uAh)R>z;h%M#G`a; zga>WMqIeH$oN-)(n}>pFqzglRK3nN$$YuO6$V zY1o1(C}&}t40e0nmcl?@5atD|SfQAe3q6yQQ6tuiFfUWn)C^m3a)pV)n;|S)Mg!Nt zS0J2ftQA09^owmF1pCrgiac&fd7L|3=pk-x0MES$R~r*aH|;l>grD}>RWME9f0BUD z4EG-J2n&B2=xk{cK2+SP*XIkJ3}N|ryVmca40f?TJwk|Mp$(`SKrlN+eiwxcCQFkT zKf@c*+?;$qtceN6AV%giULcu=#BIuG67>=6_@Y@QO2v_^jC?$axKgy;FP`ur1;G9UDL>pV#5V|3j|G3_8`uyR6<3GfJ}4rrHmuS@ zU3ls&>*k$dx;grON36fMF}hlmLMn}h_+AJ9ZpXa6exJ7q>-kO<0nPtZ;hZ~Tn*X_@ zY^oF1{7)6mxihBupF7H?I$_QKRN`WDJ literal 0 HcmV?d00001 diff --git a/m4/db.m4 b/m4/db.m4 index e8d54747b2..f487ba2cc2 100644 --- a/m4/db.m4 +++ b/m4/db.m4 @@ -1,5 +1,5 @@ # BEGIN COPYRIGHT BLOCK -# Copyright (C) 2022 Red Hat, Inc. +# Copyright (C) 2024 Red Hat, Inc. # All rights reserved. # # License: GPL (version 3 or any later version). @@ -68,10 +68,37 @@ AC_ARG_WITH(db-lib, AS_HELP_STRING([--with-db-lib=PATH],[Berkeley DB library dir ], AC_MSG_RESULT(no)) +# check for --with-libbdb-ro +AC_MSG_CHECKING(for --with-libbdb-ro) +AC_ARG_WITH(libbdb-ro, AS_HELP_STRING([--with-libbdb-ro],[Use a read-only Berkeley Database shared library (default: use standard or bundled libbdb)]), +[ + if test "$withval" = "yes"; then + with_libbdb_ro=yes + AC_MSG_RESULT(yes) + AC_SUBST(with_libbdb_ro) + else + with_libbdb_ro=no + AC_MSG_RESULT(no) + fi +], +[ + with_libbdb_ro=yes + AC_MSG_RESULT(yes) + AC_SUBST(with_libbdb_ro) +]) +AM_CONDITIONAL([WITH_LIBBDB_RO],[test "$with_libbdb_ro" != no]) + dnl - check in system locations +db_bdb_srcdir="ldap/servers/slapd/back-ldbm/db-bdb" if test -z "$db_inc"; then AC_MSG_CHECKING(for db.h) - if test -f "/usr/include/db4/db.h"; then + if test "$with_libbdb_ro" = yes; then + AC_MSG_RESULT([using lib/librobdb/lib/robdb.h]) + db_incdir="lib/librobdb/lib" + db_inc="-Ilib/librobdb/lib" + db_libdir="" + db_lib="-lrobdb" + elif test -f "/usr/include/db4/db.h"; then AC_MSG_RESULT([using /usr/include/db4/db.h]) db_incdir="/usr/include/db4" db_inc="-I/usr/include/db4" @@ -96,9 +123,15 @@ if test -z "$db_inc"; then fi dnl figure out which version of db we're using from the header file +if test "$with_libbdb_ro" = yes; then +db_ver_maj=5 +db_ver_min=3 +db_ver_pat=0 +else db_ver_maj=`grep DB_VERSION_MAJOR $db_incdir/db.h | awk '{print $3}'` db_ver_min=`grep DB_VERSION_MINOR $db_incdir/db.h | awk '{print $3}'` db_ver_pat=`grep DB_VERSION_PATCH $db_incdir/db.h | awk '{print $3}'` +fi dnl Ensure that we have libdb at least 4.7, older versions aren't supported if test ${db_ver_maj} -lt 4; then @@ -111,12 +144,14 @@ dnl libname is libdb-maj.min e.g. libdb-4.2 db_libver=${db_ver_maj}.${db_ver_min} dnl make sure the lib is available dnl use true so libdb won't be added to LIBS +if test "$with_libbdb_ro" != yes; then save_ldflags="$LDFLAGS" LDFLAGS="$db_lib $LDFLAGS" AC_CHECK_LIB([db-$db_libver], [db_create], [true], [AC_MSG_ERROR([$db_incdir/db.h is version $db_libver but libdb-$db_libver not found])], [$LIBNSL]) LDFLAGS="$save_ldflags" +fi # if DB is not found yet, try pkg-config @@ -133,7 +168,8 @@ else db_bindir=/usr/bin fi - +AC_SUBST(db_bdb_srcdir) +AC_SUBST(db_bdbro_srcdir) AC_SUBST(db_inc) AC_SUBST(db_incdir) AC_SUBST(db_lib) diff --git a/rpm.mk b/rpm.mk index 8aa2dc3539..c7a69dba5e 100644 --- a/rpm.mk +++ b/rpm.mk @@ -26,6 +26,19 @@ RPMBUILD_OPTIONS += $(if $(filter 1, $(BUNDLE_LIBDB)),--with bundle_libdb,--with LIBDB_URL ?= $(shell rpmspec $(RPMBUILD_OPTIONS) -P $(RPMBUILD)/SPECS/389-ds-base.spec | awk '/^Source4:/ {print $$2}') LIBDB_TARBALL ?= $(shell basename "$(LIBDB_URL)") +# Enable BUNDLE_BDBREADERS if neither BUNDLE_LIBDB nor /usr/include/db.h is available +ifeq ($(BUNDLE_LIBDB), 1) +BUNDLE_BDBREADERS ?= 0 +else +ifeq (,$(wildcard /usr/include/db.h#)) +BUNDLE_BDBREADERS ?= 1 +else +BUNDLE_BDBREADERS ?= 0 +endif +endif +RPMBUILD_OPTIONS += $(if $(filter 1, $(BUNDLE_BDBREADERS)),--with libbdb-ro,--without libbdb-ro) + + # Some sanitizers are supported only by clang CLANG_ON = 0 RPMBUILD_OPTIONS += $(if $(filter 1, $(CLANG_ON)),--with clang,--without clang) @@ -111,7 +124,7 @@ endif fi ; \ if [ $(BUNDLE_LIBDB) -eq 1 ]; then \ curl -LO $(LIBDB_URL) ; \ - fi + fi ; rpmroot: rm -rf $(RPMBUILD) @@ -149,6 +162,7 @@ srpms: rpmroot srpmdistdir download-cargo-dependencies tarballs rpmbuildprep python3 rpm/bundle-rust-npm.py $(CARGO_PATH) $(NODE_MODULES_PATH) $(RPMBUILD)/SPECS/$(PACKAGE).spec -f rpmbuild --define "_topdir $(RPMBUILD)" -bs $(RPMBUILD)/SPECS/$(PACKAGE).spec $(RPMBUILD_OPTIONS) cp $(RPMBUILD)/SRPMS/*.src.rpm dist/srpms/ + @echo RPMBUILD=$(RPMBUILD) rm -rf $(RPMBUILD) srpm: srpms @@ -164,8 +178,26 @@ rpms: rpmroot srpmdistdir rpmdistdir tarballs rpmbuildprep rpmbuild --define "_topdir $(RPMBUILD)" -ba $(RPMBUILD)/SPECS/$(PACKAGE).spec $(RPMBUILD_OPTIONS) cp $(RPMBUILD)/RPMS/*/*.rpm dist/rpms/ cp $(RPMBUILD)/SRPMS/*.src.rpm dist/srpms/ + @echo RPMBUILD=$(RPMBUILD) rm -rf $(RPMBUILD) rpm: rpms patch_rpms: | patch rpms + +debug: + @echo BUNDLE_JEMALLOC=$(BUNDLE_JEMALLOC) + @echo BUNDLE_LIBDB=$(BUNDLE_LIBDB) + @echo BUNDLE_BDBREADERS=$(BUNDLE_BDBREADERS) + @echo CLANG_ON=$(CLANG_ON) + @echo ASAN_ON=$(ASAN_ON) + @echo MSAN_ON=$(MSAN_ON) + @echo TSAN_ON=$(TSAN_ON) + @echo UBSAN_ON=$(UBSAN_ON) + @echo COCKPIT_ON=$(COCKPIT_ON) + @echo JEMALLOC_URL=$(JEMALLOC_URL) + @echo LIBDB_URL=$(LIBDB_URL) + +d2: + echo $(wildcard /usr/include/db.hX) + echo $(wildcard /usr/include/db.h) diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in index 2d5aff99c8..c684d5a901 100644 --- a/rpm/389-ds-base.spec.in +++ b/rpm/389-ds-base.spec.in @@ -21,6 +21,8 @@ %endif %endif +%bcond libbdb_ro %{!defined rhel} + # This is used in certain builds to help us know if it has extra features. %global variant base %global prerel __VERSION_PREREL__%{nil} @@ -107,9 +109,11 @@ BuildRequires: libtsan BuildRequires: libubsan %endif %endif +%if %{without libbdb_ro} %if %{without bundle_libdb} BuildRequires: libdb-devel %endif +%endif # The following are needed to build the snmp ldap-agent BuildRequires: net-snmp-devel @@ -179,16 +183,22 @@ Requires: cyrus-sasl-md5 # This is optionally supported by us, as we use it in our tests Requires: cyrus-sasl-plain # this is needed for backldbm +%if %{with libbdb_ro} +Requires: %{name}-robdb-libs-%{version} +%else %if %{without bundle_libdb} Requires: libdb %endif +%endif Requires: lmdb # This picks up libperl.so as a Requires, so we add this versioned one Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) # Needed by logconv.pl +%if %{without libbdb_ro} %if %{without bundle_libdb} Requires: perl-DB_File %endif +%endif Requires: perl-Archive-Tar %if 0%{?fedora} >= 33 || 0%{?rhel} >= 9 Requires: perl-debugger @@ -220,6 +230,17 @@ isn't what you want. Please contact support immediately. Please see http://seclists.org/oss-sec/2016/q1/363 for more information. %endif +%if %{with libbdb_ro} +%package robdb-libs +Summary: Read-only Berkeley Database Library +License: GPL-2.0-or-later OR LGPL-2.1-or-later + +%description robdb-libs +The %{name}-robdb-lib package contains a library derived from rpm +project (https://github.com/rpm-software-management/rpm) that provides +some basic functions to search and read Berkeley Database records +%endif + %package libs Summary: Core libraries for 389 Directory Server (%{variant}) @@ -423,6 +444,9 @@ popd autoreconf -fiv %configure \ +%if %{with libbdb_ro} + --with-libbdb-ro \ +%endif %if %{with bundle_libdb} --with-bundle-libdb=%{_builddir}/%{libdb_base_version}/BUILD/%{libdb_base_dir}/dist/dist-tls \ %endif @@ -528,6 +552,24 @@ cp -pa $libdbbuilddir/dist/dist-tls/.libs/%{libdb_bundle_name} $RPM_BUILD_ROOT%{ popd %endif +%if %{with libbdb_ro} +mkdir -p ../robdb +pushd ../robdb +tar -xjf %{_sourcedir}/%{name}-%{version}.tar.bz2 --transform "s,^%{name}-%{version}/lib/librobdb,.," %{name}-%{version}/lib/librobdb/* +cp -pa COPYING COPYING.librobdb +cp -pa COPYING %{_builddir}/%{name}-%{version}/COPYING.librobdb +cp -pa COPYING.RPM %{_builddir}/%{name}-%{version}/COPYING.RPM +install -m 0755 -d %{buildroot}/%{_libdir} +install -m 0755 -d %{buildroot}/%{_docdir}/%{name}-robdb-libs +install -m 0755 -d %{buildroot}/%{_licensedir}/%{name} +install -m 0755 -d %{buildroot}/%{_licensedir}/%{name}-robdb-libs +install -m 0644 $PWD/README.md %{buildroot}/%{_docdir}/%{name}-robdb-libs/README.md +install -m 0644 $PWD/COPYING %{buildroot}/%{_licensedir}/%{name}-robdb-libs/COPYING +install -m 0644 $PWD/COPYING.RPM %{buildroot}/%{_licensedir}/%{name}-robdb-libs/COPYING.RPM +install -m 0644 $PWD/COPYING.librobdb %{buildroot}/%{_licensedir}/%{name}/COPYING.librobdb +install -m 0644 $PWD/COPYING %{buildroot}/%{_licensedir}/%{name}/COPYING.RPM +popd +%endif %check # This checks the code, if it fails it prints why, then re-raises the fail to shortcircuit the rpm build. @@ -540,11 +582,11 @@ if ! make DESTDIR="$RPM_BUILD_ROOT" check; then cat ./test-suite.log && false; f %post if [ -n "$DEBUGPOSTTRANS" ] ; then - output=$DEBUGPOSTTRANS - output2=${DEBUGPOSTTRANS}.upgrade +output=$DEBUGPOSTTRANS +output2=${DEBUGPOSTTRANS}.upgrade else - output=/dev/null - output2=/dev/null +output=/dev/null +output2=/dev/null fi # reload to pick up any changes to systemd files @@ -564,11 +606,11 @@ HOMEDIR="/usr/share/dirsrv" getent group $GROUPNAME >/dev/null || groupadd -f -g $ALLOCATED_GID -r $GROUPNAME if ! getent passwd $USERNAME >/dev/null ; then - if ! getent passwd $ALLOCATED_UID >/dev/null ; then - useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME - else - useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME - fi +if ! getent passwd $ALLOCATED_UID >/dev/null ; then +useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME +else +useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME +fi fi # Reload our sysctl before we restart (if we can) @@ -578,46 +620,46 @@ sysctl --system &> $output; true instbase="%{_sysconfdir}/%{pkgname}" ninst=0 for dir in $instbase/slapd-* ; do - echo dir = $dir >> $output 2>&1 || : - if [ ! -d "$dir" ] ; then continue ; fi - case "$dir" in *.removed) continue ;; esac - basename=`basename $dir` - inst="%{pkgname}@`echo $basename | sed -e 's/slapd-//g'`" - echo found instance $inst - getting status >> $output 2>&1 || : - if /bin/systemctl -q is-active $inst ; then - echo instance $inst is running >> $output 2>&1 || : - instances="$instances $inst" - else - echo instance $inst is not running >> $output 2>&1 || : - fi - ninst=`expr $ninst + 1` +echo dir = $dir >> $output 2>&1 || : +if [ ! -d "$dir" ] ; then continue ; fi +case "$dir" in *.removed) continue ;; esac +basename=`basename $dir` +inst="%{pkgname}@`echo $basename | sed -e 's/slapd-//g'`" +echo found instance $inst - getting status >> $output 2>&1 || : +if /bin/systemctl -q is-active $inst ; then +echo instance $inst is running >> $output 2>&1 || : +instances="$instances $inst" +else +echo instance $inst is not running >> $output 2>&1 || : +fi +ninst=`expr $ninst + 1` done if [ $ninst -eq 0 ] ; then - echo no instances to upgrade >> $output 2>&1 || : - exit 0 # have no instances to upgrade - just skip the rest +echo no instances to upgrade >> $output 2>&1 || : +exit 0 # have no instances to upgrade - just skip the rest else - # restart running instances - echo shutting down all instances . . . >> $output 2>&1 || : - for inst in $instances ; do - echo stopping instance $inst >> $output 2>&1 || : - /bin/systemctl stop $inst >> $output 2>&1 || : - done - for inst in $instances ; do - echo starting instance $inst >> $output 2>&1 || : - /bin/systemctl start $inst >> $output 2>&1 || : - done +# restart running instances +echo shutting down all instances . . . >> $output 2>&1 || : +for inst in $instances ; do +echo stopping instance $inst >> $output 2>&1 || : +/bin/systemctl stop $inst >> $output 2>&1 || : +done +for inst in $instances ; do +echo starting instance $inst >> $output 2>&1 || : +/bin/systemctl start $inst >> $output 2>&1 || : +done fi %preun if [ $1 -eq 0 ]; then # Final removal - # remove instance specific service files/links - rm -rf %{_sysconfdir}/systemd/system/%{groupname}.wants/* > /dev/null 2>&1 || : +# remove instance specific service files/links +rm -rf %{_sysconfdir}/systemd/system/%{groupname}.wants/* > /dev/null 2>&1 || : fi %postun if [ $1 = 0 ]; then # Final removal - rm -rf /var/run/%{pkgname} +rm -rf /var/run/%{pkgname} fi %post snmp @@ -754,6 +796,16 @@ fi %doc README.md %endif +%if %{with libbdb_ro} +%files robdb-libs +%license COPYING.librobdb COPYING.RPM +%doc %{_defaultdocdir}/%{name}-robdb-libs/README.md +/usr/lib64/dirsrv/librobdb.so +%{_licensedir}/%{name}-robdb-libs/COPYING +%{_licensedir}/%{name}/COPYING.RPM +%{_licensedir}/%{name}/COPYING.librobdb +%endif + %changelog %autochangelog From 875f3955db43a4266c7fe8b90d0457015f50fc4a Mon Sep 17 00:00:00 2001 From: Pierre Rogier Date: Wed, 4 Dec 2024 15:43:33 +0100 Subject: [PATCH 2/4] issue 6430 - Fix review comments --- .../back-ldbm/db-bdb/bdb_bdbreader_glue.c | 4 +- ldap/servers/slapd/back-ldbm/dbimpl.c | 3 - lib/librobdb/README.md | 6 +- lib/librobdb/robdb.spec | 7 +- rpm/389-ds-base.spec.in | 74 +++++++++---------- 5 files changed, 48 insertions(+), 46 deletions(-) diff --git a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c index 539bb9d73a..77cb1570e1 100644 --- a/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c +++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c @@ -9,8 +9,6 @@ #include "bdb_layer.h" #include -#define DEBUG 1 - /* * This file contains the stub that transform usual bdb API (limited to the function 389-ds needs to export a db and a changelog * to bdb_ro callbacks @@ -248,7 +246,7 @@ int db_close(DB *db, u_int32_t flags) int dbc_close(DBC *dbc) { - bdbreader_bdb_close(dbc->impl); + bdbreader_cur_close(dbc->impl); dbc->impl = NULL; slapi_ch_free((void **)&dbc); return DB_SUCCESS; diff --git a/ldap/servers/slapd/back-ldbm/dbimpl.c b/ldap/servers/slapd/back-ldbm/dbimpl.c index 487dc44d1e..f00779c3ce 100644 --- a/ldap/servers/slapd/back-ldbm/dbimpl.c +++ b/ldap/servers/slapd/back-ldbm/dbimpl.c @@ -397,7 +397,6 @@ const char *dblayer_op2str(dbi_op_t op) return str[idx]; } -<<<<<<< HEAD /* Get the li_directory directory from the database instance name - * Caller should free the returned value */ @@ -440,8 +439,6 @@ get_li_directory(const char *fname) } /* Open db env, db and db file privately (for dbscan) */ -======= -/* Open db env, db and db file privately (used by dbscan) */ int dblayer_private_open(const char *plgname, const char *dbfilename, int rw, Slapi_Backend **be, dbi_env_t **env, dbi_db_t **db) { struct ldbminfo *li; diff --git a/lib/librobdb/README.md b/lib/librobdb/README.md index c2c87cf6e4..a79bca9ea4 100644 --- a/lib/librobdb/README.md +++ b/lib/librobdb/README.md @@ -18,9 +18,13 @@ See test/test.c (Using a 389ds entries database as example, It shows how to dump # Running tests dnf install -y dist/RPMS/*/*.rpm - make test +or + +make localtest + + # LICENSE Same as lib part for rpm: GPLv2 or alternatively LGPL (See COPYING and COPYING.RPM for full details) diff --git a/lib/librobdb/robdb.spec b/lib/librobdb/robdb.spec index f7072d9b62..0bf4150725 100644 --- a/lib/librobdb/robdb.spec +++ b/lib/librobdb/robdb.spec @@ -3,9 +3,9 @@ Version: 1.1 Release: %{autorelease -n %{?dist}} Summary: Provide basic functions to search and read Berkeley Database records -License: GPL-2.0-or-later +License: GPL-2.0-or-later OR LGPL-2.1-or-later URL: https://github.com/389ds/389-ds-base/lib/librobdb -Source0: %{name}-%{version}.tar.bz2 +Source0: %{name}-%{version}.tar.bz2 BuildRequires: gcc # Requires: @@ -46,6 +46,9 @@ some basic functions to search and read Berkeley Database records %{?ldconfig_scriptlets} +%check +make localtest + %files libs %license COPYING COPYING.RPM diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in index c684d5a901..b01ea9a16a 100644 --- a/rpm/389-ds-base.spec.in +++ b/rpm/389-ds-base.spec.in @@ -582,11 +582,11 @@ if ! make DESTDIR="$RPM_BUILD_ROOT" check; then cat ./test-suite.log && false; f %post if [ -n "$DEBUGPOSTTRANS" ] ; then -output=$DEBUGPOSTTRANS -output2=${DEBUGPOSTTRANS}.upgrade + output=$DEBUGPOSTTRANS + output2=${DEBUGPOSTTRANS}.upgrade else -output=/dev/null -output2=/dev/null + output=/dev/null + output2=/dev/null fi # reload to pick up any changes to systemd files @@ -606,11 +606,11 @@ HOMEDIR="/usr/share/dirsrv" getent group $GROUPNAME >/dev/null || groupadd -f -g $ALLOCATED_GID -r $GROUPNAME if ! getent passwd $USERNAME >/dev/null ; then -if ! getent passwd $ALLOCATED_UID >/dev/null ; then -useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME -else -useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME -fi + if ! getent passwd $ALLOCATED_UID >/dev/null ; then + useradd -r -u $ALLOCATED_UID -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME + else + useradd -r -g $GROUPNAME -d $HOMEDIR -s /sbin/nologin -c "user for 389-ds-base" $USERNAME + fi fi # Reload our sysctl before we restart (if we can) @@ -620,46 +620,46 @@ sysctl --system &> $output; true instbase="%{_sysconfdir}/%{pkgname}" ninst=0 for dir in $instbase/slapd-* ; do -echo dir = $dir >> $output 2>&1 || : -if [ ! -d "$dir" ] ; then continue ; fi -case "$dir" in *.removed) continue ;; esac -basename=`basename $dir` -inst="%{pkgname}@`echo $basename | sed -e 's/slapd-//g'`" -echo found instance $inst - getting status >> $output 2>&1 || : -if /bin/systemctl -q is-active $inst ; then -echo instance $inst is running >> $output 2>&1 || : -instances="$instances $inst" -else -echo instance $inst is not running >> $output 2>&1 || : -fi -ninst=`expr $ninst + 1` + echo dir = $dir >> $output 2>&1 || : + if [ ! -d "$dir" ] ; then continue ; fi + case "$dir" in *.removed) continue ;; esac + basename=`basename $dir` + inst="%{pkgname}@`echo $basename | sed -e 's/slapd-//g'`" + echo found instance $inst - getting status >> $output 2>&1 || : + if /bin/systemctl -q is-active $inst ; then + echo instance $inst is running >> $output 2>&1 || : + instances="$instances $inst" + else + echo instance $inst is not running >> $output 2>&1 || : + fi + ninst=`expr $ninst + 1` done if [ $ninst -eq 0 ] ; then -echo no instances to upgrade >> $output 2>&1 || : -exit 0 # have no instances to upgrade - just skip the rest + echo no instances to upgrade >> $output 2>&1 || : + exit 0 # have no instances to upgrade - just skip the rest else -# restart running instances -echo shutting down all instances . . . >> $output 2>&1 || : -for inst in $instances ; do -echo stopping instance $inst >> $output 2>&1 || : -/bin/systemctl stop $inst >> $output 2>&1 || : -done -for inst in $instances ; do -echo starting instance $inst >> $output 2>&1 || : -/bin/systemctl start $inst >> $output 2>&1 || : -done + # restart running instances + echo shutting down all instances . . . >> $output 2>&1 || : + for inst in $instances ; do + echo stopping instance $inst >> $output 2>&1 || : + /bin/systemctl stop $inst >> $output 2>&1 || : + done + for inst in $instances ; do + echo starting instance $inst >> $output 2>&1 || : + /bin/systemctl start $inst >> $output 2>&1 || : + done fi %preun if [ $1 -eq 0 ]; then # Final removal -# remove instance specific service files/links -rm -rf %{_sysconfdir}/systemd/system/%{groupname}.wants/* > /dev/null 2>&1 || : + # remove instance specific service files/links + rm -rf %{_sysconfdir}/systemd/system/%{groupname}.wants/* > /dev/null 2>&1 || : fi %postun if [ $1 = 0 ]; then # Final removal -rm -rf /var/run/%{pkgname} + rm -rf /var/run/%{pkgname} fi %post snmp From 0db4461d616dedc703bd2e9b01c65f88cb970b9a Mon Sep 17 00:00:00 2001 From: Pierre Rogier Date: Thu, 5 Dec 2024 15:14:34 +0100 Subject: [PATCH 3/4] Issue 6430 - Fix spec file URL --- lib/librobdb/robdb.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/librobdb/robdb.spec b/lib/librobdb/robdb.spec index 0bf4150725..8d3a27e0fe 100644 --- a/lib/librobdb/robdb.spec +++ b/lib/librobdb/robdb.spec @@ -4,7 +4,7 @@ Release: %{autorelease -n %{?dist}} Summary: Provide basic functions to search and read Berkeley Database records License: GPL-2.0-or-later OR LGPL-2.1-or-later -URL: https://github.com/389ds/389-ds-base/lib/librobdb +URL: https://github.com/389ds/389-ds-base/tree/main/lib/librobdb Source0: %{name}-%{version}.tar.bz2 BuildRequires: gcc From d633be9b7dc573874d31012dcbcb22b62a47ea6b Mon Sep 17 00:00:00 2001 From: progier389 Date: Thu, 9 Jan 2025 16:18:10 +0100 Subject: [PATCH 4/4] Apply Viktor's suggestions from code review Co-authored-by: Viktor Ashirov --- rpm.mk | 2 +- rpm/389-ds-base.spec.in | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rpm.mk b/rpm.mk index c7a69dba5e..41e2f6cfe8 100644 --- a/rpm.mk +++ b/rpm.mk @@ -36,7 +36,7 @@ else BUNDLE_BDBREADERS ?= 0 endif endif -RPMBUILD_OPTIONS += $(if $(filter 1, $(BUNDLE_BDBREADERS)),--with libbdb-ro,--without libbdb-ro) +RPMBUILD_OPTIONS += $(if $(filter 1, $(BUNDLE_BDBREADERS)),--with libbdb_ro,--without libbdb_ro) # Some sanitizers are supported only by clang diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in index b01ea9a16a..2629279231 100644 --- a/rpm/389-ds-base.spec.in +++ b/rpm/389-ds-base.spec.in @@ -184,7 +184,7 @@ Requires: cyrus-sasl-md5 Requires: cyrus-sasl-plain # this is needed for backldbm %if %{with libbdb_ro} -Requires: %{name}-robdb-libs-%{version} +Requires: %{name}-robdb-libs= %{version}-%{release} %else %if %{without bundle_libdb} Requires: libdb @@ -800,7 +800,7 @@ fi %files robdb-libs %license COPYING.librobdb COPYING.RPM %doc %{_defaultdocdir}/%{name}-robdb-libs/README.md -/usr/lib64/dirsrv/librobdb.so +%{_libdir}/%{pkgname}/librobdb.so %{_licensedir}/%{name}-robdb-libs/COPYING %{_licensedir}/%{name}/COPYING.RPM %{_licensedir}/%{name}/COPYING.librobdb