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>
57 #include "mmapstring.h"
58 #include "mailmbox_parse.h"
60 #include "file-utils.h"
64 http://www.qmail.org/qmail-manual-html/man5/mbox.html
68 /* mbox is a file with a corresponding filename */
70 #define UID_HEADER "X-LibEtPan-UID:"
80 int claws_mailmbox_write_lock(struct claws_mailmbox_folder
* folder
)
84 if (folder
->mb_read_only
)
85 return MAILMBOX_ERROR_READONLY
;
87 r
= maillock_write_lock(folder
->mb_filename
, folder
->mb_fd
);
89 return MAILMBOX_NO_ERROR
;
91 return MAILMBOX_ERROR_FILE
;
94 int claws_mailmbox_write_unlock(struct claws_mailmbox_folder
* folder
)
98 r
= maillock_write_unlock(folder
->mb_filename
, folder
->mb_fd
);
100 return MAILMBOX_NO_ERROR
;
102 return MAILMBOX_ERROR_FILE
;
105 int claws_mailmbox_read_lock(struct claws_mailmbox_folder
* folder
)
109 r
= maillock_read_lock(folder
->mb_filename
, folder
->mb_fd
);
111 return MAILMBOX_NO_ERROR
;
113 return MAILMBOX_ERROR_FILE
;
116 int claws_mailmbox_read_unlock(struct claws_mailmbox_folder
* folder
)
120 r
= maillock_read_unlock(folder
->mb_filename
, folder
->mb_fd
);
122 return MAILMBOX_NO_ERROR
;
124 return MAILMBOX_ERROR_FILE
;
129 map the file into memory.
130 the file must be locked.
133 int claws_mailmbox_map(struct claws_mailmbox_folder
* folder
)
140 r
= g_stat(folder
->mb_filename
, &buf
);
142 debug_print("stat failed %d\n", r
);
143 res
= MAILMBOX_ERROR_FILE
;
147 if (buf
.st_size
== 0) {
148 folder
->mb_mapping
= NULL
;
149 folder
->mb_mapping_size
= 0;
150 return MAILMBOX_NO_ERROR
;
152 if (folder
->mb_read_only
)
153 str
= (char *) mmap(NULL
, buf
.st_size
, PROT_READ
,
154 MAP_PRIVATE
, folder
->mb_fd
, 0);
156 str
= (char *) mmap(NULL
, buf
.st_size
, PROT_READ
| PROT_WRITE
,
157 MAP_SHARED
, folder
->mb_fd
, 0);
158 if (str
== MAP_FAILED
) {
160 debug_print("map of %lld bytes failed\n", (long long)buf
.st_size
);
161 res
= MAILMBOX_ERROR_FILE
;
165 folder
->mb_mapping
= str
;
166 folder
->mb_mapping_size
= buf
.st_size
;
168 return MAILMBOX_NO_ERROR
;
178 void claws_mailmbox_unmap(struct claws_mailmbox_folder
* folder
)
180 munmap(folder
->mb_mapping
, folder
->mb_mapping_size
);
181 folder
->mb_mapping
= NULL
;
182 folder
->mb_mapping_size
= 0;
185 void claws_mailmbox_sync(struct claws_mailmbox_folder
* folder
)
187 msync(folder
->mb_mapping
, folder
->mb_mapping_size
, MS_SYNC
);
190 void claws_mailmbox_timestamp(struct claws_mailmbox_folder
* folder
)
195 r
= g_stat(folder
->mb_filename
, &buf
);
197 folder
->mb_mtime
= (time_t) -1;
199 folder
->mb_mtime
= buf
.st_mtime
;
206 int claws_mailmbox_open(struct claws_mailmbox_folder
* folder
)
211 if (!folder
->mb_read_only
) {
213 fd
= open(folder
->mb_filename
, O_RDWR
| O_CREAT
, S_IRUSR
| S_IWUSR
);
216 if (folder
->mb_read_only
|| (fd
< 0)) {
218 fd
= open(folder
->mb_filename
, O_RDONLY
);
220 return MAILMBOX_ERROR_FILE_NOT_FOUND
;
224 folder
->mb_read_only
= read_only
;
226 return MAILMBOX_NO_ERROR
;
233 void claws_mailmbox_close(struct claws_mailmbox_folder
* folder
)
235 close(folder
->mb_fd
);
240 static int claws_mailmbox_validate_lock(struct claws_mailmbox_folder
* folder
,
241 int (* custom_lock
)(struct claws_mailmbox_folder
*),
242 int (* custom_unlock
)(struct claws_mailmbox_folder
*))
248 r
= g_stat(folder
->mb_filename
, &buf
);
250 buf
.st_mtime
= (time_t) -1;
253 if ((buf
.st_mtime
!= folder
->mb_mtime
) ||
254 ((size_t) buf
.st_size
!= folder
->mb_mapping_size
)) {
257 claws_mailmbox_unmap(folder
);
258 claws_mailmbox_close(folder
);
260 r
= claws_mailmbox_open(folder
);
261 if (r
!= MAILMBOX_NO_ERROR
) {
266 r
= custom_lock(folder
);
267 if (r
!= MAILMBOX_NO_ERROR
) {
272 r
= claws_mailmbox_map(folder
);
273 if (r
!= MAILMBOX_NO_ERROR
) {
278 r
= claws_mailmbox_parse(folder
);
279 if (r
!= MAILMBOX_NO_ERROR
) {
284 folder
->mb_mtime
= buf
.st_mtime
;
286 return MAILMBOX_NO_ERROR
;
289 r
= custom_lock(folder
);
290 if (r
!= MAILMBOX_NO_ERROR
) {
296 return MAILMBOX_NO_ERROR
;
299 custom_unlock(folder
);
305 int claws_mailmbox_validate_write_lock(struct claws_mailmbox_folder
* folder
)
307 return claws_mailmbox_validate_lock(folder
,
308 claws_mailmbox_write_lock
,
309 claws_mailmbox_write_unlock
);
313 int claws_mailmbox_validate_read_lock(struct claws_mailmbox_folder
* folder
)
315 return claws_mailmbox_validate_lock(folder
,
316 claws_mailmbox_read_lock
,
317 claws_mailmbox_read_unlock
);
321 /* ********************************************************************** */
322 /* append messages */
324 #define MAX_FROM_LINE_SIZE 256
326 static inline size_t get_line(const char * line
, size_t length
,
327 const char ** pnext_line
, size_t * pcount
)
337 if (* line
== '\r') {
344 if (* line
== '\n') {
354 else if (* line
== '\n') {
376 TODO : should strip \r\n if any
377 see also in write_fixed_line
380 static inline size_t get_fixed_line_size(const char * line
, size_t length
,
381 const char ** pnext_line
, size_t * pcount
,
382 size_t * pfixed_count
)
385 const char * next_line
;
388 if (!get_line(line
, length
, &next_line
, &count
))
393 if (line
[0] == 'F') {
394 if (strncmp(line
, "From ", 5) == 0)
399 * pnext_line
= next_line
;
401 * pfixed_count
= fixed_count
;
406 static size_t get_fixed_message_size(const char * message
, size_t size
,
407 uint32_t uid
, int force_no_uid
)
431 if (cur_token
+ strlen(UID_HEADER
) <= size
) {
432 if (message
[cur_token
] == 'X') {
433 if (strncasecmp(message
+ cur_token
, UID_HEADER
,
434 strlen(UID_HEADER
)) == 0) {
440 r
= mailimf_ignore_field_parse(message
, size
, &cur_token
);
442 case MAILIMF_NO_ERROR
:
444 fixed_size
+= cur_token
- begin
;
446 case MAILIMF_ERROR_PARSE
:
457 fixed_size
+= strlen(UID_HEADER
" \r\n");
459 fixed_size
+= strlen(UID_HEADER
" \n");
463 while (tmp_uid
>= 10) {
472 left
= size
- cur_token
;
473 next
= message
+ cur_token
;
480 if (!get_fixed_line_size(cur
, left
, &next
, &count
, &fixed_count
))
483 fixed_size
+= fixed_count
;
490 static inline char * write_fixed_line(char * str
,
491 const char * line
, size_t length
,
492 const char ** pnext_line
, size_t * pcount
)
495 const char * next_line
;
497 if (!get_line(line
, length
, &next_line
, &count
))
501 if (line
[0] == 'F') {
502 if (strncmp(line
, "From ", 5) == 0) {
509 memcpy(str
, line
, count
);
511 * pnext_line
= next_line
;
518 static char * write_fixed_message(char * str
,
519 const char * message
, size_t size
,
520 uint32_t uid
, int force_no_uid
)
526 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
;
613 if (folder
->mb_read_only
) {
614 res
= MAILMBOX_ERROR_READONLY
;
619 from_size
= strlen(DEFAULT_FROM_LINE
);
620 if (localtime_r(&date
, &time_info
) != NULL
)
621 from_size
= strftime(from_line
, MAX_FROM_LINE_SIZE
, "From - %a %b %_2d %T %Y\n", &time_info
);
624 for(i
= 0 ; i
< carray_count(append_tab
) ; i
++) {
625 struct claws_mailmbox_append_info
* info
;
627 info
= carray_get(append_tab
, i
);
628 extra_size
+= from_size
;
629 extra_size
+= get_fixed_message_size(info
->ai_message
, info
->ai_size
,
630 folder
->mb_max_uid
+ i
+ 1,
633 extra_size
+= 2; /* CR LF */
635 extra_size
+= 1; /* CR LF */
639 left
= folder
->mb_mapping_size
;
642 if (folder
->mb_mapping
[left
- 1] == '\n') {
647 else if (folder
->mb_mapping
[left
- 1] == '\r') {
658 old_size
= folder
->mb_mapping_size
;
659 claws_mailmbox_unmap(folder
);
664 extra_size
+= (2 - crlf_count
) * 2;
666 /* Need the number of LFs, not CRLFs */
667 extra_size
+= (2 - crlf_count
) * 1; /* 2 */
671 r
= ftruncate(folder
->mb_fd
, extra_size
+ old_size
);
673 debug_print("ftruncate failed with %d\n", r
);
674 claws_mailmbox_map(folder
);
675 res
= MAILMBOX_ERROR_FILE
;
679 r
= claws_mailmbox_map(folder
);
681 debug_print("claws_mailmbox_map failed with %d\n", r
);
682 r
= ftruncate(folder
->mb_fd
, old_size
);
684 debug_print("ftruncate failed with %d\n", r
);
685 return MAILMBOX_ERROR_FILE
;
688 str
= folder
->mb_mapping
+ old_size
;
691 for(i
= 0 ; i
< 2 - crlf_count
; i
++) {
701 for(i
= 0 ; i
< carray_count(append_tab
) ; i
++) {
702 struct claws_mailmbox_append_info
* info
;
704 info
= carray_get(append_tab
, i
);
706 memcpy(str
, from_line
, from_size
);
708 str
+= strlen(from_line
);
710 str
= write_fixed_message(str
, info
->ai_message
, info
->ai_size
,
711 folder
->mb_max_uid
+ i
+ 1,
722 folder
->mb_max_uid
+= carray_count(append_tab
);
724 return MAILMBOX_NO_ERROR
;
731 claws_mailmbox_append_message_list(struct claws_mailmbox_folder
* folder
,
738 r
= claws_mailmbox_validate_write_lock(folder
);
739 if (r
!= MAILMBOX_NO_ERROR
) {
744 r
= claws_mailmbox_expunge_no_lock(folder
);
745 if (r
!= MAILMBOX_NO_ERROR
) {
750 cur_token
= folder
->mb_mapping_size
;
752 r
= claws_mailmbox_append_message_list_no_lock(folder
, append_tab
);
753 if (r
!= MAILMBOX_NO_ERROR
) {
758 claws_mailmbox_sync(folder
);
760 r
= claws_mailmbox_parse_additionnal(folder
, &cur_token
);
761 if (r
!= MAILMBOX_NO_ERROR
) {
766 claws_mailmbox_timestamp(folder
);
768 claws_mailmbox_write_unlock(folder
);
770 return MAILMBOX_NO_ERROR
;
773 claws_mailmbox_write_unlock(folder
);
779 claws_mailmbox_append_message(struct claws_mailmbox_folder
* folder
,
780 const char * data
, size_t len
)
783 struct claws_mailmbox_append_info
* append_info
;
789 res
= MAILMBOX_ERROR_MEMORY
;
793 append_info
= claws_mailmbox_append_info_new(data
, len
);
794 if (append_info
== NULL
) {
795 res
= MAILMBOX_ERROR_MEMORY
;
799 r
= carray_add(tab
, append_info
, NULL
);
801 res
= MAILMBOX_ERROR_MEMORY
;
802 goto free_append_info
;
805 r
= claws_mailmbox_append_message_list(folder
, tab
);
807 claws_mailmbox_append_info_free(append_info
);
813 claws_mailmbox_append_info_free(append_info
);
820 /* ********************************************************************** */
822 int claws_mailmbox_fetch_msg_no_lock(struct claws_mailmbox_folder
* folder
,
823 uint32_t num
, const char ** result
,
826 struct claws_mailmbox_msg_info
* info
;
833 key
.len
= sizeof(num
);
835 r
= chash_get(folder
->mb_hash
, &key
, &data
);
837 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
843 if (info
->msg_deleted
) {
844 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
848 * result
= folder
->mb_mapping
+ info
->msg_headers
;
849 * result_len
= info
->msg_size
- info
->msg_start_len
;
851 return MAILMBOX_NO_ERROR
;
857 int claws_mailmbox_fetch_msg_headers_no_lock(struct claws_mailmbox_folder
* folder
,
858 uint32_t num
, const char ** result
,
861 struct claws_mailmbox_msg_info
* info
;
868 key
.len
= sizeof(num
);
870 r
= chash_get(folder
->mb_hash
, &key
, &data
);
872 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
878 if (info
->msg_deleted
) {
879 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
883 * result
= folder
->mb_mapping
+ info
->msg_headers
;
884 * result_len
= info
->msg_headers_len
;
886 return MAILMBOX_NO_ERROR
;
892 int claws_mailmbox_fetch_msg(struct claws_mailmbox_folder
* folder
,
893 uint32_t num
, const char ** result
,
896 MMAPString
* mmapstr
;
904 r
= claws_mailmbox_validate_read_lock(folder
);
905 if (r
!= MAILMBOX_NO_ERROR
) {
910 r
= claws_mailmbox_fetch_msg_no_lock(folder
, num
, &data
, &len
);
911 if (r
!= MAILMBOX_NO_ERROR
) {
916 /* size with no uid */
917 fixed_size
= get_fixed_message_size(data
, len
, 0, 1 /* force no uid */);
920 mmapstr
= mmap_string_new_len(data
, fixed_size
);
921 if (mmapstr
== NULL
) {
922 res
= MAILMBOX_ERROR_MEMORY
;
926 mmapstr
= mmap_string_sized_new(fixed_size
);
927 if (mmapstr
== NULL
) {
928 res
= MAILMBOX_ERROR_MEMORY
;
932 end
= write_fixed_message(mmapstr
->str
, data
, len
, 0, 1 /* force no uid */);
934 mmapstr
->len
= fixed_size
;
936 r
= mmap_string_ref(mmapstr
);
938 mmap_string_free(mmapstr
);
939 res
= MAILMBOX_ERROR_MEMORY
;
943 * result
= mmapstr
->str
;
944 * result_len
= mmapstr
->len
;
946 claws_mailmbox_read_unlock(folder
);
948 return MAILMBOX_NO_ERROR
;
951 claws_mailmbox_read_unlock(folder
);
956 int claws_mailmbox_fetch_msg_headers(struct claws_mailmbox_folder
* folder
,
957 uint32_t num
, const char ** result
,
960 MMAPString
* mmapstr
;
968 r
= claws_mailmbox_validate_read_lock(folder
);
969 if (r
!= MAILMBOX_NO_ERROR
) {
974 r
= claws_mailmbox_fetch_msg_headers_no_lock(folder
, num
, &data
, &len
);
975 if (r
!= MAILMBOX_NO_ERROR
) {
981 mmapstr
= mmap_string_new_len(data
, len
);
982 if (mmapstr
== NULL
) {
983 res
= MAILMBOX_ERROR_MEMORY
;
987 /* size with no uid */
988 fixed_size
= get_fixed_message_size(data
, len
, 0, 1 /* force no uid */);
990 mmapstr
= mmap_string_sized_new(fixed_size
);
991 if (mmapstr
== NULL
) {
992 res
= MAILMBOX_ERROR_MEMORY
;
996 end
= write_fixed_message(mmapstr
->str
, data
, len
, 0, 1 /* force no uid */);
998 mmapstr
->len
= fixed_size
;
1000 r
= mmap_string_ref(mmapstr
);
1002 mmap_string_free(mmapstr
);
1003 res
= MAILMBOX_ERROR_MEMORY
;
1007 * result
= mmapstr
->str
;
1008 * result_len
= mmapstr
->len
;
1010 claws_mailmbox_read_unlock(folder
);
1012 return MAILMBOX_NO_ERROR
;
1015 claws_mailmbox_read_unlock(folder
);
1020 void claws_mailmbox_fetch_result_free(char * msg
)
1022 mmap_string_unref(msg
);
1026 int claws_mailmbox_copy_msg_list(struct claws_mailmbox_folder
* dest_folder
,
1027 struct claws_mailmbox_folder
* src_folder
,
1032 carray
* append_tab
;
1035 r
= claws_mailmbox_validate_read_lock(src_folder
);
1036 if (r
!= MAILMBOX_NO_ERROR
) {
1041 append_tab
= carray_new(carray_count(tab
));
1042 if (append_tab
== NULL
) {
1043 res
= MAILMBOX_ERROR_MEMORY
;
1047 for(i
= 0 ; i
< carray_count(tab
) ; i
++) {
1048 struct claws_mailmbox_append_info
* append_info
;
1053 uid
= * ((uint32_t *) carray_get(tab
, i
));
1055 r
= claws_mailmbox_fetch_msg_no_lock(src_folder
, uid
, &data
, &len
);
1056 if (r
!= MAILMBOX_NO_ERROR
) {
1061 append_info
= claws_mailmbox_append_info_new(data
, len
);
1062 if (append_info
== NULL
) {
1063 res
= MAILMBOX_ERROR_MEMORY
;
1067 r
= carray_add(append_tab
, append_info
, NULL
);
1069 claws_mailmbox_append_info_free(append_info
);
1070 res
= MAILMBOX_ERROR_MEMORY
;
1075 r
= claws_mailmbox_append_message_list(dest_folder
, append_tab
);
1076 if (r
!= MAILMBOX_NO_ERROR
) {
1081 for(i
= 0 ; i
< carray_count(append_tab
) ; i
++) {
1082 struct claws_mailmbox_append_info
* append_info
;
1084 append_info
= carray_get(append_tab
, i
);
1085 claws_mailmbox_append_info_free(append_info
);
1087 carray_free(append_tab
);
1089 claws_mailmbox_read_unlock(src_folder
);
1091 return MAILMBOX_NO_ERROR
;
1094 for(i
= 0 ; i
< carray_count(append_tab
) ; i
++) {
1095 struct claws_mailmbox_append_info
* append_info
;
1097 append_info
= carray_get(append_tab
, i
);
1098 claws_mailmbox_append_info_free(append_info
);
1100 carray_free(append_tab
);
1102 claws_mailmbox_read_unlock(src_folder
);
1107 int claws_mailmbox_copy_msg(struct claws_mailmbox_folder
* dest_folder
,
1108 struct claws_mailmbox_folder
* src_folder
,
1116 tab
= carray_new(1);
1118 res
= MAILMBOX_ERROR_MEMORY
;
1122 puid
= malloc(sizeof(* puid
));
1124 res
= MAILMBOX_ERROR_MEMORY
;
1129 r
= claws_mailmbox_copy_msg_list(dest_folder
, src_folder
, tab
);
1139 static int claws_mailmbox_expunge_to_file_no_lock(char * dest_filename
, int dest_fd
,
1140 struct claws_mailmbox_folder
* folder
,
1141 size_t * result_size
)
1151 for(i
= 0 ; i
< carray_count(folder
->mb_tab
) ; i
++) {
1152 struct claws_mailmbox_msg_info
* info
;
1154 info
= carray_get(folder
->mb_tab
, i
);
1156 if (!info
->msg_deleted
) {
1157 size
+= info
->msg_size
+ info
->msg_padding
;
1159 if (!folder
->mb_no_uid
) {
1160 if (!info
->msg_written_uid
) {
1164 size
+= strlen(UID_HEADER
" \r\n");
1166 size
+= strlen(UID_HEADER
" \n");
1168 uid
= info
->msg_uid
;
1179 r
= ftruncate(dest_fd
, size
);
1181 res
= MAILMBOX_ERROR_FILE
;
1186 dest
= (char *) mmap(0, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, dest_fd
, 0);
1187 if (dest
== MAP_FAILED
) {
1188 res
= MAILMBOX_ERROR_FILE
;
1194 for(i
= 0 ; i
< carray_count(folder
->mb_tab
) ; i
++) {
1195 struct claws_mailmbox_msg_info
* info
;
1197 info
= carray_get(folder
->mb_tab
, i
);
1199 if (!info
->msg_deleted
) {
1200 memcpy(dest
+ cur_offset
, folder
->mb_mapping
+ info
->msg_start
,
1201 info
->msg_headers_len
+ info
->msg_start_len
);
1202 cur_offset
+= info
->msg_headers_len
+ info
->msg_start_len
;
1204 if (!folder
->mb_no_uid
) {
1205 if (!info
->msg_written_uid
) {
1208 memcpy(dest
+ cur_offset
, UID_HEADER
" ", strlen(UID_HEADER
" "));
1209 cur_offset
+= strlen(UID_HEADER
" ");
1211 numlen
= snprintf(dest
+ cur_offset
, size
- cur_offset
,
1212 "%i\r\n", info
->msg_uid
);
1214 numlen
= snprintf(dest
+ cur_offset
, size
- cur_offset
,
1215 "%i\n", info
->msg_uid
);
1217 cur_offset
+= numlen
;
1221 memcpy(dest
+ cur_offset
,
1222 folder
->mb_mapping
+ info
->msg_headers
+ info
->msg_headers_len
,
1223 info
->msg_size
- (info
->msg_start_len
+ info
->msg_headers_len
)
1224 + info
->msg_padding
);
1226 cur_offset
+= info
->msg_size
-
1227 (info
->msg_start_len
+ info
->msg_headers_len
)
1228 + info
->msg_padding
;
1234 msync(dest
, size
, MS_SYNC
);
1238 * result_size
= size
;
1240 return MAILMBOX_NO_ERROR
;
1246 int claws_mailmbox_expunge_no_lock(struct claws_mailmbox_folder
* folder
)
1248 char tmpfile
[PATH_MAX
+ 8]; /* for the extra Xs */
1254 if (folder
->mb_read_only
)
1255 return MAILMBOX_ERROR_READONLY
;
1257 if (((folder
->mb_written_uid
>= folder
->mb_max_uid
) || folder
->mb_no_uid
) &&
1258 (!folder
->mb_changed
)) {
1259 /* no need to expunge */
1260 return MAILMBOX_NO_ERROR
;
1263 snprintf(tmpfile
, sizeof(tmpfile
), "%sXXXXXX", folder
->mb_filename
);
1264 dest_fd
= g_mkstemp(tmpfile
);
1267 res
= MAILMBOX_ERROR_FILE
;
1271 r
= claws_mailmbox_expunge_to_file_no_lock(tmpfile
, dest_fd
,
1273 if (r
!= MAILMBOX_NO_ERROR
) {
1280 r
= rename(tmpfile
, folder
->mb_filename
);
1286 claws_mailmbox_unmap(folder
);
1287 claws_mailmbox_close(folder
);
1289 r
= claws_mailmbox_open(folder
);
1290 if (r
!= MAILMBOX_NO_ERROR
) {
1295 r
= claws_mailmbox_map(folder
);
1296 if (r
!= MAILMBOX_NO_ERROR
) {
1301 r
= claws_mailmbox_parse(folder
);
1302 if (r
!= MAILMBOX_NO_ERROR
) {
1307 claws_mailmbox_timestamp(folder
);
1309 folder
->mb_changed
= FALSE
;
1310 folder
->mb_deleted_count
= 0;
1312 return MAILMBOX_NO_ERROR
;
1321 int claws_mailmbox_expunge(struct claws_mailmbox_folder
* folder
)
1326 r
= claws_mailmbox_validate_write_lock(folder
);
1327 if (r
!= MAILMBOX_NO_ERROR
) {
1332 r
= claws_mailmbox_expunge_no_lock(folder
);
1335 claws_mailmbox_write_unlock(folder
);
1340 int claws_mailmbox_delete_msg(struct claws_mailmbox_folder
* folder
, uint32_t uid
)
1342 struct claws_mailmbox_msg_info
* info
;
1348 if (folder
->mb_read_only
) {
1349 res
= MAILMBOX_ERROR_READONLY
;
1354 key
.len
= sizeof(uid
);
1356 r
= chash_get(folder
->mb_hash
, &key
, &data
);
1358 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
1364 if (info
->msg_deleted
) {
1365 res
= MAILMBOX_ERROR_MSG_NOT_FOUND
;
1369 info
->msg_deleted
= TRUE
;
1370 folder
->mb_changed
= TRUE
;
1371 folder
->mb_deleted_count
++;
1373 return MAILMBOX_NO_ERROR
;
1393 int claws_mailmbox_init(const char * filename
,
1396 uint32_t default_written_uid
,
1397 struct claws_mailmbox_folder
** result_folder
)
1399 struct claws_mailmbox_folder
* folder
;
1403 folder
= claws_mailmbox_folder_new(filename
);
1404 if (folder
== NULL
) {
1405 debug_print("folder is null for %s\n", filename
);
1406 res
= MAILMBOX_ERROR_MEMORY
;
1409 folder
->mb_no_uid
= force_no_uid
;
1410 folder
->mb_read_only
= force_readonly
;
1411 folder
->mb_written_uid
= default_written_uid
;
1413 folder
->mb_changed
= FALSE
;
1414 folder
->mb_deleted_count
= 0;
1416 r
= claws_mailmbox_open(folder
);
1417 if (r
!= MAILMBOX_NO_ERROR
) {
1418 debug_print("folder can't be opened %d\n", r
);
1423 r
= claws_mailmbox_map(folder
);
1424 if (r
!= MAILMBOX_NO_ERROR
) {
1425 debug_print("folder can't be mapped %d\n", r
);
1430 r
= claws_mailmbox_validate_read_lock(folder
);
1431 if (r
!= MAILMBOX_NO_ERROR
) {
1432 debug_print("folder can't be locked %d\n", r
);
1437 claws_mailmbox_read_unlock(folder
);
1439 * result_folder
= folder
;
1441 return MAILMBOX_NO_ERROR
;
1444 claws_mailmbox_unmap(folder
);
1446 claws_mailmbox_close(folder
);
1448 claws_mailmbox_folder_free(folder
);
1463 void claws_mailmbox_done(struct claws_mailmbox_folder
* folder
)
1465 if (!folder
->mb_read_only
)
1466 claws_mailmbox_expunge(folder
);
1468 claws_mailmbox_unmap(folder
);
1469 claws_mailmbox_close(folder
);
1471 claws_mailmbox_folder_free(folder
);