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