Fix size calculation for MH and Maildir mailboxes
Exclude from calculation any eventual nested mailboxes. * libproto/maildir/mbox.c: Provide the mailbox_size method. * libproto/mh/mbox.c: Likewise.
Showing
2 changed files
with
231 additions
and
44 deletions
... | @@ -666,44 +666,63 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) | ... | @@ -666,44 +666,63 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) |
666 | size_t index; | 666 | size_t index; |
667 | int rc = 0; | 667 | int rc = 0; |
668 | int need_sort = 0; | 668 | int need_sort = 0; |
669 | struct stat st; | ||
669 | 670 | ||
670 | while ((entry = readdir (dir))) | 671 | while ((entry = readdir (dir))) |
671 | { | 672 | { |
672 | switch (entry->d_name[0]) | 673 | char *fname; |
674 | |||
675 | if (entry->d_name[0] == '.') | ||
676 | continue; | ||
677 | |||
678 | rc = maildir_mkfilename (amd->name, dirname, entry->d_name, &fname); | ||
679 | if (rc) | ||
673 | { | 680 | { |
674 | case '.': | 681 | mu_diag_funcall (MU_DIAG_ERROR, "maildir_mkfilename", |
675 | break; | 682 | entry->d_name, rc); |
683 | continue; | ||
684 | } | ||
685 | |||
686 | if (stat (fname, &st)) | ||
687 | { | ||
688 | rc = errno; | ||
689 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
690 | ("can't stat %s: %s", fname, mu_strerror (rc))); | ||
691 | free (fname); | ||
692 | continue; | ||
693 | } | ||
676 | 694 | ||
677 | default: | 695 | free (fname); |
678 | /* Message not found. Index points to the array cell where it | ||
679 | would be placed */ | ||
680 | msg = calloc (1, sizeof (*msg)); | ||
681 | if (!msg) | ||
682 | { | ||
683 | rc = ENOMEM; | ||
684 | break; | ||
685 | } | ||
686 | key.file_name = entry->d_name; | ||
687 | if (!amd_msg_lookup (amd, (struct _amd_message *) &key, &index)) | ||
688 | continue; | ||
689 | rc = _amd_message_append (amd, (struct _amd_message *) msg); | ||
690 | if (rc) | ||
691 | { | ||
692 | free (msg); | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | msg->dir = dirname; | ||
697 | msg->file_name = strdup (entry->d_name); | ||
698 | 696 | ||
699 | p = maildir_name_info_ptr (msg->file_name); | 697 | if (!S_ISREG (st.st_mode)) |
700 | if (p) | 698 | continue; |
701 | msg->amd_message.attr_flags = info_to_flags (p); | 699 | |
702 | else | 700 | msg = calloc (1, sizeof (*msg)); |
703 | msg->amd_message.attr_flags = 0; | 701 | if (!msg) |
704 | msg->amd_message.orig_flags = msg->amd_message.attr_flags; | 702 | { |
705 | need_sort = 1; | 703 | rc = ENOMEM; |
704 | break; | ||
706 | } | 705 | } |
706 | key.file_name = entry->d_name; | ||
707 | if (!amd_msg_lookup (amd, (struct _amd_message *) &key, &index)) | ||
708 | continue; | ||
709 | rc = _amd_message_append (amd, (struct _amd_message *) msg); | ||
710 | if (rc) | ||
711 | { | ||
712 | free (msg); | ||
713 | break; | ||
714 | } | ||
715 | |||
716 | msg->dir = dirname; | ||
717 | msg->file_name = strdup (entry->d_name); | ||
718 | |||
719 | p = maildir_name_info_ptr (msg->file_name); | ||
720 | if (p) | ||
721 | msg->amd_message.attr_flags = info_to_flags (p); | ||
722 | else | ||
723 | msg->amd_message.attr_flags = 0; | ||
724 | msg->amd_message.orig_flags = msg->amd_message.attr_flags; | ||
725 | need_sort = 1; | ||
707 | } | 726 | } |
708 | 727 | ||
709 | if (rc == 0 && need_sort) | 728 | if (rc == 0 && need_sort) |
... | @@ -712,9 +731,7 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) | ... | @@ -712,9 +731,7 @@ maildir_scan_dir (struct _amd_data *amd, DIR *dir, char *dirname) |
712 | } | 731 | } |
713 | 732 | ||
714 | static int | 733 | static int |
715 | maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | 734 | maildir_scan_unlocked (mu_mailbox_t mailbox, size_t *pcount, int do_notify) |
716 | size_t *pcount, | ||
717 | int do_notify) | ||
718 | { | 735 | { |
719 | struct _amd_data *amd = mailbox->data; | 736 | struct _amd_data *amd = mailbox->data; |
720 | DIR *dir; | 737 | DIR *dir; |
... | @@ -723,12 +740,6 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -723,12 +740,6 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
723 | struct stat st; | 740 | struct stat st; |
724 | size_t i; | 741 | size_t i; |
725 | 742 | ||
726 | if (amd == NULL) | ||
727 | return EINVAL; | ||
728 | if (mailbox->flags & MU_STREAM_APPEND) | ||
729 | return 0; | ||
730 | mu_monitor_wrlock (mailbox->monitor); | ||
731 | |||
732 | /* 1st phase: Flush tmp/ */ | 743 | /* 1st phase: Flush tmp/ */ |
733 | maildir_flush (amd); | 744 | maildir_flush (amd); |
734 | 745 | ||
... | @@ -748,11 +759,11 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -748,11 +759,11 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
748 | } | 759 | } |
749 | free (name); | 760 | free (name); |
750 | 761 | ||
762 | /* 3rd phase: Scan cur/ */ | ||
751 | status = maildir_mkfilename (amd->name, CURSUF, NULL, &name); | 763 | status = maildir_mkfilename (amd->name, CURSUF, NULL, &name); |
752 | if (status) | 764 | if (status) |
753 | return status; | 765 | return status; |
754 | 766 | ||
755 | /* 3rd phase: Scan cur/ */ | ||
756 | status = maildir_opendir (&dir, name, | 767 | status = maildir_opendir (&dir, name, |
757 | PERMS | | 768 | PERMS | |
758 | mu_stream_flags_to_mode (mailbox->flags, 1)); | 769 | mu_stream_flags_to_mode (mailbox->flags, 1)); |
... | @@ -778,11 +789,120 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ... | @@ -778,11 +789,120 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, |
778 | if (pcount) | 789 | if (pcount) |
779 | *pcount = amd->msg_count; | 790 | *pcount = amd->msg_count; |
780 | 791 | ||
781 | /* Clean up the things */ | ||
782 | amd_cleanup (mailbox); | ||
783 | return status; | 792 | return status; |
784 | } | 793 | } |
785 | 794 | ||
795 | static int | ||
796 | maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, | ||
797 | size_t *pcount, | ||
798 | int do_notify) | ||
799 | { | ||
800 | struct _amd_data *amd = mailbox->data; | ||
801 | int rc; | ||
802 | |||
803 | if (amd == NULL) | ||
804 | return EINVAL; | ||
805 | if (mailbox->flags & MU_STREAM_APPEND) | ||
806 | return 0; | ||
807 | mu_monitor_wrlock (mailbox->monitor); | ||
808 | rc = maildir_scan_unlocked (mailbox, pcount, do_notify); | ||
809 | mu_monitor_unlock (mailbox->monitor); | ||
810 | return rc; | ||
811 | } | ||
812 | |||
813 | static int | ||
814 | maildir_size_dir (struct _amd_data *amd, char *dirsuf, mu_off_t *psize) | ||
815 | { | ||
816 | DIR *dir; | ||
817 | struct dirent *entry; | ||
818 | int rc = 0; | ||
819 | struct stat st; | ||
820 | char *name; | ||
821 | |||
822 | rc = maildir_mkfilename (amd->name, dirsuf, NULL, &name); | ||
823 | if (rc) | ||
824 | return rc; | ||
825 | dir = opendir (name); | ||
826 | |||
827 | if (!dir) | ||
828 | { | ||
829 | rc = errno; | ||
830 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
831 | ("can't open directory %s: %s", name, mu_strerror (rc))); | ||
832 | free (name); | ||
833 | if (rc == ENOENT) | ||
834 | return 0; | ||
835 | return rc; | ||
836 | } | ||
837 | |||
838 | while ((entry = readdir (dir))) | ||
839 | { | ||
840 | char *fname; | ||
841 | |||
842 | if (entry->d_name[0] == '.') | ||
843 | continue; | ||
844 | |||
845 | rc = maildir_mkfilename (amd->name, dirsuf, entry->d_name, &fname); | ||
846 | if (rc) | ||
847 | { | ||
848 | mu_diag_funcall (MU_DIAG_ERROR, "maildir_mkfilename", | ||
849 | entry->d_name, rc); | ||
850 | continue; | ||
851 | } | ||
852 | |||
853 | if (stat (fname, &st)) | ||
854 | { | ||
855 | rc = errno; | ||
856 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
857 | ("can't stat %s: %s", fname, mu_strerror (rc))); | ||
858 | free (fname); | ||
859 | continue; | ||
860 | } | ||
861 | |||
862 | free (fname); | ||
863 | |||
864 | if (S_ISREG (st.st_mode)) | ||
865 | *psize += st.st_size; | ||
866 | } | ||
867 | |||
868 | closedir (dir); | ||
869 | free (name); | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | |||
874 | static int | ||
875 | maildir_size_unlocked (struct _amd_data *amd, mu_off_t *psize) | ||
876 | { | ||
877 | mu_off_t size = 0; | ||
878 | int rc; | ||
879 | |||
880 | rc = maildir_size_dir (amd, NEWSUF, &size); | ||
881 | if (rc) | ||
882 | return rc; | ||
883 | rc = maildir_size_dir (amd, CURSUF, &size); | ||
884 | if (rc) | ||
885 | return rc; | ||
886 | *psize = size; | ||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | static int | ||
891 | maildir_size (mu_mailbox_t mailbox, mu_off_t *psize) | ||
892 | { | ||
893 | struct _amd_data *amd = mailbox->data; | ||
894 | int rc; | ||
895 | |||
896 | if (amd == NULL) | ||
897 | return EINVAL; | ||
898 | |||
899 | mu_monitor_wrlock (mailbox->monitor); | ||
900 | rc = maildir_size_unlocked (amd, psize); | ||
901 | mu_monitor_unlock (mailbox->monitor); | ||
902 | |||
903 | return rc; | ||
904 | } | ||
905 | |||
786 | 906 | ||
787 | static int | 907 | static int |
788 | maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid) | 908 | maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid) |
... | @@ -926,6 +1046,7 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) | ... | @@ -926,6 +1046,7 @@ _mailbox_maildir_init (mu_mailbox_t mailbox) |
926 | amd->remove = maildir_remove; | 1046 | amd->remove = maildir_remove; |
927 | amd->chattr_msg = maildir_chattr_msg; | 1047 | amd->chattr_msg = maildir_chattr_msg; |
928 | amd->capabilities = MU_AMD_STATUS; | 1048 | amd->capabilities = MU_AMD_STATUS; |
1049 | amd->mailbox_size = maildir_size; | ||
929 | 1050 | ||
930 | /* Set our properties. */ | 1051 | /* Set our properties. */ |
931 | { | 1052 | { | ... | ... |
... | @@ -62,6 +62,7 @@ | ... | @@ -62,6 +62,7 @@ |
62 | #include <mailutils/observer.h> | 62 | #include <mailutils/observer.h> |
63 | #include <mailutils/io.h> | 63 | #include <mailutils/io.h> |
64 | #include <mailutils/cctype.h> | 64 | #include <mailutils/cctype.h> |
65 | #include <mailutils/cstr.h> | ||
65 | #include <mailutils/mh.h> | 66 | #include <mailutils/mh.h> |
66 | #include <mailutils/sys/mailbox.h> | 67 | #include <mailutils/sys/mailbox.h> |
67 | #include <mailutils/sys/registrar.h> | 68 | #include <mailutils/sys/registrar.h> |
... | @@ -281,14 +282,78 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, | ... | @@ -281,14 +282,78 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, |
281 | } | 282 | } |
282 | /* Clean up the things */ | 283 | /* Clean up the things */ |
283 | 284 | ||
285 | mu_locker_unlock (mailbox->locker); | ||
284 | amd_cleanup (mailbox); | 286 | amd_cleanup (mailbox); |
285 | #ifdef WITH_PTHREAD | 287 | #ifdef WITH_PTHREAD |
286 | pthread_cleanup_pop (0); | 288 | pthread_cleanup_pop (0); |
287 | #endif | 289 | #endif |
288 | return status; | 290 | return status; |
289 | } | 291 | } |
292 | |||
293 | static int | ||
294 | mh_size_unlocked (struct _amd_data *amd, mu_off_t *psize) | ||
295 | { | ||
296 | mu_off_t size = 0; | ||
297 | int rc; | ||
298 | struct stat st; | ||
299 | DIR *dir; | ||
300 | struct dirent *entry; | ||
301 | |||
302 | dir = opendir (amd->name); | ||
303 | if (!dir) | ||
304 | return errno; | ||
305 | |||
306 | while ((entry = readdir (dir))) | ||
307 | { | ||
308 | if (*mu_str_skip_class (entry->d_name, MU_CTYPE_DIGIT) == 0) | ||
309 | { | ||
310 | char *fname = mu_make_file_name (amd->name, entry->d_name); | ||
311 | if (!fname) | ||
312 | continue; | ||
313 | if (stat (fname, &st)) | ||
314 | { | ||
315 | rc = errno; | ||
316 | mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, | ||
317 | ("can't stat %s: %s", fname, mu_strerror (rc))); | ||
318 | free (fname); | ||
319 | continue; | ||
320 | } | ||
321 | if (S_ISREG (st.st_mode)) | ||
322 | size += st.st_size; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | *psize = size; | ||
327 | |||
328 | closedir (dir); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
290 | 332 | ||
291 | static int | 333 | static int |
334 | mh_size (mu_mailbox_t mailbox, mu_off_t *psize) | ||
335 | { | ||
336 | struct _amd_data *amd = mailbox->data; | ||
337 | int rc; | ||
338 | |||
339 | mu_monitor_wrlock (mailbox->monitor); | ||
340 | #ifdef WITH_PTHREAD | ||
341 | pthread_cleanup_push (amd_cleanup, (void *)mailbox); | ||
342 | #endif | ||
343 | mu_locker_lock (mailbox->locker); | ||
344 | |||
345 | rc = mh_size_unlocked (amd, psize); | ||
346 | |||
347 | mu_locker_unlock (mailbox->locker); | ||
348 | mu_monitor_unlock (mailbox->monitor); | ||
349 | #ifdef WITH_PTHREAD | ||
350 | pthread_cleanup_pop (0); | ||
351 | #endif | ||
352 | return rc; | ||
353 | } | ||
354 | |||
355 | |||
356 | static int | ||
292 | mh_qfetch (struct _amd_data *amd, mu_message_qid_t qid) | 357 | mh_qfetch (struct _amd_data *amd, mu_message_qid_t qid) |
293 | { | 358 | { |
294 | char *p; | 359 | char *p; |
... | @@ -467,7 +532,8 @@ _mailbox_mh_init (mu_mailbox_t mailbox) | ... | @@ -467,7 +532,8 @@ _mailbox_mh_init (mu_mailbox_t mailbox) |
467 | amd->message_uid = mh_message_uid; | 532 | amd->message_uid = mh_message_uid; |
468 | amd->next_uid = _mh_next_seq; | 533 | amd->next_uid = _mh_next_seq; |
469 | amd->remove = mh_remove; | 534 | amd->remove = mh_remove; |
470 | 535 | amd->mailbox_size = mh_size; | |
536 | |||
471 | mailbox->_get_property = mh_get_property; | 537 | mailbox->_get_property = mh_get_property; |
472 | mailbox->_translate = mh_translate; | 538 | mailbox->_translate = mh_translate; |
473 | 539 | ... | ... |
-
Please register or sign in to post a comment