xref: /PHP-5.5/ext/dba/dba_db3.c (revision 73c1be26)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2015 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: Sascha Schumann <sascha@schumann.cx>                         |
16    +----------------------------------------------------------------------+
17  */
18 
19 /* $Id$ */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "php.h"
26 
27 #if DBA_DB3
28 #include "php_db3.h"
29 #include <sys/stat.h>
30 
31 #include <string.h>
32 #ifdef DB3_INCLUDE_FILE
33 #include DB3_INCLUDE_FILE
34 #else
35 #include <db.h>
36 #endif
37 
php_dba_db3_errcall_fcn(const char * errpfx,char * msg)38 static void php_dba_db3_errcall_fcn(const char *errpfx, char *msg)
39 {
40 	TSRMLS_FETCH();
41 
42 	php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
43 }
44 
45 #define DB3_DATA dba_db3_data *dba = info->dbf
46 #define DB3_GKEY \
47 	DBT gkey; \
48 	memset(&gkey, 0, sizeof(gkey)); \
49 	gkey.data = (char *) key; gkey.size = keylen
50 
51 typedef struct {
52 	DB *dbp;
53 	DBC *cursor;
54 } dba_db3_data;
55 
DBA_OPEN_FUNC(db3)56 DBA_OPEN_FUNC(db3)
57 {
58 	DB *dbp = NULL;
59 	DBTYPE type;
60 	int gmode = 0, err;
61 	int filemode = 0644;
62 	struct stat check_stat;
63 	int s = VCWD_STAT(info->path, &check_stat);
64 
65 	if (!s && !check_stat.st_size) {
66 		info->mode = DBA_TRUNC; /* force truncate */
67 	}
68 
69 	type = info->mode == DBA_READER ? DB_UNKNOWN :
70 		info->mode == DBA_TRUNC ? DB_BTREE :
71 		s ? DB_BTREE : DB_UNKNOWN;
72 
73 	gmode = info->mode == DBA_READER ? DB_RDONLY :
74 		(info->mode == DBA_CREAT && s) ? DB_CREATE :
75 		(info->mode == DBA_CREAT && !s) ? 0 :
76 		info->mode == DBA_WRITER ? 0         :
77 		info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
78 
79 	if (gmode == -1) {
80 		return FAILURE; /* not possible */
81 	}
82 
83 	if (info->argc > 0) {
84 		convert_to_long_ex(info->argv[0]);
85 		filemode = Z_LVAL_PP(info->argv[0]);
86 	}
87 
88 #ifdef DB_FCNTL_LOCKING
89 	gmode |= DB_FCNTL_LOCKING;
90 #endif
91 
92 	if ((err=db_create(&dbp, NULL, 0)) == 0) {
93 	    dbp->set_errcall(dbp, php_dba_db3_errcall_fcn);
94 	    if ((err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
95 			dba_db3_data *data;
96 
97 			data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
98 			data->dbp = dbp;
99 			data->cursor = NULL;
100 			info->dbf = data;
101 
102 			return SUCCESS;
103 		} else {
104 			dbp->close(dbp, 0);
105 			*error = db_strerror(err);
106 		}
107 	} else {
108 		*error = db_strerror(err);
109 	}
110 
111 	return FAILURE;
112 }
113 
DBA_CLOSE_FUNC(db3)114 DBA_CLOSE_FUNC(db3)
115 {
116 	DB3_DATA;
117 
118 	if (dba->cursor) dba->cursor->c_close(dba->cursor);
119 	dba->dbp->close(dba->dbp, 0);
120 	pefree(dba, info->flags&DBA_PERSISTENT);
121 }
122 
DBA_FETCH_FUNC(db3)123 DBA_FETCH_FUNC(db3)
124 {
125 	DBT gval;
126 	char *new = NULL;
127 	DB3_DATA;
128 	DB3_GKEY;
129 
130 	memset(&gval, 0, sizeof(gval));
131 	if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
132 		if (newlen) *newlen = gval.size;
133 		new = estrndup(gval.data, gval.size);
134 	}
135 	return new;
136 }
137 
DBA_UPDATE_FUNC(db3)138 DBA_UPDATE_FUNC(db3)
139 {
140 	DBT gval;
141 	DB3_DATA;
142 	DB3_GKEY;
143 
144 	memset(&gval, 0, sizeof(gval));
145 	gval.data = (char *) val;
146 	gval.size = vallen;
147 
148 	if (!dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
149 				mode == 1 ? DB_NOOVERWRITE : 0)) {
150 		return SUCCESS;
151 	}
152 	return FAILURE;
153 }
154 
DBA_EXISTS_FUNC(db3)155 DBA_EXISTS_FUNC(db3)
156 {
157 	DBT gval;
158 	DB3_DATA;
159 	DB3_GKEY;
160 
161 	memset(&gval, 0, sizeof(gval));
162 	if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
163 		return SUCCESS;
164 	}
165 	return FAILURE;
166 }
167 
DBA_DELETE_FUNC(db3)168 DBA_DELETE_FUNC(db3)
169 {
170 	DB3_DATA;
171 	DB3_GKEY;
172 
173 	return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
174 }
175 
DBA_FIRSTKEY_FUNC(db3)176 DBA_FIRSTKEY_FUNC(db3)
177 {
178 	DB3_DATA;
179 
180 	if (dba->cursor) {
181 		dba->cursor->c_close(dba->cursor);
182 	}
183 
184 	dba->cursor = NULL;
185 	if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0) != 0) {
186 		return NULL;
187 	}
188 
189 	/* we should introduce something like PARAM_PASSTHRU... */
190 	return dba_nextkey_db3(info, newlen TSRMLS_CC);
191 }
192 
DBA_NEXTKEY_FUNC(db3)193 DBA_NEXTKEY_FUNC(db3)
194 {
195 	DB3_DATA;
196 	DBT gkey, gval;
197 	char *nkey = NULL;
198 
199 	memset(&gkey, 0, sizeof(gkey));
200 	memset(&gval, 0, sizeof(gval));
201 
202 	if (dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT) == 0) {
203 		if (gkey.data) {
204 			nkey = estrndup(gkey.data, gkey.size);
205 			if (newlen) *newlen = gkey.size;
206 		}
207 	}
208 
209 	return nkey;
210 }
211 
DBA_OPTIMIZE_FUNC(db3)212 DBA_OPTIMIZE_FUNC(db3)
213 {
214 	return SUCCESS;
215 }
216 
DBA_SYNC_FUNC(db3)217 DBA_SYNC_FUNC(db3)
218 {
219 	DB3_DATA;
220 
221 	return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
222 }
223 
DBA_INFO_FUNC(db3)224 DBA_INFO_FUNC(db3)
225 {
226 	return estrdup(DB_VERSION_STRING);
227 }
228 
229 #endif
230 
231 /*
232  * Local variables:
233  * tab-width: 4
234  * c-basic-offset: 4
235  * End:
236  * vim600: sw=4 ts=4 fdm=marker
237  * vim<600: sw=4 ts=4
238  */
239