Commit 8611b6e6 8611b6e6b983579fd8955f5878f53d463acce42a by Sergey Poznyakoff

Fix message delivery to maildir boxes.

* libproto/include/amd.h (struct _amd_message): Remove `deleted',
add `orig_flags' instead.
(struct _amd_data): Remove `msg_file_name', add `cur_msg_file_name'
and `new_msg_file_name'.
Add `mailbox_size'.
* libproto/maildir/mbox.c (struct _maildir_message): Remove
`newflag', add `dir'.
(maildir_name_info_ptr): New function.
(mk_info_filename): Bugfix.
(maildir_cur_message_name, maildir_new_message_name): New
functions.
(maildir_msg_init): Set ->dir
(maildir_msg_finish_delivery): Handle error conditions.
(maildir_scan_dir): New argument `dirname'. Initialize orig_flags.
(maildir_qfetch): Initialize dir.
(_mailbox_maildir_init): Set cur_msg_file_name and
new_msg_file_name.
* libproto/mh/mbox.c (_mh_cur_message_name)
(_mh_new_message_name): New functions.
(mh_scan0): Initialize orig_flags.
(_mailbox_mh_init): Set cur_msg_file_name and
new_msg_file_name.
* mailbox/amd.c (amd_message_qid, _amd_message_save)
(amd_append_message, amd_expunge, amd_scan_message)
(amd_pool_open, amd_header_fill): Use appropriate msg_file_name
functions.
(amd_get_size): Implemented.
* mailbox/mailbox.c (mu_mailbox_flush): Bugfix.
1 parent 5d286f5d
1 2008-01-06 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 Fix message delivery to maildir boxes.
4
5 * libproto/include/amd.h (struct _amd_message): Remove `deleted',
6 add `orig_flags' instead.
7 (struct _amd_data): Remove `msg_file_name', add `cur_msg_file_name'
8 and `new_msg_file_name'.
9 Add `mailbox_size'.
10 * libproto/maildir/mbox.c (struct _maildir_message): Remove
11 `newflag', add `dir'.
12 (maildir_name_info_ptr): New function.
13 (mk_info_filename): Bugfix.
14 (maildir_cur_message_name, maildir_new_message_name): New
15 functions.
16 (maildir_msg_init): Set ->dir
17 (maildir_msg_finish_delivery): Handle error conditions.
18 (maildir_scan_dir): New argument `dirname'. Initialize orig_flags.
19 (maildir_qfetch): Initialize dir.
20 (_mailbox_maildir_init): Set cur_msg_file_name and
21 new_msg_file_name.
22 * libproto/mh/mbox.c (_mh_cur_message_name)
23 (_mh_new_message_name): New functions.
24 (mh_scan0): Initialize orig_flags.
25 (_mailbox_mh_init): Set cur_msg_file_name and
26 new_msg_file_name.
27 * mailbox/amd.c (amd_message_qid, _amd_message_save)
28 (amd_append_message, amd_expunge, amd_scan_message)
29 (amd_pool_open, amd_header_fill): Use appropriate msg_file_name
30 functions.
31 (amd_get_size): Implemented.
32 * mailbox/mailbox.c (mu_mailbox_flush): Bugfix.
33
1 2008-01-05 Sergey Poznyakoff <gray@gnu.org.ua> 34 2008-01-05 Sergey Poznyakoff <gray@gnu.org.ua>
2 35
3 * NEWS: Update. 36 * NEWS: Update.
......
...@@ -48,8 +48,9 @@ struct _amd_message ...@@ -48,8 +48,9 @@ struct _amd_message
48 mu_off_t body_start; /* Offset of body start in the message file */ 48 mu_off_t body_start; /* Offset of body start in the message file */
49 mu_off_t body_end; /* Offset of body end (size of file, effectively)*/ 49 mu_off_t body_end; /* Offset of body end (size of file, effectively)*/
50 50
51 int attr_flags; /* Attribute flags */ 51 int orig_flags; /* Original attribute flags */
52 int deleted; /* Was the message originally deleted */ 52 int attr_flags; /* Current attribute flags */
53
53 54
54 time_t mtime; /* Time of last modification */ 55 time_t mtime; /* Time of last modification */
55 size_t header_lines; /* Number of lines in the header part */ 56 size_t header_lines; /* Number of lines in the header part */
...@@ -65,9 +66,11 @@ struct _amd_data ...@@ -65,9 +66,11 @@ struct _amd_data
65 int (*msg_init_delivery) (struct _amd_data *, struct _amd_message *); 66 int (*msg_init_delivery) (struct _amd_data *, struct _amd_message *);
66 int (*msg_finish_delivery) (struct _amd_data *, struct _amd_message *); 67 int (*msg_finish_delivery) (struct _amd_data *, struct _amd_message *);
67 void (*msg_free) (struct _amd_message *); 68 void (*msg_free) (struct _amd_message *);
68 char *(*msg_file_name) (struct _amd_message *, int deleted); 69 int (*cur_msg_file_name) (struct _amd_message *, char **);
70 int (*new_msg_file_name) (struct _amd_message *, int attr_flags, char **);
69 int (*scan0) (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, 71 int (*scan0) (mu_mailbox_t mailbox, size_t msgno, size_t *pcount,
70 int do_notify); 72 int do_notify);
73 int (*mailbox_size) (mu_mailbox_t mailbox, mu_off_t *psize);
71 int (*qfetch) (struct _amd_data *, mu_message_qid_t qid); 74 int (*qfetch) (struct _amd_data *, mu_message_qid_t qid);
72 int (*msg_cmp) (struct _amd_message *, struct _amd_message *); 75 int (*msg_cmp) (struct _amd_message *, struct _amd_message *);
73 int (*message_uid) (mu_message_t msg, size_t *puid); 76 int (*message_uid) (mu_message_t msg, size_t *puid);
......
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
78 struct _maildir_message 78 struct _maildir_message
79 { 79 {
80 struct _amd_message amd_message; 80 struct _amd_message amd_message;
81 int newflag; 81 char *dir;
82 char *file_name; 82 char *file_name;
83 unsigned long uid; 83 unsigned long uid;
84 }; 84 };
...@@ -123,6 +123,15 @@ info_to_flags (char *buf) ...@@ -123,6 +123,15 @@ info_to_flags (char *buf)
123 return 0; 123 return 0;
124 } 124 }
125 125
126 static char *
127 maildir_name_info_ptr (char *name)
128 {
129 char *p = strchr (name, ':');
130 if (p && memcmp (p + 1, "2,", 2) == 0)
131 return p + 3;
132 return NULL;
133 }
134
126 135
127 static int 136 static int
128 maildir_message_cmp (struct _amd_message *a, struct _amd_message *b) 137 maildir_message_cmp (struct _amd_message *a, struct _amd_message *b)
...@@ -269,7 +278,7 @@ mk_info_filename (char *directory, char *suffix, char *name, int flags) ...@@ -269,7 +278,7 @@ mk_info_filename (char *directory, char *suffix, char *name, int flags)
269 size += 3 + strlen (fbuf); 278 size += 3 + strlen (fbuf);
270 279
271 tmp = malloc (size); 280 tmp = malloc (size);
272 if (fbuf[0]) 281 if (!fbuf[0])
273 sprintf (tmp, "%s/%s/%*.*s:2", directory, suffix, namelen, namelen, name); 282 sprintf (tmp, "%s/%s/%*.*s:2", directory, suffix, namelen, namelen, name);
274 else 283 else
275 sprintf (tmp, "%s/%s/%*.*s:2,%s", directory, suffix, namelen, namelen, name, fbuf); 284 sprintf (tmp, "%s/%s/%*.*s:2,%s", directory, suffix, namelen, namelen, name, fbuf);
...@@ -324,16 +333,31 @@ maildir_uniq (struct _amd_data *amd, int fd) ...@@ -324,16 +333,31 @@ maildir_uniq (struct _amd_data *amd, int fd)
324 return strdup (buffer); 333 return strdup (buffer);
325 } 334 }
326 335
327 char * 336 /* FIXME: The following two functions dump core on ENOMEM */
328 maildir_message_name (struct _amd_message *amsg, int deleted) 337 static int
338 maildir_cur_message_name (struct _amd_message *amsg, char **pname)
329 { 339 {
330 struct _maildir_message *msg = (struct _maildir_message *) amsg; 340 struct _maildir_message *msg = (struct _maildir_message *) amsg;
331 if (deleted) 341 *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name);
332 return NULL; /* Force amd.c to unlink the file. 342 return 0;
333 FIXME: We could also add a 'T' info to it. Should 343 }
334 we have an option deciding which approach to take? */ 344
335 return maildir_mkfilename (amsg->amd->name, 345 static int
336 msg->newflag ? NEWSUF : CURSUF, msg->file_name); 346 maildir_new_message_name (struct _amd_message *amsg, int flags, char **pname)
347 {
348 struct _maildir_message *msg = (struct _maildir_message *) amsg;
349 if (flags & MU_ATTRIBUTE_DELETED)
350 {
351 /* Force amd.c to unlink the file.
352 FIXME: We could also add a 'T' info to it. Should
353 we have an option deciding which approach to take? */
354 *pname = NULL;
355 }
356 else if (strcmp (msg->dir, CURSUF) == 0)
357 *pname = mk_info_filename (amsg->amd->name, CURSUF, msg->file_name, flags);
358 else
359 *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name);
360 return 0;
337 } 361 }
338 362
339 static void 363 static void
...@@ -415,6 +439,8 @@ maildir_msg_init (struct _amd_data *amd, struct _amd_message *amm) ...@@ -415,6 +439,8 @@ maildir_msg_init (struct _amd_data *amd, struct _amd_message *amm)
415 439
416 name = maildir_uniq (amd, -1); 440 name = maildir_uniq (amd, -1);
417 fname = maildir_mkfilename (amd->name, NEWSUF, name); 441 fname = maildir_mkfilename (amd->name, NEWSUF, name);
442
443 msg->dir = TMPSUF;
418 444
419 for (i = 0; i < NTRIES; i++) 445 for (i = 0; i < NTRIES; i++)
420 { 446 {
...@@ -442,11 +468,13 @@ maildir_msg_finish_delivery (struct _amd_data *amd, struct _amd_message *amm) ...@@ -442,11 +468,13 @@ maildir_msg_finish_delivery (struct _amd_data *amd, struct _amd_message *amm)
442 char *newname = maildir_mkfilename (amd->name, NEWSUF, msg->file_name); 468 char *newname = maildir_mkfilename (amd->name, NEWSUF, msg->file_name);
443 469
444 unlink (newname); 470 unlink (newname);
445 if (link (oldname, newname)) 471 if (link (oldname, newname) == 0)
472 unlink (oldname);
473 else
446 { 474 {
447 unlink (oldname); 475 return errno; /* FIXME? */
448 msg->newflag = 1;
449 } 476 }
477 msg->dir = NEWSUF;
450 free (oldname); 478 free (oldname);
451 free (newname); 479 free (newname);
452 return 0; 480 return 0;
...@@ -535,16 +563,15 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name) ...@@ -535,16 +563,15 @@ maildir_message_lookup (struct _amd_data *amd, char *file_name)
535 } 563 }
536 564
537 static int 565 static int
538 maildir_scan_dir (struct _amd_data *amd, DIR *dir) 566 maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname)
539 { 567 {
540 struct _maildir_message *msg;
541 struct dirent *entry; 568 struct dirent *entry;
569 struct _maildir_message *msg;
570 char *p;
571 int insert;
542 572
543 while ((entry = readdir (dir))) 573 while ((entry = readdir (dir)))
544 { 574 {
545 char *p;
546 int insert;
547
548 switch (entry->d_name[0]) 575 switch (entry->d_name[0])
549 { 576 {
550 case '.': 577 case '.':
...@@ -555,7 +582,6 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir) ...@@ -555,7 +582,6 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir)
555 if (msg) 582 if (msg)
556 { 583 {
557 free (msg->file_name); 584 free (msg->file_name);
558 msg->newflag = 0;
559 insert = 0; 585 insert = 0;
560 } 586 }
561 else 587 else
...@@ -564,14 +590,15 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir) ...@@ -564,14 +590,15 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir)
564 insert = 1; 590 insert = 1;
565 } 591 }
566 592
593 msg->dir = dirname;
567 msg->file_name = strdup (entry->d_name); 594 msg->file_name = strdup (entry->d_name);
568 595
569 p = strchr (msg->file_name, ':'); 596 p = maildir_name_info_ptr (msg->file_name);
570 if (p && strcmp (p+1, "2,") == 0) 597 if (p)
571 msg->amd_message.attr_flags = info_to_flags (p+3); 598 msg->amd_message.attr_flags = info_to_flags (p);
572 else 599 else
573 msg->amd_message.attr_flags = 0; 600 msg->amd_message.attr_flags = 0;
574 msg->amd_message.deleted = msg->amd_message.attr_flags & MU_ATTRIBUTE_DELETED; 601 msg->amd_message.orig_flags = msg->amd_message.attr_flags;
575 if (insert) 602 if (insert)
576 { 603 {
577 msg->uid = amd->next_uid (amd); 604 msg->uid = amd->next_uid (amd);
...@@ -595,7 +622,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, ...@@ -595,7 +622,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
595 622
596 if (amd == NULL) 623 if (amd == NULL)
597 return EINVAL; 624 return EINVAL;
598 625 if (mailbox->flags & MU_STREAM_APPEND)
626 return 0;
599 mu_monitor_wrlock (mailbox->monitor); 627 mu_monitor_wrlock (mailbox->monitor);
600 628
601 /* 1st phase: Flush tmp/ */ 629 /* 1st phase: Flush tmp/ */
...@@ -617,7 +645,7 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, ...@@ -617,7 +645,7 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
617 status = maildir_opendir (&dir, name, PERMS); 645 status = maildir_opendir (&dir, name, PERMS);
618 if (status == 0) 646 if (status == 0)
619 { 647 {
620 status = maildir_scan_dir (amd, dir); 648 status = maildir_scan_dir (amd, dir, CURSUF);
621 closedir (dir); 649 closedir (dir);
622 } 650 }
623 free (name); 651 free (name);
...@@ -666,19 +694,32 @@ maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid) ...@@ -666,19 +694,32 @@ maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid)
666 struct _maildir_message *msg; 694 struct _maildir_message *msg;
667 char *name = strrchr (qid, '/'); 695 char *name = strrchr (qid, '/');
668 char *p; 696 char *p;
697 char *dir;
669 698
670 if (!name) 699 if (!name)
671 return EINVAL; 700 return EINVAL;
672 name++; 701 name++;
702 if (name - qid < 4)
703 return EINVAL;
704 else if (memcmp (name - 4, CURSUF, sizeof (CURSUF) - 1) == 0)
705 dir = CURSUF;
706 else if (memcmp (name - 4, NEWSUF, sizeof (NEWSUF) - 1) == 0)
707 dir = NEWSUF;
708 else if (memcmp (name - 4, TMPSUF, sizeof (TMPSUF) - 1) == 0)
709 dir = TMPSUF;
710 else
711 return EINVAL;
712
673 msg = calloc (1, sizeof(*msg)); 713 msg = calloc (1, sizeof(*msg));
674 msg->file_name = strdup (name); 714 msg->file_name = strdup (name);
675 715 msg->dir = dir;
676 p = strchr (msg->file_name, ':'); 716
677 if (p && strcmp (p + 1, "2,") == 0) 717 p = maildir_name_info_ptr (msg->file_name);
678 msg->amd_message.attr_flags = info_to_flags (p + 3); 718 if (p)
719 msg->amd_message.attr_flags = info_to_flags (p);
679 else 720 else
680 msg->amd_message.attr_flags = 0; 721 msg->amd_message.attr_flags = 0;
681 msg->amd_message.deleted = msg->amd_message.attr_flags & MU_ATTRIBUTE_DELETED; 722 msg->amd_message.orig_flags = msg->amd_message.attr_flags;
682 msg->uid = amd->next_uid (amd); 723 msg->uid = amd->next_uid (amd);
683 _amd_message_insert (amd, (struct _amd_message*) msg); 724 _amd_message_insert (amd, (struct _amd_message*) msg);
684 return 0; 725 return 0;
...@@ -699,7 +740,8 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) ...@@ -699,7 +740,8 @@ _mailbox_maildir_init (mu_mailbox_t mailbox)
699 amd->msg_free = maildir_msg_free; 740 amd->msg_free = maildir_msg_free;
700 amd->msg_init_delivery = maildir_msg_init; 741 amd->msg_init_delivery = maildir_msg_init;
701 amd->msg_finish_delivery = maildir_msg_finish_delivery; 742 amd->msg_finish_delivery = maildir_msg_finish_delivery;
702 amd->msg_file_name = maildir_message_name; 743 amd->cur_msg_file_name = maildir_cur_message_name;
744 amd->new_msg_file_name = maildir_new_message_name;
703 amd->scan0 = maildir_scan0; 745 amd->scan0 = maildir_scan0;
704 amd->qfetch = maildir_qfetch; 746 amd->qfetch = maildir_qfetch;
705 amd->msg_cmp = maildir_message_cmp; 747 amd->msg_cmp = maildir_message_cmp;
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2 Copyright (C) 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2007 Free Software Foundation, Inc. 3 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
4 4
5 This library is free software; you can redistribute it and/or 5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public 6 modify it under the terms of the GNU Lesser General Public
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
66 #include <mailbox0.h> 66 #include <mailbox0.h>
67 #include <registrar0.h> 67 #include <registrar0.h>
68 #include <amd.h> 68 #include <amd.h>
69 #include <mu_umaxtostr.h>
69 70
70 struct _mh_message 71 struct _mh_message
71 { 72 {
...@@ -93,22 +94,55 @@ _mh_next_seq (struct _amd_data *amd) ...@@ -93,22 +94,55 @@ _mh_next_seq (struct _amd_data *amd)
93 return (msg ? msg->seq_number : 0) + 1; 94 return (msg ? msg->seq_number : 0) + 1;
94 } 95 }
95 96
96 /* Return filename for the message. 97 /* Return current filename for the message.
97 NOTE: Allocates memory. */ 98 NOTE: Allocates memory. */
98 static char * 99 static int
99 _mh_message_name (struct _amd_message *amsg, int deleted) 100 _mh_cur_message_name (struct _amd_message *amsg, char **pname)
101 {
102 int status = 0;
103 struct _mh_message *mhm = (struct _mh_message *) amsg;
104 char *filename;
105 char buf[UINTMAX_STRSIZE_BOUND];
106 char *pnum = umaxtostr (mhm->seq_number, buf);
107 size_t len = strlen (amsg->amd->name) + 1 + strlen (pnum) + 1;
108 filename = malloc (len);
109 if (filename)
110 {
111 strcpy (filename, amsg->amd->name);
112 strcat (filename, "/");
113 strcat (filename, pnum);
114 *pname = filename;
115 }
116 else
117 status = ENOMEM;
118 return status;
119 }
120
121 /* Return newfilename for the message.
122 NOTE: Allocates memory. */
123 static int
124 _mh_new_message_name (struct _amd_message *amsg, int flags, char **pname)
100 { 125 {
126 int status = 0;
101 struct _mh_message *mhm = (struct _mh_message *) amsg; 127 struct _mh_message *mhm = (struct _mh_message *) amsg;
102 char *filename; 128 char *filename;
103 size_t len = strlen (amsg->amd->name) + 32; 129 char buf[UINTMAX_STRSIZE_BOUND];
130 char *pnum = umaxtostr (mhm->seq_number, buf);
131 size_t len = strlen (amsg->amd->name) + 1 +
132 ((flags & MU_ATTRIBUTE_DELETED) ? 1 : 0) + strlen (pnum) + 1;
104 filename = malloc (len); 133 filename = malloc (len);
105 if (deleted) 134 if (filename)
106 snprintf (filename, len, "%s/,%lu", amsg->amd->name, 135 {
107 (unsigned long) mhm->seq_number); 136 strcpy (filename, amsg->amd->name);
137 strcat (filename, "/");
138 if (flags & MU_ATTRIBUTE_DELETED)
139 strcat (filename, ",");
140 strcat (filename, pnum);
141 *pname = filename;
142 }
108 else 143 else
109 snprintf (filename, len, "%s/%lu", amsg->amd->name, 144 status = ENOMEM;
110 (unsigned long) mhm->seq_number); 145 return status;
111 return filename;
112 } 146 }
113 147
114 /* Find the message with the given sequence number */ 148 /* Find the message with the given sequence number */
...@@ -193,13 +227,14 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, ...@@ -193,13 +227,14 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount,
193 227
194 msg->seq_number = num; 228 msg->seq_number = num;
195 msg->amd_message.attr_flags = attr_flags; 229 msg->amd_message.attr_flags = attr_flags;
196 msg->amd_message.deleted = attr_flags & MU_ATTRIBUTE_DELETED; 230 msg->amd_message.orig_flags = msg->amd_message.attr_flags;
197 231
198 _amd_message_insert (amd, (struct _amd_message*) msg); 232 _amd_message_insert (amd, (struct _amd_message*) msg);
199 } 233 }
200 else 234 else
201 { 235 {
202 msg->amd_message.attr_flags = attr_flags; 236 msg->amd_message.attr_flags = attr_flags;
237 msg->amd_message.orig_flags = msg->amd_message.attr_flags;
203 } 238 }
204 } 239 }
205 240
...@@ -278,7 +313,7 @@ mh_qfetch (struct _amd_data *amd, mu_message_qid_t qid) ...@@ -278,7 +313,7 @@ mh_qfetch (struct _amd_data *amd, mu_message_qid_t qid)
278 msg = calloc (1, sizeof (*msg)); 313 msg = calloc (1, sizeof (*msg));
279 msg->seq_number = num; 314 msg->seq_number = num;
280 msg->amd_message.attr_flags = attr_flags; 315 msg->amd_message.attr_flags = attr_flags;
281 msg->amd_message.deleted = attr_flags & MU_ATTRIBUTE_DELETED; 316 msg->amd_message.orig_flags = msg->amd_message.attr_flags;
282 _amd_message_insert (amd, (struct _amd_message*) msg); 317 _amd_message_insert (amd, (struct _amd_message*) msg);
283 return 0; 318 return 0;
284 } 319 }
...@@ -321,7 +356,8 @@ _mailbox_mh_init (mu_mailbox_t mailbox) ...@@ -321,7 +356,8 @@ _mailbox_mh_init (mu_mailbox_t mailbox)
321 amd->msg_free = NULL; 356 amd->msg_free = NULL;
322 amd->msg_init_delivery = _mh_msg_init; 357 amd->msg_init_delivery = _mh_msg_init;
323 amd->msg_finish_delivery = NULL; 358 amd->msg_finish_delivery = NULL;
324 amd->msg_file_name = _mh_message_name; 359 amd->cur_msg_file_name = _mh_cur_message_name;
360 amd->new_msg_file_name = _mh_new_message_name;
325 amd->scan0 = mh_scan0; 361 amd->scan0 = mh_scan0;
326 amd->qfetch = mh_qfetch; 362 amd->qfetch = mh_qfetch;
327 amd->msg_cmp = mh_message_cmp; 363 amd->msg_cmp = mh_message_cmp;
......
...@@ -389,9 +389,7 @@ amd_message_qid (mu_message_t msg, mu_message_qid_t *pqid) ...@@ -389,9 +389,7 @@ amd_message_qid (mu_message_t msg, mu_message_qid_t *pqid)
389 { 389 {
390 struct _amd_message *mhm = mu_message_get_owner (msg); 390 struct _amd_message *mhm = mu_message_get_owner (msg);
391 391
392 *pqid = mhm->amd->msg_file_name (mhm, 392 return mhm->amd->cur_msg_file_name (mhm, pqid);
393 mhm->attr_flags & MU_ATTRIBUTE_DELETED);
394 return 0;
395 } 393 }
396 394
397 struct _amd_message * 395 struct _amd_message *
...@@ -644,7 +642,8 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, ...@@ -644,7 +642,8 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm,
644 } 642 }
645 643
646 /* Add imapbase */ 644 /* Add imapbase */
647 if (amd->next_uid 645 if (!(amd->mailbox->flags & MU_STREAM_APPEND)
646 && amd->next_uid
648 && (!amd->msg_array || (amd->msg_array[0] == mhm))) /*FIXME*/ 647 && (!amd->msg_array || (amd->msg_array[0] == mhm))) /*FIXME*/
649 { 648 {
650 nbytes += fprintf (fp, "X-IMAPbase: %lu %u\n", 649 nbytes += fprintf (fp, "X-IMAPbase: %lu %u\n",
...@@ -712,14 +711,29 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm, ...@@ -712,14 +711,29 @@ _amd_message_save (struct _amd_data *amd, struct _amd_message *mhm,
712 free (buf); 711 free (buf);
713 fclose (fp); 712 fclose (fp);
714 713
715 /* FIXME: This does not work for maildir. */ 714 status = amd->new_msg_file_name (mhm, mhm->attr_flags, &msg_name);
716 msg_name = amd->msg_file_name (mhm, mhm->deleted); 715 if (status == 0)
717 if (rename (name, msg_name)) 716 {
718 status = errno; 717 char *old_name;
718 status = amd->cur_msg_file_name (mhm, &old_name);
719 if (status == 0)
720 {
721 if (rename (name, msg_name))
722 status = errno;
723 else
724 {
725 if (strcmp (old_name, msg_name))
726 /* Unlink original message */
727 unlink (old_name);
728 }
729 free (old_name);
730 mhm->orig_flags = mhm->attr_flags;
731 }
732 free (msg_name);
733 }
719 free (name); 734 free (name);
720 free (msg_name);
721 735
722 return 0; 736 return status;
723 } 737 }
724 738
725 static int 739 static int
...@@ -772,14 +786,17 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -772,14 +786,17 @@ amd_append_message (mu_mailbox_t mailbox, mu_message_t msg)
772 } 786 }
773 787
774 if (amd->msg_finish_delivery) 788 if (amd->msg_finish_delivery)
775 amd->msg_finish_delivery (amd, mhm); 789 status = amd->msg_finish_delivery (amd, mhm);
776 790
777 if (mailbox->observable) 791 if (status == 0 && mailbox->observable)
778 { 792 {
779 char *qid = amd->msg_file_name (mhm, 793 char *qid;
780 mhm->attr_flags & MU_ATTRIBUTE_DELETED); 794 if (amd->cur_msg_file_name (mhm, &qid) == 0)
781 mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_APPEND, qid); 795 {
782 free (qid); 796 mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_APPEND,
797 qid);
798 free (qid);
799 }
783 } 800 }
784 801
785 return status; 802 return status;
...@@ -883,10 +900,22 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -883,10 +900,22 @@ amd_expunge (mu_mailbox_t mailbox)
883 900
884 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED) 901 if (mhm->attr_flags & MU_ATTRIBUTE_DELETED)
885 { 902 {
886 if (!mhm->deleted) 903 if (!(mhm->orig_flags & MU_ATTRIBUTE_DELETED))
887 { 904 {
888 char *old_name = amd->msg_file_name (mhm, 0); 905 int rc;
889 char *new_name = amd->msg_file_name (mhm, 1); 906 char *old_name;
907 char *new_name;
908
909 rc = amd->cur_msg_file_name (mhm, &old_name);
910 if (rc)
911 return rc;
912 rc = amd->new_msg_file_name (mhm, mhm->attr_flags, &new_name);
913 if (rc)
914 {
915 free (old_name);
916 return rc;
917 }
918
890 if (new_name) 919 if (new_name)
891 { 920 {
892 /* Rename original message */ 921 /* Rename original message */
...@@ -907,7 +936,6 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -907,7 +936,6 @@ amd_expunge (mu_mailbox_t mailbox)
907 || (mhm->message && mu_message_is_modified (mhm->message))) 936 || (mhm->message && mu_message_is_modified (mhm->message)))
908 { 937 {
909 _amd_attach_message (mailbox, mhm, NULL); 938 _amd_attach_message (mailbox, mhm, NULL);
910 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED;
911 _amd_message_save (amd, mhm, 1); 939 _amd_message_save (amd, mhm, 1);
912 } 940 }
913 i++; /* Move to the next message */ 941 i++; /* Move to the next message */
...@@ -947,7 +975,6 @@ amd_sync (mu_mailbox_t mailbox) ...@@ -947,7 +975,6 @@ amd_sync (mu_mailbox_t mailbox)
947 || (mhm->message && mu_message_is_modified (mhm->message))) 975 || (mhm->message && mu_message_is_modified (mhm->message)))
948 { 976 {
949 _amd_attach_message (mailbox, mhm, NULL); 977 _amd_attach_message (mailbox, mhm, NULL);
950 mhm->deleted = mhm->attr_flags & MU_ATTRIBUTE_DELETED;
951 _amd_message_save (amd, mhm, 0); 978 _amd_message_save (amd, mhm, 0);
952 } 979 }
953 } 980 }
...@@ -1074,7 +1101,11 @@ amd_scan_message (struct _amd_message *mhm) ...@@ -1074,7 +1101,11 @@ amd_scan_message (struct _amd_message *mhm)
1074 if (mhm->mtime) 1101 if (mhm->mtime)
1075 { 1102 {
1076 struct stat st; 1103 struct stat st;
1077 char *msg_name = mhm->amd->msg_file_name (mhm, mhm->deleted); 1104 char *msg_name;
1105
1106 status = mhm->amd->cur_msg_file_name (mhm, &msg_name);
1107 if (status)
1108 return status;
1078 1109
1079 if (stat (msg_name, &st) == 0 && st.st_mtime == mhm->mtime) 1110 if (stat (msg_name, &st) == 0 && st.st_mtime == mhm->mtime)
1080 { 1111 {
...@@ -1158,10 +1189,80 @@ amd_is_updated (mu_mailbox_t mailbox) ...@@ -1158,10 +1189,80 @@ amd_is_updated (mu_mailbox_t mailbox)
1158 } 1189 }
1159 1190
1160 static int 1191 static int
1161 amd_get_size (mu_mailbox_t mailbox MU_ARG_UNUSED, mu_off_t *psize MU_ARG_UNUSED) 1192 compute_mailbox_size (const char *name, mu_off_t *psize)
1162 { 1193 {
1163 /*FIXME*/ 1194 DIR *dir;
1164 return ENOSYS; 1195 struct dirent *entry;
1196 char *buf;
1197 size_t bufsize;
1198 size_t dirlen;
1199 size_t flen;
1200 int status = 0;
1201 struct stat sb;
1202
1203 dir = opendir (name);
1204 if (!dir)
1205 return errno;
1206
1207 dirlen = strlen (name);
1208 bufsize = dirlen + 32;
1209 buf = malloc (bufsize);
1210 if (!buf)
1211 {
1212 closedir (dir);
1213 return ENOMEM;
1214 }
1215
1216 strcpy (buf, name);
1217 if (buf[dirlen-1] != '/')
1218 buf[++dirlen - 1] = '/';
1219
1220 while ((entry = readdir (dir)))
1221 {
1222 switch (entry->d_name[0])
1223 {
1224 case '.':
1225 break;
1226
1227 default:
1228 flen = strlen (entry->d_name);
1229 if (dirlen + flen + 1 > bufsize)
1230 {
1231 bufsize = dirlen + flen + 1;
1232 buf = realloc (buf, bufsize);
1233 if (!buf)
1234 {
1235 status = ENOMEM;
1236 break;
1237 }
1238 }
1239 strcpy (buf + dirlen, entry->d_name);
1240 if (stat (buf, &sb) == 0)
1241 {
1242 if (S_ISREG (sb.st_mode))
1243 *psize += sb.st_size;
1244 else if (S_ISDIR (sb.st_mode))
1245 compute_mailbox_size (buf, psize);
1246 }
1247 /* FIXME: else? */
1248 break;
1249 }
1250 }
1251
1252 free (buf);
1253
1254 closedir (dir);
1255 return 0;
1256 }
1257
1258 static int
1259 amd_get_size (mu_mailbox_t mailbox, mu_off_t *psize)
1260 {
1261 struct _amd_data *amd = mailbox->data;
1262 if (amd->mailbox_size)
1263 return amd->mailbox_size (mailbox, psize);
1264 *psize = 0;
1265 return compute_mailbox_size (amd->name, psize);
1165 } 1266 }
1166 1267
1167 /* Return number of open streams residing in a message pool */ 1268 /* Return number of open streams residing in a message pool */
...@@ -1202,6 +1303,7 @@ amd_pool_lookup (struct _amd_message *mhm) ...@@ -1202,6 +1303,7 @@ amd_pool_lookup (struct _amd_message *mhm)
1202 static int 1303 static int
1203 amd_pool_open (struct _amd_message *mhm) 1304 amd_pool_open (struct _amd_message *mhm)
1204 { 1305 {
1306 int status;
1205 struct _amd_data *amd = mhm->amd; 1307 struct _amd_data *amd = mhm->amd;
1206 if (amd_pool_lookup (mhm)) 1308 if (amd_pool_lookup (mhm))
1207 return 0; 1309 return 0;
...@@ -1210,7 +1312,9 @@ amd_pool_open (struct _amd_message *mhm) ...@@ -1210,7 +1312,9 @@ amd_pool_open (struct _amd_message *mhm)
1210 amd_message_stream_close (amd->msg_pool[amd->pool_first++]); 1312 amd_message_stream_close (amd->msg_pool[amd->pool_first++]);
1211 amd->pool_first %= MAX_OPEN_STREAMS; 1313 amd->pool_first %= MAX_OPEN_STREAMS;
1212 } 1314 }
1213 amd_message_stream_open (mhm); 1315 status = amd_message_stream_open (mhm);
1316 if (status)
1317 return status;
1214 amd->msg_pool[amd->pool_last++] = mhm; 1318 amd->msg_pool[amd->pool_last++] = mhm;
1215 amd->pool_last %= MAX_OPEN_STREAMS; 1319 amd->pool_last %= MAX_OPEN_STREAMS;
1216 return 0; 1320 return 0;
...@@ -1237,12 +1341,13 @@ int ...@@ -1237,12 +1341,13 @@ int
1237 amd_message_stream_open (struct _amd_message *mhm) 1341 amd_message_stream_open (struct _amd_message *mhm)
1238 { 1342 {
1239 struct _amd_data *amd = mhm->amd; 1343 struct _amd_data *amd = mhm->amd;
1240 char *filename = amd->msg_file_name (mhm, mhm->deleted); 1344 char *filename;
1241 int status; 1345 int status;
1242 int flags = MU_STREAM_ALLOW_LINKS; 1346 int flags = MU_STREAM_ALLOW_LINKS;
1243 1347
1244 if (!filename) 1348 status = amd->cur_msg_file_name (mhm, &filename);
1245 return ENOMEM; 1349 if (status)
1350 return status;
1246 1351
1247 /* The message should be at least readable */ 1352 /* The message should be at least readable */
1248 if (amd->mailbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND)) 1353 if (amd->mailbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND))
...@@ -1399,8 +1504,9 @@ amd_header_fill (mu_header_t header, char *buffer, size_t len, ...@@ -1399,8 +1504,9 @@ amd_header_fill (mu_header_t header, char *buffer, size_t len,
1399 { 1504 {
1400 mu_message_t msg = mu_header_get_owner (header); 1505 mu_message_t msg = mu_header_get_owner (header);
1401 struct _amd_message *mhm = mu_message_get_owner (msg); 1506 struct _amd_message *mhm = mu_message_get_owner (msg);
1402 1507 int status = amd_pool_open (mhm);
1403 amd_pool_open (mhm); 1508 if (status)
1509 return status;
1404 return amd_readstream (mhm, buffer, len, off, pnread, 0, 1510 return amd_readstream (mhm, buffer, len, off, pnread, 0,
1405 0, mhm->body_start); 1511 0, mhm->body_start);
1406 } 1512 }
......
...@@ -325,18 +325,15 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge) ...@@ -325,18 +325,15 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge)
325 return 0; 325 return 0;
326 326
327 mu_mailbox_messages_count (mbox, &total); 327 mu_mailbox_messages_count (mbox, &total);
328 if (mbox->flags & MU_STREAM_APPEND) 328 if (!(mbox->flags & MU_STREAM_APPEND))
329 i = total; 329 for (i = 1; i <= total; i++)
330 else 330 {
331 i = 1; 331 mu_message_t msg = NULL;
332 for ( ; i <= total; i++) 332 mu_attribute_t attr = NULL;
333 { 333 mu_mailbox_get_message (mbox, i, &msg);
334 mu_message_t msg = NULL; 334 mu_message_get_attribute (msg, &attr);
335 mu_attribute_t attr = NULL; 335 mu_attribute_set_seen (attr);
336 mu_mailbox_get_message (mbox, i, &msg); 336 }
337 mu_message_get_attribute (msg, &attr);
338 mu_attribute_set_seen (attr);
339 }
340 337
341 if (expunge) 338 if (expunge)
342 status = mu_mailbox_expunge (mbox); 339 status = mu_mailbox_expunge (mbox);
......