Back to index

php5  5.3.10
dba_cdb.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Sascha Schumann <sascha@schumann.cx>                        |
00016    |          Marcus Boerger <helly@php.net>                              |
00017    +----------------------------------------------------------------------+
00018  */
00019 
00020 /* $Id: dba_cdb.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 
00026 #include "php.h"
00027 
00028 #if DBA_CDB
00029 #include "php_cdb.h"
00030 
00031 #include <sys/types.h>
00032 #ifdef HAVE_UNISTD_H
00033 #include <unistd.h>
00034 #endif
00035 #include <fcntl.h>
00036 
00037 #if DBA_CDB_BUILTIN
00038 # include "libcdb/cdb.h"
00039 # include "libcdb/cdb_make.h"
00040 # include "libcdb/uint32.h"
00041 #else
00042 # ifdef CDB_INCLUDE_FILE
00043 #  include CDB_INCLUDE_FILE
00044 # endif
00045 #endif
00046 
00047 #define CDB_INFO \
00048        dba_cdb *cdb = (dba_cdb *) info->dbf
00049 
00050 typedef struct {
00051        struct cdb c;
00052 #if DBA_CDB_BUILTIN
00053        struct cdb_make m;
00054        php_stream *file;
00055        int make;
00056 #else
00057        int file;
00058 #endif
00059        uint32 eod; /* size of constant database */
00060        uint32 pos; /* current position for traversing */
00061 } dba_cdb;
00062 
00063 DBA_OPEN_FUNC(cdb)
00064 {
00065 #if DBA_CDB_BUILTIN
00066        php_stream* file = 0;
00067        int make;
00068 #else
00069        int file = 0;
00070 #endif
00071        dba_cdb *cdb;
00072        dba_info *pinfo = (dba_info *) info;
00073 
00074        switch (info->mode) {
00075               case DBA_READER: 
00076 #if DBA_CDB_BUILTIN
00077                      make = 0;
00078                      file = info->fp;
00079 #else
00080                      file = VCWD_OPEN(info->path, O_RDONLY);
00081                      if (file < 0) {
00082                             *error = "Unable to open file";
00083                             return FAILURE;
00084                      }
00085 #endif
00086                      break;
00087 #if DBA_CDB_BUILTIN
00088               case DBA_TRUNC:
00089                      make = 1;
00090                      file = info->fp;
00091                      break;
00092               case DBA_CREAT:
00093               case DBA_WRITER:
00094                      *error = "Update operations are not supported";
00095                      return FAILURE; /* not supported */
00096 #endif
00097               default: 
00098                      *error = "Currently not supported";
00099                      return FAILURE;
00100        }
00101 
00102        cdb = pemalloc(sizeof(dba_cdb), info->flags&DBA_PERSISTENT);
00103        memset(cdb, 0, sizeof(dba_cdb));
00104 
00105 #if DBA_CDB_BUILTIN
00106        if (make) {
00107               cdb_make_start(&cdb->m, file TSRMLS_CC);
00108        } else {
00109               cdb_init(&cdb->c, file TSRMLS_CC);
00110        }
00111        cdb->make = make;
00112 #else
00113        cdb_init(&cdb->c, file);
00114 #endif
00115        cdb->file = file;
00116        
00117        pinfo->dbf = cdb;
00118        return SUCCESS;
00119 }
00120 
00121 DBA_CLOSE_FUNC(cdb)
00122 {
00123        CDB_INFO;
00124 
00125        /* cdb_free does not close associated file */
00126 #if DBA_CDB_BUILTIN
00127        if (cdb->make) {
00128               cdb_make_finish(&cdb->m TSRMLS_CC);
00129        } else {
00130               cdb_free(&cdb->c TSRMLS_CC);
00131        }
00132 #else
00133        cdb_free(&cdb->c);
00134        close(cdb->file);
00135 #endif
00136        pefree(cdb, info->flags&DBA_PERSISTENT);
00137 }
00138 
00139 #if DBA_CDB_BUILTIN
00140 # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos TSRMLS_CC)
00141 # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len TSRMLS_CC)
00142 # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len TSRMLS_CC)
00143 #else
00144 # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos)
00145 # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len)
00146 # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len)
00147 #endif
00148 
00149 DBA_FETCH_FUNC(cdb)
00150 {
00151        CDB_INFO;
00152        unsigned int len;
00153        char *new_entry = NULL;
00154        
00155 #if DBA_CDB_BUILTIN
00156        if (cdb->make)
00157               return NULL; /* database was opened writeonly */
00158 #endif
00159        if (php_cdb_find(&cdb->c, key, keylen) == 1) {
00160               while(skip--) {
00161                      if (php_cdb_findnext(&cdb->c, key, keylen) != 1) {
00162                             return NULL;
00163                      }
00164               }
00165               len = cdb_datalen(&cdb->c);
00166               new_entry = safe_emalloc(len, 1, 1);
00167               
00168               if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) {
00169                      efree(new_entry);
00170                      return NULL;
00171               }
00172               new_entry[len] = 0;
00173               if (newlen) 
00174                      *newlen = len;
00175        }
00176        
00177        return new_entry;
00178 }
00179 
00180 DBA_UPDATE_FUNC(cdb)
00181 {
00182 #if DBA_CDB_BUILTIN
00183        CDB_INFO;
00184 
00185        if (!cdb->make)
00186               return FAILURE; /* database was opened readonly */
00187        if (!mode)
00188               return FAILURE; /* cdb_make dosn't know replace */
00189        if (cdb_make_add(&cdb->m, key, keylen, val, vallen TSRMLS_CC) != -1)
00190               return SUCCESS;
00191 #endif
00192        return FAILURE;
00193 }
00194 
00195 DBA_EXISTS_FUNC(cdb)
00196 {
00197        CDB_INFO;
00198 
00199 #if DBA_CDB_BUILTIN
00200        if (cdb->make)
00201               return FAILURE; /* database was opened writeonly */
00202 #endif
00203        if (php_cdb_find(&cdb->c, key, keylen) == 1)
00204               return SUCCESS;
00205        return FAILURE;
00206 }
00207 
00208 DBA_DELETE_FUNC(cdb)
00209 {
00210        return FAILURE; /* cdb doesn't support delete */
00211 }
00212 
00213 /* {{{ cdb_file_read */
00214 #if DBA_CDB_BUILTIN
00215 # define cdb_file_read(fildes, buf, size) php_stream_read(fildes, buf, size)
00216 #else
00217 # define cdb_file_read(fildes, buf, size) read(fildes, buf, size)
00218 #endif
00219 /* }}} */
00220 
00221 #define CREAD(n) do { \
00222        if (cdb_file_read(cdb->file, buf, n) < n) return NULL; \
00223 } while (0)
00224 
00225 /* {{{ cdb_file_lseek 
00226  php_stream_seek does not return actual position */
00227 #if DBA_CDB_BUILTIN
00228 int cdb_file_lseek(php_stream *fp, off_t offset, int whence TSRMLS_DC) {
00229        php_stream_seek(fp, offset, whence);
00230        return php_stream_tell(fp);
00231 }
00232 #else
00233 int cdb_file_lseek(int fd, off_t offset, int whence TSRMLS_DC) {
00234        return lseek(fd, offset, whence);
00235 }
00236 #endif
00237 /* }}} */
00238 
00239 #define CSEEK(n) do { \
00240        if (n >= cdb->eod) return NULL; \
00241        if (cdb_file_lseek(cdb->file, (off_t)n, SEEK_SET TSRMLS_CC) != (off_t) n) return NULL; \
00242 } while (0)
00243 
00244 
00245 DBA_FIRSTKEY_FUNC(cdb)
00246 {
00247        CDB_INFO;
00248        uint32 klen, dlen;
00249        char buf[8];
00250        char *key;
00251 
00252 #if DBA_CDB_BUILTIN
00253        if (cdb->make)
00254               return NULL; /* database was opened writeonly */
00255 #endif
00256 
00257        cdb->eod = -1;
00258        CSEEK(0);
00259        CREAD(4);
00260        
00261        /* Total length of file in bytes */
00262        uint32_unpack(buf, &cdb->eod);
00263        
00264        CSEEK(2048);
00265        CREAD(8);
00266        
00267        /* The first four bytes contain the length of the key */
00268        uint32_unpack(buf, &klen);
00269        uint32_unpack(buf + 4, &dlen);
00270 
00271        key = safe_emalloc(klen, 1, 1);
00272        if (cdb_file_read(cdb->file, key, klen) < klen) {
00273               efree(key);
00274               key = NULL;
00275        } else {
00276               key[klen] = '\0';
00277               if (newlen) *newlen = klen;
00278        }
00279 
00280        /*       header + klenlen + dlenlen + klen + dlen */
00281        cdb->pos = 2048 + 4       + 4       + klen + dlen;
00282               
00283        return key;
00284 }
00285 
00286 DBA_NEXTKEY_FUNC(cdb)
00287 {
00288        CDB_INFO;
00289        uint32 klen, dlen;
00290        char buf[8];
00291        char *key;
00292 
00293 #if DBA_CDB_BUILTIN
00294        if (cdb->make)
00295               return NULL; /* database was opened writeonly */
00296 #endif
00297 
00298        CSEEK(cdb->pos);
00299        CREAD(8);
00300        uint32_unpack(buf, &klen);
00301        uint32_unpack(buf + 4, &dlen);
00302        
00303        key = safe_emalloc(klen, 1, 1);
00304        if (cdb_file_read(cdb->file, key, klen) < klen) {
00305               efree(key);
00306               key = NULL;
00307        } else {
00308               key[klen] = '\0';
00309               if (newlen) *newlen = klen;
00310        }
00311        
00312        cdb->pos += 8 + klen + dlen;
00313        
00314        return key;
00315 }
00316 
00317 DBA_OPTIMIZE_FUNC(cdb)
00318 {
00319        return SUCCESS;
00320 }
00321 
00322 DBA_SYNC_FUNC(cdb)
00323 {
00324        /* this is read-only */
00325        return SUCCESS;
00326 }
00327 
00328 DBA_INFO_FUNC(cdb)
00329 {
00330 #if DBA_CDB_BUILTIN
00331        if (!strcmp(hnd->name, "cdb")) {
00332               return estrdup(cdb_version());
00333        } else {
00334               return estrdup(cdb_make_version());
00335        }
00336 #else
00337        return estrdup("External");
00338 #endif
00339 }
00340 
00341 #endif
00342 
00343 /*
00344  * Local variables:
00345  * tab-width: 4
00346  * c-basic-offset: 4
00347  * End:
00348  * vim600: sw=4 ts=4 fdm=marker
00349  * vim<600: sw=4 ts=4
00350  */