1 /*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Margo Seltzer.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #if defined(LIBC_SCCS) && !defined(lint)
38 static char sccsid[] = "@(#)dbm.c 8.6 (Berkeley) 11/7/95";
39 #endif /* LIBC_SCCS and not lint */
40
41 #include "db-int.h"
42
43 #include <sys/param.h>
44
45 #include <fcntl.h>
46 #include <stdio.h>
47 #include <string.h>
48
49 #include "db-ndbm.h"
50 #include "db-dbm.h"
51 #include "hash.h"
52
53 /* If the two size fields of datum and DBMT are not equal, then
54 * casting between structures will result in stack garbage being
55 * transferred. Has been observed for DEC Alpha OSF, but will handle
56 * the general case.
57 */
58
59 #define NEED_COPY
60
61 /*
62 *
63 * This package provides dbm and ndbm compatible interfaces to DB.
64 * First are the DBM routines, which call the NDBM routines, and
65 * the NDBM routines, which call the DB routines.
66 */
67 static DBM *__cur_db;
68
69 static void no_open_db __P((void));
70
71 int
kdb2_dbminit(char * file)72 kdb2_dbminit(char *file)
73 {
74 if (__cur_db != NULL)
75 (void)kdb2_dbm_close(__cur_db);
76 if ((__cur_db = kdb2_dbm_open(file, O_RDWR|O_BINARY, 0)) != NULL)
77 return (0);
78 if ((__cur_db = kdb2_dbm_open(file, O_RDONLY|O_BINARY, 0)) != NULL)
79 return (0);
80 return (-1);
81 }
82
83 datum
kdb2_fetch(datum key)84 kdb2_fetch(datum key)
85 {
86 datum item;
87
88 if (__cur_db == NULL) {
89 no_open_db();
90 item.dptr = 0;
91 item.dsize = 0;
92 return (item);
93 }
94 return (kdb2_dbm_fetch(__cur_db, key));
95 }
96
97 datum
kdb2_firstkey(void)98 kdb2_firstkey(void)
99 {
100 datum item;
101
102 if (__cur_db == NULL) {
103 no_open_db();
104 item.dptr = 0;
105 item.dsize = 0;
106 return (item);
107 }
108 return (kdb2_dbm_firstkey(__cur_db));
109 }
110
111 datum
kdb2_nextkey(datum key)112 kdb2_nextkey(datum key)
113 {
114 datum item;
115
116 if (__cur_db == NULL) {
117 no_open_db();
118 item.dptr = 0;
119 item.dsize = 0;
120 return (item);
121 }
122 return (kdb2_dbm_nextkey(__cur_db));
123 }
124
125 int
kdb2_delete(datum key)126 kdb2_delete(datum key)
127 {
128 if (__cur_db == NULL) {
129 no_open_db();
130 return (-1);
131 }
132 return (kdb2_dbm_delete(__cur_db, key));
133 }
134
135 int
kdb2_store(datum key,datum dat)136 kdb2_store(datum key, datum dat)
137 {
138 if (__cur_db == NULL) {
139 no_open_db();
140 return (-1);
141 }
142 return (kdb2_dbm_store(__cur_db, key, dat, DBM_REPLACE));
143 }
144
145 static void
no_open_db(void)146 no_open_db(void)
147 {
148 (void)fprintf(stderr, "dbm: no open database.\n");
149 }
150
151 /*
152 * Returns:
153 * *DBM on success
154 * NULL on failure
155 */
156 DBM *
kdb2_dbm_open(const char * file,int flags,int mode)157 kdb2_dbm_open(const char *file, int flags, int mode)
158 {
159 HASHINFO info;
160 char path[MAXPATHLEN];
161
162 info.bsize = 4096;
163 info.ffactor = 40;
164 info.nelem = 1;
165 info.cachesize = 0;
166 info.hash = NULL;
167 info.lorder = 0;
168 (void)strncpy(path, file, sizeof(path) - 1);
169 path[sizeof(path) - 1] = '\0';
170 (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path));
171 return ((DBM *)__hash_open(path, flags, mode, &info, 0));
172 }
173
174 /*
175 * Returns:
176 * Nothing.
177 */
178 void
kdb2_dbm_close(DBM * db)179 kdb2_dbm_close(DBM *db)
180 {
181 (void)(db->close)(db);
182 }
183
184 /*
185 * Returns:
186 * DATUM on success
187 * NULL on failure
188 */
189 datum
kdb2_dbm_fetch(DBM * db,datum key)190 kdb2_dbm_fetch(DBM *db, datum key)
191 {
192 datum retval;
193 int status;
194
195 #ifdef NEED_COPY
196 DBT k, r;
197
198 k.data = key.dptr;
199 k.size = key.dsize;
200 status = (db->get)(db, &k, &r, 0);
201 retval.dptr = r.data;
202 retval.dsize = r.size;
203 #else
204 status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0);
205 #endif
206 if (status) {
207 retval.dptr = NULL;
208 retval.dsize = 0;
209 }
210 return (retval);
211 }
212
213 /*
214 * Returns:
215 * DATUM on success
216 * NULL on failure
217 */
218 datum
kdb2_dbm_firstkey(DBM * db)219 kdb2_dbm_firstkey(DBM *db)
220 {
221 int status;
222 datum retkey;
223
224 #ifdef NEED_COPY
225 DBT k, r;
226
227 status = (db->seq)(db, &k, &r, R_FIRST);
228 retkey.dptr = k.data;
229 retkey.dsize = k.size;
230 #else
231 datum retdata;
232
233 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST);
234 #endif
235 if (status)
236 retkey.dptr = NULL;
237 return (retkey);
238 }
239
240 /*
241 * Returns:
242 * DATUM on success
243 * NULL on failure
244 */
245 datum
kdb2_dbm_nextkey(DBM * db)246 kdb2_dbm_nextkey(DBM *db)
247 {
248 int status;
249 datum retkey;
250
251 #ifdef NEED_COPY
252 DBT k, r;
253
254 status = (db->seq)(db, &k, &r, R_NEXT);
255 retkey.dptr = k.data;
256 retkey.dsize = k.size;
257 #else
258 datum retdata;
259
260 status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT);
261 #endif
262 if (status)
263 retkey.dptr = NULL;
264 return (retkey);
265 }
266
267 /*
268 * Returns:
269 * 0 on success
270 * <0 failure
271 */
272 int
kdb2_dbm_delete(DBM * db,datum key)273 kdb2_dbm_delete(DBM *db, datum key)
274 {
275 int status;
276
277 #ifdef NEED_COPY
278 DBT k;
279
280 k.data = key.dptr;
281 k.size = key.dsize;
282 status = (db->del)(db, &k, 0);
283 #else
284 status = (db->del)(db, (DBT *)&key, 0);
285 #endif
286 if (status)
287 return (-1);
288 else
289 return (0);
290 }
291
292 /*
293 * Returns:
294 * 0 on success
295 * <0 failure
296 * 1 if DBM_INSERT and entry exists
297 */
298 int
kdb2_dbm_store(DBM * db,datum key,datum content,int flags)299 kdb2_dbm_store(DBM *db, datum key, datum content, int flags)
300 {
301 #ifdef NEED_COPY
302 DBT k, c;
303
304 k.data = key.dptr;
305 k.size = key.dsize;
306 c.data = content.dptr;
307 c.size = content.dsize;
308 return ((db->put)(db, &k, &c,
309 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
310 #else
311 return ((db->put)(db, (DBT *)&key, (DBT *)&content,
312 (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
313 #endif
314 }
315
316 int
kdb2_dbm_error(DBM * db)317 kdb2_dbm_error(DBM *db)
318 {
319 HTAB *hp;
320
321 hp = (HTAB *)db->internal;
322 return (hp->local_errno);
323 }
324
325 int
kdb2_dbm_clearerr(DBM * db)326 kdb2_dbm_clearerr(DBM *db)
327 {
328 HTAB *hp;
329
330 hp = (HTAB *)db->internal;
331 hp->local_errno = 0;
332 return (0);
333 }
334
335 int
kdb2_dbm_dirfno(DBM * db)336 kdb2_dbm_dirfno(DBM *db)
337 {
338 return(((HTAB *)db->internal)->fp);
339 }
340