diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-12 08:54:11 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2007-04-12 08:54:11 +0000 |
commit | b9859b7dcd488df71ed18deeb2e034063b5bc8bd (patch) | |
tree | 9427a803a6e2292f7d18190859d1f9915b22e38c | |
parent | 15ddbce71e6c1f4f9fc3d76adaca0f962d08c576 (diff) | |
download | mailfromd-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-- | ChangeLog | 7 | ||||
-rw-r--r-- | src/bi_db.m4 | 39 | ||||
-rw-r--r-- | src/cache.c | 24 | ||||
-rw-r--r-- | src/db.c | 266 | ||||
-rw-r--r-- | src/dnscache.c | 16 | ||||
-rw-r--r-- | src/mu_dbm.c | 276 | ||||
-rw-r--r-- | src/mu_dbm.h | 18 | ||||
-rw-r--r-- | src/rate.c | 11 |
8 files changed, 433 insertions, 224 deletions
@@ -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); } @@ -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 |