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