Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / bdbobj / bdbobj.c
1 /*
2 ** Copyright 1998 - 2003 Double Precision, Inc. See COPYING for
3 ** distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <fcntl.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #if HAVE_FCNTL_H
14 #include <fcntl.h>
15 #endif
16 #if HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif
19
20 #include "bdbobj.h"
21
22 void bdbobj_init(struct bdbobj *obj)
23 {
24 obj->has_dbf=0;
25
26 #if DB_VERSION_MAJOR >= 2
27 obj->has_dbc=0;
28 #endif
29 }
30
31 void bdbobj_close(struct bdbobj *obj)
32 {
33 #if DB_VERSION_MAJOR >= 2
34 if (obj->has_dbc)
35 {
36 (*obj->dbc->c_close)(obj->dbc);
37 obj->has_dbc=0;
38 }
39 #endif
40 if ( obj->has_dbf )
41 {
42 #if DB_VERSION_MAJOR < 2
43 (*obj->dbf->close)(obj->dbf);
44 #else
45 (*obj->dbf->close)(obj->dbf, 0);
46 #endif
47 obj->has_dbf=0;
48 }
49 }
50
51 int bdbobj_open(struct bdbobj *obj, const char *filename, const char *modestr)
52 {
53 #if DB_VERSION_MAJOR < 2
54
55 int flags=O_RDONLY;
56
57 #else
58
59 int flags=DB_RDONLY;
60
61 #endif
62
63 DBTYPE dbtype=DB_HASH;
64
65 for ( ; *modestr; modestr++)
66 switch (*modestr) {
67 case 'c':
68 case 'C':
69 #if DB_VERSION_MAJOR < 2
70 flags=O_RDWR|O_CREAT;
71 #else
72 flags=DB_CREATE;
73 #endif
74 break;
75 case 'w':
76 case 'W':
77 #if DB_VERSION_MAJOR < 2
78 flags=O_RDWR;
79 #else
80 flags=0;
81 #endif
82 break;
83 case 'n':
84 case 'N':
85 #if DB_VERSION_MAJOR < 2
86 flags=O_RDWR|O_CREAT|O_TRUNC;
87 #else
88 flags=DB_CREATE|DB_TRUNCATE;
89 #endif
90
91 break;
92
93 case 'b':
94 case 'B':
95 dbtype=DB_BTREE;
96 break;
97
98 case 'e':
99 case 'E':
100 dbtype=DB_RECNO;
101 break;
102 }
103
104 bdbobj_close(obj);
105
106 #if DB_VERSION_MAJOR < 3
107 #if DB_VERSION_MAJOR < 2
108 if ( (obj->dbf=dbopen(filename, flags, 0664, dbtype, 0)) != 0)
109 #else
110 if ( db_open(filename, dbtype, flags, 0664, 0, 0, &obj->dbf) == 0)
111 #endif
112 #else
113 obj->dbf=0;
114
115 #define DB_40 0
116
117 #if DB_VERSION_MAJOR == 4
118 #if DB_VERSION_MINOR == 0
119
120 #undef DB_40
121 #define DB_40 1
122
123 #endif
124 #endif
125
126 #if DB_VERSION_MAJOR == 3
127 #undef DB_40
128 #define DB_40 1
129 #endif
130
131 if (db_create(&obj->dbf, NULL, 0) == 0)
132 {
133 if ( (*obj->dbf->open)(obj->dbf,
134
135 #if DB_40
136
137 #else
138 NULL,
139 #endif
140
141 filename, NULL,
142 dbtype, flags, 0664))
143 {
144 (*obj->dbf->close)(obj->dbf, DB_NOSYNC);
145 obj->dbf=0;
146 }
147 }
148
149 if (obj->dbf)
150 #endif
151 {
152 #ifdef FD_CLOEXEC
153
154 #if DB_VERSION_MAJOR < 2
155 int fd=(*obj->dbf->fd)(obj->dbf);
156 #else
157 int fd;
158
159 if ((*obj->dbf->fd)(obj->dbf, &fd))
160 fd= -1;
161 #endif
162
163 if (fd >= 0) fcntl(fd, F_SETFD, FD_CLOEXEC);
164 #endif
165
166
167 obj->has_dbf=1;
168 return (0);
169 }
170 return (-1);
171 }
172
173 int bdbobj_store(struct bdbobj *obj, const char *key, size_t keylen,
174 const char *data,
175 size_t datalen,
176 const char *mode)
177 {
178 DBT dkey, dval;
179
180 memset(&dkey, 0, sizeof(dkey));
181 memset(&dval, 0, sizeof(dval));
182
183 dkey.data=(void *)key;
184 dkey.size=keylen;
185 dval.data=(void *)data;
186 dval.size=datalen;
187
188 #if DB_VERSION_MAJOR < 2
189 return (obj->has_dbf ? (*obj->dbf->put)(obj->dbf, &dkey, &dval, (
190 *mode == 'i' || *mode == 'I' ? R_NOOVERWRITE:0)):-1);
191 #else
192 return (obj->has_dbf ? (*obj->dbf->put)(obj->dbf, 0, &dkey, &dval, (
193 *mode == 'i' || *mode == 'I' ? DB_NOOVERWRITE:0)):-1);
194 #endif
195 }
196
197 static char *doquery(struct bdbobj *obj,
198 const char *, size_t, size_t *, const char *);
199
200 char *bdbobj_fetch(struct bdbobj *obj, const char *key, size_t keylen,
201 size_t *datalen, const char *options)
202 {
203 char *p=doquery(obj, key, keylen, datalen, options);
204 char *q;
205
206 if (!p) return (0);
207
208 q=(char *)malloc(*datalen);
209
210 if (!q) return (0);
211
212 memcpy(q, p, *datalen);
213 return (q);
214 }
215
216 char *dofetch(struct bdbobj *, const char *, size_t, size_t *);
217
218 static char *doquery(struct bdbobj *obj, const char *key, size_t keylen,
219 size_t *datalen, const char *options)
220 {
221 char *p;
222
223 for (;;)
224 {
225 if ((p=dofetch(obj, key, keylen, datalen)) != 0)
226 return (p);
227 if (!options) break;
228 if (*options == 'I')
229 {
230 while (keylen && key[--keylen] != '.')
231 ;
232 if (!keylen) break;
233 continue;
234 }
235 if (*options == 'D')
236 {
237 size_t i;
238
239 for (i=0; i<keylen; i++)
240 if (key[i] == '@') { ++i; break; }
241 if (i < keylen)
242 {
243 if ((p=dofetch(obj, key, i, datalen)) != 0)
244 return (p);
245 key += i;
246 keylen -= i;
247 continue;
248 }
249
250 for (i=0; i<keylen; i++)
251 if (key[i] == '.') { ++i; break; }
252 if (i < keylen)
253 {
254 key += i;
255 keylen -= i;
256 continue;
257 }
258 break;
259 }
260 break;
261 }
262 return (0);
263 }
264
265 char *dofetch(struct bdbobj *obj, const char *key, size_t keylen,
266 size_t *datalen)
267 {
268 DBT dkey, val;
269
270 if (!obj->has_dbf) return (0);
271
272 memset(&dkey, 0, sizeof(dkey));
273 memset(&val, 0, sizeof(val));
274
275 dkey.data=(void *)key;
276 dkey.size=keylen;
277
278 #if DB_VERSION_MAJOR < 2
279 if ( (*obj->dbf->get)(obj->dbf, &dkey, &val, 0)) return (0);
280 #else
281 if ( (*obj->dbf->get)(obj->dbf, 0, &dkey, &val, 0)) return (0);
282 #endif
283
284 *datalen=val.size;
285 return ((char *)val.data);
286 }
287
288 int bdbobj_exists(struct bdbobj *obj, const char *key, size_t keylen)
289 {
290 size_t datalen;
291 char *p=doquery(obj, key, keylen, &datalen, 0);
292
293 return (p ? 1:0);
294 }