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