summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/maildir/maildirdriver_message.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/maildir/maildirdriver_message.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/maildir/maildirdriver_message.c b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
new file mode 100644
index 0000000..58bc6bd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/maildir/maildirdriver_message.c
@@ -0,0 +1,255 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "maildirdriver_message.h"
37#include "maildirdriver_tools.h"
38
39#include "mailmessage_tools.h"
40#include "maildirdriver.h"
41#include "maildir.h"
42#include "generic_cache.h"
43
44#include <unistd.h>
45#include <sys/mman.h>
46#include <sys/types.h>
47#include <sys/stat.h>
48#include <fcntl.h>
49#include <string.h>
50#include <stdlib.h>
51
52static int get_flags(mailmessage * msg_info,
53 struct mail_flags ** result);
54
55static int prefetch(mailmessage * msg_info);
56
57static void prefetch_free(struct generic_message_t * msg);
58
59static int initialize(mailmessage * msg_info);
60
61static void check(mailmessage * msg_info);
62
63static mailmessage_driver local_maildir_message_driver = {
64 .msg_name = "maildir",
65
66 .msg_initialize = initialize,
67 .msg_uninitialize = mailmessage_generic_uninitialize,
68
69 .msg_flush = mailmessage_generic_flush,
70 .msg_check = check,
71
72 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
73
74 .msg_fetch = mailmessage_generic_fetch,
75 .msg_fetch_header = mailmessage_generic_fetch_header,
76 .msg_fetch_body = mailmessage_generic_fetch_header,
77 .msg_fetch_size = NULL,
78 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
79 .msg_fetch_section = mailmessage_generic_fetch_section,
80 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
81 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
82 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
83 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
84
85 .msg_get_flags = get_flags,
86};
87
88mailmessage_driver * maildir_message_driver = &local_maildir_message_driver;
89
90struct maildir_msg_data {
91 int fd;
92};
93
94static inline struct maildir_session_state_data *
95get_session_data(mailmessage * msg)
96{
97 return msg->msg_session->sess_data;
98}
99
100static struct maildir * get_maildir_session(mailmessage * msg)
101{
102 return get_session_data(msg)->md_session;
103}
104
105static int prefetch(mailmessage * msg_info)
106{
107 struct generic_message_t * msg;
108 int res;
109 struct maildir_msg_data * data;
110 char * filename;
111 int fd;
112 char * mapping;
113 struct maildir * md;
114
115 md = get_maildir_session(msg_info);
116
117 if (msg_info->msg_uid == NULL) {
118 res = MAIL_ERROR_INVAL;
119 goto err;
120 }
121
122 filename = maildir_message_get(md, msg_info->msg_uid);
123 if (filename == NULL) {
124 res = MAIL_ERROR_MEMORY;
125 goto err;
126 }
127
128 fd = open(filename, O_RDONLY);
129 free(filename);
130 if (fd == -1) {
131 res = MAIL_ERROR_FILE;
132 goto err;
133 }
134
135 mapping = mmap(NULL, msg_info->msg_size, PROT_READ, MAP_PRIVATE, fd, 0);
136 if (mapping == MAP_FAILED) {
137 res = MAIL_ERROR_FILE;
138 goto close;
139 }
140
141 data = malloc(sizeof(* data));
142 if (data == NULL) {
143 res = MAIL_ERROR_MEMORY;
144 goto unmap;
145 }
146
147 data->fd = fd;
148
149 msg = msg_info->msg_data;
150
151 msg->msg_data = data;
152 msg->msg_message = mapping;
153 msg->msg_length = msg_info->msg_size;
154
155 return MAIL_NO_ERROR;
156
157 unmap:
158 munmap(mapping, msg_info->msg_size);
159 close:
160 close(fd);
161 err:
162 return res;
163}
164
165static void prefetch_free(struct generic_message_t * msg)
166{
167 if (msg->msg_message != NULL) {
168 struct maildir_msg_data * data;
169
170 munmap(msg->msg_message, msg->msg_length);
171 msg->msg_message = NULL;
172 data = msg->msg_data;
173 close(data->fd);
174 free(data);
175 }
176}
177
178static int initialize(mailmessage * msg_info)
179{
180 struct generic_message_t * msg;
181 int r;
182
183 r = mailmessage_generic_initialize(msg_info);
184 if (r != MAIL_NO_ERROR)
185 return r;
186
187 msg = msg_info->msg_data;
188 msg->msg_prefetch = prefetch;
189 msg->msg_prefetch_free = prefetch_free;
190
191 return MAIL_NO_ERROR;
192}
193
194static void check(mailmessage * msg_info)
195{
196 int r;
197
198 if (msg_info->msg_flags != NULL) {
199 r = mail_flags_store_set(get_session_data(msg_info)->md_flags_store,
200 msg_info);
201 /* ignore errors */
202 }
203}
204
205static int get_flags(mailmessage * msg_info,
206 struct mail_flags ** result)
207{
208 chashdatum key;
209 chashdatum value;
210 struct maildir * md;
211 struct mail_flags * flags;
212 struct maildir_session_state_data * data;
213 struct maildir_msg * md_msg;
214 int r;
215 uint32_t driver_flags;
216 clist * ext;
217
218 if (msg_info->msg_flags != NULL) {
219 * result = msg_info->msg_flags;
220 return MAIL_NO_ERROR;
221 }
222
223 data = get_session_data(msg_info);
224 flags = mail_flags_store_get(data->md_flags_store,
225 msg_info->msg_index);
226 if (flags != NULL) {
227 msg_info->msg_flags = flags;
228 * result = msg_info->msg_flags;
229 return MAIL_NO_ERROR;
230 }
231
232 md = get_maildir_session(msg_info);
233 if (md == NULL)
234 return MAIL_ERROR_BAD_STATE;
235
236 key.data = msg_info->msg_uid;
237 key.len = strlen(msg_info->msg_uid);
238 r = chash_get(md->mdir_msg_hash, &key, &value);
239 if (r < 0)
240 return MAIL_ERROR_MSG_NOT_FOUND;
241
242 md_msg = value.data;
243
244 driver_flags = maildirdriver_maildir_flags_to_flags(md_msg->msg_flags);
245
246 ext = clist_new();
247 if (ext == NULL)
248 return MAIL_ERROR_MEMORY;
249
250 msg_info->msg_flags = mail_flags_new(driver_flags, ext);
251
252 * result = msg_info->msg_flags;
253
254 return MAIL_NO_ERROR;
255}