diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-10-20 16:16:02 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-10-20 16:30:00 +0300 |
commit | fa3be4baf0edf9c9df06ca272a19fae88c71d88b (patch) | |
tree | 91755894f2d64b7d84489c707c0fe681653eafaa | |
parent | f697923aaf4a171efe5a074fc064edf415d6643f (diff) | |
download | mailutils-fa3be4baf0edf9c9df06ca272a19fae88c71d88b.tar.gz mailutils-fa3be4baf0edf9c9df06ca272a19fae88c71d88b.tar.bz2 |
Change attribute handling in Maildir format.
* include/mailutils/message.h (MU_MSG_ATTRIBUTE_MODIFIED)
(MU_MSG_HEADER_MODIFIED,MU_MSG_BODY_MODIFIED): New flags.
* libmailutils/mailbox/message.c (mu_message_is_modified): Return
a bitmask from the above values.
* libmailutils/property/create.c (mu_property_create_init): Return
error code.
* include/mailutils/sys/amd.h (_amd_data) <chattr_msg>
<capabilities, prop>: New members.
<uidvalidity>: Remove.
* libmailutils/base/amd.c: Use MH-style proplist to keep
the mailbox properties: uidvalidity, last uid and to
cache its size.
Store message attributes in the message header only if the
mailbox implementation is unable to keep them elsewhere.
Use chattr_msg method (if provided) to flush changes in
message attributes.
* libproto/maildir/folder.c (_maildir_list_p): Ignore .mh* and .mu* files.
* libproto/mh/folder.c (_mh_list_p): Likewise.
* libproto/maildir/mbox.c: Implement all Maildir flags (except P).
Implement the chattr_msg method.
* libproto/mh/mbox.c: Remove special handling for uidvalidity.
* mh/tests/folder.at: Ignore .mu-prop in directory listings.
-rw-r--r-- | include/mailutils/message.h | 5 | ||||
-rw-r--r-- | include/mailutils/sys/amd.h | 19 | ||||
-rw-r--r-- | libmailutils/base/amd.c | 433 | ||||
-rw-r--r-- | libmailutils/mailbox/message.c | 12 | ||||
-rw-r--r-- | libmailutils/property/create.c | 2 | ||||
-rw-r--r-- | libproto/maildir/folder.c | 3 | ||||
-rw-r--r-- | libproto/maildir/mbox.c | 66 | ||||
-rw-r--r-- | libproto/mh/folder.c | 8 | ||||
-rw-r--r-- | libproto/mh/mbox.c | 16 | ||||
-rw-r--r-- | mh/tests/folder.at | 4 |
10 files changed, 378 insertions, 190 deletions
diff --git a/include/mailutils/message.h b/include/mailutils/message.h index 605817cc8..79878ac89 100644 --- a/include/mailutils/message.h +++ b/include/mailutils/message.h @@ -53,6 +53,11 @@ extern void mu_message_destroy (mu_message_t *, void *owner); extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); extern void *mu_message_get_owner (mu_message_t); + +#define MU_MSG_ATTRIBUTE_MODIFIED 0x01 +#define MU_MSG_HEADER_MODIFIED 0x02 +#define MU_MSG_BODY_MODIFIED 0x04 + extern int mu_message_is_modified (mu_message_t); extern int mu_message_clear_modified (mu_message_t); extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); diff --git a/include/mailutils/sys/amd.h b/include/mailutils/sys/amd.h index 35c54c5f6..ce710d0e5 100644 --- a/include/mailutils/sys/amd.h +++ b/include/mailutils/sys/amd.h @@ -43,7 +43,13 @@ mu_monitor_wrlock (mbox->monitor); \ } while (0); -# define MU_AMD_SIZE_FILE_NAME ".mu-size" +#define _MU_AMD_PROP_UIDVALIDITY "uid-validity" +#define _MU_AMD_PROP_NEXT_UID "next-uid" +#define _MU_AMD_PROP_SIZE "size" + +#define _MU_AMD_PROP_FILE_NAME ".mu-prop" +/* Legacy (2.x) size file name */ +#define _MU_AMD_SIZE_FILE_NAME ".mu-size" struct _amd_data; struct _amd_message @@ -64,6 +70,10 @@ struct _amd_message struct _amd_data *amd; /* Back pointer. */ }; +/* AMD capabilities */ +#define MU_AMD_STATUS 0x01 /* format keeps status flags */ +#define MU_AMD_IMAPBASE 0x02 /* format keeps IMAP base */ + struct _amd_data { size_t msg_size; /* Size of struct _amd_message */ @@ -83,16 +93,19 @@ struct _amd_data size_t (*next_uid) (struct _amd_data *mhd); int (*remove) (struct _amd_data *); int (*delete_msg) (struct _amd_data *, struct _amd_message *); - + int (*chattr_msg) (struct _amd_message *, int); + /* List of messages: */ size_t msg_count; /* number of messages in the list */ size_t msg_max; /* maximum message buffer capacity */ struct _amd_message **msg_array; - unsigned long uidvalidity; + int capabilities; int has_new_msg; /* New messages have been appended */ char *name; /* Directory name */ + mu_property_t prop; /* Properties: uidvalidity, nextuid, etc. */ + /* Pool of open message streams */ struct _amd_message *msg_pool[MAX_OPEN_STREAMS]; int pool_first; /* Index to the first used entry in msg_pool */ diff --git a/libmailutils/base/amd.c b/libmailutils/base/amd.c index a63651aab..a5685d99a 100644 --- a/libmailutils/base/amd.c +++ b/libmailutils/base/amd.c @@ -129,7 +129,148 @@ struct _amd_body_stream mu_body_t body; mu_off_t off; }; + +/* AMD Properties */ +int +_amd_prop_fetch_off (struct _amd_data *amd, const char *name, mu_off_t *pval) +{ + const char *p; + mu_off_t n = 0; + + if (!amd->prop || mu_property_sget_value (amd->prop, name, &p)) + return MU_ERR_NOENT; + if (!pval) + return 0; + for (; *p; p++) + { + if (!mu_isdigit (*p)) + return EINVAL; + n = n * 10 + *p - '0'; + } + *pval = n; + return 0; +} + +int +_amd_prop_fetch_size (struct _amd_data *amd, const char *name, size_t *pval) +{ + mu_off_t n; + int rc = _amd_prop_fetch_off (amd, name, &n); + if (rc == 0) + { + size_t s = n; + if (s != n) + return ERANGE; + if (pval) + *pval = s; + } + return rc; +} + +int +_amd_prop_fetch_ulong (struct _amd_data *amd, const char *name, + unsigned long *pval) +{ + mu_off_t n; + int rc = _amd_prop_fetch_off (amd, name, &n); + if (rc == 0) + { + unsigned long s = n; + if (s != n) + return ERANGE; + if (pval) + *pval = s; + } + return rc; +} +int +_amd_prop_store_off (struct _amd_data *amd, const char *name, mu_off_t val) +{ + char nbuf[128]; + char *p; + int sign = 0; + + p = nbuf + sizeof nbuf; + *--p = 0; + if (val < 0) + { + sign = 1; + val = - val; + } + do + { + unsigned d = val % 10; + if (p == nbuf) + return ERANGE; + *--p = d + '0'; + val /= 10; + } + while (val); + if (sign) + { + if (p == nbuf) + return ERANGE; + *--p = '-'; + } + return mu_property_set_value (amd->prop, name, p, 1); +} + +/* Backward-compatible size file support */ +static int +read_size_file (struct _amd_data *amd) +{ + FILE *fp; + int rc; + char *name = mu_make_file_name (amd->name, _MU_AMD_SIZE_FILE_NAME); + if (!name) + return 1; + fp = fopen (name, "r"); + if (fp) + { + unsigned long size; + if (fscanf (fp, "%lu", &size) == 1) + { + rc = _amd_prop_store_off (amd, _MU_AMD_PROP_SIZE, size); + } + else + rc = 1; + fclose (fp); + unlink (name); + } + else + rc = 1; + free (name); + return rc; +} + +static int +_amd_prop_create (struct _amd_data *amd) +{ + int rc; + struct mu_mh_prop *mhprop; + mhprop = calloc (1, sizeof (mhprop[0])); + if (!mhprop) + return ENOMEM; + mhprop->filename = mu_make_file_name (amd->name, _MU_AMD_PROP_FILE_NAME); + if (!mhprop->filename) + { + free (mhprop); + return errno; + } + rc = mu_property_create_init (&amd->prop, mu_mh_property_init, mhprop); + if (rc) + { + mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, + ("mu_property_create_init: %s", + mu_strerror (rc))); + free (mhprop->filename); + free (mhprop); + } + else + read_size_file (amd); + return rc; +} /* Operations on message array */ @@ -246,8 +387,8 @@ amd_array_expand (struct _amd_data *amd, size_t index) return 0; } -/* Shrink the message array by removing element at INDEX-COUNT and - shifting left by COUNT positions all the elements on the right of +/* Shrink the message array by removing the element at INDEX-COUNT and + shifting left by COUNT positions all the elements to the right of it. */ int amd_array_shrink (struct _amd_data *amd, size_t index, size_t count) @@ -273,7 +414,7 @@ amd_init_mailbox (mu_mailbox_t mailbox, size_t amd_size, return EINVAL; amd = mailbox->data = calloc (1, amd_size); - if (mailbox->data == NULL) + if (amd == NULL) return ENOMEM; /* Back pointer. */ @@ -333,7 +474,9 @@ amd_destroy (mu_mailbox_t mailbox) free (amd->msg_array[i]); } free (amd->msg_array); - + + mu_property_destroy (&amd->prop); + if (amd->name) free (amd->name); @@ -374,6 +517,9 @@ amd_open (mu_mailbox_t mailbox, int flags) W_OK : R_OK | X_OK)) return errno; + /* Create/read properties. It is not an error if this fails. */ + _amd_prop_create (amd); + if (mailbox->locker == NULL) mu_locker_create (&mailbox->locker, "/dev/null", 0); @@ -405,7 +551,6 @@ amd_close (mu_mailbox_t mailbox) amd->msg_count = 0; /* number of messages in the list */ amd->msg_max = 0; /* maximum message buffer capacity */ - amd->uidvalidity = 0; mu_monitor_unlock (mailbox->monitor); return 0; @@ -547,6 +692,27 @@ _amd_attach_message (mu_mailbox_t mailbox, struct _amd_message *mhm, } static int +_amd_scan0 (struct _amd_data *amd, size_t msgno, size_t *pcount, + int do_notify) +{ + int status = amd->scan0 (amd->mailbox, msgno, pcount, do_notify); + if (status != 0) + return status; + /* Reset the uidvalidity. */ + if (amd->msg_count > 0) + { + unsigned long uidval; + if (_amd_prop_fetch_ulong (amd, _MU_AMD_PROP_UIDVALIDITY, &uidval) || + !uidval) + { + uidval = (unsigned long)time (NULL); + _amd_prop_store_off (amd, _MU_AMD_PROP_UIDVALIDITY, uidval); + } + } + return 0; +} + +static int amd_get_message (mu_mailbox_t mailbox, size_t msgno, mu_message_t *pmsg) { int status; @@ -562,7 +728,7 @@ amd_get_message (mu_mailbox_t mailbox, size_t msgno, mu_message_t *pmsg) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - status = amd->scan0 (mailbox, 1, NULL, 0); + status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) return status; } @@ -647,7 +813,6 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, mu_body_t body; const char *sbuf; mu_envelope_t env = NULL; - char statbuf[MU_STATUS_BUF_SIZE]; status = mu_message_size (msg, &bsize); if (status) @@ -724,17 +889,6 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, } mu_stream_destroy (&stream); - /* Add imapbase */ - if (!(amd->mailbox->flags & MU_STREAM_APPEND) - && amd->next_uid - && (!amd->msg_array || (amd->msg_array[0] == mhm))) /*FIXME*/ - { - nbytes += fprintf (fp, "X-IMAPbase: %lu %u\n", - (unsigned long) amd->uidvalidity, - (unsigned) amd->next_uid (amd)); - nlines++; - } - mu_message_get_envelope (msg, &env); if (mu_envelope_sget_date (env, &sbuf) == 0) { @@ -754,15 +908,21 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, fprintf (fp, "%s: %s\n", MU_HEADER_ENV_SENDER, sbuf); nlines++; } - - /* Add status */ - mu_message_get_attribute (msg, &attr); - mu_attribute_to_string (attr, statbuf, sizeof (statbuf), &n); - if (n) + + if (!(amd->capabilities & MU_AMD_STATUS)) { - nbytes += fprintf (fp, "Status: %s\n", statbuf); - nlines++; + /* Add status */ + char statbuf[MU_STATUS_BUF_SIZE]; + + mu_message_get_attribute (msg, &attr); + mu_attribute_to_string (attr, statbuf, sizeof (statbuf), &n); + if (n) + { + nbytes += fprintf (fp, "Status: %s\n", statbuf); + nlines++; + } } + nbytes += fprintf (fp, "\n"); nlines++; @@ -858,7 +1018,7 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - status = amd->scan0 (mailbox, 1, NULL, 0); + status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) { free (mhm); @@ -923,7 +1083,7 @@ amd_messages_count (mu_mailbox_t mailbox, size_t *pcount) return EINVAL; if (!amd_is_updated (mailbox)) - return amd->scan0 (mailbox, amd->msg_count, pcount, 0); + return _amd_scan0 (amd, amd->msg_count, pcount, 0); if (pcount) *pcount = amd->msg_count; @@ -943,7 +1103,7 @@ amd_messages_recent (mu_mailbox_t mailbox, size_t *pcount) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - int status = amd->scan0 (mailbox, 1, NULL, 0); + int status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) return status; } @@ -967,7 +1127,7 @@ amd_message_unseen (mu_mailbox_t mailbox, size_t *pmsgno) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - int status = amd->scan0 (mailbox, 1, NULL, 0); + int status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) return status; } @@ -982,71 +1142,10 @@ amd_message_unseen (mu_mailbox_t mailbox, size_t *pmsgno) } return 0; } - -static char * -make_size_file_name (struct _amd_data *amd) -{ - size_t size = strlen (amd->name) + 1 + sizeof (MU_AMD_SIZE_FILE_NAME); - char *name = malloc (size); - if (name) - { - strcpy (name, amd->name); - strcat (name, "/"); - strcat (name, MU_AMD_SIZE_FILE_NAME); - } - return name; -} - -static int -read_size_file (struct _amd_data *amd, mu_off_t *psize) -{ - FILE *fp; - int rc; - char *name = make_size_file_name (amd); - if (!name) - return 1; - fp = fopen (name, "r"); - if (fp) - { - unsigned long size; - if (fscanf (fp, "%lu", &size) == 1) - { - *psize = size; - rc = 0; - } - else - rc = 1; - fclose (fp); - } - else - rc = 1; - free (name); - return rc; -} - -static int -write_size_file (struct _amd_data *amd, mu_off_t size) -{ - FILE *fp; - int rc; - char *name = make_size_file_name (amd); - if (!name) - return 1; - fp = fopen (name, "w"); - if (fp) - { - fprintf (fp, "%lu", (unsigned long) size); - fclose (fp); - rc = 0; - } - else - rc = 1; - free (name); - return rc; -} - + static int -compute_mailbox_size (struct _amd_data *amd, const char *name, mu_off_t *psize) +_compute_mailbox_size_recursive (struct _amd_data *amd, const char *name, + mu_off_t *psize) { DIR *dir; struct dirent *entry; @@ -1099,7 +1198,7 @@ compute_mailbox_size (struct _amd_data *amd, const char *name, mu_off_t *psize) if (S_ISREG (sb.st_mode)) *psize += sb.st_size; else if (S_ISDIR (sb.st_mode)) - compute_mailbox_size (amd, buf, psize); + _compute_mailbox_size_recursive (amd, buf, psize); } /* FIXME: else? */ break; @@ -1113,6 +1212,20 @@ compute_mailbox_size (struct _amd_data *amd, const char *name, mu_off_t *psize) } static int +compute_mailbox_size (struct _amd_data *amd, mu_off_t *psize) +{ + mu_off_t size = 0; + int rc = _compute_mailbox_size_recursive (amd, amd->name, &size); + if (rc == 0) + { + rc = _amd_prop_store_off (amd, _MU_AMD_PROP_SIZE, size); + if (rc == 0 && psize) + *psize = size; + } + return rc; +} + +static int amd_remove_mbox (mu_mailbox_t mailbox) { int rc; @@ -1123,11 +1236,22 @@ amd_remove_mbox (mu_mailbox_t mailbox) rc = amd->remove (amd); if (rc == 0) { - char *name = make_size_file_name (amd); + char *name; + + name = mu_make_file_name (amd->name, _MU_AMD_SIZE_FILE_NAME); if (!name) return ENOMEM; if (unlink (name) && errno != ENOENT) rc = errno; + else + { + free (name); + name = mu_make_file_name (amd->name, _MU_AMD_PROP_FILE_NAME); + if (!name) + return ENOMEM; + if (unlink (name) && errno != ENOENT) + rc = errno; + } free (name); } @@ -1147,6 +1271,55 @@ amd_remove_mbox (mu_mailbox_t mailbox) } static int +_amd_update_message (struct _amd_data *amd, struct _amd_message *mhm, + int expunge, int *upd) +{ + int flg, rc; + + if (mhm->message) + flg = mu_message_is_modified (mhm->message); + else if (mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) + flg = MU_MSG_ATTRIBUTE_MODIFIED; + + if (!flg) + return 0; + + if (flg == MU_MSG_ATTRIBUTE_MODIFIED && amd->chattr_msg) + { + rc = amd->chattr_msg (mhm, expunge); + if (rc) + { + mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, + ("_amd_update_message: chattr_msg failed: %s", + mu_strerror (rc))); + return rc; + } + } + else + { + rc = _amd_attach_message (amd->mailbox, mhm, NULL); + if (rc) + { + mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, + ("_amd_update_message: _amd_attach_message failed: %s", + mu_strerror (rc))); + return rc; + } + + rc = _amd_message_save (amd, mhm, expunge); + if (rc) + { + mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, + ("_amd_update_message: _amd_message_save failed: %s", + mu_strerror (rc))); + return rc; + } + } + *upd = 1; + return rc; +} + +static int amd_expunge (mu_mailbox_t mailbox) { struct _amd_data *amd = mailbox->data; @@ -1232,13 +1405,7 @@ amd_expunge (mu_mailbox_t mailbox) } else { - if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) - || (mhm->message && mu_message_is_modified (mhm->message))) - { - _amd_attach_message (mailbox, mhm, NULL); - _amd_message_save (amd, mhm, 1); - updated = 1; - } + _amd_update_message (amd, mhm, 1, &updated);/*FIXME: Error checking*/ } } @@ -1263,10 +1430,7 @@ amd_expunge (mu_mailbox_t mailbox) if (updated && !amd->mailbox_size) { - mu_off_t size = 0; - int rc = compute_mailbox_size (amd, amd->name, &size); - if (rc == 0) - write_size_file (amd, size); + compute_mailbox_size (amd, NULL); } return 0; } @@ -1297,22 +1461,12 @@ amd_sync (mu_mailbox_t mailbox) for ( ; i < amd->msg_count; i++) { mhm = amd->msg_array[i]; - - if ((mhm->attr_flags & MU_ATTRIBUTE_MODIFIED) - || (mhm->message && mu_message_is_modified (mhm->message))) - { - _amd_attach_message (mailbox, mhm, NULL); - _amd_message_save (amd, mhm, 0); - updated = 1; - } + _amd_update_message (amd, mhm, 0, &updated); } if (updated && !amd->mailbox_size) { - mu_off_t size = 0; - int rc = compute_mailbox_size (amd, amd->name, &size); - if (rc == 0) - write_size_file (amd, size); + compute_mailbox_size (amd, NULL); } return 0; @@ -1328,13 +1482,12 @@ amd_uidvalidity (mu_mailbox_t mailbox, unsigned long *puidvalidity) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - status = amd->scan0 (mailbox, 1, NULL, 0); + status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) return status; } - if (puidvalidity) - *puidvalidity = amd->uidvalidity; - return 0; + + return _amd_prop_fetch_ulong (amd, _MU_AMD_PROP_UIDVALIDITY, puidvalidity); } static int @@ -1351,7 +1504,7 @@ amd_uidnext (mu_mailbox_t mailbox, size_t *puidnext) /* If we did not start a scanning yet do it now. */ if (amd->msg_count == 0) { - status = amd->scan0 (mailbox, 1, NULL, 0); + status = _amd_scan0 (amd, 1, NULL, 0); if (status != 0) return status; } @@ -1458,7 +1611,9 @@ amd_scan_message (struct _amd_message *mhm) size_t body_start = 0; struct stat st; char *msg_name; - + struct _amd_data *amd = mhm->amd; + int amd_capa = amd->capabilities; + /* Check if the message was modified after the last scan */ status = mhm->amd->cur_msg_file_name (mhm, &msg_name); if (status) @@ -1498,17 +1653,25 @@ amd_scan_message (struct _amd_message *mhm) hlines++; /* Process particular attributes */ - if (mu_c_strncasecmp (buf, "status:", 7) == 0) + if (!(amd_capa & MU_AMD_STATUS) && + mu_c_strncasecmp (buf, "status:", 7) == 0) { int deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED; mu_string_to_flags (buf, &mhm->attr_flags); mhm->attr_flags |= deleted; } - else if (mu_c_strncasecmp (buf, "x-imapbase:", 11) == 0) + else if (!(amd_capa & MU_AMD_IMAPBASE) && + mu_c_strncasecmp (buf, "x-imapbase:", 11) == 0) { - char *p; - mhm->amd->uidvalidity = strtoul (buf + 11, &p, 10); - /* second number is next uid. Ignored */ + if (_amd_prop_fetch_ulong (amd, _MU_AMD_PROP_UIDVALIDITY, + NULL)) + { + char *p; + unsigned long uidval = strtoul (buf + 11, &p, 10); + /* The next number is next uid. Ignored */ + _amd_prop_store_off (amd, _MU_AMD_PROP_UIDVALIDITY, + uidval); + } } } else @@ -1545,7 +1708,7 @@ amd_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount) struct _amd_data *amd = mailbox->data; if (! amd_is_updated (mailbox)) - return amd->scan0 (mailbox, msgno, pcount, 1); + return _amd_scan0 (amd, msgno, pcount, 1); if (pcount) *pcount = amd->msg_count; @@ -1573,14 +1736,8 @@ amd_get_size (mu_mailbox_t mailbox, mu_off_t *psize) struct _amd_data *amd = mailbox->data; if (amd->mailbox_size) return amd->mailbox_size (mailbox, psize); - *psize = 0; - if (read_size_file (amd, psize)) - { - int rc = compute_mailbox_size (amd, amd->name, psize); - if (rc == 0) - write_size_file (amd, *psize); - return rc; - } + if (_amd_prop_fetch_off (amd, _MU_AMD_PROP_SIZE, psize)) + return compute_mailbox_size (amd, psize); return 0; } diff --git a/libmailutils/mailbox/message.c b/libmailutils/mailbox/message.c index 01835d699..8cf233af2 100644 --- a/libmailutils/mailbox/message.c +++ b/libmailutils/mailbox/message.c @@ -667,10 +667,14 @@ mu_message_is_modified (mu_message_t msg) int mod = 0; if (msg) { - mod |= mu_header_is_modified (msg->header); - mod |= mu_attribute_is_modified (msg->attribute); - mod |= mu_body_is_modified (msg->body); - mod |= msg->flags; + if (mu_header_is_modified (msg->header)) + mod |= MU_MSG_HEADER_MODIFIED; + if (mu_attribute_is_modified (msg->attribute)) + mod |= MU_MSG_ATTRIBUTE_MODIFIED; + if (mu_body_is_modified (msg->body)) + mod |= MU_MSG_BODY_MODIFIED; + if (msg->flags & MESSAGE_MODIFIED) + mod |= MU_MSG_BODY_MODIFIED | MU_MSG_HEADER_MODIFIED; } return mod; } diff --git a/libmailutils/property/create.c b/libmailutils/property/create.c index c9454ad4b..e91a5ab8c 100644 --- a/libmailutils/property/create.c +++ b/libmailutils/property/create.c @@ -45,7 +45,7 @@ mu_property_create_init (mu_property_t *pprop, mu_property_set_init (prop, initfun, initdata); *pprop = prop; } - return 0; + return rc; } int diff --git a/libproto/maildir/folder.c b/libproto/maildir/folder.c index 539731532..bba68487a 100644 --- a/libproto/maildir/folder.c +++ b/libproto/maildir/folder.c @@ -92,7 +92,8 @@ _maildir_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) return strcmp (name, TMPSUF) && strcmp (name, CURSUF) && strcmp (name, NEWSUF) - && strcmp (name, MU_AMD_SIZE_FILE_NAME); + && !((strlen (name) > 3) && + (memcmp (name, ".mh", 3) == 0 || memcmp (name, ".mu", 3) == 0)); } static struct _mu_record _maildir_record = diff --git a/libproto/maildir/mbox.c b/libproto/maildir/mbox.c index 90768e2c6..acf8f9be1 100644 --- a/libproto/maildir/mbox.c +++ b/libproto/maildir/mbox.c @@ -84,19 +84,24 @@ struct _maildir_message /* Attribute handling. - FIXME: P (Passed), D (Draft) and F (Flagged) are not handled */ + FIXME: P (Passed) is not handled */ static struct info_map { char letter; int flag; } info_map[] = { + { 'D', MU_ATTRIBUTE_DRAFT }, + { 'F', MU_ATTRIBUTE_FLAGGED }, + { 'P', 0 }, /* (passed): the user has resent/forwarded/bounced this + message to someone else. */ { 'R', MU_ATTRIBUTE_READ }, { 'S', MU_ATTRIBUTE_SEEN }, { 'T', MU_ATTRIBUTE_DELETED }, + { 'a', MU_ATTRIBUTE_ANSWERED }, }; #define info_map_size (sizeof (info_map) / sizeof (info_map[0])) -/* NOTE: BUF must be at least 7 bytes long */ +/* NOTE: BUF must be at least info_map_size bytes long */ static int flags_to_info (int flags, char *buf) { @@ -254,7 +259,7 @@ maildir_mkfilename (const char *directory, const char *suffix, const char *name) static char * mk_info_filename (char *directory, char *suffix, char *name, int flags) { - char fbuf[9]; + char fbuf[info_map_size + 1]; char *tmp; int namelen; size_t size; @@ -691,23 +696,6 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, if (pcount) *pcount = amd->msg_count; - /* Reset the uidvalidity. */ - if (amd->msg_count > 0) - { - if (amd->uidvalidity == 0) - { - amd->uidvalidity = (unsigned long) time (NULL); - /* FIXME amd->uidnext = amd->msg_count + 1;*/ - /* Tell that we have been modified for expunging. */ - if (amd->msg_count) - { - amd_message_stream_open (amd->msg_array[0]); - amd_message_stream_close (amd->msg_array[0]); - amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; - } - } - } - /* Clean up the things */ amd_cleanup (mailbox); return status; @@ -773,6 +761,42 @@ maildir_remove (struct _amd_data *amd) return rc; } + +static int +maildir_chattr_msg (struct _amd_message *amsg, int expunge) +{ + struct _maildir_message *mp = (struct _maildir_message *) amsg; + struct _amd_data *amd = amsg->amd; + int rc; + char *new_name; + + rc = amd->new_msg_file_name (amsg, amsg->attr_flags, expunge, &new_name); + if (rc) + return rc; + if (!new_name) + { + if (unlink (mp->file_name)) + rc = errno; + } + else + { + char *cur_name; + + rc = maildir_cur_message_name (amsg, &cur_name); + if (rc) + { + free (new_name); + return rc; + } + if (rename (cur_name, new_name)) + rc = errno; + free (cur_name); + } + + free (new_name); + return rc; +} + int _mailbox_maildir_init (mu_mailbox_t mailbox) @@ -797,6 +821,8 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) amd->message_uid = maildir_message_uid; amd->next_uid = maildir_next_uid; amd->remove = maildir_remove; + amd->chattr_msg = maildir_chattr_msg; + amd->capabilities = MU_AMD_STATUS; /* Set our properties. */ { diff --git a/libproto/mh/folder.c b/libproto/mh/folder.c index 87b94d42b..66e02cfce 100644 --- a/libproto/mh/folder.c +++ b/libproto/mh/folder.c @@ -121,11 +121,9 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) static int _mh_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) { - int len; - - if (strcmp (name, MU_AMD_SIZE_FILE_NAME) == 0 - || name[0] == ',' - || (((len = strlen (name)) > 3) && memcmp (name, ".mh", 3) == 0)) + if (name[0] == ',' || + ((strlen (name) > 3) && + (memcmp (name, ".mh", 3) == 0 || memcmp (name, ".mu", 3) == 0))) return 0; for (; *name; name++) diff --git a/libproto/mh/mbox.c b/libproto/mh/mbox.c index 5a51ba170..6ffa9586a 100644 --- a/libproto/mh/mbox.c +++ b/libproto/mh/mbox.c @@ -278,22 +278,6 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, if (pcount) *pcount = amd->msg_count; - - /* Reset the uidvalidity. */ - if (amd->msg_count > 0) - { - if (amd->uidvalidity == 0) - { - amd->uidvalidity = (unsigned long)time (NULL); - /* Tell that we have been modified for expunging. */ - if (amd->msg_count) - { - amd_message_stream_open (amd->msg_array[0]); - amd_message_stream_close (amd->msg_array[0]); - amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; - } - } - } } /* Clean up the things */ diff --git a/mh/tests/folder.at b/mh/tests/folder.at index 8d89d9e48..6b616aaae 100644 --- a/mh/tests/folder.at +++ b/mh/tests/folder.at @@ -87,7 +87,7 @@ do mv Mail/inbox/$i Mail/inbox/${i}0 done folder -pack || exit $? -find Mail/inbox | sort +find Mail/inbox -not -name '.mu-prop' | sort ], [0], [Mail/inbox @@ -105,7 +105,7 @@ do mv Mail/inbox/$i Mail/inbox/${i}0 done folder --pack=1 || exit $? -find Mail/inbox | sort +find Mail/inbox -not -name '.mu-prop' | sort ], [0], [Mail/inbox |