Imported Upstream version 0.63.0
[hcoop/debian/courier-authlib.git] / gdbmobj / gdbmobj.c
1 /*
2 ** Copyright 1998 - 2000 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 "gdbmobj.h"
11 #include <stdlib.h>
12 #if HAVE_FCNTL_H
13 #include <fcntl.h>
14 #endif
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18
19 static const char rcsid[]="$Id: gdbmobj.c,v 1.9 2006/10/28 19:22:52 mrsam Exp $";
20
21 void gdbmobj_init(struct gdbmobj *obj)
22 {
23 obj->has_dbf=0;
24 obj->prev_key=0;
25 obj->prev_key_len=0;
26 }
27
28 void gdbmobj_close(struct gdbmobj *obj)
29 {
30 if (obj->has_dbf)
31 {
32 obj->has_dbf=0;
33 gdbm_close(obj->dbf);
34 }
35 if (obj->prev_key)
36 {
37 free(obj->prev_key);
38 obj->prev_key=0;
39 }
40 }
41
42 int gdbmobj_open(struct gdbmobj *obj, const char *filename, const char *modestr)
43 {
44 int mode=GDBM_READER;
45
46 for ( ; *modestr; modestr++)
47 switch (*modestr) {
48 case 'c':
49 case 'C':
50 mode=GDBM_WRCREAT;
51 break;
52 case 'w':
53 case 'W':
54 mode=GDBM_WRITER;
55 break;
56 case 'n':
57 case 'N':
58 mode=GDBM_NEWDB;
59 break;
60 }
61
62 gdbmobj_close(obj);
63 if ((obj->dbf=gdbm_open((char *)filename, 0, mode, 0664, 0)) != 0)
64 {
65 /* Where possible, set the close-on-exec bit */
66
67 #if HAVE_GDBM_FDESC
68 #ifdef FD_CLOEXEC
69
70 int fd=gdbm_fdesc(obj->dbf);
71
72 if (fd >= 0) fcntl(fd, F_SETFD, FD_CLOEXEC);
73 #endif
74 #endif
75
76 obj->has_dbf=1;
77 return (0);
78 }
79 return (-1);
80 }
81
82 int gdbmobj_store(struct gdbmobj *obj, const char *key, size_t keylen,
83 const char *data,
84 size_t datalen,
85 const char *mode)
86 {
87 datum dkey;
88 datum dval;
89
90 dkey.dptr=(char *)key;
91 dkey.dsize=keylen;
92
93 dval.dptr=(char *)data;
94 dval.dsize=datalen;
95
96 return (obj->has_dbf ? gdbm_store(obj->dbf, dkey, dval, (
97 *mode == 'i' || *mode == 'I' ?
98 GDBM_INSERT:GDBM_REPLACE)):-1);
99 }
100
101 int gdbmobj_exists(struct gdbmobj *obj, const char *key, size_t keylen)
102 {
103 datum dkey;
104
105 if (!obj->has_dbf) return (0);
106
107 dkey.dptr=(char *)key;
108 dkey.dsize=keylen;
109
110 if (gdbm_exists(obj->dbf, dkey)) return (1);
111 return (0);
112 }
113
114 char *gdbm_dofetch(struct gdbmobj *, const char *, size_t, size_t *);
115
116 char *gdbmobj_fetch(struct gdbmobj *obj, const char *key, size_t keylen,
117 size_t *datalen, const char *options)
118 {
119 char *p;
120
121 for (;;)
122 {
123 if ((p=gdbm_dofetch(obj, key, keylen, datalen)) != 0)
124 return (p);
125 if (!options) break;
126 if (*options == 'I')
127 {
128 while (keylen && key[--keylen] != '.')
129 ;
130 if (!keylen) break;
131 continue;
132 }
133 if (*options == 'D')
134 {
135 size_t i;
136
137 for (i=0; i<keylen; i++)
138 if (key[i] == '@') { ++i; break; }
139 if (i < keylen)
140 {
141 if ((p=gdbm_dofetch(obj, key, i, datalen)) != 0)
142 return (p);
143 key += i;
144 keylen -= i;
145 continue;
146 }
147
148 for (i=0; i<keylen; i++)
149 if (key[i] == '.') { ++i; break; }
150 if (i < keylen)
151 {
152 key += i;
153 keylen -= i;
154 continue;
155 }
156 break;
157 }
158 break;
159 }
160 return (0);
161 }
162
163 char *gdbm_dofetch(struct gdbmobj *obj,
164 const char *key, size_t keylen, size_t *datalen)
165 {
166 datum dkey, val;
167
168 if (!obj->has_dbf) return (0);
169
170 dkey.dptr=(char *)key;
171 dkey.dsize=keylen;
172
173 val=gdbm_fetch(obj->dbf, dkey);
174
175 if (!val.dptr) return (0);
176 *datalen=val.dsize;
177 return (val.dptr);
178 }