xref: /PHP-8.4/ext/dba/dba_dbm.c (revision 11accb5c)
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_DBM
24 #include "php_dbm.h"
25 
26 #ifdef DBM_INCLUDE_FILE
27 #include DBM_INCLUDE_FILE
28 #endif
29 #ifdef DBA_GDBM
30 #include "php_gdbm.h"
31 #endif
32 
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 
38 #define TRUNC_IT(extension, mode) \
39 	snprintf(buf, MAXPATHLEN, "%s" extension, ZSTR_VAL(info->path)); \
40 	buf[MAXPATHLEN-1] = '\0'; \
41 	if((fd = VCWD_OPEN_MODE(buf, O_CREAT | mode | O_WRONLY, filemode)) == -1) \
42 		return FAILURE; \
43 	close(fd);
44 
45 
46 typedef struct {
47 	datum nextkey;
48 } dba_dbm_data;
49 
DBA_OPEN_FUNC(dbm)50 DBA_OPEN_FUNC(dbm)
51 {
52 	int fd;
53 	int filemode = info->file_permission;
54 
55 	if(info->mode == DBA_TRUNC) {
56 		char buf[MAXPATHLEN];
57 
58 		/* dbm/ndbm original */
59 		TRUNC_IT(".pag", O_TRUNC);
60 		TRUNC_IT(".dir", O_TRUNC);
61 	}
62 
63 	if(info->mode == DBA_CREAT) {
64 		char buf[MAXPATHLEN];
65 
66 		TRUNC_IT(".pag", 0);
67 		TRUNC_IT(".dir", 0);
68 	}
69 
70 	if(dbminit((char *) ZSTR_VAL(info->path)) == -1) {
71 		return FAILURE;
72 	}
73 
74 	info->dbf = pemalloc(sizeof(dba_dbm_data), info->flags&DBA_PERSISTENT);
75 	memset(info->dbf, 0, sizeof(dba_dbm_data));
76 	return SUCCESS;
77 }
78 
DBA_CLOSE_FUNC(dbm)79 DBA_CLOSE_FUNC(dbm)
80 {
81 	pefree(info->dbf, info->flags&DBA_PERSISTENT);
82 	dbmclose();
83 }
84 
DBA_FETCH_FUNC(dbm)85 DBA_FETCH_FUNC(dbm)
86 {
87 	datum gval;
88 	datum gkey;
89 
90 	gkey.dptr = ZSTR_VAL(key);
91 	gkey.dsize = ZSTR_LEN(key);
92 	gval = fetch(gkey);
93 	if (gval.dptr) {
94 		return zend_string_init(gval.dptr, gval.dsize, /* persistent */ false);
95 	}
96 	return NULL;
97 }
98 
DBA_UPDATE_FUNC(dbm)99 DBA_UPDATE_FUNC(dbm)
100 {
101 	datum gval;
102 	datum gkey;
103 
104 	gkey.dptr = ZSTR_VAL(key);
105 	gkey.dsize = ZSTR_LEN(key);
106 
107 	if (mode == 1) { /* insert */
108 		gval = fetch(gkey);
109 		if (gval.dptr) {
110 			return FAILURE;
111 		}
112 	}
113 
114 	gval.dptr = ZSTR_VAL(val);
115 	gval.dsize = ZSTR_LEN(val);
116 
117 	return (store(gkey, gval) == -1 ? FAILURE : SUCCESS);
118 }
119 
DBA_EXISTS_FUNC(dbm)120 DBA_EXISTS_FUNC(dbm)
121 {
122 	datum gval;
123 	datum gkey;
124 
125 	gkey.dptr = ZSTR_VAL(key);
126 	gkey.dsize = ZSTR_LEN(key);
127 
128 	gval = fetch(gkey);
129 	if (gval.dptr) {
130 		return SUCCESS;
131 	}
132 	return FAILURE;
133 }
134 
DBA_DELETE_FUNC(dbm)135 DBA_DELETE_FUNC(dbm)
136 {
137 	datum gkey;
138 
139 	gkey.dptr = ZSTR_VAL(key);
140 	gkey.dsize = ZSTR_LEN(key);
141 	return(delete(gkey) == -1 ? FAILURE : SUCCESS);
142 }
143 
DBA_FIRSTKEY_FUNC(dbm)144 DBA_FIRSTKEY_FUNC(dbm)
145 {
146 	dba_dbm_data *dba = info->dbf;
147 	datum gkey;
148 	zend_string *key = NULL;
149 
150 	gkey = firstkey();
151 	if (gkey.dptr) {
152 		key = zend_string_init(gkey.dptr, gkey.dsize, /* persistent */ false);
153 		dba->nextkey = gkey;
154 	} else {
155 		dba->nextkey.dptr = NULL;
156 	}
157 	return key;
158 }
159 
DBA_NEXTKEY_FUNC(dbm)160 DBA_NEXTKEY_FUNC(dbm)
161 {
162 	dba_dbm_data *dba = info->dbf;
163 	datum gkey;
164 	zend_string *key = NULL;
165 
166 	if (!dba->nextkey.dptr) { return NULL; }
167 
168 	gkey = nextkey(dba->nextkey);
169 	if (gkey.dptr) {
170 		key = zend_string_init(gkey.dptr, gkey.dsize, /* persistent */ false);
171 		dba->nextkey = gkey;
172 	} else {
173 		dba->nextkey.dptr = NULL;
174 	}
175 	return key;
176 }
177 
DBA_OPTIMIZE_FUNC(dbm)178 DBA_OPTIMIZE_FUNC(dbm)
179 {
180 	/* dummy */
181 	return SUCCESS;
182 }
183 
DBA_SYNC_FUNC(dbm)184 DBA_SYNC_FUNC(dbm)
185 {
186 	return SUCCESS;
187 }
188 
DBA_INFO_FUNC(dbm)189 DBA_INFO_FUNC(dbm)
190 {
191 #ifdef DBA_GDBM
192 	if (!strcmp(DBM_VERSION, "GDBM"))
193 	{
194 		return dba_info_gdbm(hnd, info);
195 	}
196 #endif
197 	return estrdup(DBM_VERSION);
198 }
199 
200 #endif
201