diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 76a1eb4b07..f42686cff1 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -101,7 +101,13 @@ jobs: sudo docker exec $CID sh -c "systemctl enable --now cockpit.socket" sudo docker exec $CID sh -c "mkdir -p /workspace/assets/cores && chmod 777 /workspace{,/assets{,/cores}}" sudo docker exec $CID sh -c "echo '/workspace/assets/cores/core.%e.%P' > /proc/sys/kernel/core_pattern" - sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=bdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }} + if sudo docker exec $CID sh -c "test -f /usr/lib64/dirsrv/librobdb.so" + then + echo "Tests skipped because read-only Berkeley Database is installed." > pytest.html + echo "'Tests skipped because read-only Berkeley Database is installed.'" > pytest.xml + else + sudo docker exec -e WEBUI=1 -e NSSLAPD_DB_LIB=bdb -e DEBUG=pw:api -e PASSWD="${PASSWD}" $CID py.test --suppress-no-test-exit-code -m "not flaky" --junit-xml=pytest.xml --html=pytest.html --browser=firefox --browser=chromium -v dirsrvtests/tests/suites/${{ matrix.suite }} + fi - name: Make the results file readable by all if: always() diff --git a/Makefile.am b/Makefile.am index dfaaa47dca..5d1023d6ba 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) @@ -326,6 +333,9 @@ bin_PROGRAMS = dbscan \ # ---------------------------------------------------------------------------------------- server_LTLIBRARIES = libslapd.la libldaputil.la libns-dshttpd.la librewriters.la +if WITH_LIBBDB_RO +server_LTLIBRARIES += librobdb.la +endif lib_LTLIBRARIES = libsvrcore.la @@ -1196,19 +1206,26 @@ 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) + ROBDB_INC = -I$(srcdir)/lib/librobdb/lib +else if BUNDLE_LIBDB # db-bdb sources are compiled within libback-bdb.so DB_BDB_WITHIN_BACKLDBM = @@ -1222,6 +1239,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 @@ -1298,11 +1329,24 @@ libback_ldbm_la_SOURCES = ldap/servers/slapd/back-ldbm/ancestorid.c \ $(DB_BDB_WITHIN_BACKLDBM) -libback_ldbm_la_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS) $(DB_INC) +libback_ldbm_la_CPPFLAGS = $(AM_CPPFLAGS) $(DSPLUGIN_CPPFLAGS) $(DB_INC) $(ROBDB_INC) 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/dirsrvtests/tests/data/bdb_instances/instances.tgz b/dirsrvtests/tests/data/bdb_instances/instances.tgz new file mode 100644 index 0000000000..c7691ffa78 Binary files /dev/null and b/dirsrvtests/tests/data/bdb_instances/instances.tgz differ diff --git a/dirsrvtests/tests/suites/clu/dsctl_dblib_test.py b/dirsrvtests/tests/suites/clu/dsctl_dblib_test.py index 141384bb43..5e805fb6df 100644 --- a/dirsrvtests/tests/suites/clu/dsctl_dblib_test.py +++ b/dirsrvtests/tests/suites/clu/dsctl_dblib_test.py @@ -11,13 +11,14 @@ import ldap import os import time -from lib389._constants import DEFAULT_SUFFIX +from lib389._constants import DEFAULT_SUFFIX, BDB_IMPL_STATUS from lib389.backend import DatabaseConfig from lib389.cli_ctl.dblib import (FakeArgs, dblib_bdb2mdb, dblib_mdb2bdb, dblib_cleanup) from lib389.idm.user import UserAccounts from lib389.replica import ReplicationManager from lib389.topologies import topology_m2 as topo_m2, topology_st as topo_st from lib389.utils import check_plugin_strings +from lib389.cli_ctl.dblib import get_bdb_impl_status log = logging.getLogger(__name__) @@ -86,7 +87,7 @@ def _check_db(inst, log, impl): assert db_files != bdb_list assert db_files == mdb_list - +@pytest.mark.skipif(get_bdb_impl_status() == BDB_IMPL_STATUS.READ_ONLY, reason = 'Cannot read with read-only bdb') def test_dblib_migration(init_user): """ Verify dsctl dblib xxxxxxx sub commands (migration between bdb and lmdb) diff --git a/dirsrvtests/tests/suites/lib389/config_compare_test.py b/dirsrvtests/tests/suites/lib389/config_compare_test.py index 3eb3d0ea4d..fca33665f8 100644 --- a/dirsrvtests/tests/suites/lib389/config_compare_test.py +++ b/dirsrvtests/tests/suites/lib389/config_compare_test.py @@ -13,6 +13,8 @@ from lib389.topologies import topology_i2 from lib389.config import Config from lib389.dseldif import DSEldif +from lib389.cli_ctl.dblib import get_bdb_impl_status +from lib389._constants import BDB_IMPL_STATUS pytestmark = pytest.mark.tier1 @@ -47,7 +49,6 @@ def test_config_compare(topology_i2): assert Config.compare(st1_config, st2_config) - @pytest.fixture(scope="function", params=db_types_and_states) def set_db_type_and_state(topology_i2, request): """ @@ -72,6 +73,7 @@ def fin(): return (dbtype,state) +@pytest.mark.skipif(get_bdb_impl_status() == BDB_IMPL_STATUS.READ_ONLY, reason="This test cannot run if bdb is read-only") def test_get_db_lib(request, topology_i2, set_db_type_and_state): """ Check that get_db_lib() returns the configured database type. diff --git a/dirsrvtests/tests/suites/upgrade/upgrade_bdb2mdb_test.py b/dirsrvtests/tests/suites/upgrade/upgrade_bdb2mdb_test.py new file mode 100644 index 0000000000..3430e28949 --- /dev/null +++ b/dirsrvtests/tests/suites/upgrade/upgrade_bdb2mdb_test.py @@ -0,0 +1,244 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2025 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- +# + +import os +import logging +import pwd +import pytest +import re +import socket +import subprocess +import tarfile +import time +from contextlib import suppress, chdir +from itertools import permutations +from lib389.cli_base import FakeArgs +from lib389.cli_ctl.dblib import get_bdb_impl_status, dblib_bdb2mdb +from lib389._constants import * +from lib389.dseldif import DSEldif +from lib389 import DirSrv +from lib389.replica import ReplicationManager +from lib389.topologies import topology_m2 as topo_m2 +from lib389.utils import ( + get_default_db_lib, + resolve_selinux_path, + selinux_label_file, + selinux_label_port, + selinux_present, + ) +from pathlib import Path + +log = logging.getLogger(__name__) + +# Environmaent variable used to generate the tarball +GENTARBALL = "GENERATE_BDB_TARBALL" +CURRENT_FILE = os.path.realpath(__file__) +TARFILENAME = f'{Path(CURRENT_FILE).parents[2]}/data/bdb_instances/instances.tgz' + +class MigrationHandler: + def __init__(self): + self.hostname = socket.gethostname() + self.uid = os.getuid() + self.gid = os.getgid() + self.idir = os.getenv("PREFIX", "/") + self.inst_list=[] + self.username = pwd.getpwuid(self.uid).pw_name + # Determine the instances names + with tarfile.open(name=TARFILENAME, mode='r:gz') as tar: + names = [] + for member in tar: + match = re.match('.*/slapd-([^/]*)/dse.ldif$',member.path) + if match and match.group(1) not in names: + names.append(match.group(1)) + self.names = names + log.info(f'MigrationHandler has following instances: {names}') + + + def replace_dse_line(self, line, old_hostname): + if old_hostname: + line = line.replace(old_hostname, self.hostname) + if self.idir != '/': + for name in ( '/etc/', '/var/l', '/run/', ): + line = line.replace(f' {name}', f' {self.idir}/{name}') + if line.startswith('nsslapd-localuser:'): + line = f'nsslapd-localuser: {self.username}\n' + return line + + def remap_dse(self, path): + old_hostname = None + tmppath = f'{path}.tmp' + with open(path, 'rt') as fin: + with open(tmppath, 'wt') as fout: + for line in fin: + match = re.match(r'nsslapd-localhost:\s*(\S*)',line) + if match: + old_hostname = match.group(1) + fout.write(self.replace_dse_line(line, old_hostname)) + os.remove(path) + os.rename(tmppath, path) + + def tar_filter(self, member, path): + fullpath = f'{path}/{member.path}' + # Do not try to overwrite existing files except dse.ldif + if os.path.exists(fullpath) and not member.path.endswith('/dse.ldif'): + return None + # use the current user credentials + member.uid = self.uid + member.gid = self.gid + # Security: reject tricky files that may be in tar ball + return tarfile.tar_filter(member, path) + + def relabel_selinux(self): + if not selinux_present(): + return + for inst in self.inst_list: + log.info("Performing SELinux labeling on instance {inst.serverid} ...") + dse = DSEldif(inst) + + selinux_attr_labels = { + (DN_CONFIG, 'nsslapd-bakdir'): 'dirsrv_var_lib_t', + (DN_CONFIG, 'nsslapd-certdir'): 'dirsrv_config_t', + (DN_CONFIG, 'nsslapd-ldifdir'): 'dirsrv_var_lib_t', + (DN_CONFIG, 'nsslapd-lockdir'): 'dirsrv_var_lock_t', + (DN_CONFIG, 'nsslapd-rundir'): 'dirsrv_var_run_t', + (DN_CONFIG, 'nsslapd-schemadir'): 'dirsrv_config_t', + (DN_CONFIG, 'nsslapd-tmpdir'): 'tmp_t', + (DN_CONFIG_LDBM, 'nsslapd-db-home-directory'): 'dirsrv_tmpfs_t', + (DN_CONFIG_LDBM, 'nsslapd-directory'): 'dirsrv_var_lib_t', + } + # Generates the path -> label dict + selinux_labels = { dse.get(pair[0], pair[1], single=True) : label for pair,label in selinux_attr_labels.items() } + log_dir = os.path.dirname(dse.get(DN_CONFIG, 'nsslapd-accesslog', single=True)) + selinux_attr_labels[log_dir] = 'dirsrv_var_log_t' + + for path, label in selinux_labels.items(): + with suppress(ValueError): + selinux_label_file(resolve_selinux_path(str(path)), label) + + for port_attr in ( 'nsslapd-port', 'nsslapd-securePort' ): + port = dse.get(DN_CONFIG, port_attr, single=True) + if port is None or port == '0': + continue + selinux_label_port(port) + + def dirsrv_instances(self, ignore_errors=False): + inst_list = [] + for name in self.names: + inst = DirSrv() + try: + inst.local_simple_allocate(name, binddn=DN_DM, password=PW_DM) + except FileNotFoundError as ex: + if ignore_errors is not True: + raise ex + continue + inst.setup_ldapi() + inst_list.append(inst) + return inst_list + + + def extract_instances(self): + with tarfile.open(name=TARFILENAME, mode='r:gz') as tar: + tar.extractall(path=self.idir, filter=self.tar_filter) + + # Fix the dse.ldif + for name in self.names: + self.remap_dse(f'{self.idir}/etc/dirsrv/slapd-{name}/dse.ldif') + + # Create missing directory + os.makedirs(f'{self.idir}/var/log/dirsrv/slapd-supplier1', mode=0o750, exist_ok=True) + os.makedirs(f'{self.idir}/var/log/dirsrv/slapd-supplier2', mode=0o750, exist_ok=True) + os.makedirs(f'{self.idir}/run/lock/dirsrv/slapd-supplier1', mode=0o750, exist_ok=True) + os.makedirs(f'{self.idir}/run/lock/dirsrv/slapd-supplier2', mode=0o750, exist_ok=True) + + # Generate DirSrv instances + self.inst_list = self.dirsrv_instances() + + # Relabel + if self.uid == 0: + self.relabel_selinux() + + + def remove_instances(self): + for inst in self.dirsrv_instances(ignore_errors=True): + inst.delete() + + + def migrate2mdb(self): + args = FakeArgs() + args.tmpdir = None + for inst in self.inst_list: + log.info(f'Migrating instance {inst.serverid} from bdb to mdb') + dblib_bdb2mdb(inst, log, args) + inst.start() + inst.open() + + +def strip_path(path): + return re.match(r'^/*([^/].*)$', path).group(1) + + +@pytest.mark.skipif(get_default_db_lib() != "bdb", reason = f'Requires bdb mode') +@pytest.mark.skipif(os.getenv(GENTARBALL) is None, reason = f'Requires setting {GENTARBALL} environment variable') +def test_generate_tarball(topo_m2): + """Test Generate the tarball for test_upgradefrombdb + + :id: 0325c4fe-da66-11ef-98fc-482ae39447e5 + :setup: two suppliers + :steps: + 1. Check that replication is working + 2. Generaters the tarball + :expectedresults: + 1. Success + 2. Success + """ + idir = os.getenv("PREFIX", "/") + repl = ReplicationManager(DEFAULT_SUFFIX) + for i1,i2 in permutations(topo_m2, 2): + log.info(f'Testing replication {i1.serverid} --> {i2.serverid}') + repl.test_replication(i1, i2) + tardir = Path(TARFILENAME).parent + os.makedirs(tardir, mode = 0o755, exist_ok = True) + with tarfile.open(name=TARFILENAME, mode='w:gz') as tar, chdir(idir): + for inst in topo_m2: + name = inst.serverid + tar.add(strip_path(f'{idir}/etc/dirsrv/slapd-{name}')) + tar.add(strip_path(f'{idir}/var/lib/dirsrv/slapd-{name}/db')) + + +#@pytest.mark.skipif(get_bdb_impl_status() != BDB_IMPL_STATUS.READ_ONLY, reason = 'Already tested through clu/dsctl_dblib_test.py:test_dblib_migration') +def test_upgradefrombdb(): + """Test upgrade from bdb to mdb + + :id: f0f02d12-da4f-11ef-966f-482ae39447e5 + :setup: None + :steps: + 1. Extract bdb instances from the tar ball + 2. Migrate the instances to mdb + 3. Check that replication is still working + :expectedresults: + 1. Success + 2. Success + 3. Success + """ + + handler = MigrationHandler() + handler.remove_instances() + handler.extract_instances() + handler.migrate2mdb() + repl = ReplicationManager(DEFAULT_SUFFIX) + for i1,i2 in permutations(handler.inst_list, 2): + log.info(f'Testing replication {i1.serverid} --> {i2.serverid}') + repl.test_replication(i1, i2) + handler.remove_instances() + +if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode + pytest.main(["-s", CURRENT_FILE]) + 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..77cb1570e1 --- /dev/null +++ b/ldap/servers/slapd/back-ldbm/db-bdb/bdb_bdbreader_glue.c @@ -0,0 +1,489 @@ +/** 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 + +/* + * 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_cur_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..f00779c3ce 100644 --- a/ldap/servers/slapd/back-ldbm/dbimpl.c +++ b/ldap/servers/slapd/back-ldbm/dbimpl.c @@ -454,6 +454,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 +542,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 a47846c503..517bd954c5 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("bdbreader_bdb_open", &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; @@ -1462,9 +1475,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..a79bca9ea4 --- /dev/null +++ b/lib/librobdb/README.md @@ -0,0 +1,30 @@ +# 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 + +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/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..8d3a27e0fe --- /dev/null +++ b/lib/librobdb/robdb.spec @@ -0,0 +1,67 @@ +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 OR LGPL-2.1-or-later +URL: https://github.com/389ds/389-ds-base/tree/main/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} + +%check +make localtest + + +%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 0000000000..abefbce1c3 Binary files /dev/null and b/lib/librobdb/tests/test.db differ 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..a27c134d7c 100644 --- a/rpm.mk +++ b/rpm.mk @@ -26,6 +26,11 @@ 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)") +# Check if BUNDLE_BDBREADERS is enabled. +BUNDLE_BDBREADERS = $(shell ./rpm/is-robdb-used $(BUNDLE_LIBDB)) +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 +116,7 @@ endif fi ; \ if [ $(BUNDLE_LIBDB) -eq 1 ]; then \ curl -LO $(LIBDB_URL) ; \ - fi + fi ; rpmroot: rm -rf $(RPMBUILD) @@ -149,6 +154,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 +170,22 @@ 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) diff --git a/rpm/389-ds-base.spec.in b/rpm/389-ds-base.spec.in index 95c8e962c5..88e20e6dfd 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}-%{release} +%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 @@ -223,6 +233,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}) @@ -426,6 +447,11 @@ popd autoreconf -fiv %configure \ +%if %{with libbdb_ro} + --with-libbdb-ro \ +%else + --without-libbdb-ro \ +%endif %if %{with bundle_libdb} --with-bundle-libdb=%{_builddir}/%{libdb_base_version}/BUILD/%{libdb_base_dir}/dist/dist-tls \ %endif @@ -531,6 +557,21 @@ cp -pa $libdbbuilddir/dist/dist-tls/.libs/%{libdb_bundle_name} $RPM_BUILD_ROOT%{ popd %endif +%if %{with libbdb_ro} +pushd lib/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 %{buildroot}/%{_licensedir}/%{name}/COPYING.librobdb +install -m 0644 $PWD/COPYING.RPM %{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. @@ -697,6 +738,9 @@ fi %exclude %{_libdir}/%{pkgname}/lib/libjemalloc_pic.a %exclude %{_libdir}/%{pkgname}/lib/pkgconfig %endif +%if %{with libbdb_ro} +%exclude %{_libdir}/%{pkgname}/librobdb.so +%endif %files devel %doc LICENSE LICENSE.GPLv3+ LICENSE.openssl README.devel @@ -759,6 +803,17 @@ fi %doc README.md %endif +%if %{with libbdb_ro} +%files robdb-libs +%license COPYING.librobdb COPYING.RPM +%doc %{_defaultdocdir}/%{name}-robdb-libs/README.md +%{_libdir}/%{pkgname}/librobdb.so +%{_licensedir}/%{name}-robdb-libs/COPYING +%{_licensedir}/%{name}/COPYING.RPM +%{_licensedir}/%{name}/COPYING.librobdb + +%endif + %changelog %autochangelog diff --git a/rpm/is-robdb-used b/rpm/is-robdb-used new file mode 100755 index 0000000000..6db27623cb --- /dev/null +++ b/rpm/is-robdb-used @@ -0,0 +1,23 @@ +#!/bin/bash + +# Determine if Read Only Berkeley Database is needed. + +BUNDLE_LIBDB="$1" + +rc() +{ + echo $1 + exit 0 +} + +# Not needed if libdb is bundled (Typically on RHEL) +[ x$BUNDLE_LIBDB = x1 ] && rc 0 +# Needed if libdb is not available +[ ! -f /usr/include/db.h ] && rc 1 +# Needed on Fedora and CentOs +[ -f /etc/fedora-release ] && rc 1 +[ -f /etc/centos-release ] && rc 1 +# Still support full bdb +rc 0 + + diff --git a/src/Cargo.lock b/src/Cargo.lock index ac51bde43e..03e3240b5b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -41,23 +41,23 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -105,12 +105,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -175,18 +176,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -203,18 +204,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "entryuuid" @@ -240,9 +241,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys", @@ -250,9 +251,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fernet" @@ -295,9 +296,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hashbrown" @@ -344,24 +345,24 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "librnsslapd" @@ -384,9 +385,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "lock_api" @@ -421,33 +422,33 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ - "adler", + "adler2", ] [[package]] name = "object" -version = "0.36.1" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -466,14 +467,14 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.95", ] [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -533,21 +534,24 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-hack" @@ -557,9 +561,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -579,9 +583,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -633,9 +637,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags 2.6.0", "errno", @@ -658,35 +662,42 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.95", ] [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "slapd" version = "0.1.0" @@ -728,9 +739,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.72" +version = "2.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" dependencies = [ "proc-macro2", "quote", @@ -739,12 +750,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", + "once_cell", "rustix", "windows-sys", ] @@ -766,9 +779,9 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "tokio" -version = "1.38.1" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "pin-project-lite", @@ -777,13 +790,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.95", ] [[package]] @@ -797,9 +810,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "uuid" @@ -818,9 +831,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -846,9 +859,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ "windows-sys", ] @@ -861,9 +874,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.52.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] @@ -932,6 +945,27 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.95", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -949,5 +983,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.72", + "syn 2.0.95", ] diff --git a/src/lib389/lib389/cli_ctl/dblib.py b/src/lib389/lib389/cli_ctl/dblib.py index 053a72d61c..85cb1cce33 100644 --- a/src/lib389/lib389/cli_ctl/dblib.py +++ b/src/lib389/lib389/cli_ctl/dblib.py @@ -51,18 +51,18 @@ def __init__(self, *args, **kwargs): def get_bdb_impl_status(): backldbm = 'libback-ldbm' - bundledbdb_plugin = 'libback-ldbm' - robdb_symbol = 'bdbro_getcb_vector' + bundledbdb_plugin = 'libback-bdb' + robdb_symbol = 'bdbreader_bdb_open' libdb = 'libdb-' plgstrs = check_plugin_strings(backldbm, [bundledbdb_plugin, robdb_symbol, libdb]) + if plgstrs[robdb_symbol] is True: + # read-only bdb build + return BDB_IMPL_STATUS.READ_ONLY if plgstrs[bundledbdb_plugin] is True: # bundled bdb build if find_plugin_path(bundledbdb_plugin): return BDB_IMPL_STATUS.BUNDLED return BDB_IMPL_STATUS.NONE - if plgstrs[robdb_symbol] is True: - # read-only bdb build - return BDB_IMPL_STATUS.READ_ONLY if plgstrs[libdb] is True: # standard bdb package build return BDB_IMPL_STATUS.STANDARD diff --git a/src/lib389/lib389/topologies.py b/src/lib389/lib389/topologies.py index eda0fd8baf..e7445245e6 100644 --- a/src/lib389/lib389/topologies.py +++ b/src/lib389/lib389/topologies.py @@ -22,6 +22,7 @@ from lib389.nss_ssl import NssSsl from lib389._constants import * from lib389.cli_base import LogCapture +from lib389.cli_ctl.dblib import get_bdb_impl_status TLS_HOSTNAME_CHECK = os.getenv('TLS_HOSTNAME_CHECK', default=True) HAPROXY_TRUSTED_IP = os.getenv('HAPROXY_TRUSTED_IP', default='')