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
44 #include <sys/types.h>
53 #include "mmapstring.h"
54 #include "mailmbox_parse.h"
59 http://www.qmail.org/qmail-manual-html/man5/mbox.html
65 /* mbox is a file with a corresponding filename */
67 #define UID_HEADER "X-LibEtPan-UID:"
77 int claws_mailmbox_write_lock(struct claws_mailmbox_folder * folder)
81 if (folder->mb_read_only)
82 return MAILMBOX_ERROR_READONLY;
84 r = maillock_write_lock(folder->mb_filename, folder->mb_fd);
86 return MAILMBOX_NO_ERROR;
88 return MAILMBOX_ERROR_FILE;
91 int claws_mailmbox_write_unlock(struct claws_mailmbox_folder * folder)
95 r = maillock_write_unlock(folder->mb_filename, folder->mb_fd);
97 return MAILMBOX_NO_ERROR;
99 return MAILMBOX_ERROR_FILE;
102 int claws_mailmbox_read_lock(struct claws_mailmbox_folder * folder)
106 r = maillock_read_lock(folder->mb_filename, folder->mb_fd);
108 return MAILMBOX_NO_ERROR;
110 return MAILMBOX_ERROR_FILE;
113 int claws_mailmbox_read_unlock(struct claws_mailmbox_folder * folder)
117 r = maillock_read_unlock(folder->mb_filename, folder->mb_fd);
119 return MAILMBOX_NO_ERROR;
121 return MAILMBOX_ERROR_FILE;
126 map the file into memory.
127 the file must be locked.
130 int claws_mailmbox_map(struct claws_mailmbox_folder * folder)
137 r = g_stat(folder->mb_filename, &buf);
139 debug_print("stat failed %d\n", r);
140 res = MAILMBOX_ERROR_FILE;
144 if (buf.st_size == 0) {
145 folder->mb_mapping = NULL;
146 folder->mb_mapping_size = 0;
147 return MAILMBOX_NO_ERROR;
149 if (folder->mb_read_only)
150 str = (char *) mmap(NULL, buf.st_size, PROT_READ,
151 MAP_PRIVATE, folder->mb_fd, 0);
153 str = (char *) mmap(NULL, buf.st_size, PROT_READ | PROT_WRITE,
154 MAP_SHARED, folder->mb_fd, 0);
155 if (str == MAP_FAILED) {
157 debug_print("map of %lld bytes failed\n", (long long)buf.st_size);
158 res = MAILMBOX_ERROR_FILE;
162 folder->mb_mapping = str;
163 folder->mb_mapping_size = buf.st_size;
165 return MAILMBOX_NO_ERROR;
175 void claws_mailmbox_unmap(struct claws_mailmbox_folder * folder)
177 munmap(folder->mb_mapping, folder->mb_mapping_size);
178 folder->mb_mapping = NULL;
179 folder->mb_mapping_size = 0;
182 void claws_mailmbox_sync(struct claws_mailmbox_folder * folder)
184 msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC);
187 void claws_mailmbox_timestamp(struct claws_mailmbox_folder * folder)
192 r = g_stat(folder->mb_filename, &buf);
194 folder->mb_mtime = (time_t) -1;
196 folder->mb_mtime = buf.st_mtime;
203 int claws_mailmbox_open(struct claws_mailmbox_folder * folder)
208 if (!folder->mb_read_only) {
210 fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
213 if (folder->mb_read_only || (fd < 0)) {
215 fd = open(folder->mb_filename, O_RDONLY);
217 return MAILMBOX_ERROR_FILE_NOT_FOUND;
221 folder->mb_read_only = read_only;
223 return MAILMBOX_NO_ERROR;
230 void claws_mailmbox_close(struct claws_mailmbox_folder * folder)
232 close(folder->mb_fd);
237 static int claws_mailmbox_validate_lock(struct claws_mailmbox_folder * folder,
238 int (* custom_lock)(struct claws_mailmbox_folder *),
239 int (* custom_unlock)(struct claws_mailmbox_folder *))
245 r = g_stat(folder->mb_filename, &buf);
247 buf.st_mtime = (time_t) -1;
250 if ((buf.st_mtime != folder->mb_mtime) ||
251 ((size_t) buf.st_size != folder->mb_mapping_size)) {
254 claws_mailmbox_unmap(folder);
255 claws_mailmbox_close(folder);
257 r = claws_mailmbox_open(folder);
258 if (r != MAILMBOX_NO_ERROR) {
263 r = custom_lock(folder);
264 if (r != MAILMBOX_NO_ERROR) {
269 r = claws_mailmbox_map(folder);
270 if (r != MAILMBOX_NO_ERROR) {
275 r = claws_mailmbox_parse(folder);
276 if (r != MAILMBOX_NO_ERROR) {
281 folder->mb_mtime = buf.st_mtime;
283 return MAILMBOX_NO_ERROR;
286 r = custom_lock(folder);
287 if (r != MAILMBOX_NO_ERROR) {
293 return MAILMBOX_NO_ERROR;
296 custom_unlock(folder);
302 int claws_mailmbox_validate_write_lock(struct claws_mailmbox_folder * folder)
304 return claws_mailmbox_validate_lock(folder,
305 claws_mailmbox_write_lock,
306 claws_mailmbox_write_unlock);
310 int claws_mailmbox_validate_read_lock(struct claws_mailmbox_folder * folder)
312 return claws_mailmbox_validate_lock(folder,
313 claws_mailmbox_read_lock,
314 claws_mailmbox_read_unlock);
318 /* ********************************************************************** */
319 /* append messages */
321 #define MAX_FROM_LINE_SIZE 256
323 static inline size_t get_line(const char * line, size_t length,
324 const char ** pnext_line, size_t * pcount)
334 if (* line == '\r') {
341 if (* line == '\n') {
351 else if (* line == '\n') {
373 TODO : should strip \r\n if any
374 see also in write_fixed_line
377 static inline size_t get_fixed_line_size(const char * line, size_t length,
378 const char ** pnext_line, size_t * pcount,
379 size_t * pfixed_count)
382 const char * next_line;
385 if (!get_line(line, length, &next_line, &count))
390 if (line[0] == 'F') {
391 if (strncmp(line, "From ", 5) == 0)
396 * pnext_line = next_line;
398 * pfixed_count = fixed_count;
403 static size_t get_fixed_message_size(const char * message, size_t size,
404 uint32_t uid, int force_no_uid)
428 if (cur_token + strlen(UID_HEADER) <= size) {
429 if (message[cur_token] == 'X') {
430 if (strncasecmp(message + cur_token, UID_HEADER,
431 strlen(UID_HEADER)) == 0) {
437 r = mailimf_ignore_field_parse(message, size, &cur_token);
439 case MAILIMF_NO_ERROR:
441 fixed_size += cur_token - begin;
443 case MAILIMF_ERROR_PARSE:
454 fixed_size += strlen(UID_HEADER " \r\n");
456 fixed_size += strlen(UID_HEADER " \n");
460 while (tmp_uid >= 10) {
469 left = size - cur_token;
470 next = message + cur_token;
477 if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count))
480 fixed_size += fixed_count;
487 static inline char * write_fixed_line(char * str,
488 const char * line, size_t length,
489 const char ** pnext_line, size_t * pcount)
492 const char * next_line;
494 if (!get_line(line, length, &next_line, &count))
498 if (line[0] == 'F') {
499 if (strncmp(line, "From ", 5) == 0) {
506 memcpy(str, line, count);
508 * pnext_line = next_line;
515 static char * write_fixed_message(char * str,
516 const char * message, size_t size,
517 uint32_t uid, int force_no_uid)
523 const char * cur_src;
537 if (cur_token + strlen(UID_HEADER) <= size) {
538 if (message[cur_token] == 'X') {
539 if (strncasecmp(message + cur_token, UID_HEADER,
540 strlen(UID_HEADER)) == 0) {
546 r = mailimf_ignore_field_parse(message, size, &cur_token);
548 case MAILIMF_NO_ERROR:
550 memcpy(str, message + begin, cur_token - begin);
551 str += cur_token - begin;
554 case MAILIMF_ERROR_PARSE:
564 memcpy(str, UID_HEADER " ", strlen(UID_HEADER " "));
565 str += strlen(UID_HEADER " ");
567 numlen = snprintf(str, 20, "%i\r\n", uid);
569 numlen = snprintf(str, 20, "%i\n", uid);
576 cur_src = message + cur_token;
577 left = size - cur_token;
580 const char * next = NULL;
582 str = write_fixed_line(str, cur_src, left, &next, &count);
591 #define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n"
594 claws_mailmbox_append_message_list_no_lock(struct claws_mailmbox_folder * folder,
599 char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE;
610 if (folder->mb_read_only) {
611 res = MAILMBOX_ERROR_READONLY;
616 from_size = strlen(DEFAULT_FROM_LINE);
617 if (localtime_r(&date, &time_info) != NULL)
618 from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %a %b %_2d %T %Y\n", &time_info);
621 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
622 struct claws_mailmbox_append_info * info;
624 info = carray_get(append_tab, i);
625 extra_size += from_size;
626 extra_size += get_fixed_message_size(info->ai_message, info->ai_size,
627 folder->mb_max_uid + i + 1,
630 extra_size += 2; /* CR LF */
632 extra_size += 1; /* CR LF */
636 left = folder->mb_mapping_size;
639 if (folder->mb_mapping[left - 1] == '\n') {
644 else if (folder->mb_mapping[left - 1] == '\r') {
655 old_size = folder->mb_mapping_size;
656 claws_mailmbox_unmap(folder);
661 extra_size += (2 - crlf_count) * 2;
663 /* Need the number of LFs, not CRLFs */
664 extra_size += (2 - crlf_count) * 1; /* 2 */
668 r = ftruncate(folder->mb_fd, extra_size + old_size);
670 debug_print("ftruncate failed with %d\n", r);
671 claws_mailmbox_map(folder);
672 res = MAILMBOX_ERROR_FILE;
676 r = claws_mailmbox_map(folder);
678 debug_print("claws_mailmbox_map failed with %d\n", r);
679 r = ftruncate(folder->mb_fd, old_size);
681 debug_print("ftruncate failed with %d\n", r);
682 return MAILMBOX_ERROR_FILE;
685 str = folder->mb_mapping + old_size;
688 for(i = 0 ; i < 2 - crlf_count ; i ++) {
698 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
699 struct claws_mailmbox_append_info * info;
701 info = carray_get(append_tab, i);
703 memcpy(str, from_line, from_size);
705 str += strlen(from_line);
707 str = write_fixed_message(str, info->ai_message, info->ai_size,
708 folder->mb_max_uid + i + 1,
719 folder->mb_max_uid += carray_count(append_tab);
721 return MAILMBOX_NO_ERROR;
728 claws_mailmbox_append_message_list(struct claws_mailmbox_folder * folder,
735 r = claws_mailmbox_validate_write_lock(folder);
736 if (r != MAILMBOX_NO_ERROR) {
741 r = claws_mailmbox_expunge_no_lock(folder);
742 if (r != MAILMBOX_NO_ERROR) {
747 cur_token = folder->mb_mapping_size;
749 r = claws_mailmbox_append_message_list_no_lock(folder, append_tab);
750 if (r != MAILMBOX_NO_ERROR) {
755 claws_mailmbox_sync(folder);
757 r = claws_mailmbox_parse_additionnal(folder, &cur_token);
758 if (r != MAILMBOX_NO_ERROR) {
763 claws_mailmbox_timestamp(folder);
765 claws_mailmbox_write_unlock(folder);
767 return MAILMBOX_NO_ERROR;
770 claws_mailmbox_write_unlock(folder);
776 claws_mailmbox_append_message(struct claws_mailmbox_folder * folder,
777 const char * data, size_t len)
780 struct claws_mailmbox_append_info * append_info;
786 res = MAILMBOX_ERROR_MEMORY;
790 append_info = claws_mailmbox_append_info_new(data, len);
791 if (append_info == NULL) {
792 res = MAILMBOX_ERROR_MEMORY;
796 r = carray_add(tab, append_info, NULL);
798 res = MAILMBOX_ERROR_MEMORY;
799 goto free_append_info;
802 r = claws_mailmbox_append_message_list(folder, tab);
804 claws_mailmbox_append_info_free(append_info);
810 claws_mailmbox_append_info_free(append_info);
817 /* ********************************************************************** */
819 int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder * folder,
820 uint32_t num, const char ** result,
823 struct claws_mailmbox_msg_info * info;
830 key.len = sizeof(num);
832 r = chash_get(folder->mb_hash, &key, &data);
834 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
840 if (info->msg_deleted) {
841 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
845 * result = folder->mb_mapping + info->msg_headers;
846 * result_len = info->msg_size - info->msg_start_len;
848 return MAILMBOX_NO_ERROR;
854 int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder * folder,
855 uint32_t num, const char ** result,
858 struct claws_mailmbox_msg_info * info;
865 key.len = sizeof(num);
867 r = chash_get(folder->mb_hash, &key, &data);
869 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
875 if (info->msg_deleted) {
876 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
880 * result = folder->mb_mapping + info->msg_headers;
881 * result_len = info->msg_headers_len;
883 return MAILMBOX_NO_ERROR;
889 int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder * folder,
890 uint32_t num, const char ** result,
893 MMAPString * mmapstr;
901 r = claws_mailmbox_validate_read_lock(folder);
902 if (r != MAILMBOX_NO_ERROR) {
907 r = claws_mailmbox_fetch_msg_no_lock(folder, num, &data, &len);
908 if (r != MAILMBOX_NO_ERROR) {
913 /* size with no uid */
914 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
917 mmapstr = mmap_string_new_len(data, fixed_size);
918 if (mmapstr == NULL) {
919 res = MAILMBOX_ERROR_MEMORY;
923 mmapstr = mmap_string_sized_new(fixed_size);
924 if (mmapstr == NULL) {
925 res = MAILMBOX_ERROR_MEMORY;
929 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
931 mmapstr->len = fixed_size;
933 r = mmap_string_ref(mmapstr);
935 mmap_string_free(mmapstr);
936 res = MAILMBOX_ERROR_MEMORY;
940 * result = mmapstr->str;
941 * result_len = mmapstr->len;
943 claws_mailmbox_read_unlock(folder);
945 return MAILMBOX_NO_ERROR;
948 claws_mailmbox_read_unlock(folder);
953 int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder * folder,
954 uint32_t num, const char ** result,
957 MMAPString * mmapstr;
965 r = claws_mailmbox_validate_read_lock(folder);
966 if (r != MAILMBOX_NO_ERROR) {
971 r = claws_mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len);
972 if (r != MAILMBOX_NO_ERROR) {
978 mmapstr = mmap_string_new_len(data, len);
979 if (mmapstr == NULL) {
980 res = MAILMBOX_ERROR_MEMORY;
984 /* size with no uid */
985 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
987 mmapstr = mmap_string_sized_new(fixed_size);
988 if (mmapstr == NULL) {
989 res = MAILMBOX_ERROR_MEMORY;
993 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
995 mmapstr->len = fixed_size;
997 r = mmap_string_ref(mmapstr);
999 mmap_string_free(mmapstr);
1000 res = MAILMBOX_ERROR_MEMORY;
1004 * result = mmapstr->str;
1005 * result_len = mmapstr->len;
1007 claws_mailmbox_read_unlock(folder);
1009 return MAILMBOX_NO_ERROR;
1012 claws_mailmbox_read_unlock(folder);
1017 void claws_mailmbox_fetch_result_free(char * msg)
1019 mmap_string_unref(msg);
1023 int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder * dest_folder,
1024 struct claws_mailmbox_folder * src_folder,
1029 carray * append_tab;
1032 r = claws_mailmbox_validate_read_lock(src_folder);
1033 if (r != MAILMBOX_NO_ERROR) {
1038 append_tab = carray_new(carray_count(tab));
1039 if (append_tab == NULL) {
1040 res = MAILMBOX_ERROR_MEMORY;
1044 for(i = 0 ; i < carray_count(tab) ; i ++) {
1045 struct claws_mailmbox_append_info * append_info;
1050 uid = * ((uint32_t *) carray_get(tab, i));
1052 r = claws_mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len);
1053 if (r != MAILMBOX_NO_ERROR) {
1058 append_info = claws_mailmbox_append_info_new(data, len);
1059 if (append_info == NULL) {
1060 res = MAILMBOX_ERROR_MEMORY;
1064 r = carray_add(append_tab, append_info, NULL);
1066 claws_mailmbox_append_info_free(append_info);
1067 res = MAILMBOX_ERROR_MEMORY;
1072 r = claws_mailmbox_append_message_list(dest_folder, append_tab);
1073 if (r != MAILMBOX_NO_ERROR) {
1078 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1079 struct claws_mailmbox_append_info * append_info;
1081 append_info = carray_get(append_tab, i);
1082 claws_mailmbox_append_info_free(append_info);
1084 carray_free(append_tab);
1086 claws_mailmbox_read_unlock(src_folder);
1088 return MAILMBOX_NO_ERROR;
1091 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1092 struct claws_mailmbox_append_info * append_info;
1094 append_info = carray_get(append_tab, i);
1095 claws_mailmbox_append_info_free(append_info);
1097 carray_free(append_tab);
1099 claws_mailmbox_read_unlock(src_folder);
1104 int claws_mailmbox_copy_msg(struct claws_mailmbox_folder * dest_folder,
1105 struct claws_mailmbox_folder * src_folder,
1113 tab = carray_new(1);
1115 res = MAILMBOX_ERROR_MEMORY;
1119 puid = malloc(sizeof(* puid));
1121 res = MAILMBOX_ERROR_MEMORY;
1126 r = claws_mailmbox_copy_msg_list(dest_folder, src_folder, tab);
1136 static int claws_mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd,
1137 struct claws_mailmbox_folder * folder,
1138 size_t * result_size)
1148 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1149 struct claws_mailmbox_msg_info * info;
1151 info = carray_get(folder->mb_tab, i);
1153 if (!info->msg_deleted) {
1154 size += info->msg_size + info->msg_padding;
1156 if (!folder->mb_no_uid) {
1157 if (!info->msg_written_uid) {
1161 size += strlen(UID_HEADER " \r\n");
1163 size += strlen(UID_HEADER " \n");
1165 uid = info->msg_uid;
1176 r = ftruncate(dest_fd, size);
1178 res = MAILMBOX_ERROR_FILE;
1183 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0);
1184 if (dest == MAP_FAILED) {
1185 res = MAILMBOX_ERROR_FILE;
1191 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1192 struct claws_mailmbox_msg_info * info;
1194 info = carray_get(folder->mb_tab, i);
1196 if (!info->msg_deleted) {
1197 memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start,
1198 info->msg_headers_len + info->msg_start_len);
1199 cur_offset += info->msg_headers_len + info->msg_start_len;
1201 if (!folder->mb_no_uid) {
1202 if (!info->msg_written_uid) {
1205 memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " "));
1206 cur_offset += strlen(UID_HEADER " ");
1208 numlen = snprintf(dest + cur_offset, size - cur_offset,
1209 "%i\r\n", info->msg_uid);
1211 numlen = snprintf(dest + cur_offset, size - cur_offset,
1212 "%i\n", info->msg_uid);
1214 cur_offset += numlen;
1218 memcpy(dest + cur_offset,
1219 folder->mb_mapping + info->msg_headers + info->msg_headers_len,
1220 info->msg_size - (info->msg_start_len + info->msg_headers_len)
1221 + info->msg_padding);
1223 cur_offset += info->msg_size -
1224 (info->msg_start_len + info->msg_headers_len)
1225 + info->msg_padding;
1231 msync(dest, size, MS_SYNC);
1235 * result_size = size;
1237 return MAILMBOX_NO_ERROR;
1243 int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder * folder)
1245 char tmpfile[PATH_MAX];
1251 if (folder->mb_read_only)
1252 return MAILMBOX_ERROR_READONLY;
1254 if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
1255 (!folder->mb_changed)) {
1256 /* no need to expunge */
1257 return MAILMBOX_NO_ERROR;
1260 snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename);
1261 dest_fd = g_mkstemp(tmpfile);
1264 res = MAILMBOX_ERROR_FILE;
1268 r = claws_mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd,
1270 if (r != MAILMBOX_NO_ERROR) {
1277 r = rename(tmpfile, folder->mb_filename);
1283 claws_mailmbox_unmap(folder);
1284 claws_mailmbox_close(folder);
1286 r = claws_mailmbox_open(folder);
1287 if (r != MAILMBOX_NO_ERROR) {
1292 r = claws_mailmbox_map(folder);
1293 if (r != MAILMBOX_NO_ERROR) {
1298 r = claws_mailmbox_parse(folder);
1299 if (r != MAILMBOX_NO_ERROR) {
1304 claws_mailmbox_timestamp(folder);
1306 folder->mb_changed = FALSE;
1307 folder->mb_deleted_count = 0;
1309 return MAILMBOX_NO_ERROR;
1318 int claws_mailmbox_expunge(struct claws_mailmbox_folder * folder)
1323 r = claws_mailmbox_validate_write_lock(folder);
1324 if (r != MAILMBOX_NO_ERROR) {
1329 r = claws_mailmbox_expunge_no_lock(folder);
1332 claws_mailmbox_write_unlock(folder);
1337 int claws_mailmbox_delete_msg(struct claws_mailmbox_folder * folder, uint32_t uid)
1339 struct claws_mailmbox_msg_info * info;
1345 if (folder->mb_read_only) {
1346 res = MAILMBOX_ERROR_READONLY;
1351 key.len = sizeof(uid);
1353 r = chash_get(folder->mb_hash, &key, &data);
1355 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1361 if (info->msg_deleted) {
1362 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1366 info->msg_deleted = TRUE;
1367 folder->mb_changed = TRUE;
1368 folder->mb_deleted_count ++;
1370 return MAILMBOX_NO_ERROR;
1390 int claws_mailmbox_init(const char * filename,
1393 uint32_t default_written_uid,
1394 struct claws_mailmbox_folder ** result_folder)
1396 struct claws_mailmbox_folder * folder;
1400 folder = claws_mailmbox_folder_new(filename);
1401 if (folder == NULL) {
1402 debug_print("folder is null for %s\n", filename);
1403 res = MAILMBOX_ERROR_MEMORY;
1406 folder->mb_no_uid = force_no_uid;
1407 folder->mb_read_only = force_readonly;
1408 folder->mb_written_uid = default_written_uid;
1410 folder->mb_changed = FALSE;
1411 folder->mb_deleted_count = 0;
1413 r = claws_mailmbox_open(folder);
1414 if (r != MAILMBOX_NO_ERROR) {
1415 debug_print("folder can't be opened %d\n", r);
1420 r = claws_mailmbox_map(folder);
1421 if (r != MAILMBOX_NO_ERROR) {
1422 debug_print("folder can't be mapped %d\n", r);
1427 r = claws_mailmbox_validate_read_lock(folder);
1428 if (r != MAILMBOX_NO_ERROR) {
1429 debug_print("folder can't be locked %d\n", r);
1434 claws_mailmbox_read_unlock(folder);
1436 * result_folder = folder;
1438 return MAILMBOX_NO_ERROR;
1441 claws_mailmbox_unmap(folder);
1443 claws_mailmbox_close(folder);
1445 claws_mailmbox_folder_free(folder);
1460 void claws_mailmbox_done(struct claws_mailmbox_folder * folder)
1462 if (!folder->mb_read_only)
1463 claws_mailmbox_expunge(folder);
1465 claws_mailmbox_unmap(folder);
1466 claws_mailmbox_close(folder);
1468 claws_mailmbox_folder_free(folder);