summaryrefslogtreecommitdiffabout
path: root/libetpan/src/data-types/mail_cache_db.c
Unidiff
Diffstat (limited to 'libetpan/src/data-types/mail_cache_db.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/data-types/mail_cache_db.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/libetpan/src/data-types/mail_cache_db.c b/libetpan/src/data-types/mail_cache_db.c
new file mode 100644
index 0000000..0b73775
--- a/dev/null
+++ b/libetpan/src/data-types/mail_cache_db.c
@@ -0,0 +1,403 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "mail_cache_db.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <stdlib.h>
42#include <string.h>
43
44#ifndef CONFIG_H
45#define CONFIG_H
46#include "config.h"
47#endif
48
49#include "libetpan-config.h"
50
51#include "maillock.h"
52
53#if DBVERS >= 1
54#include <db.h>
55#endif
56
57#if DBVERS >= 1
58static struct mail_cache_db * mail_cache_db_new(DB * db)
59{
60 struct mail_cache_db * cache_db;
61
62 cache_db = malloc(sizeof(* cache_db));
63 if (cache_db == NULL)
64 return NULL;
65 cache_db->internal_database = db;
66
67 return cache_db;
68}
69
70static void mail_cache_db_free(struct mail_cache_db * cache_db)
71{
72 free(cache_db);
73}
74#endif
75
76int mail_cache_db_open(const char * filename,
77 struct mail_cache_db ** pcache_db)
78{
79#if DBVERS >= 1
80 DB * dbp;
81 int r;
82 struct mail_cache_db * cache_db;
83
84#if DB_VERSION_MAJOR >= 3
85 r = db_create(&dbp, NULL, 0);
86 if (r != 0)
87 goto err;
88
89#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1))
90 r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE,
91 S_IRUSR | S_IWUSR);
92#else
93 r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR);
94#endif
95 if (r != 0)
96 goto close_db;
97#else
98#if DBVERS > 1
99 r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR,
100 NULL, NULL, &dbp);
101 if (r != 0)
102 goto err;
103#elif DBVERS == 1
104 dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL);
105 if (dbp == NULL)
106 goto err;
107#else
108 goto err;
109#endif
110#endif
111
112 cache_db = mail_cache_db_new(dbp);
113 if (cache_db == NULL)
114 goto close_db;
115
116 * pcache_db = cache_db;
117
118 return 0;
119
120 close_db:
121#if DBVERS > 1
122 dbp->close(dbp, 0);
123#elif DBVERS == 1
124 dbp->close(dbp);
125#endif
126 err:
127 return -1;
128#else
129 return -1;
130#endif
131}
132
133void mail_cache_db_close(struct mail_cache_db * cache_db)
134{
135#if DBVERS >= 1
136 DB * dbp;
137
138 dbp = cache_db->internal_database;
139
140#if DBVERS > 1
141 dbp->close(cache_db->internal_database, 0);
142#elif DBVERS == 1
143 dbp->close(cache_db->internal_database);
144#endif
145
146 mail_cache_db_free(cache_db);
147#endif
148}
149
150int mail_cache_db_open_lock(const char * filename,
151 struct mail_cache_db ** pcache_db)
152{
153 int r;
154 struct mail_cache_db * cache_db;
155
156 r = maillock_write_lock(filename, -1);
157 if (r < 0)
158 goto err;
159
160 r = mail_cache_db_open(filename, &cache_db);
161 if (r < 0)
162 goto unlock;
163
164 * pcache_db = cache_db;
165
166 return 0;
167
168 unlock:
169 maillock_write_unlock(filename, -1);
170 err:
171 return -1;
172}
173
174void mail_cache_db_close_unlock(const char * filename,
175 struct mail_cache_db * cache_db)
176{
177 maillock_write_unlock(filename, -1);
178 mail_cache_db_close(cache_db);
179}
180
181
182int mail_cache_db_put(struct mail_cache_db * cache_db,
183 const void * key, size_t key_len, const void * value, size_t value_len)
184{
185#if DBVERS >= 1
186 int r;
187 DBT db_key;
188 DBT db_data;
189 DB * dbp;
190
191 dbp = cache_db->internal_database;
192
193 memset(&db_key, 0, sizeof(db_key));
194 memset(&db_data, 0, sizeof(db_data));
195 db_key.data = (void *) key;
196 db_key.size = key_len;
197 db_data.data = (void *) value;
198 db_data.size = value_len;
199
200#if DBVERS > 1
201 r = dbp->put(dbp, NULL, &db_key, &db_data, 0);
202#elif DBVERS == 1
203 r = dbp->put(dbp, &db_key, &db_data, 0);
204#else
205 r = -1;
206#endif
207
208 return r;
209#else
210 return -1;
211#endif
212}
213
214int mail_cache_db_get(struct mail_cache_db * cache_db,
215 const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len)
216{
217#if DBVERS >= 1
218 int r;
219 DBT db_key;
220 DBT db_data;
221 DB * dbp;
222
223 dbp = cache_db->internal_database;
224
225 memset(&db_key, 0, sizeof(db_key));
226 memset(&db_data, 0, sizeof(db_data));
227 db_key.data = (void *) key;
228 db_key.size = key_len;
229
230#if DBVERS > 1
231 r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
232#elif DBVERS == 1
233 r = dbp->get(dbp, &db_key, &db_data, 0);
234#else
235 r = -1;
236#endif
237
238 if (r != 0)
239 return r;
240
241 * pvalue = db_data.data;
242 * pvalue_len = db_data.size;
243
244 return 0;
245#else
246 return -1;
247#endif
248}
249
250int mail_cache_db_del(struct mail_cache_db * cache_db,
251 const void * key, size_t key_len)
252{
253#if DBVERS >= 1
254 int r;
255 DBT db_key;
256 DB * dbp;
257
258 dbp = cache_db->internal_database;
259
260 memset(&db_key, 0, sizeof(db_key));
261 db_key.data = (void *) key;
262 db_key.size = key_len;
263
264#if DBVERS > 1
265 r = dbp->del(dbp, NULL, &db_key, 0);
266#elif DBVERS == 1
267 r = dbp->del(dbp, &db_key, 0);
268#else
269 r = -1;
270#endif
271
272 return r;
273#else
274 return -1;
275#endif
276}
277
278#if DBVERS > 1
279int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
280 chash * exist)
281{
282 DB * dbp;
283 int r;
284 DBC * dbcp;
285 DBT db_key;
286 DBT db_data;
287
288 dbp = cache_db->internal_database;
289
290 r = dbp->cursor(dbp, NULL, &dbcp, 0);
291 if (r != 0)
292 return r;
293
294 memset(&db_key, 0, sizeof(db_key));
295 memset(&db_data, 0, sizeof(db_data));
296
297 while (1) {
298 chashdatum hash_key;
299 chashdatum hash_data;
300
301 r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT);
302 if (r != 0)
303 break;
304
305 hash_key.data = db_key.data;
306 hash_key.len = db_key.size;
307
308 r = chash_get(exist, &hash_key, &hash_data);
309 if (r < 0) {
310 r = dbcp->c_del(dbcp, 0);
311 if (r != 0)
312 return r;
313 }
314 }
315
316 r = dbcp->c_close(dbcp);
317 if (r != 0)
318 return r;
319
320 return 0;
321}
322#elif DBVERS == 1
323int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
324 chash * exist)
325{
326 DB * dbp;
327 int r;
328 DBT db_key;
329 DBT db_data;
330
331 dbp = cache_db->internal_database;
332
333 r = dbp->seq(dbp, &db_key, &db_data, R_FIRST);
334 if (r == -1)
335 return r;
336
337 while (r == 0) {
338 chashdatum hash_key;
339 chashdatum hash_data;
340
341 hash_key.data = db_key.data;
342 hash_key.len = db_key.size;
343
344 r = chash_get(exist, &hash_key, &hash_data);
345 if (r < 0) {
346 r = dbp->del(dbp, &db_key, 0);
347 if (r != 0)
348 return r;
349 }
350
351 r = dbp->seq(dbp, &db_key, &db_data, R_NEXT);
352 if (r == -1)
353 return r;
354 }
355
356 return 0;
357}
358#else
359int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
360 chash * exist)
361{
362 return -1;
363}
364#endif
365
366int mail_cache_db_get_size(struct mail_cache_db * cache_db,
367 const void * key, size_t key_len, size_t * pvalue_len)
368{
369#if DBVERS >= 1
370 int r;
371 DBT db_key;
372 DBT db_data;
373 DB * dbp;
374
375 dbp = cache_db->internal_database;
376
377 memset(&db_key, 0, sizeof(db_key));
378 memset(&db_data, 0, sizeof(db_data));
379 db_key.data = (void *) key;
380 db_key.size = key_len;
381#if DBVERS > 1
382 db_data.flags = DB_DBT_USERMEM;
383 db_data.ulen = 0;
384#endif
385
386#if DBVERS > 1
387 r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
388#elif DBVERS == 1
389 r = dbp->get(dbp, &db_key, &db_data, 0);
390#else
391 r = -1;
392#endif
393
394 if (r != 0)
395 return r;
396
397 * pvalue_len = db_data.size;
398
399 return 0;
400#else
401 return -1;
402#endif
403}