aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-04-12 11:50:38 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-04-12 11:50:38 +0000
commit7f8a5835e41a0032769daec4865484680b332d6c (patch)
tree542e64a854fb882b814b571fc0cab4e1a82570b5
parentb9859b7dcd488df71ed18deeb2e034063b5bc8bd (diff)
downloadmailfromd-7f8a5835e41a0032769daec4865484680b332d6c.tar.gz
mailfromd-7f8a5835e41a0032769daec4865484680b332d6c.tar.bz2
Re-implement database locking for Berkeley DB
git-svn-id: file:///svnroot/mailfromd/trunk@1352 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog2
-rw-r--r--src/mu_dbm.c144
2 files changed, 127 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 177e1fb5..75150bbb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
2007-04-12 Sergey Poznyakoff <gray@gnu.org.ua>
+ * src/mu_dbm.c: Re-implement database locking for Berkeley DB
+
* 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,
diff --git a/src/mu_dbm.c b/src/mu_dbm.c
index 421a846c..461731e7 100644
--- a/src/mu_dbm.c
+++ b/src/mu_dbm.c
@@ -46,15 +46,12 @@ mu_fcheck_perm (int fd, int mode)
if (fstat (fd, &st) == -1)
{
if (errno == ENOENT)
- return 0;
+ return ENOENT;
else
- return 1;
+ return MU_ERR_FAILURE;
}
if ((st.st_mode & 0777) != mode)
- {
- errno = MU_ERR_UNSAFE_PERMS;
- return 1;
- }
+ return errno = MU_ERR_UNSAFE_PERMS;
return 0;
}
@@ -68,25 +65,18 @@ mu_check_perm (const char *name, int mode)
if (stat (name, &st) == -1)
{
if (errno == ENOENT)
- return 0;
+ return ENOENT;
else
- return 1;
+ return MU_ERR_FAILURE;
}
if ((st.st_mode & 0777) != mode)
- {
- errno = MU_ERR_UNSAFE_PERMS;
- return 1;
- }
+ return errno = MU_ERR_UNSAFE_PERMS;
+
return 0;
}
#if defined(WITH_GDBM)
-void
-mu_dbm_finish ()
-{
-}
-
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode, int *ro)
{
@@ -216,6 +206,8 @@ mu_dbm_datum_free (DBM_DATUM *datum)
const char *
mu_dbm_strerror ()
{
+ if (errno == MU_ERR_UNSAFE_PERMS)
+ return mu_strerror (errno);
return gdbm_strerror (gdbm_errno);
}
@@ -223,6 +215,68 @@ mu_dbm_strerror ()
int mu_dbm_errno;
+static int
+lock_file (int fd, int type)
+{
+ int i;
+ struct flock fl;
+ int rc = 0;
+
+ memset(&fl, 0, sizeof fl);
+ fl.l_whence = SEEK_SET;
+ fl.l_type = type;
+
+ for (i = 0; i < lock_retry_count_option; i++)
+ {
+ if (fcntl(fd, F_SETLK, &fl) == 0)
+ {
+ rc = 0;
+ break;
+ }
+ rc = errno;
+ if (!(errno == EAGAIN || errno == EACCES))
+ break;
+ sleep (lock_retry_timeout_option);
+ }
+ return rc;
+}
+
+#define LOCK_SUFFIX ".lock"
+
+static int
+make_lockfile (char *name, int *pfd, char **plockname)
+{
+ int rc;
+ int fd;
+ char *lockname;
+ size_t size;
+
+ size = strlen (name) + sizeof LOCK_SUFFIX;
+ lockname = malloc (size);
+ if (!lockname)
+ return errno;
+ strcpy (lockname, name);
+ strcat (lockname, LOCK_SUFFIX);
+ fd = open (lockname, O_CREAT|O_RDWR, 0600);
+ if (!fd)
+ {
+ free (lockname);
+ return errno;
+ }
+
+ rc = lock_file (fd, F_WRLCK);
+ if (rc)
+ {
+ free (lockname);
+ return rc;
+ }
+
+ *plockname = lockname;
+ *pfd = fd;
+ return 0;
+}
+
+
static void
mu_dbm_errcall_fcn (const char *errpfx, char *msg)
{
@@ -235,10 +289,14 @@ mu_dbm_errcall_fcn (const char *errpfx, char *msg)
int
mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
{
- int f, rc;
+ int f;
DB *db = NULL;
+ int lockfd = -1;
+ char *lockname;
+ int fd;
- if (mu_check_perm (name, mode))
+ mu_dbm_errno = mu_check_perm (name, mode);
+ if (mu_dbm_errno && mu_dbm_errno != ENOENT)
return MU_ERR_UNSAFE_PERMS;
if (ro)
@@ -251,6 +309,8 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
break;
case MU_STREAM_READ:
+ if (mu_dbm_errno == ENOENT)
+ return MU_ERR_FAILURE;
f = DB_RDONLY;
break;
@@ -263,6 +323,17 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
return -1;
}
+ if (mu_dbm_errno == ENOENT)
+ {
+ mu_dbm_errno = make_lockfile (name, &lockfd, &lockname);
+ if (mu_dbm_errno)
+ {
+ mu_error ("Cannot lock file %s: %s",
+ name, mu_strerror (mu_dbm_errno));
+ return MU_ERR_FAILURE;
+ }
+ }
+
#if DB_VERSION_MAJOR == 2
mu_dbm_errno = db_open (name, DB_HASH, f, mode, NULL, NULL, &db);
#else
@@ -277,10 +348,39 @@ mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode, int *ro)
#endif
if (mu_dbm_errno)
return MU_ERR_FAILURE;
+
+ if (mu_dbm_errno = db->fd (db, &fd))
+ {
+ mu_error("Cannot get file descriptor for the database: %s",
+ mu_dbm_strerror ());
+ db->close (db, 0);
+ if (lockfd != -1)
+ {
+ unlink (lockname);
+ free (lockname);
+ close (lockfd);
+ }
+ return MU_ERR_FAILURE;
+ }
+
+ mu_dbm_errno = lock_file (fd, (flags == MU_STREAM_READ) ? F_RDLCK : F_WRLCK);
+ if (lockfd != -1)
+ {
+ unlink (lockname);
+ free (lockname);
+ close (lockfd);
+ }
+
+ if (mu_dbm_errno)
+ {
+ db->close (db, 0);
+ return MU_ERR_FAILURE;
+ }
dbm->name = strdup (name);
dbm->db = db;
dbm->dbc = NULL;
+
return 0;
}
@@ -413,7 +513,13 @@ mu_dbm_datum_free(DBM_DATUM *datum)
const char *
mu_dbm_strerror ()
{
+ if (errno == MU_ERR_UNSAFE_PERMS)
+ return mu_strerror (errno);
+#if DB_VERSION_MAJOR > 2
return db_strerror (mu_dbm_errno);
+#else
+ return mu_strerror (mu_dbm_errno);
+#endif
}
#endif

Return to:

Send suggestions and report system problems to the System administrator.