summaryrefslogtreecommitdiff
path: root/dbm
diff options
context:
space:
mode:
authorPaul Querna <pquerna@apache.org>2009-03-24 10:32:34 +0000
committerPaul Querna <pquerna@apache.org>2009-03-24 10:32:34 +0000
commitdfd4f72bed0d7ac95c8ee1a27a6aa652bd766e52 (patch)
tree69804a4de7433f4755bd62c647dee518c48c673a /dbm
parent97a7d58c22e482e25154e5e46c7dd91d6222a947 (diff)
downloadapr-dfd4f72bed0d7ac95c8ee1a27a6aa652bd766e52.tar.gz
Merge APR-Util trunk into APR.
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@757704 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'dbm')
-rw-r--r--dbm/NWGNUdbmdb297
-rw-r--r--dbm/NWGNUdbmgdbm296
-rw-r--r--dbm/NWGNUmakefile251
-rw-r--r--dbm/apr_dbm.c296
-rw-r--r--dbm/apr_dbm_berkeleydb.c404
-rw-r--r--dbm/apr_dbm_db.dsp215
-rw-r--r--dbm/apr_dbm_gdbm.c255
-rw-r--r--dbm/apr_dbm_gdbm.dsp215
-rw-r--r--dbm/apr_dbm_ndbm.c238
-rw-r--r--dbm/apr_dbm_sdbm.c224
-rw-r--r--dbm/sdbm/sdbm.c584
-rw-r--r--dbm/sdbm/sdbm_hash.c63
-rw-r--r--dbm/sdbm/sdbm_lock.c79
-rw-r--r--dbm/sdbm/sdbm_pair.c319
-rw-r--r--dbm/sdbm/sdbm_pair.h40
-rw-r--r--dbm/sdbm/sdbm_private.h84
-rw-r--r--dbm/sdbm/sdbm_tune.h40
17 files changed, 3900 insertions, 0 deletions
diff --git a/dbm/NWGNUdbmdb b/dbm/NWGNUdbmdb
new file mode 100644
index 000000000..e60e108df
--- /dev/null
+++ b/dbm/NWGNUdbmdb
@@ -0,0 +1,297 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)\build\NWGNUhead.inc
+endif
+
+#include $(APR)\build\NWGNUcustom.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+DB_INC = $(DBSDK)/inc
+DB_IMP = $(DBSDK)/imp/libdb47.imp
+DB_LIB = $(DBSDK)/lib/libdb47.lib
+DB_NLM = libdb47
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include/arch/netware \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(APRUTIL)/include/private \
+ $(APR) \
+ $(DB_INC) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ -DAPU_DSO_MODULE_BUILD \
+ -DAPU_HAVE_DB=1 \
+ -DAPU_HAVE_DB_VERSION=4 \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+ifdef LINK_STATIC
+XLFLAGS += \
+ -l $(DBSDK)/lib \
+ $(EOLIST)
+endif
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = dbmdb
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Portability Runtime Library $(VERSION_STR) DBM Berkeley DB Driver Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = dbmdb
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)\$(NLM_NAME).nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/apr_dbm_berkeleydb.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ libcpre.o \
+ $(EOLIST)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+ $(DB_LIB) \
+ $(EOLIST)
+endif
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ aprlib \
+ libc \
+ $(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+ $(DB_NLM) \
+ $(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @$(APR)/aprlib.imp \
+ @libc.imp \
+ $(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+ @$(DB_IMP) \
+ $(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ apr_dbm_type_db \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
+
+
diff --git a/dbm/NWGNUdbmgdbm b/dbm/NWGNUdbmgdbm
new file mode 100644
index 000000000..048f6fc79
--- /dev/null
+++ b/dbm/NWGNUdbmgdbm
@@ -0,0 +1,296 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+ifndef EnvironmentDefined
+include $(APR_WORK)\build\NWGNUhead.inc
+endif
+
+#include $(APR)\build\NWGNUcustom.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+# LINK_STATIC = 1
+
+# for now defined here - should finally go into build/NWGNUenvironment.inc
+GDBM_INC = $(GDBMSDK)/inc
+GDBM_IMP = $(GDBMSDK)/imp/libgdbm.imp
+GDBM_LIB = $(GDBMSDK)/lib/libgdbm.lib
+GDBM_NLM = libgdbm
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include/arch/netware \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(APRUTIL)/include/private \
+ $(APR) \
+ $(GDBM_INC) \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ -DAPU_DSO_MODULE_BUILD \
+ -DAPU_HAVE_GDBM=1 \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+ifdef LINK_STATIC
+XLFLAGS += \
+ -l $(GDBMSDK)/lib \
+ $(EOLIST)
+endif
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME = dbmgdbm
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Apache Portability Runtime Library $(VERSION_STR) GDBM Driver Module
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = dbmgdbm
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 8192
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)\$(NLM_NAME).nlm \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(OBJDIR)/apr_dbm_gdbm.o \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ libcpre.o \
+ $(EOLIST)
+
+ifeq ($(LINK_STATIC),1)
+FILES_nlm_libs += \
+ $(GDBM_LIB) \
+ $(EOLIST)
+endif
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ aprlib \
+ libc \
+ $(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_modules += \
+ $(GDBM_NLM) \
+ $(EOLIST)
+endif
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @$(APR)/aprlib.imp \
+ @libc.imp \
+ $(EOLIST)
+
+ifneq ($(LINK_STATIC),1)
+FILES_nlm_Ximports += \
+ @$(GDBM_IMP) \
+ $(EOLIST)
+endif
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ apr_dbm_type_gdbm \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
+
+
diff --git a/dbm/NWGNUmakefile b/dbm/NWGNUmakefile
new file mode 100644
index 000000000..e30372fa9
--- /dev/null
+++ b/dbm/NWGNUmakefile
@@ -0,0 +1,251 @@
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+# These flags will be added to the link.opt file
+#
+XLFLAGS += \
+ $(EOLIST)
+
+#
+# These values will be appended to the correct variables based on the value of
+# RELEASE
+#
+ifeq "$(RELEASE)" "debug"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "noopt"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+ifeq "$(RELEASE)" "release"
+XINCDIRS += \
+ $(EOLIST)
+
+XCFLAGS += \
+ $(EOLIST)
+
+XDEFINES += \
+ $(EOLIST)
+
+XLFLAGS += \
+ $(EOLIST)
+endif
+
+#
+# These are used by the link target if an NLM is being generated
+# This is used by the link 'name' directive to name the nlm. If left blank
+# TARGET_nlm (see below) will be used.
+#
+NLM_NAME =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(AP_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM =
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If these are specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS =
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled
+# by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+ifeq "$(APU_HAVE_DB)" "1"
+TARGET_nlm += $(OBJDIR)/dbmdb.nlm $(OBJDIR)/dbmdb.nlm $(EOLIST)
+endif
+ifeq "$(APU_HAVE_GDBM)" "1"
+TARGET_nlm += $(OBJDIR)/dbmgdbm.nlm $(OBJDIR)/dbmgdbm.nlm $(EOLIST)
+endif
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(EOLIST)
+
+#
+# These are the LIB files needed to create the NLM target above.
+# These will be added as a library command in the link.opt file.
+#
+FILES_nlm_libs = \
+ $(EOLIST)
+
+#
+# These are the modules that the above NLM target depends on to load.
+# These will be added as a module command in the link.opt file.
+#
+FILES_nlm_modules = \
+ $(EOLIST)
+
+#
+# If the nlm has a msg file, put it's path here
+#
+FILE_nlm_msg =
+
+#
+# If the nlm has a hlp file put it's path here
+#
+FILE_nlm_hlp =
+
+#
+# If this is specified, it will override $(NWOS)\copyright.txt.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (leave this section alone)
+#
+
+libs :: $(OBJDIR) $(TARGET_lib)
+
+nlms :: libs $(TARGET_nlm)
+
+#
+# Updated this target to create necessary directories and copy files to the
+# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms $(INSTDIRS) FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALLBASE)
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
+
diff --git a/dbm/apr_dbm.c b/dbm/apr_dbm.c
new file mode 100644
index 000000000..613d0fe1a
--- /dev/null
+++ b/dbm/apr_dbm.c
@@ -0,0 +1,296 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_dso.h"
+#include "apr_hash.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr_general.h"
+
+#include "apu_config.h"
+#include "apu.h"
+#include "apu_internal.h"
+#include "apu_version.h"
+#include "apr_dbm_private.h"
+#include "apu_select_dbm.h"
+#include "apr_dbm.h"
+#include "apr_dbm_private.h"
+
+/* ### note: the setting of DBM_VTABLE will go away once we have multiple
+ ### DBMs in here.
+ ### Well, that day is here. So, do we remove DBM_VTABLE and the old
+ ### API entirely? Oh, what to do. We need an APU_DEFAULT_DBM #define.
+ ### Sounds like a job for autoconf. */
+
+#if APU_USE_DB
+#define DBM_VTABLE apr_dbm_type_db
+#define DBM_NAME "db"
+#elif APU_USE_GDBM
+#define DBM_VTABLE apr_dbm_type_gdbm
+#define DBM_NAME "gdbm"
+#elif APU_USE_NDBM
+#define DBM_VTABLE apr_dbm_type_ndbm
+#define DBM_NAME "ndbm"
+#elif APU_USE_SDBM
+#define DBM_VTABLE apr_dbm_type_sdbm
+#define DBM_NAME "sdbm"
+#else /* Not in the USE_xDBM list above */
+#error a DBM implementation was not specified
+#endif
+
+#if APU_DSO_BUILD
+
+static apr_hash_t *drivers = NULL;
+
+static apr_status_t dbm_term(void *ptr)
+{
+ /* set drivers to NULL so init can work again */
+ drivers = NULL;
+
+ /* Everything else we need is handled by cleanups registered
+ * when we created mutexes and loaded DSOs
+ */
+ return APR_SUCCESS;
+}
+
+#endif /* APU_DSO_BUILD */
+
+static apr_status_t dbm_open_type(apr_dbm_type_t const* * vtable,
+ const char *type,
+ apr_pool_t *pool)
+{
+#if !APU_DSO_BUILD
+
+ *vtable = NULL;
+ if (!strcasecmp(type, "default")) *vtable = &DBM_VTABLE;
+#if APU_HAVE_DB
+ else if (!strcasecmp(type, "db")) *vtable = &apr_dbm_type_db;
+#endif
+ else if (*type && !strcasecmp(type + 1, "dbm")) {
+#if APU_HAVE_GDBM
+ if (*type == 'G' || *type == 'g') *vtable = &apr_dbm_type_gdbm;
+#endif
+#if APU_HAVE_NDBM
+ if (*type == 'N' || *type == 'n') *vtable = &apr_dbm_type_ndbm;
+#endif
+#if APU_HAVE_SDBM
+ if (*type == 'S' || *type == 's') *vtable = &apr_dbm_type_sdbm;
+#endif
+ /* avoid empty block */ ;
+ }
+ if (*vtable)
+ return APR_SUCCESS;
+ return APR_ENOTIMPL;
+
+#else /* APU_DSO_BUILD */
+
+ char modname[32];
+ char symname[34];
+ apr_dso_handle_sym_t symbol;
+ apr_status_t rv;
+ int usertype = 0;
+
+ if (!strcasecmp(type, "default")) type = DBM_NAME;
+ else if (!strcasecmp(type, "db")) type = "db";
+ else if (*type && !strcasecmp(type + 1, "dbm")) {
+ if (*type == 'G' || *type == 'g') type = "gdbm";
+ else if (*type == 'N' || *type == 'n') type = "ndbm";
+ else if (*type == 'S' || *type == 's') type = "sdbm";
+ }
+ else usertype = 1;
+
+ if (!drivers)
+ {
+ apr_pool_t *parent;
+
+ /* Top level pool scope, need process-scope lifetime */
+ for (parent = pool; parent; parent = apr_pool_parent_get(pool))
+ pool = parent;
+
+ /* deprecate in 2.0 - permit implicit initialization */
+ apu_dso_init(pool);
+
+ drivers = apr_hash_make(pool);
+ apr_hash_set(drivers, "sdbm", APR_HASH_KEY_STRING, &apr_dbm_type_sdbm);
+
+ apr_pool_cleanup_register(pool, NULL, dbm_term,
+ apr_pool_cleanup_null);
+ }
+
+ rv = apu_dso_mutex_lock();
+ if (rv) {
+ *vtable = NULL;
+ return rv;
+ }
+
+ *vtable = apr_hash_get(drivers, type, APR_HASH_KEY_STRING);
+ if (*vtable) {
+ apu_dso_mutex_unlock();
+ return APR_SUCCESS;
+ }
+
+ /* The driver DSO must have exactly the same lifetime as the
+ * drivers hash table; ignore the passed-in pool */
+ pool = apr_hash_pool_get(drivers);
+
+#if defined(NETWARE)
+ apr_snprintf(modname, sizeof(modname), "dbm%s.nlm", type);
+#elif defined(WIN32)
+ apr_snprintf(modname, sizeof(modname),
+ "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".dll", type);
+#else
+ apr_snprintf(modname, sizeof(modname),
+ "apr_dbm_%s-" APU_STRINGIFY(APU_MAJOR_VERSION) ".so", type);
+#endif
+ apr_snprintf(symname, sizeof(symname), "apr_dbm_type_%s", type);
+
+ rv = apu_dso_load(NULL, &symbol, modname, symname, pool);
+ if (rv == APR_SUCCESS || rv == APR_EINIT) { /* previously loaded?!? */
+ *vtable = symbol;
+ if (usertype)
+ type = apr_pstrdup(pool, type);
+ apr_hash_set(drivers, type, APR_HASH_KEY_STRING, *vtable);
+ rv = APR_SUCCESS;
+ }
+ else
+ *vtable = NULL;
+
+ apu_dso_mutex_unlock();
+ return rv;
+
+#endif /* APU_DSO_BUILD */
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char *type,
+ const char *pathname,
+ apr_int32_t mode,
+ apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ apr_dbm_type_t const* vtable = NULL;
+ apr_status_t rv = dbm_open_type(&vtable, type, pool);
+
+ if (rv == APR_SUCCESS) {
+ rv = (vtable->open)(pdb, pathname, mode, perm, pool);
+ }
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ return apr_dbm_open_ex(pdb, DBM_NAME, pathname, mode, perm, pool);
+}
+
+APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
+{
+ (*dbm->type->close)(dbm);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue)
+{
+ return (*dbm->type->fetch)(dbm, key, pvalue);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ return (*dbm->type->store)(dbm, key, value);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
+{
+ return (*dbm->type->del)(dbm, key);
+}
+
+APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ return (*dbm->type->exists)(dbm, key);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ return (*dbm->type->firstkey)(dbm, pkey);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ return (*dbm->type->nextkey)(dbm, pkey);
+}
+
+APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ (*dbm->type->freedatum)(dbm, data);
+}
+
+APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+ char *errbuf, apr_size_t errbufsize)
+{
+ if (errcode != NULL)
+ *errcode = dbm->errcode;
+
+ /* assert: errbufsize > 0 */
+
+ if (dbm->errmsg == NULL)
+ *errbuf = '\0';
+ else
+ (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
+ return errbuf;
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p,
+ const char *type,
+ const char *pathname,
+ const char **used1,
+ const char **used2)
+{
+ apr_dbm_type_t const* vtable;
+ apr_status_t rv = dbm_open_type(&vtable, type, p);
+
+ if (rv == APR_SUCCESS) {
+ (vtable->getusednames)(p, pathname, used1, used2);
+ return APR_SUCCESS;
+ }
+ return rv;
+}
+
+APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
+ const char *pathname,
+ const char **used1,
+ const char **used2)
+{
+ apr_dbm_get_usednames_ex(p, DBM_NAME, pathname, used1, used2);
+}
+
+/* Most DBM libraries take a POSIX mode for creating files. Don't trust
+ * the mode_t type, some platforms may not support it, int is safe.
+ */
+APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
+{
+ int mode = 0;
+
+ mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */
+ mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
+ mode |= 0007 & (perm); /* World maps 1 for 1 */
+ return mode;
+}
diff --git a/dbm/apr_dbm_berkeleydb.c b/dbm/apr_dbm_berkeleydb.c
new file mode 100644
index 000000000..0cbab82ba
--- /dev/null
+++ b/dbm/apr_dbm_berkeleydb.c
@@ -0,0 +1,404 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#define APU_WANT_DB
+#include "apu_want.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for abort() */
+#endif
+
+#include "apu_config.h"
+#include "apu.h"
+
+#if APU_HAVE_DB
+#include "apr_dbm_private.h"
+
+/*
+ * We pick up all varieties of Berkeley DB through db.h (included through
+ * apu_select_dbm.h). This code has been compiled/tested against DB1,
+ * DB_185, DB2, DB3, and DB4.
+ */
+
+#if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 4)
+/* We will treat anything greater than 4.1 as DB4.
+ * We can treat 4.0 as DB3.
+ */
+#if defined(DB_VERSION_MINOR) && (DB_VERSION_MINOR >= 1)
+#define DB_VER 4
+#else
+#define DB_VER 3
+#endif
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
+#define DB_VER 3
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
+#define DB_VER 2
+#else
+#define DB_VER 1
+#endif
+
+typedef struct {
+ DB *bdb;
+#if DB_VER != 1
+ DBC *curs;
+#endif
+} real_file_t;
+
+
+#if DB_VER == 1
+#define TXN_ARG
+#else
+#define TXN_ARG NULL,
+#endif
+
+#define GET_BDB(f) (((real_file_t *)(f))->bdb)
+
+#define do_fetch(bdb, k, v) ((*(bdb)->get)(bdb, TXN_ARG &(k), &(v), 0))
+
+#if DB_VER == 1
+#include <sys/fcntl.h>
+#define APR_DBM_DBMODE_RO O_RDONLY
+#define APR_DBM_DBMODE_RW O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
+#define APR_DBM_DBMODE_RWTRUNC (O_CREAT | O_RDWR | O_TRUNC)
+#else
+#define APR_DBM_DBMODE_RO DB_RDONLY
+#define APR_DBM_DBMODE_RW 0
+#define APR_DBM_DBMODE_RWCREATE DB_CREATE
+#define APR_DBM_DBMODE_RWTRUNC DB_TRUNCATE
+#endif /* DBVER == 1 */
+
+/* --------------------------------------------------------------------------
+**
+** UTILITY FUNCTIONS
+*/
+
+/* map a DB error to an apr_status_t */
+static apr_status_t db2s(int dberr)
+{
+ if (dberr != 0) {
+ /* ### need to fix this */
+ return APR_OS_START_USEERR + dberr;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ if (dbm_said == APR_SUCCESS) {
+ dbm->errcode = 0;
+ dbm->errmsg = NULL;
+ }
+ else {
+ /* ### need to fix. dberr was tossed in db2s(). */
+ /* ### use db_strerror() */
+ dbm->errcode = dbm_said;
+#if DB_VER == 1 || DB_VER == 2
+ dbm->errmsg = NULL;
+#else
+ dbm->errmsg = db_strerror(dbm_said - APR_OS_START_USEERR);
+#endif
+ rv = dbm_said;
+ }
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR BERKELEY DB
+**
+** ### we may need three sets of these: db1, db2, db3
+*/
+
+static apr_status_t vt_db_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ real_file_t file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ int dberr;
+
+#if DB_VER >= 3
+ if ((dberr = db_create(&file.bdb, NULL, 0)) == 0) {
+ if ((dberr = (*file.bdb->open)(file.bdb,
+#if DB_VER == 4
+ NULL,
+#endif
+ pathname, NULL,
+ DB_HASH, dbmode,
+ apr_posix_perms2mode(perm))) != 0) {
+ /* close the DB handler */
+ (void) (*file.bdb->close)(file.bdb, 0);
+ }
+ }
+ file.curs = NULL;
+#elif DB_VER == 2
+ dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
+ NULL, NULL, &file.bdb);
+ file.curs = NULL;
+#else
+ file.bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
+ DB_HASH, NULL);
+ if (file.bdb == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+ dberr = 0;
+#endif
+ if (dberr != 0)
+ return db2s(dberr);
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_db;
+ (*pdb)->file = apr_pmemdup(pool, &file, sizeof(file));
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_db_close(apr_dbm_t *dbm)
+{
+ (*GET_BDB(dbm->file)->close)(GET_BDB(dbm->file)
+#if DB_VER != 1
+ , 0
+#endif
+ );
+}
+
+static apr_status_t vt_db_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
+{
+ DBT ckey = { 0 };
+ DBT rd = { 0 };
+ int dberr;
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ dberr = do_fetch(GET_BDB(dbm->file), ckey, rd);
+
+ /* "not found" is not an error. return zero'd value. */
+ if (dberr ==
+#if DB_VER == 1
+ RET_SPECIAL
+#else
+ DB_NOTFOUND
+#endif
+ ) {
+ memset(&rd, 0, sizeof(rd));
+ dberr = 0;
+ }
+
+ pvalue->dptr = rd.data;
+ pvalue->dsize = rd.size;
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ DBT ckey = { 0 };
+ DBT cvalue = { 0 };
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ cvalue.data = value.dptr;
+ cvalue.size = value.dsize;
+
+ rv = db2s((*GET_BDB(dbm->file)->put)(GET_BDB(dbm->file),
+ TXN_ARG
+ &ckey,
+ &cvalue,
+ 0));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_db_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ DBT ckey = { 0 };
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ rv = db2s((*GET_BDB(dbm->file)->del)(GET_BDB(dbm->file),
+ TXN_ARG
+ &ckey,
+ 0));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_db_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ DBT ckey = { 0 }; /* converted key */
+ DBT data = { 0 };
+ int dberr;
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ dberr = do_fetch(GET_BDB(dbm->file), ckey, data);
+
+ /* note: the result data is "loaned" to us; we don't need to free it */
+
+ /* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
+ that *any* error means it doesn't exist. */
+ return dberr == 0;
+}
+
+static apr_status_t vt_db_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ real_file_t *f = dbm->file;
+ DBT first = { 0 };
+ DBT data = { 0 };
+ int dberr;
+
+#if DB_VER == 1
+ dberr = (*f->bdb->seq)(f->bdb, &first, &data, R_FIRST);
+#else
+ if ((dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs
+#if DB_VER >= 3 || ((DB_VERSION_MAJOR == 2) && (DB_VERSION_MINOR > 5))
+ , 0
+#endif
+ )) == 0) {
+ dberr = (*f->curs->c_get)(f->curs, &first, &data, DB_FIRST);
+ if (dberr == DB_NOTFOUND) {
+ memset(&first, 0, sizeof(first));
+ (*f->curs->c_close)(f->curs);
+ f->curs = NULL;
+ dberr = 0;
+ }
+ }
+#endif
+
+ pkey->dptr = first.data;
+ pkey->dsize = first.size;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ real_file_t *f = dbm->file;
+ DBT ckey = { 0 };
+ DBT data = { 0 };
+ int dberr;
+
+ ckey.data = pkey->dptr;
+ ckey.size = pkey->dsize;
+
+#if DB_VER == 1
+ dberr = (*f->bdb->seq)(f->bdb, &ckey, &data, R_NEXT);
+ if (dberr == RET_SPECIAL) {
+ dberr = 0;
+ ckey.data = NULL;
+ ckey.size = 0;
+ }
+#else
+ if (f->curs == NULL)
+ return APR_EINVAL;
+
+ dberr = (*f->curs->c_get)(f->curs, &ckey, &data, DB_NEXT);
+ if (dberr == DB_NOTFOUND) {
+ (*f->curs->c_close)(f->curs);
+ f->curs = NULL;
+ dberr = 0;
+ ckey.data = NULL;
+ ckey.size = 0;
+ }
+#endif
+
+ pkey->dptr = ckey.data;
+ pkey->dsize = ckey.size;
+
+ /* store any error info into DBM, and return a status code. */
+ /* ### or use db2s(dberr) instead of APR_SUCCESS? */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_db_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ /* nothing to do */
+}
+
+static void vt_db_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+
+APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_db = {
+ "db",
+
+ vt_db_open,
+ vt_db_close,
+ vt_db_fetch,
+ vt_db_store,
+ vt_db_del,
+ vt_db_exists,
+ vt_db_firstkey,
+ vt_db_nextkey,
+ vt_db_freedatum,
+ vt_db_usednames
+};
+
+#endif /* APU_HAVE_DB */
diff --git a/dbm/apr_dbm_db.dsp b/dbm/apr_dbm_db.dsp
new file mode 100644
index 000000000..6b7e838ab
--- /dev/null
+++ b/dbm/apr_dbm_db.dsp
@@ -0,0 +1,215 @@
+# Microsoft Developer Studio Project File - Name="apr_dbm_db" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbm_db - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "apr_dbm_db.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_dbm_db.mak" CFG="apr_dbm_db - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_dbm_db - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_db - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "apr_dbm_db - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbm_db-1.dll" /pdb:"Release\apr_dbm_db-1.pdb" /implib:"Release\apr_dbm_db-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbm_db-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_db - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbm_db-1.dll" /pdb:"Debug\apr_dbm_db-1.pdb" /implib:"Debug\apr_dbm_db-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbm_db-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_db - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbm_db-1.dll" /pdb:"x64\Release\apr_dbm_db-1.pdb" /implib:"x64\Release\apr_dbm_db-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbm_db-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_db - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_DB=1 /D APU_HAVE_DB_VERSION=4 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_db_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbm_db-1.res" /d DLL_NAME="apr_dbm_db" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libdb47.lib /nologo /base:"0x6EF00000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbm_db-1.dll" /pdb:"x64\Debug\apr_dbm_db-1.pdb" /implib:"x64\Debug\apr_dbm_db-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbm_db-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "apr_dbm_db - Win32 Release"
+# Name "apr_dbm_db - Win32 Debug"
+# Name "apr_dbm_db - x64 Release"
+# Name "apr_dbm_db - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbm_berkeleydb.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbm.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_select_dbm.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbm/apr_dbm_gdbm.c b/dbm/apr_dbm_gdbm.c
new file mode 100644
index 000000000..749447a0a
--- /dev/null
+++ b/dbm/apr_dbm_gdbm.c
@@ -0,0 +1,255 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu_config.h"
+#include "apu.h"
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for free() */
+#endif
+
+#if APU_HAVE_GDBM
+#include "apr_dbm_private.h"
+
+#include <gdbm.h>
+
+#define APR_DBM_DBMODE_RO GDBM_READER
+#define APR_DBM_DBMODE_RW GDBM_WRITER
+#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
+#define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB
+
+/* map a GDBM error to an apr_status_t */
+static apr_status_t g2s(int gerr)
+{
+ if (gerr == -1) {
+ /* ### need to fix this */
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t datum_cleanup(void *dptr)
+{
+ if (dptr)
+ free(dptr);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
+ dbm->errmsg = NULL;
+ }
+ else {
+ dbm->errmsg = gdbm_strerror(gdbm_errno);
+ rv = APR_EGENERAL; /* ### need something better */
+ }
+
+ /* captured it. clear it now. */
+ gdbm_errno = GDBM_NO_ERROR;
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR GDBM
+*/
+
+static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ GDBM_FILE file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ /* Note: stupid cast to get rid of "const" on the pathname */
+ file = gdbm_open((char *) pathname, 0, dbmode, apr_posix_perms2mode(perm),
+ NULL);
+
+ if (file == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_gdbm;
+ (*pdb)->file = file;
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_gdbm_close(apr_dbm_t *dbm)
+{
+ gdbm_close(dbm->file);
+}
+
+static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue)
+{
+ datum kd, rd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ rd = gdbm_fetch(dbm->file, kd);
+
+ pvalue->dptr = rd.dptr;
+ pvalue->dsize = rd.dsize;
+
+ if (pvalue->dptr)
+ apr_pool_cleanup_register(dbm->pool, pvalue->dptr, datum_cleanup,
+ apr_pool_cleanup_null);
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ int rc;
+ datum kd, vd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ vd.dptr = value.dptr;
+ vd.dsize = value.dsize;
+
+ rc = gdbm_store(dbm->file, kd, vd, GDBM_REPLACE);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, g2s(rc));
+}
+
+static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ int rc;
+ datum kd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ rc = gdbm_delete(dbm->file, kd);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, g2s(rc));
+}
+
+static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ datum kd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ return gdbm_exists(dbm->file, kd) != 0;
+}
+
+static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ datum rd;
+
+ rd = gdbm_firstkey(dbm->file);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ if (pkey->dptr)
+ apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
+ apr_pool_cleanup_null);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ datum kd, rd;
+
+ kd.dptr = pkey->dptr;
+ kd.dsize = pkey->dsize;
+
+ rd = gdbm_nextkey(dbm->file, kd);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ if (pkey->dptr)
+ apr_pool_cleanup_register(dbm->pool, pkey->dptr, datum_cleanup,
+ apr_pool_cleanup_null);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
+}
+
+static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
+ "gdbm",
+ vt_gdbm_open,
+ vt_gdbm_close,
+ vt_gdbm_fetch,
+ vt_gdbm_store,
+ vt_gdbm_del,
+ vt_gdbm_exists,
+ vt_gdbm_firstkey,
+ vt_gdbm_nextkey,
+ vt_gdbm_freedatum,
+ vt_gdbm_usednames
+};
+
+#endif /* APU_HAVE_GDBM */
diff --git a/dbm/apr_dbm_gdbm.dsp b/dbm/apr_dbm_gdbm.dsp
new file mode 100644
index 000000000..061cedf55
--- /dev/null
+++ b/dbm/apr_dbm_gdbm.dsp
@@ -0,0 +1,215 @@
+# Microsoft Developer Studio Project File - Name="apr_dbm_gdbm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=apr_dbm_gdbm - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "apr_dbm_gdbm.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "apr_dbm_gdbm.mak" CFG="apr_dbm_gdbm - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "apr_dbm_gdbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - x64 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "apr_dbm_gdbm - x64 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "apr_dbm_gdbm - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"Release/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"Release\apr_dbm_gdbm-1.dll" /pdb:"Release\apr_dbm_gdbm-1.pdb" /implib:"Release\apr_dbm_gdbm-1.lib" /MACHINE:X86 /opt:ref
+# Begin Special Build Tool
+TargetPath=Release\apr_dbm_gdbm-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_gdbm - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"Debug/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"Debug\apr_dbm_gdbm-1.dll" /pdb:"Debug\apr_dbm_gdbm-1.pdb" /implib:"Debug\apr_dbm_gdbm-1.lib" /MACHINE:X86
+# Begin Special Build Tool
+TargetPath=Debug\apr_dbm_gdbm-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_gdbm - x64 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "x64\Release"
+# PROP BASE Intermediate_Dir "x64\Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "x64\Release"
+# PROP Intermediate_Dir "x64\Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "../include" /I "../../apr/include" /I "../include/private" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /fo"x64/Release/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "NDEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Release\apr_dbm_gdbm-1.dll" /pdb:"x64\Release\apr_dbm_gdbm-1.pdb" /implib:"x64\Release\apr_dbm_gdbm-1.lib" /MACHINE:X64 /opt:ref
+# Begin Special Build Tool
+TargetPath=x64\Release\apr_dbm_gdbm-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ELSEIF "$(CFG)" == "apr_dbm_gdbm - x64 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "x64\Debug"
+# PROP BASE Intermediate_Dir "x64\Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "x64\Debug"
+# PROP Intermediate_Dir "x64\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /EHsc /c
+# ADD CPP /nologo /MDd /W3 /Zi /Od /I "../include" /I "../../apr/include" /I "../include/private" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APU_DSO_MODULE_BUILD" /D APU_HAVE_GDBM=1 /Fo"$(INTDIR)\" /Fd"$(INTDIR)\apr_dbm_gdbm_src" /FD /EHsc /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /fo"x64/Debug/apr_dbm_gdbm-1.res" /d DLL_NAME="apr_dbm_gdbm" /d "_DEBUG" /d "APU_VERSION_ONLY" /I "../include" /I "../../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib libgdbm.lib /nologo /base:"0x6EF10000" /subsystem:windows /dll /incremental:no /debug /out:"x64\Debug\apr_dbm_gdbm-1.dll" /pdb:"x64\Debug\apr_dbm_gdbm-1.pdb" /implib:"x64\Debug\apr_dbm_gdbm-1.lib" /MACHINE:X64
+# Begin Special Build Tool
+TargetPath=x64\Debug\apr_dbm_gdbm-1.dll
+SOURCE="$(InputPath)"
+PostBuild_Desc=Embed .manifest
+PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2
+# End Special Build Tool
+
+!ENDIF
+
+# Begin Target
+
+# Name "apr_dbm_gdbm - Win32 Release"
+# Name "apr_dbm_gdbm - Win32 Debug"
+# Name "apr_dbm_gdbm - x64 Release"
+# Name "apr_dbm_gdbm - x64 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\apr_dbm_gdbm.c
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\apr_dbm.h
+# End Source File
+# End Group
+# Begin Group "Internal Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_config.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_dbd_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_internal.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\include\private\apu_select_dbm.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\libaprutil.rc
+# End Source File
+# End Target
+# End Project
diff --git a/dbm/apr_dbm_ndbm.c b/dbm/apr_dbm_ndbm.c
new file mode 100644
index 000000000..7f3818624
--- /dev/null
+++ b/dbm/apr_dbm_ndbm.c
@@ -0,0 +1,238 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for free() */
+#endif
+
+#include "apu_config.h"
+#include "apu.h"
+
+#if APU_HAVE_NDBM
+#include "apr_dbm_private.h"
+
+#include <ndbm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define APR_DBM_DBMODE_RO O_RDONLY
+#define APR_DBM_DBMODE_RW O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_RDWR|O_CREAT)
+#define APR_DBM_DBMODE_RWTRUNC (O_RDWR|O_CREAT|O_TRUNC)
+
+/* map a NDBM error to an apr_status_t */
+static apr_status_t ndbm2s(int ndbmerr)
+{
+ if (ndbmerr == -1) {
+ /* ### need to fix this */
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ dbm->errmsg = NULL;
+ if (dbm_error((DBM*)dbm->file)) {
+ dbm->errmsg = NULL;
+ rv = APR_EGENERAL; /* ### need something better */
+ }
+
+ /* captured it. clear it now. */
+ dbm_clearerr((DBM*)dbm->file);
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR NDBM
+*/
+
+static apr_status_t vt_ndbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ DBM *file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ file = dbm_open(pathname, dbmode, apr_posix_perms2mode(perm));
+ if (file == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_ndbm;
+ (*pdb)->file = file;
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_ndbm_close(apr_dbm_t *dbm)
+{
+ dbm_close(dbm->file);
+}
+
+static apr_status_t vt_ndbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue)
+{
+ datum kd, rd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ rd = dbm_fetch(dbm->file, kd);
+
+ pvalue->dptr = rd.dptr;
+ pvalue->dsize = rd.dsize;
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ int rc;
+ datum kd, vd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ vd.dptr = value.dptr;
+ vd.dsize = value.dsize;
+
+ rc = dbm_store(dbm->file, kd, vd, DBM_REPLACE);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, ndbm2s(rc));
+}
+
+static apr_status_t vt_ndbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ int rc;
+ datum kd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ rc = dbm_delete(dbm->file, kd);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, ndbm2s(rc));
+}
+
+static int vt_ndbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ datum kd, rd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = key.dsize;
+
+ rd = dbm_fetch(dbm->file, kd);
+
+ return rd.dptr != NULL;
+}
+
+static apr_status_t vt_ndbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ datum rd;
+
+ rd = dbm_firstkey(dbm->file);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ datum kd, rd;
+
+ kd.dptr = pkey->dptr;
+ kd.dsize = pkey->dsize;
+
+ rd = dbm_nextkey(dbm->file);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_ndbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ /* nothing to do */
+}
+
+static void vt_ndbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_ndbm = {
+ "ndbm",
+ vt_ndbm_open,
+ vt_ndbm_close,
+ vt_ndbm_fetch,
+ vt_ndbm_store,
+ vt_ndbm_del,
+ vt_ndbm_exists,
+ vt_ndbm_firstkey,
+ vt_ndbm_nextkey,
+ vt_ndbm_freedatum,
+ vt_ndbm_usednames
+};
+
+#endif /* APU_HAVE_NDBM */
diff --git a/dbm/apr_dbm_sdbm.c b/dbm/apr_dbm_sdbm.c
new file mode 100644
index 000000000..6f531a176
--- /dev/null
+++ b/dbm/apr_dbm_sdbm.c
@@ -0,0 +1,224 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apu_config.h"
+#include "apu.h"
+
+#if APU_HAVE_SDBM
+
+#include "apr_dbm_private.h"
+#include "apr_sdbm.h"
+
+#define APR_DBM_DBMODE_RO (APR_READ | APR_BUFFERED)
+#define APR_DBM_DBMODE_RW (APR_READ | APR_WRITE)
+#define APR_DBM_DBMODE_RWCREATE (APR_READ | APR_WRITE | APR_CREATE)
+#define APR_DBM_DBMODE_RWTRUNC (APR_READ | APR_WRITE | APR_CREATE | \
+ APR_TRUNCATE)
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ dbm->errcode = dbm_said;
+
+ if (dbm_said != APR_SUCCESS) {
+ dbm->errmsg = apr_psprintf(dbm->pool, "%pm", &dbm_said);
+ } else {
+ dbm->errmsg = NULL;
+ }
+
+ return dbm_said;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR SDBM
+*/
+
+static apr_status_t vt_sdbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ apr_sdbm_t *file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ apr_status_t rv;
+
+ rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_sdbm;
+ (*pdb)->file = file;
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_sdbm_close(apr_dbm_t *dbm)
+{
+ apr_sdbm_close(dbm->file);
+}
+
+static apr_status_t vt_sdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue)
+{
+ apr_status_t rv;
+ apr_sdbm_datum_t kd, rd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = (int)key.dsize;
+
+ rv = apr_sdbm_fetch(dbm->file, &rd, kd);
+
+ pvalue->dptr = rd.dptr;
+ pvalue->dsize = rd.dsize;
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ apr_sdbm_datum_t kd, vd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = (int)key.dsize;
+
+ vd.dptr = value.dptr;
+ vd.dsize = (int)value.dsize;
+
+ rv = apr_sdbm_store(dbm->file, kd, vd, APR_SDBM_REPLACE);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ apr_sdbm_datum_t kd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = (int)key.dsize;
+
+ rv = apr_sdbm_delete(dbm->file, kd);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_sdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ int exists;
+ apr_sdbm_datum_t vd, kd;
+
+ kd.dptr = key.dptr;
+ kd.dsize = (int)key.dsize;
+
+ if (apr_sdbm_fetch(dbm->file, &vd, kd) != APR_SUCCESS)
+ exists = 0;
+ else
+ exists = vd.dptr != NULL;
+
+ return exists;
+}
+
+static apr_status_t vt_sdbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ apr_status_t rv;
+ apr_sdbm_datum_t rd;
+
+ rv = apr_sdbm_firstkey(dbm->file, &rd);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ apr_status_t rv;
+ apr_sdbm_datum_t rd;
+
+ rv = apr_sdbm_nextkey(dbm->file, &rd);
+
+ pkey->dptr = rd.dptr;
+ pkey->dsize = rd.dsize;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_sdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+}
+
+static void vt_sdbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrcat(pool, pathname, APR_SDBM_DIRFEXT, NULL);
+ *used2 = apr_pstrcat(pool, pathname, APR_SDBM_PAGFEXT, NULL);
+}
+
+APU_MODULE_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_sdbm = {
+ "sdbm",
+ vt_sdbm_open,
+ vt_sdbm_close,
+ vt_sdbm_fetch,
+ vt_sdbm_store,
+ vt_sdbm_del,
+ vt_sdbm_exists,
+ vt_sdbm_firstkey,
+ vt_sdbm_nextkey,
+ vt_sdbm_freedatum,
+ vt_sdbm_usednames
+};
+
+#endif /* APU_HAVE_SDBM */
diff --git a/dbm/sdbm/sdbm.c b/dbm/sdbm/sdbm.c
new file mode 100644
index 000000000..9dfcc4bce
--- /dev/null
+++ b/dbm/sdbm/sdbm.c
@@ -0,0 +1,584 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * ex-public domain, ported to APR for Apache 2
+ * core routines
+ */
+
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h> /* for memset() */
+#include <stdlib.h> /* for malloc() and free() */
+
+/*
+ * forward
+ */
+static int getdbit (apr_sdbm_t *, long);
+static apr_status_t setdbit(apr_sdbm_t *, long);
+static apr_status_t getpage(apr_sdbm_t *db, long);
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db);
+static apr_status_t makroom(apr_sdbm_t *, long, int);
+
+/*
+ * useful macros
+ */
+#define bad(x) ((x).dptr == NULL || (x).dsize <= 0)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+#define OFF_PAG(off) (apr_off_t) (off) * PBLKSIZ
+#define OFF_DIR(off) (apr_off_t) (off) * DBLKSIZ
+
+static const long masks[] = {
+ 000000000000, 000000000001, 000000000003, 000000000007,
+ 000000000017, 000000000037, 000000000077, 000000000177,
+ 000000000377, 000000000777, 000000001777, 000000003777,
+ 000000007777, 000000017777, 000000037777, 000000077777,
+ 000000177777, 000000377777, 000000777777, 000001777777,
+ 000003777777, 000007777777, 000017777777, 000037777777,
+ 000077777777, 000177777777, 000377777777, 000777777777,
+ 001777777777, 003777777777, 007777777777, 017777777777
+};
+
+const apr_sdbm_datum_t sdbm_nullitem = { NULL, 0 };
+
+static apr_status_t database_cleanup(void *data)
+{
+ apr_sdbm_t *db = data;
+
+ /*
+ * Can't rely on apr_sdbm_unlock, since it will merely
+ * decrement the refcnt if several locks are held.
+ */
+ if (db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK))
+ (void) apr_file_unlock(db->dirf);
+ (void) apr_file_close(db->dirf);
+ (void) apr_file_close(db->pagf);
+ free(db);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t prep(apr_sdbm_t **pdb, const char *dirname, const char *pagname,
+ apr_int32_t flags, apr_fileperms_t perms, apr_pool_t *p)
+{
+ apr_sdbm_t *db;
+ apr_status_t status;
+
+ *pdb = NULL;
+
+ db = malloc(sizeof(*db));
+ memset(db, 0, sizeof(*db));
+
+ db->pool = p;
+
+ /*
+ * adjust user flags so that WRONLY becomes RDWR,
+ * as required by this package. Also set our internal
+ * flag for RDONLY if needed.
+ */
+ if (!(flags & APR_WRITE)) {
+ db->flags |= SDBM_RDONLY;
+ }
+
+ /*
+ * adjust the file open flags so that we handle locking
+ * on our own (don't rely on any locking behavior within
+ * an apr_file_t, in case it's ever introduced, and set
+ * our own flag.
+ */
+ if (flags & APR_SHARELOCK) {
+ db->flags |= SDBM_SHARED;
+ flags &= ~APR_SHARELOCK;
+ }
+
+ flags |= APR_BINARY | APR_READ;
+
+ /*
+ * open the files in sequence, and stat the dirfile.
+ * If we fail anywhere, undo everything, return NULL.
+ */
+
+ if ((status = apr_file_open(&db->dirf, dirname, flags, perms, p))
+ != APR_SUCCESS)
+ goto error;
+
+ if ((status = apr_file_open(&db->pagf, pagname, flags, perms, p))
+ != APR_SUCCESS)
+ goto error;
+
+ if ((status = apr_sdbm_lock(db, (db->flags & SDBM_RDONLY)
+ ? APR_FLOCK_SHARED
+ : APR_FLOCK_EXCLUSIVE))
+ != APR_SUCCESS)
+ goto error;
+
+ /* apr_pcalloc zeroed the buffers
+ * apr_sdbm_lock stated the dirf->size and invalidated the cache
+ */
+
+ /*
+ * if we are opened in SHARED mode, unlock ourself
+ */
+ if (db->flags & SDBM_SHARED)
+ if ((status = apr_sdbm_unlock(db)) != APR_SUCCESS)
+ goto error;
+
+ /* make sure that we close the database at some point */
+ apr_pool_cleanup_register(p, db, database_cleanup, apr_pool_cleanup_null);
+
+ /* Done! */
+ *pdb = db;
+ return APR_SUCCESS;
+
+error:
+ if (db->dirf && db->pagf)
+ (void) apr_sdbm_unlock(db);
+ if (db->dirf != NULL)
+ (void) apr_file_close(db->dirf);
+ if (db->pagf != NULL) {
+ (void) apr_file_close(db->pagf);
+ }
+ free(db);
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *file,
+ apr_int32_t flags,
+ apr_fileperms_t perms, apr_pool_t *p)
+{
+ char *dirname = apr_pstrcat(p, file, APR_SDBM_DIRFEXT, NULL);
+ char *pagname = apr_pstrcat(p, file, APR_SDBM_PAGFEXT, NULL);
+
+ return prep(db, dirname, pagname, flags, perms, p);
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db)
+{
+ return apr_pool_cleanup_run(db->pool, db, database_cleanup);
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, apr_sdbm_datum_t *val,
+ apr_sdbm_datum_t key)
+{
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ *val = getpair(db->pagbuf, key);
+ /* ### do we want a not-found result? */
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+static apr_status_t write_page(apr_sdbm_t *db, const char *buf, long pagno)
+{
+ apr_status_t status;
+ apr_off_t off = OFF_PAG(pagno);
+
+ if ((status = apr_file_seek(db->pagf, APR_SET, &off)) == APR_SUCCESS)
+ status = apr_file_write_full(db->pagf, buf, PBLKSIZ, NULL);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db,
+ const apr_sdbm_datum_t key)
+{
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+ if (apr_sdbm_rdonly(db))
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ if (!delpair(db->pagbuf, key))
+ /* ### should we define some APRUTIL codes? */
+ status = APR_EGENERAL;
+ else
+ status = write_page(db, db->pagbuf, db->pagbno);
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
+ apr_sdbm_datum_t val, int flags)
+{
+ int need;
+ register long hash;
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+ if (apr_sdbm_rdonly(db))
+ return APR_EINVAL;
+ need = key.dsize + val.dsize;
+ /*
+ * is the pair too big (or too small) for this database ??
+ */
+ if (need < 0 || need > PAIRMAX)
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, (hash = exhash(key)))) == APR_SUCCESS) {
+
+ /*
+ * if we need to replace, delete the key/data pair
+ * first. If it is not there, ignore.
+ */
+ if (flags == APR_SDBM_REPLACE)
+ (void) delpair(db->pagbuf, key);
+ else if (!(flags & APR_SDBM_INSERTDUP) && duppair(db->pagbuf, key)) {
+ status = APR_EEXIST;
+ goto error;
+ }
+ /*
+ * if we do not have enough room, we have to split.
+ */
+ if (!fitpair(db->pagbuf, need))
+ if ((status = makroom(db, hash, need)) != APR_SUCCESS)
+ goto error;
+ /*
+ * we have enough room or split is successful. insert the key,
+ * and update the page file.
+ */
+ (void) putpair(db->pagbuf, key, val);
+
+ status = write_page(db, db->pagbuf, db->pagbno);
+ }
+
+error:
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static apr_status_t makroom(apr_sdbm_t *db, long hash, int need)
+{
+ long newp;
+ char twin[PBLKSIZ];
+ char *pag = db->pagbuf;
+ char *new = twin;
+ register int smax = SPLTMAX;
+ apr_status_t status;
+
+ do {
+ /*
+ * split the current page
+ */
+ (void) splpage(pag, new, db->hmask + 1);
+ /*
+ * address of the new page
+ */
+ newp = (hash & db->hmask) | (db->hmask + 1);
+
+ /*
+ * write delay, read avoidence/cache shuffle:
+ * select the page for incoming pair: if key is to go to the new page,
+ * write out the previous one, and copy the new one over, thus making
+ * it the current page. If not, simply write the new page, and we are
+ * still looking at the page of interest. current page is not updated
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
+ */
+ if (hash & (db->hmask + 1)) {
+ if ((status = write_page(db, db->pagbuf, db->pagbno))
+ != APR_SUCCESS)
+ return status;
+
+ db->pagbno = newp;
+ (void) memcpy(pag, new, PBLKSIZ);
+ }
+ else {
+ if ((status = write_page(db, new, newp)) != APR_SUCCESS)
+ return status;
+ }
+
+ if ((status = setdbit(db, db->curbit)) != APR_SUCCESS)
+ return status;
+ /*
+ * see if we have enough room now
+ */
+ if (fitpair(pag, need))
+ return APR_SUCCESS;
+ /*
+ * try again... update curbit and hmask as getpage would have
+ * done. because of our update of the current page, we do not
+ * need to read in anything. BUT we have to write the current
+ * [deferred] page out, as the window of failure is too great.
+ */
+ db->curbit = 2 * db->curbit
+ + ((hash & (db->hmask + 1)) ? 2 : 1);
+ db->hmask |= db->hmask + 1;
+
+ if ((status = write_page(db, db->pagbuf, db->pagbno))
+ != APR_SUCCESS)
+ return status;
+
+ } while (--smax);
+
+ /*
+ * if we are here, this is real bad news. After SPLTMAX splits,
+ * we still cannot fit the key. say goodnight.
+ */
+#if 0
+ (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+ /* ### ENOSPC not really appropriate but better than nothing */
+ return APR_ENOSPC;
+
+}
+
+/* Reads 'len' bytes from file 'f' at offset 'off' into buf.
+ * 'off' is given relative to the start of the file.
+ * If EOF is returned while reading, this is taken as success.
+ */
+static apr_status_t read_from(apr_file_t *f, void *buf,
+ apr_off_t off, apr_size_t len)
+{
+ apr_status_t status;
+
+ if ((status = apr_file_seek(f, APR_SET, &off)) != APR_SUCCESS ||
+ ((status = apr_file_read_full(f, buf, len, NULL)) != APR_SUCCESS)) {
+ /* if EOF is reached, pretend we read all zero's */
+ if (status == APR_EOF) {
+ memset(buf, 0, len);
+ status = APR_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db,
+ apr_sdbm_datum_t *key)
+{
+ apr_status_t status;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ /*
+ * start at page 0
+ */
+ if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(0), PBLKSIZ))
+ == APR_SUCCESS) {
+ db->pagbno = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+ status = getnext(key, db);
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db,
+ apr_sdbm_datum_t *key)
+{
+ apr_status_t status;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ status = getnext(key, db);
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+/*
+ * all important binary tree traversal
+ */
+static apr_status_t getpage(apr_sdbm_t *db, long hash)
+{
+ register int hbit;
+ register long dbit;
+ register long pagb;
+ apr_status_t status;
+
+ dbit = 0;
+ hbit = 0;
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+
+ debug(("dbit: %d...", dbit));
+
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+ /*
+ * see if the block we need is already in memory.
+ * note: this lookaside cache has about 10% hit rate.
+ */
+ if (pagb != db->pagbno) {
+ /*
+ * note: here, we assume a "hole" is read as 0s.
+ * if not, must zero pagbuf first.
+ * ### joe: this assumption was surely never correct? but
+ * ### we make it so in read_from anyway.
+ */
+ if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(pagb), PBLKSIZ))
+ != APR_SUCCESS)
+ return status;
+
+ if (!chkpage(db->pagbuf))
+ return APR_ENOSPC; /* ### better error? */
+ db->pagbno = pagb;
+
+ debug(("pag read: %d\n", pagb));
+ }
+ return APR_SUCCESS;
+}
+
+static int getdbit(apr_sdbm_t *db, long dbit)
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ)
+ != APR_SUCCESS)
+ return 0;
+
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+}
+
+static apr_status_t setdbit(apr_sdbm_t *db, long dbit)
+{
+ register long c;
+ register long dirb;
+ apr_status_t status;
+ apr_off_t off;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ))
+ != APR_SUCCESS)
+ return status;
+
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+
+ if (dbit >= db->maxbno)
+ db->maxbno += DBLKSIZ * BYTESIZ;
+
+ off = OFF_DIR(dirb);
+ if ((status = apr_file_seek(db->dirf, APR_SET, &off)) == APR_SUCCESS)
+ status = apr_file_write_full(db->dirf, db->dirbuf, DBLKSIZ, NULL);
+
+ return status;
+}
+
+/*
+* getnext - get the next key in the page, and if done with
+* the page, try the next page in sequence
+*/
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db)
+{
+ apr_status_t status;
+ for (;;) {
+ db->keyptr++;
+ *key = getnkey(db->pagbuf, db->keyptr);
+ if (key->dptr != NULL)
+ return APR_SUCCESS;
+ /*
+ * we either run out, or there is nothing on this page..
+ * try the next one... If we lost our position on the
+ * file, we will have to seek.
+ */
+ db->keyptr = 0;
+ if (db->pagbno != db->blkptr++) {
+ apr_off_t off = OFF_PAG(db->blkptr);
+ if ((status = apr_file_seek(db->pagf, APR_SET, &off))
+ != APR_SUCCESS)
+ return status;
+ }
+
+ db->pagbno = db->blkptr;
+ /* ### EOF acceptable here too? */
+ if ((status = apr_file_read_full(db->pagf, db->pagbuf, PBLKSIZ, NULL))
+ != APR_SUCCESS)
+ return status;
+ if (!chkpage(db->pagbuf))
+ return APR_EGENERAL; /* ### need better error */
+ }
+
+ /* NOTREACHED */
+}
+
+
+APU_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db)
+{
+ /* ### Should we return true if the first lock is a share lock,
+ * to reflect that apr_sdbm_store and apr_sdbm_delete will fail?
+ */
+ return (db->flags & SDBM_RDONLY) != 0;
+}
+
diff --git a/dbm/sdbm/sdbm_hash.c b/dbm/sdbm/sdbm_hash.c
new file mode 100644
index 000000000..e4d751794
--- /dev/null
+++ b/dbm/sdbm/sdbm_hash.c
@@ -0,0 +1,63 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+#include "apr_sdbm.h"
+#include "sdbm_private.h"
+
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599 nice.
+ * 65587 even better.
+ */
+long sdbm_hash(const char *str, int len)
+{
+ register unsigned long n = 0;
+
+#define DUFF /* go ahead and use the loop-unrolled version */
+#ifdef DUFF
+
+#define HASHC n = *str++ + 65599 * n
+
+ if (len > 0) {
+ register int loop = (len + 8 - 1) >> 3;
+
+ switch(len & (8 - 1)) {
+ case 0: do {
+ HASHC; case 7: HASHC;
+ case 6: HASHC; case 5: HASHC;
+ case 4: HASHC; case 3: HASHC;
+ case 2: HASHC; case 1: HASHC;
+ } while (--loop);
+ }
+
+ }
+#else
+ while (len--)
+ n = *str++ + 65599 * n;
+#endif
+ return n;
+}
diff --git a/dbm/sdbm/sdbm_lock.c b/dbm/sdbm/sdbm_lock.c
new file mode 100644
index 000000000..7d62ffd62
--- /dev/null
+++ b/dbm/sdbm/sdbm_lock.c
@@ -0,0 +1,79 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_info.h"
+#include "apr_file_io.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_private.h"
+#include "sdbm_tune.h"
+
+/* NOTE: this function may block until it acquires the lock */
+APU_DECLARE(apr_status_t) apr_sdbm_lock(apr_sdbm_t *db, int type)
+{
+ apr_status_t status;
+ int lock_type = type & APR_FLOCK_TYPEMASK;
+
+ if (!(lock_type == APR_FLOCK_SHARED || lock_type == APR_FLOCK_EXCLUSIVE))
+ return APR_EINVAL;
+
+ if (db->flags & SDBM_EXCLUSIVE_LOCK) {
+ ++db->lckcnt;
+ return APR_SUCCESS;
+ }
+ else if (db->flags & SDBM_SHARED_LOCK) {
+ /*
+ * Cannot promote a shared lock to an exlusive lock
+ * in a cross-platform compatibile manner.
+ */
+ if (type == APR_FLOCK_EXCLUSIVE)
+ return APR_EINVAL;
+ ++db->lckcnt;
+ return APR_SUCCESS;
+ }
+ /*
+ * zero size: either a fresh database, or one with a single,
+ * unsplit data page: dirpage is all zeros.
+ */
+ if ((status = apr_file_lock(db->dirf, type)) == APR_SUCCESS)
+ {
+ apr_finfo_t finfo;
+ if ((status = apr_file_info_get(&finfo, APR_FINFO_SIZE, db->dirf))
+ != APR_SUCCESS) {
+ (void) apr_file_unlock(db->dirf);
+ return status;
+ }
+
+ SDBM_INVALIDATE_CACHE(db, finfo);
+
+ ++db->lckcnt;
+ if (type == APR_FLOCK_SHARED)
+ db->flags |= SDBM_SHARED_LOCK;
+ else if (type == APR_FLOCK_EXCLUSIVE)
+ db->flags |= SDBM_EXCLUSIVE_LOCK;
+ }
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_unlock(apr_sdbm_t *db)
+{
+ if (!(db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK)))
+ return APR_EINVAL;
+ if (--db->lckcnt > 0)
+ return APR_SUCCESS;
+ db->flags &= ~(SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK);
+ return apr_file_unlock(db->dirf);
+}
diff --git a/dbm/sdbm/sdbm_pair.c b/dbm/sdbm/sdbm_pair.c
new file mode 100644
index 000000000..213020073
--- /dev/null
+++ b/dbm/sdbm/sdbm_pair.c
@@ -0,0 +1,319 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain.
+ *
+ * page-level routines
+ */
+
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h> /* for memset() */
+
+
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/*
+ * forward
+ */
+static int seepair(char *, int, char *, int);
+
+/*
+ * page format:
+ * +------------------------------+
+ * ino | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | - - - ----> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * calculating the offsets for free area: if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+ register int n;
+ register int off;
+ register int avail;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+ avail = off - (n + 1) * sizeof(short);
+ need += 2 * sizeof(short);
+
+ debug(("avail %d need %d\n", avail, need));
+
+ return need <= avail;
+}
+
+void
+putpair(pag, key, val)
+char *pag;
+apr_sdbm_datum_t key;
+apr_sdbm_datum_t val;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+/*
+ * enter the key first
+ */
+ off -= key.dsize;
+ (void) memcpy(pag + off, key.dptr, key.dsize);
+ ino[n + 1] = off;
+/*
+ * now the data
+ */
+ off -= val.dsize;
+ (void) memcpy(pag + off, val.dptr, val.dsize);
+ ino[n + 2] = off;
+/*
+ * adjust item count
+ */
+ ino[0] += 2;
+}
+
+apr_sdbm_datum_t
+getpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register int i;
+ register int n;
+ apr_sdbm_datum_t val;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return sdbm_nullitem;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return sdbm_nullitem;
+
+ val.dptr = pag + ino[i + 1];
+ val.dsize = ino[i] - ino[i + 1];
+ return val;
+}
+
+int
+duppair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register short *ino = (short *) pag;
+ return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+}
+
+apr_sdbm_datum_t
+getnkey(pag, num)
+char *pag;
+int num;
+{
+ apr_sdbm_datum_t key;
+ register int off;
+ register short *ino = (short *) pag;
+
+ num = num * 2 - 1;
+ if (ino[0] == 0 || num > ino[0])
+ return sdbm_nullitem;
+
+ off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+
+ key.dptr = pag + ino[num];
+ key.dsize = off - ino[num];
+
+ return key;
+}
+
+int
+delpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register int n;
+ register int i;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return 0;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+ if (i < n - 1) {
+ register int m;
+ register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+ register char *src = pag + ino[i + 1];
+ register short zoo = (short) (dst - src);
+
+ debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+ m = ino[i + 1] - ino[n];
+
+#undef DUFF /* just use memmove. it should be plenty fast. */
+#ifdef DUFF
+#define MOVB *--dst = *--src
+
+ if (m > 0) {
+ register int loop = (m + 8 - 1) >> 3;
+
+ switch (m & (8 - 1)) {
+ case 0: do {
+ MOVB; case 7: MOVB;
+ case 6: MOVB; case 5: MOVB;
+ case 4: MOVB; case 3: MOVB;
+ case 2: MOVB; case 1: MOVB;
+ } while (--loop);
+ }
+ }
+#else
+ dst -= m;
+ src -= m;
+ memmove(dst, src, m);
+#endif
+
+/*
+ * adjust offset index up
+ */
+ while (i < n - 1) {
+ ino[i] = ino[i + 2] + zoo;
+ i++;
+ }
+ }
+ ino[0] -= 2;
+ return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+ register int i;
+ register int off = PBLKSIZ;
+ register short *ino = (short *) pag;
+
+ for (i = 1; i < n; i += 2) {
+ if (siz == off - ino[i] &&
+ memcmp(key, pag + ino[i], siz) == 0)
+ return i;
+ off = ino[i + 1];
+ }
+ return 0;
+}
+
+void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+ apr_sdbm_datum_t key;
+ apr_sdbm_datum_t val;
+
+ register int n;
+ register int off = PBLKSIZ;
+ char cur[PBLKSIZ];
+ register short *ino = (short *) cur;
+
+ (void) memcpy(cur, pag, PBLKSIZ);
+ (void) memset(pag, 0, PBLKSIZ);
+ (void) memset(new, 0, PBLKSIZ);
+
+ n = ino[0];
+ for (ino++; n > 0; ino += 2) {
+ key.dptr = cur + ino[0];
+ key.dsize = off - ino[0];
+ val.dptr = cur + ino[1];
+ val.dsize = ino[0] - ino[1];
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+ (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+ off = ino[1];
+ n -= 2;
+ }
+
+ debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
+ ((short *) new)[0] / 2,
+ ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity:
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+int
+chkpage(pag)
+char *pag;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (n > 0) {
+ off = PBLKSIZ;
+ for (ino++; n > 0; ino += 2) {
+ if (ino[0] > off || ino[1] > off ||
+ ino[1] > ino[0])
+ return 0;
+ off = ino[1];
+ n -= 2;
+ }
+ }
+ return 1;
+}
diff --git a/dbm/sdbm/sdbm_pair.h b/dbm/sdbm/sdbm_pair.h
new file mode 100644
index 000000000..222c5e17f
--- /dev/null
+++ b/dbm/sdbm/sdbm_pair.h
@@ -0,0 +1,40 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SDBM_PAIR_H
+#define SDBM_PAIR_H
+
+/* Mini EMBED (pair.c) */
+#define chkpage apu__sdbm_chkpage
+#define delpair apu__sdbm_delpair
+#define duppair apu__sdbm_duppair
+#define fitpair apu__sdbm_fitpair
+#define getnkey apu__sdbm_getnkey
+#define getpair apu__sdbm_getpair
+#define putpair apu__sdbm_putpair
+#define splpage apu__sdbm_splpage
+
+int fitpair(char *, int);
+void putpair(char *, apr_sdbm_datum_t, apr_sdbm_datum_t);
+apr_sdbm_datum_t getpair(char *, apr_sdbm_datum_t);
+int delpair(char *, apr_sdbm_datum_t);
+int chkpage (char *);
+apr_sdbm_datum_t getnkey(char *, int);
+void splpage(char *, char *, long);
+int duppair(char *, apr_sdbm_datum_t);
+
+#endif /* SDBM_PAIR_H */
+
diff --git a/dbm/sdbm/sdbm_private.h b/dbm/sdbm/sdbm_private.h
new file mode 100644
index 000000000..f5d1ae06b
--- /dev/null
+++ b/dbm/sdbm/sdbm_private.h
@@ -0,0 +1,84 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_PRIVATE_H
+#define SDBM_PRIVATE_H
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_errno.h" /* for apr_status_t */
+
+#if 0
+/* if the block/page size is increased, it breaks perl apr_sdbm_t compatibility */
+#define DBLKSIZ 16384
+#define PBLKSIZ 8192
+#define PAIRMAX 8008 /* arbitrary on PBLKSIZ-N */
+#else
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
+#endif
+#define SPLTMAX 10 /* maximum allowed splits */
+
+/* for apr_sdbm_t.flags */
+#define SDBM_RDONLY 0x1 /* data base open read-only */
+#define SDBM_SHARED 0x2 /* data base open for sharing */
+#define SDBM_SHARED_LOCK 0x4 /* data base locked for shared read */
+#define SDBM_EXCLUSIVE_LOCK 0x8 /* data base locked for write */
+
+struct apr_sdbm_t {
+ apr_pool_t *pool;
+ apr_file_t *dirf; /* directory file descriptor */
+ apr_file_t *pagf; /* page file descriptor */
+ apr_int32_t flags; /* status/error flags, see below */
+ long maxbno; /* size of dirfile in bits */
+ long curbit; /* current bit number */
+ long hmask; /* current hash mask */
+ long blkptr; /* current block for nextkey */
+ int keyptr; /* current key for nextkey */
+ long blkno; /* current page to read/write */
+ long pagbno; /* current page in pagbuf */
+ char pagbuf[PBLKSIZ]; /* page file block buffer */
+ long dirbno; /* current block in dirbuf */
+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
+ int lckcnt; /* number of calls to sdbm_lock */
+};
+
+
+#define sdbm_hash apu__sdbm_hash
+#define sdbm_nullitem apu__sdbm_nullitem
+
+extern const apr_sdbm_datum_t sdbm_nullitem;
+
+long sdbm_hash(const char *str, int len);
+
+/*
+ * zero the cache
+ */
+#define SDBM_INVALIDATE_CACHE(db, finfo) \
+ do { db->dirbno = (!finfo.size) ? 0 : -1; \
+ db->pagbno = -1; \
+ db->maxbno = (long)(finfo.size * BYTESIZ); \
+ } while (0);
+
+#endif /* SDBM_PRIVATE_H */
diff --git a/dbm/sdbm/sdbm_tune.h b/dbm/sdbm/sdbm_tune.h
new file mode 100644
index 000000000..9bf3d09f2
--- /dev/null
+++ b/dbm/sdbm/sdbm_tune.h
@@ -0,0 +1,40 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_TUNE_H
+#define SDBM_TUNE_H
+
+#include "apr_errno.h"
+
+/* ### this might be better off as sizeof(char *) */
+#define BYTESIZ 8
+
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
+
+#endif /* SDBM_TUNE_H */