2 * libEtPan! -- a mail stuff library
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "claws-features.h"
49 #include <sys/types.h>
58 #include "mmapstring.h"
59 #include "mailmbox_parse.h"
61 #include "file-utils.h"
65 http://www.qmail.org/qmail-manual-html/man5/mbox.html
71 /* mbox is a file with a corresponding filename */
73 #define UID_HEADER "X-LibEtPan-UID:"
83 int claws_mailmbox_write_lock(struct claws_mailmbox_folder * folder)
87 if (folder->mb_read_only)
88 return MAILMBOX_ERROR_READONLY;
90 r = maillock_write_lock(folder->mb_filename, folder->mb_fd);
92 return MAILMBOX_NO_ERROR;
94 return MAILMBOX_ERROR_FILE;
97 int claws_mailmbox_write_unlock(struct claws_mailmbox_folder * folder)
101 r = maillock_write_unlock(folder->mb_filename, folder->mb_fd);
103 return MAILMBOX_NO_ERROR;
105 return MAILMBOX_ERROR_FILE;
108 int claws_mailmbox_read_lock(struct claws_mailmbox_folder * folder)
112 r = maillock_read_lock(folder->mb_filename, folder->mb_fd);
114 return MAILMBOX_NO_ERROR;
116 return MAILMBOX_ERROR_FILE;
119 int claws_mailmbox_read_unlock(struct claws_mailmbox_folder * folder)
123 r = maillock_read_unlock(folder->mb_filename, folder->mb_fd);
125 return MAILMBOX_NO_ERROR;
127 return MAILMBOX_ERROR_FILE;
132 map the file into memory.
133 the file must be locked.
136 int claws_mailmbox_map(struct claws_mailmbox_folder * folder)
143 r = g_stat(folder->mb_filename, &buf);
145 debug_print("stat failed %d\n", r);
146 res = MAILMBOX_ERROR_FILE;
150 if (buf.st_size == 0) {
151 folder->mb_mapping = NULL;
152 folder->mb_mapping_size = 0;
153 return MAILMBOX_NO_ERROR;
155 if (folder->mb_read_only)
156 str = (char *) mmap(NULL, buf.st_size, PROT_READ,
157 MAP_PRIVATE, folder->mb_fd, 0);
159 str = (char *) mmap(NULL, buf.st_size, PROT_READ | PROT_WRITE,
160 MAP_SHARED, folder->mb_fd, 0);
161 if (str == MAP_FAILED) {
163 debug_print("map of %lld bytes failed\n", (long long)buf.st_size);
164 res = MAILMBOX_ERROR_FILE;
168 folder->mb_mapping = str;
169 folder->mb_mapping_size = buf.st_size;
171 return MAILMBOX_NO_ERROR;
181 void claws_mailmbox_unmap(struct claws_mailmbox_folder * folder)
183 munmap(folder->mb_mapping, folder->mb_mapping_size);
184 folder->mb_mapping = NULL;
185 folder->mb_mapping_size = 0;
188 void claws_mailmbox_sync(struct claws_mailmbox_folder * folder)
190 msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC);
193 void claws_mailmbox_timestamp(struct claws_mailmbox_folder * folder)
198 r = g_stat(folder->mb_filename, &buf);
200 folder->mb_mtime = (time_t) -1;
202 folder->mb_mtime = buf.st_mtime;
209 int claws_mailmbox_open(struct claws_mailmbox_folder * folder)
214 if (!folder->mb_read_only) {
216 fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
219 if (folder->mb_read_only || (fd < 0)) {
221 fd = open(folder->mb_filename, O_RDONLY);
223 return MAILMBOX_ERROR_FILE_NOT_FOUND;
227 folder->mb_read_only = read_only;
229 return MAILMBOX_NO_ERROR;
236 void claws_mailmbox_close(struct claws_mailmbox_folder * folder)
238 close(folder->mb_fd);
243 static int claws_mailmbox_validate_lock(struct claws_mailmbox_folder * folder,
244 int (* custom_lock)(struct claws_mailmbox_folder *),
245 int (* custom_unlock)(struct claws_mailmbox_folder *))
251 r = g_stat(folder->mb_filename, &buf);
253 buf.st_mtime = (time_t) -1;
256 if ((buf.st_mtime != folder->mb_mtime) ||
257 ((size_t) buf.st_size != folder->mb_mapping_size)) {
260 claws_mailmbox_unmap(folder);
261 claws_mailmbox_close(folder);
263 r = claws_mailmbox_open(folder);
264 if (r != MAILMBOX_NO_ERROR) {
269 r = custom_lock(folder);
270 if (r != MAILMBOX_NO_ERROR) {
275 r = claws_mailmbox_map(folder);
276 if (r != MAILMBOX_NO_ERROR) {
281 r = claws_mailmbox_parse(folder);
282 if (r != MAILMBOX_NO_ERROR) {
287 folder->mb_mtime = buf.st_mtime;
289 return MAILMBOX_NO_ERROR;
292 r = custom_lock(folder);
293 if (r != MAILMBOX_NO_ERROR) {
299 return MAILMBOX_NO_ERROR;
302 custom_unlock(folder);
308 int claws_mailmbox_validate_write_lock(struct claws_mailmbox_folder * folder)
310 return claws_mailmbox_validate_lock(folder,
311 claws_mailmbox_write_lock,
312 claws_mailmbox_write_unlock);
316 int claws_mailmbox_validate_read_lock(struct claws_mailmbox_folder * folder)
318 return claws_mailmbox_validate_lock(folder,
319 claws_mailmbox_read_lock,
320 claws_mailmbox_read_unlock);
324 /* ********************************************************************** */
325 /* append messages */
327 #define MAX_FROM_LINE_SIZE 256
329 static inline size_t get_line(const char * line, size_t length,
330 const char ** pnext_line, size_t * pcount)
340 if (* line == '\r') {
347 if (* line == '\n') {
357 else if (* line == '\n') {
379 TODO : should strip \r\n if any
380 see also in write_fixed_line
383 static inline size_t get_fixed_line_size(const char * line, size_t length,
384 const char ** pnext_line, size_t * pcount,
385 size_t * pfixed_count)
388 const char * next_line;
391 if (!get_line(line, length, &next_line, &count))
396 if (line[0] == 'F') {
397 if (strncmp(line, "From ", 5) == 0)
402 * pnext_line = next_line;
404 * pfixed_count = fixed_count;
409 static size_t get_fixed_message_size(const char * message, size_t size,
410 uint32_t uid, int force_no_uid)
434 if (cur_token + strlen(UID_HEADER) <= size) {
435 if (message[cur_token] == 'X') {
436 if (strncasecmp(message + cur_token, UID_HEADER,
437 strlen(UID_HEADER)) == 0) {
443 r = mailimf_ignore_field_parse(message, size, &cur_token);
445 case MAILIMF_NO_ERROR:
447 fixed_size += cur_token - begin;
449 case MAILIMF_ERROR_PARSE:
460 fixed_size += strlen(UID_HEADER " \r\n");
462 fixed_size += strlen(UID_HEADER " \n");
466 while (tmp_uid >= 10) {
475 left = size - cur_token;
476 next = message + cur_token;
483 if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count))
486 fixed_size += fixed_count;
493 static inline char * write_fixed_line(char * str,
494 const char * line, size_t length,
495 const char ** pnext_line, size_t * pcount)
498 const char * next_line;
500 if (!get_line(line, length, &next_line, &count))
504 if (line[0] == 'F') {
505 if (strncmp(line, "From ", 5) == 0) {
512 memcpy(str, line, count);
514 * pnext_line = next_line;
521 static char * write_fixed_message(char * str,
522 const char * message, size_t size,
523 uint32_t uid, int force_no_uid)
529 const char * cur_src;
543 if (cur_token + strlen(UID_HEADER) <= size) {
544 if (message[cur_token] == 'X') {
545 if (strncasecmp(message + cur_token, UID_HEADER,
546 strlen(UID_HEADER)) == 0) {
552 r = mailimf_ignore_field_parse(message, size, &cur_token);
554 case MAILIMF_NO_ERROR:
556 memcpy(str, message + begin, cur_token - begin);
557 str += cur_token - begin;
560 case MAILIMF_ERROR_PARSE:
570 memcpy(str, UID_HEADER " ", strlen(UID_HEADER " "));
571 str += strlen(UID_HEADER " ");
573 numlen = snprintf(str, 20, "%i\r\n", uid);
575 numlen = snprintf(str, 20, "%i\n", uid);
582 cur_src = message + cur_token;
583 left = size - cur_token;
586 const char * next = NULL;
588 str = write_fixed_line(str, cur_src, left, &next, &count);
597 #define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n"
600 claws_mailmbox_append_message_list_no_lock(struct claws_mailmbox_folder * folder,
605 char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE;
616 if (folder->mb_read_only) {
617 res = MAILMBOX_ERROR_READONLY;
622 from_size = strlen(DEFAULT_FROM_LINE);
623 if (localtime_r(&date, &time_info) != NULL)
624 from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %a %b %_2d %T %Y\n", &time_info);
627 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
628 struct claws_mailmbox_append_info * info;
630 info = carray_get(append_tab, i);
631 extra_size += from_size;
632 extra_size += get_fixed_message_size(info->ai_message, info->ai_size,
633 folder->mb_max_uid + i + 1,
636 extra_size += 2; /* CR LF */
638 extra_size += 1; /* CR LF */
642 left = folder->mb_mapping_size;
645 if (folder->mb_mapping[left - 1] == '\n') {
650 else if (folder->mb_mapping[left - 1] == '\r') {
661 old_size = folder->mb_mapping_size;
662 claws_mailmbox_unmap(folder);
667 extra_size += (2 - crlf_count) * 2;
669 /* Need the number of LFs, not CRLFs */
670 extra_size += (2 - crlf_count) * 1; /* 2 */
674 r = ftruncate(folder->mb_fd, extra_size + old_size);
676 debug_print("ftruncate failed with %d\n", r);
677 claws_mailmbox_map(folder);
678 res = MAILMBOX_ERROR_FILE;
682 r = claws_mailmbox_map(folder);
684 debug_print("claws_mailmbox_map failed with %d\n", r);
685 r = ftruncate(folder->mb_fd, old_size);
687 debug_print("ftruncate failed with %d\n", r);
688 return MAILMBOX_ERROR_FILE;
691 str = folder->mb_mapping + old_size;
694 for(i = 0 ; i < 2 - crlf_count ; i ++) {
704 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
705 struct claws_mailmbox_append_info * info;
707 info = carray_get(append_tab, i);
709 memcpy(str, from_line, from_size);
711 str += strlen(from_line);
713 str = write_fixed_message(str, info->ai_message, info->ai_size,
714 folder->mb_max_uid + i + 1,
725 folder->mb_max_uid += carray_count(append_tab);
727 return MAILMBOX_NO_ERROR;
734 claws_mailmbox_append_message_list(struct claws_mailmbox_folder * folder,
741 r = claws_mailmbox_validate_write_lock(folder);
742 if (r != MAILMBOX_NO_ERROR) {
747 r = claws_mailmbox_expunge_no_lock(folder);
748 if (r != MAILMBOX_NO_ERROR) {
753 cur_token = folder->mb_mapping_size;
755 r = claws_mailmbox_append_message_list_no_lock(folder, append_tab);
756 if (r != MAILMBOX_NO_ERROR) {
761 claws_mailmbox_sync(folder);
763 r = claws_mailmbox_parse_additionnal(folder, &cur_token);
764 if (r != MAILMBOX_NO_ERROR) {
769 claws_mailmbox_timestamp(folder);
771 claws_mailmbox_write_unlock(folder);
773 return MAILMBOX_NO_ERROR;
776 claws_mailmbox_write_unlock(folder);
782 claws_mailmbox_append_message(struct claws_mailmbox_folder * folder,
783 const char * data, size_t len)
786 struct claws_mailmbox_append_info * append_info;
792 res = MAILMBOX_ERROR_MEMORY;
796 append_info = claws_mailmbox_append_info_new(data, len);
797 if (append_info == NULL) {
798 res = MAILMBOX_ERROR_MEMORY;
802 r = carray_add(tab, append_info, NULL);
804 res = MAILMBOX_ERROR_MEMORY;
805 goto free_append_info;
808 r = claws_mailmbox_append_message_list(folder, tab);
810 claws_mailmbox_append_info_free(append_info);
816 claws_mailmbox_append_info_free(append_info);
823 /* ********************************************************************** */
825 int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder * folder,
826 uint32_t num, const char ** result,
829 struct claws_mailmbox_msg_info * info;
836 key.len = sizeof(num);
838 r = chash_get(folder->mb_hash, &key, &data);
840 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
846 if (info->msg_deleted) {
847 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
851 * result = folder->mb_mapping + info->msg_headers;
852 * result_len = info->msg_size - info->msg_start_len;
854 return MAILMBOX_NO_ERROR;
860 int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder * folder,
861 uint32_t num, const char ** result,
864 struct claws_mailmbox_msg_info * info;
871 key.len = sizeof(num);
873 r = chash_get(folder->mb_hash, &key, &data);
875 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
881 if (info->msg_deleted) {
882 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
886 * result = folder->mb_mapping + info->msg_headers;
887 * result_len = info->msg_headers_len;
889 return MAILMBOX_NO_ERROR;
895 int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder * folder,
896 uint32_t num, const char ** result,
899 MMAPString * mmapstr;
907 r = claws_mailmbox_validate_read_lock(folder);
908 if (r != MAILMBOX_NO_ERROR) {
913 r = claws_mailmbox_fetch_msg_no_lock(folder, num, &data, &len);
914 if (r != MAILMBOX_NO_ERROR) {
919 /* size with no uid */
920 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
923 mmapstr = mmap_string_new_len(data, fixed_size);
924 if (mmapstr == NULL) {
925 res = MAILMBOX_ERROR_MEMORY;
929 mmapstr = mmap_string_sized_new(fixed_size);
930 if (mmapstr == NULL) {
931 res = MAILMBOX_ERROR_MEMORY;
935 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
937 mmapstr->len = fixed_size;
939 r = mmap_string_ref(mmapstr);
941 mmap_string_free(mmapstr);
942 res = MAILMBOX_ERROR_MEMORY;
946 * result = mmapstr->str;
947 * result_len = mmapstr->len;
949 claws_mailmbox_read_unlock(folder);
951 return MAILMBOX_NO_ERROR;
954 claws_mailmbox_read_unlock(folder);
959 int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder * folder,
960 uint32_t num, const char ** result,
963 MMAPString * mmapstr;
971 r = claws_mailmbox_validate_read_lock(folder);
972 if (r != MAILMBOX_NO_ERROR) {
977 r = claws_mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len);
978 if (r != MAILMBOX_NO_ERROR) {
984 mmapstr = mmap_string_new_len(data, len);
985 if (mmapstr == NULL) {
986 res = MAILMBOX_ERROR_MEMORY;
990 /* size with no uid */
991 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
993 mmapstr = mmap_string_sized_new(fixed_size);
994 if (mmapstr == NULL) {
995 res = MAILMBOX_ERROR_MEMORY;
999 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
1001 mmapstr->len = fixed_size;
1003 r = mmap_string_ref(mmapstr);
1005 mmap_string_free(mmapstr);
1006 res = MAILMBOX_ERROR_MEMORY;
1010 * result = mmapstr->str;
1011 * result_len = mmapstr->len;
1013 claws_mailmbox_read_unlock(folder);
1015 return MAILMBOX_NO_ERROR;
1018 claws_mailmbox_read_unlock(folder);
1023 void claws_mailmbox_fetch_result_free(char * msg)
1025 mmap_string_unref(msg);
1029 int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder * dest_folder,
1030 struct claws_mailmbox_folder * src_folder,
1035 carray * append_tab;
1038 r = claws_mailmbox_validate_read_lock(src_folder);
1039 if (r != MAILMBOX_NO_ERROR) {
1044 append_tab = carray_new(carray_count(tab));
1045 if (append_tab == NULL) {
1046 res = MAILMBOX_ERROR_MEMORY;
1050 for(i = 0 ; i < carray_count(tab) ; i ++) {
1051 struct claws_mailmbox_append_info * append_info;
1056 uid = * ((uint32_t *) carray_get(tab, i));
1058 r = claws_mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len);
1059 if (r != MAILMBOX_NO_ERROR) {
1064 append_info = claws_mailmbox_append_info_new(data, len);
1065 if (append_info == NULL) {
1066 res = MAILMBOX_ERROR_MEMORY;
1070 r = carray_add(append_tab, append_info, NULL);
1072 claws_mailmbox_append_info_free(append_info);
1073 res = MAILMBOX_ERROR_MEMORY;
1078 r = claws_mailmbox_append_message_list(dest_folder, append_tab);
1079 if (r != MAILMBOX_NO_ERROR) {
1084 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1085 struct claws_mailmbox_append_info * append_info;
1087 append_info = carray_get(append_tab, i);
1088 claws_mailmbox_append_info_free(append_info);
1090 carray_free(append_tab);
1092 claws_mailmbox_read_unlock(src_folder);
1094 return MAILMBOX_NO_ERROR;
1097 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1098 struct claws_mailmbox_append_info * append_info;
1100 append_info = carray_get(append_tab, i);
1101 claws_mailmbox_append_info_free(append_info);
1103 carray_free(append_tab);
1105 claws_mailmbox_read_unlock(src_folder);
1110 int claws_mailmbox_copy_msg(struct claws_mailmbox_folder * dest_folder,
1111 struct claws_mailmbox_folder * src_folder,
1119 tab = carray_new(1);
1121 res = MAILMBOX_ERROR_MEMORY;
1125 puid = malloc(sizeof(* puid));
1127 res = MAILMBOX_ERROR_MEMORY;
1132 r = claws_mailmbox_copy_msg_list(dest_folder, src_folder, tab);
1142 static int claws_mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd,
1143 struct claws_mailmbox_folder * folder,
1144 size_t * result_size)
1154 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1155 struct claws_mailmbox_msg_info * info;
1157 info = carray_get(folder->mb_tab, i);
1159 if (!info->msg_deleted) {
1160 size += info->msg_size + info->msg_padding;
1162 if (!folder->mb_no_uid) {
1163 if (!info->msg_written_uid) {
1167 size += strlen(UID_HEADER " \r\n");
1169 size += strlen(UID_HEADER " \n");
1171 uid = info->msg_uid;
1182 r = ftruncate(dest_fd, size);
1184 res = MAILMBOX_ERROR_FILE;
1189 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0);
1190 if (dest == MAP_FAILED) {
1191 res = MAILMBOX_ERROR_FILE;
1197 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1198 struct claws_mailmbox_msg_info * info;
1200 info = carray_get(folder->mb_tab, i);
1202 if (!info->msg_deleted) {
1203 memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start,
1204 info->msg_headers_len + info->msg_start_len);
1205 cur_offset += info->msg_headers_len + info->msg_start_len;
1207 if (!folder->mb_no_uid) {
1208 if (!info->msg_written_uid) {
1211 memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " "));
1212 cur_offset += strlen(UID_HEADER " ");
1214 numlen = snprintf(dest + cur_offset, size - cur_offset,
1215 "%i\r\n", info->msg_uid);
1217 numlen = snprintf(dest + cur_offset, size - cur_offset,
1218 "%i\n", info->msg_uid);
1220 cur_offset += numlen;
1224 memcpy(dest + cur_offset,
1225 folder->mb_mapping + info->msg_headers + info->msg_headers_len,
1226 info->msg_size - (info->msg_start_len + info->msg_headers_len)
1227 + info->msg_padding);
1229 cur_offset += info->msg_size -
1230 (info->msg_start_len + info->msg_headers_len)
1231 + info->msg_padding;
1237 msync(dest, size, MS_SYNC);
1241 * result_size = size;
1243 return MAILMBOX_NO_ERROR;
1249 int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder * folder)
1251 char tmpfile[PATH_MAX + 8]; /* for the extra Xs */
1257 if (folder->mb_read_only)
1258 return MAILMBOX_ERROR_READONLY;
1260 if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
1261 (!folder->mb_changed)) {
1262 /* no need to expunge */
1263 return MAILMBOX_NO_ERROR;
1266 snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename);
1267 dest_fd = g_mkstemp(tmpfile);
1270 res = MAILMBOX_ERROR_FILE;
1274 r = claws_mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd,
1276 if (r != MAILMBOX_NO_ERROR) {
1283 r = rename(tmpfile, folder->mb_filename);
1289 claws_mailmbox_unmap(folder);
1290 claws_mailmbox_close(folder);
1292 r = claws_mailmbox_open(folder);
1293 if (r != MAILMBOX_NO_ERROR) {
1298 r = claws_mailmbox_map(folder);
1299 if (r != MAILMBOX_NO_ERROR) {
1304 r = claws_mailmbox_parse(folder);
1305 if (r != MAILMBOX_NO_ERROR) {
1310 claws_mailmbox_timestamp(folder);
1312 folder->mb_changed = FALSE;
1313 folder->mb_deleted_count = 0;
1315 return MAILMBOX_NO_ERROR;
1324 int claws_mailmbox_expunge(struct claws_mailmbox_folder * folder)
1329 r = claws_mailmbox_validate_write_lock(folder);
1330 if (r != MAILMBOX_NO_ERROR) {
1335 r = claws_mailmbox_expunge_no_lock(folder);
1338 claws_mailmbox_write_unlock(folder);
1343 int claws_mailmbox_delete_msg(struct claws_mailmbox_folder * folder, uint32_t uid)
1345 struct claws_mailmbox_msg_info * info;
1351 if (folder->mb_read_only) {
1352 res = MAILMBOX_ERROR_READONLY;
1357 key.len = sizeof(uid);
1359 r = chash_get(folder->mb_hash, &key, &data);
1361 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1367 if (info->msg_deleted) {
1368 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1372 info->msg_deleted = TRUE;
1373 folder->mb_changed = TRUE;
1374 folder->mb_deleted_count ++;
1376 return MAILMBOX_NO_ERROR;
1396 int claws_mailmbox_init(const char * filename,
1399 uint32_t default_written_uid,
1400 struct claws_mailmbox_folder ** result_folder)
1402 struct claws_mailmbox_folder * folder;
1406 folder = claws_mailmbox_folder_new(filename);
1407 if (folder == NULL) {
1408 debug_print("folder is null for %s\n", filename);
1409 res = MAILMBOX_ERROR_MEMORY;
1412 folder->mb_no_uid = force_no_uid;
1413 folder->mb_read_only = force_readonly;
1414 folder->mb_written_uid = default_written_uid;
1416 folder->mb_changed = FALSE;
1417 folder->mb_deleted_count = 0;
1419 r = claws_mailmbox_open(folder);
1420 if (r != MAILMBOX_NO_ERROR) {
1421 debug_print("folder can't be opened %d\n", r);
1426 r = claws_mailmbox_map(folder);
1427 if (r != MAILMBOX_NO_ERROR) {
1428 debug_print("folder can't be mapped %d\n", r);
1433 r = claws_mailmbox_validate_read_lock(folder);
1434 if (r != MAILMBOX_NO_ERROR) {
1435 debug_print("folder can't be locked %d\n", r);
1440 claws_mailmbox_read_unlock(folder);
1442 * result_folder = folder;
1444 return MAILMBOX_NO_ERROR;
1447 claws_mailmbox_unmap(folder);
1449 claws_mailmbox_close(folder);
1451 claws_mailmbox_folder_free(folder);
1466 void claws_mailmbox_done(struct claws_mailmbox_folder * folder)
1468 if (!folder->mb_read_only)
1469 claws_mailmbox_expunge(folder);
1471 claws_mailmbox_unmap(folder);
1472 claws_mailmbox_close(folder);
1474 claws_mailmbox_folder_free(folder);