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