![]() ![]() | ![]() |
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.4 ! misho 5: | Copyright (c) 1997-2014 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 20: /* $Id$ */
1.1 misho 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: {
65: #if DBA_CDB_BUILTIN
66: php_stream* file = 0;
67: int make;
68: #else
69: int file = 0;
70: #endif
71: dba_cdb *cdb;
72: dba_info *pinfo = (dba_info *) info;
73:
74: switch (info->mode) {
75: case DBA_READER:
76: #if DBA_CDB_BUILTIN
77: make = 0;
78: 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: break;
87: #if DBA_CDB_BUILTIN
88: case DBA_TRUNC:
89: make = 1;
90: file = info->fp;
91: break;
92: case DBA_CREAT:
93: case DBA_WRITER:
94: *error = "Update operations are not supported";
95: return FAILURE; /* not supported */
96: #endif
97: default:
98: *error = "Currently not supported";
99: return FAILURE;
100: }
101:
102: cdb = pemalloc(sizeof(dba_cdb), info->flags&DBA_PERSISTENT);
103: memset(cdb, 0, sizeof(dba_cdb));
104:
105: #if DBA_CDB_BUILTIN
106: if (make) {
107: cdb_make_start(&cdb->m, file TSRMLS_CC);
108: } else {
109: cdb_init(&cdb->c, file TSRMLS_CC);
110: }
111: cdb->make = make;
112: #else
113: cdb_init(&cdb->c, file);
114: #endif
115: cdb->file = file;
116:
117: pinfo->dbf = cdb;
118: return SUCCESS;
119: }
120:
121: DBA_CLOSE_FUNC(cdb)
122: {
123: CDB_INFO;
124:
125: /* cdb_free does not close associated file */
126: #if DBA_CDB_BUILTIN
127: if (cdb->make) {
128: cdb_make_finish(&cdb->m TSRMLS_CC);
129: } else {
130: cdb_free(&cdb->c TSRMLS_CC);
131: }
132: #else
133: cdb_free(&cdb->c);
134: close(cdb->file);
135: #endif
136: pefree(cdb, info->flags&DBA_PERSISTENT);
137: }
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: {
151: CDB_INFO;
152: unsigned int len;
153: char *new_entry = NULL;
154:
155: #if DBA_CDB_BUILTIN
156: if (cdb->make)
157: return NULL; /* database was opened writeonly */
158: #endif
159: if (php_cdb_find(&cdb->c, key, keylen) == 1) {
160: while(skip--) {
161: if (php_cdb_findnext(&cdb->c, key, keylen) != 1) {
162: return NULL;
163: }
164: }
165: len = cdb_datalen(&cdb->c);
166: new_entry = safe_emalloc(len, 1, 1);
167:
168: if (php_cdb_read(&cdb->c, new_entry, len, cdb_datapos(&cdb->c)) == -1) {
169: efree(new_entry);
170: return NULL;
171: }
172: new_entry[len] = 0;
173: if (newlen)
174: *newlen = len;
175: }
176:
177: return new_entry;
178: }
179:
180: DBA_UPDATE_FUNC(cdb)
181: {
182: #if DBA_CDB_BUILTIN
183: CDB_INFO;
184:
185: if (!cdb->make)
186: return FAILURE; /* database was opened readonly */
187: if (!mode)
188: return FAILURE; /* cdb_make dosn't know replace */
189: if (cdb_make_add(&cdb->m, key, keylen, val, vallen TSRMLS_CC) != -1)
190: return SUCCESS;
191: #endif
192: return FAILURE;
193: }
194:
195: DBA_EXISTS_FUNC(cdb)
196: {
197: CDB_INFO;
198:
199: #if DBA_CDB_BUILTIN
200: if (cdb->make)
201: return FAILURE; /* database was opened writeonly */
202: #endif
203: if (php_cdb_find(&cdb->c, key, keylen) == 1)
204: return SUCCESS;
205: return FAILURE;
206: }
207:
208: DBA_DELETE_FUNC(cdb)
209: {
210: 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: int cdb_file_lseek(php_stream *fp, off_t offset, int whence TSRMLS_DC) {
229: php_stream_seek(fp, offset, whence);
230: 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: {
247: CDB_INFO;
248: uint32 klen, dlen;
249: char buf[8];
250: char *key;
251:
252: #if DBA_CDB_BUILTIN
253: if (cdb->make)
254: return NULL; /* database was opened writeonly */
255: #endif
256:
257: cdb->eod = -1;
258: CSEEK(0);
259: CREAD(4);
260:
261: /* Total length of file in bytes */
262: uint32_unpack(buf, &cdb->eod);
263:
264: CSEEK(2048);
265: CREAD(8);
266:
267: /* The first four bytes contain the length of the key */
268: uint32_unpack(buf, &klen);
269: uint32_unpack(buf + 4, &dlen);
270:
271: key = safe_emalloc(klen, 1, 1);
272: if (cdb_file_read(cdb->file, key, klen) < klen) {
273: efree(key);
274: key = NULL;
275: } else {
276: key[klen] = '\0';
277: if (newlen) *newlen = klen;
278: }
279:
280: /* header + klenlen + dlenlen + klen + dlen */
281: cdb->pos = 2048 + 4 + 4 + klen + dlen;
282:
283: return key;
284: }
285:
286: DBA_NEXTKEY_FUNC(cdb)
287: {
288: CDB_INFO;
289: uint32 klen, dlen;
290: char buf[8];
291: char *key;
292:
293: #if DBA_CDB_BUILTIN
294: if (cdb->make)
295: return NULL; /* database was opened writeonly */
296: #endif
297:
298: CSEEK(cdb->pos);
299: CREAD(8);
300: uint32_unpack(buf, &klen);
301: uint32_unpack(buf + 4, &dlen);
302:
303: key = safe_emalloc(klen, 1, 1);
304: if (cdb_file_read(cdb->file, key, klen) < klen) {
305: efree(key);
306: key = NULL;
307: } else {
308: key[klen] = '\0';
309: if (newlen) *newlen = klen;
310: }
311:
312: cdb->pos += 8 + klen + dlen;
313:
314: return key;
315: }
316:
317: DBA_OPTIMIZE_FUNC(cdb)
318: {
319: return SUCCESS;
320: }
321:
322: DBA_SYNC_FUNC(cdb)
323: {
324: /* this is read-only */
325: return SUCCESS;
326: }
327:
328: DBA_INFO_FUNC(cdb)
329: {
330: #if DBA_CDB_BUILTIN
331: if (!strcmp(hnd->name, "cdb")) {
332: return estrdup(cdb_version());
333: } else {
334: 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: */