Commit 5b3ac30a 5b3ac30a697287b6b72e3d7f717e19a159cae821 by Sergey Poznyakoff

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.
1 parent 47b3b9bc
...@@ -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! */
......