2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto & The Sylpheed Claws Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include <sys/types.h>
29 #include "mbox_folder.h"
32 #include "procheader.h"
36 #define MSGBUFSIZE 8192
38 static void mbox_folder_init (Folder *folder,
42 static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp,
43 gchar * new_filename, gint size);
44 static gboolean mbox_rewrite(gchar * mbox);
45 static gboolean mbox_purge_deleted(gchar * mbox);
46 static gchar * mbox_get_new_path(FolderItem * parent, gchar * name);
47 static gchar * mbox_get_folderitem_name(gchar * name);
49 MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num);
50 GSList *mbox_get_num_list(Folder *folder, FolderItem *item);
51 gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item);
53 Folder *mbox_folder_new(const gchar *name, const gchar *path)
57 folder = (Folder *)g_new0(MBOXFolder, 1);
58 mbox_folder_init(folder, name, path);
63 void mbox_folder_destroy(MBOXFolder *folder)
65 folder_local_folder_destroy(LOCAL_FOLDER(folder));
68 static void mbox_folder_init(Folder *folder, const gchar *name, const gchar *path)
70 folder_local_folder_init(folder, name, path);
72 folder->type = F_MBOX;
75 folder->get_msg_list = mbox_get_msg_list;
77 folder->fetch_msg = mbox_fetch_msg;
78 folder->fetch_msginfo = mbox_fetch_msginfo;
79 folder->add_msg = mbox_add_msg;
80 folder->copy_msg = mbox_copy_msg;
81 folder->remove_msg = mbox_remove_msg;
82 folder->remove_all_msg = mbox_remove_all_msg;
84 folder->scan = mbox_scan_folder;
86 folder->get_num_list = mbox_get_num_list;
87 folder->create_tree = mbox_create_tree;
88 folder->create_folder = mbox_create_folder;
89 folder->rename_folder = mbox_rename_folder;
90 folder->remove_folder = mbox_remove_folder;
91 folder->check_msgnum_validity
92 = mbox_check_msgnum_validity;
95 static gchar * mbox_folder_create_parent(const gchar * path)
97 if (!is_file_exist(path)) {
100 new_path = g_dirname(path);
101 if (new_path[strlen(new_path) - 1] == G_DIR_SEPARATOR)
102 new_path[strlen(new_path) - 1] = '\0';
104 if (!is_dir_exist(new_path))
105 make_dir_hier(new_path);
112 static gchar *mbox_folder_get_path(FolderItem *item)
117 g_return_val_if_fail(item != NULL, NULL);
119 if (item->path && item->path[0] == G_DIR_SEPARATOR) {
120 mbox_folder_create_parent(item->path);
121 return g_strdup(item->path);
124 folder_path = g_strdup(LOCAL_FOLDER(item->folder)->rootpath);
125 g_return_val_if_fail(folder_path != NULL, NULL);
127 if (folder_path[0] == G_DIR_SEPARATOR) {
129 path = g_strconcat(folder_path, G_DIR_SEPARATOR_S,
133 path = g_strdup(folder_path);
136 path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S,
137 folder_path, G_DIR_SEPARATOR_S,
140 path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S,
146 mbox_folder_create_parent(path);
152 /**********************************************************/
156 /**********************************************************/
159 static GSList * file_lock = NULL;
161 static gboolean mbox_file_lock_file(gchar * base)
163 gchar *lockfile, *locklink;
167 lockfile = g_strdup_printf("%s.%d", base, getpid());
168 if ((lockfp = fopen(lockfile, "wb")) == NULL) {
169 FILE_OP_ERROR(lockfile, "fopen");
170 g_warning(_("can't create lock file %s\n"), lockfile);
171 g_warning(_("use 'flock' instead of 'file' if possible.\n"));
176 fprintf(lockfp, "%d\n", getpid());
179 locklink = g_strconcat(base, ".lock", NULL);
180 while (link(lockfile, locklink) < 0) {
181 FILE_OP_ERROR(lockfile, "link");
183 g_warning(_("can't create %s\n"), lockfile);
189 g_warning(_("mailbox is owned by another"
190 " process, waiting...\n"));
200 static gboolean mbox_fcntl_lockwrite_file(FILE * fp)
204 lck.l_type = F_WRLCK;
209 if (fcntl(fileno(fp), F_SETLK, &lck) < 0)
215 static gboolean mbox_fcntl_lockread_file(FILE * fp)
219 lck.l_type = F_RDLCK;
224 if (fcntl(fileno(fp), F_SETLK, &lck) < 0)
230 static gboolean mbox_fcntl_unlock_file(FILE * fp)
234 lck.l_type = F_UNLCK;
239 if (fcntl(fileno(fp), F_SETLK, &lck) < 0)
245 static gboolean mbox_file_unlock_file(gchar * base)
249 lockfile = g_strdup_printf("%s.lock", base);
256 static gboolean mbox_lockread_file(FILE * fp, gchar * base)
260 result = mbox_fcntl_lockread_file(fp);
262 if ((result = mbox_file_lock_file(base)) == TRUE) {
263 file_lock = g_slist_append(file_lock, g_strdup(base));
264 debug_print("lockfile lock %s.\n", base);
267 g_warning(_("could not lock read file %s\n"), base);
270 debug_print("fcntl lock %s.\n", base);
275 static gboolean mbox_lockwrite_file(FILE * fp, gchar * base)
279 result = mbox_fcntl_lockwrite_file(fp);
281 if ((result = mbox_file_lock_file(base)) == TRUE) {
282 file_lock = g_slist_append(file_lock, g_strdup(base));
283 debug_print("lockfile lock %s.\n", base);
286 g_warning(_("could not lock write file %s\n"), base);
289 debug_print("fcntl lock %s.\n", base);
294 static gboolean mbox_unlock_file(FILE * fp, gchar * base)
296 gboolean result = FALSE;
298 gboolean unlocked = FALSE;
300 for(l = file_lock ; l != NULL ; l = g_slist_next(l)) {
301 gchar * data = l->data;
303 if (strcmp(data, base) == 0) {
304 file_lock = g_slist_remove(file_lock, data);
306 result = mbox_file_unlock_file(base);
308 debug_print("lockfile unlock - %s.\n", base);
314 result = mbox_fcntl_unlock_file(fp);
315 debug_print("fcntl unlock - %s.\n", base);
321 /**********************************************************/
325 /**********************************************************/
327 #define MAILFILE_ERROR_NO_ERROR 0x000
328 #define MAILFILE_ERROR_FILE_NOT_FOUND 0x001
329 #define MAILFILE_ERROR_MEMORY 0x002
330 #define MAILFILE_ERROR_MESSAGE_NOT_FOUND 0x003
332 static int mailfile_error = MAILFILE_ERROR_NO_ERROR;
334 #define STATE_BEGIN 0x000
335 #define STATE_TEXT_READ 0x001
336 #define STATE_FROM_READ 0x002
337 #define STATE_FIELD_READ 0x003
338 #define STATE_END 0x004
339 #define STATE_END_OF_FILE 0x005
340 #define STATE_MEM_ERROR 0x006
341 #define STATE_TEXT_BEGIN 0x007
343 #define STATE_MASK 0x0FF /* filter state from functions */
345 #define STATE_RESTORE_POS 0x100 /* go back while reading */
347 typedef struct _mailfile mailfile;
371 #define MSG_IS_INVALID(msg) \
372 ((msg).perm_flags == (msg).tmp_flags && (msg).tmp_flags == -1)
374 #define MSG_SET_INVALID(msg) \
375 ((msg).perm_flags = (msg).tmp_flags = -1)
377 static int startFrom(char * s)
379 return (strncmp(s, "From ", 5) == 0);
382 static int startSpace(char * s)
384 return ((*s == ' ') || (*s == '\t'));
387 static int startEmpty(char * s)
392 static void free_msg_list(GList * l)
394 GList * elt = g_list_first(l);
399 elt = g_list_next(elt);
406 static mailfile * mailfile_init_from_file(FILE * f, gchar * filename)
409 GList * msg_list = NULL;
416 struct _message * data = NULL;
422 while (state != STATE_END_OF_FILE) {
423 if ((state & STATE_RESTORE_POS) == 0) {
424 former_pos = lastpos;
427 r = fgets(s, 256, f);
430 ignore_next = (s[strlen(s) - 1] != '\n');
435 switch(state & 0x0F) {
438 state = STATE_END_OF_FILE;
439 else if (startFrom(s)) {
440 state = STATE_FROM_READ;
442 data = g_new0(struct _message, 1);
444 free_msg_list(msg_list);
449 data->msgnum = msgnum;
450 data->offset = lastpos;
451 data->header = lastpos;
454 data->messageid = NULL;
455 data->fromspace = NULL;
456 MSG_SET_INVALID(data->flags);
457 MSG_SET_INVALID(data->old_flags);
458 data->fetched = FALSE;
459 msg_list = g_list_append(msg_list,
467 case STATE_TEXT_READ:
470 else if (startFrom(s))
471 state = STATE_END | STATE_RESTORE_POS;
473 state = STATE_TEXT_READ;
476 case STATE_TEXT_BEGIN:
477 data->content = lastpos;
480 else if (startFrom(s)) {
481 state = STATE_END | STATE_RESTORE_POS;
484 state = STATE_TEXT_READ;
488 case STATE_FROM_READ:
489 data->content = lastpos;
492 else if (startSpace(s))
493 state = STATE_FROM_READ;
494 else if (startEmpty(s))
495 state = STATE_TEXT_READ;
497 state = STATE_FIELD_READ;
500 case STATE_FIELD_READ:
501 data->content = lastpos;
504 else if (startSpace(s))
505 state = STATE_FIELD_READ;
506 else if (startEmpty(s)) {
507 state = STATE_TEXT_BEGIN;
510 state = STATE_FIELD_READ;
514 if ((state & STATE_MASK) == STATE_END) {
515 state = STATE_BEGIN | (state & STATE_RESTORE_POS);
521 r = fgets(s, 256, f);
522 if (r == NULL || *r == '\0')
525 while (s[strlen(s) - 1] != '\n');
529 mf = (mailfile *) g_new0(struct _mailfile, 1);
531 free_msg_list(msg_list);
532 mailfile_error = MAILFILE_ERROR_MEMORY;
536 mf->msg_list = g_list_first(msg_list);
538 mf->filename = g_strdup(filename);
541 mailfile_error = MAILFILE_ERROR_NO_ERROR;
546 static mailfile * mailfile_init(char * filename)
552 f = fopen(filename, "rb");
555 mailfile_error = MAILFILE_ERROR_FILE_NOT_FOUND;
559 mbox_lockread_file(f, filename);
561 mf = mailfile_init_from_file(f, filename);
563 mbox_unlock_file(f, filename);
570 static void mailfile_done(mailfile * f)
572 free_msg_list(f->msg_list);
579 #define MAX_READ 4096
581 static char * readfile(char * filename, int offset, int max_offset)
590 handle = fopen(filename, "rb");
592 if (handle == NULL) {
593 mailfile_error = MAILFILE_ERROR_FILE_NOT_FOUND;
597 size = max_offset - offset;
599 message = (char *) malloc(size + 1);
600 if (message == NULL) {
602 mailfile_error = MAILFILE_ERROR_MEMORY;
606 fseek(handle, offset, SEEK_SET);
610 if ((size - pos) > MAX_READ)
615 bread = fread(message + pos, 1, max, handle);
631 static char * mailfile_readmsg(mailfile f, int index)
637 struct _message * msginfo;
639 nth = g_list_nth(f->msg_list, index);
642 mailfile_error = MAILFILE_ERROR_MESSAGE_NOT_FOUND;
646 msginfo = (struct _message *)nth->data;
648 offset = msginfo->offset;
649 max_offset = msginfo->end;
650 message = readfile(f->filename, offset, max_offset);
652 mailfile_error = MAILFILE_ERROR_NO_ERROR;
657 static char * mailfile_readheader(mailfile f, int index)
663 struct _message * msginfo;
665 nth = g_list_nth(f->msg_list, index);
668 mailfile_error = MAILFILE_ERROR_MESSAGE_NOT_FOUND;
672 msginfo = (struct _message *)nth->data;
674 offset = msginfo->offset;
675 max_offset = msginfo->content;
676 message = readfile(f->filename, offset, max_offset);
678 mailfile_error = MAILFILE_ERROR_NO_ERROR;
683 static int mailfile_count(mailfile * f)
685 return g_list_length(f->msg_list);
688 static int mailfile_find_deleted(mailfile f, char * filename)
692 handle = fopen(filename, "rb");
695 struct _message m = elt->data;
696 n = fread(&m.deleted, sizeof(int), 1, handle);
699 elt = g_list_next(elt);
708 /**********************************************************/
710 /* mbox cache operations */
712 /**********************************************************/
719 gboolean modification;
722 typedef struct _mboxcache mboxcache;
724 static GHashTable * mbox_cache_table = NULL;
726 static MsgInfo *mbox_parse_msg(FILE * fp, struct _message * msg,
730 MsgFlags flags = { 0, 0 };
732 MSG_SET_PERM_FLAGS(flags, MSG_NEW | MSG_UNREAD);
734 g_return_val_if_fail(fp != NULL, NULL);
737 if (item->stype == F_QUEUE) {
738 MSG_SET_TMP_FLAGS(flags, MSG_QUEUED);
739 } else if (item->stype == F_DRAFT) {
740 MSG_SET_TMP_FLAGS(flags, MSG_DRAFT);
744 msginfo = procheader_parse_stream(fp, flags, FALSE, FALSE);
746 if (!msginfo) return NULL;
749 msginfo->msgnum = msg->msgnum;
750 msginfo->folder = item;
756 static void mbox_cache_init()
758 mbox_cache_table = g_hash_table_new(g_str_hash, g_str_equal);
761 static void mbox_cache_done()
763 g_hash_table_destroy(mbox_cache_table);
766 static void mbox_cache_free_mbox(mboxcache * cache)
768 g_hash_table_remove(mbox_cache_table, cache->filename);
771 mailfile_done(cache->mf);
773 g_ptr_array_free(cache->tab_mf, FALSE);
775 g_free(cache->filename);
779 static void mbox_cache_get_msginfo_from_file(FILE * fp, GList * msg_list)
784 for(l = msg_list ; l != NULL ; l = g_list_next(l)) {
785 struct _message * msg;
787 msg = (struct _message *) l->data;
789 fseek(fp, msg->header, SEEK_SET);
790 msginfo = mbox_parse_msg(fp, msg, NULL);
794 g_strdup(msginfo->msgid);
795 if (msginfo->fromspace)
797 g_strdup(msginfo->fromspace);
798 msg->flags = msginfo->flags;
799 msg->old_flags = msginfo->flags;
801 procmsg_msginfo_free(msginfo);
806 static void mbox_cache_get_msginfo(gchar * filename, GList * msg_list)
810 fp = fopen(filename, "rb");
814 mbox_cache_get_msginfo_from_file(fp, msg_list);
818 static mboxcache * mbox_cache_read_mbox(gchar * filename)
825 if (stat(filename, &s) < 0)
828 mf = mailfile_init(filename);
832 cache = g_new0(mboxcache, 1);
834 cache->mtime = s.st_mtime;
836 cache->filename = g_strdup(filename);
837 cache->modification = FALSE;
839 cache->tab_mf = g_ptr_array_new();
840 for(l = mf->msg_list ; l != NULL ; l = g_list_next(l))
841 g_ptr_array_add(cache->tab_mf, l->data);
843 mbox_cache_get_msginfo(filename, mf->msg_list);
845 debug_print(_("read mbox - %s\n"), filename);
850 static mboxcache * mbox_cache_read_mbox_from_file(FILE * fp, gchar * filename)
857 if (stat(filename, &s) < 0)
860 mf = mailfile_init_from_file(fp, filename);
864 cache = g_new0(mboxcache, 1);
866 cache->mtime = s.st_mtime;
868 cache->filename = g_strdup(filename);
870 cache->tab_mf = g_ptr_array_new();
871 for(l = mf->msg_list ; l != NULL ; l = g_list_next(l))
872 g_ptr_array_add(cache->tab_mf, l->data);
874 mbox_cache_get_msginfo_from_file(fp, mf->msg_list);
876 debug_print(_("read mbox from file - %s\n"), filename);
881 static void mbox_cache_insert_mbox(mboxcache * data)
883 if (mbox_cache_table == NULL)
886 g_hash_table_insert(mbox_cache_table, data->filename, data);
889 static mboxcache * mbox_cache_get_mbox(gchar * filename)
891 if (mbox_cache_table == NULL)
894 return g_hash_table_lookup(mbox_cache_table, filename);
898 static gint mbox_cache_get_count(gchar * filename)
902 cache = mbox_cache_get_mbox(filename);
905 if (cache->mf == NULL)
907 return cache->mf->count;
910 static gint mbox_cache_get_mtime(gchar * filename)
914 cache = mbox_cache_get_mbox(filename);
920 static GList * mbox_cache_get_msg_list(gchar * filename)
924 cache = mbox_cache_get_mbox(filename);
929 if (cache->mf == NULL)
932 return cache->mf->msg_list;
935 static void mbox_cache_synchronize_lists(GList * old_msg_list,
936 GList * new_msg_list)
941 for(l2 = old_msg_list ; l2 != NULL ; l2 = g_list_next(l2)) {
942 struct _message * msg2 = l2->data;
944 if ((msg2->messageid == NULL) ||
945 (msg2->fromspace == NULL))
948 for(l = new_msg_list ; l != NULL ; l = g_list_next(l)) {
949 struct _message * msg = l->data;
951 if ((msg->messageid == NULL) ||
952 (msg->fromspace == NULL))
955 if ((strcmp(msg->messageid, msg2->messageid) == 0) &&
956 (strcmp(msg->fromspace, msg2->fromspace) == 0)) {
957 if (msg2->flags.perm_flags != msg2->old_flags.perm_flags) {
958 msg->flags = msg2->flags;
966 static void mbox_cache_synchronize(gchar * filename, gboolean sync)
968 mboxcache * new_cache;
969 mboxcache * old_cache;
970 gboolean scan_new = TRUE;
973 old_cache = mbox_cache_get_mbox(filename);
975 if (old_cache != NULL) {
976 if (stat(filename, &s) < 0) {
977 FILE_OP_ERROR(filename, "stat");
978 } else if (old_cache->mtime == s.st_mtime) {
979 debug_print("Folder is not modified.\n");
988 if (strstr(filename, "trash") == 0)
989 printf("old_cache: %p %s\n", old_cache, filename);
991 printf("begin old\n");
992 for(l = old_cache->mf->msg_list ; l != NULL ;
993 l = g_list_next(l)) {
994 struct _message * msg = l->data;
1001 new_cache = mbox_cache_read_mbox(filename);
1004 if (strstr(filename, "trash") == 0)
1005 printf("new_cache: %p %s\n", new_cache, filename);
1007 printf("begin new\n");
1008 for(l = new_cache->mf->msg_list ; l != NULL ;
1009 l = g_list_next(l)) {
1010 struct _message * msg = l->data;
1011 printf("%p\n", msg);
1013 printf("end new\n");
1020 if (sync && new_cache && old_cache)
1021 mbox_cache_synchronize_lists(old_cache->mf->msg_list,
1022 new_cache->mf->msg_list);
1024 if (old_cache != NULL)
1025 mbox_cache_free_mbox(old_cache);
1028 mbox_cache_insert_mbox(new_cache);
1030 printf("insert %p %s\n", new_cache, new_cache->filename);
1031 printf("inserted %s %p\n", filename,
1032 mbox_cache_get_mbox(filename));
1038 static void mbox_cache_synchronize_from_file(FILE * fp, gchar * filename,
1041 mboxcache * new_cache;
1042 mboxcache * old_cache;
1043 gboolean scan_new = TRUE;
1046 old_cache = mbox_cache_get_mbox(filename);
1048 if (old_cache != NULL) {
1049 if (stat(filename, &s) < 0) {
1050 FILE_OP_ERROR(filename, "stat");
1051 } else if (old_cache->mtime == s.st_mtime) {
1052 debug_print("Folder is not modified.\n");
1063 if (strstr(filename, "trash") == 0)
1064 printf("old_cache: %p %s\n", old_cache, filename);
1067 printf("begin old\n");
1068 for(l = old_cache->mf->msg_list ; l != NULL ;
1069 l = g_list_next(l)) {
1070 struct _message * msg = l->data;
1071 printf("%p\n", msg);
1073 printf("end old\n");
1077 new_cache = mbox_cache_read_mbox_from_file(fp, filename);
1080 if (strstr(filename, "trash") == 0)
1081 printf("new_cache: %p %s\n", new_cache, filename);
1084 printf("begin new\n");
1085 for(l = new_cache->mf->msg_list ; l != NULL ;
1086 l = g_list_next(l)) {
1087 struct _message * msg = l->data;
1088 printf("%p\n", msg);
1090 printf("end new\n");
1097 if (sync && new_cache && old_cache)
1098 mbox_cache_synchronize_lists(old_cache->mf->msg_list,
1099 new_cache->mf->msg_list);
1101 if (old_cache != NULL)
1102 mbox_cache_free_mbox(old_cache);
1105 mbox_cache_insert_mbox(new_cache);
1107 printf("insert %p %s\n", new_cache, new_cache->filename);
1108 printf("inserted %s %p\n", filename,
1109 mbox_cache_get_mbox(filename));
1115 gboolean mbox_cache_msg_fetched(gchar * filename, gint num)
1117 struct _message * msg;
1120 cache = mbox_cache_get_mbox(filename);
1125 msg = (struct _message *) g_ptr_array_index(cache->tab_mf,
1130 return msg->fetched;
1133 void mbox_cache_msg_set_fetched(gchar * filename, gint num)
1135 struct _message * msg;
1138 cache = mbox_cache_get_mbox(filename);
1143 msg = (struct _message *) g_ptr_array_index(cache->tab_mf,
1148 msg->fetched = TRUE;
1151 struct _message * mbox_cache_get_msg(gchar * filename, gint num)
1155 cache = mbox_cache_get_mbox(filename);
1157 if (cache == NULL) {
1161 return (struct _message *) g_ptr_array_index(cache->tab_mf,
1166 /**********************************************************/
1168 /* mbox operations */
1170 /**********************************************************/
1173 GSList *mbox_get_msg_list(Folder *folder, FolderItem *item, gboolean use_cache)
1182 struct timeval tv_before, tv_after, tv_result;
1184 gettimeofday(&tv_before, NULL);
1189 mbox_path = mbox_folder_get_path(item);
1191 if (mbox_path == NULL)
1194 mbox_purge_deleted(mbox_path);
1196 fp = fopen(mbox_path, "rb");
1203 mbox_lockread_file(fp, mbox_path);
1205 mbox_cache_synchronize_from_file(fp, mbox_path, TRUE);
1207 item->last_num = mbox_cache_get_count(mbox_path);
1209 for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ;
1210 l = g_list_next(l)) {
1211 struct _message * msg;
1213 msg = (struct _message *) l->data;
1215 if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) {
1216 fseek(fp, msg->header, SEEK_SET);
1218 msginfo = mbox_parse_msg(fp, msg, item);
1220 if (!MSG_IS_INVALID(msg->flags))
1221 msginfo->flags = msg->flags;
1223 msg->old_flags = msginfo->flags;
1224 msg->flags = msginfo->flags;
1227 mlist = g_slist_append(mlist, msginfo);
1230 MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED);
1234 mbox_unlock_file(fp, mbox_path);
1241 gettimeofday(&tv_after, NULL);
1243 timersub(&tv_after, &tv_before, &tv_result);
1244 g_print("mbox_get_msg_list: %s: elapsed time: %ld.%06ld sec\n",
1245 mbox_path, tv_result.tv_sec, tv_result.tv_usec);
1251 static gboolean mbox_extract_msg(FolderItem * item, gint msgnum,
1252 gchar * dest_filename)
1254 struct _message * msg;
1261 /* GList * msg_list;*/
1262 gboolean already_fetched;
1265 mbox_path = mbox_folder_get_path(item);
1267 if (mbox_path == NULL)
1270 src = fopen(mbox_path, "rb");
1276 mbox_lockread_file(src, mbox_path);
1278 mbox_cache_synchronize_from_file(src, mbox_path, TRUE);
1280 already_fetched = mbox_cache_msg_fetched(mbox_path, msgnum);
1282 if (already_fetched) {
1283 mbox_unlock_file(src, mbox_path);
1289 msg = mbox_cache_get_msg(mbox_path, msgnum);
1292 mbox_unlock_file(src, mbox_path);
1298 offset = msg->offset;
1299 max_offset = msg->end;
1301 size = max_offset - offset;
1303 fseek(src, offset, SEEK_SET);
1305 dest = fopen(dest_filename, "wb");
1307 mbox_unlock_file(src, mbox_path);
1313 if (change_file_mode_rw(dest, dest_filename) < 0) {
1314 FILE_OP_ERROR(dest_filename, "chmod");
1315 g_warning(_("can't change file mode\n"));
1318 if (!mbox_write_data(src, dest, dest_filename, size)) {
1319 mbox_unlock_file(src, mbox_path);
1322 unlink(dest_filename);
1330 FILE_OP_ERROR(mbox_path, "fread");
1334 mbox_cache_msg_set_fetched(mbox_path, msgnum);
1336 if (fclose(dest) == -1) {
1337 FILE_OP_ERROR(dest_filename, "fclose");
1341 mbox_unlock_file(src, mbox_path);
1343 if (fclose(src) == -1) {
1344 FILE_OP_ERROR(mbox_path, "fclose");
1351 unlink(dest_filename);
1358 gchar *mbox_fetch_msg(Folder *folder, FolderItem *item, gint num)
1363 g_return_val_if_fail(item != NULL, NULL);
1365 path = folder_item_get_path(item);
1366 if (!is_dir_exist(path))
1367 make_dir_hier(path);
1369 filename = g_strconcat(path, G_DIR_SEPARATOR_S, itos(num), NULL);
1373 if (!mbox_extract_msg(item, num, filename)) {
1381 gint mbox_add_msg(Folder *folder, FolderItem *dest, const gchar *file,
1382 gboolean remove_source)
1391 gchar from_line[MSGBUFSIZE];
1393 if (dest->last_num < 0) {
1394 mbox_scan_folder(folder, dest);
1395 if (dest->last_num < 0) return -1;
1398 src_fp = fopen(file, "rb");
1399 if (src_fp == NULL) {
1403 mbox_path = mbox_folder_get_path(dest);
1404 if (mbox_path == NULL)
1407 dest_fp = fopen(mbox_path, "ab");
1408 if (dest_fp == NULL) {
1414 if (change_file_mode_rw(dest_fp, mbox_path) < 0) {
1415 FILE_OP_ERROR(mbox_path, "chmod");
1416 g_warning(_("can't change file mode\n"));
1419 old_size = ftell(dest_fp);
1421 mbox_lockwrite_file(dest_fp, mbox_path);
1423 if (fgets(from_line, sizeof(from_line), src_fp) == NULL) {
1424 mbox_unlock_file(dest_fp, mbox_path);
1425 g_warning(_("unvalid file - %s.\n"), file);
1432 if (strncmp(from_line, "From ", 5) != 0) {
1435 if (stat(file, &s) < 0) {
1436 mbox_unlock_file(dest_fp, mbox_path);
1437 g_warning(_("invalid file - %s.\n"), file);
1444 fprintf(dest_fp, "From - %s", ctime(&s.st_mtime));
1447 fputs(from_line, dest_fp);
1450 n_read = fread(buf, 1, sizeof(buf), src_fp);
1451 if ((n_read < (gint) sizeof(buf)) && ferror(src_fp))
1453 if (fwrite(buf, n_read, 1, dest_fp) < 1) {
1454 mbox_unlock_file(dest_fp, mbox_path);
1455 g_warning(_("writing to %s failed.\n"), mbox_path);
1456 ftruncate(fileno(dest_fp), old_size);
1463 if (n_read < (gint) sizeof(buf))
1469 if (ferror(src_fp)) {
1470 FILE_OP_ERROR(mbox_path, "fread");
1473 mbox_unlock_file(dest_fp, mbox_path);
1475 if (fclose(src_fp) == -1) {
1476 FILE_OP_ERROR(file, "fclose");
1480 if (fclose(dest_fp) == -1) {
1481 FILE_OP_ERROR(mbox_path, "fclose");
1487 ftruncate(fileno(dest_fp), old_size);
1492 if (remove_source) {
1493 if (unlink(file) < 0)
1494 FILE_OP_ERROR(file, "unlink");
1500 return dest->last_num;
1504 gint mbox_remove_msg(Folder *folder, FolderItem *item, gint num)
1506 struct _message * msg;
1509 mbox_path = mbox_folder_get_path(item);
1510 if (mbox_path == NULL)
1513 mbox_cache_synchronize(mbox_path, TRUE);
1515 msg = mbox_cache_get_msg(mbox_path, num);
1520 MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED);
1525 gint mbox_remove_all_msg(Folder *folder, FolderItem *item)
1530 mbox_path = mbox_folder_get_path(item);
1531 if (mbox_path == NULL)
1534 fp = fopen(mbox_path, "wb");
1548 gint mbox_move_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
1553 filename = mbox_fetch_msg(folder, msginfo->folder, msginfo->msgnum);
1554 if (filename == NULL)
1557 msgnum = mbox_add_msg(folder, dest, filename, TRUE);
1560 MSG_SET_FLAGS(msginfo->flags, MSG_REALLY_DELETED);
1561 mbox_change_flags(folder, msginfo->folder, msginfo);
1567 gint mbox_move_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
1570 gchar * mbox_path = NULL;
1572 for(l = msglist ; l != NULL ; l = g_slist_next(l)) {
1573 MsgInfo * msginfo = (MsgInfo *) l->data;
1575 if (msginfo->folder && mbox_path == NULL)
1576 mbox_path = mbox_folder_get_path(msginfo->folder);
1578 mbox_move_msg(folder, dest, msginfo);
1582 mbox_cache_synchronize(mbox_path);
1586 mbox_path = mbox_folder_get_path(dest);
1587 mbox_cache_synchronize(mbox_path);
1590 return dest->last_num;
1595 gint mbox_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
1600 filename = mbox_fetch_msg(folder, msginfo->folder, msginfo->msgnum);
1601 if (filename == NULL)
1604 msgnum = mbox_add_msg(folder, dest, filename, FALSE);
1609 gint mbox_copy_msgs_with_dest(Folder *folder, FolderItem *dest, GSList *msglist)
1612 gchar * mbox_path = NULL;
1614 for(l = msglist ; l != NULL ; l = g_slist_next(l)) {
1615 MsgInfo * msginfo = (MsgInfo *) l->data;
1617 if (msginfo->folder && mbox_path == NULL)
1618 mbox_path = mbox_folder_get_path(msginfo->folder);
1620 mbox_copy_msg(folder, dest, msginfo);
1624 mbox_cache_synchronize(mbox_path);
1628 mbox_path = mbox_folder_get_path(dest);
1629 mbox_cache_synchronize(mbox_path);
1632 return dest->last_num;
1636 struct _copy_flags_info
1642 typedef struct _copy_flags_info CopyFlagsInfo;
1644 GSList * copy_flags_data = NULL;
1646 gint mbox_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
1648 Folder * src_folder;
1653 struct _message * msg;
1654 CopyFlagsInfo * flags_info;
1656 src_folder = msginfo->folder->folder;
1658 g_return_val_if_fail(src_folder->fetch_msg != NULL, -1);
1661 mbox_path = mbox_folder_get_path(msginfo->folder);
1662 mbox_rewrite(mbox_path);
1666 filename = src_folder->fetch_msg(src_folder,
1669 if (filename == NULL)
1672 num = folder->add_msg(folder, dest, filename, FALSE);
1675 mbox_path = mbox_folder_get_path(dest);
1676 msg = mbox_cache_get_msg(mbox_path, num);
1678 msg->flags = msginfo->flags;
1685 flags_info = g_new0(CopyFlagsInfo, 1);
1686 flags_info->num = num;
1687 flags_info->flags = msginfo->flags;
1688 copy_flags_data = g_slist_append(copy_flags_data, flags_info);
1693 void mbox_finished_copy(Folder *folder, FolderItem *dest)
1699 mbox_path = mbox_folder_get_path(dest);
1700 if (mbox_path == NULL)
1703 mbox_cache_synchronize(mbox_path, TRUE);
1705 for(l = copy_flags_data ; l != NULL ; l = g_slist_next(l)) {
1706 CopyFlagsInfo * flags_info = l->data;
1707 struct _message * msg;
1709 msg = mbox_cache_get_msg(mbox_path, flags_info->num);
1711 msg->flags = flags_info->flags;
1715 if (copy_flags_data != NULL) {
1716 cache = mbox_cache_get_mbox(mbox_path);
1717 cache->modification = TRUE;
1720 g_slist_free(copy_flags_data);
1721 copy_flags_data = NULL;
1723 mbox_rewrite(mbox_path);
1728 void mbox_scan_folder(Folder *folder, FolderItem *item)
1735 mbox_path = mbox_folder_get_path(item);
1736 if (mbox_path == NULL)
1739 mbox_cache_synchronize(mbox_path, TRUE);
1741 cached = mbox_cache_get_mbox(mbox_path);
1743 if (cached == NULL) {
1752 n_msg = mbox_cache_get_count(mbox_path);
1755 item->new = item->unread = item->total = 0;
1762 for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ;
1763 l = g_list_next(l)) {
1764 struct _message * msg = (struct _message *) l->data;
1765 if (!MSG_IS_REALLY_DELETED(msg->flags))
1767 if (MSG_IS_NEW(msg->flags) && !MSG_IS_IGNORE_THREAD(msg->flags))
1769 if (MSG_IS_UNREAD(msg->flags) && !MSG_IS_IGNORE_THREAD(msg->flags))
1774 item->unread = unread;
1775 item->total = total;
1778 debug_print(_("Last number in dir %s = %d\n"), mbox_path,
1780 item->last_num = n_msg;
1784 gchar * mbox_get_virtual_path(FolderItem * item)
1789 if (item->parent == NULL) {
1793 gchar * parent_path;
1794 gchar * result_path;
1796 parent_path = mbox_get_virtual_path(item->parent);
1797 if (parent_path == NULL)
1798 result_path = g_strdup(item->name);
1800 result_path = g_strconcat(parent_path,
1803 g_free(parent_path);
1809 static gboolean mbox_write_data(FILE * mbox_fp, FILE * new_fp,
1810 gchar * new_filename, gint size)
1818 while (pos < size) {
1819 if ((size - pos) > (gint) sizeof(buf))
1824 n_read = fread(buf, 1, max, mbox_fp);
1826 if (n_read < max && ferror(mbox_fp)) {
1829 if (fwrite(buf, n_read, 1, new_fp) < 1) {
1830 g_warning(_("writing to %s failed.\n"), new_filename);
1843 static gboolean mbox_write_message(FILE * mbox_fp, FILE * new_fp,
1844 gchar * new_filename,
1845 struct _message * msg)
1848 GPtrArray * headers;
1851 fseek(mbox_fp, msg->header, SEEK_SET);
1853 headers = procheader_get_header_array_asis(mbox_fp);
1855 for (i = 0; i < (gint) headers->len; i++) {
1856 Header * h = g_ptr_array_index(headers, i);
1858 if (!procheader_headername_equal(h->name,
1860 !procheader_headername_equal(h->name,
1862 fwrite(h->name, strlen(h->name),
1864 if (h->name[strlen(h->name) - 1] != ' ')
1865 fwrite(" ", 1, 1, new_fp);
1866 fwrite(h->body, strlen(h->body),
1868 fwrite("\n", 1, 1, new_fp);
1870 procheader_header_free(h);
1871 g_ptr_array_remove_index(headers, i);
1875 g_ptr_array_free(headers, FALSE);
1877 if (!MSG_IS_INVALID(msg->flags)) {
1879 fwrite("Status: ", strlen("Status: "), 1, new_fp);
1880 if (!MSG_IS_UNREAD(msg->flags))
1881 fwrite("R", 1, 1, new_fp);
1882 fwrite("O", 1, 1, new_fp);
1883 fwrite("\n", 1, 1, new_fp);
1885 /* X-Status header */
1886 if (MSG_IS_REALLY_DELETED(msg->flags)
1887 || MSG_IS_MARKED(msg->flags)
1888 || MSG_IS_DELETED(msg->flags)
1889 || MSG_IS_REPLIED(msg->flags)
1890 || MSG_IS_FORWARDED(msg->flags)) {
1891 fwrite("X-Status: ", strlen("X-Status: "), 1, new_fp);
1892 if (MSG_IS_REALLY_DELETED(msg->flags))
1893 fwrite("D", 1, 1, new_fp); /* really deleted */
1895 if (MSG_IS_MARKED(msg->flags))
1896 fwrite("F", 1, 1, new_fp);
1897 if (MSG_IS_DELETED(msg->flags))
1898 fwrite("d", 1, 1, new_fp);
1899 if (MSG_IS_REPLIED(msg->flags))
1900 fwrite("r", 1, 1, new_fp);
1901 if (MSG_IS_FORWARDED(msg->flags))
1902 fwrite("f", 1, 1, new_fp);
1904 fwrite("\n", 1, 1, new_fp);
1908 fwrite("\n", 1, 1, new_fp);
1910 size = msg->end - msg->content;
1911 fseek(mbox_fp, msg->content, SEEK_SET);
1913 return mbox_write_data(mbox_fp, new_fp, new_filename, size);
1916 void mbox_update_mark(Folder * folder, FolderItem * item)
1920 mbox_path = mbox_folder_get_path(item);
1921 if (mbox_path == NULL)
1924 mbox_rewrite(mbox_path);
1928 void mbox_change_flags(Folder * folder, FolderItem * item, MsgInfo * info)
1930 struct _message * msg;
1934 mbox_path = mbox_folder_get_path(item);
1935 if (mbox_path == NULL)
1938 msg = mbox_cache_get_msg(mbox_path, info->msgnum);
1940 cache = mbox_cache_get_mbox(mbox_path);
1944 if ((msg == NULL) || (cache == NULL))
1947 msg->flags = info->flags;
1949 cache->modification = TRUE;
1953 static gboolean mbox_rewrite(gchar * mbox)
1964 msg_list = mbox_cache_get_msg_list(mbox);
1966 cache = mbox_cache_get_mbox(mbox);
1970 if (!cache->modification) {
1971 debug_print(_("no modification - %s\n"), mbox);
1975 debug_print(_("save modification - %s\n"), mbox);
1977 mbox_fp = fopen(mbox, "rb+");
1978 mbox_lockwrite_file(mbox_fp, mbox);
1980 mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE);
1982 new = g_strconcat(mbox, ".", itos((int) mbox), NULL);
1983 new_fp = fopen(new, "wb");
1985 if (change_file_mode_rw(new_fp, new) < 0) {
1986 FILE_OP_ERROR(new, "chmod");
1987 g_warning(_("can't change file mode\n"));
1990 mbox_lockwrite_file(new_fp, new);
1995 msg_list = mbox_cache_get_msg_list(mbox);
1996 for(l = msg_list ; l != NULL ; l = g_list_next(l)) {
1997 struct _message * msg = (struct _message *) l->data;
1998 if (!mbox_write_message(mbox_fp, new_fp, new, msg)) {
2007 if (rename(new, mbox) == -1) {
2008 g_warning(_("can't rename %s to %s\n"), new, mbox);
2009 mbox_unlock_file(new_fp, new);
2011 mbox_unlock_file(mbox_fp, mbox);
2016 if (change_file_mode_rw(new_fp, mbox) < 0) {
2017 FILE_OP_ERROR(new, "chmod");
2018 g_warning(_("can't change file mode\n"));
2021 mbox_unlock_file(new_fp, new);
2025 mbox_unlock_file(mbox_fp, mbox);
2029 debug_print(_("%i messages written - %s\n"), count, mbox);
2031 cache = mbox_cache_get_mbox(mbox);
2036 mbox_cache_synchronize(mbox, FALSE);
2041 static gboolean mbox_purge_deleted(gchar * mbox)
2048 gboolean modification = FALSE;
2052 mbox_cache_synchronize(mbox, TRUE);
2054 msg_list = mbox_cache_get_msg_list(mbox);
2056 for(l = msg_list ; l != NULL ; l = g_list_next(l)) {
2057 struct _message * msg = (struct _message *) l->data;
2058 if (!MSG_IS_INVALID(msg->flags) && MSG_IS_REALLY_DELETED(msg->flags)) {
2059 modification = TRUE;
2064 if (!modification) {
2065 debug_print(_("no deleted messages - %s\n"), mbox);
2069 debug_print(_("purge deleted messages - %s\n"), mbox);
2071 mbox_fp = fopen(mbox, "rb+");
2072 mbox_lockwrite_file(mbox_fp, mbox);
2074 mbox_cache_synchronize_from_file(mbox_fp, mbox, TRUE);
2076 new = g_strconcat(mbox, ".", itos((int) mbox), NULL);
2077 new_fp = fopen(new, "wb");
2079 if (change_file_mode_rw(new_fp, new) < 0) {
2080 FILE_OP_ERROR(new, "chmod");
2081 g_warning(_("can't change file mode\n"));
2084 mbox_lockwrite_file(new_fp, new);
2089 msg_list = mbox_cache_get_msg_list(mbox);
2090 for(l = msg_list ; l != NULL ; l = g_list_next(l)) {
2091 struct _message * msg = (struct _message *) l->data;
2092 if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) {
2093 if (!mbox_write_message(mbox_fp, new_fp, new, msg)) {
2103 if (rename(new, mbox) == -1) {
2104 g_warning(_("can't rename %s to %s\n"), new, mbox);
2105 mbox_unlock_file(new_fp, new);
2107 mbox_unlock_file(mbox_fp, mbox);
2112 if (change_file_mode_rw(new_fp, mbox) < 0) {
2113 FILE_OP_ERROR(new, "chmod");
2114 g_warning(_("can't change file mode\n"));
2117 mbox_unlock_file(new_fp, new);
2121 mbox_unlock_file(mbox_fp, mbox);
2125 debug_print(_("%i messages written - %s\n"), count, mbox);
2127 mbox_cache_synchronize(mbox, FALSE);
2132 #define MAKE_DIR_IF_NOT_EXIST(dir) \
2134 if (!is_dir_exist(dir)) { \
2135 if (is_file_exist(dir)) { \
2136 g_warning(_("File `%s' already exists.\n" \
2137 "Can't create folder."), dir); \
2140 if (mkdir(dir, S_IRWXU) < 0) { \
2141 FILE_OP_ERROR(dir, "mkdir"); \
2144 if (chmod(dir, S_IRWXU) < 0) \
2145 FILE_OP_ERROR(dir, "chmod"); \
2149 gint mbox_create_tree(Folder *folder)
2153 g_return_val_if_fail(folder != NULL, -1);
2155 CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), -1);
2156 rootpath = LOCAL_FOLDER(folder)->rootpath;
2157 MAKE_DIR_IF_NOT_EXIST(rootpath);
2158 CHDIR_RETURN_VAL_IF_FAIL(rootpath, -1);
2163 #undef MAKE_DIR_IF_NOT_EXIST
2165 static gchar * mbox_get_new_path(FolderItem * parent, gchar * name)
2169 if (strchr(name, '/') == NULL) {
2170 if (parent->path != NULL)
2171 path = g_strconcat(parent->path, ".sbd", G_DIR_SEPARATOR_S, name, NULL);
2173 path = g_strdup(name);
2176 path = g_strdup(name);
2181 static gchar * mbox_get_folderitem_name(gchar * name)
2185 foldername = g_strdup(g_basename(name));
2190 FolderItem *mbox_create_folder(Folder *folder, FolderItem *parent,
2194 FolderItem *new_item;
2197 g_return_val_if_fail(folder != NULL, NULL);
2198 g_return_val_if_fail(parent != NULL, NULL);
2199 g_return_val_if_fail(name != NULL, NULL);
2201 path = mbox_get_new_path(parent, (gchar *) name);
2203 foldername = mbox_get_folderitem_name((gchar *) name);
2205 new_item = folder_item_new(foldername, path);
2206 folder_item_append(parent, new_item);
2208 if (!strcmp(name, "inbox")) {
2209 new_item->stype = F_INBOX;
2210 new_item->folder->inbox = new_item;
2211 } else if (!strcmp(name, "outbox")) {
2212 new_item->stype = F_OUTBOX;
2213 new_item->folder->outbox = new_item;
2214 } else if (!strcmp(name, "draft")) {
2215 new_item->stype = F_DRAFT;
2216 new_item->folder->draft = new_item;
2217 } else if (!strcmp(name, "queue")) {
2218 new_item->stype = F_QUEUE;
2219 new_item->folder->queue = new_item;
2220 } else if (!strcmp(name, "trash")) {
2221 new_item->stype = F_TRASH;
2222 new_item->folder->trash = new_item;
2231 gint mbox_rename_folder(Folder *folder, FolderItem *item, const gchar *name)
2236 g_return_val_if_fail(folder != NULL, -1);
2237 g_return_val_if_fail(item != NULL, -1);
2238 g_return_val_if_fail(item->path != NULL, -1);
2239 g_return_val_if_fail(name != NULL, -1);
2241 path = mbox_get_new_path(item->parent, (gchar *) name);
2242 foldername = mbox_get_folderitem_name((gchar *) name);
2244 if (rename(item->path, path) == -1) {
2247 g_warning(_("Cannot rename folder item"));
2255 item->name = foldername;
2261 gint mbox_remove_folder(Folder *folder, FolderItem *item)
2263 g_return_val_if_fail(folder != NULL, -1);
2264 g_return_val_if_fail(item != NULL, -1);
2265 g_return_val_if_fail(item->path != NULL, -1);
2267 folder_item_remove(item);
2271 GSList *mbox_get_num_list(Folder *folder, FolderItem *item)
2280 mbox_path = mbox_folder_get_path(item);
2282 if (mbox_path == NULL)
2285 mbox_purge_deleted(mbox_path);
2287 fp = fopen(mbox_path, "rb");
2294 mbox_lockread_file(fp, mbox_path);
2296 mbox_cache_synchronize_from_file(fp, mbox_path, TRUE);
2298 item->last_num = mbox_cache_get_count(mbox_path);
2300 for(l = mbox_cache_get_msg_list(mbox_path) ; l != NULL ;
2301 l = g_list_next(l)) {
2302 struct _message * msg;
2304 msg = (struct _message *) l->data;
2306 if (MSG_IS_INVALID(msg->flags) || !MSG_IS_REALLY_DELETED(msg->flags)) {
2307 mlist = g_slist_append(mlist, GINT_TO_POINTER(msg->msgnum));
2309 MSG_SET_PERM_FLAGS(msg->flags, MSG_REALLY_DELETED);
2313 mbox_unlock_file(fp, mbox_path);
2322 MsgInfo *mbox_fetch_msginfo(Folder *folder, FolderItem *item, gint num)
2325 struct _message *msg;
2329 g_return_val_if_fail(folder != NULL, NULL);
2330 g_return_val_if_fail(item != NULL, NULL);
2332 mbox_path = mbox_folder_get_path(item);
2334 g_return_val_if_fail(mbox_path != NULL, NULL);
2336 src = fopen(mbox_path, "rb");
2341 mbox_lockread_file(src, mbox_path);
2342 mbox_cache_synchronize_from_file(src, mbox_path, TRUE);
2344 msg = mbox_cache_get_msg(mbox_path, num);
2346 mbox_unlock_file(src, mbox_path);
2352 fseek(src, msg->header, SEEK_SET);
2353 msginfo = mbox_parse_msg(src, msg, item);
2355 mbox_unlock_file(src, mbox_path);
2362 gboolean mbox_check_msgnum_validity(Folder *folder, FolderItem *item)
2364 mboxcache * old_cache;
2365 gboolean scan_new = TRUE;
2369 filename = mbox_folder_get_path(item);
2371 old_cache = mbox_cache_get_mbox(filename);
2373 if (old_cache != NULL) {
2374 if (stat(filename, &s) < 0) {
2375 FILE_OP_ERROR(filename, "stat");
2376 } else if (old_cache->mtime == s.st_mtime) {
2377 debug_print("Folder is not modified.\n");