Back to index

php5  5.3.10
cdb.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2010 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    | Author: Marcus Boerger <helly@php.net>                               |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: cdb.c 293036 2010-01-03 09:23:27Z sebastian $ */
00020 
00021 /* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #include "php.h"
00028 
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #ifndef PHP_WIN32
00032 #include <sys/mman.h>
00033 #endif
00034 #ifdef HAVE_UNISTD_H
00035 #include <unistd.h>
00036 #endif
00037 #include <string.h>
00038 #include <errno.h>
00039 #include "cdb.h"
00040 
00041 #ifndef EPROTO
00042 # define EPROTO -15  /* cdb 0.75's default for PROTOless systems */
00043 #endif
00044 
00045 /* {{{ cdb_match */
00046 static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos TSRMLS_DC)
00047 {
00048        char buf[32];
00049        unsigned int n;
00050 
00051        while (len > 0) {
00052               n = sizeof(buf);
00053               if (n > len) 
00054                      n = len;
00055               if (cdb_read(c, buf, n, pos TSRMLS_CC) == -1) 
00056                      return -1;
00057               if (memcmp(buf, key, n)) 
00058                      return 0;
00059               pos += n;
00060               key += n;
00061               len -= n;
00062        }
00063        return 1;
00064 }
00065 /* }}} */
00066 
00067 /* {{{ cdb_hash */
00068 uint32 cdb_hash(char *buf, unsigned int len)
00069 {
00070        uint32 h;
00071        const unsigned char * b = (unsigned char *)buf;
00072 
00073        h = CDB_HASHSTART;
00074        while (len--) {
00075               h = ( h + (h << 5)) ^ (*b++);
00076        }
00077        return h;
00078 }
00079 /* }}} */
00080 
00081 /* {{{ cdb_free */
00082 void cdb_free(struct cdb *c TSRMLS_DC)
00083 {
00084 }
00085 /* }}} */
00086 
00087 /* {{{ cdb_findstart */
00088 void cdb_findstart(struct cdb *c TSRMLS_DC)
00089 {
00090        c->loop = 0;
00091 }
00092 /* }}} */
00093 
00094 /* {{{ cdb_init */
00095 void cdb_init(struct cdb *c, php_stream *fp TSRMLS_DC)
00096 {
00097        cdb_free(c TSRMLS_CC);
00098        cdb_findstart(c TSRMLS_CC);
00099        c->fp = fp;
00100 }
00101 /* }}} */
00102 
00103 /* {{{ cdb_read */
00104 int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos TSRMLS_DC)
00105 {
00106        if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) {
00107               errno = EPROTO;
00108               return -1;
00109        }
00110        while (len > 0) {
00111               int r;
00112               do {
00113                      r = php_stream_read(c->fp, buf, len);
00114               } while ((r == -1) && (errno == EINTR));
00115               if (r == -1) 
00116                      return -1;
00117               if (r == 0) {
00118                      errno = EPROTO;
00119                      return -1;
00120               }
00121               buf += r;
00122               len -= r;
00123        }
00124        return 0;
00125 }
00126 /* }}} */
00127 
00128 /* {{{ cdb_findnext */
00129 int cdb_findnext(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
00130 {
00131        char buf[8];
00132        uint32 pos;
00133        uint32 u;
00134 
00135        if (!c->loop) {
00136               u = cdb_hash(key, len);
00137               if (cdb_read(c, buf, 8, (u << 3) & 2047 TSRMLS_CC) == -1) 
00138                      return -1;
00139               uint32_unpack(buf + 4,&c->hslots);
00140               if (!c->hslots) 
00141                      return 0;
00142               uint32_unpack(buf, &c->hpos);
00143               c->khash = u;
00144               u >>= 8;
00145               u %= c->hslots;
00146               u <<= 3;
00147               c->kpos = c->hpos + u;
00148        }
00149 
00150        while (c->loop < c->hslots) {
00151               if (cdb_read(c, buf, 8, c->kpos TSRMLS_CC) == -1) 
00152                      return -1;
00153               uint32_unpack(buf + 4, &pos);
00154               if (!pos) 
00155                      return 0;
00156               c->loop += 1;
00157               c->kpos += 8;
00158               if (c->kpos == c->hpos + (c->hslots << 3)) 
00159                      c->kpos = c->hpos;
00160               uint32_unpack(buf, &u);
00161               if (u == c->khash) {
00162                      if (cdb_read(c, buf, 8, pos TSRMLS_CC) == -1) 
00163                             return -1;
00164                      uint32_unpack(buf, &u);
00165                      if (u == len)
00166                      switch(cdb_match(c, key, len, pos + 8 TSRMLS_CC)) {
00167                      case -1:
00168                             return -1;
00169                      case 1:
00170                             uint32_unpack(buf + 4, &c->dlen);
00171                             c->dpos = pos + 8 + len;
00172                             return 1;
00173                      }
00174               }
00175        }
00176 
00177        return 0;
00178 }
00179 /* }}} */
00180 
00181 /* {{{ cdb_find */
00182 int cdb_find(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
00183 {
00184        cdb_findstart(c TSRMLS_CC);
00185        return cdb_findnext(c, key, len TSRMLS_CC);
00186 }
00187 /* }}} */
00188 
00189 /* {{{ cdb_version */
00190 char *cdb_version() 
00191 {
00192        return "0.75, $Revision: 293036 $";
00193 }
00194 /* }}} */