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