xref: /PHP-7.4/ext/dba/dba_db2.c (revision 92ac598a)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 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 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22 
23 #include "php.h"
24 
25 #if DBA_DB2
26 #include "php_db2.h"
27 #include <sys/stat.h>
28 
29 #include <string.h>
30 #ifdef DB2_INCLUDE_FILE
31 #include DB2_INCLUDE_FILE
32 #endif
33 
34 #define DB2_DATA dba_db2_data *dba = info->dbf
35 #define DB2_GKEY \
36 	DBT gkey = {0}; \
37 	gkey.data = (char *) key; \
38 	gkey.size = keylen
39 
40 typedef struct {
41 	DB *dbp;
42 	DBC *cursor;
43 } dba_db2_data;
44 
DBA_OPEN_FUNC(db2)45 DBA_OPEN_FUNC(db2)
46 {
47 	DB *dbp;
48 	DBTYPE type;
49 	int gmode = 0;
50 	int filemode = 0644;
51 	struct stat check_stat;
52 	int s = VCWD_STAT(info->path, &check_stat);
53 
54 	if (!s && !check_stat.st_size) {
55 		info->mode = DBA_TRUNC; /* force truncate */
56 	}
57 
58 	type = info->mode == DBA_READER ? DB_UNKNOWN :
59 		info->mode == DBA_TRUNC ? DB_BTREE :
60 		s ? DB_BTREE : DB_UNKNOWN;
61 
62 	gmode = info->mode == DBA_READER ? DB_RDONLY :
63 		(info->mode == DBA_CREAT && s) ? DB_CREATE :
64 		(info->mode == DBA_CREAT && !s) ? 0 :
65 		info->mode == DBA_WRITER ? 0         :
66 		info->mode == DBA_TRUNC ? DB_CREATE | DB_TRUNCATE : -1;
67 
68 	if (gmode == -1) {
69 		return FAILURE;/* not possible */
70 	}
71 
72 	if (info->argc > 0) {
73 		filemode = zval_get_long(&info->argv[0]);
74 	}
75 
76 	if (db_open(info->path, type, gmode, filemode, NULL, NULL, &dbp)) {
77 		return FAILURE;
78 	}
79 
80 	info->dbf = pemalloc(sizeof(dba_db2_data), info->flags&DBA_PERSISTENT);
81 	memset(info->dbf, 0, sizeof(dba_db2_data));
82 	((dba_db2_data *) info->dbf)->dbp = dbp;
83 	return SUCCESS;
84 }
85 
DBA_CLOSE_FUNC(db2)86 DBA_CLOSE_FUNC(db2)
87 {
88 	DB2_DATA;
89 
90 	if (dba->cursor)
91 		dba->cursor->c_close(dba->cursor);
92 	dba->dbp->close(dba->dbp, 0);
93 	pefree(dba, info->flags&DBA_PERSISTENT);
94 }
95 
DBA_FETCH_FUNC(db2)96 DBA_FETCH_FUNC(db2)
97 {
98 	DBT gval = {0};
99 	DB2_DATA;
100 	DB2_GKEY;
101 
102 	if (dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
103 		return NULL;
104 	}
105 
106 	if (newlen) *newlen = gval.size;
107 	return estrndup(gval.data, gval.size);
108 }
109 
DBA_UPDATE_FUNC(db2)110 DBA_UPDATE_FUNC(db2)
111 {
112 	DBT gval = {0};
113 	DB2_DATA;
114 	DB2_GKEY;
115 
116 	gval.data = (char *) val;
117 	gval.size = vallen;
118 
119 	if (dba->dbp->put(dba->dbp, NULL, &gkey, &gval,
120 				mode == 1 ? DB_NOOVERWRITE : 0)) {
121 		return FAILURE;
122 	}
123 	return SUCCESS;
124 }
125 
DBA_EXISTS_FUNC(db2)126 DBA_EXISTS_FUNC(db2)
127 {
128 	DBT gval = {0};
129 	DB2_DATA;
130 	DB2_GKEY;
131 
132 	if (dba->dbp->get(dba->dbp, NULL, &gkey, &gval, 0)) {
133 		return FAILURE;
134 	}
135 	return SUCCESS;
136 }
137 
DBA_DELETE_FUNC(db2)138 DBA_DELETE_FUNC(db2)
139 {
140 	DB2_DATA;
141 	DB2_GKEY;
142 
143 	return dba->dbp->del(dba->dbp, NULL, &gkey, 0) ? FAILURE : SUCCESS;
144 }
145 
DBA_FIRSTKEY_FUNC(db2)146 DBA_FIRSTKEY_FUNC(db2)
147 {
148 	DB2_DATA;
149 
150 	if (dba->cursor) {
151 		dba->cursor->c_close(dba->cursor);
152 		dba->cursor = NULL;
153 	}
154 
155 #if (DB_VERSION_MAJOR > 2) || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR > 6) || (DB_VERSION_MAJOR == 2 && DB_VERSION_MINOR == 6 && DB_VERSION_PATCH >= 4)
156 	if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor, 0)) {
157 #else
158 	if (dba->dbp->cursor(dba->dbp, NULL, &dba->cursor)) {
159 #endif
160 		return NULL;
161 	}
162 
163 	/* we should introduce something like PARAM_PASSTHRU... */
164 	return dba_nextkey_db2(info, newlen);
165 }
166 
167 DBA_NEXTKEY_FUNC(db2)
168 {
169 	DB2_DATA;
170 	DBT gkey = {0}, gval = {0};
171 
172 	if (dba->cursor->c_get(dba->cursor, &gkey, &gval, DB_NEXT)
173 			|| !gkey.data)
174 		return NULL;
175 
176 	if (newlen) *newlen = gkey.size;
177 	return estrndup(gkey.data, gkey.size);
178 }
179 
180 DBA_OPTIMIZE_FUNC(db2)
181 {
182 	return SUCCESS;
183 }
184 
185 DBA_SYNC_FUNC(db2)
186 {
187 	DB2_DATA;
188 
189 	return dba->dbp->sync(dba->dbp, 0) ? FAILURE : SUCCESS;
190 }
191 
192 DBA_INFO_FUNC(db2)
193 {
194 	return estrdup(DB_VERSION_STRING);
195 }
196 
197 #endif
198