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.
Showing
10 changed files
with
83 additions
and
52 deletions
... | @@ -53,6 +53,11 @@ extern void mu_message_destroy (mu_message_t *, void *owner); | ... | @@ -53,6 +53,11 @@ extern void mu_message_destroy (mu_message_t *, void *owner); |
53 | extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); | 53 | extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); |
54 | 54 | ||
55 | extern void *mu_message_get_owner (mu_message_t); | 55 | extern void *mu_message_get_owner (mu_message_t); |
56 | |||
57 | #define MU_MSG_ATTRIBUTE_MODIFIED 0x01 | ||
58 | #define MU_MSG_HEADER_MODIFIED 0x02 | ||
59 | #define MU_MSG_BODY_MODIFIED 0x04 | ||
60 | |||
56 | extern int mu_message_is_modified (mu_message_t); | 61 | extern int mu_message_is_modified (mu_message_t); |
57 | extern int mu_message_clear_modified (mu_message_t); | 62 | extern int mu_message_clear_modified (mu_message_t); |
58 | extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); | 63 | extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); | ... | ... |
... | @@ -43,7 +43,13 @@ | ... | @@ -43,7 +43,13 @@ |
43 | mu_monitor_wrlock (mbox->monitor); \ | 43 | mu_monitor_wrlock (mbox->monitor); \ |
44 | } while (0); | 44 | } while (0); |
45 | 45 | ||
46 | # define MU_AMD_SIZE_FILE_NAME ".mu-size" | 46 | #define _MU_AMD_PROP_UIDVALIDITY "uid-validity" |
47 | #define _MU_AMD_PROP_NEXT_UID "next-uid" | ||
48 | #define _MU_AMD_PROP_SIZE "size" | ||
49 | |||
50 | #define _MU_AMD_PROP_FILE_NAME ".mu-prop" | ||
51 | /* Legacy (2.x) size file name */ | ||
52 | #define _MU_AMD_SIZE_FILE_NAME ".mu-size" | ||
47 | 53 | ||
48 | struct _amd_data; | 54 | struct _amd_data; |
49 | struct _amd_message | 55 | struct _amd_message |
... | @@ -64,6 +70,10 @@ struct _amd_message | ... | @@ -64,6 +70,10 @@ struct _amd_message |
64 | struct _amd_data *amd; /* Back pointer. */ | 70 | struct _amd_data *amd; /* Back pointer. */ |
65 | }; | 71 | }; |
66 | 72 | ||
73 | /* AMD capabilities */ | ||
74 | #define MU_AMD_STATUS 0x01 /* format keeps status flags */ | ||
75 | #define MU_AMD_IMAPBASE 0x02 /* format keeps IMAP base */ | ||
76 | |||
67 | struct _amd_data | 77 | struct _amd_data |
68 | { | 78 | { |
69 | size_t msg_size; /* Size of struct _amd_message */ | 79 | size_t msg_size; /* Size of struct _amd_message */ |
... | @@ -83,16 +93,19 @@ struct _amd_data | ... | @@ -83,16 +93,19 @@ struct _amd_data |
83 | size_t (*next_uid) (struct _amd_data *mhd); | 93 | size_t (*next_uid) (struct _amd_data *mhd); |
84 | int (*remove) (struct _amd_data *); | 94 | int (*remove) (struct _amd_data *); |
85 | int (*delete_msg) (struct _amd_data *, struct _amd_message *); | 95 | int (*delete_msg) (struct _amd_data *, struct _amd_message *); |
86 | 96 | int (*chattr_msg) (struct _amd_message *, int); | |
97 | |||
87 | /* List of messages: */ | 98 | /* List of messages: */ |
88 | size_t msg_count; /* number of messages in the list */ | 99 | size_t msg_count; /* number of messages in the list */ |
89 | size_t msg_max; /* maximum message buffer capacity */ | 100 | size_t msg_max; /* maximum message buffer capacity */ |
90 | struct _amd_message **msg_array; | 101 | struct _amd_message **msg_array; |
91 | 102 | ||
92 | unsigned long uidvalidity; | 103 | int capabilities; |
93 | int has_new_msg; /* New messages have been appended */ | 104 | int has_new_msg; /* New messages have been appended */ |
94 | char *name; /* Directory name */ | 105 | char *name; /* Directory name */ |
95 | 106 | ||
107 | mu_property_t prop; /* Properties: uidvalidity, nextuid, etc. */ | ||
108 | |||
96 | /* Pool of open message streams */ | 109 | /* Pool of open message streams */ |
97 | struct _amd_message *msg_pool[MAX_OPEN_STREAMS]; | 110 | struct _amd_message *msg_pool[MAX_OPEN_STREAMS]; |
98 | int pool_first; /* Index to the first used entry in msg_pool */ | 111 | int pool_first; /* Index to the first used entry in msg_pool */ | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -667,10 +667,14 @@ mu_message_is_modified (mu_message_t msg) | ... | @@ -667,10 +667,14 @@ mu_message_is_modified (mu_message_t msg) |
667 | int mod = 0; | 667 | int mod = 0; |
668 | if (msg) | 668 | if (msg) |
669 | { | 669 | { |
670 | mod |= mu_header_is_modified (msg->header); | 670 | if (mu_header_is_modified (msg->header)) |
671 | mod |= mu_attribute_is_modified (msg->attribute); | 671 | mod |= MU_MSG_HEADER_MODIFIED; |
672 | mod |= mu_body_is_modified (msg->body); | 672 | if (mu_attribute_is_modified (msg->attribute)) |
673 | mod |= msg->flags; | 673 | mod |= MU_MSG_ATTRIBUTE_MODIFIED; |
674 | if (mu_body_is_modified (msg->body)) | ||
675 | mod |= MU_MSG_BODY_MODIFIED; | ||
676 | if (msg->flags & MESSAGE_MODIFIED) | ||
677 | mod |= MU_MSG_BODY_MODIFIED | MU_MSG_HEADER_MODIFIED; | ||
674 | } | 678 | } |
675 | return mod; | 679 | return mod; |
676 | } | 680 | } | ... | ... |
... | @@ -45,7 +45,7 @@ mu_property_create_init (mu_property_t *pprop, | ... | @@ -45,7 +45,7 @@ mu_property_create_init (mu_property_t *pprop, |
45 | mu_property_set_init (prop, initfun, initdata); | 45 | mu_property_set_init (prop, initfun, initdata); |
46 | *pprop = prop; | 46 | *pprop = prop; |
47 | } | 47 | } |
48 | return 0; | 48 | return rc; |
49 | } | 49 | } |
50 | 50 | ||
51 | int | 51 | int | ... | ... |
... | @@ -92,7 +92,8 @@ _maildir_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) | ... | @@ -92,7 +92,8 @@ _maildir_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) |
92 | return strcmp (name, TMPSUF) | 92 | return strcmp (name, TMPSUF) |
93 | && strcmp (name, CURSUF) | 93 | && strcmp (name, CURSUF) |
94 | && strcmp (name, NEWSUF) | 94 | && strcmp (name, NEWSUF) |
95 | && strcmp (name, MU_AMD_SIZE_FILE_NAME); | 95 | && !((strlen (name) > 3) && |
96 | (memcmp (name, ".mh", 3) == 0 || memcmp (name, ".mu", 3) == 0)); | ||
96 | } | 97 | } |
97 | 98 | ||
98 | static struct _mu_record _maildir_record = | 99 | static struct _mu_record _maildir_record = | ... | ... |
... | @@ -84,19 +84,24 @@ struct _maildir_message | ... | @@ -84,19 +84,24 @@ struct _maildir_message |
84 | 84 | ||
85 | 85 | ||
86 | /* Attribute handling. | 86 | /* Attribute handling. |
87 | FIXME: P (Passed), D (Draft) and F (Flagged) are not handled */ | 87 | FIXME: P (Passed) is not handled */ |
88 | 88 | ||
89 | static struct info_map { | 89 | static struct info_map { |
90 | char letter; | 90 | char letter; |
91 | int flag; | 91 | int flag; |
92 | } info_map[] = { | 92 | } info_map[] = { |
93 | { 'D', MU_ATTRIBUTE_DRAFT }, | ||
94 | { 'F', MU_ATTRIBUTE_FLAGGED }, | ||
95 | { 'P', 0 }, /* (passed): the user has resent/forwarded/bounced this | ||
96 | message to someone else. */ | ||
93 | { 'R', MU_ATTRIBUTE_READ }, | 97 | { 'R', MU_ATTRIBUTE_READ }, |
94 | { 'S', MU_ATTRIBUTE_SEEN }, | 98 | { 'S', MU_ATTRIBUTE_SEEN }, |
95 | { 'T', MU_ATTRIBUTE_DELETED }, | 99 | { 'T', MU_ATTRIBUTE_DELETED }, |
100 | { 'a', MU_ATTRIBUTE_ANSWERED }, | ||
96 | }; | 101 | }; |
97 | #define info_map_size (sizeof (info_map) / sizeof (info_map[0])) | 102 | #define info_map_size (sizeof (info_map) / sizeof (info_map[0])) |
98 | 103 | ||
99 | /* NOTE: BUF must be at least 7 bytes long */ | 104 | /* NOTE: BUF must be at least info_map_size bytes long */ |
100 | static int | 105 | static int |
101 | flags_to_info (int flags, char *buf) | 106 | flags_to_info (int flags, char *buf) |
102 | { | 107 | { |
... | @@ -254,7 +259,7 @@ maildir_mkfilename (const char *directory, const char *suffix, const char *name) | ... | @@ -254,7 +259,7 @@ maildir_mkfilename (const char *directory, const char *suffix, const char *name) |
254 | static char * | 259 | static char * |
255 | mk_info_filename (char *directory, char *suffix, char *name, int flags) | 260 | mk_info_filename (char *directory, char *suffix, char *name, int flags) |
256 | { | 261 | { |
257 | char fbuf[9]; | 262 | char fbuf[info_map_size + 1]; |
258 | char *tmp; | 263 | char *tmp; |
259 | int namelen; | 264 | int namelen; |
260 | size_t size; | 265 | size_t size; |
... | @@ -691,23 +696,6 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -691,23 +696,6 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
691 | if (pcount) | 696 | if (pcount) |
692 | *pcount = amd->msg_count; | 697 | *pcount = amd->msg_count; |
693 | 698 | ||
694 | /* Reset the uidvalidity. */ | ||
695 | if (amd->msg_count > 0) | ||
696 | { | ||
697 | if (amd->uidvalidity == 0) | ||
698 | { | ||
699 | amd->uidvalidity = (unsigned long) time (NULL); | ||
700 | /* FIXME amd->uidnext = amd->msg_count + 1;*/ | ||
701 | /* Tell that we have been modified for expunging. */ | ||
702 | if (amd->msg_count) | ||
703 | { | ||
704 | amd_message_stream_open (amd->msg_array[0]); | ||
705 | amd_message_stream_close (amd->msg_array[0]); | ||
706 | amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; | ||
707 | } | ||
708 | } | ||
709 | } | ||
710 | |||
711 | /* Clean up the things */ | 699 | /* Clean up the things */ |
712 | amd_cleanup (mailbox); | 700 | amd_cleanup (mailbox); |
713 | return status; | 701 | return status; |
... | @@ -773,6 +761,42 @@ maildir_remove (struct _amd_data *amd) | ... | @@ -773,6 +761,42 @@ maildir_remove (struct _amd_data *amd) |
773 | return rc; | 761 | return rc; |
774 | } | 762 | } |
775 | 763 | ||
764 | |||
765 | static int | ||
766 | maildir_chattr_msg (struct _amd_message *amsg, int expunge) | ||
767 | { | ||
768 | struct _maildir_message *mp = (struct _maildir_message *) amsg; | ||
769 | struct _amd_data *amd = amsg->amd; | ||
770 | int rc; | ||
771 | char *new_name; | ||
772 | |||
773 | rc = amd->new_msg_file_name (amsg, amsg->attr_flags, expunge, &new_name); | ||
774 | if (rc) | ||
775 | return rc; | ||
776 | if (!new_name) | ||
777 | { | ||
778 | if (unlink (mp->file_name)) | ||
779 | rc = errno; | ||
780 | } | ||
781 | else | ||
782 | { | ||
783 | char *cur_name; | ||
784 | |||
785 | rc = maildir_cur_message_name (amsg, &cur_name); | ||
786 | if (rc) | ||
787 | { | ||
788 | free (new_name); | ||
789 | return rc; | ||
790 | } | ||
791 | if (rename (cur_name, new_name)) | ||
792 | rc = errno; | ||
793 | free (cur_name); | ||
794 | } | ||
795 | |||
796 | free (new_name); | ||
797 | return rc; | ||
798 | } | ||
799 | |||
776 | 800 | ||
777 | int | 801 | int |
778 | _mailbox_maildir_init (mu_mailbox_t mailbox) | 802 | _mailbox_maildir_init (mu_mailbox_t mailbox) |
... | @@ -797,6 +821,8 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) | ... | @@ -797,6 +821,8 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) |
797 | amd->message_uid = maildir_message_uid; | 821 | amd->message_uid = maildir_message_uid; |
798 | amd->next_uid = maildir_next_uid; | 822 | amd->next_uid = maildir_next_uid; |
799 | amd->remove = maildir_remove; | 823 | amd->remove = maildir_remove; |
824 | amd->chattr_msg = maildir_chattr_msg; | ||
825 | amd->capabilities = MU_AMD_STATUS; | ||
800 | 826 | ||
801 | /* Set our properties. */ | 827 | /* Set our properties. */ |
802 | { | 828 | { | ... | ... |
... | @@ -121,11 +121,9 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) | ... | @@ -121,11 +121,9 @@ _mh_is_scheme (mu_record_t record, mu_url_t url, int flags) |
121 | static int | 121 | static int |
122 | _mh_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) | 122 | _mh_list_p (mu_record_t record, const char *name, int flags MU_ARG_UNUSED) |
123 | { | 123 | { |
124 | int len; | 124 | if (name[0] == ',' || |
125 | 125 | ((strlen (name) > 3) && | |
126 | if (strcmp (name, MU_AMD_SIZE_FILE_NAME) == 0 | 126 | (memcmp (name, ".mh", 3) == 0 || memcmp (name, ".mu", 3) == 0))) |
127 | || name[0] == ',' | ||
128 | || (((len = strlen (name)) > 3) && memcmp (name, ".mh", 3) == 0)) | ||
129 | return 0; | 127 | return 0; |
130 | 128 | ||
131 | for (; *name; name++) | 129 | for (; *name; name++) | ... | ... |
... | @@ -278,22 +278,6 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, | ... | @@ -278,22 +278,6 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, |
278 | 278 | ||
279 | if (pcount) | 279 | if (pcount) |
280 | *pcount = amd->msg_count; | 280 | *pcount = amd->msg_count; |
281 | |||
282 | /* Reset the uidvalidity. */ | ||
283 | if (amd->msg_count > 0) | ||
284 | { | ||
285 | if (amd->uidvalidity == 0) | ||
286 | { | ||
287 | amd->uidvalidity = (unsigned long)time (NULL); | ||
288 | /* Tell that we have been modified for expunging. */ | ||
289 | if (amd->msg_count) | ||
290 | { | ||
291 | amd_message_stream_open (amd->msg_array[0]); | ||
292 | amd_message_stream_close (amd->msg_array[0]); | ||
293 | amd->msg_array[0]->attr_flags |= MU_ATTRIBUTE_MODIFIED; | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | } | 281 | } |
298 | /* Clean up the things */ | 282 | /* Clean up the things */ |
299 | 283 | ... | ... |
... | @@ -87,7 +87,7 @@ do | ... | @@ -87,7 +87,7 @@ do |
87 | mv Mail/inbox/$i Mail/inbox/${i}0 | 87 | mv Mail/inbox/$i Mail/inbox/${i}0 |
88 | done | 88 | done |
89 | folder -pack || exit $? | 89 | folder -pack || exit $? |
90 | find Mail/inbox | sort | 90 | find Mail/inbox -not -name '.mu-prop' | sort |
91 | ], | 91 | ], |
92 | [0], | 92 | [0], |
93 | [Mail/inbox | 93 | [Mail/inbox |
... | @@ -105,7 +105,7 @@ do | ... | @@ -105,7 +105,7 @@ do |
105 | mv Mail/inbox/$i Mail/inbox/${i}0 | 105 | mv Mail/inbox/$i Mail/inbox/${i}0 |
106 | done | 106 | done |
107 | folder --pack=1 || exit $? | 107 | folder --pack=1 || exit $? |
108 | find Mail/inbox | sort | 108 | find Mail/inbox -not -name '.mu-prop' | sort |
109 | ], | 109 | ], |
110 | [0], | 110 | [0], |
111 | [Mail/inbox | 111 | [Mail/inbox | ... | ... |
-
Please register or sign in to post a comment