aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-04-12 08:54:11 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-04-12 08:54:11 +0000
commitb9859b7dcd488df71ed18deeb2e034063b5bc8bd (patch)
tree9427a803a6e2292f7d18190859d1f9915b22e38c
parent15ddbce71e6c1f4f9fc3d76adaca0f962d08c576 (diff)
downloadmailfromd-b9859b7dcd488df71ed18deeb2e034063b5bc8bd.tar.gz
mailfromd-b9859b7dcd488df71ed18deeb2e034063b5bc8bd.tar.bz2
* src/mu_dbm.c, src/mu_dbm.h (mu_dbm_strerror): New function
(mu_dbm_firstkey, mu_dbm_nextkey): Change signature * src/dnscache.c, src/db.c, src/cache.c, src/rate.c, src/bi_db.m4: Update for new mu_dbm interface. git-svn-id: file:///svnroot/mailfromd/trunk@1351 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog7
-rw-r--r--src/bi_db.m439
-rw-r--r--src/cache.c24
-rw-r--r--src/db.c266
-rw-r--r--src/dnscache.c16
-rw-r--r--src/mu_dbm.c276
-rw-r--r--src/mu_dbm.h18
-rw-r--r--src/rate.c11
8 files changed, 433 insertions, 224 deletions
diff --git a/ChangeLog b/ChangeLog
index 56be7894..177e1fb5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-04-12 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * src/mu_dbm.c, src/mu_dbm.h (mu_dbm_strerror): New function
+ (mu_dbm_firstkey, mu_dbm_nextkey): Change signature
+ * src/dnscache.c, src/db.c, src/cache.c, src/rate.c,
+ src/bi_db.m4: Update for new mu_dbm interface.
+
2007-04-11 Sergey Poznyakoff <gray@gnu.org.ua>
* src/engine.c, src/mailfromd.h, src/prog.c, src/main.c,
diff --git a/src/bi_db.m4 b/src/bi_db.m4
index fecc0eb8..4b852ae2 100644
--- a/src/bi_db.m4
+++ b/src/bi_db.m4
@@ -34,7 +34,7 @@ dbmap_lookup(eval_environ_t env, char *dbname, const char *keystr,
MF_THROW(mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
@@ -93,7 +93,7 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value,
MF_THROW(mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = keystr;
MU_DATUM_SIZE(key) = strlen(keystr);
@@ -108,10 +108,11 @@ MF_DEFUN(dbput, VOID, STRING dbname, STRING keystr, STRING value,
mu_dbm_close(&db);
MF_ASSERT(rc == 0,
mf_dbfailure,
- "failed to insert data to %s: %s %s",
+ "failed to insert data to %s: %s %s: %s",
dbname,
key,
- value);
+ value,
+ mu_dbm_strerror());
}
END
@@ -119,19 +120,25 @@ MF_DEFUN(dbdel, VOID, STRING dbname, STRING keystr, OPTIONAL, NUMBER null)
{
DBM_FILE db;
DBM_DATUM key;
-
+ int rc;
if (mu_dbm_open(dbname, &db, MU_STREAM_RDWR, 0640, NULL))
MF_THROW(mf_dbfailure,
"mu_dbm_open(%s) failed: %s",
dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = keystr;
MU_DATUM_SIZE(key) = strlen(keystr);
if (null)
MU_DATUM_SIZE(key)++;
- mu_dbm_delete(&db, key);
+ rc = mu_dbm_delete(&db, key);
mu_dbm_close(&db);
+ MF_ASSERT(rc == 0,
+ mf_dbfailure,
+ "failed to delete data `%s' from `%s': %s",
+ key,
+ dbname,
+ mu_dbm_strerror());
}
END
@@ -187,7 +194,7 @@ MF_DEFUN(greylist, NUMBER, STRING email, NUMBER interval)
rc = mu_dbm_open(greylist_format->dbname, &db, MU_STREAM_RDWR, 0600,
&readonly);
MF_ASSERT(rc == 0, mf_dbfailure, "mu_dbm_open(%s) failed: %s",
- greylist_format->dbname, mu_strerror(errno));
+ greylist_format->dbname, mu_dbm_strerror());
memset(&key, 0, sizeof key);
memset(&contents, 0, sizeof contents);
@@ -232,9 +239,11 @@ MF_DEFUN(greylist, NUMBER, STRING email, NUMBER interval)
memcpy(MU_DATUM_PTR(contents),
&now, sizeof now);
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error("Cannot insert datum in "
- "greylist database %s",
- greylist_format->dbname);
+ mu_error("Cannot insert datum `%s' in "
+ "greylist database %s: %s",
+ key,
+ greylist_format->dbname,
+ mu_dbm_strerror());
} else
debug(20, "database opened in readonly mode: "
"not updating");
@@ -251,9 +260,11 @@ MF_DEFUN(greylist, NUMBER, STRING email, NUMBER interval)
MU_DATUM_PTR(contents) = (void*)&now;
MU_DATUM_SIZE(contents) = sizeof now;
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error("Cannot insert datum in greylist "
- "database %s",
- greylist_format->dbname);
+ mu_error("Cannot insert datum `%s' in greylist "
+ "database %s: %s",
+ key,
+ greylist_format->dbname,
+ mu_dbm_strerror());
rc = 1;
} else
rc = 0;
diff --git a/src/cache.c b/src/cache.c
index ff6aa2b2..d5a2da4e 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -39,12 +39,13 @@ cache_get(char *email)
DBM_DATUM key;
DBM_DATUM contents;
int readonly = 0;
+ int res;
debug1(50, "getting cache info for %s", email);
if (mu_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600,
&readonly)) {
mu_error("mu_dbm_open(%s) failed: %s", cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return mf_failure;
}
if (readonly)
@@ -55,7 +56,7 @@ cache_get(char *email)
memset (&contents, 0, sizeof contents);
MU_DATUM_PTR (key) = email;
MU_DATUM_SIZE (key) = strlen (email) + 1;
- if (mu_dbm_fetch(&db, key, &contents) == 0) {
+ if ((res = mu_dbm_fetch(&db, key, &contents)) == 0) {
char timebuf[80];
struct cache_result *res = (struct cache_result *)
MU_DATUM_PTR(contents);
@@ -70,15 +71,20 @@ cache_get(char *email)
debug1(50,
"removing expired entry for %s",email);
if (mu_dbm_delete(&db, key))
- mu_error("Cannot remove record for %s",
- email);
+ mu_error("Cannot remove record `%s' from %s: %s",
+ email, db.name,
+ mu_dbm_strerror());
}
rc = mf_failure;
} else {
rc = res->status;
}
- } else
+ } else {
+ if (res != MU_ERR_NOENT)
+ mu_error("Cannot fetch record `%s' from `%s': %s",
+ email, db.name, mu_dbm_strerror());
rc = mf_failure;
+ }
mu_dbm_datum_free(&contents);
mu_dbm_close(&db);
return rc;
@@ -98,9 +104,10 @@ cache_insert(char *email, mf_status rc)
debug4(50,"inserting cache info for %s. status=%s (%d), time=%s",
email, mf_status_str(rc), rc,
mailfromd_timestr(res.timestamp, timebuf, sizeof timebuf));
- if (mu_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
+ if (mu_dbm_open(cache_format->dbname, &db, MU_STREAM_RDWR,
+ 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return;
}
@@ -111,7 +118,8 @@ cache_insert(char *email, mf_status rc)
MU_DATUM_PTR(contents) = (void*)&res;
MU_DATUM_SIZE(contents) = sizeof(res);
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error("Cannot insert datum");
+ mu_error("Cannot insert datum `%s' into `%s': %s",
+ email, db.name, mu_dbm_strerror());
mu_dbm_close(&db);
}
diff --git a/src/db.c b/src/db.c
index efa52a16..1978dec8 100644
--- a/src/db.c
+++ b/src/db.c
@@ -79,104 +79,149 @@ db_list_item(char *dbname, char *email, db_item_printer_t fun)
DBM_FILE db;
DBM_DATUM key, contents;
int rc = 1;
+ int res;
if (mu_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
memset (&contents, 0, sizeof contents);
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = email;
MU_DATUM_SIZE(key) = strlen (email) + 1;
- if (mu_dbm_fetch(&db, key, &contents) == 0) {
+ if ((res = mu_dbm_fetch(&db, key, &contents)) == 0) {
fun(MU_DATUM_PTR(key),
MU_DATUM_SIZE(key),
MU_DATUM_PTR(contents));
rc = 0;
- }
+ } else if (res != MU_ERR_NOENT)
+ mu_error("Cannot fetch record `%s' from `%s': %s",
+ email, db.name, mu_dbm_strerror());
+
mu_dbm_close(&db);
return rc;
}
+typedef int (*db_enum_func)(DBM_DATUM key, DBM_DATUM cnt, void *data);
+
+int
+db_enumerate(DBM_FILE *db, db_enum_func fun, void *data)
+{
+ int rc = 0;
+ int res;
+ DBM_DATUM key, prev, contents;
+
+ for (res = mu_dbm_firstkey (db, &key); res == 0;
+ prev = key,
+ res = mu_dbm_nextkey (db, prev, &key),
+ mu_dbm_datum_free(&prev)) {
+ memset (&contents, 0, sizeof contents);
+ if (mu_dbm_fetch (db, key, &contents) == 0) {
+ int fr = fun(key, contents, data);
+ mu_dbm_datum_free(&contents);
+ if (fr) {
+ mu_dbm_datum_free(&key);
+ break;
+ }
+ } else {
+ mu_error("Cannot fetch data `%*.*s' from `%s': %s",
+ MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
+ MU_DATUM_PTR(key),
+ db->name,
+ mu_dbm_strerror());
+ rc = 1;
+ }
+ }
+ if (res != MU_ERR_NOENT) {
+ mu_error("Unexpected error scanning database %s: %s",
+ db->name, mu_dbm_strerror());
+ rc = 1;
+ }
+ return rc;
+}
+
+static int
+db_list_func(DBM_DATUM key, DBM_DATUM contents, void *data)
+{
+ db_item_printer_t fun = data;
+ fun(MU_DATUM_PTR(key), MU_DATUM_SIZE(key), MU_DATUM_PTR(contents));
+ return 0;
+}
+
int
db_list(char *dbname, db_item_printer_t fun)
{
DBM_FILE db;
- DBM_DATUM key, contents;
+ DBM_DATUM key, prev, contents;
int rc = 0;
+ int res;
if (mu_dbm_open(dbname, &db, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- for (key = mu_dbm_firstkey (&db); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&db, key)) {
- memset (&contents, 0, sizeof contents);
- if (mu_dbm_fetch (&db, key, &contents) == 0) {
- fun(MU_DATUM_PTR(key),
- MU_DATUM_SIZE(key),
- MU_DATUM_PTR(contents));
- } else {
- mu_error("Cannot fetch data for %*.*s",
- MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
- MU_DATUM_PTR(key));
- rc = 1;
- }
- }
+ db_enumerate(&db, db_list_func, fun);
mu_dbm_close(&db);
return 1;
}
+struct expire_data {
+ db_expire_t fun;
+ struct obstack stk;
+ size_t key_count;
+};
+
+static int
+db_expire_func(DBM_DATUM key, DBM_DATUM contents, void *data)
+{
+ struct expire_data *dp = data;
+ if (dp->fun(MU_DATUM_PTR(contents))) {
+ size_t size = MU_DATUM_SIZE(key);
+ obstack_grow(&dp->stk, &size, sizeof size);
+ obstack_grow(&dp->stk, MU_DATUM_PTR(key), size);
+ dp->key_count++;
+ }
+ return 0;
+}
+
int
db_expire(char *dbname, db_expire_t fun)
{
DBM_FILE db;
DBM_DATUM key, contents;
+ struct expire_data ed;
size_t size;
- struct obstack stk;
char *base, *p;
- size_t i, key_count = 0;
+ size_t i;
int rc = 0;
+ int res;
if (mu_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- obstack_init(&stk);
+ ed.fun = fun;
+ obstack_init(&ed.stk);
+ ed.key_count = 0;
debug1(1, "Expiring %s: mark phase", dbname);
- for (key = mu_dbm_firstkey (&db); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&db, key)) {
- memset (&contents, 0, sizeof contents);
- if (mu_dbm_fetch (&db, key, &contents) == 0) {
- if (fun(MU_DATUM_PTR(contents))) {
- size = MU_DATUM_SIZE(key);
- obstack_grow(&stk, &size, sizeof size);
- obstack_grow(&stk, MU_DATUM_PTR(key), size);
- key_count++;
- }
- } else {
- mu_error("Cannot fetch data for %*.*s",
- MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
- MU_DATUM_PTR(key));
- rc = !ignore_failed_reads_option;
- }
- mu_dbm_datum_free (&contents);
- }
+ if (db_enumerate(&db, db_expire_func, &ed))
+ rc = !ignore_failed_reads_option;
+
size = 0;
- obstack_grow(&stk, &size, sizeof size);
+ obstack_grow(&ed.stk, &size, sizeof size);
debug2(1, "Number of keys to expire: %lu, memory used: %u",
- (unsigned long) key_count,
- (unsigned) obstack_memory_used(&stk));
+ (unsigned long) ed.key_count,
+ (unsigned) obstack_memory_used(&ed.stk));
debug1(1, "Expiring %s: sweep phase", dbname);
- base = obstack_finish(&stk);
- for (i = 0, p = base; i < key_count; i++) {
+ base = obstack_finish(&ed.stk);
+ for (i = 0, p = base; i < ed.key_count; i++) {
size = *(size_t*)p;
p += sizeof(size_t);
@@ -184,15 +229,15 @@ db_expire(char *dbname, db_expire_t fun)
MU_DATUM_PTR(key) = p;
MU_DATUM_SIZE(key) = size;
if (mu_dbm_delete(&db, key)) {
- mu_error ("Cannot remove record for %*.*s",
- size, size, p);
+ mu_error ("Cannot remove record `%*.*s' from `%s': %s",
+ size, size, p, db.name, mu_dbm_strerror());
rc = 1;
}
p += size;
}
debug1(1, "Finished expiring %s", dbname);
- obstack_free(&stk, NULL);
+ obstack_free(&ed.stk, NULL);
mu_dbm_close(&db);
return rc;
}
@@ -206,14 +251,15 @@ db_delete(char *dbname, char *id)
if (mu_dbm_open(dbname, &db, MU_STREAM_RDWR, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
memset(&key, 0, sizeof key);
MU_DATUM_PTR(key) = id;
MU_DATUM_SIZE(key) = strlen (id) + 1;
if (mu_dbm_delete(&db, key)) {
- mu_error("Cannot remove record for %s", id);
+ mu_error("Cannot remove record `%s' from `%s': %s", id,
+ dbname, mu_dbm_strerror());
rc = 1;
} else
rc = 0;
@@ -244,88 +290,100 @@ make_tmp_name(char *dbname)
return newname;
}
+struct compact_data {
+ int rc;
+ db_expire_t fun;
+ DBM_FILE ndb;
+};
+
+static int
+db_compact_func(DBM_DATUM key, DBM_DATUM contents, void *data)
+{
+ struct compact_data *dp = data;
+
+ if (!dp->fun || dp->fun(MU_DATUM_PTR(contents)) == 0) {
+ if (((char*)MU_DATUM_PTR(key))[MU_DATUM_SIZE(key) - 1]) {
+ /* Old database format. Convert. */
+ size_t size;
+ char *p;
+ DBM_DATUM newkey;
+
+ size = MU_DATUM_SIZE(key);
+ p = malloc(size+1);
+ if (!MU_DATUM_PTR(newkey)) {
+ mu_error("Not enough memory");
+ return 1;
+ }
+ memcpy(p, MU_DATUM_PTR(key), size);
+ p[size] = 0;
+
+ memset(&newkey, 0, sizeof newkey);
+ MU_DATUM_SIZE(newkey) = size+1;
+ MU_DATUM_PTR(newkey) = p;
+ if (mu_dbm_insert(&dp->ndb, newkey, contents, 1)) {
+ mu_error ("Cannot insert datum `%s' into `%s': %s",
+ p, dp->ndb.name,
+ mu_dbm_strerror());
+ dp->rc = 1;
+ }
+ free(p);
+ } else if (mu_dbm_insert(&dp->ndb, key, contents, 1)) {
+ mu_error("Cannot insert datum `%*.*s' into `%s': %s",
+ MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
+ MU_DATUM_PTR(key),
+ dp->ndb.name,
+ mu_dbm_strerror());
+ dp->rc = 1;
+ }
+ }
+ return 0;
+}
+
int
db_compact(char *dbname, db_expire_t fun)
{
DBM_DATUM key, contents;
- DBM_FILE odb, ndb;
- int rc = 0;
+ DBM_FILE odb;
char *tmpname;
-
+ struct compact_data dat;
+
debug1(1, "Compacting database `%s'", dbname);
tmpname = make_tmp_name(dbname);
if (mu_dbm_open(dbname, &odb, MU_STREAM_READ, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- if (mu_dbm_open(tmpname, &ndb, MU_STREAM_CREAT, 0600, NULL)) {
+ dat.rc = 0;
+ dat.fun = fun;
+ if (mu_dbm_open(tmpname, &dat.ndb, MU_STREAM_CREAT, 0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s", tmpname,
- mu_strerror(errno));
+ mu_dbm_strerror());
return 1;
}
- for (key = mu_dbm_firstkey (&odb); MU_DATUM_PTR(key);
- key = mu_dbm_nextkey (&odb, key)) {
- memset (&contents, 0, sizeof contents);
- if (mu_dbm_fetch (&odb, key, &contents)) {
- rc = !ignore_failed_reads_option;
- mu_error("Cannot fetch data for %*.*s",
- MU_DATUM_SIZE(key), MU_DATUM_SIZE(key),
- MU_DATUM_PTR(key));
- continue;
- }
- if (!fun || fun(MU_DATUM_PTR(contents)) == 0) {
- if (((char*)MU_DATUM_PTR(key))[MU_DATUM_SIZE(key) - 1]) {
- /* Old database format. Convert. */
- size_t size;
- char *p;
- DBM_DATUM newkey;
-
- size = MU_DATUM_SIZE(key);
- p = malloc(size+1);
- if (!MU_DATUM_PTR(newkey)) {
- mu_error("Not enough memory");
- rc = 1;
- break;
- }
- memcpy(p, MU_DATUM_PTR(key), size);
- p[size] = 0;
-
- memset(&newkey, 0, sizeof newkey);
- MU_DATUM_SIZE(newkey) = size+1;
- MU_DATUM_PTR(newkey) = p;
- if (mu_dbm_insert(&ndb, newkey, contents, 1)) {
- mu_error ("Cannot insert datum");
- rc = 1;
- }
- free(p);
- } else if (mu_dbm_insert(&ndb, key, contents, 1)) {
- mu_error ("Cannot insert datum");
- rc = 1;
- }
- }
- mu_dbm_datum_free (&contents);
- }
- mu_dbm_close(&ndb);
+
+ db_enumerate(&odb, db_compact_func, &dat);
+
+ mu_dbm_close(&dat.ndb);
mu_dbm_close(&odb);
- if (rc == 0) {
+ if (dat.rc == 0) {
if (unlink(dbname)) {
mu_error("Cannot unlink %s: %s",
dbname, mu_strerror(errno));
- rc = 1;
+ dat.rc = 1;
} else if (rename(tmpname, dbname)) {
mu_error("Cannot rename %s to %s: %s",
tmpname, dbname, mu_strerror(errno));
- rc = 1;
+ dat.rc = 1;
}
}
free(tmpname);
- return rc;
+ return dat.rc;
}
size_t
diff --git a/src/dnscache.c b/src/dnscache.c
index 1395fe00..74f3adc1 100644
--- a/src/dnscache.c
+++ b/src/dnscache.c
@@ -107,6 +107,7 @@ dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
DBM_FILE db;
DBM_DATUM key;
DBM_DATUM contents;
+ int res;
if (dns_make_key(type, keystr, &key))
return mf_failure;
@@ -117,13 +118,13 @@ dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
NULL)) {
mu_error("mu_dbm_open(%s) failed: %s",
dns_cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
dns_free_key(&key);
return mf_failure;
}
memset (&contents, 0, sizeof contents);
- if (mu_dbm_fetch(&db, key, &contents) == 0) {
+ if ((res = mu_dbm_fetch(&db, key, &contents)) == 0) {
int argc;
char **argv;
@@ -140,8 +141,12 @@ dns_cache_get(int type, const char *keystr, char **rbuf, size_t rcnt)
rc = parse_value(type, keystr, argc, argv, rbuf, rcnt);
mu_argcv_free(argc, argv);
mu_dbm_datum_free(&contents);
- } else
+ } else {
+ if (res != MU_ERR_NOENT)
+ mu_error("Cannot fetch `%s' from `%s': %s",
+ keystr, db.name, mu_dbm_strerror());
rc = mf_failure;
+ }
mu_dbm_close(&db);
dns_free_key(&key);
return rc;
@@ -164,7 +169,7 @@ dns_cache_put(int type, const char *keystr, time_t ttl,
0600, NULL)) {
mu_error("mu_dbm_open(%s) failed: %s",
dns_cache_format->dbname,
- mu_strerror(errno));
+ mu_dbm_strerror());
dns_free_key(&key);
return;
}
@@ -192,7 +197,8 @@ dns_cache_put(int type, const char *keystr, time_t ttl,
MU_DATUM_PTR(contents) = p;
MU_DATUM_SIZE(contents) = blen + 1 + len + 1;
if (mu_dbm_insert(&db, key, contents, 1))
- mu_error("Cannot insert datum");
+ mu_error("Cannot insert datum `%s' into `%s': %s",
+ keystr, db.name, mu_dbm_strerror());
free(p);
}
mu_dbm_close(&db);
diff --git a/src/mu_dbm.c b/src/mu_dbm.c
index 33929474..421a846c 100644
--- a/src/mu_dbm.c
+++ b/src/mu_dbm.c
@@ -1,6 +1,5 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,6 +34,10 @@
#include <mailutils/errno.h>
#include <mailfromd.h>
+#ifndef MU_ERR_EXISTS
+# define MU_ERR_EXISTS EEXIST
+#endif
+
int
mu_fcheck_perm (int fd, int mode)
{
@@ -79,6 +82,11 @@ mu_check_perm (const char *name, int mode)
#if defined(WITH_GDBM)
+void
+mu_dbm_finish ()
+{
+}
+
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
{
@@ -88,47 +96,55 @@ mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
GDBM_FILE gdbm;
if (mu_check_perm (name, mode))
- return -1;
+ return MU_ERR_UNSAFE_PERMS;
if (ro)
- *ro = 0;
+ *ro = 0;
+
switch (flags)
{
case MU_STREAM_CREAT:
f = GDBM_NEWDB;
break;
+
case MU_STREAM_READ:
f = GDBM_READER;
break;
+
case MU_STREAM_RDWR:
f = GDBM_WRCREAT;
break;
+
default:
errno = EINVAL;
return 1;
}
- for (i = 0; i < lock_retry_count_option; i++) {
- gdbm = gdbm_open(name, 512, f, mode, NULL);
- if (gdbm || errno != EAGAIN)
- break;
- sleep(lock_retry_timeout_option);
- }
-
- if (!gdbm) {
- if (ro) {
- gdbm = gdbm_open(name, 512, GDBM_READER, mode, NULL);
- if (gdbm)
- *ro = 1;
- }
- }
+ for (i = 0; i < lock_retry_count_option; i++)
+ {
+ gdbm = gdbm_open (name, 512, f, mode, NULL);
+ if (gdbm || errno != EAGAIN)
+ break;
+ sleep (lock_retry_timeout_option);
+ }
+
+ if (!gdbm)
+ {
+ if (ro)
+ {
+ gdbm = gdbm_open (name, 512, GDBM_READER, mode, NULL);
+ if (gdbm)
+ *ro = 1;
+ }
+ }
- rc = gdbm == NULL;
+ rc = (gdbm == NULL) ? MU_ERR_FAILURE : 0;
- if (rc == 0) {
- db->db = gdbm;
- db->name = strdup (name);
- }
+ if (rc == 0)
+ {
+ db->db = gdbm;
+ db->name = strdup (name);
+ }
return rc;
}
@@ -145,87 +161,122 @@ int
mu_dbm_fetch (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *ret)
{
*ret = gdbm_fetch(db->db, key);
- return ret->dptr == NULL;
+ if (ret->dptr == NULL)
+ return MU_ERR_NOENT;
+ return 0;
}
int
mu_dbm_delete (DBM_FILE *db, DBM_DATUM key)
{
- return gdbm_delete (db->db, key);
+ return gdbm_delete (db->db, key) ? MU_ERR_FAILURE : 0;
}
int
mu_dbm_insert (DBM_FILE *db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
- return gdbm_store(db->db, key, contents,
- replace ? GDBM_REPLACE : GDBM_INSERT);
+ switch (gdbm_store(db->db, key, contents,
+ replace ? GDBM_REPLACE : GDBM_INSERT))
+ {
+ case -1:
+ return MU_ERR_FAILURE;
+
+ case 0:
+ return 0;
+
+ case 1:
+ return MU_ERR_EXISTS;
+ }
+ return MU_ERR_FAILURE;
}
-DBM_DATUM
-mu_dbm_firstkey (DBM_FILE *db)
+int
+mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey)
{
- return gdbm_firstkey (db->db);
+ *pkey = gdbm_firstkey (db->db);
+ return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
}
-DBM_DATUM
-mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM key)
+int
+mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM prevkey, DBM_DATUM *pkey)
{
- return gdbm_nextkey (db->db, key);
+ *pkey = gdbm_nextkey (db->db, prevkey);
+ return (pkey->dptr == NULL) ? MU_ERR_FAILURE : 0;
}
void
-mu_dbm_datum_free(DBM_DATUM *datum)
+mu_dbm_datum_free (DBM_DATUM *datum)
{
- void *ptr = MU_DATUM_PTR(*datum);
- if (ptr)
- free(ptr);
- MU_DATUM_PTR(*datum) = 0;
+ void *ptr = MU_DATUM_PTR (*datum);
+ if (ptr)
+ free (ptr);
+ MU_DATUM_PTR (*datum) = 0;
+}
+
+const char *
+mu_dbm_strerror ()
+{
+ return gdbm_strerror (gdbm_errno);
}
#elif defined(WITH_BDB)
+int mu_dbm_errno;
+
+static void
+mu_dbm_errcall_fcn (const char *errpfx, char *msg)
+{
+ if (errpfx)
+ mu_error ("%s: Berkeley DB error: %s", errpfx, msg);
+ else
+ mu_error ("Berkeley DB error: %s", msg);
+}
+
int
mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
{
int f, rc;
- DB *db;
-
+ DB *db = NULL;
+
if (mu_check_perm (name, mode))
- return -1;
+ return MU_ERR_UNSAFE_PERMS;
if (ro)
- *ro = 0;
+ *ro = 0;
switch (flags)
{
case MU_STREAM_CREAT:
- f = DB_CREATE|DB_TRUNCATE;
+ f = DB_CREATE | DB_TRUNCATE;
break;
+
case MU_STREAM_READ:
f = DB_RDONLY;
break;
+
case MU_STREAM_RDWR:
f = DB_CREATE;
break;
+
default:
errno = EINVAL;
return -1;
- }
+ }
#if DB_VERSION_MAJOR == 2
- rc = db_open (name, DB_HASH, f, mode, NULL, NULL, &db);
+ mu_dbm_errno = db_open (name, DB_HASH, f, mode, NULL, NULL, &db);
#else
- rc = db_create (&db, NULL, 0);
- if (rc != 0 || db == NULL)
- return rc;
+ mu_dbm_errno = db_create (&db, NULL, 0);
+ if (mu_dbm_errno != 0 || db == NULL)
+ return MU_ERR_FAILURE;
# if DB_VERSION_MAJOR == 3
- rc = db->open (db, name, NULL, DB_HASH, f, mode);
+ mu_dbm_errno = db->open (db, name, NULL, DB_HASH, f, mode);
# else
- rc = db->open (db, NULL, name, NULL, DB_HASH, f, mode);
+ mu_dbm_errno = db->open (db, NULL, name, NULL, DB_HASH, f, mode);
# endif
#endif
- if (rc)
- return -1;
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
dbm->name = strdup (name);
dbm->db = db;
@@ -236,86 +287,139 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
int
mu_dbm_close (DBM_FILE *db)
{
- db->db->close (db->db, 0);
+ if (db->dbc)
+ {
+ mu_dbm_errno = db->dbc->c_close(db->dbc);
+ db->dbc = NULL;
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
+ }
+ mu_dbm_errno = db->db->close (db->db, 0);
+ if (mu_dbm_errno == DB_INCOMPLETE)
+ mu_dbm_errno = 0;
free (db->name);
- return 0;
+ return (mu_dbm_errno == 0) ? 0 : MU_ERR_FAILURE;
}
int
mu_dbm_fetch (DBM_FILE *db, DBM_DATUM key, DBM_DATUM *ret)
{
- return db->db->get (db->db, NULL, &key, ret, 0);
+ mu_dbm_errno = db->db->get (db->db, NULL, &key, ret, 0);
+ switch (mu_dbm_errno)
+ {
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
+ }
}
int
mu_dbm_delete (DBM_FILE *db, DBM_DATUM key)
{
- return db->db->del (db->db, NULL, &key, 0);
+ return (mu_dbm_errno = db->db->del (db->db, NULL, &key, 0))
+ ? MU_ERR_FAILURE : 0;
}
int
mu_dbm_insert (DBM_FILE *db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
- /*FIXME: replace unused*/
- return db->db->put (db->db, NULL, &key, &contents, 0);
+ int flags = replace ? 0 : DB_NOOVERWRITE;
+ mu_dbm_errno = db->db->put (db->db, NULL, &key, &contents, flags);
+ switch (mu_dbm_errno)
+ {
+ case 0:
+ return 0;
+
+ case DB_KEYEXIST:
+ return MU_ERR_EXISTS;
+
+ default:
+ return MU_ERR_FAILURE;
+ }
}
-DBM_DATUM
-mu_dbm_firstkey (DBM_FILE *db)
+int
+mu_dbm_firstkey (DBM_FILE *db, DBM_DATUM *pkey)
{
- DBT key, data;
+ DBT data;
int ret;
- memset(&key, 0, sizeof key);
+ memset(pkey, 0, sizeof *pkey);
memset(&data, 0, sizeof data);
if (!db->dbc)
{
- if (db->db->cursor(db->db, NULL, &db->dbc BDB2_CURSOR_LASTARG) != 0)
- return key;
+ mu_dbm_errno = db->db->cursor(db->db, NULL, &db->dbc
+ BDB2_CURSOR_LASTARG);
+ if (mu_dbm_errno)
+ return MU_ERR_FAILURE;
}
- if ((ret = db->dbc->c_get(db->dbc, &key, &data, DB_FIRST)) != 0)
+ mu_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_FIRST);
+ switch (mu_dbm_errno)
{
- key.data = NULL;
- key.size = 0;
- if (ret == DB_NOTFOUND)
- errno = MU_ERR_NOENT;
- else
- errno = ret;
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
}
- return key;
}
-DBM_DATUM
-mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM pkey /*unused*/)
+int
+mu_dbm_nextkey (DBM_FILE *db, DBM_DATUM prevkey /*unused*/, DBM_DATUM *pkey)
{
- DBT key, data;
+ DBT data;
int ret;
- memset(&key, 0, sizeof key);
+ memset(pkey, 0, sizeof *pkey);
memset(&data, 0, sizeof data);
if (!db->dbc)
- return key;
+ {
+ mu_dbm_errno = EINVAL;
+ return MU_ERR_FAILURE;
+ }
- if ((ret = db->dbc->c_get(db->dbc, &key, &data, DB_NEXT)) != 0)
+ mu_dbm_errno = db->dbc->c_get(db->dbc, pkey, &data, DB_NEXT);
+
+ switch (mu_dbm_errno)
{
- key.data = NULL;
- key.size = 0;
- if (ret == DB_NOTFOUND)
- errno = MU_ERR_NOENT;
- else
- errno = ret;
+ case 0:
+ return 0;
+
+ case DB_NOTFOUND:
+ return MU_ERR_NOENT;
+
+ default:
+ return MU_ERR_FAILURE;
}
- return key;
}
void
mu_dbm_datum_free(DBM_DATUM *datum)
{
- /* empty */
+ /* empty */
+}
+
+const char *
+mu_dbm_strerror ()
+{
+ return db_strerror (mu_dbm_errno);
}
#endif
+/*
+ Local Variables:
+ c-file-style: "gnu"
+ End:
+*/
diff --git a/src/mu_dbm.h b/src/mu_dbm.h
index d1502b92..3b8ea99b 100644
--- a/src/mu_dbm.h
+++ b/src/mu_dbm.h
@@ -1,5 +1,6 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2006,
+ 2007 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms