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