1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
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 : | Authors: Sascha Schumann <sascha@schumann.cx> |
16 : | Marcus Boerger <helly@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: dba_cdb.c 272374 2008-12-31 11:17:49Z sebastian $ */
21 :
22 : #ifdef HAVE_CONFIG_H
23 : #include "config.h"
24 : #endif
25 :
26 : #include "php.h"
27 :
28 : #if DBA_CDB
29 : #include "php_cdb.h"
30 :
31 : #include <sys/types.h>
32 : #ifdef HAVE_UNISTD_H
33 : #include <unistd.h>
34 : #endif
35 : #include <fcntl.h>
36 :
37 : #if DBA_CDB_BUILTIN
38 : # include "libcdb/cdb.h"
39 : # include "libcdb/cdb_make.h"
40 : # include "libcdb/uint32.h"
41 : #else
42 : # ifdef CDB_INCLUDE_FILE
43 : # include CDB_INCLUDE_FILE
44 : # endif
45 : #endif
46 :
47 : #define CDB_INFO \
48 : dba_cdb *cdb = (dba_cdb *) info->dbf
49 :
50 : typedef struct {
51 : struct cdb c;
52 : #if DBA_CDB_BUILTIN
53 : struct cdb_make m;
54 : php_stream *file;
55 : int make;
56 : #else
57 : int file;
58 : #endif
59 : uint32 eod; /* size of constant database */
60 : uint32 pos; /* current position for traversing */
61 : } dba_cdb;
62 :
63 : DBA_OPEN_FUNC(cdb)
64 10 : {
65 : #if DBA_CDB_BUILTIN
66 10 : php_stream* file = 0;
67 : int make;
68 : #else
69 : int file = 0;
70 : #endif
71 : dba_cdb *cdb;
72 10 : dba_info *pinfo = (dba_info *) info;
73 :
74 10 : switch (info->mode) {
75 : case DBA_READER:
76 : #if DBA_CDB_BUILTIN
77 7 : make = 0;
78 7 : file = info->fp;
79 : #else
80 : file = VCWD_OPEN(info->path, O_RDONLY);
81 : if (file < 0) {
82 : *error = "Unable to open file";
83 : return FAILURE;
84 : }
85 : #endif
86 7 : break;
87 : #if DBA_CDB_BUILTIN
88 : case DBA_TRUNC:
89 3 : make = 1;
90 3 : file = info->fp;
91 3 : break;
92 : case DBA_CREAT:
93 : case DBA_WRITER:
94 0 : *error = "Update operations are not supported";
95 0 : return FAILURE; /* not supported */
96 : #endif
97 : default:
98 0 : *error = "Currently not supported";
99 0 : return FAILURE;
100 : }
101 :
102 10 : cdb = pemalloc(sizeof(dba_cdb), info->flags&DBA_PERSISTENT);
103 10 : memset(cdb, 0, sizeof(dba_cdb));
104 :
105 : #if DBA_CDB_BUILTIN
106 10 : if (make) {
107 3 : cdb_make_start(&cdb->m, file TSRMLS_CC);
108 : } else {
109 7 : cdb_init(&cdb->c, file TSRMLS_CC);
110 : }
111 10 : cdb->make = make;
112 : #else
113 : cdb_init(&cdb->c, file);
114 : #endif
115 10 : cdb->file = file;
116 :
117 10 : pinfo->dbf = cdb;
118 10 : return SUCCESS;
119 : }
120 :
121 : DBA_CLOSE_FUNC(cdb)
122 10 : {
123 10 : CDB_INFO;
124 :
125 : /* cdb_free does not close associated file */
126 : #if DBA_CDB_BUILTIN
127 10 : if (cdb->make) {
128 3 : cdb_make_finish(&cdb->m TSRMLS_CC);
129 : } else {
130 7 : cdb_free(&cdb->c TSRMLS_CC);
131 : }
132 : #else
133 : cdb_free(&cdb->c);
134 : close(cdb->file);
135 : #endif
136 10 : pefree(cdb, info->flags&DBA_PERSISTENT);
137 10 : }
138 :
139 : #if DBA_CDB_BUILTIN
140 : # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos TSRMLS_CC)
141 : # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len TSRMLS_CC)
142 : # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len TSRMLS_CC)
143 : #else
144 : # define php_cdb_read(cdb, buf, len, pos) cdb_read(cdb, buf, len, pos)
145 : # define php_cdb_findnext(cdb, key, len) cdb_findnext(cdb, key, len)
146 : # define php_cdb_find(cdb, key, len) cdb_find(cdb, key, len)
147 : #endif
148 :
149 : DBA_FETCH_FUNC(cdb)
150 34 : {
151 34 : CDB_INFO;
152 : unsigned int len;
153 34 : char *new_entry = NULL;
154 :
155 : #if DBA_CDB_BUILTIN
156 34 : if (cdb->make)
157 0 : return NULL; /* database was opened writeonly */
158 : #endif
159 34 : if (php_cdb_find(&cdb->c, key, keylen) == 1) {
160 72 : while(skip--) {
161 4 : if (php_cdb_findnext(&cdb->c, key, keylen) != 1) {
162 0 : return NULL;
163 : }
164 : }
165 34 : len = cdb_datalen(&cdb->c);
166 34 : new_entry = safe_emalloc(len, 1, 1);
167 :
168 34 : if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) {
169 0 : efree(new_entry);
170 0 : return NULL;
171 : }
172 34 : new_entry[len] = 0;
173 34 : if (newlen)
174 34 : *newlen = len;
175 : }
176 :
177 34 : return new_entry;
178 : }
179 :
180 : DBA_UPDATE_FUNC(cdb)
181 17 : {
182 : #if DBA_CDB_BUILTIN
183 17 : CDB_INFO;
184 :
185 17 : if (!cdb->make)
186 0 : return FAILURE; /* database was opened readonly */
187 17 : if (!mode)
188 0 : return FAILURE; /* cdb_make dosn't know replace */
189 17 : if (cdb_make_add(&cdb->m, key, keylen, val, vallen TSRMLS_CC) != -1)
190 17 : return SUCCESS;
191 : #endif
192 0 : return FAILURE;
193 : }
194 :
195 : DBA_EXISTS_FUNC(cdb)
196 17 : {
197 17 : CDB_INFO;
198 :
199 : #if DBA_CDB_BUILTIN
200 17 : if (cdb->make)
201 0 : return FAILURE; /* database was opened writeonly */
202 : #endif
203 17 : if (php_cdb_find(&cdb->c, key, keylen) == 1)
204 14 : return SUCCESS;
205 3 : return FAILURE;
206 : }
207 :
208 : DBA_DELETE_FUNC(cdb)
209 0 : {
210 0 : return FAILURE; /* cdb doesn't support delete */
211 : }
212 :
213 : /* {{{ cdb_file_read */
214 : #if DBA_CDB_BUILTIN
215 : # define cdb_file_read(fildes, buf, size) php_stream_read(fildes, buf, size)
216 : #else
217 : # define cdb_file_read(fildes, buf, size) read(fildes, buf, size)
218 : #endif
219 : /* }}} */
220 :
221 : #define CREAD(n) do { \
222 : if (cdb_file_read(cdb->file, buf, n) < n) return NULL; \
223 : } while (0)
224 :
225 : /* {{{ cdb_file_lseek
226 : php_stream_seek does not return actual position */
227 : #if DBA_CDB_BUILTIN
228 32 : int cdb_file_lseek(php_stream *fp, off_t offset, int whence TSRMLS_DC) {
229 32 : php_stream_seek(fp, offset, whence);
230 32 : return php_stream_tell(fp);
231 : }
232 : #else
233 : int cdb_file_lseek(int fd, off_t offset, int whence TSRMLS_DC) {
234 : return lseek(fd, offset, whence);
235 : }
236 : #endif
237 : /* }}} */
238 :
239 : #define CSEEK(n) do { \
240 : if (n >= cdb->eod) return NULL; \
241 : if (cdb_file_lseek(cdb->file, (off_t)n, SEEK_SET TSRMLS_CC) != (off_t) n) return NULL; \
242 : } while (0)
243 :
244 :
245 : DBA_FIRSTKEY_FUNC(cdb)
246 5 : {
247 5 : CDB_INFO;
248 : uint32 klen, dlen;
249 : char buf[8];
250 : char *key;
251 :
252 : #if DBA_CDB_BUILTIN
253 5 : if (cdb->make)
254 0 : return NULL; /* database was opened writeonly */
255 : #endif
256 :
257 5 : cdb->eod = -1;
258 5 : CSEEK(0);
259 5 : CREAD(4);
260 :
261 : /* Total length of file in bytes */
262 5 : uint32_unpack(buf, &cdb->eod);
263 :
264 5 : CSEEK(2048);
265 5 : CREAD(8);
266 :
267 : /* The first four bytes contain the length of the key */
268 5 : uint32_unpack(buf, &klen);
269 5 : uint32_unpack(buf + 4, &dlen);
270 :
271 5 : key = safe_emalloc(klen, 1, 1);
272 5 : if (cdb_file_read(cdb->file, key, klen) < klen) {
273 0 : efree(key);
274 0 : key = NULL;
275 : } else {
276 5 : key[klen] = '\0';
277 5 : if (newlen) *newlen = klen;
278 : }
279 :
280 : /* header + klenlen + dlenlen + klen + dlen */
281 5 : cdb->pos = 2048 + 4 + 4 + klen + dlen;
282 :
283 5 : return key;
284 : }
285 :
286 : DBA_NEXTKEY_FUNC(cdb)
287 27 : {
288 27 : CDB_INFO;
289 : uint32 klen, dlen;
290 : char buf[8];
291 : char *key;
292 :
293 : #if DBA_CDB_BUILTIN
294 27 : if (cdb->make)
295 0 : return NULL; /* database was opened writeonly */
296 : #endif
297 :
298 27 : CSEEK(cdb->pos);
299 22 : CREAD(8);
300 22 : uint32_unpack(buf, &klen);
301 22 : uint32_unpack(buf + 4, &dlen);
302 :
303 22 : key = safe_emalloc(klen, 1, 1);
304 22 : if (cdb_file_read(cdb->file, key, klen) < klen) {
305 0 : efree(key);
306 0 : key = NULL;
307 : } else {
308 22 : key[klen] = '\0';
309 22 : if (newlen) *newlen = klen;
310 : }
311 :
312 22 : cdb->pos += 8 + klen + dlen;
313 :
314 22 : return key;
315 : }
316 :
317 : DBA_OPTIMIZE_FUNC(cdb)
318 0 : {
319 0 : return SUCCESS;
320 : }
321 :
322 : DBA_SYNC_FUNC(cdb)
323 0 : {
324 : /* this is read-only */
325 0 : return SUCCESS;
326 : }
327 :
328 : DBA_INFO_FUNC(cdb)
329 0 : {
330 : #if DBA_CDB_BUILTIN
331 0 : if (!strcmp(hnd->name, "cdb")) {
332 0 : return estrdup(cdb_version());
333 : } else {
334 0 : return estrdup(cdb_make_version());
335 : }
336 : #else
337 : return estrdup("External");
338 : #endif
339 : }
340 :
341 : #endif
342 :
343 : /*
344 : * Local variables:
345 : * tab-width: 4
346 : * c-basic-offset: 4
347 : * End:
348 : * vim600: sw=4 ts=4 fdm=marker
349 : * vim<600: sw=4 ts=4
350 : */
|