summaryrefslogtreecommitdiff
path: root/ext/dba
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/dba
downloadphp2-c4dd7a1a684490673e25aaf4fabec5df138854c4.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/dba')
-rw-r--r--ext/dba/CREDITS2
-rwxr-xr-xext/dba/README54
-rw-r--r--ext/dba/config.m4635
-rw-r--r--ext/dba/config.w3218
-rw-r--r--ext/dba/dba.c1247
-rw-r--r--ext/dba/dba.dsp213
-rw-r--r--ext/dba/dba_cdb.c350
-rw-r--r--ext/dba/dba_db1.c197
-rw-r--r--ext/dba/dba_db2.c209
-rw-r--r--ext/dba/dba_db3.c238
-rw-r--r--ext/dba/dba_db4.c302
-rw-r--r--ext/dba/dba_dbm.c213
-rw-r--r--ext/dba/dba_flatfile.c188
-rw-r--r--ext/dba/dba_gdbm.c200
-rw-r--r--ext/dba/dba_inifile.c194
-rw-r--r--ext/dba/dba_ndbm.c171
-rw-r--r--ext/dba/dba_qdbm.c194
-rw-r--r--ext/dba/dba_tcadb.c221
-rwxr-xr-xext/dba/install_cdb.sh53
-rw-r--r--ext/dba/libcdb/cdb.c194
-rw-r--r--ext/dba/libcdb/cdb.h57
-rw-r--r--ext/dba/libcdb/cdb_make.c244
-rw-r--r--ext/dba/libcdb/cdb_make.h64
-rw-r--r--ext/dba/libcdb/uint32.c49
-rw-r--r--ext/dba/libcdb/uint32.h39
-rw-r--r--ext/dba/libflatfile/flatfile.c320
-rw-r--r--ext/dba/libflatfile/flatfile.h48
-rw-r--r--ext/dba/libinifile/inifile.c593
-rw-r--r--ext/dba/libinifile/inifile.h66
-rw-r--r--ext/dba/php_cdb.h12
-rw-r--r--ext/dba/php_db1.h12
-rw-r--r--ext/dba/php_db2.h12
-rw-r--r--ext/dba/php_db3.h12
-rw-r--r--ext/dba/php_db4.h12
-rw-r--r--ext/dba/php_dba.h153
-rw-r--r--ext/dba/php_dbm.h12
-rw-r--r--ext/dba/php_flatfile.h12
-rw-r--r--ext/dba/php_gdbm.h12
-rw-r--r--ext/dba/php_inifile.h12
-rw-r--r--ext/dba/php_ndbm.h12
-rw-r--r--ext/dba/php_qdbm.h12
-rw-r--r--ext/dba/php_tcadb.h41
-rw-r--r--ext/dba/tests/bug36436.phpt37
-rw-r--r--ext/dba/tests/bug38698.phpt26
-rw-r--r--ext/dba/tests/bug48240.phpt28
-rw-r--r--ext/dba/tests/bug49125.phpt30
-rw-r--r--ext/dba/tests/clean.inc5
-rw-r--r--ext/dba/tests/dba001.phpt25
-rw-r--r--ext/dba/tests/dba002.phpt26
-rw-r--r--ext/dba/tests/dba003.phpt28
-rw-r--r--ext/dba/tests/dba004.phpt32
-rw-r--r--ext/dba/tests/dba005.phpt39
-rw-r--r--ext/dba/tests/dba006.phpt41
-rw-r--r--ext/dba/tests/dba007.phpt52
-rw-r--r--ext/dba/tests/dba008.phpt37
-rw-r--r--ext/dba/tests/dba009.phpt37
-rw-r--r--ext/dba/tests/dba010.phpt44
-rw-r--r--ext/dba/tests/dba011.phpt38
-rw-r--r--ext/dba/tests/dba012.phpt42
-rw-r--r--ext/dba/tests/dba013.phpt27
-rw-r--r--ext/dba/tests/dba014.phpt27
-rw-r--r--ext/dba/tests/dba015.phpt76
-rw-r--r--ext/dba/tests/dba016.phpt23
-rw-r--r--ext/dba/tests/dba_cdb.phpt51
-rw-r--r--ext/dba/tests/dba_cdb_001.phpt89
-rw-r--r--ext/dba/tests/dba_cdb_make.phpt40
-rw-r--r--ext/dba/tests/dba_cdb_read.phpt65
-rw-r--r--ext/dba/tests/dba_db1.phpt46
-rw-r--r--ext/dba/tests/dba_db2.phpt46
-rw-r--r--ext/dba/tests/dba_db3.phpt46
-rw-r--r--ext/dba/tests/dba_db4_000.phpt50
-rw-r--r--ext/dba/tests/dba_db4_001.phpt32
-rw-r--r--ext/dba/tests/dba_db4_002.phpt32
-rw-r--r--ext/dba/tests/dba_db4_003.phpt46
-rw-r--r--ext/dba/tests/dba_db4_004.phpt40
-rw-r--r--ext/dba/tests/dba_db4_005.phpt32
-rw-r--r--ext/dba/tests/dba_db4_006.phpt32
-rw-r--r--ext/dba/tests/dba_db4_007.phpt41
-rw-r--r--ext/dba/tests/dba_db4_008.phpt40
-rw-r--r--ext/dba/tests/dba_db4_009.phpt53
-rw-r--r--ext/dba/tests/dba_db4_010.phpt38
-rw-r--r--ext/dba/tests/dba_db4_011.phpt36
-rw-r--r--ext/dba/tests/dba_db4_012.phpt31
-rw-r--r--ext/dba/tests/dba_db4_013.phpt40
-rw-r--r--ext/dba/tests/dba_db4_014.phpt32
-rw-r--r--ext/dba/tests/dba_db4_015.phpt39
-rw-r--r--ext/dba/tests/dba_db4_016.phpt59
-rw-r--r--ext/dba/tests/dba_db4_017.phpt37
-rw-r--r--ext/dba/tests/dba_db4_018.phpt76
-rw-r--r--ext/dba/tests/dba_db4_handlers.phpt50
-rw-r--r--ext/dba/tests/dba_db4_optimize.phpt38
-rw-r--r--ext/dba/tests/dba_db4_sync.phpt38
-rw-r--r--ext/dba/tests/dba_dbm.phpt46
-rw-r--r--ext/dba/tests/dba_flatfile.phpt50
-rw-r--r--ext/dba/tests/dba_gdbm.phpt34
-rw-r--r--ext/dba/tests/dba_handler.inc90
-rw-r--r--ext/dba/tests/dba_handlers.phpt69
-rw-r--r--ext/dba/tests/dba_inifile.phpt46
-rw-r--r--ext/dba/tests/dba_ndbm.phpt46
-rw-r--r--ext/dba/tests/dba_optimize.phpt51
-rw-r--r--ext/dba/tests/dba_qdbm.phpt34
-rw-r--r--ext/dba/tests/dba_split.phpt83
-rw-r--r--ext/dba/tests/dba_sync.phpt51
-rw-r--r--ext/dba/tests/dba_tcadb.phpt50
-rw-r--r--ext/dba/tests/skipif.inc23
-rw-r--r--ext/dba/tests/test.cdbbin0 -> 2230 bytes
-rw-r--r--ext/dba/tests/test.inc7
107 files changed, 9594 insertions, 0 deletions
diff --git a/ext/dba/CREDITS b/ext/dba/CREDITS
new file mode 100644
index 0000000..370b3ea
--- /dev/null
+++ b/ext/dba/CREDITS
@@ -0,0 +1,2 @@
+DBA
+Sascha Schumann, Marcus Boerger \ No newline at end of file
diff --git a/ext/dba/README b/ext/dba/README
new file mode 100755
index 0000000..0c22830
--- /dev/null
+++ b/ext/dba/README
@@ -0,0 +1,54 @@
+These functions build the foundation for accessing Berkeley DB style
+databases.
+
+This is a general abstraction layer for several file-based databases. As
+such, functionality is limited to a common subset of features supported
+by modern databases such as Sleepycat Software's DB2. (This is not to be
+confused with IBM's DB2 software, which is supported through the ODBC
+functions.)
+
+This extensions allows to work with the following databases:
+dbm DBM is the oldest (original) type of Berkeley DB style databases.
+ You should avoid it, if possible. We do not support the
+ compatibility functions built into DB2 and gdbm, because they are
+ only compatible on the source code level, but cannot handle the
+ original dbm format.
+ndbm NDBM is a newer type and more flexible than dbm. It still has
+ most of the arbitrary limits of dbm (therefore it is deprecated).
+gdbm GDBM is the GNU database manager.
+db2 DB2 is Sleepycat Software's DB2. It's described as "a programmatic
+ toolkit that provides high-performance built-in database support
+ for both standalone and client/server applications.
+db3 DB3 is Sleepycat Software's DB3.
+db4 DB4 is Sleepycat Software's DB4. This is available since PHP 5.0.
+cdb CDB is "a fast, reliable, lightweight package for creating and
+ reading constant databases." It is from the author of qmail and
+ can be found at http://cr.yp.to/cdb.html. Since it is constant,
+ we support only reading operations. And since PHP 4.3.0 we support
+ writing (not updating) through the internal cdb library.
+cdb_make Since PHP 4.3.0 we support creation (not updating) of cdb files
+ when the bundled cdb library is used.
+flatfile This is available since PHP 4.3.0 for compatibility with the
+ deprecated dbm extension only and should be avoided. However you
+ may use this where files were created in this format. That happens
+ when configure could not find any external library.
+inifile This is available since PHP 4.3.3 to be able to modify php.ini
+ files from within PHP scripts. When working with ini files you
+ can pass arrays of the form array(0=>group,1=>value_name) or
+ strings of the form "[group]value_name" where group is optional.
+ As the functions dba_firstkey() and dba_nextkey() return string
+ representations of the key there is a new function dba_key_split()
+ available since PHP 5 which allows to convert the string keys into
+ array keys without loosing FALSE.
+qdbm This is available since PHP 5.0.0. The qdbm library can be loaded
+ from http://qdbm.sourceforge.net.
+
+
+After configuring and compiling PHP you must execute the following test
+from commandline:
+ php run-tests.php ext/dba.
+This shows whether your combination of handlers works. Most problematic
+are dbm and ndbm which conflict with many installations. The reason for
+this is that on several systems these libraries are part of more than one
+other library. The configuration test only prevents you from configuring
+malfaunctioning single handlers but not combinations. \ No newline at end of file
diff --git a/ext/dba/config.m4 b/ext/dba/config.m4
new file mode 100644
index 0000000..4b12351
--- /dev/null
+++ b/ext/dba/config.m4
@@ -0,0 +1,635 @@
+dnl
+dnl $Id$
+dnl
+
+dnl Suppose we need FlatFile if no support or only CDB is used.
+
+AC_DEFUN([PHP_DBA_STD_BEGIN],[
+ unset THIS_INCLUDE THIS_LIBS THIS_LFLAGS THIS_PREFIX THIS_RESULT
+])
+
+AC_DEFUN([PHP_TEMP_LDFLAGS],[
+ old_LDFLAGS=$LDFLAGS
+ LDFLAGS="$1 $LDFLAGS"
+ old_LIBS=$LIBS
+ LIBS="$2 $LIBS"
+ $3
+ LDFLAGS=$old_LDFLAGS
+ LIBS=$old_LIBS
+])
+
+dnl Assign INCLUDE/LFLAGS from PREFIX
+AC_DEFUN([PHP_DBA_STD_ASSIGN],[
+ if test -n "$THIS_PREFIX" && test "$THIS_PREFIX" != "/usr"; then
+ THIS_LFLAGS=$THIS_PREFIX/$PHP_LIBDIR
+ fi
+])
+
+dnl Standard check
+AC_DEFUN([PHP_DBA_STD_CHECK],[
+ THIS_RESULT=yes
+ if test -z "$THIS_INCLUDE"; then
+ AC_MSG_ERROR([DBA: Could not find necessary header file(s).])
+ fi
+ if test -z "$THIS_LIBS"; then
+ AC_MSG_ERROR([DBA: Could not find necessary library.])
+ fi
+])
+
+dnl Attach THIS_x to DBA_x
+AC_DEFUN([PHP_DBA_STD_ATTACH],[
+ PHP_ADD_LIBRARY_WITH_PATH($THIS_LIBS, $THIS_LFLAGS, DBA_SHARED_LIBADD)
+ unset THIS_INCLUDE THIS_LIBS THIS_LFLAGS THIS_PREFIX
+])
+
+dnl Print the result message
+dnl parameters(name [, full name [, empty or error message]])
+AC_DEFUN([PHP_DBA_STD_RESULT],[
+ THIS_NAME=[]translit($1,a-z0-9-,A-Z0-9_)
+ if test -n "$2"; then
+ THIS_FULL_NAME="$2"
+ else
+ THIS_FULL_NAME="$THIS_NAME"
+ fi
+ AC_MSG_CHECKING([for $THIS_FULL_NAME support])
+ if test -n "$3"; then
+ AC_MSG_ERROR($3)
+ fi
+ if test "$THIS_RESULT" = "yes" || test "$THIS_RESULT" = "builtin"; then
+ HAVE_DBA=1
+ eval HAVE_$THIS_NAME=1
+ AC_MSG_RESULT([$THIS_RESULT])
+ else
+ AC_MSG_RESULT(no)
+ fi
+ unset THIS_RESULT THIS_NAME THIS_FULL_NAME
+])
+
+dnl
+dnl Options
+dnl
+
+PHP_ARG_ENABLE(dba,,
+[ --enable-dba Build DBA with bundled modules. To build shared DBA
+ extension use --enable-dba=shared])
+
+PHP_ARG_WITH(qdbm,,
+[ --with-qdbm[=DIR] DBA: QDBM support], no, no)
+
+PHP_ARG_WITH(gdbm,,
+[ --with-gdbm[=DIR] DBA: GDBM support], no, no)
+
+PHP_ARG_WITH(ndbm,,
+[ --with-ndbm[=DIR] DBA: NDBM support], no, no)
+
+PHP_ARG_WITH(db4,,
+[ --with-db4[=DIR] DBA: Oracle Berkeley DB 4.x or 5.x support], no, no)
+
+PHP_ARG_WITH(db3,,
+[ --with-db3[=DIR] DBA: Oracle Berkeley DB 3.x support], no, no)
+
+PHP_ARG_WITH(db2,,
+[ --with-db2[=DIR] DBA: Oracle Berkeley DB 2.x support], no, no)
+
+PHP_ARG_WITH(db1,,
+[ --with-db1[=DIR] DBA: Oracle Berkeley DB 1.x support/emulation], no, no)
+
+PHP_ARG_WITH(dbm,,
+[ --with-dbm[=DIR] DBA: DBM support], no, no)
+
+PHP_ARG_WITH(tcadb,,
+[ --with-tcadb[=DIR] DBA: Tokyo Cabinet abstract DB support], no, no)
+
+
+dnl
+dnl Library checks
+dnl
+
+# QDBM
+if test "$PHP_QDBM" != "no"; then
+ PHP_DBA_STD_BEGIN
+ for i in $PHP_QDBM /usr/local /usr; do
+ if test -f "$i/include/depot.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/depot.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in qdbm; do
+ PHP_CHECK_LIBRARY($LIB, dpopen, [
+ AC_DEFINE_UNQUOTED(QDBM_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_QDBM, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(qdbm)
+
+# GDBM
+if test "$PHP_GDBM" != "no"; then
+ PHP_DBA_STD_BEGIN
+ if test "$HAVE_QDBM" = "1"; then
+ PHP_DBA_STD_RESULT(gdbm, gdbm, [You cannot combine --with-gdbm with --with-qdbm])
+ fi
+ for i in $PHP_GDBM /usr/local /usr; do
+ if test -f "$i/include/gdbm.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/gdbm.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ PHP_CHECK_LIBRARY(gdbm, gdbm_open, [
+ AC_DEFINE_UNQUOTED(GDBM_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_GDBM, 1, [ ])
+ THIS_LIBS=gdbm
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(gdbm)
+
+# NDBM
+if test "$PHP_NDBM" != "no"; then
+ PHP_DBA_STD_BEGIN
+ for i in $PHP_NDBM /usr/local /usr; do
+ if test -f "$i/include/ndbm.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/ndbm.h
+ break
+ elif test -f "$i/include/db1/ndbm.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db1/ndbm.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in ndbm db1 c; do
+ PHP_CHECK_LIBRARY($LIB, dbm_open, [
+ AC_DEFINE_UNQUOTED(NDBM_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_NDBM, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(ndbm)
+
+dnl TCADB
+if test "$PHP_TCADB" != "no"; then
+ PHP_DBA_STD_BEGIN
+ for i in $PHP_TCADB /usr/local /usr; do
+ if test -f "$i/include/tcadb.h"; then
+ THIS_PREFIX=$i
+ PHP_ADD_INCLUDE($THIS_PREFIX/include)
+ THIS_INCLUDE=$i/include/tcadb.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in tokyocabinet; do
+ PHP_CHECK_LIBRARY($LIB, tcadbopen, [
+ AC_DEFINE_UNQUOTED(TCADB_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_TCADB, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(tcadb)
+
+dnl Berkeley specific (library and version test)
+dnl parameters(version, library list, function)
+AC_DEFUN([PHP_DBA_DB_CHECK],[
+ if test -z "$THIS_INCLUDE"; then
+ AC_MSG_ERROR([DBA: Could not find necessary header file(s).])
+ fi
+ for LIB in $2; do
+ if test -f $THIS_PREFIX/$PHP_LIBDIR/lib$LIB.a || test -f $THIS_PREFIX/$PHP_LIBDIR/lib$LIB.$SHLIB_SUFFIX_NAME; then
+ lib_found="";
+ PHP_TEMP_LDFLAGS(-L$THIS_PREFIX/$PHP_LIBDIR, -l$LIB,[
+ AC_TRY_LINK([
+#include "$THIS_INCLUDE"
+ ],[
+ $3;
+ ],[
+ AC_EGREP_CPP(yes,[
+#include "$THIS_INCLUDE"
+#if DB_VERSION_MAJOR == $1 || ($1 == 4 && DB_VERSION_MAJOR == 5)
+ yes
+#endif
+ ],[
+ THIS_LIBS=$LIB
+ lib_found=1
+ ])
+ ])
+ ])
+ if test -n "$lib_found"; then
+ lib_found="";
+ break;
+ fi
+ fi
+ done
+ if test -z "$THIS_LIBS"; then
+ AC_MSG_CHECKING([for DB$1 major version])
+ AC_MSG_ERROR([Header contains different version])
+ fi
+ if test "$1" = "4"; then
+ AC_MSG_CHECKING([for DB4 minor version and patch level])
+ AC_EGREP_CPP(yes,[
+#include "$THIS_INCLUDE"
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR != 1) || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 1 && DB_VERSION_PATCH >= 25)
+ yes
+#endif
+ ],[
+ AC_MSG_RESULT(ok)
+ ],[
+ AC_MSG_ERROR([Version 4.1 requires patch level 25])
+ ])
+ fi
+ if test "$ext_shared" = "yes"; then
+ AC_MSG_CHECKING([if dba can be used as shared extension])
+ AC_EGREP_CPP(yes,[
+#include "$THIS_INCLUDE"
+#if DB_VERSION_MAJOR > 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR > 2)
+ yes
+#endif
+ ],[
+ AC_MSG_RESULT(yes)
+ ],[
+ AC_MSG_ERROR([At least version 3.3 is required])
+ ])
+ fi
+ if test -n "$THIS_LIBS"; then
+ AC_DEFINE(DBA_DB$1, 1, [ ])
+ if test -n "$THIS_INCLUDE"; then
+ AC_DEFINE_UNQUOTED(DB$1_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ fi
+ else
+ AC_MSG_ERROR([DBA: Could not find necessary library.])
+ fi
+ THIS_RESULT=yes
+ DB$1_LIBS=$THIS_LIBS
+ DB$1_PREFIX=$THIS_PREFIX
+ DB$1_INCLUDE=$THIS_INCLUDE
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_ATTACH
+])
+
+# DB4
+if test "$PHP_DB4" != "no"; then
+ PHP_DBA_STD_BEGIN
+ dbdp4="/usr/local/BerkeleyDB.4."
+ dbdp5="/usr/local/BerkeleyDB.5."
+ for i in $PHP_DB4 ${dbdp5}1 ${dbdp5}0 ${dbdp4}8 ${dbdp4}7 ${dbdp4}6 ${dbdp4}5 ${dbdp4}4 ${dbdp4}3 ${dbdp4}2 ${dbdp4}1 ${dbdp}0 /usr/local /usr; do
+ if test -f "$i/db5/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/db5/db.h
+ break
+ elif test -f "$i/db4/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/db4/db.h
+ break
+ elif test -f "$i/include/db5.1/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db5.1/db.h
+ break
+ elif test -f "$i/include/db5.0/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db5.0/db.h
+ break
+ elif test -f "$i/include/db4.8/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4.8/db.h
+ break
+ elif test -f "$i/include/db4.7/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4.7/db.h
+ break
+ elif test -f "$i/include/db4.6/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4.6/db.h
+ break
+ elif test -f "$i/include/db4.5/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4.5/db.h
+ break
+ elif test -f "$i/include/db4/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4/db.h
+ break
+ elif test -f "$i/include/db/db4.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db/db4.h
+ break
+ elif test -f "$i/include/db4.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db4.h
+ break
+ elif test -f "$i/include/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db.h
+ break
+ fi
+ done
+ PHP_DBA_DB_CHECK(4, db-5.1 db-5.0 db-4.8 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0 db-4 db4 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
+fi
+PHP_DBA_STD_RESULT(db4,Berkeley DB4)
+
+# DB3
+if test "$PHP_DB3" != "no"; then
+ PHP_DBA_STD_BEGIN
+ if test "$HAVE_DB4" = "1"; then
+ PHP_DBA_STD_RESULT(db3, Berkeley DB3, [You cannot combine --with-db3 with --with-db4])
+ fi
+ for i in $PHP_DB3 /usr/local/BerkeleyDB.3.3 /usr/local/BerkeleyDB.3.2 /usr/local/BerkeleyDB.3.1 /usr/local/BerkeleyDB.3.0 /usr/local /usr; do
+ if test -f "$i/db3/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db3/db.h
+ break
+ elif test -f "$i/include/db3/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db3/db.h
+ break
+ elif test -f "$i/include/db/db3.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db/db3.h
+ break
+ elif test -f "$i/include/db3.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db3.h
+ break
+ elif test -f "$i/include/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db.h
+ break
+ fi
+ done
+ PHP_DBA_DB_CHECK(3, db-3.3 db-3.2 db-3.1 db-3.0 db-3 db3 db, [(void)db_create((DB**)0, (DB_ENV*)0, 0)])
+fi
+PHP_DBA_STD_RESULT(db3,Berkeley DB3)
+
+# DB2
+if test "$PHP_DB2" != "no"; then
+ PHP_DBA_STD_BEGIN
+ if test "$HAVE_DB3" = "1" || test "$HAVE_DB4" = "1"; then
+ PHP_DBA_STD_RESULT(db2, Berkeley DB2, [You cannot combine --with-db2 with --with-db3 or --with-db4])
+ fi
+ for i in $PHP_DB2 $PHP_DB2/BerkeleyDB /usr/BerkeleyDB /usr/local /usr; do
+ if test -f "$i/db2/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/db2/db.h
+ break
+ elif test -f "$i/include/db2/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db2/db.h
+ break
+ elif test -f "$i/include/db/db2.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db/db2.h
+ break
+ elif test -f "$i/include/db2.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db2.h
+ break
+ elif test -f "$i/include/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db.h
+ break
+ fi
+ done
+ PHP_DBA_DB_CHECK(2, db-2 db2 db, [(void)db_appinit("", NULL, (DB_ENV*)0, 0)])
+fi
+PHP_DBA_STD_RESULT(db2, Berkeley DB2)
+
+# DB1
+if test "$PHP_DB1" != "no"; then
+ PHP_DBA_STD_BEGIN
+ AC_MSG_CHECKING([for DB1 in library])
+ if test "$HAVE_DB4" = "1"; then
+ THIS_VERSION=4
+ THIS_LIBS=$DB4_LIBS
+ THIS_PREFIX=$DB4_PREFIX
+ elif test "$HAVE_DB3" = "1"; then
+ THIS_LIBS=$DB3_LIBS
+ THIS_PREFIX=$DB3_PREFIX
+ elif test "$HAVE_DB2" = "1"; then
+ THIS_VERSION=2
+ THIS_LIBS=$DB2_LIBS
+ THIS_PREFIX=$DB2_PREFIX
+ fi
+ if test "$HAVE_DB4" = "1" || test "$HAVE_DB3" = "1" || test "$HAVE_DB2" = "1"; then
+ AC_DEFINE_UNQUOTED(DB1_VERSION, "Berkeley DB 1.85 emulation in DB$THIS_VERSION", [ ])
+ for i in db$THIS_VERSION/db_185.h include/db$THIS_VERSION/db_185.h include/db/db_185.h; do
+ if test -f "$THIS_PREFIX/$i"; then
+ THIS_INCLUDE=$THIS_PREFIX/$i
+ break
+ fi
+ done
+ else
+ AC_DEFINE_UNQUOTED(DB1_VERSION, "Unknown DB1", [ ])
+ for i in $PHP_DB1 /usr/local /usr; do
+ if test -f "$i/db1/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/db1/db.h
+ break
+ elif test -f "$i/include/db1/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db1/db.h
+ break
+ elif test -f "$i/include/db.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/db.h
+ break
+ fi
+ done
+ THIS_LIBS=db
+ fi
+ AC_MSG_RESULT([$THIS_LIBS])
+ AC_MSG_CHECKING([for DB1 in header])
+ AC_MSG_RESULT([$THIS_INCLUDE])
+ if test -n "$THIS_INCLUDE"; then
+ PHP_TEMP_LDFLAGS(-L$THIS_PREFIX/$PHP_LIBDIR, -l$THIS_LIBS,[
+ AC_TRY_LINK([
+#include "$THIS_INCLUDE"
+ ],[
+ DB * dbp = dbopen("", 0, 0, DB_HASH, 0);
+ ],[
+ AC_DEFINE_UNQUOTED(DB1_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_DB1, 1, [ ])
+ THIS_RESULT=yes
+ ],[
+ THIS_RESULT=no
+ ])
+ ])
+ fi
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(db1, DB1)
+
+# DBM
+if test "$PHP_DBM" != "no"; then
+ PHP_DBA_STD_BEGIN
+ if test "$HAVE_QDBM" = "1"; then
+ PHP_DBA_STD_RESULT(dbm, dbm, [You cannot combine --with-dbm with --with-qdbm])
+ fi
+ for i in $PHP_DBM /usr/local /usr; do
+ if test -f "$i/include/dbm.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/dbm.h
+ break
+ elif test -f "$i/include/gdbm/dbm.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/gdbm/dbm.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in dbm c gdbm; do
+ PHP_CHECK_LIBRARY($LIB, dbminit, [
+ AC_MSG_CHECKING(for DBM using GDBM)
+ AC_DEFINE_UNQUOTED(DBM_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ if test "$LIB" = "gdbm"; then
+ AC_DEFINE_UNQUOTED(DBM_VERSION, "GDBM", [ ])
+ AC_MSG_RESULT(yes)
+ else
+ AC_DEFINE_UNQUOTED(DBM_VERSION, "DBM", [ ])
+ AC_MSG_RESULT(no)
+ fi
+ AC_DEFINE(DBA_DBM, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(dbm)
+
+dnl
+dnl Bundled modules that should be enabled by default if any other option is enabled
+dnl
+if test "$PHP_DBA" != "no" || test "$HAVE_DBA" = "1" || test "$with_cdb" = "yes" || test "$enable_inifile" = "yes" || test "$enable_flatfile" = "yes"; then
+ php_dba_enable=yes
+else
+ php_dba_enable=no
+fi
+
+PHP_ARG_WITH(cdb,,
+[ --without-cdb[=DIR] DBA: CDB support (bundled)], $php_dba_enable, no)
+
+PHP_ARG_ENABLE(inifile,,
+[ --disable-inifile DBA: INI support (bundled)], $php_dba_enable, no)
+
+PHP_ARG_ENABLE(flatfile,,
+[ --disable-flatfile DBA: FlatFile support (bundled)], $php_dba_enable, no)
+
+# CDB
+if test "$PHP_CDB" = "yes"; then
+ AC_DEFINE(DBA_CDB_BUILTIN, 1, [ ])
+ AC_DEFINE(DBA_CDB_MAKE, 1, [ ])
+ AC_DEFINE(DBA_CDB, 1, [ ])
+ cdb_sources="libcdb/cdb.c libcdb/cdb_make.c libcdb/uint32.c"
+ THIS_RESULT="builtin"
+elif test "$PHP_CDB" != "no"; then
+ PHP_DBA_STD_BEGIN
+ for i in $PHP_CDB /usr/local /usr; do
+ if test -f "$i/include/cdb.h"; then
+ THIS_PREFIX=$i
+ THIS_INCLUDE=$i/include/cdb.h
+ break
+ fi
+ done
+
+ if test -n "$THIS_INCLUDE"; then
+ for LIB in cdb c; do
+ PHP_CHECK_LIBRARY($LIB, cdb_read, [
+ AC_DEFINE_UNQUOTED(CDB_INCLUDE_FILE, "$THIS_INCLUDE", [ ])
+ AC_DEFINE(DBA_CDB, 1, [ ])
+ THIS_LIBS=$LIB
+ ], [], [-L$THIS_PREFIX/$PHP_LIBDIR])
+ if test -n "$THIS_LIBS"; then
+ break
+ fi
+ done
+ fi
+
+ PHP_DBA_STD_ASSIGN
+ PHP_DBA_STD_CHECK
+ PHP_DBA_STD_ATTACH
+fi
+PHP_DBA_STD_RESULT(cdb)
+
+# INIFILE
+if test "$PHP_INIFILE" != "no"; then
+ AC_DEFINE(DBA_INIFILE, 1, [ ])
+ ini_sources="libinifile/inifile.c"
+ THIS_RESULT="builtin"
+fi
+PHP_DBA_STD_RESULT(inifile, [INI File])
+
+# FLATFILE
+if test "$PHP_FLATFILE" != "no"; then
+ AC_DEFINE(DBA_FLATFILE, 1, [ ])
+ flat_sources="libflatfile/flatfile.c"
+ THIS_RESULT="builtin"
+fi
+PHP_DBA_STD_RESULT(FlatFile, FlatFile)
+
+dnl
+dnl Extension setup
+dnl
+AC_MSG_CHECKING([whether to enable DBA interface])
+if test "$HAVE_DBA" = "1"; then
+ if test "$ext_shared" = "yes"; then
+ AC_MSG_RESULT([yes, shared])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ AC_DEFINE(HAVE_DBA, 1, [ ])
+ PHP_NEW_EXTENSION(dba, dba.c dba_cdb.c dba_dbm.c dba_gdbm.c dba_ndbm.c dba_db1.c dba_db2.c dba_db3.c dba_db4.c dba_flatfile.c dba_inifile.c dba_qdbm.c dba_tcadb.c $cdb_sources $flat_sources $ini_sources, $ext_shared)
+ PHP_ADD_BUILD_DIR($ext_builddir/libinifile)
+ PHP_ADD_BUILD_DIR($ext_builddir/libcdb)
+ PHP_ADD_BUILD_DIR($ext_builddir/libflatfile)
+ PHP_SUBST(DBA_SHARED_LIBADD)
+else
+ AC_MSG_RESULT(no)
+fi
diff --git a/ext/dba/config.w32 b/ext/dba/config.w32
new file mode 100644
index 0000000..4f3514e
--- /dev/null
+++ b/ext/dba/config.w32
@@ -0,0 +1,18 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("dba", "DBA support", "no");
+
+if (PHP_DBA != "no") {
+ if (CHECK_LIB("libdb31s.lib", "dba", PHP_DBA) &&
+ CHECK_HEADER_ADD_INCLUDE("db.h", "CFLAGS_DBA")) {
+ EXTENSION("dba", "dba.c dba_cdb.c dba_db1.c dba_db2.c dba_db3.c dba_dbm.c dba_flatfile.c dba_gdbm.c dba_ndbm.c dba_inifile.c");
+ ADD_SOURCES("ext/dba/libcdb", "cdb.c cdb_make.c uint32.c", "dba");
+ ADD_SOURCES("ext/dba/libflatfile", "flatfile.c", "dba");
+ ADD_SOURCES("ext/dba/libinifile", "inifile.c", "dba");
+ AC_DEFINE('HAVE_DBA', 1, 'DBA support');
+ ADD_FLAG("CFLAGS_DBA", "/D DBA_DB1=0 /D DB1_VERSION=\"\\\"Berkeley DB 1.85 emulation in DB3\\\"\" /D DB1_INCLUDE_FILE=\"\\\"db_185.h\\\"\" /D DBA_DB3=1 /D DB3_INCLUDE_FILE=\"\\\"db.h\\\"\" /D DBA_FLATFILE=1 /D DBA_CDB=1 /D DBA_CDB_MAKE=1 /D DBA_CDB_BUILTIN=1 /D DBA_INIFILE=1");
+ } else {
+ WARNING("dba not enabled; libraries and headers not found");
+ }
+}
diff --git a/ext/dba/dba.c b/ext/dba/dba.c
new file mode 100644
index 0000000..303d65c
--- /dev/null
+++ b/ext/dba/dba.c
@@ -0,0 +1,1247 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Sascha Schumann <sascha@schumann.cx> |
+ | Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if HAVE_DBA
+
+#include "php_ini.h"
+#include <stdio.h>
+#include <fcntl.h>
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#include "php_dba.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
+#include "ext/standard/flock_compat.h"
+
+#include "php_gdbm.h"
+#include "php_ndbm.h"
+#include "php_dbm.h"
+#include "php_cdb.h"
+#include "php_db1.h"
+#include "php_db2.h"
+#include "php_db3.h"
+#include "php_db4.h"
+#include "php_flatfile.h"
+#include "php_inifile.h"
+#include "php_qdbm.h"
+#include "php_tcadb.h"
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_popen, 0, 0, 2)
+ ZEND_ARG_INFO(0, path)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_INFO(0, handlername)
+ ZEND_ARG_INFO(0, ...)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_open, 0, 0, 2)
+ ZEND_ARG_INFO(0, path)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_INFO(0, handlername)
+ ZEND_ARG_INFO(0, ...)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_close, 0)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_exists, 0)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_fetch, 0, 0, 2)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, skip)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_key_split, 0)
+ ZEND_ARG_INFO(0, key)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_firstkey, 0)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_nextkey, 0)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_delete, 0)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_insert, 0)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_replace, 0)
+ ZEND_ARG_INFO(0, key)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_optimize, 0)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_sync, 0)
+ ZEND_ARG_INFO(0, handle)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dba_handlers, 0, 0, 0)
+ ZEND_ARG_INFO(0, full_info)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_dba_list, 0)
+ZEND_END_ARG_INFO()
+
+/* }}} */
+
+/* {{{ dba_functions[]
+ */
+const zend_function_entry dba_functions[] = {
+ PHP_FE(dba_open, arginfo_dba_open)
+ PHP_FE(dba_popen, arginfo_dba_popen)
+ PHP_FE(dba_close, arginfo_dba_close)
+ PHP_FE(dba_delete, arginfo_dba_delete)
+ PHP_FE(dba_exists, arginfo_dba_exists)
+ PHP_FE(dba_fetch, arginfo_dba_fetch)
+ PHP_FE(dba_insert, arginfo_dba_insert)
+ PHP_FE(dba_replace, arginfo_dba_replace)
+ PHP_FE(dba_firstkey, arginfo_dba_firstkey)
+ PHP_FE(dba_nextkey, arginfo_dba_nextkey)
+ PHP_FE(dba_optimize, arginfo_dba_optimize)
+ PHP_FE(dba_sync, arginfo_dba_sync)
+ PHP_FE(dba_handlers, arginfo_dba_handlers)
+ PHP_FE(dba_list, arginfo_dba_list)
+ PHP_FE(dba_key_split, arginfo_dba_key_split)
+ PHP_FE_END
+};
+/* }}} */
+
+PHP_MINIT_FUNCTION(dba);
+PHP_MSHUTDOWN_FUNCTION(dba);
+PHP_MINFO_FUNCTION(dba);
+
+ZEND_BEGIN_MODULE_GLOBALS(dba)
+ char *default_handler;
+ dba_handler *default_hptr;
+ZEND_END_MODULE_GLOBALS(dba)
+
+ZEND_DECLARE_MODULE_GLOBALS(dba)
+
+#ifdef ZTS
+#define DBA_G(v) TSRMG(dba_globals_id, zend_dba_globals *, v)
+#else
+#define DBA_G(v) (dba_globals.v)
+#endif
+
+static PHP_GINIT_FUNCTION(dba);
+
+zend_module_entry dba_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "dba",
+ dba_functions,
+ PHP_MINIT(dba),
+ PHP_MSHUTDOWN(dba),
+ NULL,
+ NULL,
+ PHP_MINFO(dba),
+ NO_VERSION_YET,
+ PHP_MODULE_GLOBALS(dba),
+ PHP_GINIT(dba),
+ NULL,
+ NULL,
+ STANDARD_MODULE_PROPERTIES_EX
+};
+
+#ifdef COMPILE_DL_DBA
+ZEND_GET_MODULE(dba)
+#endif
+
+/* {{{ macromania */
+
+#define DBA_ID_PARS \
+ zval *id; \
+ dba_info *info = NULL; \
+ int ac = ZEND_NUM_ARGS()
+
+/* these are used to get the standard arguments */
+
+/* {{{ php_dba_myke_key */
+static size_t php_dba_make_key(zval *key, char **key_str, char **key_free TSRMLS_DC)
+{
+ if (Z_TYPE_P(key) == IS_ARRAY) {
+ zval **group, **name;
+ HashPosition pos;
+ size_t len;
+
+ if (zend_hash_num_elements(Z_ARRVAL_P(key)) != 2) {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Key does not have exactly two elements: (key, name)");
+ return -1;
+ }
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(key), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &group, &pos);
+ zend_hash_move_forward_ex(Z_ARRVAL_P(key), &pos);
+ zend_hash_get_current_data_ex(Z_ARRVAL_P(key), (void **) &name, &pos);
+ convert_to_string_ex(group);
+ convert_to_string_ex(name);
+ if (Z_STRLEN_PP(group) == 0) {
+ *key_str = Z_STRVAL_PP(name);
+ *key_free = NULL;
+ return Z_STRLEN_PP(name);
+ }
+ len = spprintf(key_str, 0, "[%s]%s", Z_STRVAL_PP(group), Z_STRVAL_PP(name));
+ *key_free = *key_str;
+ return len;
+ } else {
+ *key_free = NULL;
+
+ convert_to_string(key);
+ *key_str = Z_STRVAL_P(key);
+
+ return Z_STRLEN_P(key);
+ }
+}
+/* }}} */
+
+#define DBA_GET2 \
+ zval *key; \
+ char *key_str, *key_free; \
+ size_t key_len; \
+ if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
+ return; \
+ } \
+ if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
+ RETURN_FALSE; \
+ }
+
+#define DBA_GET2_3 \
+ zval *key; \
+ char *key_str, *key_free; \
+ size_t key_len; \
+ long skip = 0; \
+ switch(ac) { \
+ case 2: \
+ if (zend_parse_parameters(ac TSRMLS_CC, "zr", &key, &id) == FAILURE) { \
+ return; \
+ } \
+ break; \
+ case 3: \
+ if (zend_parse_parameters(ac TSRMLS_CC, "zlr", &key, &skip, &id) == FAILURE) { \
+ return; \
+ } \
+ break; \
+ default: \
+ WRONG_PARAM_COUNT; \
+ } \
+ if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {\
+ RETURN_FALSE; \
+ }
+
+
+#define DBA_FETCH_RESOURCE(info, id) \
+ ZEND_FETCH_RESOURCE2(info, dba_info *, id, -1, "DBA identifier", le_db, le_pdb);
+
+#define DBA_ID_GET2 DBA_ID_PARS; DBA_GET2; DBA_FETCH_RESOURCE(info, &id)
+#define DBA_ID_GET2_3 DBA_ID_PARS; DBA_GET2_3; DBA_FETCH_RESOURCE(info, &id)
+
+#define DBA_ID_DONE \
+ if (key_free) efree(key_free)
+/* a DBA handler must have specific routines */
+
+#define DBA_NAMED_HND(alias, name, flags) \
+{\
+ #alias, flags, dba_open_##name, dba_close_##name, dba_fetch_##name, dba_update_##name, \
+ dba_exists_##name, dba_delete_##name, dba_firstkey_##name, dba_nextkey_##name, \
+ dba_optimize_##name, dba_sync_##name, dba_info_##name \
+},
+
+#define DBA_HND(name, flags) DBA_NAMED_HND(name, name, flags)
+
+/* check whether the user has write access */
+#define DBA_WRITE_CHECK \
+ if(info->mode != DBA_WRITER && info->mode != DBA_TRUNC && info->mode != DBA_CREAT) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You cannot perform a modification to a database without proper access"); \
+ RETURN_FALSE; \
+ }
+
+/* }}} */
+
+/* {{{ globals */
+
+static dba_handler handler[] = {
+#if DBA_GDBM
+ DBA_HND(gdbm, DBA_LOCK_EXT) /* Locking done in library if set */
+#endif
+#if DBA_DBM
+ DBA_HND(dbm, DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_NDBM
+ DBA_HND(ndbm, DBA_LOCK_ALL) /* Could be done in library: filemode = 0644 + S_ENFMT */
+#endif
+#if DBA_CDB
+ DBA_HND(cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_CDB_BUILTIN
+ DBA_NAMED_HND(cdb_make, cdb, DBA_STREAM_OPEN|DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_DB1
+ DBA_HND(db1, DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_DB2
+ DBA_HND(db2, DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_DB3
+ DBA_HND(db3, DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_DB4
+ DBA_HND(db4, DBA_LOCK_ALL) /* No lock in lib */
+#endif
+#if DBA_INIFILE
+ DBA_HND(inifile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_CAST_AS_FD) /* No lock in lib */
+#endif
+#if DBA_FLATFILE
+ DBA_HND(flatfile, DBA_STREAM_OPEN|DBA_LOCK_ALL|DBA_NO_APPEND) /* No lock in lib */
+#endif
+#if DBA_QDBM
+ DBA_HND(qdbm, DBA_LOCK_EXT)
+#endif
+#if DBA_TCADB
+ DBA_HND(tcadb, DBA_LOCK_ALL)
+#endif
+ { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+#if DBA_FLATFILE
+#define DBA_DEFAULT "flatfile"
+#elif DBA_DB4
+#define DBA_DEFAULT "db4"
+#elif DBA_DB3
+#define DBA_DEFAULT "db3"
+#elif DBA_DB2
+#define DBA_DEFAULT "db2"
+#elif DBA_DB1
+#define DBA_DEFAULT "db1"
+#elif DBA_GDBM
+#define DBA_DEFAULT "gdbm"
+#elif DBA_NBBM
+#define DBA_DEFAULT "ndbm"
+#elif DBA_DBM
+#define DBA_DEFAULT "dbm"
+#elif DBA_QDBM
+#define DBA_DEFAULT "qdbm"
+#elif DBA_TCADB
+#define DBA_DEFAULT "tcadb"
+#else
+#define DBA_DEFAULT ""
+#endif
+/* cdb/cdb_make and ini are no option here */
+
+static int le_db;
+static int le_pdb;
+/* }}} */
+
+/* {{{ dba_fetch_resource
+PHPAPI void dba_fetch_resource(dba_info **pinfo, zval **id TSRMLS_DC)
+{
+ dba_info *info;
+ DBA_ID_FETCH
+ *pinfo = info;
+}
+*/
+/* }}} */
+
+/* {{{ dba_get_handler
+PHPAPI dba_handler *dba_get_handler(const char* handler_name)
+{
+ dba_handler *hptr;
+ for (hptr = handler; hptr->name && strcasecmp(hptr->name, handler_name); hptr++);
+ return hptr;
+}
+*/
+/* }}} */
+
+/* {{{ dba_close
+ */
+static void dba_close(dba_info *info TSRMLS_DC)
+{
+ if (info->hnd) {
+ info->hnd->close(info TSRMLS_CC);
+ }
+ if (info->path) {
+ pefree(info->path, info->flags&DBA_PERSISTENT);
+ }
+ if (info->fp && info->fp!=info->lock.fp) {
+ if(info->flags&DBA_PERSISTENT) {
+ php_stream_pclose(info->fp);
+ } else {
+ php_stream_close(info->fp);
+ }
+ }
+ if (info->lock.fp) {
+ if(info->flags&DBA_PERSISTENT) {
+ php_stream_pclose(info->lock.fp);
+ } else {
+ php_stream_close(info->lock.fp);
+ }
+ }
+ if (info->lock.name) {
+ pefree(info->lock.name, info->flags&DBA_PERSISTENT);
+ }
+ pefree(info, info->flags&DBA_PERSISTENT);
+}
+/* }}} */
+
+/* {{{ dba_close_rsrc
+ */
+static void dba_close_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ dba_info *info = (dba_info *)rsrc->ptr;
+
+ dba_close(info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ dba_close_pe_rsrc_deleter */
+int dba_close_pe_rsrc_deleter(zend_rsrc_list_entry *le, void *pDba TSRMLS_DC)
+{
+ return le->ptr == pDba;
+}
+/* }}} */
+
+/* {{{ dba_close_pe_rsrc */
+static void dba_close_pe_rsrc(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ dba_info *info = (dba_info *)rsrc->ptr;
+
+ /* closes the resource by calling dba_close_rsrc() */
+ zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) dba_close_pe_rsrc_deleter, info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ PHP_INI
+ */
+ZEND_INI_MH(OnUpdateDefaultHandler)
+{
+ dba_handler *hptr;
+
+ if (!strlen(new_value)) {
+ DBA_G(default_hptr) = NULL;
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+ }
+
+ for (hptr = handler; hptr->name && strcasecmp(hptr->name, new_value); hptr++);
+
+ if (!hptr->name) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such handler: %s", new_value);
+ return FAILURE;
+ }
+ DBA_G(default_hptr) = hptr;
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
+}
+
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("dba.default_handler", DBA_DEFAULT, PHP_INI_ALL, OnUpdateDefaultHandler, default_handler, zend_dba_globals, dba_globals)
+PHP_INI_END()
+/* }}} */
+
+/* {{{ PHP_GINIT_FUNCTION
+ */
+static PHP_GINIT_FUNCTION(dba)
+{
+ dba_globals->default_handler = "";
+ dba_globals->default_hptr = NULL;
+}
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(dba)
+{
+ REGISTER_INI_ENTRIES();
+ le_db = zend_register_list_destructors_ex(dba_close_rsrc, NULL, "dba", module_number);
+ le_pdb = zend_register_list_destructors_ex(dba_close_pe_rsrc, dba_close_rsrc, "dba persistent", module_number);
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(dba)
+{
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+/* }}} */
+
+#include "ext/standard/php_smart_str.h"
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(dba)
+{
+ dba_handler *hptr;
+ smart_str handlers = {0};
+
+ for(hptr = handler; hptr->name; hptr++) {
+ smart_str_appends(&handlers, hptr->name);
+ smart_str_appendc(&handlers, ' ');
+ }
+
+ php_info_print_table_start();
+ php_info_print_table_row(2, "DBA support", "enabled");
+ if (handlers.c) {
+ smart_str_0(&handlers);
+ php_info_print_table_row(2, "Supported handlers", handlers.c);
+ smart_str_free(&handlers);
+ } else {
+ php_info_print_table_row(2, "Supported handlers", "none");
+ }
+ php_info_print_table_end();
+ DISPLAY_INI_ENTRIES();
+}
+/* }}} */
+
+/* {{{ php_dba_update
+ */
+static void php_dba_update(INTERNAL_FUNCTION_PARAMETERS, int mode)
+{
+ char *v;
+ int val_len;
+ zval *id;
+ dba_info *info = NULL;
+ int ac = ZEND_NUM_ARGS();
+ zval *key;
+ char *val;
+ char *key_str, *key_free;
+ size_t key_len;
+
+ if (zend_parse_parameters(ac TSRMLS_CC, "zsr", &key, &val, &val_len, &id) == FAILURE) {
+ return;
+ }
+
+ if ((key_len = php_dba_make_key(key, &key_str, &key_free TSRMLS_CC)) == 0) {
+ RETURN_FALSE;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ DBA_WRITE_CHECK;
+
+ if (info->hnd->update(info, key_str, key_len, val, val_len, mode TSRMLS_CC) == SUCCESS) {
+ DBA_ID_DONE;
+ RETURN_TRUE;
+ }
+
+ DBA_ID_DONE;
+ RETURN_FALSE;
+}
+/* }}} */
+
+#define FREENOW if(args) efree(args); if(key) efree(key)
+
+/* {{{ php_find_dbm
+ */
+dba_info *php_dba_find(const char* path TSRMLS_DC)
+{
+ zend_rsrc_list_entry *le;
+ dba_info *info;
+ int numitems, i;
+
+ numitems = zend_hash_next_free_element(&EG(regular_list));
+ for (i=1; i<numitems; i++) {
+ if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
+ continue;
+ }
+ if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
+ info = (dba_info *)(le->ptr);
+ if (!strcmp(info->path, path)) {
+ return (dba_info *)(le->ptr);
+ }
+ }
+ }
+
+ return NULL;
+}
+/* }}} */
+
+/* {{{ php_dba_open
+ */
+static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
+{
+ zval ***args = (zval ***) NULL;
+ int ac = ZEND_NUM_ARGS();
+ dba_mode_t modenr;
+ dba_info *info, *other;
+ dba_handler *hptr;
+ char *key = NULL, *error = NULL;
+ int keylen = 0;
+ int i;
+ int lock_mode, lock_flag, lock_dbf = 0;
+ char *file_mode;
+ char mode[4], *pmode, *lock_file_mode = NULL;
+ int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
+ char *opened_path, *lock_name;
+
+ if(ac < 2) {
+ WRONG_PARAM_COUNT;
+ }
+
+ /* we pass additional args to the respective handler */
+ args = safe_emalloc(ac, sizeof(zval *), 0);
+ if (zend_get_parameters_array_ex(ac, args) != SUCCESS) {
+ FREENOW;
+ WRONG_PARAM_COUNT;
+ }
+
+ /* we only take string arguments */
+ for (i = 0; i < ac; i++) {
+ convert_to_string_ex(args[i]);
+ keylen += Z_STRLEN_PP(args[i]);
+ }
+
+ if (persistent) {
+ zend_rsrc_list_entry *le;
+
+ /* calculate hash */
+ key = safe_emalloc(keylen, 1, 1);
+ key[keylen] = '\0';
+ keylen = 0;
+
+ for(i = 0; i < ac; i++) {
+ memcpy(key+keylen, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
+ keylen += Z_STRLEN_PP(args[i]);
+ }
+
+ /* try to find if we already have this link in our persistent list */
+ if (zend_hash_find(&EG(persistent_list), key, keylen+1, (void **) &le) == SUCCESS) {
+ FREENOW;
+
+ if (Z_TYPE_P(le) != le_pdb) {
+ RETURN_FALSE;
+ }
+
+ info = (dba_info *)le->ptr;
+
+ ZEND_REGISTER_RESOURCE(return_value, info, le_pdb);
+ return;
+ }
+ }
+
+ if (ac==2) {
+ hptr = DBA_G(default_hptr);
+ if (!hptr) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No default handler selected");
+ FREENOW;
+ RETURN_FALSE;
+ }
+ } else {
+ for (hptr = handler; hptr->name && strcasecmp(hptr->name, Z_STRVAL_PP(args[2])); hptr++);
+ }
+
+ if (!hptr->name) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "No such handler: %s", Z_STRVAL_PP(args[2]));
+ FREENOW;
+ RETURN_FALSE;
+ }
+
+ /* Check mode: [rwnc][fl]?t?
+ * r: Read
+ * w: Write
+ * n: Create/Truncate
+ * c: Create
+ *
+ * d: force lock on database file
+ * l: force lock on lck file
+ * -: ignore locking
+ *
+ * t: test open database, warning if locked
+ */
+ strlcpy(mode, Z_STRVAL_PP(args[1]), sizeof(mode));
+ pmode = &mode[0];
+ if (pmode[0] && (pmode[1]=='d' || pmode[1]=='l' || pmode[1]=='-')) { /* force lock on db file or lck file or disable locking */
+ switch (pmode[1]) {
+ case 'd':
+ lock_dbf = 1;
+ if ((hptr->flags & DBA_LOCK_ALL) == 0) {
+ lock_flag = (hptr->flags & DBA_LOCK_ALL);
+ break;
+ }
+ /* no break */
+ case 'l':
+ lock_flag = DBA_LOCK_ALL;
+ if ((hptr->flags & DBA_LOCK_ALL) == 0) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_NOTICE, "Handler %s does locking internally", hptr->name);
+ }
+ break;
+ default:
+ case '-':
+ if ((hptr->flags & DBA_LOCK_ALL) == 0) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Locking cannot be disabled for handler %s", hptr->name);
+ FREENOW;
+ RETURN_FALSE;
+ }
+ lock_flag = 0;
+ break;
+ }
+ } else {
+ lock_flag = (hptr->flags&DBA_LOCK_ALL);
+ lock_dbf = 1;
+ }
+ switch (*pmode++) {
+ case 'r':
+ modenr = DBA_READER;
+ lock_mode = (lock_flag & DBA_LOCK_READER) ? LOCK_SH : 0;
+ file_mode = "r";
+ break;
+ case 'w':
+ modenr = DBA_WRITER;
+ lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
+ file_mode = "r+b";
+ break;
+ case 'c':
+ modenr = DBA_CREAT;
+ lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
+ if (lock_mode) {
+ if (lock_dbf) {
+ /* the create/append check will be done on the lock
+ * when the lib opens the file it is already created
+ */
+ file_mode = "r+b"; /* read & write, seek 0 */
+ lock_file_mode = "a+b"; /* append */
+ } else {
+ file_mode = "a+b"; /* append */
+ lock_file_mode = "w+b"; /* create/truncate */
+ }
+ } else {
+ file_mode = "a+b";
+ }
+ /* In case of the 'a+b' append mode, the handler is responsible
+ * to handle any rewind problems (see flatfile handler).
+ */
+ break;
+ case 'n':
+ modenr = DBA_TRUNC;
+ lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
+ file_mode = "w+b";
+ break;
+ default:
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
+ FREENOW;
+ RETURN_FALSE;
+ }
+ if (!lock_file_mode) {
+ lock_file_mode = file_mode;
+ }
+ if (*pmode=='d' || *pmode=='l' || *pmode=='-') {
+ pmode++; /* done already - skip here */
+ }
+ if (*pmode=='t') {
+ pmode++;
+ if (!lock_flag) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "You cannot combine modifiers - (no lock) and t (test lock)");
+ FREENOW;
+ RETURN_FALSE;
+ }
+ if (!lock_mode) {
+ if ((hptr->flags & DBA_LOCK_ALL) == 0) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s uses its own locking which doesn't support mode modifier t (test lock)", hptr->name);
+ FREENOW;
+ RETURN_FALSE;
+ } else {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Handler %s doesn't uses locking for this mode which makes modifier t (test lock) obsolete", hptr->name);
+ FREENOW;
+ RETURN_FALSE;
+ }
+ } else {
+ lock_mode |= LOCK_NB; /* test =: non blocking */
+ }
+ }
+ if (*pmode) {
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Illegal DBA mode");
+ FREENOW;
+ RETURN_FALSE;
+ }
+
+ info = pemalloc(sizeof(dba_info), persistent);
+ memset(info, 0, sizeof(dba_info));
+ info->path = pestrdup(Z_STRVAL_PP(args[0]), persistent);
+ info->mode = modenr;
+ info->argc = ac - 3;
+ info->argv = args + 3;
+ info->flags = (hptr->flags & ~DBA_LOCK_ALL) | (lock_flag & DBA_LOCK_ALL) | (persistent ? DBA_PERSISTENT : 0);
+ info->lock.mode = lock_mode;
+
+ /* if any open call is a locking call:
+ * check if we already habe a locking call open that should block this call
+ * the problem is some systems would allow read during write
+ */
+ if (hptr->flags & DBA_LOCK_ALL) {
+ if ((other = php_dba_find(info->path TSRMLS_CC)) != NULL) {
+ if ( ( (lock_mode&LOCK_EX) && (other->lock.mode&(LOCK_EX|LOCK_SH)) )
+ || ( (other->lock.mode&LOCK_EX) && (lock_mode&(LOCK_EX|LOCK_SH)) )
+ ) {
+ error = "Unable to establish lock (database file already open)"; /* force failure exit */
+ }
+ }
+ }
+
+ if (!error && lock_mode) {
+ if (lock_dbf) {
+ lock_name = Z_STRVAL_PP(args[0]);
+ } else {
+ spprintf(&lock_name, 0, "%s.lck", info->path);
+ if (!strcmp(file_mode, "r")) {
+ /* when in read only mode try to use existing .lck file first */
+ /* do not log errors for .lck file while in read ony mode on .lck file */
+ lock_file_mode = "rb";
+ info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|IGNORE_PATH|persistent_flag, &opened_path);
+ }
+ if (!info->lock.fp) {
+ /* when not in read mode or failed to open .lck file read only. now try again in create(write) mode and log errors */
+ lock_file_mode = "a+b";
+ } else {
+ if (!persistent) {
+ info->lock.name = opened_path;
+ } else {
+ info->lock.name = pestrdup(opened_path, persistent);
+ efree(opened_path);
+ }
+ }
+ }
+ if (!info->lock.fp) {
+ info->lock.fp = php_stream_open_wrapper(lock_name, lock_file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, &opened_path);
+ if (info->lock.fp) {
+ if (lock_dbf) {
+ /* replace the path info with the real path of the opened file */
+ pefree(info->path, persistent);
+ info->path = pestrdup(opened_path, persistent);
+ }
+ /* now store the name of the lock */
+ if (!persistent) {
+ info->lock.name = opened_path;
+ } else {
+ info->lock.name = pestrdup(opened_path, persistent);
+ efree(opened_path);
+ }
+ }
+ }
+ if (!lock_dbf) {
+ efree(lock_name);
+ }
+ if (!info->lock.fp) {
+ dba_close(info TSRMLS_CC);
+ /* stream operation already wrote an error message */
+ FREENOW;
+ RETURN_FALSE;
+ }
+ if (!php_stream_supports_lock(info->lock.fp)) {
+ error = "Stream does not support locking";
+ }
+ if (php_stream_lock(info->lock.fp, lock_mode)) {
+ error = "Unable to establish lock"; /* force failure exit */
+ }
+ }
+
+ /* centralised open stream for builtin */
+ if (!error && (hptr->flags&DBA_STREAM_OPEN)==DBA_STREAM_OPEN) {
+ if (info->lock.fp && lock_dbf) {
+ info->fp = info->lock.fp; /* use the same stream for locking and database access */
+ } else {
+ info->fp = php_stream_open_wrapper(info->path, file_mode, STREAM_MUST_SEEK|REPORT_ERRORS|IGNORE_PATH|persistent_flag, NULL);
+ }
+ if (!info->fp) {
+ dba_close(info TSRMLS_CC);
+ /* stream operation already wrote an error message */
+ FREENOW;
+ RETURN_FALSE;
+ }
+ if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
+ /* Needed becasue some systems do not allow to write to the original
+ * file contents with O_APPEND being set.
+ */
+ if (SUCCESS != php_stream_cast(info->fp, PHP_STREAM_AS_FD, (void*)&info->fd, 1)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not cast stream");
+ dba_close(info TSRMLS_CC);
+ FREENOW;
+ RETURN_FALSE;
+#ifdef F_SETFL
+ } else if (modenr == DBA_CREAT) {
+ int flags = fcntl(info->fd, F_SETFL);
+ fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
+#endif
+ }
+
+ }
+ }
+
+ if (error || hptr->open(info, &error TSRMLS_CC) != SUCCESS) {
+ dba_close(info TSRMLS_CC);
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Driver initialization failed for handler: %s%s%s", hptr->name, error?": ":"", error?error:"");
+ FREENOW;
+ RETURN_FALSE;
+ }
+
+ info->hnd = hptr;
+ info->argc = 0;
+ info->argv = NULL;
+
+ if (persistent) {
+ zend_rsrc_list_entry new_le;
+
+ Z_TYPE(new_le) = le_pdb;
+ new_le.ptr = info;
+ if (zend_hash_update(&EG(persistent_list), key, keylen+1, &new_le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
+ dba_close(info TSRMLS_CC);
+ php_error_docref2(NULL TSRMLS_CC, Z_STRVAL_PP(args[0]), Z_STRVAL_PP(args[1]), E_WARNING, "Could not register persistent resource");
+ FREENOW;
+ RETURN_FALSE;
+ }
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, info, (persistent ? le_pdb : le_db));
+ FREENOW;
+}
+/* }}} */
+#undef FREENOW
+
+/* {{{ proto resource dba_popen(string path, string mode [, string handlername, string ...])
+ Opens path using the specified handler in mode persistently */
+PHP_FUNCTION(dba_popen)
+{
+ php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto resource dba_open(string path, string mode [, string handlername, string ...])
+ Opens path using the specified handler in mode*/
+PHP_FUNCTION(dba_open)
+{
+ php_dba_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto void dba_close(resource handle)
+ Closes database */
+PHP_FUNCTION(dba_close)
+{
+ zval *id;
+ dba_info *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
+ return;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ zend_list_delete(Z_RESVAL_P(id));
+}
+/* }}} */
+
+/* {{{ proto bool dba_exists(string key, resource handle)
+ Checks, if the specified key exists */
+PHP_FUNCTION(dba_exists)
+{
+ DBA_ID_GET2;
+
+ if(info->hnd->exists(info, key_str, key_len TSRMLS_CC) == SUCCESS) {
+ DBA_ID_DONE;
+ RETURN_TRUE;
+ }
+ DBA_ID_DONE;
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto string dba_fetch(string key, [int skip ,] resource handle)
+ Fetches the data associated with key */
+PHP_FUNCTION(dba_fetch)
+{
+ char *val;
+ int len = 0;
+ DBA_ID_GET2_3;
+
+ if (ac==3) {
+ if (!strcmp(info->hnd->name, "cdb")) {
+ if (skip < 0) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip values greater than or equal to zero, using skip=0", info->hnd->name);
+ skip = 0;
+ }
+ } else if (!strcmp(info->hnd->name, "inifile")) {
+ /* "-1" is compareable to 0 but allows a non restrictive
+ * access which is fater. For example 'inifile' uses this
+ * to allow faster access when the key was already found
+ * using firstkey/nextkey. However explicitly setting the
+ * value to 0 ensures the first value.
+ */
+ if (skip < -1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s accepts only skip value -1 and greater, using skip=0", info->hnd->name);
+ skip = 0;
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Handler %s does not support optional skip parameter, the value will be ignored", info->hnd->name);
+ skip = 0;
+ }
+ } else {
+ skip = 0;
+ }
+ if((val = info->hnd->fetch(info, key_str, key_len, skip, &len TSRMLS_CC)) != NULL) {
+ DBA_ID_DONE;
+ RETURN_STRINGL(val, len, 0);
+ }
+ DBA_ID_DONE;
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto array|false dba_key_split(string key)
+ Splits an inifile key into an array of the form array(0=>group,1=>value_name) but returns false if input is false or null */
+PHP_FUNCTION(dba_key_split)
+{
+ zval *zkey;
+ char *key, *name;
+ int key_len;
+
+ if (ZEND_NUM_ARGS() != 1) {
+ WRONG_PARAM_COUNT;
+ }
+ if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &zkey) == SUCCESS) {
+ if (Z_TYPE_P(zkey) == IS_NULL || (Z_TYPE_P(zkey) == IS_BOOL && !Z_LVAL_P(zkey))) {
+ RETURN_BOOL(0);
+ }
+ }
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len) == FAILURE) {
+ RETURN_BOOL(0);
+ }
+ array_init(return_value);
+ if (key[0] == '[' && (name = strchr(key, ']')) != NULL) {
+ add_next_index_stringl(return_value, key+1, name - (key + 1), 1);
+ add_next_index_stringl(return_value, name+1, key_len - (name - key + 1), 1);
+ } else {
+ add_next_index_stringl(return_value, "", 0, 1);
+ add_next_index_stringl(return_value, key, key_len, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto string dba_firstkey(resource handle)
+ Resets the internal key pointer and returns the first key */
+PHP_FUNCTION(dba_firstkey)
+{
+ char *fkey;
+ int len;
+ zval *id;
+ dba_info *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
+ return;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ fkey = info->hnd->firstkey(info, &len TSRMLS_CC);
+
+ if (fkey)
+ RETURN_STRINGL(fkey, len, 0);
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto string dba_nextkey(resource handle)
+ Returns the next key */
+PHP_FUNCTION(dba_nextkey)
+{
+ char *nkey;
+ int len;
+ zval *id;
+ dba_info *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
+ return;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ nkey = info->hnd->nextkey(info, &len TSRMLS_CC);
+
+ if (nkey)
+ RETURN_STRINGL(nkey, len, 0);
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool dba_delete(string key, resource handle)
+ Deletes the entry associated with key
+ If inifile: remove all other key lines */
+PHP_FUNCTION(dba_delete)
+{
+ DBA_ID_GET2;
+
+ DBA_WRITE_CHECK;
+
+ if(info->hnd->delete(info, key_str, key_len TSRMLS_CC) == SUCCESS)
+ {
+ DBA_ID_DONE;
+ RETURN_TRUE;
+ }
+ DBA_ID_DONE;
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool dba_insert(string key, string value, resource handle)
+ If not inifile: Insert value as key, return false, if key exists already
+ If inifile: Add vakue as key (next instance of key) */
+PHP_FUNCTION(dba_insert)
+{
+ php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto bool dba_replace(string key, string value, resource handle)
+ Inserts value as key, replaces key, if key exists already
+ If inifile: remove all other key lines */
+PHP_FUNCTION(dba_replace)
+{
+ php_dba_update(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
+/* }}} */
+
+/* {{{ proto bool dba_optimize(resource handle)
+ Optimizes (e.g. clean up, vacuum) database */
+PHP_FUNCTION(dba_optimize)
+{
+ zval *id;
+ dba_info *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
+ return;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ DBA_WRITE_CHECK;
+
+ if (info->hnd->optimize(info TSRMLS_CC) == SUCCESS) {
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool dba_sync(resource handle)
+ Synchronizes database */
+PHP_FUNCTION(dba_sync)
+{
+ zval *id;
+ dba_info *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &id) == FAILURE) {
+ return;
+ }
+
+ DBA_FETCH_RESOURCE(info, &id);
+
+ if (info->hnd->sync(info TSRMLS_CC) == SUCCESS) {
+ RETURN_TRUE;
+ }
+
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto array dba_handlers([bool full_info])
+ List configured database handlers */
+PHP_FUNCTION(dba_handlers)
+{
+ dba_handler *hptr;
+ zend_bool full_info = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &full_info) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ for(hptr = handler; hptr->name; hptr++) {
+ if (full_info) {
+ add_assoc_string(return_value, hptr->name, hptr->info(hptr, NULL TSRMLS_CC), 0);
+ } else {
+ add_next_index_string(return_value, hptr->name, 1);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto array dba_list()
+ List opened databases */
+PHP_FUNCTION(dba_list)
+{
+ ulong numitems, i;
+ zend_rsrc_list_entry *le;
+ dba_info *info;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ numitems = zend_hash_next_free_element(&EG(regular_list));
+ for (i=1; i<numitems; i++) {
+ if (zend_hash_index_find(&EG(regular_list), i, (void **) &le)==FAILURE) {
+ continue;
+ }
+ if (Z_TYPE_P(le) == le_db || Z_TYPE_P(le) == le_pdb) {
+ info = (dba_info *)(le->ptr);
+ add_index_string(return_value, i, info->path, 1);
+ }
+ }
+}
+/* }}} */
+
+#endif /* HAVE_DBA */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba.dsp b/ext/dba/dba.dsp
new file mode 100644
index 0000000..ddfd148
--- /dev/null
+++ b/ext/dba/dba.dsp
@@ -0,0 +1,213 @@
+# Microsoft Developer Studio Project File - Name="dba" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=dba - Win32 Debug_TS Berkeley DB3
+!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 "dba.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 "dba.mak" CFG="dba - Win32 Debug_TS Berkeley DB3"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dba - Win32 Release_TS Berkeley DB3" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "dba - Win32 Debug_TS Berkeley DB3" (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)" == "dba - Win32 Release_TS Berkeley DB3"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=0 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_DBA" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_DBA=1 /D DBA_DB3=1 /D DB3_INCLUDE_FILE="db.h" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=0 /D DBA_DB3=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_DBA" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_DBA=1 /D DBA_FLATFILE=1 /D DBA_CDB=1 /D DBA_CDB_MAKE=1 /D DBA_CDB_BUILTIN=1 /D DBA_INIFILE=1 /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "NDEBUG"
+# ADD RSC /l 0x407 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 php5ts.lib libdb31s.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_dba.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+# ADD LINK32 php5ts.lib libdb31s.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_dba.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+
+!ELSEIF "$(CFG)" == "dba - Win32 Debug_TS Berkeley DB3"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_DBA" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_DBA=1 /D "DBA_DB3" /D DB3_INCLUDE_FILE="db.h" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "DBA_DB3" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "COMPILE_DL_DBA" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_DBA=1 /D DBA_FLATFILE=1 /D DBA_CDB=1 /D DBA_CDB_MAKE=1 /D DBA_CDB_BUILTIN=1 /D DBA_INIFILE=1 /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x407 /d "_DEBUG"
+# ADD RSC /l 0x407 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 php5ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS/php_dba.dll" /pdbtype:sept /libpath:"..\..\Debug_TS"
+# ADD LINK32 php5ts_debug.lib libdb31s.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"..\..\Debug_TS/php_dba.dll" /pdbtype:sept /libpath:"..\..\Debug_TS"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dba - Win32 Release_TS Berkeley DB3"
+# Name "dba - Win32 Debug_TS Berkeley DB3"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\libcdb\cdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libcdb\cdb_make.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_cdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_db2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_db3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_dbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_flatfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_gdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_inifile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dba_ndbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libflatfile\flatfile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libinifile\inifile.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\libcdb\uint32.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\libcdb\cdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\libcdb\cdb_make.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\libflatfile\flatfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_cdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_db2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_db3.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_dba.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_dbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_flatfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_gdbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_inifile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\php_ndbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\libcdb\uint32.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\libinifile\inifile.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/ext/dba/dba_cdb.c b/ext/dba/dba_cdb.c
new file mode 100644
index 0000000..a4a7314
--- /dev/null
+++ b/ext/dba/dba_cdb.c
@@ -0,0 +1,350 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Sascha Schumann <sascha@schumann.cx> |
+ | Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_CDB
+#include "php_cdb.h"
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+
+#if DBA_CDB_BUILTIN
+# include "libcdb/cdb.h"
+# include "libcdb/cdb_make.h"
+# include "libcdb/uint32.h"
+#else
+# ifdef CDB_INCLUDE_FILE
+# include CDB_INCLUDE_FILE
+# endif
+#endif
+
+#define CDB_INFO \
+ dba_cdb *cdb = (dba_cdb *) info->dbf
+
+typedef struct {
+ struct cdb c;
+#if DBA_CDB_BUILTIN
+ struct cdb_make m;
+ php_stream *file;
+ int make;
+#else
+ int file;
+#endif
+ uint32 eod; /* size of constant database */
+ uint32 pos; /* current position for traversing */
+} dba_cdb;
+
+DBA_OPEN_FUNC(cdb)
+{
+#if DBA_CDB_BUILTIN
+ php_stream* file = 0;
+ int make;
+#else
+ int file = 0;
+#endif
+ dba_cdb *cdb;
+ dba_info *pinfo = (dba_info *) info;
+
+ switch (info->mode) {
+ case DBA_READER:
+#if DBA_CDB_BUILTIN
+ make = 0;
+ file = info->fp;
+#else
+ file = VCWD_OPEN(info->path, O_RDONLY);
+ if (file < 0) {
+ *error = "Unable to open file";
+ return FAILURE;
+ }
+#endif
+ break;
+#if DBA_CDB_BUILTIN
+ case DBA_TRUNC:
+ make = 1;
+ file = info->fp;
+ break;
+ case DBA_CREAT:
+ case DBA_WRITER:
+ *error = "Update operations are not supported";
+ return FAILURE; /* not supported */
+#endif
+ default:
+ *error = "Currently not supported";
+ return FAILURE;
+ }
+
+ cdb = pemalloc(sizeof(dba_cdb), info->flags&DBA_PERSISTENT);
+ memset(cdb, 0, sizeof(dba_cdb));
+
+#if DBA_CDB_BUILTIN
+ if (make) {
+ cdb_make_start(&cdb->m, file TSRMLS_CC);
+ } else {
+ cdb_init(&cdb->c, file TSRMLS_CC);
+ }
+ cdb->make = make;
+#else
+ cdb_init(&cdb->c, file);
+#endif
+ cdb->file = file;
+
+ pinfo->dbf = cdb;
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(cdb)
+{
+ CDB_INFO;
+
+ /* cdb_free does not close associated file */
+#if DBA_CDB_BUILTIN
+ if (cdb->make) {
+ cdb_make_finish(&cdb->m TSRMLS_CC);
+ } else {
+ cdb_free(&cdb->c TSRMLS_CC);
+ }
+#else
+ cdb_free(&cdb->c);
+ close(cdb->file);
+#endif
+ pefree(cdb, info->flags&DBA_PERSISTENT);
+}
+
+#if DBA_CDB_BUILTIN
+# define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos TSRMLS_CC)
+# define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len TSRMLS_CC)
+# define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len TSRMLS_CC)
+#else
+# define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos)
+# define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len)
+# define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len)
+#endif
+
+DBA_FETCH_FUNC(cdb)
+{
+ CDB_INFO;
+ unsigned int len;
+ char *new_entry = NULL;
+
+#if DBA_CDB_BUILTIN
+ if (cdb->make)
+ return NULL; /* database was opened writeonly */
+#endif
+ if (php_cdb_find(&cdb->c, key, keylen) == 1) {
+ while(skip--) {
+ if (php_cdb_findnext(&cdb->c, key, keylen) != 1) {
+ return NULL;
+ }
+ }
+ len = cdb_datalen(&cdb->c);
+ new_entry = safe_emalloc(len, 1, 1);
+
+ if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) {
+ efree(new_entry);
+ return NULL;
+ }
+ new_entry[len] = 0;
+ if (newlen)
+ *newlen = len;
+ }
+
+ return new_entry;
+}
+
+DBA_UPDATE_FUNC(cdb)
+{
+#if DBA_CDB_BUILTIN
+ CDB_INFO;
+
+ if (!cdb->make)
+ return FAILURE; /* database was opened readonly */
+ if (!mode)
+ return FAILURE; /* cdb_make dosn't know replace */
+ if (cdb_make_add(&cdb->m, key, keylen, val, vallen TSRMLS_CC) != -1)
+ return SUCCESS;
+#endif
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(cdb)
+{
+ CDB_INFO;
+
+#if DBA_CDB_BUILTIN
+ if (cdb->make)
+ return FAILURE; /* database was opened writeonly */
+#endif
+ if (php_cdb_find(&cdb->c, key, keylen) == 1)
+ return SUCCESS;
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(cdb)
+{
+ return FAILURE; /* cdb doesn't support delete */
+}
+
+/* {{{ cdb_file_read */
+#if DBA_CDB_BUILTIN
+# define cdb_file_read(fildes, buf, size) php_stream_read(fildes, buf, size)
+#else
+# define cdb_file_read(fildes, buf, size) read(fildes, buf, size)
+#endif
+/* }}} */
+
+#define CREAD(n) do { \
+ if (cdb_file_read(cdb->file, buf, n) < n) return NULL; \
+} while (0)
+
+/* {{{ cdb_file_lseek
+ php_stream_seek does not return actual position */
+#if DBA_CDB_BUILTIN
+int cdb_file_lseek(php_stream *fp, off_t offset, int whence TSRMLS_DC) {
+ php_stream_seek(fp, offset, whence);
+ return php_stream_tell(fp);
+}
+#else
+int cdb_file_lseek(int fd, off_t offset, int whence TSRMLS_DC) {
+ return lseek(fd, offset, whence);
+}
+#endif
+/* }}} */
+
+#define CSEEK(n) do { \
+ if (n >= cdb->eod) return NULL; \
+ if (cdb_file_lseek(cdb->file, (off_t)n, SEEK_SET TSRMLS_CC) != (off_t) n) return NULL; \
+} while (0)
+
+
+DBA_FIRSTKEY_FUNC(cdb)
+{
+ CDB_INFO;
+ uint32 klen, dlen;
+ char buf[8];
+ char *key;
+
+#if DBA_CDB_BUILTIN
+ if (cdb->make)
+ return NULL; /* database was opened writeonly */
+#endif
+
+ cdb->eod = -1;
+ CSEEK(0);
+ CREAD(4);
+
+ /* Total length of file in bytes */
+ uint32_unpack(buf, &cdb->eod);
+
+ CSEEK(2048);
+ CREAD(8);
+
+ /* The first four bytes contain the length of the key */
+ uint32_unpack(buf, &klen);
+ uint32_unpack(buf + 4, &dlen);
+
+ key = safe_emalloc(klen, 1, 1);
+ if (cdb_file_read(cdb->file, key, klen) < klen) {
+ efree(key);
+ key = NULL;
+ } else {
+ key[klen] = '\0';
+ if (newlen) *newlen = klen;
+ }
+
+ /* header + klenlen + dlenlen + klen + dlen */
+ cdb->pos = 2048 + 4 + 4 + klen + dlen;
+
+ return key;
+}
+
+DBA_NEXTKEY_FUNC(cdb)
+{
+ CDB_INFO;
+ uint32 klen, dlen;
+ char buf[8];
+ char *key;
+
+#if DBA_CDB_BUILTIN
+ if (cdb->make)
+ return NULL; /* database was opened writeonly */
+#endif
+
+ CSEEK(cdb->pos);
+ CREAD(8);
+ uint32_unpack(buf, &klen);
+ uint32_unpack(buf + 4, &dlen);
+
+ key = safe_emalloc(klen, 1, 1);
+ if (cdb_file_read(cdb->file, key, klen) < klen) {
+ efree(key);
+ key = NULL;
+ } else {
+ key[klen] = '\0';
+ if (newlen) *newlen = klen;
+ }
+
+ cdb->pos += 8 + klen + dlen;
+
+ return key;
+}
+
+DBA_OPTIMIZE_FUNC(cdb)
+{
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(cdb)
+{
+ /* this is read-only */
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(cdb)
+{
+#if DBA_CDB_BUILTIN
+ if (!strcmp(hnd->name, "cdb")) {
+ return estrdup(cdb_version());
+ } else {
+ return estrdup(cdb_make_version());
+ }
+#else
+ return estrdup("External");
+#endif
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_db1.c b/ext/dba/dba_db1.c
new file mode 100644
index 0000000..fbb24d2
--- /dev/null
+++ b/ext/dba/dba_db1.c
@@ -0,0 +1,197 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Shen Cheng-Da <cdsheen@gmail.com> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_DB1
+#include "php_db1.h"
+
+#ifdef DB1_INCLUDE_FILE
+#include DB1_INCLUDE_FILE
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define DB1_DATA dba_db1_data *dba = info->dbf
+#define DB1_GKEY DBT gkey; gkey.data = (char *) key; gkey.size = keylen
+
+typedef struct {
+ DB *dbp;
+} dba_db1_data;
+
+DBA_OPEN_FUNC(db1)
+{
+ dba_db1_data *dba;
+ DB *db;
+
+ int gmode;
+ int filemode = 0644;
+
+ if (info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ gmode = 0;
+ switch (info->mode) {
+ case DBA_READER:
+ gmode = O_RDONLY;
+ break;
+ case DBA_WRITER:
+ gmode = O_RDWR;
+ break;
+ case DBA_CREAT:
+ gmode = O_RDWR | O_CREAT;
+ break;
+ case DBA_TRUNC:
+ gmode = O_RDWR | O_CREAT | O_TRUNC;
+ break;
+ default:
+ return FAILURE; /* not possible */
+ }
+
+ db = dbopen((char *)info->path, gmode, filemode, DB_HASH, NULL);
+
+ if (db == NULL) {
+ return FAILURE;
+ }
+
+ dba = pemalloc(sizeof(*dba), info->flags&DBA_PERSISTENT);
+ dba->dbp = db;
+
+ info->dbf = dba;
+
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(db1)
+{
+ DB1_DATA;
+ dba->dbp->close(dba->dbp);
+ pefree(info->dbf, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(db1)
+{
+ DBT gval;
+ DB1_DATA;
+ DB1_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ if (dba->dbp->get(dba->dbp, &gkey, &gval, 0) == RET_SUCCESS) {
+ if (newlen) *newlen = gval.size;
+ return estrndup(gval.data, gval.size);
+ }
+ return NULL;
+}
+
+DBA_UPDATE_FUNC(db1)
+{
+ DBT gval;
+ DB1_DATA;
+ DB1_GKEY;
+
+ gval.data = (char *) val;
+ gval.size = vallen;
+
+ return dba->dbp->put(dba->dbp, &gkey, &gval, mode == 1 ? R_NOOVERWRITE : 0) != RET_SUCCESS ? FAILURE : SUCCESS;
+}
+
+DBA_EXISTS_FUNC(db1)
+{
+ DBT gval;
+ DB1_DATA;
+ DB1_GKEY;
+
+ return dba->dbp->get(dba->dbp, &gkey, &gval, 0) != RET_SUCCESS ? FAILURE : SUCCESS;
+}
+
+DBA_DELETE_FUNC(db1)
+{
+ DB1_DATA;
+ DB1_GKEY;
+
+ return dba->dbp->del(dba->dbp, &gkey, 0) != RET_SUCCESS ? FAILURE : SUCCESS;
+}
+
+DBA_FIRSTKEY_FUNC(db1)
+{
+ DBT gkey;
+ DBT gval;
+ DB1_DATA;
+
+ memset(&gkey, 0, sizeof(gkey));
+ memset(&gval, 0, sizeof(gval));
+
+ if (dba->dbp->seq(dba->dbp, &gkey, &gval, R_FIRST) == RET_SUCCESS) {
+ if (newlen) *newlen = gkey.size;
+ return estrndup(gkey.data, gkey.size);
+ }
+ return NULL;
+}
+
+DBA_NEXTKEY_FUNC(db1)
+{
+ DBT gkey;
+ DBT gval;
+ DB1_DATA;
+
+ memset(&gkey, 0, sizeof(gkey));
+ memset(&gval, 0, sizeof(gval));
+
+ if (dba->dbp->seq(dba->dbp, &gkey, &gval, R_NEXT) == RET_SUCCESS) {
+ if (newlen) *newlen = gkey.size;
+ return estrndup(gkey.data, gkey.size);
+ }
+ return NULL;
+}
+
+DBA_OPTIMIZE_FUNC(db1)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(db1)
+{
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(db1)
+{
+ return estrdup(DB1_VERSION);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_db2.c b/ext/dba/dba_db2.c
new file mode 100644
index 0000000..d92613a
--- /dev/null
+++ b/ext/dba/dba_db2.c
@@ -0,0 +1,209 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_DB2
+#include "php_db2.h"
+#include <sys/stat.h>
+
+#include <string.h>
+#ifdef DB2_INCLUDE_FILE
+#include DB2_INCLUDE_FILE
+#endif
+
+#define DB2_DATA dba_db2_data *dba = info->dbf
+#define DB2_GKEY \
+ DBT gkey = {0}; \
+ gkey.data = (char *) key; \
+ gkey.size = keylen
+
+typedef struct {
+ DB *dbp;
+ DBC *cursor;
+} dba_db2_data;
+
+DBA_OPEN_FUNC(db2)
+{
+ DB *dbp;
+ DBTYPE type;
+ int gmode = 0;
+ int filemode = 0644;
+ struct stat check_stat;
+ int s = VCWD_STAT(info->path, &check_stat);
+
+ if (!s && !check_stat.st_size) {
+ info->mode = DBA_TRUNC; /* force truncate */
+ }
+
+ type = info->mode == DBA_READER ? DB_UNKNOWN :
+ info->mode == DBA_TRUNC ? DB_BTREE :
+ s ? DB_BTREE : DB_UNKNOWN;
+
+ gmode = info->mode == DBA_READER ? DB_RDONLY :
+ (info->mode == DBA_CREAT && s) ? DB_CREATE :
+ (info->mode == DBA_CREAT && !s) ? 0 :
+ info->mode == DBA_WRITER ? 0 :
+ info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
+
+ if (gmode == -1) {
+ return FAILURE;/* not possible */
+ }
+
+ if (info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ if (db_open(info->path, type, gmode, filemode, NULL, NULL, &dbp)) {
+ return FAILURE;
+ }
+
+ info->dbf = pemalloc(sizeof(dba_db2_data), info->flags&DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_db2_data));
+ ((dba_db2_data *) info->dbf)->dbp = dbp;
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(db2)
+{
+ DB2_DATA;
+
+ if (dba->cursor)
+ dba->cursor->c_close(dba->cursor);
+ dba->dbp->close(dba->dbp, 0);
+ pefree(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(db2)
+{
+ DBT gval = {0};
+ DB2_DATA;
+ DB2_GKEY;
+
+ if (dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ return NULL;
+ }
+
+ if (newlen) *newlen = gval.size;
+ return estrndup(gval.data, gval.size);
+}
+
+DBA_UPDATE_FUNC(db2)
+{
+ DBT gval = {0};
+ DB2_DATA;
+ DB2_GKEY;
+
+ gval.data = (char *) val;
+ gval.size = vallen;
+
+ if (dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
+ mode == 1 ? DB_NOOVERWRITE : 0)) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+DBA_EXISTS_FUNC(db2)
+{
+ DBT gval = {0};
+ DB2_DATA;
+ DB2_GKEY;
+
+ if (dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+
+DBA_DELETE_FUNC(db2)
+{
+ DB2_DATA;
+ DB2_GKEY;
+
+ return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_FIRSTKEY_FUNC(db2)
+{
+ DB2_DATA;
+
+ if (dba->cursor) {
+ dba->cursor->c_close(dba->cursor);
+ dba->cursor = NULL;
+ }
+
+#if (DB_VERSION_MAJOR > 2) || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 6) || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 6 && DB_VERSION_PATCH >= 4)
+ if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0)) {
+#else
+ if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor)) {
+#endif
+ return NULL;
+ }
+
+ /* we should introduce something like PARAM_PASSTHRU... */
+ return dba_nextkey_db2(info, newlen TSRMLS_CC);
+}
+
+DBA_NEXTKEY_FUNC(db2)
+{
+ DB2_DATA;
+ DBT gkey = {0}, gval = {0};
+
+ if (dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT)
+ || !gkey.data)
+ return NULL;
+
+ if (newlen) *newlen = gkey.size;
+ return estrndup(gkey.data, gkey.size);
+}
+
+DBA_OPTIMIZE_FUNC(db2)
+{
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(db2)
+{
+ DB2_DATA;
+
+ return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_INFO_FUNC(db2)
+{
+ return estrdup(DB_VERSION_STRING);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_db3.c b/ext/dba/dba_db3.c
new file mode 100644
index 0000000..b236865
--- /dev/null
+++ b/ext/dba/dba_db3.c
@@ -0,0 +1,238 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_DB3
+#include "php_db3.h"
+#include <sys/stat.h>
+
+#include <string.h>
+#ifdef DB3_INCLUDE_FILE
+#include DB3_INCLUDE_FILE
+#else
+#include <db.h>
+#endif
+
+static void php_dba_db3_errcall_fcn(const char *errpfx, char *msg)
+{
+ TSRMLS_FETCH();
+
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
+}
+
+#define DB3_DATA dba_db3_data *dba = info->dbf
+#define DB3_GKEY \
+ DBT gkey; \
+ memset(&gkey, 0, sizeof(gkey)); \
+ gkey.data = (char *) key; gkey.size = keylen
+
+typedef struct {
+ DB *dbp;
+ DBC *cursor;
+} dba_db3_data;
+
+DBA_OPEN_FUNC(db3)
+{
+ DB *dbp = NULL;
+ DBTYPE type;
+ int gmode = 0, err;
+ int filemode = 0644;
+ struct stat check_stat;
+ int s = VCWD_STAT(info->path, &check_stat);
+
+ if (!s && !check_stat.st_size) {
+ info->mode = DBA_TRUNC; /* force truncate */
+ }
+
+ type = info->mode == DBA_READER ? DB_UNKNOWN :
+ info->mode == DBA_TRUNC ? DB_BTREE :
+ s ? DB_BTREE : DB_UNKNOWN;
+
+ gmode = info->mode == DBA_READER ? DB_RDONLY :
+ (info->mode == DBA_CREAT && s) ? DB_CREATE :
+ (info->mode == DBA_CREAT && !s) ? 0 :
+ info->mode == DBA_WRITER ? 0 :
+ info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
+
+ if (gmode == -1) {
+ return FAILURE; /* not possible */
+ }
+
+ if (info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+#ifdef DB_FCNTL_LOCKING
+ gmode |= DB_FCNTL_LOCKING;
+#endif
+
+ if ((err=db_create(&dbp, NULL, 0)) == 0) {
+ dbp->set_errcall(dbp, php_dba_db3_errcall_fcn);
+ if ((err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+ dba_db3_data *data;
+
+ data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
+ data->dbp = dbp;
+ data->cursor = NULL;
+ info->dbf = data;
+
+ return SUCCESS;
+ } else {
+ dbp->close(dbp, 0);
+ *error = db_strerror(err);
+ }
+ } else {
+ *error = db_strerror(err);
+ }
+
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(db3)
+{
+ DB3_DATA;
+
+ if (dba->cursor) dba->cursor->c_close(dba->cursor);
+ dba->dbp->close(dba->dbp, 0);
+ pefree(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(db3)
+{
+ DBT gval;
+ char *new = NULL;
+ DB3_DATA;
+ DB3_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ if (newlen) *newlen = gval.size;
+ new = estrndup(gval.data, gval.size);
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(db3)
+{
+ DBT gval;
+ DB3_DATA;
+ DB3_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ gval.data = (char *) val;
+ gval.size = vallen;
+
+ if (!dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
+ mode == 1 ? DB_NOOVERWRITE : 0)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(db3)
+{
+ DBT gval;
+ DB3_DATA;
+ DB3_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(db3)
+{
+ DB3_DATA;
+ DB3_GKEY;
+
+ return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_FIRSTKEY_FUNC(db3)
+{
+ DB3_DATA;
+
+ if (dba->cursor) {
+ dba->cursor->c_close(dba->cursor);
+ }
+
+ dba->cursor = NULL;
+ if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0) != 0) {
+ return NULL;
+ }
+
+ /* we should introduce something like PARAM_PASSTHRU... */
+ return dba_nextkey_db3(info, newlen TSRMLS_CC);
+}
+
+DBA_NEXTKEY_FUNC(db3)
+{
+ DB3_DATA;
+ DBT gkey, gval;
+ char *nkey = NULL;
+
+ memset(&gkey, 0, sizeof(gkey));
+ memset(&gval, 0, sizeof(gval));
+
+ if (dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT) == 0) {
+ if (gkey.data) {
+ nkey = estrndup(gkey.data, gkey.size);
+ if (newlen) *newlen = gkey.size;
+ }
+ }
+
+ return nkey;
+}
+
+DBA_OPTIMIZE_FUNC(db3)
+{
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(db3)
+{
+ DB3_DATA;
+
+ return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_INFO_FUNC(db3)
+{
+ return estrdup(DB_VERSION_STRING);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_db4.c b/ext/dba/dba_db4.c
new file mode 100644
index 0000000..8987f1a
--- /dev/null
+++ b/ext/dba/dba_db4.c
@@ -0,0 +1,302 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ | Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_DB4
+#include "php_db4.h"
+#include <sys/stat.h>
+
+#include <string.h>
+#ifdef DB4_INCLUDE_FILE
+#include DB4_INCLUDE_FILE
+#else
+#include <db.h>
+#endif
+
+static void php_dba_db4_errcall_fcn(
+#if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3))
+ const DB_ENV *dbenv,
+#endif
+ const char *errpfx, const char *msg)
+{
+ TSRMLS_FETCH();
+
+#if (DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 8))
+/* Bug 51086, Berkeley DB 4.8.26 */
+/* This code suppresses a BDB 4.8+ error message, thus keeping PHP test compatibility */
+ {
+ const char *function = get_active_function_name(TSRMLS_C);
+ if (function && (!strcmp(function,"dba_popen") || !strcmp(function,"dba_open"))
+ && (!strncmp(msg, "fop_read_meta", sizeof("fop_read_meta")-1)
+ || !strncmp(msg, "BDB0004 fop_read_meta", sizeof("BDB0004 fop_read_meta")-1))) {
+ return;
+ }
+ }
+#endif
+
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
+}
+
+#define DB4_DATA dba_db4_data *dba = info->dbf
+#define DB4_GKEY \
+ DBT gkey; \
+ memset(&gkey, 0, sizeof(gkey)); \
+ gkey.data = (char *) key; gkey.size = keylen
+
+typedef struct {
+ DB *dbp;
+ DBC *cursor;
+} dba_db4_data;
+
+DBA_OPEN_FUNC(db4)
+{
+ DB *dbp = NULL;
+ DBTYPE type;
+ int gmode = 0, err;
+ int filemode = 0644;
+ struct stat check_stat;
+ int s = VCWD_STAT(info->path, &check_stat);
+
+#if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 7) /* Bug 51086 */
+ if (!s && !check_stat.st_size) {
+ info->mode = DBA_TRUNC; /* force truncate */
+ }
+
+ type = info->mode == DBA_READER ? DB_UNKNOWN :
+ info->mode == DBA_TRUNC ? DB_BTREE :
+ s ? DB_BTREE : DB_UNKNOWN;
+
+ gmode = info->mode == DBA_READER ? DB_RDONLY :
+ (info->mode == DBA_CREAT && s) ? DB_CREATE :
+ (info->mode == DBA_CREAT && !s) ? 0 :
+ info->mode == DBA_WRITER ? 0 :
+ info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
+#else
+ if (!s && !check_stat.st_size) {
+ info->mode = DBA_CREAT; /* force creation */
+ }
+
+ type = info->mode == DBA_READER ? DB_UNKNOWN :
+ (info->mode == DBA_TRUNC || info->mode == DBA_CREAT) ? DB_BTREE :
+ s ? DB_BTREE : DB_UNKNOWN;
+
+ gmode = info->mode == DBA_READER ? DB_RDONLY :
+ info->mode == DBA_CREAT ? DB_CREATE :
+ info->mode == DBA_WRITER ? 0 :
+ info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
+#endif
+
+ if (gmode == -1) {
+ return FAILURE; /* not possible */
+ }
+
+ if (info->flags & DBA_PERSISTENT) {
+ gmode |= DB_THREAD;
+ }
+
+ if (info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ if ((err=db_create(&dbp, NULL, 0)) == 0) {
+ dbp->set_errcall(dbp, php_dba_db4_errcall_fcn);
+ if (
+#if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
+ (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
+#else
+ (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+#endif
+ dba_db4_data *data;
+
+ data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
+ data->dbp = dbp;
+ data->cursor = NULL;
+ info->dbf = data;
+
+ return SUCCESS;
+ } else {
+ dbp->close(dbp, 0);
+ *error = db_strerror(err);
+ }
+ } else {
+ *error = db_strerror(err);
+ }
+
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(db4)
+{
+ DB4_DATA;
+
+ if (dba->cursor) dba->cursor->c_close(dba->cursor);
+ dba->dbp->close(dba->dbp, 0);
+ pefree(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(db4)
+{
+ DBT gval;
+ char *new = NULL;
+ DB4_DATA;
+ DB4_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ if (info->flags & DBA_PERSISTENT) {
+ gval.flags |= DB_DBT_MALLOC;
+ }
+ if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ if (newlen) *newlen = gval.size;
+ new = estrndup(gval.data, gval.size);
+ if (info->flags & DBA_PERSISTENT) {
+ free(gval.data);
+ }
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(db4)
+{
+ DBT gval;
+ DB4_DATA;
+ DB4_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+ gval.data = (char *) val;
+ gval.size = vallen;
+
+ if (!dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
+ mode == 1 ? DB_NOOVERWRITE : 0)) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(db4)
+{
+ DBT gval;
+ DB4_DATA;
+ DB4_GKEY;
+
+ memset(&gval, 0, sizeof(gval));
+
+ if (info->flags & DBA_PERSISTENT) {
+ gval.flags |= DB_DBT_MALLOC;
+ }
+
+ if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
+ if (info->flags & DBA_PERSISTENT) {
+ free(gval.data);
+ }
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(db4)
+{
+ DB4_DATA;
+ DB4_GKEY;
+
+ return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_FIRSTKEY_FUNC(db4)
+{
+ DB4_DATA;
+
+ if (dba->cursor) {
+ dba->cursor->c_close(dba->cursor);
+ }
+
+ dba->cursor = NULL;
+ if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0) != 0) {
+ return NULL;
+ }
+
+ /* we should introduce something like PARAM_PASSTHRU... */
+ return dba_nextkey_db4(info, newlen TSRMLS_CC);
+}
+
+DBA_NEXTKEY_FUNC(db4)
+{
+ DB4_DATA;
+ DBT gkey, gval;
+ char *nkey = NULL;
+
+ memset(&gkey, 0, sizeof(gkey));
+ memset(&gval, 0, sizeof(gval));
+
+ if (info->flags & DBA_PERSISTENT) {
+ gkey.flags |= DB_DBT_MALLOC;
+ gval.flags |= DB_DBT_MALLOC;
+ }
+ if (dba->cursor && dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT) == 0) {
+ if (gkey.data) {
+ nkey = estrndup(gkey.data, gkey.size);
+ if (newlen) *newlen = gkey.size;
+ }
+ if (info->flags & DBA_PERSISTENT) {
+ if (gkey.data) {
+ free(gkey.data);
+ }
+ if (gval.data) {
+ free(gval.data);
+ }
+ }
+ }
+
+ return nkey;
+}
+
+DBA_OPTIMIZE_FUNC(db4)
+{
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(db4)
+{
+ DB4_DATA;
+
+ return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
+}
+
+DBA_INFO_FUNC(db4)
+{
+ return estrdup(DB_VERSION_STRING);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_dbm.c b/ext/dba/dba_dbm.c
new file mode 100644
index 0000000..2f3b800
--- /dev/null
+++ b/ext/dba/dba_dbm.c
@@ -0,0 +1,213 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_DBM
+#include "php_dbm.h"
+
+#ifdef DBM_INCLUDE_FILE
+#include DBM_INCLUDE_FILE
+#endif
+#if DBA_GDBM
+#include "php_gdbm.h"
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define DBM_DATA dba_dbm_data *dba = info->dbf
+#define DBM_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
+
+#define TRUNC_IT(extension, mode) \
+ snprintf(buf, MAXPATHLEN, "%s" extension, info->path); \
+ buf[MAXPATHLEN-1] = '\0'; \
+ if((fd = VCWD_OPEN_MODE(buf, O_CREAT | mode | O_WRONLY, filemode)) == -1) \
+ return FAILURE; \
+ close(fd);
+
+
+typedef struct {
+ datum nextkey;
+} dba_dbm_data;
+
+DBA_OPEN_FUNC(dbm)
+{
+ int fd;
+ int filemode = 0644;
+
+ if(info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ if(info->mode == DBA_TRUNC) {
+ char buf[MAXPATHLEN];
+
+ /* dbm/ndbm original */
+ TRUNC_IT(".pag", O_TRUNC);
+ TRUNC_IT(".dir", O_TRUNC);
+ }
+
+ if(info->mode == DBA_CREAT) {
+ char buf[MAXPATHLEN];
+
+ TRUNC_IT(".pag", 0);
+ TRUNC_IT(".dir", 0);
+ }
+
+ if(dbminit((char *) info->path) == -1) {
+ return FAILURE;
+ }
+
+ info->dbf = pemalloc(sizeof(dba_dbm_data), info->flags&DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_dbm_data));
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(dbm)
+{
+ pefree(info->dbf, info->flags&DBA_PERSISTENT);
+ dbmclose();
+}
+
+DBA_FETCH_FUNC(dbm)
+{
+ datum gval;
+ char *new = NULL;
+
+ DBM_GKEY;
+ gval = fetch(gkey);
+ if(gval.dptr) {
+ if(newlen) *newlen = gval.dsize;
+ new = estrndup(gval.dptr, gval.dsize);
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(dbm)
+{
+ datum gval;
+
+ DBM_GKEY;
+
+ if (mode == 1) { /* insert */
+ gval = fetch(gkey);
+ if(gval.dptr) {
+ return FAILURE;
+ }
+ }
+
+ gval.dptr = (char *) val;
+ gval.dsize = vallen;
+
+ return (store(gkey, gval) == -1 ? FAILURE : SUCCESS);
+}
+
+DBA_EXISTS_FUNC(dbm)
+{
+ datum gval;
+ DBM_GKEY;
+
+ gval = fetch(gkey);
+ if(gval.dptr) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(dbm)
+{
+ DBM_GKEY;
+ return(delete(gkey) == -1 ? FAILURE : SUCCESS);
+}
+
+DBA_FIRSTKEY_FUNC(dbm)
+{
+ DBM_DATA;
+ datum gkey;
+ char *key = NULL;
+
+ gkey = firstkey();
+ if(gkey.dptr) {
+ if(newlen) *newlen = gkey.dsize;
+ key = estrndup(gkey.dptr, gkey.dsize);
+ dba->nextkey = gkey;
+ } else
+ dba->nextkey.dptr = NULL;
+ return key;
+}
+
+DBA_NEXTKEY_FUNC(dbm)
+{
+ DBM_DATA;
+ datum gkey;
+ char *nkey = NULL;
+
+ if(!dba->nextkey.dptr) return NULL;
+
+ gkey = nextkey(dba->nextkey);
+ if(gkey.dptr) {
+ if(newlen) *newlen = gkey.dsize;
+ nkey = estrndup(gkey.dptr, gkey.dsize);
+ dba->nextkey = gkey;
+ } else
+ dba->nextkey.dptr = NULL;
+ return nkey;
+}
+
+DBA_OPTIMIZE_FUNC(dbm)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(dbm)
+{
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(dbm)
+{
+#if DBA_GDBM
+ if (!strcmp(DBM_VERSION, "GDBM"))
+ {
+ return dba_info_gdbm(hnd, info TSRMLS_CC);
+ }
+#endif
+ return estrdup(DBM_VERSION);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_flatfile.c b/ext/dba/dba_flatfile.c
new file mode 100644
index 0000000..082aa5c
--- /dev/null
+++ b/ext/dba/dba_flatfile.c
@@ -0,0 +1,188 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_FLATFILE
+#include "php_flatfile.h"
+
+#include "libflatfile/flatfile.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define FLATFILE_DATA flatfile *dba = info->dbf
+#define FLATFILE_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
+
+DBA_OPEN_FUNC(flatfile)
+{
+ info->dbf = pemalloc(sizeof(flatfile), info->flags&DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(flatfile));
+
+ ((flatfile*)info->dbf)->fp = info->fp;
+
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(flatfile)
+{
+ FLATFILE_DATA;
+
+ if (dba->nextkey.dptr) {
+ efree(dba->nextkey.dptr);
+ }
+ pefree(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(flatfile)
+{
+ datum gval;
+ char *new = NULL;
+
+ FLATFILE_DATA;
+ FLATFILE_GKEY;
+
+ gval = flatfile_fetch(dba, gkey TSRMLS_CC);
+ if (gval.dptr) {
+ if (newlen) {
+ *newlen = gval.dsize;
+ }
+ new = estrndup(gval.dptr, gval.dsize);
+ efree(gval.dptr);
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(flatfile)
+{
+ datum gval;
+
+ FLATFILE_DATA;
+ FLATFILE_GKEY;
+ gval.dptr = (char *) val;
+ gval.dsize = vallen;
+
+ switch(flatfile_store(dba, gkey, gval, mode==1 ? FLATFILE_INSERT : FLATFILE_REPLACE TSRMLS_CC)) {
+ case -1:
+ php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Operation not possible");
+ return FAILURE;
+ default:
+ case 0:
+ return SUCCESS;
+ case 1:
+ php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Key already exists");
+ return FAILURE;
+ }
+}
+
+DBA_EXISTS_FUNC(flatfile)
+{
+ datum gval;
+ FLATFILE_DATA;
+ FLATFILE_GKEY;
+
+ gval = flatfile_fetch(dba, gkey TSRMLS_CC);
+ if (gval.dptr) {
+ efree(gval.dptr);
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(flatfile)
+{
+ FLATFILE_DATA;
+ FLATFILE_GKEY;
+ return(flatfile_delete(dba, gkey TSRMLS_CC) == -1 ? FAILURE : SUCCESS);
+}
+
+DBA_FIRSTKEY_FUNC(flatfile)
+{
+ FLATFILE_DATA;
+
+ if (dba->nextkey.dptr) {
+ efree(dba->nextkey.dptr);
+ }
+ dba->nextkey = flatfile_firstkey(dba TSRMLS_CC);
+ if (dba->nextkey.dptr) {
+ if (newlen) {
+ *newlen = dba->nextkey.dsize;
+ }
+ return estrndup(dba->nextkey.dptr, dba->nextkey.dsize);
+ }
+ return NULL;
+}
+
+DBA_NEXTKEY_FUNC(flatfile)
+{
+ FLATFILE_DATA;
+
+ if (!dba->nextkey.dptr) {
+ return NULL;
+ }
+
+ if (dba->nextkey.dptr) {
+ efree(dba->nextkey.dptr);
+ }
+ dba->nextkey = flatfile_nextkey(dba TSRMLS_CC);
+ if (dba->nextkey.dptr) {
+ if (newlen) {
+ *newlen = dba->nextkey.dsize;
+ }
+ return estrndup(dba->nextkey.dptr, dba->nextkey.dsize);
+ }
+ return NULL;
+}
+
+DBA_OPTIMIZE_FUNC(flatfile)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(flatfile)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(flatfile)
+{
+ return estrdup(flatfile_version());
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_gdbm.c b/ext/dba/dba_gdbm.c
new file mode 100644
index 0000000..7534568
--- /dev/null
+++ b/ext/dba/dba_gdbm.c
@@ -0,0 +1,200 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_GDBM
+#include "php_gdbm.h"
+
+#ifdef GDBM_INCLUDE_FILE
+#include GDBM_INCLUDE_FILE
+#endif
+
+#define GDBM_DATA dba_gdbm_data *dba = info->dbf
+#define GDBM_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
+
+typedef struct {
+ GDBM_FILE dbf;
+ datum nextkey;
+} dba_gdbm_data;
+
+DBA_OPEN_FUNC(gdbm)
+{
+ GDBM_FILE dbf;
+ int gmode = 0;
+ int filemode = 0644;
+
+ gmode = info->mode == DBA_READER ? GDBM_READER :
+ info->mode == DBA_WRITER ? GDBM_WRITER :
+ info->mode == DBA_CREAT ? GDBM_WRCREAT :
+ info->mode == DBA_TRUNC ? GDBM_NEWDB : -1;
+
+ if(gmode == -1)
+ return FAILURE; /* not possible */
+
+ if(info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ dbf = gdbm_open(info->path, 0, gmode, filemode, NULL);
+
+ if(dbf) {
+ info->dbf = pemalloc(sizeof(dba_gdbm_data), info->flags&DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_gdbm_data));
+ ((dba_gdbm_data *) info->dbf)->dbf = dbf;
+ return SUCCESS;
+ }
+ *error = gdbm_strerror(gdbm_errno);
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(gdbm)
+{
+ GDBM_DATA;
+
+ if(dba->nextkey.dptr) free(dba->nextkey.dptr);
+ gdbm_close(dba->dbf);
+ pefree(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(gdbm)
+{
+ GDBM_DATA;
+ datum gval;
+ char *new = NULL;
+
+ GDBM_GKEY;
+ gval = gdbm_fetch(dba->dbf, gkey);
+ if(gval.dptr) {
+ if(newlen) *newlen = gval.dsize;
+ new = estrndup(gval.dptr, gval.dsize);
+ free(gval.dptr);
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(gdbm)
+{
+ datum gval;
+ GDBM_DATA;
+
+ GDBM_GKEY;
+ gval.dptr = (char *) val;
+ gval.dsize = vallen;
+
+ if(gdbm_store(dba->dbf, gkey, gval,
+ mode == 1 ? GDBM_INSERT : GDBM_REPLACE) == 0)
+ return SUCCESS;
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", gdbm_strerror(gdbm_errno));
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(gdbm)
+{
+ GDBM_DATA;
+ GDBM_GKEY;
+
+ return gdbm_exists(dba->dbf, gkey) ? SUCCESS : FAILURE;
+}
+
+DBA_DELETE_FUNC(gdbm)
+{
+ GDBM_DATA;
+ GDBM_GKEY;
+
+ return gdbm_delete(dba->dbf, gkey) == -1 ? FAILURE : SUCCESS;
+}
+
+DBA_FIRSTKEY_FUNC(gdbm)
+{
+ GDBM_DATA;
+ datum gkey;
+ char *key = NULL;
+
+ if(dba->nextkey.dptr) {
+ free(dba->nextkey.dptr);
+ }
+
+ gkey = gdbm_firstkey(dba->dbf);
+ if(gkey.dptr) {
+ key = estrndup(gkey.dptr, gkey.dsize);
+ if(newlen) *newlen = gkey.dsize;
+ dba->nextkey = gkey;
+ } else {
+ dba->nextkey.dptr = NULL;
+ }
+ return key;
+}
+
+DBA_NEXTKEY_FUNC(gdbm)
+{
+ GDBM_DATA;
+ char *nkey = NULL;
+ datum gkey;
+
+ if(!dba->nextkey.dptr) return NULL;
+
+ gkey = gdbm_nextkey(dba->dbf, dba->nextkey);
+ free(dba->nextkey.dptr);
+ if(gkey.dptr) {
+ nkey = estrndup(gkey.dptr, gkey.dsize);
+ if(newlen) *newlen = gkey.dsize;
+ dba->nextkey = gkey;
+ } else {
+ dba->nextkey.dptr = NULL;
+ }
+ return nkey;
+}
+
+DBA_OPTIMIZE_FUNC(gdbm)
+{
+ GDBM_DATA;
+ gdbm_reorganize(dba->dbf);
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(gdbm)
+{
+ GDBM_DATA;
+
+ gdbm_sync(dba->dbf);
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(gdbm)
+{
+ return estrdup(gdbm_version);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_inifile.c b/ext/dba/dba_inifile.c
new file mode 100644
index 0000000..e1359b6
--- /dev/null
+++ b/ext/dba/dba_inifile.c
@@ -0,0 +1,194 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_INIFILE
+#include "php_inifile.h"
+
+#include "libinifile/inifile.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define INIFILE_DATA \
+ inifile *dba = info->dbf
+
+#define INIFILE_GKEY \
+ key_type ini_key; \
+ if (!key) { \
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No key specified"); \
+ return 0; \
+ } \
+ ini_key = inifile_key_split((char*)key) /* keylen not needed here */
+
+#define INIFILE_DONE \
+ inifile_key_free(&ini_key)
+
+DBA_OPEN_FUNC(inifile)
+{
+ info->dbf = inifile_alloc(info->fp, info->mode == DBA_READER, info->flags&DBA_PERSISTENT TSRMLS_CC);
+
+ return info->dbf ? SUCCESS : FAILURE;
+}
+
+DBA_CLOSE_FUNC(inifile)
+{
+ INIFILE_DATA;
+
+ inifile_free(dba, info->flags&DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(inifile)
+{
+ val_type ini_val;
+
+ INIFILE_DATA;
+ INIFILE_GKEY;
+
+ ini_val = inifile_fetch(dba, &ini_key, skip TSRMLS_CC);
+ *newlen = ini_val.value ? strlen(ini_val.value) : 0;
+ INIFILE_DONE;
+ return ini_val.value;
+}
+
+DBA_UPDATE_FUNC(inifile)
+{
+ val_type ini_val;
+ int res;
+
+ INIFILE_DATA;
+ INIFILE_GKEY;
+
+ ini_val.value = val;
+
+ if (mode == 1) {
+ res = inifile_append(dba, &ini_key, &ini_val TSRMLS_CC);
+ } else {
+ res = inifile_replace(dba, &ini_key, &ini_val TSRMLS_CC);
+ }
+ INIFILE_DONE;
+ switch(res) {
+ case -1:
+ php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Operation not possible");
+ return FAILURE;
+ default:
+ case 0:
+ return SUCCESS;
+ case 1:
+ php_error_docref1(NULL TSRMLS_CC, key, E_WARNING, "Key already exists");
+ return FAILURE;
+ }
+}
+
+DBA_EXISTS_FUNC(inifile)
+{
+ val_type ini_val;
+
+ INIFILE_DATA;
+ INIFILE_GKEY;
+
+ ini_val = inifile_fetch(dba, &ini_key, 0 TSRMLS_CC);
+ INIFILE_DONE;
+ if (ini_val.value) {
+ inifile_val_free(&ini_val);
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(inifile)
+{
+ int res;
+
+ INIFILE_DATA;
+ INIFILE_GKEY;
+
+ res = inifile_delete(dba, &ini_key TSRMLS_CC);
+
+ INIFILE_DONE;
+ return (res == -1 ? FAILURE : SUCCESS);
+}
+
+DBA_FIRSTKEY_FUNC(inifile)
+{
+ INIFILE_DATA;
+
+ if (inifile_firstkey(dba TSRMLS_CC)) {
+ char *result = inifile_key_string(&dba->curr.key);
+ *newlen = strlen(result);
+ return result;
+ } else {
+ return NULL;
+ }
+}
+
+DBA_NEXTKEY_FUNC(inifile)
+{
+ INIFILE_DATA;
+
+ if (!dba->curr.key.group && !dba->curr.key.name) {
+ return NULL;
+ }
+
+ if (inifile_nextkey(dba TSRMLS_CC)) {
+ char *result = inifile_key_string(&dba->curr.key);
+ *newlen = strlen(result);
+ return result;
+ } else {
+ return NULL;
+ }
+}
+
+DBA_OPTIMIZE_FUNC(inifile)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(inifile)
+{
+ /* dummy */
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(inifile)
+{
+ return estrdup(inifile_version());
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_ndbm.c b/ext/dba/dba_ndbm.c
new file mode 100644
index 0000000..8b5bbda
--- /dev/null
+++ b/ext/dba/dba_ndbm.c
@@ -0,0 +1,171 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_NDBM
+#include "php_ndbm.h"
+
+#include <fcntl.h>
+#ifdef NDBM_INCLUDE_FILE
+#include NDBM_INCLUDE_FILE
+#endif
+
+#define NDBM_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
+
+DBA_OPEN_FUNC(ndbm)
+{
+ DBM *dbf;
+ int gmode = 0;
+ int filemode = 0644;
+ dba_info *pinfo = (dba_info *) info;
+
+ switch(info->mode) {
+ case DBA_READER:
+ gmode = O_RDONLY;
+ break;
+ case DBA_WRITER:
+ gmode = O_RDWR;
+ break;
+ case DBA_CREAT:
+ gmode = O_RDWR | O_CREAT;
+ break;
+ case DBA_TRUNC:
+ gmode = O_RDWR | O_CREAT | O_TRUNC;
+ break;
+ default:
+ return FAILURE; /* not possible */
+ }
+
+ if(info->argc > 0) {
+ convert_to_long_ex(info->argv[0]);
+ filemode = Z_LVAL_PP(info->argv[0]);
+ }
+
+ dbf = dbm_open(info->path, gmode, filemode);
+
+ pinfo->dbf = dbf;
+ return SUCCESS;
+}
+
+DBA_CLOSE_FUNC(ndbm)
+{
+ dbm_close(info->dbf);
+}
+
+DBA_FETCH_FUNC(ndbm)
+{
+ datum gval;
+ char *new = NULL;
+
+ NDBM_GKEY;
+ gval = dbm_fetch(info->dbf, gkey);
+ if(gval.dptr) {
+ if(newlen) *newlen = gval.dsize;
+ new = estrndup(gval.dptr, gval.dsize);
+ }
+ return new;
+}
+
+DBA_UPDATE_FUNC(ndbm)
+{
+ datum gval;
+
+ NDBM_GKEY;
+ gval.dptr = (char *) val;
+ gval.dsize = vallen;
+
+ if(!dbm_store(info->dbf, gkey, gval, mode == 1 ? DBM_INSERT : DBM_REPLACE))
+ return SUCCESS;
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(ndbm)
+{
+ datum gval;
+ NDBM_GKEY;
+ gval = dbm_fetch(info->dbf, gkey);
+ if(gval.dptr) {
+ return SUCCESS;
+ }
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(ndbm)
+{
+ NDBM_GKEY;
+ return(dbm_delete(info->dbf, gkey) == -1 ? FAILURE : SUCCESS);
+}
+
+DBA_FIRSTKEY_FUNC(ndbm)
+{
+ datum gkey;
+ char *key = NULL;
+
+ gkey = dbm_firstkey(info->dbf);
+ if(gkey.dptr) {
+ if(newlen) *newlen = gkey.dsize;
+ key = estrndup(gkey.dptr, gkey.dsize);
+ }
+ return key;
+}
+
+DBA_NEXTKEY_FUNC(ndbm)
+{
+ datum gkey;
+ char *nkey = NULL;
+
+ gkey = dbm_nextkey(info->dbf);
+ if(gkey.dptr) {
+ if(newlen) *newlen = gkey.dsize;
+ nkey = estrndup(gkey.dptr, gkey.dsize);
+ }
+ return nkey;
+}
+
+DBA_OPTIMIZE_FUNC(ndbm)
+{
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(ndbm)
+{
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(ndbm)
+{
+ return estrdup("NDBM");
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_qdbm.c b/ext/dba/dba_qdbm.c
new file mode 100644
index 0000000..485b199
--- /dev/null
+++ b/ext/dba/dba_qdbm.c
@@ -0,0 +1,194 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcin Gibula <mg@iceni.pl> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_QDBM
+#include "php_qdbm.h"
+
+#ifdef QDBM_INCLUDE_FILE
+#include QDBM_INCLUDE_FILE
+#endif
+
+#define QDBM_DATA dba_qdbm_data *dba = info->dbf
+
+typedef struct {
+ DEPOT *dbf;
+} dba_qdbm_data;
+
+DBA_OPEN_FUNC(qdbm)
+{
+ DEPOT *dbf;
+
+ switch(info->mode) {
+ case DBA_READER:
+ dbf = dpopen(info->path, DP_OREADER, 0);
+ break;
+ case DBA_WRITER:
+ dbf = dpopen(info->path, DP_OWRITER, 0);
+ break;
+ case DBA_CREAT:
+ dbf = dpopen(info->path, DP_OWRITER | DP_OCREAT, 0);
+ break;
+ case DBA_TRUNC:
+ dbf = dpopen(info->path, DP_OWRITER | DP_OCREAT | DP_OTRUNC, 0);
+ break;
+ default:
+ return FAILURE;
+ }
+
+ if (dbf) {
+ info->dbf = pemalloc(sizeof(dba_qdbm_data), info->flags & DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_qdbm_data));
+ ((dba_qdbm_data *) info->dbf)->dbf = dbf;
+ return SUCCESS;
+ }
+
+ *error = (char *) dperrmsg(dpecode);
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(qdbm)
+{
+ QDBM_DATA;
+
+ dpclose(dba->dbf);
+ pefree(dba, info->flags & DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(qdbm)
+{
+ QDBM_DATA;
+ char *value, *new = NULL;
+ int value_size;
+
+ value = dpget(dba->dbf, key, keylen, 0, -1, &value_size);
+ if (value) {
+ if (newlen) *newlen = value_size;
+ new = estrndup(value, value_size);
+ free(value);
+ }
+
+ return new;
+}
+
+DBA_UPDATE_FUNC(qdbm)
+{
+ QDBM_DATA;
+ int result;
+
+ result = dpput(dba->dbf, key, keylen, val, vallen, mode == 1 ? DP_DKEEP : DP_DOVER);
+ if (result)
+ return SUCCESS;
+
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "%s", dperrmsg(dpecode));
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(qdbm)
+{
+ QDBM_DATA;
+ char *value;
+
+ value = dpget(dba->dbf, key, keylen, 0, -1, NULL);
+ if (value) {
+ free(value);
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(qdbm)
+{
+ QDBM_DATA;
+
+ return dpout(dba->dbf, key, keylen) ? SUCCESS : FAILURE;
+}
+
+DBA_FIRSTKEY_FUNC(qdbm)
+{
+ QDBM_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ dpiterinit(dba->dbf);
+
+ value = dpiternext(dba->dbf, &value_size);
+ if (value) {
+ if (newlen) *newlen = value_size;
+ new = estrndup(value, value_size);
+ free(value);
+ }
+
+ return new;
+}
+
+DBA_NEXTKEY_FUNC(qdbm)
+{
+ QDBM_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ value = dpiternext(dba->dbf, &value_size);
+ if (value) {
+ if (newlen) *newlen = value_size;
+ new = estrndup(value, value_size);
+ free(value);
+ }
+
+ return new;
+}
+
+DBA_OPTIMIZE_FUNC(qdbm)
+{
+ QDBM_DATA;
+
+ dpoptimize(dba->dbf, 0);
+ return SUCCESS;
+}
+
+DBA_SYNC_FUNC(qdbm)
+{
+ QDBM_DATA;
+
+ dpsync(dba->dbf);
+ return SUCCESS;
+}
+
+DBA_INFO_FUNC(qdbm)
+{
+ return estrdup(dpversion);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/dba_tcadb.c b/ext/dba/dba_tcadb.c
new file mode 100644
index 0000000..082a1ae
--- /dev/null
+++ b/ext/dba/dba_tcadb.c
@@ -0,0 +1,221 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Michael Maclean <mgdm@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if DBA_TCADB
+#include "php_tcadb.h"
+
+#ifdef TCADB_INCLUDE_FILE
+#include TCADB_INCLUDE_FILE
+#endif
+
+#define TCADB_DATA dba_tcadb_data *dba = info->dbf
+
+typedef struct {
+ TCADB *tcadb;
+} dba_tcadb_data;
+
+DBA_OPEN_FUNC(tcadb)
+{
+ char *path_string;
+ TCADB *tcadb = tcadbnew();
+
+ if (tcadb) {
+ switch(info->mode) {
+ case DBA_READER:
+ spprintf(&path_string, 0, "%s#mode=r", info->path);
+ break;
+ case DBA_WRITER:
+ spprintf(&path_string, 0, "%s#mode=w", info->path);
+ break;
+ case DBA_CREAT:
+ spprintf(&path_string, 0, "%s#mode=wc", info->path);
+ break;
+ case DBA_TRUNC:
+ spprintf(&path_string, 0, "%s#mode=wct", info->path);
+ break;
+ default:
+ tcadbdel(tcadb);
+ return FAILURE;
+ }
+
+ if (!tcadbopen(tcadb, path_string)) {
+ efree(path_string);
+ tcadbdel(tcadb);
+ return FAILURE;
+ }
+
+ efree(path_string);
+
+ info->dbf = pemalloc(sizeof(dba_tcadb_data), info->flags & DBA_PERSISTENT);
+ memset(info->dbf, 0, sizeof(dba_tcadb_data));
+ ((dba_tcadb_data *) info->dbf)->tcadb = tcadb;
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
+DBA_CLOSE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ tcadbclose(dba->tcadb);
+ pefree(dba, info->flags & DBA_PERSISTENT);
+}
+
+DBA_FETCH_FUNC(tcadb)
+{
+ TCADB_DATA;
+ char *value, *new = NULL;
+ int value_size;
+
+ value = tcadbget(dba->tcadb, key, keylen, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_UPDATE_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int result;
+
+ if (mode == 1) {
+ /* Insert */
+ if (tcadbvsiz(dba->tcadb, key, keylen) > -1) {
+ return FAILURE;
+ }
+ }
+
+ result = tcadbput(dba->tcadb, key, keylen, val, vallen);
+
+ if (result) {
+ return SUCCESS;
+ }
+
+ php_error_docref2(NULL TSRMLS_CC, key, val, E_WARNING, "Error updating data");
+ return FAILURE;
+}
+
+DBA_EXISTS_FUNC(tcadb)
+{
+ TCADB_DATA;
+ char *value;
+ int value_len;
+
+ value = tcadbget(dba->tcadb, key, keylen, &value_len);
+ if (value) {
+ tcfree(value);
+ return SUCCESS;
+ }
+
+ return FAILURE;
+}
+
+DBA_DELETE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ return tcadbout(dba->tcadb, key, keylen) ? SUCCESS : FAILURE;
+}
+
+DBA_FIRSTKEY_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ tcadbiterinit(dba->tcadb);
+
+ value = tcadbiternext(dba->tcadb, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_NEXTKEY_FUNC(tcadb)
+{
+ TCADB_DATA;
+ int value_size;
+ char *value, *new = NULL;
+
+ value = tcadbiternext(dba->tcadb, &value_size);
+ if (value) {
+ if (newlen) {
+ *newlen = value_size;
+ }
+ new = estrndup(value, value_size);
+ tcfree(value);
+ }
+
+ return new;
+}
+
+DBA_OPTIMIZE_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+#if _TC_LIBVER >= 811
+ return tcadboptimize(dba->tcadb, NULL) ? SUCCESS : FAILURE;
+#else
+ return FAILURE;
+#endif
+}
+
+DBA_SYNC_FUNC(tcadb)
+{
+ TCADB_DATA;
+
+ return tcadbsync(dba->tcadb) ? SUCCESS : FAILURE;
+}
+
+DBA_INFO_FUNC(tcadb)
+{
+ return estrdup(tcversion);
+}
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/install_cdb.sh b/ext/dba/install_cdb.sh
new file mode 100755
index 0000000..ce5f3cc
--- /dev/null
+++ b/ext/dba/install_cdb.sh
@@ -0,0 +1,53 @@
+#! /bin/sh
+
+# You can use this script if you want to use an external cdb lib. If you
+# compile php using --with-cdb the internal functions will be used and no
+# external library is used so that this script is not necessary.
+#
+# cdb-0.75 lacks support for installing header files and creating a
+# library which programs can link against. This shell script fills
+# the gap.
+#
+# $Id: install_cdb.sh,v 1.2 2002-11-04 17:53:04 helly Exp $
+
+if test -r "cdb.a" && test -r "auto-str.c" && test -r "byte.a"; then
+ :
+else
+ echo "Please execute this script in the cdb-0.75 source directory after 'make'"
+ exit 1
+fi
+
+prefix=$1
+
+if test -z "$prefix"; then
+ prefix=/usr/local
+fi
+
+echo "Using prefix $prefix"
+
+if mkdir -p "$prefix/include" "$prefix/lib"; then
+ :
+else
+ echo "Creating directories failed. Please become superuser."
+ exit 1
+fi
+
+mkdir -p tmp || exit 1
+cd tmp
+ar x ../cdb.a
+ar x ../byte.a
+ar x ../unix.a
+ar x ../byte.a
+ar x ../buffer.a
+cp ../error.o .
+
+# not really portable
+ar r "$prefix/lib/libcdb.a" *
+ranlib "$prefix/lib/libcdb.a"
+cd ..
+
+rm -rf tmp
+
+cp cdb.h uint32.h "$prefix/include"
+
+echo "done"
diff --git a/ext/dba/libcdb/cdb.c b/ext/dba/libcdb/cdb.c
new file mode 100644
index 0000000..2b101f8
--- /dev/null
+++ b/ext/dba/libcdb/cdb.c
@@ -0,0 +1,194 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id: bc4ee08831fe552aab0f3fdce506f7b734dde461 $ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef PHP_WIN32
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include "cdb.h"
+
+#ifndef EPROTO
+# define EPROTO -15 /* cdb 0.75's default for PROTOless systems */
+#endif
+
+/* {{{ cdb_match */
+static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos TSRMLS_DC)
+{
+ char buf[32];
+ unsigned int n;
+
+ while (len > 0) {
+ n = sizeof(buf);
+ if (n > len)
+ n = len;
+ if (cdb_read(c, buf, n, pos TSRMLS_CC) == -1)
+ return -1;
+ if (memcmp(buf, key, n))
+ return 0;
+ pos += n;
+ key += n;
+ len -= n;
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ cdb_hash */
+uint32 cdb_hash(char *buf, unsigned int len)
+{
+ uint32 h;
+ const unsigned char * b = (unsigned char *)buf;
+
+ h = CDB_HASHSTART;
+ while (len--) {
+ h = ( h + (h << 5)) ^ (*b++);
+ }
+ return h;
+}
+/* }}} */
+
+/* {{{ cdb_free */
+void cdb_free(struct cdb *c TSRMLS_DC)
+{
+}
+/* }}} */
+
+/* {{{ cdb_findstart */
+void cdb_findstart(struct cdb *c TSRMLS_DC)
+{
+ c->loop = 0;
+}
+/* }}} */
+
+/* {{{ cdb_init */
+void cdb_init(struct cdb *c, php_stream *fp TSRMLS_DC)
+{
+ cdb_free(c TSRMLS_CC);
+ cdb_findstart(c TSRMLS_CC);
+ c->fp = fp;
+}
+/* }}} */
+
+/* {{{ cdb_read */
+int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos TSRMLS_DC)
+{
+ if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) {
+ errno = EPROTO;
+ return -1;
+ }
+ while (len > 0) {
+ int r;
+ do {
+ r = php_stream_read(c->fp, buf, len);
+ } while ((r == -1) && (errno == EINTR));
+ if (r == -1)
+ return -1;
+ if (r == 0) {
+ errno = EPROTO;
+ return -1;
+ }
+ buf += r;
+ len -= r;
+ }
+ return 0;
+}
+/* }}} */
+
+/* {{{ cdb_findnext */
+int cdb_findnext(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
+{
+ char buf[8];
+ uint32 pos;
+ uint32 u;
+
+ if (!c->loop) {
+ u = cdb_hash(key, len);
+ if (cdb_read(c, buf, 8, (u << 3) & 2047 TSRMLS_CC) == -1)
+ return -1;
+ uint32_unpack(buf + 4,&c->hslots);
+ if (!c->hslots)
+ return 0;
+ uint32_unpack(buf, &c->hpos);
+ c->khash = u;
+ u >>= 8;
+ u %= c->hslots;
+ u <<= 3;
+ c->kpos = c->hpos + u;
+ }
+
+ while (c->loop < c->hslots) {
+ if (cdb_read(c, buf, 8, c->kpos TSRMLS_CC) == -1)
+ return -1;
+ uint32_unpack(buf + 4, &pos);
+ if (!pos)
+ return 0;
+ c->loop += 1;
+ c->kpos += 8;
+ if (c->kpos == c->hpos + (c->hslots << 3))
+ c->kpos = c->hpos;
+ uint32_unpack(buf, &u);
+ if (u == c->khash) {
+ if (cdb_read(c, buf, 8, pos TSRMLS_CC) == -1)
+ return -1;
+ uint32_unpack(buf, &u);
+ if (u == len)
+ switch(cdb_match(c, key, len, pos + 8 TSRMLS_CC)) {
+ case -1:
+ return -1;
+ case 1:
+ uint32_unpack(buf + 4, &c->dlen);
+ c->dpos = pos + 8 + len;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+/* }}} */
+
+/* {{{ cdb_find */
+int cdb_find(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
+{
+ cdb_findstart(c TSRMLS_CC);
+ return cdb_findnext(c, key, len TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ cdb_version */
+char *cdb_version()
+{
+ return "0.75, $Id: bc4ee08831fe552aab0f3fdce506f7b734dde461 $";
+}
+/* }}} */
diff --git a/ext/dba/libcdb/cdb.h b/ext/dba/libcdb/cdb.h
new file mode 100644
index 0000000..5be8ec4
--- /dev/null
+++ b/ext/dba/libcdb/cdb.h
@@ -0,0 +1,57 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifndef CDB_H
+#define CDB_H
+
+#include "uint32.h"
+
+#define CDB_HASHSTART 5381
+
+struct cdb {
+ php_stream *fp;
+ uint32 loop; /* number of hash slots searched under this key */
+ uint32 khash; /* initialized if loop is nonzero */
+ uint32 kpos; /* initialized if loop is nonzero */
+ uint32 hpos; /* initialized if loop is nonzero */
+ uint32 hslots; /* initialized if loop is nonzero */
+ uint32 dpos; /* initialized if cdb_findnext() returns 1 */
+ uint32 dlen; /* initialized if cdb_findnext() returns 1 */
+};
+
+uint32 cdb_hash(char *, unsigned int);
+
+void cdb_free(struct cdb * TSRMLS_DC);
+void cdb_init(struct cdb *, php_stream *fp TSRMLS_DC);
+
+int cdb_read(struct cdb *, char *, unsigned int, uint32 TSRMLS_DC);
+
+void cdb_findstart(struct cdb * TSRMLS_DC);
+int cdb_findnext(struct cdb *, char *, unsigned int TSRMLS_DC);
+int cdb_find(struct cdb *, char *, unsigned int TSRMLS_DC);
+
+#define cdb_datapos(c) ((c)->dpos)
+#define cdb_datalen(c) ((c)->dlen)
+
+char *cdb_version();
+
+#endif
diff --git a/ext/dba/libcdb/cdb_make.c b/ext/dba/libcdb/cdb_make.c
new file mode 100644
index 0000000..606b56e
--- /dev/null
+++ b/ext/dba/libcdb/cdb_make.c
@@ -0,0 +1,244 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id: 154118c15260d2e1f134cf7534ff244ba31b4353 $ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include "cdb.h"
+#include "cdb_make.h"
+#include "uint32.h"
+
+/* {{{ cdb_make_write */
+static int cdb_make_write(struct cdb_make *c, char *buf, uint32 sz TSRMLS_DC) {
+ return php_stream_write(c->fp, buf, sz) == sz ? 0 : -1;
+}
+
+/* {{{ cdb_posplus */
+static int cdb_posplus(struct cdb_make *c, uint32 len)
+{
+ uint32 newpos = c->pos + len;
+ if (newpos < len) {
+ errno = ENOMEM;
+ return -1;
+ }
+ c->pos = newpos;
+ return 0;
+}
+/* }}} */
+
+/* {{{ cdb_make_start */
+int cdb_make_start(struct cdb_make *c, php_stream * f TSRMLS_DC)
+{
+ c->head = 0;
+ c->split = 0;
+ c->hash = 0;
+ c->numentries = 0;
+ c->fp = f;
+ c->pos = sizeof(c->final);
+ if (php_stream_seek(f, c->pos, SEEK_SET) == -1) {
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Fseek failed");
+ return -1;
+ }
+ return php_stream_tell(c->fp);
+}
+/* }}} */
+
+/* {{{ cdb_make_addend */
+int cdb_make_addend(struct cdb_make *c, unsigned int keylen, unsigned int datalen, uint32 h TSRMLS_DC)
+{
+ struct cdb_hplist *head;
+
+ head = c->head;
+ if (!head || (head->num >= CDB_HPLIST)) {
+ head = (struct cdb_hplist *) emalloc(sizeof(struct cdb_hplist));
+ if (!head)
+ return -1;
+ head->num = 0;
+ head->next = c->head;
+ c->head = head;
+ }
+ head->hp[head->num].h = h;
+ head->hp[head->num].p = c->pos;
+ ++head->num;
+ ++c->numentries;
+ if (cdb_posplus(c,8) == -1)
+ return -1;
+ if (cdb_posplus(c, keylen) == -1)
+ return -1;
+ if (cdb_posplus(c, datalen) == -1)
+ return -1;
+ return 0;
+}
+/* }}} */
+
+/* {{{ cdb_make_addbegin */
+int cdb_make_addbegin(struct cdb_make *c, unsigned int keylen, unsigned int datalen TSRMLS_DC)
+{
+ char buf[8];
+
+ if (keylen > 0xffffffff) {
+ errno = ENOMEM;
+ return -1;
+ }
+ if (datalen > 0xffffffff) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ uint32_pack(buf, keylen);
+ uint32_pack(buf + 4, datalen);
+ if (cdb_make_write(c, buf, 8 TSRMLS_CC) != 0)
+ return -1;
+ return 0;
+}
+
+/* {{{ cdb_make_add */
+int cdb_make_add(struct cdb_make *c,char *key,unsigned int keylen,char *data,unsigned int datalen TSRMLS_DC)
+{
+ if (cdb_make_addbegin(c, keylen, datalen TSRMLS_CC) == -1)
+ return -1;
+ if (cdb_make_write(c, key, keylen TSRMLS_CC) != 0)
+ return -1;
+ if (cdb_make_write(c, data, datalen TSRMLS_CC) != 0)
+ return -1;
+ return cdb_make_addend(c, keylen, datalen, cdb_hash(key, keylen) TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ cdb_make_finish */
+int cdb_make_finish(struct cdb_make *c TSRMLS_DC)
+{
+ char buf[8];
+ int i;
+ uint32 len;
+ uint32 u;
+ uint32 memsize;
+ uint32 count;
+ uint32 where;
+ struct cdb_hplist *x;
+ struct cdb_hp *hp;
+
+ for (i = 0;i < 256;++i)
+ c->count[i] = 0;
+
+ for (x = c->head; x; x = x->next) {
+ i = x->num;
+ while (i--)
+ ++c->count[255 & x->hp[i].h];
+ }
+
+ memsize = 1;
+ for (i = 0;i < 256;++i) {
+ u = c->count[i] * 2;
+ if (u > memsize)
+ memsize = u;
+ }
+
+ memsize += c->numentries; /* no overflow possible up to now */
+ u = (uint32) 0 - (uint32) 1;
+ u /= sizeof(struct cdb_hp);
+ if (memsize > u) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ c->split = (struct cdb_hp *) safe_emalloc(memsize, sizeof(struct cdb_hp), 0);
+ if (!c->split)
+ return -1;
+
+ c->hash = c->split + c->numentries;
+
+ u = 0;
+ for (i = 0;i < 256;++i) {
+ u += c->count[i]; /* bounded by numentries, so no overflow */
+ c->start[i] = u;
+ }
+
+ for (x = c->head; x; x = x->next) {
+ i = x->num;
+ while (i--)
+ c->split[--c->start[255 & x->hp[i].h]] = x->hp[i];
+ }
+
+ for (i = 0;i < 256;++i) {
+ count = c->count[i];
+
+ len = count + count; /* no overflow possible */
+ uint32_pack(c->final + 8 * i,c->pos);
+ uint32_pack(c->final + 8 * i + 4,len);
+
+ for (u = 0;u < len;++u)
+ c->hash[u].h = c->hash[u].p = 0;
+
+ hp = c->split + c->start[i];
+ for (u = 0;u < count;++u) {
+ where = (hp->h >> 8) % len;
+ while (c->hash[where].p)
+ if (++where == len)
+ where = 0;
+ c->hash[where] = *hp++;
+ }
+
+ for (u = 0;u < len;++u) {
+ uint32_pack(buf, c->hash[u].h);
+ uint32_pack(buf + 4, c->hash[u].p);
+ if (cdb_make_write(c, buf, 8 TSRMLS_CC) != 0)
+ return -1;
+ if (cdb_posplus(c, 8) == -1)
+ return -1;
+ }
+ }
+
+ if (c->split)
+ efree(c->split);
+
+ for (x = c->head; x; c->head = x) {
+ x = x->next;
+ efree(c->head);
+ }
+
+ if (php_stream_flush(c->fp) != 0)
+ return -1;
+ php_stream_rewind(c->fp);
+ if (php_stream_tell(c->fp) != 0)
+ return -1;
+ if (cdb_make_write(c, c->final, sizeof(c->final) TSRMLS_CC) != 0)
+ return -1;
+ return php_stream_flush(c->fp);
+}
+/* }}} */
+
+/* {{{ cdb_make_version */
+char *cdb_make_version()
+{
+ return "0.75, $Id: 154118c15260d2e1f134cf7534ff244ba31b4353 $";
+}
diff --git a/ext/dba/libcdb/cdb_make.h b/ext/dba/libcdb/cdb_make.h
new file mode 100644
index 0000000..5bb0ddf
--- /dev/null
+++ b/ext/dba/libcdb/cdb_make.h
@@ -0,0 +1,64 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifndef CDB_MAKE_H
+#define CDB_MAKE_H
+
+#include <stdio.h>
+#include "uint32.h"
+
+#define CDB_HPLIST 1000
+
+struct cdb_hp {
+ uint32 h;
+ uint32 p;
+};
+
+struct cdb_hplist {
+ struct cdb_hp hp[CDB_HPLIST];
+ struct cdb_hplist *next;
+ int num;
+} ;
+
+struct cdb_make {
+ /* char bspace[8192]; */
+ char final[2048];
+ uint32 count[256];
+ uint32 start[256];
+ struct cdb_hplist *head;
+ struct cdb_hp *split; /* includes space for hash */
+ struct cdb_hp *hash;
+ uint32 numentries;
+ /* buffer b; */
+ uint32 pos;
+ /* int fd; */
+ php_stream * fp;
+};
+
+int cdb_make_start(struct cdb_make *, php_stream * TSRMLS_DC);
+int cdb_make_addbegin(struct cdb_make *, unsigned int, unsigned int TSRMLS_DC);
+int cdb_make_addend(struct cdb_make *, unsigned int, unsigned int, uint32 TSRMLS_DC);
+int cdb_make_add(struct cdb_make *, char *, unsigned int, char *, unsigned int TSRMLS_DC);
+int cdb_make_finish(struct cdb_make * TSRMLS_DC);
+char *cdb_make_version();
+
+#endif
diff --git a/ext/dba/libcdb/uint32.c b/ext/dba/libcdb/uint32.c
new file mode 100644
index 0000000..803a3d5
--- /dev/null
+++ b/ext/dba/libcdb/uint32.c
@@ -0,0 +1,49 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#include "uint32.h"
+
+/* {{{ uint32_pack */
+void uint32_pack(char *out, uint32 in)
+{
+ out[0] = in&0xff; in>>=8;
+ out[1] = in&0xff; in>>=8;
+ out[2] = in&0xff; in>>=8;
+ out[3] = in&0xff;
+}
+/* }}} */
+
+/* {{{ uint32_unpack */
+void uint32_unpack(const char *in, uint32 *out)
+{
+ *out = (((uint32)(unsigned char)in[3])<<24) |
+ (((uint32)(unsigned char)in[2])<<16) |
+ (((uint32)(unsigned char)in[1])<<8) |
+ (((uint32)(unsigned char)in[0]));
+}
+/* }}} */
diff --git a/ext/dba/libcdb/uint32.h b/ext/dba/libcdb/uint32.h
new file mode 100644
index 0000000..ac44f05
--- /dev/null
+++ b/ext/dba/libcdb/uint32.h
@@ -0,0 +1,39 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+/* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
+
+#ifndef UINT32_H
+#define UINT32_H
+
+#if SIZEOF_INT == 4
+/* Most 32-bit and 64-bit systems have 32-bit ints */
+typedef unsigned int uint32;
+#elif SIZEOF_LONG == 4
+/* 16-bit systems? */
+typedef unsigned long uint32;
+#else
+#error Need type which holds 32 bits
+#endif
+
+void uint32_pack(char *out, uint32 in);
+void uint32_unpack(const char *in, uint32 *out);
+
+#endif
diff --git a/ext/dba/libflatfile/flatfile.c b/ext/dba/libflatfile/flatfile.c
new file mode 100644
index 0000000..194f016
--- /dev/null
+++ b/ext/dba/libflatfile/flatfile.c
@@ -0,0 +1,320 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Marcus Boerger <helly@php.net> |
+ | based on ext/db/db.c by: |
+ | Rasmus Lerdorf <rasmus@php.net> |
+ | Jim Winstead <jimw@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id: 6ce2f616c81b8404a2b4143c0be5cadeaa0d4742 $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "flatfile.h"
+
+#define FLATFILE_BLOCK_SIZE 1024
+
+/*
+ * ret = -1 means that database was opened for read-only
+ * ret = 0 success
+ * ret = 1 key already exists - nothing done
+ */
+
+/* {{{ flatfile_store
+ */
+int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode TSRMLS_DC) {
+ if (mode == FLATFILE_INSERT) {
+ if (flatfile_findkey(dba, key_datum TSRMLS_CC)) {
+ return 1;
+ }
+ php_stream_seek(dba->fp, 0L, SEEK_END);
+ php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
+ php_stream_flush(dba->fp);
+ if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
+ return -1;
+ }
+ php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
+ php_stream_flush(dba->fp);
+ if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
+ return -1;
+ }
+ } else { /* FLATFILE_REPLACE */
+ flatfile_delete(dba, key_datum TSRMLS_CC);
+ php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", key_datum.dsize);
+ php_stream_flush(dba->fp);
+ if (php_stream_write(dba->fp, key_datum.dptr, key_datum.dsize) < key_datum.dsize) {
+ return -1;
+ }
+ php_stream_printf(dba->fp TSRMLS_CC, "%zu\n", value_datum.dsize);
+ if (php_stream_write(dba->fp, value_datum.dptr, value_datum.dsize) < value_datum.dsize) {
+ return -1;
+ }
+ }
+
+ php_stream_flush(dba->fp);
+ return 0;
+}
+/* }}} */
+
+/* {{{ flatfile_fetch
+ */
+datum flatfile_fetch(flatfile *dba, datum key_datum TSRMLS_DC) {
+ datum value_datum = {NULL, 0};
+ char buf[16];
+
+ if (flatfile_findkey(dba, key_datum TSRMLS_CC)) {
+ if (php_stream_gets(dba->fp, buf, sizeof(buf))) {
+ value_datum.dsize = atoi(buf);
+ value_datum.dptr = safe_emalloc(value_datum.dsize, 1, 1);
+ value_datum.dsize = php_stream_read(dba->fp, value_datum.dptr, value_datum.dsize);
+ } else {
+ value_datum.dptr = NULL;
+ value_datum.dsize = 0;
+ }
+ }
+ return value_datum;
+}
+/* }}} */
+
+/* {{{ flatfile_delete
+ */
+int flatfile_delete(flatfile *dba, datum key_datum TSRMLS_DC) {
+ char *key = key_datum.dptr;
+ size_t size = key_datum.dsize;
+ size_t buf_size = FLATFILE_BLOCK_SIZE;
+ char *buf = emalloc(buf_size);
+ size_t num;
+ size_t pos;
+
+ php_stream_rewind(dba->fp);
+ while(!php_stream_eof(dba->fp)) {
+ /* read in the length of the key name */
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ pos = php_stream_tell(dba->fp);
+
+ /* read in the key name */
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+
+ if (size == num && !memcmp(buf, key, size)) {
+ php_stream_seek(dba->fp, pos, SEEK_SET);
+ php_stream_putc(dba->fp, 0);
+ php_stream_flush(dba->fp);
+ php_stream_seek(dba->fp, 0L, SEEK_END);
+ efree(buf);
+ return SUCCESS;
+ }
+
+ /* read in the length of the value */
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ /* read in the value */
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ }
+ efree(buf);
+ return FAILURE;
+}
+/* }}} */
+
+/* {{{ flatfile_findkey
+ */
+int flatfile_findkey(flatfile *dba, datum key_datum TSRMLS_DC) {
+ size_t buf_size = FLATFILE_BLOCK_SIZE;
+ char *buf = emalloc(buf_size);
+ size_t num;
+ int ret=0;
+ void *key = key_datum.dptr;
+ size_t size = key_datum.dsize;
+
+ php_stream_rewind(dba->fp);
+ while (!php_stream_eof(dba->fp)) {
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ if (size == num) {
+ if (!memcmp(buf, key, size)) {
+ ret = 1;
+ break;
+ }
+ }
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ }
+ efree(buf);
+ return ret;
+}
+/* }}} */
+
+/* {{{ flatfile_firstkey
+ */
+datum flatfile_firstkey(flatfile *dba TSRMLS_DC) {
+ datum res;
+ size_t num;
+ size_t buf_size = FLATFILE_BLOCK_SIZE;
+ char *buf = emalloc(buf_size);
+
+ php_stream_rewind(dba->fp);
+ while(!php_stream_eof(dba->fp)) {
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ if (*(buf) != 0) {
+ dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
+ res.dptr = buf;
+ res.dsize = num;
+ return res;
+ }
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ }
+ efree(buf);
+ res.dptr = NULL;
+ res.dsize = 0;
+ return res;
+}
+/* }}} */
+
+/* {{{ flatfile_nextkey
+ */
+datum flatfile_nextkey(flatfile *dba TSRMLS_DC) {
+ datum res;
+ size_t num;
+ size_t buf_size = FLATFILE_BLOCK_SIZE;
+ char *buf = emalloc(buf_size);
+
+ php_stream_seek(dba->fp, dba->CurrentFlatFilePos, SEEK_SET);
+ while(!php_stream_eof(dba->fp)) {
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ if (!php_stream_gets(dba->fp, buf, 15)) {
+ break;
+ }
+ num = atoi(buf);
+ if (num >= buf_size) {
+ buf_size = num + FLATFILE_BLOCK_SIZE;
+ buf = erealloc(buf, buf_size);
+ }
+ num = php_stream_read(dba->fp, buf, num);
+ if (num < 0) {
+ break;
+ }
+ if (*(buf)!=0) {
+ dba->CurrentFlatFilePos = php_stream_tell(dba->fp);
+ res.dptr = buf;
+ res.dsize = num;
+ return res;
+ }
+ }
+ efree(buf);
+ res.dptr = NULL;
+ res.dsize = 0;
+ return res;
+}
+/* }}} */
+
+/* {{{ flatfile_version */
+char *flatfile_version()
+{
+ return "1.0, $Id: 6ce2f616c81b8404a2b4143c0be5cadeaa0d4742 $";
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/libflatfile/flatfile.h b/ext/dba/libflatfile/flatfile.h
new file mode 100644
index 0000000..b8fbedd
--- /dev/null
+++ b/ext/dba/libflatfile/flatfile.h
@@ -0,0 +1,48 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_LIB_FLATFILE_H
+#define PHP_LIB_FLATFILE_H
+
+typedef struct {
+ char *dptr;
+ size_t dsize;
+} datum;
+
+typedef struct {
+ char *lockfn;
+ int lockfd;
+ php_stream *fp;
+ size_t CurrentFlatFilePos;
+ datum nextkey;
+} flatfile;
+
+#define FLATFILE_INSERT 1
+#define FLATFILE_REPLACE 0
+
+int flatfile_store(flatfile *dba, datum key_datum, datum value_datum, int mode TSRMLS_DC);
+datum flatfile_fetch(flatfile *dba, datum key_datum TSRMLS_DC);
+int flatfile_delete(flatfile *dba, datum key_datum TSRMLS_DC);
+int flatfile_findkey(flatfile *dba, datum key_datum TSRMLS_DC);
+datum flatfile_firstkey(flatfile *dba TSRMLS_DC);
+datum flatfile_nextkey(flatfile *dba TSRMLS_DC);
+char *flatfile_version();
+
+#endif
diff --git a/ext/dba/libinifile/inifile.c b/ext/dba/libinifile/inifile.c
new file mode 100644
index 0000000..0db90b5
--- /dev/null
+++ b/ext/dba/libinifile/inifile.c
@@ -0,0 +1,593 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id: 89373b1e33a6204bf8d50f955dc09d37ecf29ea2 $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_globals.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "inifile.h"
+
+/* ret = -1 means that database was opened for read-only
+ * ret = 0 success
+ * ret = 1 key already exists - nothing done
+ */
+
+/* {{{ inifile_version */
+char *inifile_version()
+{
+ return "1.0, $Id: 89373b1e33a6204bf8d50f955dc09d37ecf29ea2 $";
+}
+/* }}} */
+
+/* {{{ inifile_free_key */
+void inifile_key_free(key_type *key)
+{
+ if (key->group) {
+ efree(key->group);
+ }
+ if (key->name) {
+ efree(key->name);
+ }
+ memset(key, 0, sizeof(key_type));
+}
+/* }}} */
+
+/* {{{ inifile_free_val */
+void inifile_val_free(val_type *val)
+{
+ if (val->value) {
+ efree(val->value);
+ }
+ memset(val, 0, sizeof(val_type));
+}
+/* }}} */
+
+/* {{{ inifile_free_val */
+void inifile_line_free(line_type *ln)
+{
+ inifile_key_free(&ln->key);
+ inifile_val_free(&ln->val);
+ ln->pos = 0;
+}
+/* }}} */
+
+/* {{{ inifile_alloc */
+inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC)
+{
+ inifile *dba;
+
+ if (!readonly) {
+ if (!php_stream_truncate_supported(fp)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't truncate this stream");
+ return NULL;
+ }
+ }
+
+ dba = pemalloc(sizeof(inifile), persistent);
+ memset(dba, 0, sizeof(inifile));
+ dba->fp = fp;
+ dba->readonly = readonly;
+ return dba;
+}
+/* }}} */
+
+/* {{{ inifile_free */
+void inifile_free(inifile *dba, int persistent)
+{
+ if (dba) {
+ inifile_line_free(&dba->curr);
+ inifile_line_free(&dba->next);
+ pefree(dba, persistent);
+ }
+}
+/* }}} */
+
+/* {{{ inifile_key_split */
+key_type inifile_key_split(const char *group_name)
+{
+ key_type key;
+ char *name;
+
+ if (group_name[0] == '[' && (name = strchr(group_name, ']')) != NULL) {
+ key.group = estrndup(group_name+1, name - (group_name + 1));
+ key.name = estrdup(name+1);
+ } else {
+ key.group = estrdup("");
+ key.name = estrdup(group_name);
+ }
+ return key;
+}
+/* }}} */
+
+/* {{{ inifile_key_string */
+char * inifile_key_string(const key_type *key)
+{
+ if (key->group && *key->group) {
+ char *result;
+ spprintf(&result, 0, "[%s]%s", key->group, key->name ? key->name : "");
+ return result;
+ } else if (key->name) {
+ return estrdup(key->name);
+ } else {
+ return NULL;
+ }
+}
+/* }}} */
+
+/* {{{ etrim */
+static char *etrim(const char *str)
+{
+ char *val;
+ size_t l;
+
+ if (!str) {
+ return NULL;
+ }
+ val = (char*)str;
+ while (*val && strchr(" \t\r\n", *val)) {
+ val++;
+ }
+ l = strlen(val);
+ while (l && (strchr(" \t\r\n", val[l-1]))) {
+ l--;
+ }
+ return estrndup(val, l);
+}
+/* }}} */
+
+/* {{{ inifile_findkey
+ */
+static int inifile_read(inifile *dba, line_type *ln TSRMLS_DC) {
+ char *fline;
+ char *pos;
+
+ inifile_val_free(&ln->val);
+ while ((fline = php_stream_gets(dba->fp, NULL, 0)) != NULL) {
+ if (fline) {
+ if (fline[0] == '[') {
+ /* A value name cannot start with '['
+ * So either we find a ']' or we found an error
+ */
+ pos = strchr(fline+1, ']');
+ if (pos) {
+ *pos = '\0';
+ inifile_key_free(&ln->key);
+ ln->key.group = etrim(fline+1);
+ ln->key.name = estrdup("");
+ ln->pos = php_stream_tell(dba->fp);
+ efree(fline);
+ return 1;
+ } else {
+ efree(fline);
+ continue;
+ }
+ } else {
+ pos = strchr(fline, '=');
+ if (pos) {
+ *pos = '\0';
+ /* keep group or make empty if not existent */
+ if (!ln->key.group) {
+ ln->key.group = estrdup("");
+ }
+ if (ln->key.name) {
+ efree(ln->key.name);
+ }
+ ln->key.name = etrim(fline);
+ ln->val.value = etrim(pos+1);
+ ln->pos = php_stream_tell(dba->fp);
+ efree(fline);
+ return 1;
+ } else {
+ /* simply ignore lines without '='
+ * those should be comments
+ */
+ efree(fline);
+ continue;
+ }
+ }
+ }
+ }
+ inifile_line_free(ln);
+ return 0;
+}
+/* }}} */
+
+/* {{{ inifile_key_cmp */
+/* 0 = EQUAL
+ * 1 = GROUP-EQUAL,NAME-DIFFERENT
+ * 2 = DIFFERENT
+ */
+static int inifile_key_cmp(const key_type *k1, const key_type *k2 TSRMLS_DC)
+{
+ assert(k1->group && k1->name && k2->group && k2->name);
+
+ if (!strcasecmp(k1->group, k2->group)) {
+ if (!strcasecmp(k1->name, k2->name)) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ return 2;
+ }
+}
+/* }}} */
+
+/* {{{ inifile_fetch
+ */
+val_type inifile_fetch(inifile *dba, const key_type *key, int skip TSRMLS_DC) {
+ line_type ln = {{NULL,NULL},{NULL}};
+ val_type val;
+ int res, grp_eq = 0;
+
+ if (skip == -1 && dba->next.key.group && dba->next.key.name && !inifile_key_cmp(&dba->next.key, key TSRMLS_CC)) {
+ /* we got position already from last fetch */
+ php_stream_seek(dba->fp, dba->next.pos, SEEK_SET);
+ } else {
+ /* specific instance or not same key -> restart search */
+ /* the slow way: restart and seacrch */
+ php_stream_rewind(dba->fp);
+ inifile_line_free(&dba->next);
+ }
+ if (skip == -1) {
+ skip = 0;
+ }
+ while(inifile_read(dba, &ln TSRMLS_CC)) {
+ if (!(res=inifile_key_cmp(&ln.key, key TSRMLS_CC))) {
+ if (!skip) {
+ val.value = estrdup(ln.val.value ? ln.val.value : "");
+ /* allow faster access by updating key read into next */
+ inifile_line_free(&dba->next);
+ dba->next = ln;
+ dba->next.pos = php_stream_tell(dba->fp);
+ return val;
+ }
+ skip--;
+ } else if (res == 1) {
+ grp_eq = 1;
+ } else if (grp_eq) {
+ /* we are leaving group now: that means we cannot find the key */
+ break;
+ }
+ }
+ inifile_line_free(&ln);
+ dba->next.pos = php_stream_tell(dba->fp);
+ return ln.val;
+}
+/* }}} */
+
+/* {{{ inifile_firstkey
+ */
+int inifile_firstkey(inifile *dba TSRMLS_DC) {
+ inifile_line_free(&dba->curr);
+ dba->curr.pos = 0;
+ return inifile_nextkey(dba TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ inifile_nextkey
+ */
+int inifile_nextkey(inifile *dba TSRMLS_DC) {
+ line_type ln = {{NULL,NULL},{NULL}};
+
+ /*inifile_line_free(&dba->next); ??? */
+ php_stream_seek(dba->fp, dba->curr.pos, SEEK_SET);
+ ln.key.group = estrdup(dba->curr.key.group ? dba->curr.key.group : "");
+ inifile_read(dba, &ln TSRMLS_CC);
+ inifile_line_free(&dba->curr);
+ dba->curr = ln;
+ return ln.key.group || ln.key.name;
+}
+/* }}} */
+
+/* {{{ inifile_truncate
+ */
+static int inifile_truncate(inifile *dba, size_t size TSRMLS_DC)
+{
+ int res;
+
+ if ((res=php_stream_truncate_set_size(dba->fp, size)) != 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error in ftruncate: %d", res);
+ return FAILURE;
+ }
+ php_stream_seek(dba->fp, size, SEEK_SET);
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ inifile_find_group
+ * if found pos_grp_start points to "[group_name]"
+ */
+static int inifile_find_group(inifile *dba, const key_type *key, size_t *pos_grp_start TSRMLS_DC)
+{
+ int ret = FAILURE;
+
+ php_stream_flush(dba->fp);
+ php_stream_seek(dba->fp, 0, SEEK_SET);
+ inifile_line_free(&dba->curr);
+ inifile_line_free(&dba->next);
+
+ if (key->group && strlen(key->group)) {
+ int res;
+ line_type ln = {{NULL,NULL},{NULL}};
+
+ res = 1;
+ while(inifile_read(dba, &ln TSRMLS_CC)) {
+ if ((res=inifile_key_cmp(&ln.key, key TSRMLS_CC)) < 2) {
+ ret = SUCCESS;
+ break;
+ }
+ *pos_grp_start = php_stream_tell(dba->fp);
+ }
+ inifile_line_free(&ln);
+ } else {
+ *pos_grp_start = 0;
+ ret = SUCCESS;
+ }
+ if (ret == FAILURE) {
+ *pos_grp_start = php_stream_tell(dba->fp);
+ }
+ return ret;
+}
+/* }}} */
+
+/* {{{ inifile_next_group
+ * only valid after a call to inifile_find_group
+ * if any next group is found pos_grp_start points to "[group_name]" or whitespace before that
+ */
+static int inifile_next_group(inifile *dba, const key_type *key, size_t *pos_grp_start TSRMLS_DC)
+{
+ int ret = FAILURE;
+ line_type ln = {{NULL,NULL},{NULL}};
+
+ *pos_grp_start = php_stream_tell(dba->fp);
+ ln.key.group = estrdup(key->group);
+ while(inifile_read(dba, &ln TSRMLS_CC)) {
+ if (inifile_key_cmp(&ln.key, key TSRMLS_CC) == 2) {
+ ret = SUCCESS;
+ break;
+ }
+ *pos_grp_start = php_stream_tell(dba->fp);
+ }
+ inifile_line_free(&ln);
+ return ret;
+}
+/* }}} */
+
+/* {{{ inifile_copy_to
+ */
+static int inifile_copy_to(inifile *dba, size_t pos_start, size_t pos_end, inifile **ini_copy TSRMLS_DC)
+{
+ php_stream *fp;
+
+ if (pos_start == pos_end) {
+ *ini_copy = NULL;
+ return SUCCESS;
+ }
+ if ((fp = php_stream_temp_create(0, 64 * 1024)) == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create temporary stream");
+ *ini_copy = NULL;
+ return FAILURE;
+ }
+
+ if ((*ini_copy = inifile_alloc(fp, 1, 0 TSRMLS_CC)) == NULL) {
+ /* writes error */
+ return FAILURE;
+ }
+ php_stream_seek(dba->fp, pos_start, SEEK_SET);
+ if (!php_stream_copy_to_stream(dba->fp, fp, pos_end - pos_start)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy group [%zu - %zu] to temporary stream", pos_start, pos_end);
+ return FAILURE;
+ }
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ inifile_filter
+ * copy from to dba while ignoring key name (group must equal)
+ */
+static int inifile_filter(inifile *dba, inifile *from, const key_type *key TSRMLS_DC)
+{
+ size_t pos_start = 0, pos_next = 0, pos_curr;
+ int ret = SUCCESS;
+ line_type ln = {{NULL,NULL},{NULL}};
+
+ php_stream_seek(from->fp, 0, SEEK_SET);
+ php_stream_seek(dba->fp, 0, SEEK_END);
+ while(inifile_read(from, &ln TSRMLS_CC)) {
+ switch(inifile_key_cmp(&ln.key, key TSRMLS_CC)) {
+ case 0:
+ pos_curr = php_stream_tell(from->fp);
+ if (pos_start != pos_next) {
+ php_stream_seek(from->fp, pos_start, SEEK_SET);
+ if (!php_stream_copy_to_stream(from->fp, dba->fp, pos_next - pos_start)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy [%zu - %zu] from temporary stream", pos_next, pos_start);
+ ret = FAILURE;
+ }
+ php_stream_seek(from->fp, pos_curr, SEEK_SET);
+ }
+ pos_next = pos_start = pos_curr;
+ break;
+ case 1:
+ pos_next = php_stream_tell(from->fp);
+ break;
+ case 2:
+ /* the function is meant to process only entries from same group */
+ assert(0);
+ break;
+ }
+ }
+ if (pos_start != pos_next) {
+ php_stream_seek(from->fp, pos_start, SEEK_SET);
+ if (!php_stream_copy_to_stream(from->fp, dba->fp, pos_next - pos_start)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy [%zu - %zu] from temporary stream", pos_next, pos_start);
+ ret = FAILURE;
+ }
+ }
+ inifile_line_free(&ln);
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ inifile_delete_replace_append
+ */
+static int inifile_delete_replace_append(inifile *dba, const key_type *key, const val_type *value, int append TSRMLS_DC)
+{
+ size_t pos_grp_start, pos_grp_next;
+ inifile *ini_tmp = NULL;
+ php_stream *fp_tmp = NULL;
+ int ret;
+
+ /* 1) Search group start
+ * 2) Search next group
+ * 3) If not append: Copy group to ini_tmp
+ * 4) Open temp_stream and copy remainder
+ * 5) Truncate stream
+ * 6) If not append AND key.name given: Filtered copy back from ini_tmp
+ * to stream. Otherwise the user wanted to delete the group.
+ * 7) Append value if given
+ * 8) Append temporary stream
+ */
+
+ assert(!append || (key->name && value)); /* missuse */
+
+ /* 1 - 3 */
+ inifile_find_group(dba, key, &pos_grp_start TSRMLS_CC);
+ inifile_next_group(dba, key, &pos_grp_next TSRMLS_CC);
+ if (append) {
+ ret = SUCCESS;
+ } else {
+ ret = inifile_copy_to(dba, pos_grp_start, pos_grp_next, &ini_tmp TSRMLS_CC);
+ }
+
+ /* 4 */
+ if (ret == SUCCESS) {
+ fp_tmp = php_stream_temp_create(0, 64 * 1024);
+ if (!fp_tmp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create temporary stream");
+ ret = FAILURE;
+ } else {
+ php_stream_seek(dba->fp, 0, SEEK_END);
+ if (pos_grp_next != (size_t)php_stream_tell(dba->fp)) {
+ php_stream_seek(dba->fp, pos_grp_next, SEEK_SET);
+ if (!php_stream_copy_to_stream(dba->fp, fp_tmp, PHP_STREAM_COPY_ALL)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not copy remainder to temporary stream");
+ ret = FAILURE;
+ }
+ }
+ }
+ }
+
+ /* 5 */
+ if (ret == SUCCESS) {
+ if (!value || (key->name && strlen(key->name))) {
+ ret = inifile_truncate(dba, append ? pos_grp_next : pos_grp_start TSRMLS_CC); /* writes error on fail */
+ }
+ }
+
+ if (ret == SUCCESS) {
+ if (key->name && strlen(key->name)) {
+ /* 6 */
+ if (!append && ini_tmp) {
+ ret = inifile_filter(dba, ini_tmp, key TSRMLS_CC);
+ }
+
+ /* 7 */
+ /* important: do not query ret==SUCCESS again: inifile_filter might fail but
+ * however next operation must be done.
+ */
+ if (value) {
+ if (pos_grp_start == pos_grp_next && key->group && strlen(key->group)) {
+ php_stream_printf(dba->fp TSRMLS_CC, "[%s]\n", key->group);
+ }
+ php_stream_printf(dba->fp TSRMLS_CC, "%s=%s\n", key->name, value->value ? value->value : "");
+ }
+ }
+
+ /* 8 */
+ /* important: do not query ret==SUCCESS again: inifile_filter might fail but
+ * however next operation must be done.
+ */
+ if (fp_tmp && php_stream_tell(fp_tmp)) {
+ php_stream_seek(fp_tmp, 0, SEEK_SET);
+ php_stream_seek(dba->fp, 0, SEEK_END);
+ if (!php_stream_copy_to_stream(fp_tmp, dba->fp, PHP_STREAM_COPY_ALL)) {
+ php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "Could not copy from temporary stream - ini file truncated");
+ ret = FAILURE;
+ }
+ }
+ }
+
+ if (ini_tmp) {
+ php_stream_close(ini_tmp->fp);
+ inifile_free(ini_tmp, 0);
+ }
+ if (fp_tmp) {
+ php_stream_close(fp_tmp);
+ }
+ php_stream_flush(dba->fp);
+ php_stream_seek(dba->fp, 0, SEEK_SET);
+
+ return ret;
+}
+/* }}} */
+
+/* {{{ inifile_delete
+ */
+int inifile_delete(inifile *dba, const key_type *key TSRMLS_DC)
+{
+ return inifile_delete_replace_append(dba, key, NULL, 0 TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ inifile_relace
+ */
+int inifile_replace(inifile *dba, const key_type *key, const val_type *value TSRMLS_DC)
+{
+ return inifile_delete_replace_append(dba, key, value, 0 TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ inifile_append
+ */
+int inifile_append(inifile *dba, const key_type *key, const val_type *value TSRMLS_DC)
+{
+ return inifile_delete_replace_append(dba, key, value, 1 TSRMLS_CC);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/libinifile/inifile.h b/ext/dba/libinifile/inifile.h
new file mode 100644
index 0000000..5a25573
--- /dev/null
+++ b/ext/dba/libinifile/inifile.h
@@ -0,0 +1,66 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Marcus Boerger <helly@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_LIB_INIFILE_H
+#define PHP_LIB_INIFILE_H
+
+typedef struct {
+ char *group;
+ char *name;
+} key_type;
+
+typedef struct {
+ char *value;
+} val_type;
+
+typedef struct {
+ key_type key;
+ val_type val;
+ size_t pos;
+} line_type;
+
+typedef struct {
+ char *lockfn;
+ int lockfd;
+ php_stream *fp;
+ int readonly;
+ line_type curr;
+ line_type next;
+} inifile;
+
+val_type inifile_fetch(inifile *dba, const key_type *key, int skip TSRMLS_DC);
+int inifile_firstkey(inifile *dba TSRMLS_DC);
+int inifile_nextkey(inifile *dba TSRMLS_DC);
+int inifile_delete(inifile *dba, const key_type *key TSRMLS_DC);
+int inifile_replace(inifile *dba, const key_type *key, const val_type *val TSRMLS_DC);
+int inifile_append(inifile *dba, const key_type *key, const val_type *val TSRMLS_DC);
+char *inifile_version();
+
+key_type inifile_key_split(const char *group_name);
+char * inifile_key_string(const key_type *key);
+
+void inifile_key_free(key_type *key);
+void inifile_val_free(val_type *val);
+void inifile_line_free(line_type *ln);
+
+inifile * inifile_alloc(php_stream *fp, int readonly, int persistent TSRMLS_DC);
+void inifile_free(inifile *dba, int persistent);
+
+#endif
diff --git a/ext/dba/php_cdb.h b/ext/dba/php_cdb.h
new file mode 100644
index 0000000..a046f07
--- /dev/null
+++ b/ext/dba/php_cdb.h
@@ -0,0 +1,12 @@
+#ifndef PHP_CDB_H
+#define PHP_CDB_H
+
+#if DBA_CDB
+
+#include "php_dba.h"
+
+DBA_FUNCS(cdb);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_db1.h b/ext/dba/php_db1.h
new file mode 100644
index 0000000..c0bb5f0
--- /dev/null
+++ b/ext/dba/php_db1.h
@@ -0,0 +1,12 @@
+#ifndef PHP_DB1_H
+#define PHP_DB1_H
+
+#if DBA_DB1
+
+#include "php_dba.h"
+
+DBA_FUNCS(db1);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_db2.h b/ext/dba/php_db2.h
new file mode 100644
index 0000000..2a95223
--- /dev/null
+++ b/ext/dba/php_db2.h
@@ -0,0 +1,12 @@
+#ifndef PHP_DB2_H
+#define PHP_DB2_H
+
+#if DBA_DB2
+
+#include "php_dba.h"
+
+DBA_FUNCS(db2);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_db3.h b/ext/dba/php_db3.h
new file mode 100644
index 0000000..58bb0b6
--- /dev/null
+++ b/ext/dba/php_db3.h
@@ -0,0 +1,12 @@
+#ifndef PHP_DB3_H
+#define PHP_DB3_H
+
+#if DBA_DB3
+
+#include "php_dba.h"
+
+DBA_FUNCS(db3);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_db4.h b/ext/dba/php_db4.h
new file mode 100644
index 0000000..fa814c3
--- /dev/null
+++ b/ext/dba/php_db4.h
@@ -0,0 +1,12 @@
+#ifndef PHP_DB4_H
+#define PHP_DB4_H
+
+#if DBA_DB4
+
+#include "php_dba.h"
+
+DBA_FUNCS(db4);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_dba.h b/ext/dba/php_dba.h
new file mode 100644
index 0000000..1e931df
--- /dev/null
+++ b/ext/dba/php_dba.h
@@ -0,0 +1,153 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sascha Schumann <sascha@schumann.cx> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_DBA_H
+#define PHP_DBA_H
+
+#if HAVE_DBA
+
+typedef enum {
+ /* do not allow 0 here */
+ DBA_READER = 1,
+ DBA_WRITER,
+ DBA_TRUNC,
+ DBA_CREAT
+} dba_mode_t;
+
+typedef struct dba_lock {
+ php_stream *fp;
+ char *name;
+ int mode; /* LOCK_EX,LOCK_SH */
+} dba_lock;
+
+typedef struct dba_info {
+ /* public */
+ void *dbf; /* ptr to private data or whatever */
+ char *path;
+ dba_mode_t mode;
+ php_stream *fp; /* this is the database stream for builtin handlers */
+ int fd;
+ /* arg[cv] are only available when the dba_open handler is called! */
+ int argc;
+ zval ***argv;
+ /* private */
+ int flags; /* whether and how dba did locking and other flags*/
+ struct dba_handler *hnd;
+ dba_lock lock;
+} dba_info;
+
+#define DBA_LOCK_READER (0x0001)
+#define DBA_LOCK_WRITER (0x0002)
+#define DBA_LOCK_CREAT (0x0004)
+#define DBA_LOCK_TRUNC (0x0008)
+
+#define DBA_LOCK_EXT (0)
+#define DBA_LOCK_ALL (DBA_LOCK_READER|DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
+#define DBA_LOCK_WCT (DBA_LOCK_WRITER|DBA_LOCK_CREAT|DBA_LOCK_TRUNC)
+
+#define DBA_STREAM_OPEN (0x0010)
+#define DBA_PERSISTENT (0x0020)
+
+#define DBA_CAST_AS_FD (0x0050)
+#define DBA_NO_APPEND (0x00D0)
+
+extern zend_module_entry dba_module_entry;
+#define dba_module_ptr &dba_module_entry
+
+typedef struct dba_handler {
+ char *name; /* handler name */
+ int flags; /* whether and how dba does locking and other flags*/
+ int (*open)(dba_info *, char **error TSRMLS_DC);
+ void (*close)(dba_info * TSRMLS_DC);
+ char* (*fetch)(dba_info *, char *, int, int, int * TSRMLS_DC);
+ int (*update)(dba_info *, char *, int, char *, int, int TSRMLS_DC);
+ int (*exists)(dba_info *, char *, int TSRMLS_DC);
+ int (*delete)(dba_info *, char *, int TSRMLS_DC);
+ char* (*firstkey)(dba_info *, int * TSRMLS_DC);
+ char* (*nextkey)(dba_info *, int * TSRMLS_DC);
+ int (*optimize)(dba_info * TSRMLS_DC);
+ int (*sync)(dba_info * TSRMLS_DC);
+ char* (*info)(struct dba_handler *hnd, dba_info * TSRMLS_DC);
+ /* dba_info==NULL: Handler info, dba_info!=NULL: Database info */
+} dba_handler;
+
+/* common prototypes which must be supplied by modules */
+
+#define DBA_OPEN_FUNC(x) \
+ int dba_open_##x(dba_info *info, char **error TSRMLS_DC)
+#define DBA_CLOSE_FUNC(x) \
+ void dba_close_##x(dba_info *info TSRMLS_DC)
+#define DBA_FETCH_FUNC(x) \
+ char *dba_fetch_##x(dba_info *info, char *key, int keylen, int skip, int *newlen TSRMLS_DC)
+#define DBA_UPDATE_FUNC(x) \
+ int dba_update_##x(dba_info *info, char *key, int keylen, char *val, int vallen, int mode TSRMLS_DC)
+#define DBA_EXISTS_FUNC(x) \
+ int dba_exists_##x(dba_info *info, char *key, int keylen TSRMLS_DC)
+#define DBA_DELETE_FUNC(x) \
+ int dba_delete_##x(dba_info *info, char *key, int keylen TSRMLS_DC)
+#define DBA_FIRSTKEY_FUNC(x) \
+ char *dba_firstkey_##x(dba_info *info, int *newlen TSRMLS_DC)
+#define DBA_NEXTKEY_FUNC(x) \
+ char *dba_nextkey_##x(dba_info *info, int *newlen TSRMLS_DC)
+#define DBA_OPTIMIZE_FUNC(x) \
+ int dba_optimize_##x(dba_info *info TSRMLS_DC)
+#define DBA_SYNC_FUNC(x) \
+ int dba_sync_##x(dba_info *info TSRMLS_DC)
+#define DBA_INFO_FUNC(x) \
+ char *dba_info_##x(dba_handler *hnd, dba_info *info TSRMLS_DC)
+
+#define DBA_FUNCS(x) \
+ DBA_OPEN_FUNC(x); \
+ DBA_CLOSE_FUNC(x); \
+ DBA_FETCH_FUNC(x); \
+ DBA_UPDATE_FUNC(x); \
+ DBA_DELETE_FUNC(x); \
+ DBA_EXISTS_FUNC(x); \
+ DBA_FIRSTKEY_FUNC(x); \
+ DBA_NEXTKEY_FUNC(x); \
+ DBA_OPTIMIZE_FUNC(x); \
+ DBA_SYNC_FUNC(x); \
+ DBA_INFO_FUNC(x)
+
+#define VALLEN(p) Z_STRVAL_PP(p), Z_STRLEN_PP(p)
+
+PHP_FUNCTION(dba_open);
+PHP_FUNCTION(dba_popen);
+PHP_FUNCTION(dba_close);
+PHP_FUNCTION(dba_firstkey);
+PHP_FUNCTION(dba_nextkey);
+PHP_FUNCTION(dba_replace);
+PHP_FUNCTION(dba_insert);
+PHP_FUNCTION(dba_delete);
+PHP_FUNCTION(dba_exists);
+PHP_FUNCTION(dba_fetch);
+PHP_FUNCTION(dba_optimize);
+PHP_FUNCTION(dba_sync);
+PHP_FUNCTION(dba_handlers);
+PHP_FUNCTION(dba_list);
+PHP_FUNCTION(dba_key_split);
+
+#else
+#define dba_module_ptr NULL
+#endif
+
+#define phpext_dba_ptr dba_module_ptr
+
+#endif
diff --git a/ext/dba/php_dbm.h b/ext/dba/php_dbm.h
new file mode 100644
index 0000000..4c963d1
--- /dev/null
+++ b/ext/dba/php_dbm.h
@@ -0,0 +1,12 @@
+#ifndef PHP_DBM_H
+#define PHP_DBM_H
+
+#if DBA_DBM
+
+#include "php_dba.h"
+
+DBA_FUNCS(dbm);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_flatfile.h b/ext/dba/php_flatfile.h
new file mode 100644
index 0000000..afa9f6d
--- /dev/null
+++ b/ext/dba/php_flatfile.h
@@ -0,0 +1,12 @@
+#ifndef PHP_FLATFILE_H
+#define PHP_FLATFILE_H
+
+#if DBA_FLATFILE
+
+#include "php_dba.h"
+
+DBA_FUNCS(flatfile);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_gdbm.h b/ext/dba/php_gdbm.h
new file mode 100644
index 0000000..3068404
--- /dev/null
+++ b/ext/dba/php_gdbm.h
@@ -0,0 +1,12 @@
+#ifndef PHP_GDBM_H
+#define PHP_GDBM_H
+
+#if DBA_GDBM
+
+#include "php_dba.h"
+
+DBA_FUNCS(gdbm);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_inifile.h b/ext/dba/php_inifile.h
new file mode 100644
index 0000000..69444df
--- /dev/null
+++ b/ext/dba/php_inifile.h
@@ -0,0 +1,12 @@
+#ifndef PHP_INIFILE_H
+#define PHP_INIFILE_H
+
+#if DBA_INIFILE
+
+#include "php_dba.h"
+
+DBA_FUNCS(inifile);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_ndbm.h b/ext/dba/php_ndbm.h
new file mode 100644
index 0000000..b1ebf15
--- /dev/null
+++ b/ext/dba/php_ndbm.h
@@ -0,0 +1,12 @@
+#ifndef PHP_NDBM_H
+#define PHP_NDBM_H
+
+#if DBA_NDBM
+
+#include "php_dba.h"
+
+DBA_FUNCS(ndbm);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_qdbm.h b/ext/dba/php_qdbm.h
new file mode 100644
index 0000000..c88efcf
--- /dev/null
+++ b/ext/dba/php_qdbm.h
@@ -0,0 +1,12 @@
+#ifndef PHP_QDBM_H
+#define PHP_QDBM_H
+
+#if DBA_QDBM
+
+#include "php_dba.h"
+
+DBA_FUNCS(qdbm);
+
+#endif
+
+#endif
diff --git a/ext/dba/php_tcadb.h b/ext/dba/php_tcadb.h
new file mode 100644
index 0000000..6aa9aa7
--- /dev/null
+++ b/ext/dba/php_tcadb.h
@@ -0,0 +1,41 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Michael Maclean <mgdm@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifndef PHP_TCADB_H
+#define PHP_TCADB_H
+
+#if DBA_TCADB
+
+#include "php_dba.h"
+
+DBA_FUNCS(tcadb);
+
+#endif
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/dba/tests/bug36436.phpt b/ext/dba/tests/bug36436.phpt
new file mode 100644
index 0000000..19254df
--- /dev/null
+++ b/ext/dba/tests/bug36436.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Bug #36436 (DBA problem with Berkeley DB4)
+--SKIPIF--
+<?php
+ $handler = 'db4';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+$handler = 'db4';
+require_once(dirname(__FILE__) .'/test.inc');
+
+$db = dba_popen($db_filename, 'c', 'db4');
+
+dba_insert('X', 'XYZ', $db);
+dba_insert('Y', '123', $db);
+
+var_dump($db, dba_fetch('X', $db));
+
+var_dump(dba_firstkey($db));
+var_dump(dba_nextkey($db));
+
+dba_close($db);
+
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+resource(%d) of type (dba persistent)
+string(3) "XYZ"
+string(1) "X"
+string(1) "Y"
+===DONE===
diff --git a/ext/dba/tests/bug38698.phpt b/ext/dba/tests/bug38698.phpt
new file mode 100644
index 0000000..56dde85
--- /dev/null
+++ b/ext/dba/tests/bug38698.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Bug #38698 (Bug #38698 for some keys cdbmake creates corrupted db and cdb can't read valid db)
+--SKIPIF--
+<?php
+ $handler = 'cdb_make';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+$db_file = dirname(__FILE__) .'/129php.cdb';
+
+if (($db_make=dba_open($db_file, "n", 'cdb_make'))!==FALSE) {
+ dba_insert(pack('i',129), "Booo!", $db_make);
+ dba_close($db_make);
+ // write md5 checksum of generated database file
+ var_dump(md5_file($db_file));
+ @unlink($db_file);
+} else {
+ echo "Error creating database\n";
+}
+?>
+===DONE===
+--EXPECT--
+string(32) "1f34b74bde3744265acfc21e0f30af95"
+===DONE===
diff --git a/ext/dba/tests/bug48240.phpt b/ext/dba/tests/bug48240.phpt
new file mode 100644
index 0000000..5a72073
--- /dev/null
+++ b/ext/dba/tests/bug48240.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #48240 (DBA Segmentation fault dba_nextkey)
+--SKIPIF--
+<?php
+ $handler = 'db4';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+$handler = 'db4';
+require_once(dirname(__FILE__) .'/test.inc');
+
+$db = dba_open($db_filename, 'c', 'db4');
+
+var_dump(dba_nextkey($db));
+
+dba_close($db);
+
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+bool(false)
+===DONE===
diff --git a/ext/dba/tests/bug49125.phpt b/ext/dba/tests/bug49125.phpt
new file mode 100644
index 0000000..e06495a
--- /dev/null
+++ b/ext/dba/tests/bug49125.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #49125 (Error in dba_exists C code)
+--SKIPIF--
+<?php
+ $handler = 'db4';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+error_reporting(E_ALL);
+
+$handler = 'db4';
+require_once(dirname(__FILE__) .'/test.inc');
+
+$db = dba_popen($db_filename, 'c', 'db4');
+
+dba_insert('foo', 'foo', $db);
+
+var_dump(dba_exists('foo', $db));
+
+dba_close($db);
+
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+bool(true)
diff --git a/ext/dba/tests/clean.inc b/ext/dba/tests/clean.inc
new file mode 100644
index 0000000..7c53e7e
--- /dev/null
+++ b/ext/dba/tests/clean.inc
@@ -0,0 +1,5 @@
+<?php
+ $db_filename = dirname(__FILE__) .'/test0.dbm'; // see test.inc
+ @unlink($db_filename);
+ @unlink($db_filename.'.lck');
+?>
diff --git a/ext/dba/tests/dba001.phpt b/ext/dba/tests/dba001.phpt
new file mode 100644
index 0000000..b63829a
--- /dev/null
+++ b/ext/dba/tests/dba001.phpt
@@ -0,0 +1,25 @@
+--TEST--
+DBA File Creation Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+ dba_close($db_file);
+ } else {
+ echo "$db_file does not exist\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+database file created
diff --git a/ext/dba/tests/dba002.phpt b/ext/dba/tests/dba002.phpt
new file mode 100644
index 0000000..e60e733
--- /dev/null
+++ b/ext/dba/tests/dba002.phpt
@@ -0,0 +1,26 @@
+--TEST--
+DBA Insert/Fetch Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file);
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+This is a test insert
diff --git a/ext/dba/tests/dba003.phpt b/ext/dba/tests/dba003.phpt
new file mode 100644
index 0000000..a027b53
--- /dev/null
+++ b/ext/dba/tests/dba003.phpt
@@ -0,0 +1,28 @@
+--TEST--
+DBA Insert/Replace/Fetch Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("key1", "This is a test insert", $db_file);
+ dba_replace("key1", "This is the replacement text", $db_file);
+ $a = dba_fetch("key1", $db_file);
+ dba_close($db_file);
+ echo $a;
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+This is the replacement text
diff --git a/ext/dba/tests/dba004.phpt b/ext/dba/tests/dba004.phpt
new file mode 100644
index 0000000..6e7180c
--- /dev/null
+++ b/ext/dba/tests/dba004.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA Multiple Insert/Fetch Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ dba_insert("key3", "Third Content String", $db_file);
+ dba_insert("key4", "Another Content String", $db_file);
+ dba_insert("key5", "The last content string", $db_file);
+ $a = dba_fetch("key4", $db_file);
+ $b = dba_fetch("key2", $db_file);
+ dba_close($db_file);
+ echo "$a $b";
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+Another Content String Content String 2
diff --git a/ext/dba/tests/dba005.phpt b/ext/dba/tests/dba005.phpt
new file mode 100644
index 0000000..68ad600
--- /dev/null
+++ b/ext/dba/tests/dba005.phpt
@@ -0,0 +1,39 @@
+--TEST--
+DBA FirstKey/NextKey Loop Test With 5 Items
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ dba_insert("key3", "Third Content String", $db_file);
+ dba_insert("key4", "Another Content String", $db_file);
+ dba_insert("key5", "The last content string", $db_file);
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ for ($i=1; $i<6; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+5YYYYY
diff --git a/ext/dba/tests/dba006.phpt b/ext/dba/tests/dba006.phpt
new file mode 100644
index 0000000..a3fc738
--- /dev/null
+++ b/ext/dba/tests/dba006.phpt
@@ -0,0 +1,41 @@
+--TEST--
+DBA FirstKey/NextKey with 2 deletes
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ dba_insert("key3", "Third Content String", $db_file);
+ dba_insert("key4", "Another Content String", $db_file);
+ dba_insert("key5", "The last content string", $db_file);
+ dba_delete("key3", $db_file);
+ dba_delete("key1", $db_file);
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ for ($i=1; $i<6; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+3NYNYY
diff --git a/ext/dba/tests/dba007.phpt b/ext/dba/tests/dba007.phpt
new file mode 100644
index 0000000..2519fdc
--- /dev/null
+++ b/ext/dba/tests/dba007.phpt
@@ -0,0 +1,52 @@
+--TEST--
+DBA Multiple File Creation Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ if (!function_exists('dba_list')) die('skip dba_list() not available');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ $db_file1 = $db_filename1 = dirname(__FILE__).'/test1.dbm';
+ $db_file2 = $db_filename2 = dirname(__FILE__).'/test2.dbm';
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+ } else {
+ echo "$db_file does not exist\n";
+ }
+ if (($db_file1=dba_open($db_file1, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+ } else {
+ echo "$db_file does not exist\n";
+ }
+ if (($db_file2=dba_open($db_file2, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+ } else {
+ echo "$db_file does not exist\n";
+ }
+ var_dump(dba_list());
+ dba_close($db_file);
+
+ @unlink($db_filename1);
+ @unlink($db_filename2);
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+database file created
+database file created
+database file created
+array(3) {
+ [%d]=>
+ string(%d) "%stest0.dbm"
+ [%d]=>
+ string(%d) "%stest1.dbm"
+ [%d]=>
+ string(%d) "%stest2.dbm"
+}
diff --git a/ext/dba/tests/dba008.phpt b/ext/dba/tests/dba008.phpt
new file mode 100644
index 0000000..f7015d9
--- /dev/null
+++ b/ext/dba/tests/dba008.phpt
@@ -0,0 +1,37 @@
+--TEST--
+DBA magic_quotes_runtime Test
+--SKIPIF--
+<?php
+ die('skip, magic_quotes removed');
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ ini_set('magic_quotes_runtime', 0);
+ dba_insert("key1", '"', $db_file);
+ var_dump(dba_fetch("key1", $db_file));
+ ini_set('magic_quotes_runtime', 1);
+ var_dump(dba_fetch("key1", $db_file));
+ dba_replace("key1", '\"', $db_file);
+ var_dump(dba_fetch("key1", $db_file));
+ ini_set('magic_quotes_runtime', 0);
+ var_dump(dba_fetch("key1", $db_file));
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+string(1) """
+string(2) "\""
+string(2) "\""
+string(1) """
diff --git a/ext/dba/tests/dba009.phpt b/ext/dba/tests/dba009.phpt
new file mode 100644
index 0000000..698657b
--- /dev/null
+++ b/ext/dba/tests/dba009.phpt
@@ -0,0 +1,37 @@
+--TEST--
+DBA dba_popen Test
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ print("info $HND handler used");
+?>
+--FILE--
+<?php
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ if (($db=dba_popen($db_file, "n", $handler))!==FALSE) {
+ echo "Opened\n";
+ dba_insert("a", "Inserted", $db);
+ echo dba_fetch("a", $db)."\n";
+ dba_close($db);
+ echo "Closed\n";
+ } else {
+ echo "Error creating database\n";
+ }
+ if (($db=dba_popen($db_file, "n", $handler))!==FALSE) {
+ echo "Opened\n";
+ dba_insert("a", "Inserted", $db);
+ echo dba_fetch("a", $db)."\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+Opened
+Inserted
+Closed
+Opened
+Inserted
diff --git a/ext/dba/tests/dba010.phpt b/ext/dba/tests/dba010.phpt
new file mode 100644
index 0000000..c818373
--- /dev/null
+++ b/ext/dba/tests/dba010.phpt
@@ -0,0 +1,44 @@
+--TEST--
+DBA with array keys
+--SKIPIF--
+<?php
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert(array("", "name0") , "Content String 1", $db_file);
+ dba_insert(array("key1", "name1") , "Content String 1", $db_file);
+ dba_insert(array("key2","name2"), "Content String 2", $db_file);
+ dba_insert("[key3]name3", "Third Content String", $db_file);
+ dba_insert(array("key4","name4"), "Another Content String", $db_file);
+ dba_insert(array("key5","name5"), "The last content string", $db_file);
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ echo dba_exists(array("","name0"), $db_file) ? "Y" : "N";
+ for ($i=1; $i<5; $i++) {
+ echo dba_exists("[key$i]name$i", $db_file) ? "Y" : "N";
+ }
+ echo dba_exists(array("key5","name5"), $db_file) ? "Y" : "N";
+ echo "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+6YYYYYY
diff --git a/ext/dba/tests/dba011.phpt b/ext/dba/tests/dba011.phpt
new file mode 100644
index 0000000..71164be
--- /dev/null
+++ b/ext/dba/tests/dba011.phpt
@@ -0,0 +1,38 @@
+--TEST--
+DBA argument tests
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+var_dump(dba_open($db_file));
+var_dump(dba_open($db_file, 'n'));
+var_dump(dba_open($db_file, 'n', 'bogus'));
+var_dump(dba_open($db_file, 'q', $handler));
+var_dump(dba_open($db_file, 'nq', $handler));
+var_dump(dba_open($db_file, 'n', $handler, 2, 3, 4, 5, 6, 7, 8));
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: flatfile
+
+Warning: Wrong parameter count for dba_open() in %sdba011.php on line %d
+NULL
+resource(%d) of type (dba)
+
+Warning: dba_open(%stest0.dbm,n): No such handler: bogus in %sdba011.php on line %d
+bool(false)
+
+Warning: dba_open(%stest0.dbm,q): Illegal DBA mode in %sdba011.php on line %d
+bool(false)
+
+Warning: dba_open(%stest0.dbm,nq): Illegal DBA mode in %sdba011.php on line %d
+bool(false)
+resource(%d) of type (dba)
diff --git a/ext/dba/tests/dba012.phpt b/ext/dba/tests/dba012.phpt
new file mode 100644
index 0000000..821c4e2
--- /dev/null
+++ b/ext/dba/tests/dba012.phpt
@@ -0,0 +1,42 @@
+--TEST--
+DBA dba.default_handler tests
+--SKIPIF--
+<?php
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--INI--
+dba.default_handler=flatfile
+--FILE--
+<?php
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+echo "Test 1\n";
+
+ini_set('dba.default_handler', 'does_not_exist');
+
+var_dump(dba_open($db_filename, 'c'));
+
+echo "Test 2\n";
+
+ini_set('dba.default_handler', '');
+
+var_dump(dba_open($db_filename, 'n'));
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: flatfile
+Test 1
+
+Warning: ini_set(): No such handler: does_not_exist in %sdba012.php on line %d
+resource(%d) of type (dba)
+Test 2
+
+Warning: dba_open(%stest0.dbm,n): No default handler selected in %sdba012.php on line %d
+bool(false)
diff --git a/ext/dba/tests/dba013.phpt b/ext/dba/tests/dba013.phpt
new file mode 100644
index 0000000..bf95642
--- /dev/null
+++ b/ext/dba/tests/dba013.phpt
@@ -0,0 +1,27 @@
+--TEST--
+DBA with array key with empty array
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert(array(), "Content String 1", $db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+
+Catchable fatal error: dba_insert(): Key does not have exactly two elements: (key, name) in %sdba013.php on line %d
diff --git a/ext/dba/tests/dba014.phpt b/ext/dba/tests/dba014.phpt
new file mode 100644
index 0000000..7e52be7
--- /dev/null
+++ b/ext/dba/tests/dba014.phpt
@@ -0,0 +1,27 @@
+--TEST--
+DBA with array key with array containing too many elements
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert(array("a", "b", "c"), "Content String 2", $db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: %s
+
+Catchable fatal error: dba_insert(): Key does not have exactly two elements: (key, name) in %sdba014.php on line %d
diff --git a/ext/dba/tests/dba015.phpt b/ext/dba/tests/dba015.phpt
new file mode 100644
index 0000000..9f560c5
--- /dev/null
+++ b/ext/dba/tests/dba015.phpt
@@ -0,0 +1,76 @@
+--TEST--
+DBA with persistent connections
+--SKIPIF--
+<?php
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+echo "Test 1\n";
+$db_file1 = dba_popen($db_filename, 'n', 'flatfile');
+dba_insert("key1", "This is a test insert 1", $db_file1);
+echo dba_fetch("key1", $db_file1), "\n";
+
+
+echo "Test 2\n";
+$db_file2 = dba_popen($db_filename, 'n', 'flatfile');
+if ($db_file1 === $db_file2) {
+ echo "resources are the same\n";
+} else {
+ echo "resources are different\n";
+}
+
+
+echo "Test 3 - fetch both rows from second resource\n";
+dba_insert("key2", "This is a test insert 2", $db_file2);
+echo dba_fetch("key1", $db_file2), "\n";
+echo dba_fetch("key2", $db_file2), "\n";
+
+
+echo "Test 4 - fetch both rows from first resource\n";
+echo dba_fetch("key1", $db_file1), "\n";
+echo dba_fetch("key2", $db_file1), "\n";
+
+echo "Test 5 - close 2nd resource\n";
+dba_close($db_file2);
+var_dump($db_file1);
+var_dump($db_file2);
+
+echo "Test 6 - query after closing 2nd resource\n";
+echo dba_fetch("key1", $db_file1), "\n";
+echo dba_fetch("key2", $db_file1), "\n";
+
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--XFAIL--
+Test 6 crashes in flatfile_findkey with dba pointer of NULL, bug http://bugs.php.net/bug.php?id=51278
+--EXPECTF--
+database handler: flatfile
+Test 1
+This is a test insert 1
+Test 2
+resources are different
+Test 3 - fetch both rows from second resource
+This is a test insert 1
+This is a test insert 2
+Test 4 - fetch both rows from first resource
+This is a test insert 1
+This is a test insert 2
+Test 5 - close 2nd resource
+resource(%d) of type (dba persistent)
+resource(%d) of type (Unknown)
+Test 6 - query after closing 2nd resource
+This is a test insert 1
+This is a test insert 2
+===DONE===
diff --git a/ext/dba/tests/dba016.phpt b/ext/dba/tests/dba016.phpt
new file mode 100644
index 0000000..29726ac
--- /dev/null
+++ b/ext/dba/tests/dba016.phpt
@@ -0,0 +1,23 @@
+--TEST--
+DBA lock modifier error message test
+--SKIPIF--
+<?php
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+$db_file1 = dba_popen($db_filename, 'n-t', 'flatfile');
+
+?>
+===DONE===
+--EXPECTF--
+database handler: flatfile
+
+Warning: dba_popen(%stest0.dbm,n-t): You cannot combine modifiers - (no lock) and t (test lock) in %sdba016.php on line %d
+===DONE===
diff --git a/ext/dba/tests/dba_cdb.phpt b/ext/dba/tests/dba_cdb.phpt
new file mode 100644
index 0000000..b9ef68f
--- /dev/null
+++ b/ext/dba/tests/dba_cdb.phpt
@@ -0,0 +1,51 @@
+--TEST--
+DBA CDB handler test
+--SKIPIF--
+<?php
+ $handler = 'cdb';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die('info CDB does not support replace or delete');
+?>
+--FILE--
+<?php
+ $handler = 'cdb';
+ require_once(dirname(__FILE__) .'/test.inc');
+ require_once(dirname(__FILE__) .'/dba_handler.inc');
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+database handler: cdb
+5YYYYY
+Content String 2
+array(5) {
+ ["key1"]=>
+ string(16) "Content String 1"
+ ["key2"]=>
+ string(16) "Content String 2"
+ ["key3"]=>
+ string(20) "Third Content String"
+ ["key4"]=>
+ string(22) "Another Content String"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+5YYYYY
+Content String 2
+array(5) {
+ ["key1"]=>
+ string(16) "Content String 1"
+ ["key2"]=>
+ string(16) "Content String 2"
+ ["key3"]=>
+ string(20) "Third Content String"
+ ["key4"]=>
+ string(22) "Another Content String"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_cdb_001.phpt b/ext/dba/tests/dba_cdb_001.phpt
new file mode 100644
index 0000000..4372754
--- /dev/null
+++ b/ext/dba/tests/dba_cdb_001.phpt
@@ -0,0 +1,89 @@
+--TEST--
+DBA CDB handler test
+--SKIPIF--
+<?php
+$handler = 'cdb';
+require_once(dirname(__FILE__) .'/skipif.inc');
+die('info CDB does not support replace or delete');
+?>
+--FILE--
+<?php
+
+$handler = 'cdb';
+require_once(dirname(__FILE__) .'/test.inc');
+
+echo "Test 0\n";
+
+if (($db_file = dba_open($db_filename, 'n', $handler))!==FALSE) {
+ var_dump(dba_insert("key1", "Content String 1", $db_file));
+ var_dump(dba_replace("key1", "New Content String", $db_file));
+ var_dump(dba_fetch("key1", $db_file));
+ var_dump(dba_firstkey($db_file));
+ var_dump(dba_delete("key1", $db_file));
+ var_dump(dba_optimize($db_file));
+ var_dump(dba_sync($db_file));
+ dba_close($db_file);
+}
+else {
+ echo "Failed to open DB\n";
+}
+
+unlink($db_filename);
+
+echo "Test 1\n";
+
+if (($db_file = dba_open($db_filename, 'c', $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_close($db_file);
+}
+else {
+ echo "Failed to open DB\n";
+}
+
+echo "Test 2\n";
+
+if (($db_file = dba_open($db_filename, 'r', $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_close($db_file);
+}
+else {
+ echo "Failed to open DB\n";
+}
+
+echo "Test 3\n";
+
+if (($db_file = dba_open($db_filename, 'w', $handler))!==FALSE) {
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+}
+else {
+ echo "Failed to open DB\n";
+}
+
+?>
+===DONE===
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+Test 0
+bool(true)
+bool(false)
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+bool(true)
+Test 1
+
+Warning: dba_open(%stest0.dbm,c): Driver initialization failed for handler: cdb: Update operations are not supported in %sdba_cdb_001.php on line %d
+Failed to open DB
+Test 2
+
+Warning: dba_insert(): You cannot perform a modification to a database without proper access in %sdba_cdb_001.php on line %d
+Test 3
+
+Warning: dba_open(%stest0.dbm,w): Driver initialization failed for handler: cdb: Update operations are not supported in %sdba_cdb_001.php on line %d
+Failed to open DB
+===DONE===
diff --git a/ext/dba/tests/dba_cdb_make.phpt b/ext/dba/tests/dba_cdb_make.phpt
new file mode 100644
index 0000000..6a5f2dd
--- /dev/null
+++ b/ext/dba/tests/dba_cdb_make.phpt
@@ -0,0 +1,40 @@
+--TEST--
+DBA CDB_MAKE handler test
+--SKIPIF--
+<?php
+ $handler = 'cdb_make';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+ die('info CDB_MAKE does not support reading');
+?>
+--FILE--
+<?php
+ $handler = 'cdb_make';
+ require_once(dirname(__FILE__) .'/test.inc');
+ echo "database handler: $handler\n";
+ // print md5 checksum of test.cdb which is generated by cdb_make program
+ var_dump(md5_file(dirname(__FILE__).'/test.cdb'));
+ if (($db_make=dba_open($db_file, "n", $handler))!==FALSE) {
+ dba_insert("1", "1", $db_make);
+ dba_insert("2", "2", $db_make);
+ dba_insert("1", "3", $db_make);
+ dba_insert("2", "1", $db_make);
+ dba_insert("3", "3", $db_make);
+ dba_insert("1", "2", $db_make);
+ dba_insert("4", "4", $db_make);
+// dba_replace cdb_make doesn't know replace
+ dba_close($db_make);
+ // write md5 checksum of generated database file
+ var_dump(md5_file($db_file));
+ // no need to test created database: this is done by dba_cdb_read.phpt
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+database handler: cdb_make
+string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5"
+string(32) "12fc5ba2b9dcfef2480e5324eeb5f3e5"
diff --git a/ext/dba/tests/dba_cdb_read.phpt b/ext/dba/tests/dba_cdb_read.phpt
new file mode 100644
index 0000000..71575f5
--- /dev/null
+++ b/ext/dba/tests/dba_cdb_read.phpt
@@ -0,0 +1,65 @@
+--TEST--
+DBA CDB handler test (read only)
+--SKIPIF--
+<?php
+ $handler = 'cdb_make';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ echo "database handler: cdb\n";
+ $handler = 'cdb';
+ $db_file = dirname(__FILE__).'/test.cdb';
+ if (($db_file=dba_open($db_file, "r", $handler))!==FALSE) {
+ // read key sequence
+ $a = dba_firstkey($db_file);
+ $count= 0;
+ $keys = $a;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $keys .= $a;
+ $count++;
+ }
+ // display number of entries and key existance
+ echo $count;
+ for ($i=1; $i<8; $i++) {
+ echo dba_exists($i, $db_file) ? "Y" : "N";
+ }
+ echo "\n=";
+ echo dba_fetch(1, $db_file);
+ echo dba_fetch(2, $db_file);
+ echo dba_fetch(3, $db_file);
+ echo dba_fetch(4, $db_file);
+ echo "\n#";
+ echo dba_fetch(1, $db_file);
+ echo dba_fetch(1, $db_file);
+ echo dba_fetch(2, $db_file);
+ echo dba_fetch(2, $db_file);
+ echo "\n?".$keys;
+ // with skip = 0 dba_fetch must fetch the first result
+ echo "\n#";
+ $skip = array();
+ for ($i=0; $i < strlen($keys); $i++) {
+ $key = substr($keys, $i, 1);
+ $skip[$key] = 0;
+ echo dba_fetch($key, $db_file);
+ }
+ echo "\n=";
+ for ($i=0; $i < strlen($keys); $i++) {
+ $key = substr($keys, $i, 1);
+ echo dba_fetch($key, $skip[$key], $db_file);
+ $skip[$key]++;
+ }
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+?>
+--EXPECT--
+database handler: cdb
+7YYYYNNN
+=1234
+#1122
+?1212314
+#1212314
+=1231324
diff --git a/ext/dba/tests/dba_db1.phpt b/ext/dba/tests/dba_db1.phpt
new file mode 100644
index 0000000..a246003
--- /dev/null
+++ b/ext/dba/tests/dba_db1.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA DB1 handler test
+--SKIPIF--
+<?php
+ $handler = 'db1';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'db1';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: db1
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_db2.phpt b/ext/dba/tests/dba_db2.phpt
new file mode 100644
index 0000000..89d8a92
--- /dev/null
+++ b/ext/dba/tests/dba_db2.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA DB2 handler test
+--SKIPIF--
+<?php
+ $handler = 'db2';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'db2';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: db2
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_db3.phpt b/ext/dba/tests/dba_db3.phpt
new file mode 100644
index 0000000..257c882
--- /dev/null
+++ b/ext/dba/tests/dba_db3.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA DB3 handler test
+--SKIPIF--
+<?php
+ $handler = 'db3';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'db3';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: db3
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_db4_000.phpt b/ext/dba/tests/dba_db4_000.phpt
new file mode 100644
index 0000000..bbbc52c
--- /dev/null
+++ b/ext/dba/tests/dba_db4_000.phpt
@@ -0,0 +1,50 @@
+--TEST--
+DBA DB4 handler test
+--SKIPIF--
+<?php
+$handler = 'db4';
+require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+$handler = 'db4';
+require_once(dirname(__FILE__) .'/test.inc');
+require_once(dirname(__FILE__) .'/dba_handler.inc');
+?>
+===DONE===
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+database handler: db4
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_db4_001.phpt b/ext/dba/tests/dba_db4_001.phpt
new file mode 100644
index 0000000..ecc8389
--- /dev/null
+++ b/ext/dba/tests/dba_db4_001.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA DB4 New File Creation open("c") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file = dba_open($db_filename, "c", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_002.phpt b/ext/dba/tests/dba_db4_002.phpt
new file mode 100644
index 0000000..18ac0ec
--- /dev/null
+++ b/ext/dba/tests/dba_db4_002.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA DB4 New File Creation open("n") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file = dba_open($db_filename, "n", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_003.phpt b/ext/dba/tests/dba_db4_003.phpt
new file mode 100644
index 0000000..7e8568c
--- /dev/null
+++ b/ext/dba/tests/dba_db4_003.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA DB4 File Creation open("c") with existing file
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+var_dump(file_put_contents($db_filename, "Dummy contents"));
+
+if (($db_file = dba_open($db_filename, "c", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+// Check the file still exists
+$s = file_get_contents($db_filename);
+echo "$s\n";
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+int(14)
+
+Notice: dba_open(): %stest0.dbm: unexpected file type or format in %sdba_db4_003.php on line %d
+
+Warning: dba_open(%stest0.dbm,c): Driver initialization failed for handler: db4: Invalid argument in %sdba_db4_003.php on line %d
+Error creating %stest0.dbm
+Dummy contents
diff --git a/ext/dba/tests/dba_db4_004.phpt b/ext/dba/tests/dba_db4_004.phpt
new file mode 100644
index 0000000..ca876f8
--- /dev/null
+++ b/ext/dba/tests/dba_db4_004.phpt
@@ -0,0 +1,40 @@
+--TEST--
+DBA DB4 Truncate Existing File open("n")
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+var_dump(file_put_contents($db_filename, "Dummy contents"));
+
+if (($db_file = dba_open($db_filename, "n", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+int(14)
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_005.phpt b/ext/dba/tests/dba_db4_005.phpt
new file mode 100644
index 0000000..54bb475
--- /dev/null
+++ b/ext/dba/tests/dba_db4_005.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA DB4 New File Creation popen("c") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_006.phpt b/ext/dba/tests/dba_db4_006.phpt
new file mode 100644
index 0000000..7d95385
--- /dev/null
+++ b/ext/dba/tests/dba_db4_006.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA DB4 New File Creation popen("n") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file = dba_popen($db_filename, "n", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_007.phpt b/ext/dba/tests/dba_db4_007.phpt
new file mode 100644
index 0000000..bd95e0b
--- /dev/null
+++ b/ext/dba/tests/dba_db4_007.phpt
@@ -0,0 +1,41 @@
+--TEST--
+DBA DB4 File Creation popen("c") with existing invalid file
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+var_dump(file_put_contents($db_filename, "Dummy contents"));
+
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+int(14)
+
+Notice: dba_popen(): %stest0.dbm: unexpected file type or format in %sdba_db4_007.php on line %d
+
+Warning: dba_popen(%stest0.dbm,c): Driver initialization failed for handler: db4: Invalid argument in %sdba_db4_007.php on line %d
+Error creating %stest0.dbm
diff --git a/ext/dba/tests/dba_db4_008.phpt b/ext/dba/tests/dba_db4_008.phpt
new file mode 100644
index 0000000..80f62ea
--- /dev/null
+++ b/ext/dba/tests/dba_db4_008.phpt
@@ -0,0 +1,40 @@
+--TEST--
+DBA DB4 Truncate Existing File popen("n")
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+var_dump(file_put_contents($db_filename, "Dummy contents"));
+
+if (($db_file = dba_popen($db_filename, "n", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+int(14)
+database file created
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_009.phpt b/ext/dba/tests/dba_db4_009.phpt
new file mode 100644
index 0000000..5a870c9
--- /dev/null
+++ b/ext/dba/tests/dba_db4_009.phpt
@@ -0,0 +1,53 @@
+--TEST--
+DBA DB4 Multiple File Creation Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+$db_file1 = $db_filename1 = dirname(__FILE__).'/test1.dbm';
+$db_file2 = $db_filename2 = dirname(__FILE__).'/test2.dbm';
+if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+} else {
+ echo "$db_file does not exist\n";
+}
+if (($db_file1=dba_open($db_file1, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+} else {
+ echo "$db_file does not exist\n";
+}
+if (($db_file2=dba_open($db_file2, "n", $handler))!==FALSE) {
+ echo "database file created\n";
+} else {
+ echo "$db_file does not exist\n";
+}
+var_dump(dba_list());
+dba_close($db_file);
+
+@unlink($db_filename1);
+@unlink($db_filename2);
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+database file created
+database file created
+array(3) {
+ [%d]=>
+ string(%d) "%stest0.dbm"
+ [%d]=>
+ string(%d) "%stest1.dbm"
+ [%d]=>
+ string(%d) "%stest2.dbm"
+}
diff --git a/ext/dba/tests/dba_db4_010.phpt b/ext/dba/tests/dba_db4_010.phpt
new file mode 100644
index 0000000..fb31f05
--- /dev/null
+++ b/ext/dba/tests/dba_db4_010.phpt
@@ -0,0 +1,38 @@
+--TEST--
+DBA DB4 magic_quotes_runtime Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_file, "n", $handler))!==FALSE) {
+ ini_set('magic_quotes_runtime', 0);
+ dba_insert("key1", '"', $db_file);
+ var_dump(dba_fetch("key1", $db_file));
+ ini_set('magic_quotes_runtime', 1);
+ var_dump(dba_fetch("key1", $db_file));
+ dba_replace("key1", '\"', $db_file);
+ var_dump(dba_fetch("key1", $db_file));
+ ini_set('magic_quotes_runtime', 0);
+ var_dump(dba_fetch("key1", $db_file));
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+string(1) """
+string(2) "\""
+string(2) "\""
+string(1) """
diff --git a/ext/dba/tests/dba_db4_011.phpt b/ext/dba/tests/dba_db4_011.phpt
new file mode 100644
index 0000000..ce9be27
--- /dev/null
+++ b/ext/dba/tests/dba_db4_011.phpt
@@ -0,0 +1,36 @@
+--TEST--
+DBA DB4 with repeated key
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_filename, "c", $handler))!==FALSE) {
+ var_dump(dba_insert("key1", "Content String 1", $db_file));
+ var_dump(dba_insert("key2", "Content String 2", $db_file));
+ var_dump(dba_insert("key2", "Same key", $db_file));
+ echo dba_fetch("key1", $db_file), "\n";
+ echo dba_fetch("key2", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+bool(true)
+bool(true)
+bool(false)
+Content String 1
+Content String 2
diff --git a/ext/dba/tests/dba_db4_012.phpt b/ext/dba/tests/dba_db4_012.phpt
new file mode 100644
index 0000000..2caa43c
--- /dev/null
+++ b/ext/dba/tests/dba_db4_012.phpt
@@ -0,0 +1,31 @@
+--TEST--
+DBA DB4 New File Creation open("rl")
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file = dba_open($db_filename, "rl", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+
+Warning: dba_open(%stest0.dbm,rl): Driver initialization failed for handler: db4: No such file or directory in %sdba_db4_012.php on line %d
+Error creating %stest0.dbm
diff --git a/ext/dba/tests/dba_db4_013.phpt b/ext/dba/tests/dba_db4_013.phpt
new file mode 100644
index 0000000..ba2d171
--- /dev/null
+++ b/ext/dba/tests/dba_db4_013.phpt
@@ -0,0 +1,40 @@
+--TEST--
+DBA DB4 File open("rl") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_close($db_file);
+}
+
+if (($db_file = dba_popen($db_filename, "rl", $handler)) !== FALSE) {
+ echo "database file opened\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+database file opened
+
+Warning: dba_insert(): You cannot perform a modification to a database without proper access in %sdba_db4_013.php on line %d
diff --git a/ext/dba/tests/dba_db4_014.phpt b/ext/dba/tests/dba_db4_014.phpt
new file mode 100644
index 0000000..6fb22f8
--- /dev/null
+++ b/ext/dba/tests/dba_db4_014.phpt
@@ -0,0 +1,32 @@
+--TEST--
+DBA DB4 File open("wl") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file = dba_open($db_filename, "wl", $handler)) !== FALSE) {
+ echo "database file opened\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+
+Warning: dba_open(%stest0.dbm,wl): Driver initialization failed for handler: db4: No such file or directory in %sdba_db4_014.php on line %d
+Error creating %stest0.dbm
diff --git a/ext/dba/tests/dba_db4_015.phpt b/ext/dba/tests/dba_db4_015.phpt
new file mode 100644
index 0000000..a153567
--- /dev/null
+++ b/ext/dba/tests/dba_db4_015.phpt
@@ -0,0 +1,39 @@
+--TEST--
+DBA DB4 File open("wl") & Insert Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ echo "database file created\n";
+ dba_close($db_file);
+}
+
+if (($db_file = dba_popen($db_filename, "wl", $handler)) !== FALSE) {
+ echo "database file opened\n";
+ dba_insert("key1", "This is a test insert", $db_file);
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+database file opened
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_016.phpt b/ext/dba/tests/dba_db4_016.phpt
new file mode 100644
index 0000000..b79cc71
--- /dev/null
+++ b/ext/dba/tests/dba_db4_016.phpt
@@ -0,0 +1,59 @@
+--TEST--
+DBA DB4 File Creation popen("c") with existing valid file
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ var_dump(dba_insert("key1", "This is a test insert", $db_file));
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+// Now test reopening it
+if (($db_file = dba_popen($db_filename, "c", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ var_dump(dba_insert("key1", "second open test", $db_file));
+ var_dump(dba_insert("key2", "second open test row 2", $db_file));
+ echo dba_fetch("key1", $db_file), "\n";
+ echo dba_fetch("key2", $db_file), "\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+bool(true)
+This is a test insert
+database file created
+bool(false)
+bool(true)
+This is a test insert
+second open test row 2
diff --git a/ext/dba/tests/dba_db4_017.phpt b/ext/dba/tests/dba_db4_017.phpt
new file mode 100644
index 0000000..12bf3df
--- /dev/null
+++ b/ext/dba/tests/dba_db4_017.phpt
@@ -0,0 +1,37 @@
+--TEST--
+DBA DB4 file creation dba_open("cd")
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+if (($db_file = dba_open($db_filename, "cd", $handler)) !== FALSE) {
+ if (file_exists($db_filename)) {
+ echo "database file created\n";
+ var_dump(dba_insert("key1", "This is a test insert", $db_file));
+ echo dba_fetch("key1", $db_file), "\n";
+ dba_close($db_file);
+ } else {
+ echo "File did not get created\n";
+ }
+} else {
+ echo "Error creating $db_filename\n";
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+database file created
+bool(true)
+This is a test insert
diff --git a/ext/dba/tests/dba_db4_018.phpt b/ext/dba/tests/dba_db4_018.phpt
new file mode 100644
index 0000000..ecd1980
--- /dev/null
+++ b/ext/dba/tests/dba_db4_018.phpt
@@ -0,0 +1,76 @@
+--TEST--
+DBA DB4 with persistent connections
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+echo "Test 1\n";
+$db_file1 = dba_popen($db_filename, 'n', 'flatfile');
+dba_insert("key1", "This is a test insert 1", $db_file1);
+echo dba_fetch("key1", $db_file1), "\n";
+
+
+echo "Test 2\n";
+$db_file2 = dba_popen($db_filename, 'n', 'flatfile');
+if ($db_file1 === $db_file2) {
+ echo "resources are the same\n";
+} else {
+ echo "resources are different\n";
+}
+
+
+echo "Test 3 - fetch both rows from second resource\n";
+dba_insert("key2", "This is a test insert 2", $db_file2);
+echo dba_fetch("key1", $db_file2), "\n";
+echo dba_fetch("key2", $db_file2), "\n";
+
+
+echo "Test 4 - fetch both rows from first resource\n";
+echo dba_fetch("key1", $db_file1), "\n";
+echo dba_fetch("key2", $db_file1), "\n";
+
+echo "Test 5 - close 2nd resource\n";
+dba_close($db_file2);
+var_dump($db_file1);
+var_dump($db_file2);
+
+echo "Test 6 - query after closing 2nd resource\n";
+echo dba_fetch("key1", $db_file1), "\n";
+echo dba_fetch("key2", $db_file1), "\n";
+
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--XFAIL--
+Test 6 crashes with dba pointer of NULL, bug http://bugs.php.net/bug.php?id=51278
+--EXPECTF--
+database handler: db4
+Test 1
+This is a test insert 1
+Test 2
+resources are different
+Test 3 - fetch both rows from second resource
+This is a test insert 1
+This is a test insert 2
+Test 4 - fetch both rows from first resource
+This is a test insert 1
+This is a test insert 2
+Test 5 - close 2nd resource
+resource(%d) of type (dba persistent)
+resource(%d) of type (Unknown)
+Test 6 - query after closing 2nd resource
+This is a test insert 1
+This is a test insert 2
+===DONE===
diff --git a/ext/dba/tests/dba_db4_handlers.phpt b/ext/dba/tests/dba_db4_handlers.phpt
new file mode 100644
index 0000000..d238f43
--- /dev/null
+++ b/ext/dba/tests/dba_db4_handlers.phpt
@@ -0,0 +1,50 @@
+--TEST--
+DBA DB4 Handler Test
+--SKIPIF--
+<?php
+$handler="db4";
+require(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler="db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+function check($h)
+{
+ if (!$h) {
+ return;
+ }
+
+ foreach ($h as $key) {
+ if ($key === "db4") {
+ echo "Success: db4 enabled\n";
+ }
+ }
+}
+
+echo "Test 1\n";
+
+check(dba_handlers());
+
+echo "Test 2 - full info\n";
+$h = dba_handlers(1);
+foreach ($h as $key => $val) {
+ if ($key === "db4") {
+ echo "$val\n";
+ }
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTREGEX--
+database handler: db4
+Test 1
+Success: db4 enabled
+Test 2 - full info
+.*Berkeley DB (4|5).*
diff --git a/ext/dba/tests/dba_db4_optimize.phpt b/ext/dba/tests/dba_db4_optimize.phpt
new file mode 100644
index 0000000..de27dd8
--- /dev/null
+++ b/ext/dba/tests/dba_db4_optimize.phpt
@@ -0,0 +1,38 @@
+--TEST--
+DBA DB4 Optimize Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_filename, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ for ($i=1; $i<3; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ echo "\n";
+ var_dump(dba_optimize($db_file));
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+YY
+bool(true)
+===DONE===
diff --git a/ext/dba/tests/dba_db4_sync.phpt b/ext/dba/tests/dba_db4_sync.phpt
new file mode 100644
index 0000000..8c4e248
--- /dev/null
+++ b/ext/dba/tests/dba_db4_sync.phpt
@@ -0,0 +1,38 @@
+--TEST--
+DBA DB4 Sync Test
+--SKIPIF--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler = "db4";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_filename, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ for ($i=1; $i<3; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ echo "\n";
+ var_dump(dba_sync($db_file));
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: db4
+YY
+bool(true)
+===DONE===
diff --git a/ext/dba/tests/dba_dbm.phpt b/ext/dba/tests/dba_dbm.phpt
new file mode 100644
index 0000000..dd1fe1e
--- /dev/null
+++ b/ext/dba/tests/dba_dbm.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA DBM handler test
+--SKIPIF--
+<?php
+ $handler = 'dbm';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'dbm';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: dbm
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_flatfile.phpt b/ext/dba/tests/dba_flatfile.phpt
new file mode 100644
index 0000000..8e1ca6a
--- /dev/null
+++ b/ext/dba/tests/dba_flatfile.phpt
@@ -0,0 +1,50 @@
+--TEST--
+DBA FlatFile handler test
+--SKIPIF--
+<?php
+ $handler = 'flatfile';
+ require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+ $handler = 'flatfile';
+ require_once(dirname(__FILE__) .'/test.inc');
+ require_once(dirname(__FILE__) .'/dba_handler.inc');
+?>
+===DONE===
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+database handler: flatfile
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_gdbm.phpt b/ext/dba/tests/dba_gdbm.phpt
new file mode 100644
index 0000000..33d7d20
--- /dev/null
+++ b/ext/dba/tests/dba_gdbm.phpt
@@ -0,0 +1,34 @@
+--TEST--
+DBA GDBM handler test
+--SKIPIF--
+<?php
+ $handler = 'gdbm';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'gdbm';
+ require_once dirname(__FILE__) .'/test.inc';
+ $lock_flag = ''; // lock in library
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+
+ // Read during write is system dependant. Important is that there is no deadlock
+?>
+===DONE===
+--EXPECTF--
+database handler: gdbm
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write:%sallowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_handler.inc b/ext/dba/tests/dba_handler.inc
new file mode 100644
index 0000000..1c3f512
--- /dev/null
+++ b/ext/dba/tests/dba_handler.inc
@@ -0,0 +1,90 @@
+<?php
+
+echo "database handler: $handler\n";
+
+do {
+ if (($db_file = dba_open($db_filename, 'n'.$lock_flag, $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ dba_insert("key3", "Third Content String", $db_file);
+ dba_insert("key4", "Another Content String", $db_file);
+ dba_insert("key5", "The last content string", $db_file);
+ if ($handler != 'cdb') {
+ dba_delete("key3", $db_file);
+ dba_delete("key1", $db_file);
+ } else {
+ dba_close($db_file);
+ if (($db_file = dba_open($db_filename, 'r'.$lock_flag, $handler))===FALSE) {
+ echo "Error reopening database\n";
+ }
+ }
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ for ($i=1; $i<6; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ echo "\n";
+ echo dba_fetch("key2", $db_file)."\n";
+ if ($handler != 'cdb') {
+ dba_replace("key2", "Content 2 replaced", $db_file);
+ echo dba_fetch("key2", $db_file)."\n";
+ }
+ dba_close($db_file);
+ } else {
+ echo "Error creating database\n";
+ }
+ if ($handler != 'cdb') {
+ $db_writer = dba_open($db_filename, 'c'.$lock_flag, $handler);
+ if (($dba_reader = @dba_open($db_filename, 'r'.$lock_flag.($lock_flag ? 't' : ''), $handler))===false) {
+ echo "Read during write: not allowed\n";
+ } else {
+ echo "Read during write: allowed\n";
+ }
+ if ($db_writer!==FALSE) {
+ dba_insert("key number 6", "The 6th value", $db_writer);
+ @dba_insert("key number 6", "The 6th value inserted again would be an error", $db_writer);
+ dba_replace("key2", "Content 2 replaced 2nd time", $db_writer);
+ dba_delete("key4", $db_writer);
+ echo dba_fetch("key2", $db_writer)."\n";
+ echo dba_fetch("key number 6", $db_writer)."\n";
+ dba_close($db_writer); // when the writer is open at least db3 would fail because of buffered io.
+ } else {
+ die("Error reopening database\n");
+ }
+ }
+ if (($db_file = dba_open($db_filename, 'r'.$lock_flag, $handler))!==FALSE) {
+ $key = dba_firstkey($db_file);
+ $res = array();
+ while($key) {
+ $res[$key] = dba_fetch($key, $db_file);
+ $key = dba_nextkey($db_file);
+ }
+ ksort($res);
+ var_dump($res);
+ dba_close($db_file);
+ } else {
+ echo "Error reading database\n";
+ }
+ if (!empty($dba_reader)) {
+ dba_close($dba_reader);
+ }
+ if (($db_file = dba_popen($db_filename, 'r'.($lock_flag==''?'':'-'), $handler))!==FALSE) {
+ if ($handler == 'dbm') {
+ dba_close($db_file);
+ }
+ }
+
+ if ($lock_flag == '') {
+ break;
+ } else {
+ echo "--NO-LOCK--\n";
+ $lock_flag = '';
+ }
+} while(1);
+
+?> \ No newline at end of file
diff --git a/ext/dba/tests/dba_handlers.phpt b/ext/dba/tests/dba_handlers.phpt
new file mode 100644
index 0000000..9f66a79
--- /dev/null
+++ b/ext/dba/tests/dba_handlers.phpt
@@ -0,0 +1,69 @@
+--TEST--
+DBA Handler Test
+--SKIPIF--
+<?php
+$handler="flatfile";
+require(dirname(__FILE__) .'/skipif.inc');
+die("info $HND handler used");
+?>
+--FILE--
+<?php
+$handler="flatfile";
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+
+function check($h)
+{
+ if (!$h) {
+ return;
+ }
+
+ foreach ($h as $key) {
+ if ($key === "flatfile") {
+ echo "Success: flatfile enabled\n";
+ }
+ }
+}
+
+echo "Test 1\n";
+
+check(dba_handlers());
+
+echo "Test 2\n";
+
+check(dba_handlers(null));
+
+echo "Test 3\n";
+
+check(dba_handlers(1, 2));
+
+echo "Test 4\n";
+
+check(dba_handlers(0));
+
+echo "Test 5 - full info\n";
+$h = dba_handlers(1);
+foreach ($h as $key => $val) {
+ if ($key === "flatfile") {
+ echo "Success: flatfile enabled\n";
+ }
+}
+
+?>
+--CLEAN--
+<?php
+require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: flatfile
+Test 1
+Success: flatfile enabled
+Test 2
+Success: flatfile enabled
+Test 3
+
+Warning: dba_handlers() expects at most 1 parameter, 2 given in %sdba_handlers.php on line %d
+Test 4
+Success: flatfile enabled
+Test 5 - full info
+Success: flatfile enabled
diff --git a/ext/dba/tests/dba_inifile.phpt b/ext/dba/tests/dba_inifile.phpt
new file mode 100644
index 0000000..81ab738
--- /dev/null
+++ b/ext/dba/tests/dba_inifile.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA INIFILE handler test
+--SKIPIF--
+<?php
+ $handler = 'inifile';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'inifile';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: inifile
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_ndbm.phpt b/ext/dba/tests/dba_ndbm.phpt
new file mode 100644
index 0000000..b0f5542
--- /dev/null
+++ b/ext/dba/tests/dba_ndbm.phpt
@@ -0,0 +1,46 @@
+--TEST--
+DBA NDBM handler test
+--SKIPIF--
+<?php
+ $handler = 'ndbm';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'ndbm';
+ require_once dirname(__FILE__) .'/test.inc';
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: ndbm
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_optimize.phpt b/ext/dba/tests/dba_optimize.phpt
new file mode 100644
index 0000000..794d7e8
--- /dev/null
+++ b/ext/dba/tests/dba_optimize.phpt
@@ -0,0 +1,51 @@
+--TEST--
+DBA Optimize Test
+--SKIPIF--
+<?php
+ require_once dirname(__FILE__) .'/skipif.inc';
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_filename, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ for ($i=1; $i<3; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ echo "\n";
+ var_dump(dba_optimize());
+ var_dump(dba_optimize(""));
+ var_dump(dba_optimize($db_file));
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: flatfile
+2YY
+
+Warning: dba_optimize() expects exactly 1 parameter, 0 given in %sdba_optimize.php on line %d
+NULL
+
+Warning: dba_optimize() expects parameter 1 to be resource, string given in %sdba_optimize.php on line %d
+NULL
+bool(true)
+===DONE===
diff --git a/ext/dba/tests/dba_qdbm.phpt b/ext/dba/tests/dba_qdbm.phpt
new file mode 100644
index 0000000..ef216d9
--- /dev/null
+++ b/ext/dba/tests/dba_qdbm.phpt
@@ -0,0 +1,34 @@
+--TEST--
+DBA QDBM handler test
+--SKIPIF--
+<?php
+ $handler = 'qdbm';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'qdbm';
+ require_once dirname(__FILE__) .'/test.inc';
+ $lock_flag = ''; // lock in library
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECTF--
+database handler: qdbm
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write:%sallowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+
+Warning: dba_popen(%stest0.dbm,r-): Locking cannot be disabled for handler qdbm in %sdba_handler.inc on line %d
+===DONE===
diff --git a/ext/dba/tests/dba_split.phpt b/ext/dba/tests/dba_split.phpt
new file mode 100644
index 0000000..0989f09
--- /dev/null
+++ b/ext/dba/tests/dba_split.phpt
@@ -0,0 +1,83 @@
+--TEST--
+DBA Split Test
+--SKIPIF--
+<?php
+ require_once dirname(__FILE__) .'/skipif.inc';
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+var_dump(dba_key_split("key1", "name"));
+var_dump(dba_key_split(1));
+var_dump(dba_key_split(null));
+var_dump(dba_key_split(""));
+var_dump(dba_key_split("name1"));
+var_dump(dba_key_split("[key1"));
+var_dump(dba_key_split("[key1]"));
+var_dump(dba_key_split("key1]"));
+var_dump(dba_key_split("[key1]name1"));
+var_dump(dba_key_split("[key1]name1[key2]name2"));
+var_dump(dba_key_split("[key1]name1"));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+Warning: Wrong parameter count for dba_key_split() in %sdba_split.php on line %d
+NULL
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(1) "1"
+}
+bool(false)
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(0) ""
+}
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(5) "name1"
+}
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(5) "[key1"
+}
+array(2) {
+ [0]=>
+ string(4) "key1"
+ [1]=>
+ string(0) ""
+}
+array(2) {
+ [0]=>
+ string(0) ""
+ [1]=>
+ string(5) "key1]"
+}
+array(2) {
+ [0]=>
+ string(4) "key1"
+ [1]=>
+ string(5) "name1"
+}
+array(2) {
+ [0]=>
+ string(4) "key1"
+ [1]=>
+ string(16) "name1[key2]name2"
+}
+array(2) {
+ [0]=>
+ string(4) "key1"
+ [1]=>
+ string(5) "name1"
+}
+===DONE===
diff --git a/ext/dba/tests/dba_sync.phpt b/ext/dba/tests/dba_sync.phpt
new file mode 100644
index 0000000..e0906ee
--- /dev/null
+++ b/ext/dba/tests/dba_sync.phpt
@@ -0,0 +1,51 @@
+--TEST--
+DBA Sync Test
+--SKIPIF--
+<?php
+ require_once dirname(__FILE__) .'/skipif.inc';
+ die("info $HND handler used");
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) .'/test.inc');
+echo "database handler: $handler\n";
+if (($db_file=dba_open($db_filename, "n", $handler))!==FALSE) {
+ dba_insert("key1", "Content String 1", $db_file);
+ dba_insert("key2", "Content String 2", $db_file);
+ $a = dba_firstkey($db_file);
+ $i=0;
+ while($a) {
+ $a = dba_nextkey($db_file);
+ $i++;
+ }
+ echo $i;
+ for ($i=1; $i<3; $i++) {
+ echo dba_exists("key$i", $db_file) ? "Y" : "N";
+ }
+ echo "\n";
+ var_dump(dba_sync());
+ var_dump(dba_sync(""));
+ var_dump(dba_sync($db_file));
+ dba_close($db_file);
+} else {
+ echo "Error creating database\n";
+}
+
+?>
+===DONE===
+<?php exit(0); ?>
+--CLEAN--
+<?php
+ require(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECTF--
+database handler: flatfile
+2YY
+
+Warning: dba_sync() expects exactly 1 parameter, 0 given in %sdba_sync.php on line %d
+NULL
+
+Warning: dba_sync() expects parameter 1 to be resource, string given in %sdba_sync.php on line %d
+NULL
+bool(true)
+===DONE===
diff --git a/ext/dba/tests/dba_tcadb.phpt b/ext/dba/tests/dba_tcadb.phpt
new file mode 100644
index 0000000..52dd4de
--- /dev/null
+++ b/ext/dba/tests/dba_tcadb.phpt
@@ -0,0 +1,50 @@
+--TEST--
+DBA TCADB handler test
+--SKIPIF--
+<?php
+ $handler = 'tcadb';
+ require_once dirname(__FILE__) .'/skipif.inc';
+?>
+--FILE--
+<?php
+ $handler = 'tcadb';
+ require_once dirname(__FILE__) .'/skipif.inc';
+ $lock_flag = 'l';
+ $db_filename = $db_file = dirname(__FILE__) .'/test0.tch';
+ @unlink($db_filename);
+ @unlink($db_filename.'.lck');
+ require_once dirname(__FILE__) .'/dba_handler.inc';
+?>
+===DONE===
+--EXPECT--
+database handler: tcadb
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+--NO-LOCK--
+3NYNYY
+Content String 2
+Content 2 replaced
+Read during write: not allowed
+Content 2 replaced 2nd time
+The 6th value
+array(3) {
+ ["key number 6"]=>
+ string(13) "The 6th value"
+ ["key2"]=>
+ string(27) "Content 2 replaced 2nd time"
+ ["key5"]=>
+ string(23) "The last content string"
+}
+===DONE===
diff --git a/ext/dba/tests/skipif.inc b/ext/dba/tests/skipif.inc
new file mode 100644
index 0000000..e75000f
--- /dev/null
+++ b/ext/dba/tests/skipif.inc
@@ -0,0 +1,23 @@
+<?php
+ if (!extension_loaded('dba')) die('skip dba extension not available');
+ if (!function_exists('dba_handlers')) die ('skip dba_handlers() not available');
+ if (!sizeof(dba_handlers())) die('skip no handlers installed');
+ if (!isset($handler)) {
+ $handlers = dba_handlers();
+ if (in_array('flatfile', $handlers)) {
+ $handler = 'flatfile';
+ } else {
+ $handlers = array_diff($handlers, array('cdb', 'cdb_make')); /* these can only read OR write */
+ if (count($handlers)==0) {
+ die('skip no handler available that can be used for the test');
+ }
+ $handler = array_shift($handlers);
+ }
+ } else {
+ if (!in_array($handler, dba_handlers())) {
+ $HND = strtoupper($handler);
+ die("skip $HND handler not available");
+ }
+ }
+ $HND = strtoupper($handler);
+?>
diff --git a/ext/dba/tests/test.cdb b/ext/dba/tests/test.cdb
new file mode 100644
index 0000000..21529c6
--- /dev/null
+++ b/ext/dba/tests/test.cdb
Binary files differ
diff --git a/ext/dba/tests/test.inc b/ext/dba/tests/test.inc
new file mode 100644
index 0000000..7c4e207
--- /dev/null
+++ b/ext/dba/tests/test.inc
@@ -0,0 +1,7 @@
+<?php
+ require_once dirname(__FILE__) .'/skipif.inc';
+ $lock_flag = 'l';
+ $db_filename = $db_file = dirname(__FILE__) .'/test0.dbm';
+ @unlink($db_filename);
+ @unlink($db_filename.'.lck');
+?>