xref: /freebsd/crypto/heimdal/lib/roken/ndbm_wrap.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /*
2  * Copyright (c) 2002 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
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  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <config.h>
35 
36 #include "ndbm_wrap.h"
37 #if defined(HAVE_DBHEADER)
38 #include <db.h>
39 #elif defined(HAVE_DB5_DB_H)
40 #include <db5/db.h>
41 #elif defined(HAVE_DB4_DB_H)
42 #include <db4/db.h>
43 #elif defined(HAVE_DB3_DB_H)
44 #include <db3/db.h>
45 #else
46 #include <db.h>
47 #endif
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <fcntl.h>
53 
54 /* XXX undefine open so this works on Solaris with large file support */
55 #undef open
56 
57 #define DBT2DATUM(DBT, DATUM) do { (DATUM)->dptr = (DBT)->data; (DATUM)->dsize = (DBT)->size; } while(0)
58 #define DATUM2DBT(DATUM, DBT) do { (DBT)->data = (DATUM)->dptr; (DBT)->size = (DATUM)->dsize; } while(0)
59 #define RETURN(X) return ((X) == 0) ? 0 : -1
60 
61 #ifdef HAVE_DB3
62 static DBC *cursor;
63 #endif
64 
65 #define D(X) ((DB*)(X))
66 
67 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
68 dbm_close (DBM *db)
69 {
70 #ifdef HAVE_DB3
71     D(db)->close(D(db), 0);
72     cursor = NULL;
73 #else
74     D(db)->close(D(db));
75 #endif
76 }
77 
78 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
79 dbm_delete (DBM *db, datum dkey)
80 {
81     DBT key;
82     DATUM2DBT(&dkey, &key);
83 #ifdef HAVE_DB3
84     RETURN(D(db)->del(D(db), NULL, &key, 0));
85 #else
86     RETURN(D(db)->del(D(db), &key, 0));
87 #endif
88 }
89 
90 datum
91 dbm_fetch (DBM *db, datum dkey)
92 {
93     datum dvalue;
94     DBT key, value;
95     DATUM2DBT(&dkey, &key);
96     if(D(db)->get(D(db),
97 #ifdef HAVE_DB3
98 	       NULL,
99 #endif
100 	       &key, &value, 0) != 0) {
101 	dvalue.dptr = NULL;
102 	dvalue.dsize = 0;
103     }
104     else
105 	DBT2DATUM(&value, &dvalue);
106 
107     return dvalue;
108 }
109 
110 static datum
111 dbm_get (DB *db, int flags)
112 {
113     DBT key, value;
114     datum datum;
115 #ifdef HAVE_DB3
116     if(cursor == NULL)
117 	db->cursor(db, NULL, &cursor, 0);
118     if(cursor->c_get(cursor, &key, &value, flags) != 0) {
119 	datum.dptr = NULL;
120 	datum.dsize = 0;
121     } else
122 	DBT2DATUM(&value, &datum);
123 #else
124     db->seq(db, &key, &value, flags);
125     DBT2DATUM(&value, &datum);
126 #endif
127     return datum;
128 }
129 
130 #ifndef DB_FIRST
131 #define DB_FIRST	R_FIRST
132 #define DB_NEXT		R_NEXT
133 #define DB_NOOVERWRITE	R_NOOVERWRITE
134 #define DB_KEYEXIST	1
135 #endif
136 
137 ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL
138 dbm_firstkey (DBM *db)
139 {
140     return dbm_get(D(db), DB_FIRST);
141 }
142 
143 ROKEN_LIB_FUNCTION datum ROKEN_LIB_CALL
144 dbm_nextkey (DBM *db)
145 {
146     return dbm_get(D(db), DB_NEXT);
147 }
148 
149 ROKEN_LIB_FUNCTION DBM* ROKEN_LIB_CALL
150 dbm_open (const char *file, int flags, mode_t mode)
151 {
152 #ifdef HAVE_DB3
153     int myflags = 0;
154 #endif
155     DB *db;
156     char *fn = malloc(strlen(file) + 4);
157     if(fn == NULL)
158 	return NULL;
159     strcpy(fn, file);
160     strcat(fn, ".db");
161 #ifdef HAVE_DB3
162     if (flags & O_CREAT)
163 	myflags |= DB_CREATE;
164 
165     if (flags & O_EXCL)
166 	myflags |= DB_EXCL;
167 
168     if (flags & O_RDONLY)
169 	myflags |= DB_RDONLY;
170 
171     if (flags & O_TRUNC)
172 	myflags |= DB_TRUNCATE;
173     if(db_create(&db, NULL, 0) != 0) {
174 	free(fn);
175 	return NULL;
176     }
177 
178 #if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
179     if(db->open(db, NULL, fn, NULL, DB_BTREE, myflags, mode) != 0) {
180 #else
181     if(db->open(db, fn, NULL, DB_BTREE, myflags, mode) != 0) {
182 #endif
183 	free(fn);
184 	db->close(db, 0);
185 	return NULL;
186     }
187 #else
188     db = dbopen(fn, flags, mode, DB_BTREE, NULL);
189 #endif
190     free(fn);
191     return (DBM*)db;
192 }
193 
194 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
195 dbm_store (DBM *db, datum dkey, datum dvalue, int flags)
196 {
197     int ret;
198     DBT key, value;
199     int myflags = 0;
200     if((flags & DBM_REPLACE) == 0)
201 	myflags |= DB_NOOVERWRITE;
202     DATUM2DBT(&dkey, &key);
203     DATUM2DBT(&dvalue, &value);
204     ret = D(db)->put(D(db),
205 #ifdef HAVE_DB3
206 		     NULL,
207 #endif
208 &key, &value, myflags);
209     if(ret == DB_KEYEXIST)
210 	return 1;
211     RETURN(ret);
212 }
213 
214 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
215 dbm_error (DBM *db)
216 {
217     return 0;
218 }
219 
220 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
221 dbm_clearerr (DBM *db)
222 {
223     return 0;
224 }
225 
226