xref: /freebsd/crypto/krb5/src/plugins/kdb/db2/libdb2/hash/dbm.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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