xref: /php-src/ext/dba/dba_db3.c (revision 421c56dd)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: Sascha Schumann <sascha@schumann.cx>                         |
14    +----------------------------------------------------------------------+
15  */
16 
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "php.h"
22 
23 #ifdef DBA_DB3
24 #include "php_db3.h"
25 #include <sys/stat.h>
26 
27 #include <string.h>
28 #ifdef DB3_INCLUDE_FILE
29 #include DB3_INCLUDE_FILE
30 #else
31 #include <db.h>
32 #endif
33 
php_dba_db3_errcall_fcn(const DB_ENV * dbenv,const char * errpfx,const char * msg)34 static void php_dba_db3_errcall_fcn(
35 #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3))
36 	const DB_ENV *dbenv,
37 #endif
38 	const char *errpfx, const char *msg)
39 {
40 
41 	php_error_docref(NULL, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
42 }
43 
44 typedef struct {
45 	DB *dbp;
46 	DBC *cursor;
47 } dba_db3_data;
48 
DBA_OPEN_FUNC(db3)49 DBA_OPEN_FUNC(db3)
50 {
51 	DB *dbp = NULL;
52 	DBTYPE type;
53 	int gmode = 0, err;
54 	int filemode = info->file_permission;
55 	struct stat check_stat;
56 	int s = VCWD_STAT(ZSTR_VAL(info->path), &check_stat);
57 
58 	if (!s && !check_stat.st_size) {
59 		info->mode = DBA_TRUNC; /* force truncate */
60 	}
61 
62 	type = info->mode == DBA_READER ? DB_UNKNOWN :
63 		info->mode == DBA_TRUNC ? DB_BTREE :
64 		s ? DB_BTREE : DB_UNKNOWN;
65 
66 	gmode = info->mode == DBA_READER ? DB_RDONLY :
67 		(info->mode == DBA_CREAT && s) ? DB_CREATE :
68 		(info->mode == DBA_CREAT && !s) ? 0 :
69 		info->mode == DBA_WRITER ? 0         :
70 		info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
71 
72 	if (gmode == -1) {
73 		return FAILURE; /* not possible */
74 	}
75 
76 #ifdef DB_FCNTL_LOCKING
77 	gmode |= DB_FCNTL_LOCKING;
78 #endif
79 
80 	if ((err=db_create(&dbp, NULL, 0)) == 0) {
81 	    dbp->set_errcall(dbp, php_dba_db3_errcall_fcn);
82 		if(
83 #if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
84 			(err=dbp->open(dbp, 0, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) {
85 #else
86 			(err=dbp->open(dbp, ZSTR_VAL(info->path), NULL, type, gmode, filemode)) == 0) {
87 #endif
88 			dba_db3_data *data;
89 
90 			data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
91 			data->dbp = dbp;
92 			data->cursor = NULL;
93 			info->dbf = data;
94 
95 			return SUCCESS;
96 		} else {
97 			dbp->close(dbp, 0);
98 			*error = db_strerror(err);
99 		}
100 	} else {
101 		*error = db_strerror(err);
102 	}
103 
104 	return FAILURE;
105 }
106 
107 DBA_CLOSE_FUNC(db3)
108 {
109 	dba_db3_data *dba = info->dbf;
110 
111 	if (dba->cursor) dba->cursor->c_close(dba->cursor);
112 	dba->dbp->close(dba->dbp, 0);
113 	pefree(dba, info->flags&DBA_PERSISTENT);
114 }
115 
116 DBA_FETCH_FUNC(db3)
117 {
118 	dba_db3_data *dba = info->dbf;
119 	DBT gval;
120 	DBT gkey;
121 
122 	memset(&gkey, 0, sizeof(gkey));
123 	gkey.data = ZSTR_VAL(key);
124 	gkey.size = ZSTR_LEN(key);
125 
126 	memset(&gval, 0, sizeof(gval));
127 	if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
128 		return zend_string_init(gval.data, gval.size, /* persistent */ false);
129 	}
130 	return NULL;
131 }
132 
133 DBA_UPDATE_FUNC(db3)
134 {
135 	dba_db3_data *dba = info->dbf;
136 	DBT gval;
137 	DBT gkey;
138 
139 	memset(&gkey, 0, sizeof(gkey));
140 	gkey.data = ZSTR_VAL(key);
141 	gkey.size = ZSTR_LEN(key);
142 
143 	memset(&gval, 0, sizeof(gval));
144 	gval.data = ZSTR_VAL(val);
145 	gval.size = ZSTR_LEN(val);
146 
147 	if (!dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
148 				mode == 1 ? DB_NOOVERWRITE : 0)) {
149 		return SUCCESS;
150 	}
151 	return FAILURE;
152 }
153 
154 DBA_EXISTS_FUNC(db3)
155 {
156 	dba_db3_data *dba = info->dbf;
157 	DBT gval;
158 	DBT gkey;
159 
160 	memset(&gkey, 0, sizeof(gkey));
161 	gkey.data = ZSTR_VAL(key);
162 	gkey.size = ZSTR_LEN(key);
163 
164 	memset(&gval, 0, sizeof(gval));
165 	if (!dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
166 		return SUCCESS;
167 	}
168 	return FAILURE;
169 }
170 
171 DBA_DELETE_FUNC(db3)
172 {
173 	dba_db3_data *dba = info->dbf;
174 	DBT gkey;
175 
176 	memset(&gkey, 0, sizeof(gkey));
177 	gkey.data = ZSTR_VAL(key);
178 	gkey.size = ZSTR_LEN(key);
179 
180 	return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
181 }
182 
183 DBA_FIRSTKEY_FUNC(db3)
184 {
185 	dba_db3_data *dba = info->dbf;
186 
187 	if (dba->cursor) {
188 		dba->cursor->c_close(dba->cursor);
189 	}
190 
191 	dba->cursor = NULL;
192 	if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0) != 0) {
193 		return NULL;
194 	}
195 
196 	return dba_nextkey_db3(info);
197 }
198 
199 DBA_NEXTKEY_FUNC(db3)
200 {
201 	dba_db3_data *dba = info->dbf;
202 	DBT gkey, gval;
203 
204 	memset(&gkey, 0, sizeof(gkey));
205 	memset(&gval, 0, sizeof(gval));
206 
207 	if (dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT) == 0) {
208 		if (gkey.data) {
209 			return zend_string_init(gkey.data, gkey.size, /* persistent */ false);
210 		}
211 	}
212 
213 	return NULL;
214 }
215 
216 DBA_OPTIMIZE_FUNC(db3)
217 {
218 	return SUCCESS;
219 }
220 
221 DBA_SYNC_FUNC(db3)
222 {
223 	dba_db3_data *dba = info->dbf;
224 
225 	return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
226 }
227 
228 DBA_INFO_FUNC(db3)
229 {
230 	return estrdup(DB_VERSION_STRING);
231 }
232 
233 #endif
234