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 = 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 %lu bytes failed\n", 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 = 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 = 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)
524 const char * cur_src;
540 if (cur_token + strlen(UID_HEADER) <= size) {
541 if (message[cur_token] == 'X') {
542 if (strncasecmp(message + cur_token, UID_HEADER,
543 strlen(UID_HEADER)) == 0) {
549 r = mailimf_ignore_field_parse(message, size, &cur_token);
551 case MAILIMF_NO_ERROR:
553 memcpy(str, message + begin, cur_token - begin);
554 str += cur_token - begin;
557 case MAILIMF_ERROR_PARSE:
567 memcpy(str, UID_HEADER " ", strlen(UID_HEADER " "));
568 str += strlen(UID_HEADER " ");
570 numlen = snprintf(str, 20, "%i\r\n", uid);
572 numlen = snprintf(str, 20, "%i\n", uid);
579 cur_src = message + cur_token;
580 left = size - cur_token;
583 const char * next = NULL;
585 str = write_fixed_line(str, cur_src, left, &next, &count);
594 #define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n"
597 claws_mailmbox_append_message_list_no_lock(struct claws_mailmbox_folder * folder,
602 char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE;
614 if (folder->mb_read_only) {
615 res = MAILMBOX_ERROR_READONLY;
620 from_size = strlen(DEFAULT_FROM_LINE);
621 if (localtime_r(&date, &time_info) != NULL)
622 from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info);
624 maxuid = /* */ folder->mb_max_uid;
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 ftruncate(folder->mb_fd, old_size);
686 return MAILMBOX_ERROR_FILE;
689 str = folder->mb_mapping + old_size;
692 for(i = 0 ; i < 2 - crlf_count ; i ++) {
702 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
703 struct claws_mailmbox_append_info * info;
705 info = carray_get(append_tab, i);
707 memcpy(str, from_line, from_size);
709 str += strlen(from_line);
711 str = write_fixed_message(str, info->ai_message, info->ai_size,
712 folder->mb_max_uid + i + 1,
723 folder->mb_max_uid += carray_count(append_tab);
725 return MAILMBOX_NO_ERROR;
732 claws_mailmbox_append_message_list(struct claws_mailmbox_folder * folder,
739 r = claws_mailmbox_validate_write_lock(folder);
740 if (r != MAILMBOX_NO_ERROR) {
745 r = claws_mailmbox_expunge_no_lock(folder);
746 if (r != MAILMBOX_NO_ERROR) {
751 cur_token = folder->mb_mapping_size;
753 r = claws_mailmbox_append_message_list_no_lock(folder, append_tab);
754 if (r != MAILMBOX_NO_ERROR) {
759 claws_mailmbox_sync(folder);
761 r = claws_mailmbox_parse_additionnal(folder, &cur_token);
762 if (r != MAILMBOX_NO_ERROR) {
767 claws_mailmbox_timestamp(folder);
769 claws_mailmbox_write_unlock(folder);
771 return MAILMBOX_NO_ERROR;
774 claws_mailmbox_write_unlock(folder);
780 claws_mailmbox_append_message(struct claws_mailmbox_folder * folder,
781 const char * data, size_t len)
784 struct claws_mailmbox_append_info * append_info;
790 res = MAILMBOX_ERROR_MEMORY;
794 append_info = claws_mailmbox_append_info_new(data, len);
795 if (append_info == NULL) {
796 res = MAILMBOX_ERROR_MEMORY;
800 r = carray_add(tab, append_info, NULL);
802 res = MAILMBOX_ERROR_MEMORY;
803 goto free_append_info;
806 r = claws_mailmbox_append_message_list(folder, tab);
808 claws_mailmbox_append_info_free(append_info);
814 claws_mailmbox_append_info_free(append_info);
821 /* ********************************************************************** */
823 int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder * folder,
824 uint32_t num, const char ** result,
827 struct claws_mailmbox_msg_info * info;
834 key.len = sizeof(num);
836 r = chash_get(folder->mb_hash, &key, &data);
838 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
844 if (info->msg_deleted) {
845 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
849 * result = folder->mb_mapping + info->msg_headers;
850 * result_len = info->msg_size - info->msg_start_len;
852 return MAILMBOX_NO_ERROR;
858 int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder * folder,
859 uint32_t num, const char ** result,
862 struct claws_mailmbox_msg_info * info;
869 key.len = sizeof(num);
871 r = chash_get(folder->mb_hash, &key, &data);
873 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
879 if (info->msg_deleted) {
880 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
884 * result = folder->mb_mapping + info->msg_headers;
885 * result_len = info->msg_headers_len;
887 return MAILMBOX_NO_ERROR;
893 int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder * folder,
894 uint32_t num, const char ** result,
897 MMAPString * mmapstr;
905 r = claws_mailmbox_validate_read_lock(folder);
906 if (r != MAILMBOX_NO_ERROR) {
911 r = claws_mailmbox_fetch_msg_no_lock(folder, num, &data, &len);
912 if (r != MAILMBOX_NO_ERROR) {
917 /* size with no uid */
918 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
921 mmapstr = mmap_string_new_len(data, fixed_size);
922 if (mmapstr == NULL) {
923 res = MAILMBOX_ERROR_MEMORY;
927 mmapstr = mmap_string_sized_new(fixed_size);
928 if (mmapstr == NULL) {
929 res = MAILMBOX_ERROR_MEMORY;
933 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
935 mmapstr->len = fixed_size;
937 r = mmap_string_ref(mmapstr);
939 mmap_string_free(mmapstr);
940 res = MAILMBOX_ERROR_MEMORY;
944 * result = mmapstr->str;
945 * result_len = mmapstr->len;
947 claws_mailmbox_read_unlock(folder);
949 return MAILMBOX_NO_ERROR;
952 claws_mailmbox_read_unlock(folder);
957 int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder * folder,
958 uint32_t num, const char ** result,
961 MMAPString * mmapstr;
969 r = claws_mailmbox_validate_read_lock(folder);
970 if (r != MAILMBOX_NO_ERROR) {
975 r = claws_mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len);
976 if (r != MAILMBOX_NO_ERROR) {
982 mmapstr = mmap_string_new_len(data, len);
983 if (mmapstr == NULL) {
984 res = MAILMBOX_ERROR_MEMORY;
988 /* size with no uid */
989 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
991 mmapstr = mmap_string_sized_new(fixed_size);
992 if (mmapstr == NULL) {
993 res = MAILMBOX_ERROR_MEMORY;
997 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
999 mmapstr->len = fixed_size;
1001 r = mmap_string_ref(mmapstr);
1003 mmap_string_free(mmapstr);
1004 res = MAILMBOX_ERROR_MEMORY;
1008 * result = mmapstr->str;
1009 * result_len = mmapstr->len;
1011 claws_mailmbox_read_unlock(folder);
1013 return MAILMBOX_NO_ERROR;
1016 claws_mailmbox_read_unlock(folder);
1021 void claws_mailmbox_fetch_result_free(char * msg)
1023 mmap_string_unref(msg);
1027 int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder * dest_folder,
1028 struct claws_mailmbox_folder * src_folder,
1033 carray * append_tab;
1036 r = claws_mailmbox_validate_read_lock(src_folder);
1037 if (r != MAILMBOX_NO_ERROR) {
1042 append_tab = carray_new(carray_count(tab));
1043 if (append_tab == NULL) {
1044 res = MAILMBOX_ERROR_MEMORY;
1048 for(i = 0 ; i < carray_count(tab) ; i ++) {
1049 struct claws_mailmbox_append_info * append_info;
1054 uid = * ((uint32_t *) carray_get(tab, i));
1056 r = claws_mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len);
1057 if (r != MAILMBOX_NO_ERROR) {
1062 append_info = claws_mailmbox_append_info_new(data, len);
1063 if (append_info == NULL) {
1064 res = MAILMBOX_ERROR_MEMORY;
1068 r = carray_add(append_tab, append_info, NULL);
1070 claws_mailmbox_append_info_free(append_info);
1071 res = MAILMBOX_ERROR_MEMORY;
1076 r = claws_mailmbox_append_message_list(dest_folder, append_tab);
1077 if (r != MAILMBOX_NO_ERROR) {
1082 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1083 struct claws_mailmbox_append_info * append_info;
1085 append_info = carray_get(append_tab, i);
1086 claws_mailmbox_append_info_free(append_info);
1088 carray_free(append_tab);
1090 claws_mailmbox_read_unlock(src_folder);
1092 return MAILMBOX_NO_ERROR;
1095 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1096 struct claws_mailmbox_append_info * append_info;
1098 append_info = carray_get(append_tab, i);
1099 claws_mailmbox_append_info_free(append_info);
1101 carray_free(append_tab);
1103 claws_mailmbox_read_unlock(src_folder);
1108 int claws_mailmbox_copy_msg(struct claws_mailmbox_folder * dest_folder,
1109 struct claws_mailmbox_folder * src_folder,
1117 tab = carray_new(1);
1119 res = MAILMBOX_ERROR_MEMORY;
1123 puid = malloc(sizeof(* puid));
1125 res = MAILMBOX_ERROR_MEMORY;
1130 r = claws_mailmbox_copy_msg_list(dest_folder, src_folder, tab);
1140 static int claws_mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd,
1141 struct claws_mailmbox_folder * folder,
1142 size_t * result_size)
1152 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1153 struct claws_mailmbox_msg_info * info;
1155 info = carray_get(folder->mb_tab, i);
1157 if (!info->msg_deleted) {
1158 size += info->msg_size + info->msg_padding;
1160 if (!folder->mb_no_uid) {
1161 if (!info->msg_written_uid) {
1165 size += strlen(UID_HEADER " \r\n");
1167 size += strlen(UID_HEADER " \n");
1169 uid = info->msg_uid;
1180 r = ftruncate(dest_fd, size);
1182 res = MAILMBOX_ERROR_FILE;
1187 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0);
1188 if (dest == MAP_FAILED) {
1189 res = MAILMBOX_ERROR_FILE;
1195 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1196 struct claws_mailmbox_msg_info * info;
1198 info = carray_get(folder->mb_tab, i);
1200 if (!info->msg_deleted) {
1201 memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start,
1202 info->msg_headers_len + info->msg_start_len);
1203 cur_offset += info->msg_headers_len + info->msg_start_len;
1205 if (!folder->mb_no_uid) {
1206 if (!info->msg_written_uid) {
1209 memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " "));
1210 cur_offset += strlen(UID_HEADER " ");
1212 numlen = snprintf(dest + cur_offset, size - cur_offset,
1213 "%i\r\n", info->msg_uid);
1215 numlen = snprintf(dest + cur_offset, size - cur_offset,
1216 "%i\n", info->msg_uid);
1218 cur_offset += numlen;
1222 memcpy(dest + cur_offset,
1223 folder->mb_mapping + info->msg_headers + info->msg_headers_len,
1224 info->msg_size - (info->msg_start_len + info->msg_headers_len)
1225 + info->msg_padding);
1227 cur_offset += info->msg_size -
1228 (info->msg_start_len + info->msg_headers_len)
1229 + info->msg_padding;
1235 msync(dest, size, MS_SYNC);
1239 * result_size = size;
1241 return MAILMBOX_NO_ERROR;
1247 int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder * folder)
1249 char tmpfile[PATH_MAX];
1255 if (folder->mb_read_only)
1256 return MAILMBOX_ERROR_READONLY;
1258 if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
1259 (!folder->mb_changed)) {
1260 /* no need to expunge */
1261 return MAILMBOX_NO_ERROR;
1264 snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename);
1265 dest_fd = mkstemp(tmpfile);
1268 res = MAILMBOX_ERROR_FILE;
1272 r = claws_mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd,
1274 if (r != MAILMBOX_NO_ERROR) {
1281 r = rename(tmpfile, folder->mb_filename);
1287 claws_mailmbox_unmap(folder);
1288 claws_mailmbox_close(folder);
1290 r = claws_mailmbox_open(folder);
1291 if (r != MAILMBOX_NO_ERROR) {
1296 r = claws_mailmbox_map(folder);
1297 if (r != MAILMBOX_NO_ERROR) {
1302 r = claws_mailmbox_parse(folder);
1303 if (r != MAILMBOX_NO_ERROR) {
1308 claws_mailmbox_timestamp(folder);
1310 folder->mb_changed = FALSE;
1311 folder->mb_deleted_count = 0;
1313 return MAILMBOX_NO_ERROR;
1322 int claws_mailmbox_expunge(struct claws_mailmbox_folder * folder)
1327 r = claws_mailmbox_validate_write_lock(folder);
1328 if (r != MAILMBOX_NO_ERROR) {
1333 r = claws_mailmbox_expunge_no_lock(folder);
1336 claws_mailmbox_write_unlock(folder);
1341 int claws_mailmbox_delete_msg(struct claws_mailmbox_folder * folder, uint32_t uid)
1343 struct claws_mailmbox_msg_info * info;
1349 if (folder->mb_read_only) {
1350 res = MAILMBOX_ERROR_READONLY;
1355 key.len = sizeof(uid);
1357 r = chash_get(folder->mb_hash, &key, &data);
1359 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1365 if (info->msg_deleted) {
1366 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1370 info->msg_deleted = TRUE;
1371 folder->mb_changed = TRUE;
1372 folder->mb_deleted_count ++;
1374 return MAILMBOX_NO_ERROR;
1394 int claws_mailmbox_init(const char * filename,
1397 uint32_t default_written_uid,
1398 struct claws_mailmbox_folder ** result_folder)
1400 struct claws_mailmbox_folder * folder;
1404 folder = claws_mailmbox_folder_new(filename);
1405 if (folder == NULL) {
1406 debug_print("folder is null for %s\n", filename);
1407 res = MAILMBOX_ERROR_MEMORY;
1410 folder->mb_no_uid = force_no_uid;
1411 folder->mb_read_only = force_readonly;
1412 folder->mb_written_uid = default_written_uid;
1414 folder->mb_changed = FALSE;
1415 folder->mb_deleted_count = 0;
1417 r = claws_mailmbox_open(folder);
1418 if (r != MAILMBOX_NO_ERROR) {
1419 debug_print("folder can't be opened %d\n", r);
1424 r = claws_mailmbox_map(folder);
1425 if (r != MAILMBOX_NO_ERROR) {
1426 debug_print("folder can't be mapped %d\n", r);
1431 r = claws_mailmbox_validate_read_lock(folder);
1432 if (r != MAILMBOX_NO_ERROR) {
1433 debug_print("folder can't be locked %d\n", r);
1438 claws_mailmbox_read_unlock(folder);
1440 * result_folder = folder;
1442 return MAILMBOX_NO_ERROR;
1445 claws_mailmbox_unmap(folder);
1447 claws_mailmbox_close(folder);
1449 claws_mailmbox_folder_free(folder);
1464 void claws_mailmbox_done(struct claws_mailmbox_folder * folder)
1466 if (!folder->mb_read_only)
1467 claws_mailmbox_expunge(folder);
1469 claws_mailmbox_unmap(folder);
1470 claws_mailmbox_close(folder);
1472 claws_mailmbox_folder_free(folder);