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)
44 static 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 */
73 static DBM *__cur_db;
74
75 static void no_open_db __P((void));
76
77 int
kdb2_dbminit(file)78 kdb2_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
90 datum
kdb2_fetch(key)91 kdb2_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
105 datum
kdb2_firstkey()106 kdb2_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
119 datum
kdb2_nextkey(key)120 kdb2_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
134 int
kdb2_delete(key)135 kdb2_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
145 int
kdb2_store(key,dat)146 kdb2_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
156 static void
no_open_db()157 no_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 */
168 DBM *
kdb2_dbm_open(file,flags,mode)169 kdb2_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 */
192 void
kdb2_dbm_close(db)193 kdb2_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 */
204 datum
kdb2_dbm_fetch(db,key)205 kdb2_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 */
235 datum
kdb2_dbm_firstkey(db)236 kdb2_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 */
263 datum
kdb2_dbm_nextkey(db)264 kdb2_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 */
291 int
kdb2_dbm_delete(db,key)292 kdb2_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 */
319 int
kdb2_dbm_store(db,key,content,flags)320 kdb2_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
340 int
kdb2_dbm_error(db)341 kdb2_dbm_error(db)
342 DBM *db;
343 {
344 HTAB *hp;
345
346 hp = (HTAB *)db->internal;
347 return (hp->local_errno);
348 }
349
350 int
kdb2_dbm_clearerr(db)351 kdb2_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
361 int
kdb2_dbm_dirfno(db)362 kdb2_dbm_dirfno(db)
363 DBM *db;
364 {
365 return(((HTAB *)db->internal)->fp);
366 }
367