diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2021-05-01 11:55:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2021-05-01 12:22:02 +0300 |
commit | 5a5dddb6e1fc39efaeaa029d0b5fb7a29306fba4 (patch) | |
tree | d5c1a656797d2e694f6164480bbe45901ad11f39 /include | |
parent | 5daca02feaa90dcac68c03e479a0a61e51d2c7ca (diff) | |
download | mailutils-5a5dddb6e1fc39efaeaa029d0b5fb7a29306fba4.tar.gz mailutils-5a5dddb6e1fc39efaeaa029d0b5fb7a29306fba4.tar.bz2 |
Revise the mailbox locking functions.
The locker is created by the following call:
mu_locker_create_ext(&locker, filename, &hints);
The last arguments points to a structure mu_locker_hints_t, which
defines the settings for the locker. NULL value implies default.
Settings of an existing locker can be modified using the following
call:
mu_locker_modify(locker, &hints);
Current settings can be examined using mu_locker_get_hints.
The functions mu_locker_destroy, mu_locker_lock_mode, mu_locker_lock,
mu_locker_touchlock, mu_locker_unlock, and mu_locker_remove_lock remained
unchanged. Rest of functions is deprecated, but retained for a couple
of releases for the sake of backward compatibility.
Constants (locker types, flags, etc) are also revisited.
This commit also fixes a bug in mu_spawnvp function, which was discovered
when testing external lockers.
* include/mailutils/locker.h: Major rewrite.
(MU_LOCKER_DEFAULT_EXPIRE_TIME)
(MU_LOCKER_DEFAULT_RETRY_COUNT)
(MU_LOCKER_DEFAULT_RETRY_SLEEP)
(MU_LOCKER_DEFAULT_EXT_LOCKER): New defines.
(mu_locker_hints_t): New data type.
(MU_LOCKER_FLAG_RETRY)
(MU_LOCKER_FLAG_EXPIRE_TIME)
(MU_LOCKER_FLAG_CHECK_PID)
(MU_LOCKER_FLAG_TYPE,MU_LOCKER_FLAGS_ALL): New defines.
(mu_locker_create_ext, mu_locker_modify)
(mu_locker_get_hints): New functions.
(mu_locker_create,mu_locker_set_default_flags)
(mu_locker_set_default_retry_timeout)
(mu_locker_set_default_retry_count)
(mu_locker_set_default_expire_timeout)
(mu_locker_set_default_external_program)
(mu_locker_set_flags,mu_locker_mod_flags)
(mu_locker_set_expire_time,mu_locker_set_retries)
(mu_locker_set_retry_sleep,mu_locker_set_external)
(mu_locker_get_flags,mu_locker_get_expire_time)
(mu_locker_get_retries,mu_locker_get_retry_sleep): Mark as deprecated.
* libmailutils/base/locker.c: Rewrite.
* libmailutils/cli/stdcapa.c: New locking statements: type and
retry-sleep. retry-timeout is deprecated.
* libmailutils/tests/lck.c: Use new locker functions.
* libmailutils/tests/lock.at: Test the external locker.
* libmailutils/base/spawnvp.c (mu_spawnvp): Restore the default SIGCHLD
handler while waiting for the process to terminate.
* dotlock/dotlock.c: Use new locker functions.
* lib/manlock.c: Likewise.
* libmailutils/base/amd.c: Likewise.
* libmu_dbm/berkeley.c: Likewise.
* libmu_sieve/extensions/vacation.c: Likewise.
* libproto/dotmail/dotmail.c: Likewise.
* libproto/mbox/mboxrd.c: Likewise.
* mail/copy.c: Likewise.
* mda/lmtpd/lmtpd.c: Modify mu_locker_defaults instead of using
deprecated functions.
* mda/mda/mda.c: Likewise.
* mda/putmail/putmail.c: Likewise.
* NEWS: Document changes.
* configure.ac: Version 3.12.90.
* doc/texinfo/Makefile.am: Add programs/dotlock.texi
* doc/texinfo/programs.texi: Rewrite the locking section.
New section: dotlock.
* doc/texinfo/programs/dotlock.texi: New file.
Diffstat (limited to 'include')
-rw-r--r-- | include/mailutils/locker.h | 198 |
1 files changed, 108 insertions, 90 deletions
diff --git a/include/mailutils/locker.h b/include/mailutils/locker.h index 21aed9de9..082bbd942 100644 --- a/include/mailutils/locker.h +++ b/include/mailutils/locker.h @@ -25,105 +25,56 @@ extern "C" { #endif /* lock expiry time */ -#define MU_LOCKER_EXPIRE_TIME (10 * 60) -#define MU_LOCKER_RETRIES (10) -#define MU_LOCKER_RETRY_SLEEP (1) -#define MU_LOCKER_EXTERNAL_PROGRAM "dotlock" +#define MU_LOCKER_DEFAULT_EXPIRE_TIME (10 * 60) +#define MU_LOCKER_DEFAULT_RETRY_COUNT 10 +#define MU_LOCKER_DEFAULT_RETRY_SLEEP 1 +#define MU_LOCKER_DEFAULT_EXT_LOCKER "dotlock" /* return codes for the external locker */ -#define MU_DL_EX_PERM 4 /* insufficient permissions */ -#define MU_DL_EX_EXIST 3 /* lock requested, but file is already locked */ -#define MU_DL_EX_NEXIST 2 /* unlock requested, but file is not locked */ -#define MU_DL_EX_ERROR 1 /* failed due to some other error */ -#define MU_DL_EX_OK 0 /* success */ - -enum mu_locker_set_mode +enum { - mu_locker_assign, - mu_locker_set_bit, - mu_locker_clear_bit + MU_DL_EX_OK = 0, /* success */ + MU_DL_EX_ERROR = 1, /* failed due to some other error */ + MU_DL_EX_NEXIST = 2, /* unlock requested, but file is not locked */ + MU_DL_EX_EXIST = 3, /* lock requested, but file is already locked */ + MU_DL_EX_PERM = 4, /* insufficient permissions */ }; - -/* mu_locker_create() flags */ /* Locker types */ +enum + { + MU_LOCKER_TYPE_DOTLOCK = 0, /* Dotlock-style locking. The default. */ + MU_LOCKER_TYPE_EXTERNAL = 1, /* Use external program to lock the file. */ + MU_LOCKER_TYPE_KERNEL = 2, /* Use kernel locking (flock,lockf,ioctl) */ + MU_LOCKER_TYPE_NULL = 3, /* No locking at all. */ + }; -#define MU_LOCKER_TYPE_DOTLOCK 0 -#define MU_LOCKER_TYPE_EXTERNAL 1 - /* Use an external program to lock the file. This is necessary - for programs having permission to access a file, but do not - have write permission on the directory that contains that file. */ -#define MU_LOCKER_TYPE_KERNEL 2 - /* Use kernel locking (flock, lockf or ioctl) */ -#define MU_LOCKER_TYPE_NULL 3 - /* Special locker type: means no lock. This is to be used with - temporary mailboxes stored in memory. */ - -#define MU_LOCKER_TYPE_TO_FLAG(t) ((t) << 8) -#define MU_LOCKER_FLAG_TO_TYPE(f) ((f) >> 8) -#define MU_LOCKER_IS_TYPE(f,t) (MU_LOCKER_FLAG_TO_TYPE(f) == (t)) -#define MU_LOCKER_SET_TYPE(f,t) ((f) = MU_LOCKER_TYPE_TO_FLAG(t) | MU_LOCKER_OPTIONS(f)) -#define MU_LOCKER_TYPE_MASK 0xff00 -#define MU_LOCKER_OPTION_MASK 0x00ff -#define MU_LOCKER_OPTIONS(f) ((f) & MU_LOCKER_OPTION_MASK) +#define MU_LOCKER_TYPE_DEFAULT MU_LOCKER_TYPE_DOTLOCK -#define MU_LOCKER_NULL MU_LOCKER_TYPE_TO_FLAG(MU_LOCKER_TYPE_NULL) -#define MU_LOCKER_DOTLOCK MU_LOCKER_TYPE_TO_FLAG(MU_LOCKER_TYPE_DOTLOCK) -#define MU_LOCKER_EXTERNAL MU_LOCKER_TYPE_TO_FLAG(MU_LOCKER_TYPE_EXTERNAL) -#define MU_LOCKER_KERNEL MU_LOCKER_TYPE_TO_FLAG(MU_LOCKER_TYPE_KERNEL) - -/* Options */ - -#define MU_LOCKER_SIMPLE 0x0000 - /* Just try and dotlock the file, not the default because its usually - better to retry. */ -#define MU_LOCKER_RETRY 0x0001 - /* This requests that we loop retries times, sleeping retry_sleep - seconds in between trying to obtain the lock before failing with - MU_LOCK_CONFLICT. */ -#define MU_LOCKER_TIME 0x0002 - /* This mode checks the last update time of the lock, then removes - it if older than MU_LOCKER_EXPIRE_TIME. If a client uses this, - then the servers better periodically update the lock on the - file... do they? */ -#define MU_LOCKER_PID 0x0004 - /* PID locking is only useful for programs that aren't using - an external dotlocker, non-setgid programs will use a dotlocker, - which locks and exits imediately. This is a protection against - a server crashing, it's not generally useful. */ +typedef struct +{ + int flags; + int type; + unsigned retry_count; + unsigned retry_sleep; + unsigned expire_time; + char *ext_locker; +} mu_locker_hints_t; + +/* Locker hint flags */ +#define MU_LOCKER_FLAG_RETRY 0x0001 /* retry_count and retry_sleep are set */ +#define MU_LOCKER_FLAG_EXPIRE_TIME 0x0002 /* expire_time is set */ +#define MU_LOCKER_FLAG_CHECK_PID 0x0004 /* check if lock owner PID is active */ +#define MU_LOCKER_FLAG_EXT_LOCKER 0x0008 /* ext_locker is set */ +#define MU_LOCKER_FLAG_TYPE 0x0010 /* type is set */ + +#define MU_LOCKER_FLAGS_ALL (\ + MU_LOCKER_FLAG_TYPE | \ + MU_LOCKER_FLAG_RETRY | \ + MU_LOCKER_FLAG_EXPIRE_TIME | \ + MU_LOCKER_FLAG_EXT_LOCKER | \ + MU_LOCKER_FLAG_CHECK_PID ) -#define MU_LOCKER_DEFAULT (MU_LOCKER_DOTLOCK | MU_LOCKER_RETRY) - -/* Use these flags for as the default locker flags (the default defaults - * to MU_LOCKER_DEFAULT). A flags of 0 resets the flags back to the - * the default. - */ -extern int mu_locker_set_default_flags (int flags, enum mu_locker_set_mode mode); -extern void mu_locker_set_default_retry_timeout (time_t to); -extern void mu_locker_set_default_retry_count (size_t n); -extern void mu_locker_set_default_expire_timeout (time_t t); -extern int mu_locker_set_default_external_program (char const *path); - -/* A flags of 0 means that the default will be used. */ -extern int mu_locker_create (mu_locker_t *, const char *filename, int flags); -extern void mu_locker_destroy (mu_locker_t *); - -/* Time is measured in seconds. */ - -extern int mu_locker_set_flags (mu_locker_t, int); -extern int mu_locker_mod_flags (mu_locker_t locker, int flags, - enum mu_locker_set_mode mode); -extern int mu_locker_set_expire_time (mu_locker_t, int); -extern int mu_locker_set_retries (mu_locker_t, int); -extern int mu_locker_set_retry_sleep (mu_locker_t, int); -extern int mu_locker_set_external (mu_locker_t, const char* program); - -extern int mu_locker_get_flags (mu_locker_t, int*); -extern int mu_locker_get_expire_time (mu_locker_t, int*); -extern int mu_locker_get_retries (mu_locker_t, int*); -extern int mu_locker_get_retry_sleep (mu_locker_t, int*); -extern int mu_locker_get_external (mu_locker_t, char**); - enum mu_locker_mode { mu_lck_shr, /* Shared (advisory) lock */ @@ -132,12 +83,79 @@ enum mu_locker_mode locking otherwise */ }; +#define MU_LOCKFILE_MODE 0644 + +extern int mu_locker_create_ext (mu_locker_t *, const char *, mu_locker_hints_t *); +extern int mu_locker_modify (mu_locker_t, mu_locker_hints_t *); +extern void mu_locker_destroy (mu_locker_t *); + extern int mu_locker_lock_mode (mu_locker_t, enum mu_locker_mode); extern int mu_locker_lock (mu_locker_t); extern int mu_locker_touchlock (mu_locker_t); extern int mu_locker_unlock (mu_locker_t); extern int mu_locker_remove_lock (mu_locker_t); +extern int mu_locker_get_hints (mu_locker_t lck, mu_locker_hints_t *hints); + +extern mu_locker_hints_t mu_locker_defaults; + +/* + * Deprecated defines and interfaces. + */ + +/* Legacy definitions for locker defaults */ +#define MU_LOCKER_EXPIRE_TIME MU_LOCKER_DEFAULT_EXPIRE_TIME +#define MU_LOCKER_RETRIES MU_LOCKER_DEFAULT_RETRY_COUNT +#define MU_LOCKER_RETRY_SLEEP MU_LOCKER_DEFAULT_RETRY_SLEEP +#define MU_LOCKER_EXTERNAL_PROGRAM MU_LOCKER_DEFAULT_EXT_LOCKER + +/* Legacy definitions of locker types */ +#define MU_LOCKER_DOTLOCK (MU_LOCKER_TYPE_DOTLOCK << 8) +#define MU_LOCKER_EXTERNAL (MU_LOCKER_TYPE_EXTERNAL << 8) +#define MU_LOCKER_KERNEL (MU_LOCKER_TYPE_KERNEL << 8) +#define MU_LOCKER_NULL (MU_LOCKER_TYPE_NULL << 8) + +/* Legacy definitions of locker flags (a.k.a. options). */ +#define MU_LOCKER_SIMPLE 0x0000 +#define MU_LOCKER_RETRY MU_LOCKER_FLAG_RETRY +#define MU_LOCKER_TIME MU_LOCKER_FLAG_EXPIRE_TIME +#define MU_LOCKER_PID MU_LOCKER_FLAG_CHECK_PID + +#define MU_LOCKER_DEFAULT (MU_LOCKER_DOTLOCK | MU_LOCKER_RETRY) + +/* The following was used to pack/unpack flags and locker type: */ +#define MU_LOCKER_TYPE_TO_FLAG(t) ((t) << 8) +#define MU_LOCKER_FLAG_TO_TYPE(f) ((f) >> 8) +#define MU_LOCKER_TYPE_MASK 0xff00 +#define MU_LOCKER_OPTION_MASK 0x00ff + +enum mu_locker_set_mode + { + mu_locker_assign, + mu_locker_set_bit, + mu_locker_clear_bit + }; + +extern int mu_locker_create (mu_locker_t *, const char *, int) MU_DEPRECATED; + +extern int mu_locker_set_default_flags (int, enum mu_locker_set_mode) MU_DEPRECATED; +extern void mu_locker_set_default_retry_timeout (time_t) MU_DEPRECATED; +extern void mu_locker_set_default_retry_count (size_t) MU_DEPRECATED; +extern void mu_locker_set_default_expire_timeout (time_t) MU_DEPRECATED; +extern int mu_locker_set_default_external_program (char const *) MU_DEPRECATED; + +extern int mu_locker_set_flags (mu_locker_t, int) MU_DEPRECATED; +extern int mu_locker_mod_flags (mu_locker_t, int, enum mu_locker_set_mode) MU_DEPRECATED; +extern int mu_locker_set_expire_time (mu_locker_t, int) MU_DEPRECATED; +extern int mu_locker_set_retries (mu_locker_t, int) MU_DEPRECATED; +extern int mu_locker_set_retry_sleep (mu_locker_t, int) MU_DEPRECATED; +extern int mu_locker_set_external (mu_locker_t, const char *) MU_DEPRECATED; + +extern int mu_locker_get_flags (mu_locker_t, int *) MU_DEPRECATED; +extern int mu_locker_get_expire_time (mu_locker_t, int *) MU_DEPRECATED; +extern int mu_locker_get_retries (mu_locker_t, int *) MU_DEPRECATED; +extern int mu_locker_get_retry_sleep (mu_locker_t, int *) MU_DEPRECATED; + #ifdef __cplusplus } #endif |