![]() ![]() | ![]() |
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: Marcus Boerger <helly@php.net> |
16: | Sascha Schumann <sascha@schumann.cx> |
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_DB4
29: #include "php_db4.h"
30: #include <sys/stat.h>
31:
32: #include <string.h>
33: #ifdef DB4_INCLUDE_FILE
34: #include DB4_INCLUDE_FILE
35: #else
36: #include <db.h>
37: #endif
38:
39: static void php_dba_db4_errcall_fcn(
40: #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3))
41: const DB_ENV *dbenv,
42: #endif
43: const char *errpfx, const char *msg)
44: {
45: TSRMLS_FETCH();
46:
47: #if (DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 8))
48: /* Bug 51086, Berkeley DB 4.8.26 */
49: /* This code suppresses a BDB 4.8+ error message, thus keeping PHP test compatibility */
50: {
1.1.1.2 misho 51: const char *function = get_active_function_name(TSRMLS_C);
1.1 misho 52: if (function && (!strcmp(function,"dba_popen") || !strcmp(function,"dba_open"))
53: && (!strncmp(msg, "fop_read_meta", sizeof("fop_read_meta")-1)
54: || !strncmp(msg, "BDB0004 fop_read_meta", sizeof("BDB0004 fop_read_meta")-1))) {
55: return;
56: }
57: }
58: #endif
59:
60: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
61: }
62:
63: #define DB4_DATA dba_db4_data *dba = info->dbf
64: #define DB4_GKEY \
65: DBT gkey; \
66: memset(&gkey, 0, sizeof(gkey)); \
67: gkey.data = (char *) key; gkey.size = keylen
68:
69: typedef struct {
70: DB *dbp;
71: DBC *cursor;
72: } dba_db4_data;
73:
74: DBA_OPEN_FUNC(db4)
75: {
76: DB *dbp = NULL;
77: DBTYPE type;
78: int gmode = 0, err;
79: int filemode = 0644;
80: struct stat check_stat;
81: int s = VCWD_STAT(info->path, &check_stat);
82:
83: #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 7) /* Bug 51086 */
84: if (!s && !check_stat.st_size) {
85: info->mode = DBA_TRUNC; /* force truncate */
86: }
87:
88: type = info->mode == DBA_READER ? DB_UNKNOWN :
89: info->mode == DBA_TRUNC ? DB_BTREE :
90: s ? DB_BTREE : DB_UNKNOWN;
91:
92: gmode = info->mode == DBA_READER ? DB_RDONLY :
93: (info->mode == DBA_CREAT && s) ? DB_CREATE :
94: (info->mode == DBA_CREAT && !s) ? 0 :
95: info->mode == DBA_WRITER ? 0 :
96: info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
97: #else
98: if (!s && !check_stat.st_size) {
99: info->mode = DBA_CREAT; /* force creation */
100: }
101:
102: type = info->mode == DBA_READER ? DB_UNKNOWN :
103: (info->mode == DBA_TRUNC || info->mode == DBA_CREAT) ? DB_BTREE :
104: s ? DB_BTREE : DB_UNKNOWN;
105:
106: gmode = info->mode == DBA_READER ? DB_RDONLY :
107: info->mode == DBA_CREAT ? DB_CREATE :
108: info->mode == DBA_WRITER ? 0 :
109: info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
110: #endif
111:
112: if (gmode == -1) {
113: return FAILURE; /* not possible */
114: }
115:
116: if (info->flags & DBA_PERSISTENT) {
117: gmode |= DB_THREAD;
118: }
119:
120: if (info->argc > 0) {
121: convert_to_long_ex(info->argv[0]);
122: filemode = Z_LVAL_PP(info->argv[0]);
123: }
124:
125: if ((err=db_create(&dbp, NULL, 0)) == 0) {
126: dbp->set_errcall(dbp, php_dba_db4_errcall_fcn);
127: if (
128: #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
129: (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
130: #else
131: (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
132: #endif
133: dba_db4_data *data;
134:
135: data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
136: data->dbp = dbp;
137: data->cursor = NULL;
138: info->dbf = data;
139:
140: return SUCCESS;
141: } else {
142: dbp->close(dbp, 0);
143: *error = db_strerror(err);
144: }
145: } else {
146: *error = db_strerror(err);
147: }
148:
149: return FAILURE;
150: }
151:
152: DBA_CLOSE_FUNC(db4)
153: {
154: DB4_DATA;
155:
156: if (dba->cursor) dba->cursor->c_close(dba->cursor);
157: dba->dbp->close(dba->dbp, 0);
158: pefree(dba, info->flags&DBA_PERSISTENT);
159: }
160:
161: DBA_FETCH_FUNC(db4)
162: {
163: DBT gval;
164: char *new = NULL;
165: DB4_DATA;
166: DB4_GKEY;
167:
168: memset(&gval, 0, sizeof(gval));
169: if (info->flags & DBA_PERSISTENT) {
170: gval.flags |= DB_DBT_MALLOC;
171: }
172: if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
173: if (newlen) *newlen = gval.size;
174: new = estrndup(gval.data, gval.size);
175: if (info->flags & DBA_PERSISTENT) {
176: free(gval.data);
177: }
178: }
179: return new;
180: }
181:
182: DBA_UPDATE_FUNC(db4)
183: {
184: DBT gval;
185: DB4_DATA;
186: DB4_GKEY;
187:
188: memset(&gval, 0, sizeof(gval));
189: gval.data = (char *) val;
190: gval.size = vallen;
191:
192: if (!dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
193: mode == 1 ? DB_NOOVERWRITE : 0)) {
194: return SUCCESS;
195: }
196: return FAILURE;
197: }
198:
199: DBA_EXISTS_FUNC(db4)
200: {
201: DBT gval;
202: DB4_DATA;
203: DB4_GKEY;
204:
205: memset(&gval, 0, sizeof(gval));
206:
207: if (info->flags & DBA_PERSISTENT) {
208: gval.flags |= DB_DBT_MALLOC;
209: }
210:
211: if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
212: if (info->flags & DBA_PERSISTENT) {
213: free(gval.data);
214: }
215: return SUCCESS;
216: }
217: return FAILURE;
218: }
219:
220: DBA_DELETE_FUNC(db4)
221: {
222: DB4_DATA;
223: DB4_GKEY;
224:
225: return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
226: }
227:
228: DBA_FIRSTKEY_FUNC(db4)
229: {
230: DB4_DATA;
231:
232: if (dba->cursor) {
233: dba->cursor->c_close(dba->cursor);
234: }
235:
236: dba->cursor = NULL;
237: if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0) != 0) {
238: return NULL;
239: }
240:
241: /* we should introduce something like PARAM_PASSTHRU... */
242: return dba_nextkey_db4(info, newlen TSRMLS_CC);
243: }
244:
245: DBA_NEXTKEY_FUNC(db4)
246: {
247: DB4_DATA;
248: DBT gkey, gval;
249: char *nkey = NULL;
250:
251: memset(&gkey, 0, sizeof(gkey));
252: memset(&gval, 0, sizeof(gval));
253:
254: if (info->flags & DBA_PERSISTENT) {
255: gkey.flags |= DB_DBT_MALLOC;
256: gval.flags |= DB_DBT_MALLOC;
257: }
258: if (dba->cursor && dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT) == 0) {
259: if (gkey.data) {
260: nkey = estrndup(gkey.data, gkey.size);
261: if (newlen) *newlen = gkey.size;
262: }
263: if (info->flags & DBA_PERSISTENT) {
264: if (gkey.data) {
265: free(gkey.data);
266: }
267: if (gval.data) {
268: free(gval.data);
269: }
270: }
271: }
272:
273: return nkey;
274: }
275:
276: DBA_OPTIMIZE_FUNC(db4)
277: {
278: return SUCCESS;
279: }
280:
281: DBA_SYNC_FUNC(db4)
282: {
283: DB4_DATA;
284:
285: return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
286: }
287:
288: DBA_INFO_FUNC(db4)
289: {
290: return estrdup(DB_VERSION_STRING);
291: }
292:
293: #endif
294:
295: /*
296: * Local variables:
297: * tab-width: 4
298: * c-basic-offset: 4
299: * End:
300: * vim600: sw=4 ts=4 fdm=marker
301: * vim<600: sw=4 ts=4
302: */