summaryrefslogtreecommitdiff
path: root/ext/dba/dba_cdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dba/dba_cdb.c')
-rw-r--r--ext/dba/dba_cdb.c350
1 files changed, 350 insertions, 0 deletions
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
+ */