Bugfixes in AMD code.
* libproto/include/amd.h (new_msg_file_name): Add an argument indicating whether an actual expunsion is going to take place, as opposed to saving message flags. * libproto/maildir/mbox.c (maildir_new_message_name): Sync with above changes. * libproto/mh/mbox.c (_mh_new_message_name): Likewise. * mailbox/amd.c (_amd_message_save): Handle unlink requests (new_msg_file_name returning NULL name). This avoids creating temp files. (amd_expunge): Remove messages that have had MU_ATTRIBUTE_DELETED on mailbox open, if the underlying mailbox implementation allows that.
Showing
4 changed files
with
87 additions
and
63 deletions
... | @@ -72,7 +72,7 @@ struct _amd_data | ... | @@ -72,7 +72,7 @@ struct _amd_data |
72 | const mu_message_t); | 72 | const mu_message_t); |
73 | void (*msg_free) (struct _amd_message *); | 73 | void (*msg_free) (struct _amd_message *); |
74 | int (*cur_msg_file_name) (struct _amd_message *, char **); | 74 | int (*cur_msg_file_name) (struct _amd_message *, char **); |
75 | int (*new_msg_file_name) (struct _amd_message *, int attr_flags, char **); | 75 | int (*new_msg_file_name) (struct _amd_message *, int, int, char **); |
76 | int (*scan0) (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, | 76 | int (*scan0) (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, |
77 | int do_notify); | 77 | int do_notify); |
78 | int (*mailbox_size) (mu_mailbox_t mailbox, mu_off_t *psize); | 78 | int (*mailbox_size) (mu_mailbox_t mailbox, mu_off_t *psize); | ... | ... |
... | @@ -342,14 +342,13 @@ maildir_cur_message_name (struct _amd_message *amsg, char **pname) | ... | @@ -342,14 +342,13 @@ maildir_cur_message_name (struct _amd_message *amsg, char **pname) |
342 | } | 342 | } |
343 | 343 | ||
344 | static int | 344 | static int |
345 | maildir_new_message_name (struct _amd_message *amsg, int flags, char **pname) | 345 | maildir_new_message_name (struct _amd_message *amsg, int flags, int expunge, |
346 | char **pname) | ||
346 | { | 347 | { |
347 | struct _maildir_message *msg = (struct _maildir_message *) amsg; | 348 | struct _maildir_message *msg = (struct _maildir_message *) amsg; |
348 | if (flags & MU_ATTRIBUTE_DELETED) | 349 | if (expunge && (flags & MU_ATTRIBUTE_DELETED)) |
349 | { | 350 | { |
350 | /* Force amd.c to unlink the file. | 351 | /* Force amd.c to unlink the file. */ |
351 | FIXME: We could also add a 'T' info to it. Should | ||
352 | we have an option deciding which approach to take? */ | ||
353 | *pname = NULL; | 352 | *pname = NULL; |
354 | } | 353 | } |
355 | else if (strcmp (msg->dir, CURSUF) == 0) | 354 | else if (strcmp (msg->dir, CURSUF) == 0) | ... | ... |
... | @@ -126,7 +126,9 @@ _mh_cur_message_name (struct _amd_message *amsg, char **pname) | ... | @@ -126,7 +126,9 @@ _mh_cur_message_name (struct _amd_message *amsg, char **pname) |
126 | /* Return newfilename for the message. | 126 | /* Return newfilename for the message. |
127 | NOTE: Allocates memory. */ | 127 | NOTE: Allocates memory. */ |
128 | static int | 128 | static int |
129 | _mh_new_message_name (struct _amd_message *amsg, int flags, char **pname) | 129 | _mh_new_message_name (struct _amd_message *amsg, int flags, |
130 | int expunge MU_ARG_UNUSED, | ||
131 | char **pname) | ||
130 | { | 132 | { |
131 | int status = 0; | 133 | int status = 0; |
132 | struct _mh_message *mhm = (struct _mh_message *) amsg; | 134 | struct _mh_message *mhm = (struct _mh_message *) amsg; | ... | ... |
... | @@ -600,7 +600,7 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, | ... | @@ -600,7 +600,7 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, |
600 | int expunge) | 600 | int expunge) |
601 | { | 601 | { |
602 | mu_stream_t stream = NULL; | 602 | mu_stream_t stream = NULL; |
603 | char *name = NULL, *buf = NULL, *msg_name; | 603 | char *name = NULL, *buf = NULL, *msg_name, *old_name; |
604 | size_t n, off = 0; | 604 | size_t n, off = 0; |
605 | size_t bsize; | 605 | size_t bsize; |
606 | size_t nlines, nbytes; | 606 | size_t nlines, nbytes; |
... | @@ -618,9 +618,27 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, | ... | @@ -618,9 +618,27 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, |
618 | if (status) | 618 | if (status) |
619 | return status; | 619 | return status; |
620 | 620 | ||
621 | status = amd->new_msg_file_name (mhm, mhm->attr_flags, expunge, &msg_name); | ||
622 | if (status) | ||
623 | return status; | ||
624 | if (!msg_name) | ||
625 | { | ||
626 | /* Unlink the original file */ | ||
627 | char *old_name; | ||
628 | status = amd->cur_msg_file_name (mhm, &old_name); | ||
629 | free (msg_name); | ||
630 | if (status == 0 && unlink (old_name)) | ||
631 | status = errno; | ||
632 | free (old_name); | ||
633 | return status; | ||
634 | } | ||
635 | |||
621 | fp = _amd_tempfile (mhm->amd, &name); | 636 | fp = _amd_tempfile (mhm->amd, &name); |
622 | if (!fp) | 637 | if (!fp) |
623 | return errno; | 638 | { |
639 | free (msg_name); | ||
640 | return errno; | ||
641 | } | ||
624 | 642 | ||
625 | /* Try to allocate large buffer */ | 643 | /* Try to allocate large buffer */ |
626 | for (; bsize > 1; bsize /= 2) | 644 | for (; bsize > 1; bsize /= 2) |
... | @@ -628,7 +646,12 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, | ... | @@ -628,7 +646,12 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, |
628 | break; | 646 | break; |
629 | 647 | ||
630 | if (!bsize) | 648 | if (!bsize) |
631 | return ENOMEM; | 649 | { |
650 | unlink (name); | ||
651 | free (name); | ||
652 | free (msg_name); | ||
653 | return ENOMEM; | ||
654 | } | ||
632 | 655 | ||
633 | /* Copy flags */ | 656 | /* Copy flags */ |
634 | mu_message_get_header (msg, &hdr); | 657 | mu_message_get_header (msg, &hdr); |
... | @@ -724,42 +747,37 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, | ... | @@ -724,42 +747,37 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, |
724 | free (buf); | 747 | free (buf); |
725 | fclose (fp); | 748 | fclose (fp); |
726 | 749 | ||
727 | status = amd->new_msg_file_name (mhm, mhm->attr_flags, &msg_name); | 750 | status = amd->cur_msg_file_name (mhm, &old_name); |
728 | if (status == 0) | 751 | if (status == 0) |
729 | { | 752 | { |
730 | char *old_name; | 753 | if (rename (name, msg_name)) |
731 | status = amd->cur_msg_file_name (mhm, &old_name); | 754 | status = errno; |
732 | if (status == 0) | 755 | else |
733 | { | 756 | { |
734 | if (rename (name, msg_name)) | 757 | mode_t perms; |
735 | status = errno; | ||
736 | else | ||
737 | { | ||
738 | mode_t perms; | ||
739 | 758 | ||
740 | perms = mu_stream_flags_to_mode (amd->mailbox->flags, 0); | 759 | perms = mu_stream_flags_to_mode (amd->mailbox->flags, 0); |
741 | if (perms != 0) | 760 | if (perms != 0) |
742 | { | 761 | { |
743 | /* It is documented that the mailbox permissions are | 762 | /* It is documented that the mailbox permissions are |
744 | affected by the current umask, so take it into account | 763 | affected by the current umask, so take it into account |
745 | here. | 764 | here. |
746 | FIXME: I'm still not sure we should honor umask, though. | 765 | FIXME: I'm still not sure we should honor umask, though. |
747 | --gray | 766 | --gray |
748 | */ | 767 | */ |
749 | mode_t mask = umask (0); | 768 | mode_t mask = umask (0); |
750 | chmod (msg_name, (0600 | perms) & ~mask); | 769 | chmod (msg_name, (0600 | perms) & ~mask); |
751 | umask (mask); | 770 | umask (mask); |
752 | } | ||
753 | if (strcmp (old_name, msg_name)) | ||
754 | /* Unlink original message */ | ||
755 | unlink (old_name); | ||
756 | } | 771 | } |
757 | free (old_name); | 772 | if (strcmp (old_name, msg_name)) |
758 | 773 | /* Unlink original message */ | |
759 | mhm->orig_flags = mhm->attr_flags; | 774 | unlink (old_name); |
760 | } | 775 | } |
761 | free (msg_name); | 776 | free (old_name); |
777 | |||
778 | mhm->orig_flags = mhm->attr_flags; | ||
762 | } | 779 | } |
780 | free (msg_name); | ||
763 | free (name); | 781 | free (name); |
764 | 782 | ||
765 | return status; | 783 | return status; |
... | @@ -1065,33 +1083,38 @@ amd_expunge (mu_mailbox_t mailbox) | ... | @@ -1065,33 +1083,38 @@ amd_expunge (mu_mailbox_t mailbox) |
1065 | 1083 | ||
1066 | if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) | 1084 | if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) |
1067 | { | 1085 | { |
1068 | if (!(mhm->orig_flags & MU_ATTRIBUTE_DELETED)) | 1086 | int rc; |
1087 | char *old_name; | ||
1088 | char *new_name; | ||
1089 | |||
1090 | rc = amd->cur_msg_file_name (mhm, &old_name); | ||
1091 | if (rc) | ||
1092 | return rc; | ||
1093 | rc = amd->new_msg_file_name (mhm, mhm->attr_flags, 1, | ||
1094 | &new_name); | ||
1095 | if (rc) | ||
1069 | { | 1096 | { |
1070 | int rc; | ||
1071 | char *old_name; | ||
1072 | char *new_name; | ||
1073 | |||
1074 | rc = amd->cur_msg_file_name (mhm, &old_name); | ||
1075 | if (rc) | ||
1076 | return rc; | ||
1077 | rc = amd->new_msg_file_name (mhm, mhm->attr_flags, &new_name); | ||
1078 | if (rc) | ||
1079 | { | ||
1080 | free (old_name); | ||
1081 | return rc; | ||
1082 | } | ||
1083 | |||
1084 | if (new_name) | ||
1085 | { | ||
1086 | /* Rename original message */ | ||
1087 | rename (old_name, new_name); | ||
1088 | free (new_name); | ||
1089 | } | ||
1090 | else | ||
1091 | /* Unlink original file */ | ||
1092 | unlink (old_name); | ||
1093 | free (old_name); | 1097 | free (old_name); |
1098 | return rc; | ||
1099 | } | ||
1100 | |||
1101 | if (new_name) | ||
1102 | { | ||
1103 | /* FIXME: It may be a good idea to have a capability flag | ||
1104 | in struct _amd_data indicating that no actual removal | ||
1105 | is needed (e.g. for traditional MH). It will allow to | ||
1106 | bypass lots of no-op code here. */ | ||
1107 | if (strcmp (old_name, new_name)) | ||
1108 | /* Rename original message */ | ||
1109 | rename (old_name, new_name); | ||
1094 | } | 1110 | } |
1111 | else | ||
1112 | /* Unlink original file */ | ||
1113 | unlink (old_name); | ||
1114 | |||
1115 | free (old_name); | ||
1116 | free (new_name); | ||
1117 | |||
1095 | _amd_message_delete (amd, mhm); | 1118 | _amd_message_delete (amd, mhm); |
1096 | updated = 1; | 1119 | updated = 1; |
1097 | /* Do not increase i! */ | 1120 | /* Do not increase i! */ | ... | ... |
-
Please register or sign in to post a comment