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 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 RCSID("$Id: ndbm_wrap.c 21634 2007-07-17 11:30:36Z lha $");
37 #endif
38
39 #include "ndbm_wrap.h"
40 #if defined(HAVE_DB4_DB_H)
41 #include <db4/db.h>
42 #elif defined(HAVE_DB3_DB_H)
43 #include <db3/db.h>
44 #else
45 #include <db.h>
46 #endif
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <fcntl.h>
52
53 /* XXX undefine open so this works on Solaris with large file support */
54 #undef open
55
56 #define DBT2DATUM(DBT, DATUM) do { (DATUM)->dptr = (DBT)->data; (DATUM)->dsize = (DBT)->size; } while(0)
57 #define DATUM2DBT(DATUM, DBT) do { (DBT)->data = (DATUM)->dptr; (DBT)->size = (DATUM)->dsize; } while(0)
58 #define RETURN(X) return ((X) == 0) ? 0 : -1
59
60 #ifdef HAVE_DB3
61 static DBC *cursor;
62 #endif
63
64 #define D(X) ((DB*)(X))
65
66 void ROKEN_LIB_FUNCTION
dbm_close(DBM * db)67 dbm_close (DBM *db)
68 {
69 #ifdef HAVE_DB3
70 D(db)->close(D(db), 0);
71 cursor = NULL;
72 #else
73 D(db)->close(D(db));
74 #endif
75 }
76
77 int ROKEN_LIB_FUNCTION
dbm_delete(DBM * db,datum dkey)78 dbm_delete (DBM *db, datum dkey)
79 {
80 DBT key;
81 DATUM2DBT(&dkey, &key);
82 #ifdef HAVE_DB3
83 RETURN(D(db)->del(D(db), NULL, &key, 0));
84 #else
85 RETURN(D(db)->del(D(db), &key, 0));
86 #endif
87 }
88
89 datum
dbm_fetch(DBM * db,datum dkey)90 dbm_fetch (DBM *db, datum dkey)
91 {
92 datum dvalue;
93 DBT key, value;
94 DATUM2DBT(&dkey, &key);
95 if(D(db)->get(D(db),
96 #ifdef HAVE_DB3
97 NULL,
98 #endif
99 &key, &value, 0) != 0) {
100 dvalue.dptr = NULL;
101 dvalue.dsize = 0;
102 }
103 else
104 DBT2DATUM(&value, &dvalue);
105
106 return dvalue;
107 }
108
109 static datum
dbm_get(DB * db,int flags)110 dbm_get (DB *db, int flags)
111 {
112 DBT key, value;
113 datum datum;
114 #ifdef HAVE_DB3
115 if(cursor == NULL)
116 db->cursor(db, NULL, &cursor, 0);
117 if(cursor->c_get(cursor, &key, &value, flags) != 0) {
118 datum.dptr = NULL;
119 datum.dsize = 0;
120 } else
121 DBT2DATUM(&value, &datum);
122 #else
123 db->seq(db, &key, &value, flags);
124 #endif
125 return datum;
126 }
127
128 #ifndef DB_FIRST
129 #define DB_FIRST R_FIRST
130 #define DB_NEXT R_NEXT
131 #define DB_NOOVERWRITE R_NOOVERWRITE
132 #define DB_KEYEXIST 1
133 #endif
134
135 datum ROKEN_LIB_FUNCTION
dbm_firstkey(DBM * db)136 dbm_firstkey (DBM *db)
137 {
138 return dbm_get(D(db), DB_FIRST);
139 }
140
141 datum ROKEN_LIB_FUNCTION
dbm_nextkey(DBM * db)142 dbm_nextkey (DBM *db)
143 {
144 return dbm_get(D(db), DB_NEXT);
145 }
146
147 DBM* ROKEN_LIB_FUNCTION
dbm_open(const char * file,int flags,mode_t mode)148 dbm_open (const char *file, int flags, mode_t mode)
149 {
150 DB *db;
151 int myflags = 0;
152 char *fn = malloc(strlen(file) + 4);
153 if(fn == NULL)
154 return NULL;
155 strcpy(fn, file);
156 strcat(fn, ".db");
157 #ifdef HAVE_DB3
158 if (flags & O_CREAT)
159 myflags |= DB_CREATE;
160
161 if (flags & O_EXCL)
162 myflags |= DB_EXCL;
163
164 if (flags & O_RDONLY)
165 myflags |= DB_RDONLY;
166
167 if (flags & O_TRUNC)
168 myflags |= DB_TRUNCATE;
169 if(db_create(&db, NULL, 0) != 0) {
170 free(fn);
171 return NULL;
172 }
173
174 #if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
175 if(db->open(db, NULL, fn, NULL, DB_BTREE, myflags, mode) != 0) {
176 #else
177 if(db->open(db, fn, NULL, DB_BTREE, myflags, mode) != 0) {
178 #endif
179 free(fn);
180 db->close(db, 0);
181 return NULL;
182 }
183 #else
184 db = dbopen(fn, flags, mode, DB_BTREE, NULL);
185 #endif
186 free(fn);
187 return (DBM*)db;
188 }
189
190 int ROKEN_LIB_FUNCTION
191 dbm_store (DBM *db, datum dkey, datum dvalue, int flags)
192 {
193 int ret;
194 DBT key, value;
195 int myflags = 0;
196 if((flags & DBM_REPLACE) == 0)
197 myflags |= DB_NOOVERWRITE;
198 DATUM2DBT(&dkey, &key);
199 DATUM2DBT(&dvalue, &value);
200 ret = D(db)->put(D(db),
201 #ifdef HAVE_DB3
202 NULL,
203 #endif
204 &key, &value, myflags);
205 if(ret == DB_KEYEXIST)
206 return 1;
207 RETURN(ret);
208 }
209
210 int ROKEN_LIB_FUNCTION
211 dbm_error (DBM *db)
212 {
213 return 0;
214 }
215
216 int ROKEN_LIB_FUNCTION
217 dbm_clearerr (DBM *db)
218 {
219 return 0;
220 }
221
222