xref: /PHP-8.1/ext/dba/dba_gdbm.c (revision 01b3fc03)
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 #if DBA_GDBM
24 #include "php_gdbm.h"
25 
26 #ifdef GDBM_INCLUDE_FILE
27 #include GDBM_INCLUDE_FILE
28 #endif
29 
30 #define GDBM_DATA dba_gdbm_data *dba = info->dbf
31 #define GDBM_GKEY datum gkey; gkey.dptr = (char *) key; gkey.dsize = keylen
32 
33 typedef struct {
34 	GDBM_FILE dbf;
35 	datum nextkey;
36 } dba_gdbm_data;
37 
DBA_OPEN_FUNC(gdbm)38 DBA_OPEN_FUNC(gdbm)
39 {
40 	GDBM_FILE dbf;
41 	int gmode = 0;
42 	int filemode = 0644;
43 
44 	gmode = info->mode == DBA_READER ? GDBM_READER :
45 		info->mode == DBA_WRITER ? GDBM_WRITER :
46 		info->mode == DBA_CREAT  ? GDBM_WRCREAT :
47 		info->mode == DBA_TRUNC ? GDBM_NEWDB : -1;
48 
49 	if(gmode == -1)
50 		return FAILURE; /* not possible */
51 
52 	if(info->argc > 0) {
53 		filemode = zval_get_long(&info->argv[0]);
54 	}
55 
56 	dbf = gdbm_open(info->path, 0, gmode, filemode, NULL);
57 
58 	if(dbf) {
59 		info->dbf = pemalloc(sizeof(dba_gdbm_data), info->flags&DBA_PERSISTENT);
60 		memset(info->dbf, 0, sizeof(dba_gdbm_data));
61 		((dba_gdbm_data *) info->dbf)->dbf = dbf;
62 		return SUCCESS;
63 	}
64 	*error = (char *)gdbm_strerror(gdbm_errno);
65 	return FAILURE;
66 }
67 
DBA_CLOSE_FUNC(gdbm)68 DBA_CLOSE_FUNC(gdbm)
69 {
70 	GDBM_DATA;
71 
72 	if(dba->nextkey.dptr) free(dba->nextkey.dptr);
73 	gdbm_close(dba->dbf);
74 	pefree(dba, info->flags&DBA_PERSISTENT);
75 }
76 
DBA_FETCH_FUNC(gdbm)77 DBA_FETCH_FUNC(gdbm)
78 {
79 	GDBM_DATA;
80 	datum gval;
81 	char *new = NULL;
82 
83 	GDBM_GKEY;
84 	gval = gdbm_fetch(dba->dbf, gkey);
85 	if(gval.dptr) {
86 		if(newlen) *newlen = gval.dsize;
87 		new = estrndup(gval.dptr, gval.dsize);
88 		free(gval.dptr);
89 	}
90 	return new;
91 }
92 
DBA_UPDATE_FUNC(gdbm)93 DBA_UPDATE_FUNC(gdbm)
94 {
95 	datum gval;
96 	GDBM_DATA;
97 
98 	GDBM_GKEY;
99 	gval.dptr = (char *) val;
100 	gval.dsize = vallen;
101 
102 	switch (gdbm_store(dba->dbf, gkey, gval, mode == 1 ? GDBM_INSERT : GDBM_REPLACE)) {
103 		case 0:
104 			return SUCCESS;
105 		case 1:
106 			return FAILURE;
107 		case -1:
108 			php_error_docref2(NULL, key, val, E_WARNING, "%s", gdbm_strerror(gdbm_errno));
109 			return FAILURE;
110 		default:
111 			php_error_docref2(NULL, key, val, E_WARNING, "Unknown return value");
112 			return FAILURE;
113 	}
114 }
115 
DBA_EXISTS_FUNC(gdbm)116 DBA_EXISTS_FUNC(gdbm)
117 {
118 	GDBM_DATA;
119 	GDBM_GKEY;
120 
121 	return gdbm_exists(dba->dbf, gkey) ? SUCCESS : FAILURE;
122 }
123 
DBA_DELETE_FUNC(gdbm)124 DBA_DELETE_FUNC(gdbm)
125 {
126 	GDBM_DATA;
127 	GDBM_GKEY;
128 
129 	return gdbm_delete(dba->dbf, gkey) == -1 ? FAILURE : SUCCESS;
130 }
131 
DBA_FIRSTKEY_FUNC(gdbm)132 DBA_FIRSTKEY_FUNC(gdbm)
133 {
134 	GDBM_DATA;
135 	datum gkey;
136 	char *key = NULL;
137 
138 	if(dba->nextkey.dptr) {
139 		free(dba->nextkey.dptr);
140 	}
141 
142 	gkey = gdbm_firstkey(dba->dbf);
143 	if(gkey.dptr) {
144 		key = estrndup(gkey.dptr, gkey.dsize);
145 		if(newlen) *newlen = gkey.dsize;
146 		dba->nextkey = gkey;
147 	} else {
148 		dba->nextkey.dptr = NULL;
149 	}
150 	return key;
151 }
152 
DBA_NEXTKEY_FUNC(gdbm)153 DBA_NEXTKEY_FUNC(gdbm)
154 {
155 	GDBM_DATA;
156 	char *nkey = NULL;
157 	datum gkey;
158 
159 	if(!dba->nextkey.dptr) return NULL;
160 
161 	gkey = gdbm_nextkey(dba->dbf, dba->nextkey);
162 	free(dba->nextkey.dptr);
163 	if(gkey.dptr) {
164 		nkey = estrndup(gkey.dptr, gkey.dsize);
165 		if(newlen) *newlen = gkey.dsize;
166 		dba->nextkey = gkey;
167 	} else {
168 		dba->nextkey.dptr = NULL;
169 	}
170 	return nkey;
171 }
172 
DBA_OPTIMIZE_FUNC(gdbm)173 DBA_OPTIMIZE_FUNC(gdbm)
174 {
175 	GDBM_DATA;
176 	gdbm_reorganize(dba->dbf);
177 	return SUCCESS;
178 }
179 
DBA_SYNC_FUNC(gdbm)180 DBA_SYNC_FUNC(gdbm)
181 {
182 	GDBM_DATA;
183 
184 	gdbm_sync(dba->dbf);
185 	return SUCCESS;
186 }
187 
DBA_INFO_FUNC(gdbm)188 DBA_INFO_FUNC(gdbm)
189 {
190 	return estrdup(gdbm_version);
191 }
192 
193 #endif
194