summaryrefslogtreecommitdiffabout
path: root/libetpan/src/data-types/mail_cache_db.c
Side-by-side diff
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 @@
+/*
+ * libEtPan! -- a mail stuff library
+ *
+ * Copyright (C) 2001, 2005 - DINH Viet Hoa
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the libEtPan! project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "mail_cache_db.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef CONFIG_H
+#define CONFIG_H
+#include "config.h"
+#endif
+
+#include "libetpan-config.h"
+
+#include "maillock.h"
+
+#if DBVERS >= 1
+#include <db.h>
+#endif
+
+#if DBVERS >= 1
+static struct mail_cache_db * mail_cache_db_new(DB * db)
+{
+ struct mail_cache_db * cache_db;
+
+ cache_db = malloc(sizeof(* cache_db));
+ if (cache_db == NULL)
+ return NULL;
+ cache_db->internal_database = db;
+
+ return cache_db;
+}
+
+static void mail_cache_db_free(struct mail_cache_db * cache_db)
+{
+ free(cache_db);
+}
+#endif
+
+int mail_cache_db_open(const char * filename,
+ struct mail_cache_db ** pcache_db)
+{
+#if DBVERS >= 1
+ DB * dbp;
+ int r;
+ struct mail_cache_db * cache_db;
+
+#if DB_VERSION_MAJOR >= 3
+ r = db_create(&dbp, NULL, 0);
+ if (r != 0)
+ goto err;
+
+#if (DB_VERSION_MAJOR >= 4) && ((DB_VERSION_MAJOR > 4) || (DB_VERSION_MINOR >= 1))
+ r = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, DB_CREATE,
+ S_IRUSR | S_IWUSR);
+#else
+ r = dbp->open(dbp, filename, NULL, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR);
+#endif
+ if (r != 0)
+ goto close_db;
+#else
+#if DBVERS > 1
+ r = db_open(filename, DB_BTREE, DB_CREATE, S_IRUSR | S_IWUSR,
+ NULL, NULL, &dbp);
+ if (r != 0)
+ goto err;
+#elif DBVERS == 1
+ dbp = dbopen(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, DB_BTREE, NULL);
+ if (dbp == NULL)
+ goto err;
+#else
+ goto err;
+#endif
+#endif
+
+ cache_db = mail_cache_db_new(dbp);
+ if (cache_db == NULL)
+ goto close_db;
+
+ * pcache_db = cache_db;
+
+ return 0;
+
+ close_db:
+#if DBVERS > 1
+ dbp->close(dbp, 0);
+#elif DBVERS == 1
+ dbp->close(dbp);
+#endif
+ err:
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+void mail_cache_db_close(struct mail_cache_db * cache_db)
+{
+#if DBVERS >= 1
+ DB * dbp;
+
+ dbp = cache_db->internal_database;
+
+#if DBVERS > 1
+ dbp->close(cache_db->internal_database, 0);
+#elif DBVERS == 1
+ dbp->close(cache_db->internal_database);
+#endif
+
+ mail_cache_db_free(cache_db);
+#endif
+}
+
+int mail_cache_db_open_lock(const char * filename,
+ struct mail_cache_db ** pcache_db)
+{
+ int r;
+ struct mail_cache_db * cache_db;
+
+ r = maillock_write_lock(filename, -1);
+ if (r < 0)
+ goto err;
+
+ r = mail_cache_db_open(filename, &cache_db);
+ if (r < 0)
+ goto unlock;
+
+ * pcache_db = cache_db;
+
+ return 0;
+
+ unlock:
+ maillock_write_unlock(filename, -1);
+ err:
+ return -1;
+}
+
+void mail_cache_db_close_unlock(const char * filename,
+ struct mail_cache_db * cache_db)
+{
+ maillock_write_unlock(filename, -1);
+ mail_cache_db_close(cache_db);
+}
+
+
+int mail_cache_db_put(struct mail_cache_db * cache_db,
+ const void * key, size_t key_len, const void * value, size_t value_len)
+{
+#if DBVERS >= 1
+ int r;
+ DBT db_key;
+ DBT db_data;
+ DB * dbp;
+
+ dbp = cache_db->internal_database;
+
+ memset(&db_key, 0, sizeof(db_key));
+ memset(&db_data, 0, sizeof(db_data));
+ db_key.data = (void *) key;
+ db_key.size = key_len;
+ db_data.data = (void *) value;
+ db_data.size = value_len;
+
+#if DBVERS > 1
+ r = dbp->put(dbp, NULL, &db_key, &db_data, 0);
+#elif DBVERS == 1
+ r = dbp->put(dbp, &db_key, &db_data, 0);
+#else
+ r = -1;
+#endif
+
+ return r;
+#else
+ return -1;
+#endif
+}
+
+int mail_cache_db_get(struct mail_cache_db * cache_db,
+ const void * key, size_t key_len, void ** pvalue, size_t * pvalue_len)
+{
+#if DBVERS >= 1
+ int r;
+ DBT db_key;
+ DBT db_data;
+ DB * dbp;
+
+ dbp = cache_db->internal_database;
+
+ memset(&db_key, 0, sizeof(db_key));
+ memset(&db_data, 0, sizeof(db_data));
+ db_key.data = (void *) key;
+ db_key.size = key_len;
+
+#if DBVERS > 1
+ r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
+#elif DBVERS == 1
+ r = dbp->get(dbp, &db_key, &db_data, 0);
+#else
+ r = -1;
+#endif
+
+ if (r != 0)
+ return r;
+
+ * pvalue = db_data.data;
+ * pvalue_len = db_data.size;
+
+ return 0;
+#else
+ return -1;
+#endif
+}
+
+int mail_cache_db_del(struct mail_cache_db * cache_db,
+ const void * key, size_t key_len)
+{
+#if DBVERS >= 1
+ int r;
+ DBT db_key;
+ DB * dbp;
+
+ dbp = cache_db->internal_database;
+
+ memset(&db_key, 0, sizeof(db_key));
+ db_key.data = (void *) key;
+ db_key.size = key_len;
+
+#if DBVERS > 1
+ r = dbp->del(dbp, NULL, &db_key, 0);
+#elif DBVERS == 1
+ r = dbp->del(dbp, &db_key, 0);
+#else
+ r = -1;
+#endif
+
+ return r;
+#else
+ return -1;
+#endif
+}
+
+#if DBVERS > 1
+int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
+ chash * exist)
+{
+ DB * dbp;
+ int r;
+ DBC * dbcp;
+ DBT db_key;
+ DBT db_data;
+
+ dbp = cache_db->internal_database;
+
+ r = dbp->cursor(dbp, NULL, &dbcp, 0);
+ if (r != 0)
+ return r;
+
+ memset(&db_key, 0, sizeof(db_key));
+ memset(&db_data, 0, sizeof(db_data));
+
+ while (1) {
+ chashdatum hash_key;
+ chashdatum hash_data;
+
+ r = dbcp->c_get(dbcp, &db_key, &db_data, DB_NEXT);
+ if (r != 0)
+ break;
+
+ hash_key.data = db_key.data;
+ hash_key.len = db_key.size;
+
+ r = chash_get(exist, &hash_key, &hash_data);
+ if (r < 0) {
+ r = dbcp->c_del(dbcp, 0);
+ if (r != 0)
+ return r;
+ }
+ }
+
+ r = dbcp->c_close(dbcp);
+ if (r != 0)
+ return r;
+
+ return 0;
+}
+#elif DBVERS == 1
+int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
+ chash * exist)
+{
+ DB * dbp;
+ int r;
+ DBT db_key;
+ DBT db_data;
+
+ dbp = cache_db->internal_database;
+
+ r = dbp->seq(dbp, &db_key, &db_data, R_FIRST);
+ if (r == -1)
+ return r;
+
+ while (r == 0) {
+ chashdatum hash_key;
+ chashdatum hash_data;
+
+ hash_key.data = db_key.data;
+ hash_key.len = db_key.size;
+
+ r = chash_get(exist, &hash_key, &hash_data);
+ if (r < 0) {
+ r = dbp->del(dbp, &db_key, 0);
+ if (r != 0)
+ return r;
+ }
+
+ r = dbp->seq(dbp, &db_key, &db_data, R_NEXT);
+ if (r == -1)
+ return r;
+ }
+
+ return 0;
+}
+#else
+int mail_cache_db_clean_up(struct mail_cache_db * cache_db,
+ chash * exist)
+{
+ return -1;
+}
+#endif
+
+int mail_cache_db_get_size(struct mail_cache_db * cache_db,
+ const void * key, size_t key_len, size_t * pvalue_len)
+{
+#if DBVERS >= 1
+ int r;
+ DBT db_key;
+ DBT db_data;
+ DB * dbp;
+
+ dbp = cache_db->internal_database;
+
+ memset(&db_key, 0, sizeof(db_key));
+ memset(&db_data, 0, sizeof(db_data));
+ db_key.data = (void *) key;
+ db_key.size = key_len;
+#if DBVERS > 1
+ db_data.flags = DB_DBT_USERMEM;
+ db_data.ulen = 0;
+#endif
+
+#if DBVERS > 1
+ r = dbp->get(dbp, NULL, &db_key, &db_data, 0);
+#elif DBVERS == 1
+ r = dbp->get(dbp, &db_key, &db_data, 0);
+#else
+ r = -1;
+#endif
+
+ if (r != 0)
+ return r;
+
+ * pvalue_len = db_data.size;
+
+ return 0;
+#else
+ return -1;
+#endif
+}