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.
Showing
6 changed files
with
309 additions
and
92 deletions
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); | ... | ... |
-
Please register or sign in to post a comment