1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Marcus Boerger <helly@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: cdb.c 276986 2009-03-10 23:40:06Z helly $ */
20 :
21 : /* incorporated from D.J.Bernstein's cdb-0.75 (http://cr.yp.to/cdb.html)*/
22 :
23 : #ifdef HAVE_CONFIG_H
24 : #include "config.h"
25 : #endif
26 :
27 : #include "php.h"
28 :
29 : #include <sys/types.h>
30 : #include <sys/stat.h>
31 : #ifndef PHP_WIN32
32 : #include <sys/mman.h>
33 : #endif
34 : #ifdef HAVE_UNISTD_H
35 : #include <unistd.h>
36 : #endif
37 : #include <string.h>
38 : #include <errno.h>
39 : #include "cdb.h"
40 :
41 : #ifndef EPROTO
42 : # define EPROTO -15 /* cdb 0.75's default for PROTOless systems */
43 : #endif
44 :
45 : /* {{{ cdb_match */
46 : static int cdb_match(struct cdb *c, char *key, unsigned int len, uint32 pos TSRMLS_DC)
47 52 : {
48 : char buf[32];
49 : unsigned int n;
50 :
51 156 : while (len > 0) {
52 52 : n = sizeof(buf);
53 52 : if (n > len)
54 52 : n = len;
55 52 : if (cdb_read(c, buf, n, pos TSRMLS_CC) == -1)
56 0 : return -1;
57 52 : if (memcmp(buf, key, n))
58 0 : return 0;
59 52 : pos += n;
60 52 : key += n;
61 52 : len -= n;
62 : }
63 52 : return 1;
64 : }
65 : /* }}} */
66 :
67 : /* {{{ cdb_hash */
68 : uint32 cdb_hash(char *buf, unsigned int len)
69 69 : {
70 : uint32 h;
71 69 : const unsigned char * b = (unsigned char *)buf;
72 :
73 69 : h = CDB_HASHSTART;
74 306 : while (len--) {
75 168 : h = ( h + (h << 5)) ^ (*b++);
76 : }
77 69 : return h;
78 : }
79 : /* }}} */
80 :
81 : /* {{{ cdb_free */
82 : void cdb_free(struct cdb *c TSRMLS_DC)
83 14 : {
84 14 : }
85 : /* }}} */
86 :
87 : /* {{{ cdb_findstart */
88 : void cdb_findstart(struct cdb *c TSRMLS_DC)
89 58 : {
90 58 : c->loop = 0;
91 58 : }
92 : /* }}} */
93 :
94 : /* {{{ cdb_init */
95 : void cdb_init(struct cdb *c, php_stream *fp TSRMLS_DC)
96 7 : {
97 7 : cdb_free(c TSRMLS_CC);
98 7 : cdb_findstart(c TSRMLS_CC);
99 7 : c->fp = fp;
100 7 : }
101 : /* }}} */
102 :
103 : /* {{{ cdb_read */
104 : int cdb_read(struct cdb *c, char *buf, unsigned int len, uint32 pos TSRMLS_DC)
105 241 : {
106 241 : if (php_stream_seek(c->fp, pos, SEEK_SET) == -1) {
107 0 : errno = EPROTO;
108 0 : return -1;
109 : }
110 723 : while (len > 0) {
111 : int r;
112 : do {
113 241 : r = php_stream_read(c->fp, buf, len);
114 241 : } while ((r == -1) && (errno == EINTR));
115 241 : if (r == -1)
116 0 : return -1;
117 241 : if (r == 0) {
118 0 : errno = EPROTO;
119 0 : return -1;
120 : }
121 241 : buf += r;
122 241 : len -= r;
123 : }
124 241 : return 0;
125 : }
126 : /* }}} */
127 :
128 : /* {{{ cdb_findnext */
129 : int cdb_findnext(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
130 55 : {
131 : char buf[8];
132 : uint32 pos;
133 : uint32 u;
134 :
135 55 : if (!c->loop) {
136 51 : u = cdb_hash(key, len);
137 51 : if (cdb_read(c, buf, 8, (u << 3) & 2047 TSRMLS_CC) == -1)
138 0 : return -1;
139 51 : uint32_unpack(buf + 4,&c->hslots);
140 51 : if (!c->hslots)
141 3 : return 0;
142 48 : uint32_unpack(buf, &c->hpos);
143 48 : c->khash = u;
144 48 : u >>= 8;
145 48 : u %= c->hslots;
146 48 : u <<= 3;
147 48 : c->kpos = c->hpos + u;
148 : }
149 :
150 104 : while (c->loop < c->hslots) {
151 52 : if (cdb_read(c, buf, 8, c->kpos TSRMLS_CC) == -1)
152 0 : return -1;
153 52 : uint32_unpack(buf + 4, &pos);
154 52 : if (!pos)
155 0 : return 0;
156 52 : c->loop += 1;
157 52 : c->kpos += 8;
158 52 : if (c->kpos == c->hpos + (c->hslots << 3))
159 31 : c->kpos = c->hpos;
160 52 : uint32_unpack(buf, &u);
161 52 : if (u == c->khash) {
162 52 : if (cdb_read(c, buf, 8, pos TSRMLS_CC) == -1)
163 0 : return -1;
164 52 : uint32_unpack(buf, &u);
165 52 : if (u == len)
166 52 : switch(cdb_match(c, key, len, pos + 8 TSRMLS_CC)) {
167 : case -1:
168 0 : return -1;
169 : case 1:
170 52 : uint32_unpack(buf + 4, &c->dlen);
171 52 : c->dpos = pos + 8 + len;
172 52 : return 1;
173 : }
174 : }
175 : }
176 :
177 0 : return 0;
178 : }
179 : /* }}} */
180 :
181 : /* {{{ cdb_find */
182 : int cdb_find(struct cdb *c, char *key, unsigned int len TSRMLS_DC)
183 51 : {
184 51 : cdb_findstart(c TSRMLS_CC);
185 51 : return cdb_findnext(c, key, len TSRMLS_CC);
186 : }
187 : /* }}} */
188 :
189 : /* {{{ cdb_version */
190 : char *cdb_version()
191 0 : {
192 0 : return "0.75, $Revision: 276986 $";
193 : }
194 : /* }}} */
|