Merge branch 'debian'
[hcoop/debian/courier-authlib.git] / libs / bdbobj / bdbobj.c
CommitLineData
d9898ee8 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
22void 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
31void 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
51int bdbobj_open(struct bdbobj *obj, const char *filename, const char *modestr)
52{
53#if DB_VERSION_MAJOR < 2
54
55int flags=O_RDONLY;
56
57#else
58
59int flags=DB_RDONLY;
60
61#endif
62
63DBTYPE 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
173int bdbobj_store(struct bdbobj *obj, const char *key, size_t keylen,
174 const char *data,
175 size_t datalen,
176 const char *mode)
177{
178DBT 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
197static char *doquery(struct bdbobj *obj,
198 const char *, size_t, size_t *, const char *);
199
200char *bdbobj_fetch(struct bdbobj *obj, const char *key, size_t keylen,
201 size_t *datalen, const char *options)
202{
203char *p=doquery(obj, key, keylen, datalen, options);
204char *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
216char *dofetch(struct bdbobj *, const char *, size_t, size_t *);
217
218static char *doquery(struct bdbobj *obj, const char *key, size_t keylen,
219 size_t *datalen, const char *options)
220{
221char *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
265char *dofetch(struct bdbobj *obj, const char *key, size_t keylen,
266 size_t *datalen)
267{
268DBT 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
288int bdbobj_exists(struct bdbobj *obj, const char *key, size_t keylen)
289{
290size_t datalen;
291char *p=doquery(obj, key, keylen, &datalen, 0);
292
293 return (p ? 1:0);
294}