summaryrefslogtreecommitdiff
path: root/libmailutils
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-11-19 16:24:15 +0200
committerSergey Poznyakoff <gray@gnu.org>2020-11-19 16:24:15 +0200
commit249bf7eb77d97029ec3b87ad5269aec869c06c51 (patch)
tree77718a15e6b6a0b200ae6fc44e018c4a75a8d196 /libmailutils
parent8a652e11b61555a7cf949ef66504a50b99cc55a1 (diff)
downloadmailutils-249bf7eb77d97029ec3b87ad5269aec869c06c51.tar.gz
mailutils-249bf7eb77d97029ec3b87ad5269aec869c06c51.tar.bz2
Make sure UIDs are monotonically increased in dotmail, mh, and maildir.
* include/mailutils/sys/amd.h (_MU_AMD_PROP_UIDNEXT): New define. (MU_AMD_PROP): Remove. (MU_AMD_F_PROP): New flag. (_amd_data): New member: flags. Remove next_uid (amd_reset_uidvalidity): Change return type. (amd_update_uidnext,amd_alloc_uid): New protos. * include/mailutils/sys/dotmail.h (mu_dotmail_mailbox): New member uidvalidity_changed. * libmailutils/base/amd.c (_amd_prop_create): Set MU_AMD_F_PROP flag if the prop file exists. (amd_initial_scan): New function. (amd_get_uidvalidity, amd_set_uidvalidity) (amd_uidnext): Rewrite using amd_initial_scan. (amd_reset_uidvalidity): Return int. (amd_update_uidnext,amd_alloc_uid): New functions. * libproto/dotmail/dotmail.c (dotmail_close): Flush UID parameters if uidvalidity_changed is set. (dotmail_flush): Take three-state mode as its third argument. (dotmail_flush_unlocked): Likewise. If operating in FLUSH_UIDVALIDITY mode, clear all other modifications to the messages in the mailbox. Clear uidvalidity_changed on success. (dotmail_expunge, dotmail_sync): Update call to dotmail_flush. (dotmail_alloc_next_uid): Set uidvalidity_changed. (dotmail_rescan_unlocked): Check if the assigned UID is greater than the previously assigned one and less than the UIDNEXT value. Raise uidvalidity_changed if UIDs were re-allocated. (mu_dotmail_mailbox_uid_setup): Set uidvalidity_scanned. * libproto/dotmail/tests/Makefile.am: Add new test. * libproto/dotmail/tests/testsuite.at: Likewise. * libproto/dotmail/tests/uidnext.at: New test. * libproto/maildir/mbox.c: Use amd_update_uidnext to synchronize the computed and predicted uidnext value. (maildir_next_uid): Remove. * libproto/maildir/tests/Makefile.am: Add new test. * libproto/maildir/tests/testsuite.at: Likewise. * libproto/maildir/tests/uidnext.at: New test. * libproto/mh/mbox.c (_mh_next_seq): Remove function. (mh_scan0): Use amd_update_uidnext to synchronize the computed and predicted uidnext value. * libproto/mh/tests/Makefile.am: Add new test. * libproto/mh/tests/testsuite.at: Likewise. * libproto/mh/tests/uidnext.at: New test.
Diffstat (limited to 'libmailutils')
-rw-r--r--libmailutils/base/amd.c96
1 files changed, 59 insertions, 37 deletions
diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c
index 797c4ff8f..9913dc7e1 100644
--- a/libmailutils/base/amd.c
+++ b/libmailutils/base/amd.c
@@ -228,7 +228,7 @@ _amd_prop_create (struct _amd_data *amd)
if (access (mhprop->filename, F_OK) == 0)
{
- amd->capabilities |= MU_AMD_PROP;
+ amd->flags |= MU_AMD_F_PROP;
}
rc = mu_property_create_init (&amd->prop, mu_mh_property_init, mhprop);
@@ -1471,38 +1471,36 @@ amd_sync (mu_mailbox_t mailbox)
return 0;
}
-static int
-amd_get_uidvalidity (mu_mailbox_t mailbox, unsigned long *puidvalidity)
+static inline int
+amd_initial_scan (struct _amd_data *amd)
{
- struct _amd_data *amd = mailbox->data;
- int status = amd_messages_count (mailbox, NULL);
- if (status != 0)
- return status;
- /* If we did not start scanning yet do it now. */
- if (amd->msg_count == 0)
+ if (!(amd->flags & MU_AMD_F_INIT_SCAN))
{
- status = _amd_scan0 (amd, 1, NULL, 0);
+ int status = _amd_scan0 (amd, 1, NULL, 0);
if (status != 0)
- return status;
+ return status;
+ amd->flags |= MU_AMD_F_INIT_SCAN;
}
+ return 0;
+}
- return _amd_prop_fetch_ulong (amd, _MU_AMD_PROP_UIDVALIDITY, puidvalidity);
+static int
+amd_get_uidvalidity (mu_mailbox_t mailbox, unsigned long *pval)
+{
+ struct _amd_data *amd = mailbox->data;
+ int status = amd_initial_scan (amd);
+ if (status != 0)
+ return status;
+ return _amd_prop_fetch_ulong (amd, _MU_AMD_PROP_UIDVALIDITY, pval);
}
static int
amd_set_uidvalidity (mu_mailbox_t mailbox, unsigned long uidvalidity)
{
struct _amd_data *amd = mailbox->data;
- int status = amd_messages_count (mailbox, NULL);
+ int status = amd_initial_scan (amd);
if (status != 0)
return status;
- /* If we did not start scanning yet do it now. */
- if (amd->msg_count == 0)
- {
- status = _amd_scan0 (amd, 1, NULL, 0);
- if (status != 0)
- return status;
- }
return _amd_prop_store_off (amd, _MU_AMD_PROP_UIDVALIDITY, uidvalidity);
}
@@ -1510,23 +1508,10 @@ static int
amd_uidnext (mu_mailbox_t mailbox, size_t *puidnext)
{
struct _amd_data *amd = mailbox->data;
- int status;
-
- if (!amd->next_uid)
- return ENOSYS;
- status = mu_mailbox_messages_count (mailbox, NULL);
+ int status = amd_initial_scan (amd);
if (status != 0)
return status;
- /* If we did not start a scanning yet do it now. */
- if (amd->msg_count == 0)
- {
- status = _amd_scan0 (amd, 1, NULL, 0);
- if (status != 0)
- return status;
- }
- if (puidnext)
- *puidnext = amd->next_uid (amd);
- return 0;
+ return _amd_prop_fetch_size (amd, _MU_AMD_PROP_UIDNEXT, puidnext);
}
/* FIXME: effectively the same as mbox_cleanup */
@@ -2171,12 +2156,49 @@ amd_remove_dir (const char *name)
return rc;
}
-void
+int
amd_reset_uidvalidity (struct _amd_data *amd)
{
struct timeval tv;
gettimeofday (&tv, NULL);
- _amd_prop_store_off (amd, _MU_AMD_PROP_UIDVALIDITY, tv.tv_sec);
+ return _amd_prop_store_off (amd, _MU_AMD_PROP_UIDVALIDITY, tv.tv_sec);
+}
+
+int
+amd_update_uidnext (struct _amd_data *amd, size_t *newval)
+{
+ int rc;
+ size_t curval;
+
+ rc = _amd_prop_fetch_size (amd, _MU_AMD_PROP_UIDNEXT, &curval);
+ if (rc == MU_ERR_NOENT)
+ curval = 1;
+ else if (rc)
+ return rc;
+ if (*newval < curval)
+ {
+ *newval = curval;
+ return 0;
+ }
+ return _amd_prop_store_off (amd, _MU_AMD_PROP_UIDNEXT, *newval);
+}
+
+int
+amd_alloc_uid (struct _amd_data *amd, size_t *newval)
+{
+ int rc;
+ size_t retval;
+
+ rc = _amd_prop_fetch_size (amd, _MU_AMD_PROP_UIDNEXT, &retval);
+ if (rc == MU_ERR_NOENT)
+ retval = 1;
+ else if (rc)
+ return rc;
+ rc = _amd_prop_store_off (amd, _MU_AMD_PROP_UIDNEXT, retval + 1);
+ if (rc)
+ return rc;
+ *newval = retval;
+ return 0;
}

Return to:

Send suggestions and report system problems to the System administrator.