summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c361
1 files changed, 361 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
new file mode 100644
index 0000000..9f77d32
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_cached_message.c
@@ -0,0 +1,361 @@
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 "mboxdriver_cached_message.h"
37
38#include "mailmessage_tools.h"
39#include "mboxdriver_tools.h"
40#include "mboxdriver_cached.h"
41#include "mboxdriver.h"
42#include "mailmbox.h"
43#include "mail_cache_db.h"
44#include "generic_cache.h"
45
46#include <unistd.h>
47#include <sys/mman.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <string.h>
52#include <stdlib.h>
53
54static int mbox_prefetch(mailmessage * msg_info);
55
56static void mbox_prefetch_free(struct generic_message_t * msg);
57
58static int mbox_initialize(mailmessage * msg_info);
59
60static void mbox_uninitialize(mailmessage * msg_info);
61
62static void mbox_flush(mailmessage * msg_info);
63
64static void mbox_check(mailmessage * msg_info);
65
66static int mbox_fetch_size(mailmessage * msg_info,
67 size_t * result);
68
69static int mbox_get_flags(mailmessage * msg_info,
70 struct mail_flags ** result);
71
72static int mbox_fetch_header(mailmessage * msg_info,
73 char ** result,
74 size_t * result_len);
75
76static mailmessage_driver local_mbox_cached_message_driver = {
77 .msg_name = "mbox-cached",
78
79 .msg_initialize = mbox_initialize,
80 .msg_uninitialize = mbox_uninitialize,
81
82 .msg_flush = mbox_flush,
83 .msg_check = mbox_check,
84
85 .msg_fetch_result_free = mailmessage_generic_fetch_result_free,
86
87 .msg_fetch = mailmessage_generic_fetch,
88 .msg_fetch_header = mbox_fetch_header,
89 .msg_fetch_body = mailmessage_generic_fetch_body,
90 .msg_fetch_size = mbox_fetch_size,
91 .msg_get_bodystructure = mailmessage_generic_get_bodystructure,
92 .msg_fetch_section = mailmessage_generic_fetch_section,
93 .msg_fetch_section_header = mailmessage_generic_fetch_section_header,
94 .msg_fetch_section_mime = mailmessage_generic_fetch_section_mime,
95 .msg_fetch_section_body = mailmessage_generic_fetch_section_body,
96 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
97
98 .msg_get_flags = mbox_get_flags,
99};
100
101mailmessage_driver * mbox_cached_message_driver =
102&local_mbox_cached_message_driver;
103
104static inline struct mbox_cached_session_state_data *
105get_cached_session_data(mailmessage * msg)
106{
107 return msg->msg_session->sess_data;
108}
109
110static inline mailsession * get_ancestor_session(mailmessage * msg)
111{
112 return get_cached_session_data(msg)->mbox_ancestor;
113}
114
115static inline struct mbox_session_state_data *
116get_ancestor_session_data(mailmessage * msg)
117{
118 return get_ancestor_session(msg)->sess_data;
119}
120
121static inline struct mailmbox_folder *
122get_mbox_session(mailmessage * msg)
123{
124 return get_ancestor_session_data(msg)->mbox_folder;
125}
126
127static int mbox_prefetch(mailmessage * msg_info)
128{
129 struct generic_message_t * msg;
130 int r;
131 char * msg_content;
132 size_t msg_length;
133
134 r = mboxdriver_fetch_msg(get_ancestor_session(msg_info),
135 msg_info->msg_index,
136 &msg_content, &msg_length);
137 if (r != MAIL_NO_ERROR)
138 return r;
139
140 msg = msg_info->msg_data;
141
142 msg->msg_message = msg_content;
143 msg->msg_length = msg_length;
144
145 return MAIL_NO_ERROR;
146}
147
148static void mbox_prefetch_free(struct generic_message_t * msg)
149{
150 if (msg->msg_message != NULL) {
151 mmap_string_unref(msg->msg_message);
152 msg->msg_message = NULL;
153 }
154}
155
156static int mbox_initialize(mailmessage * msg_info)
157{
158 struct generic_message_t * msg;
159 int r;
160 char * uid;
161 char static_uid[PATH_MAX];
162 struct mailmbox_msg_info * info;
163 struct mailmbox_folder * folder;
164 int res;
165 chashdatum key;
166 chashdatum data;
167
168 folder = get_mbox_session(msg_info);
169 if (folder == NULL) {
170 res = MAIL_ERROR_BAD_STATE;
171 goto err;
172 }
173
174 key.data = (char *) &msg_info->msg_index;
175 key.len = sizeof(msg_info->msg_index);
176
177 r = chash_get(folder->mb_hash, &key, &data);
178 if (r < 0) {
179 res = MAIL_ERROR_MSG_NOT_FOUND;
180 goto err;
181 }
182
183 info = (struct mailmbox_msg_info *) data.data;
184
185 snprintf(static_uid, PATH_MAX, "%u-%lu",
186 msg_info->msg_index, (unsigned long) info->msg_body_len);
187 uid = strdup(static_uid);
188 if (uid == NULL) {
189 res = MAIL_ERROR_MEMORY;
190 goto err;
191 }
192
193 r = mailmessage_generic_initialize(msg_info);
194 if (r != MAIL_NO_ERROR) {
195 free(uid);
196 res = r;
197 goto err;
198 }
199
200 msg = msg_info->msg_data;
201
202 msg->msg_prefetch = mbox_prefetch;
203 msg->msg_prefetch_free = mbox_prefetch_free;
204 msg_info->msg_uid = uid;
205
206 return MAIL_NO_ERROR;
207
208 err:
209 return res;
210}
211
212static void mbox_uninitialize(mailmessage * msg_info)
213{
214 mailmessage_generic_uninitialize(msg_info);
215}
216
217#define FLAGS_NAME "flags.db"
218
219static void mbox_flush(mailmessage * msg_info)
220{
221 mailmessage_generic_flush(msg_info);
222}
223
224static void mbox_check(mailmessage * msg_info)
225{
226 int r;
227
228 if (msg_info->msg_flags != NULL) {
229 r = mail_flags_store_set(get_cached_session_data(msg_info)->mbox_flags_store,
230 msg_info);
231 /* ignore errors */
232 }
233}
234
235
236static int mbox_fetch_size(mailmessage * msg_info,
237 size_t * result)
238{
239 int r;
240 size_t size;
241
242 r = mboxdriver_fetch_size(get_ancestor_session(msg_info),
243 msg_info->msg_index, &size);
244 if (r != MAIL_NO_ERROR)
245 return r;
246
247 * result = size;
248
249 return MAIL_NO_ERROR;
250}
251
252static int mbox_get_flags(mailmessage * msg_info,
253 struct mail_flags ** result)
254{
255 int r;
256 struct mail_flags * flags;
257 struct mail_cache_db * cache_db_flags;
258 char filename_flags[PATH_MAX];
259 int res;
260 struct mbox_cached_session_state_data * cached_data;
261 MMAPString * mmapstr;
262 struct mailmbox_folder * folder;
263
264 if (msg_info->msg_flags != NULL) {
265 * result = msg_info->msg_flags;
266
267 return MAIL_NO_ERROR;
268 }
269
270 flags = mail_flags_store_get(get_cached_session_data(msg_info)->mbox_flags_store,
271 msg_info->msg_index);
272
273 if (flags == NULL) {
274 folder = get_mbox_session(msg_info);
275 if (folder == NULL) {
276 res = MAIL_ERROR_BAD_STATE;
277 goto err;
278 }
279
280 cached_data = get_cached_session_data(msg_info);
281 if (cached_data->mbox_quoted_mb == NULL) {
282 res = MAIL_ERROR_BAD_STATE;
283 goto err;
284 }
285
286 snprintf(filename_flags, PATH_MAX, "%s/%s/%s",
287 cached_data->mbox_flags_directory,
288 cached_data->mbox_quoted_mb, FLAGS_NAME);
289
290 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
291 if (r < 0) {
292 res = MAIL_ERROR_MEMORY;
293 goto err;
294 }
295
296 mmapstr = mmap_string_new("");
297 if (mmapstr == NULL) {
298 res = MAIL_ERROR_MEMORY;
299 goto close_db_flags;
300 }
301
302 if (msg_info->msg_index > folder->mb_written_uid) {
303 flags = mail_flags_new_empty();
304 }
305 else {
306 r = mboxdriver_get_cached_flags(cache_db_flags, mmapstr,
307 msg_info->msg_session,
308 msg_info->msg_index, &flags);
309 if (r != MAIL_NO_ERROR) {
310 flags = mail_flags_new_empty();
311 if (flags == NULL) {
312 res = MAIL_ERROR_MEMORY;
313 goto free_mmapstr;
314 }
315 }
316 }
317
318 mmap_string_free(mmapstr);
319 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
320 }
321
322 msg_info->msg_flags = flags;
323
324 * result = flags;
325
326 return MAIL_NO_ERROR;
327
328 free_mmapstr:
329 mmap_string_free(mmapstr);
330 close_db_flags:
331 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
332 err:
333 return res;
334}
335
336static int mbox_fetch_header(mailmessage * msg_info,
337 char ** result,
338 size_t * result_len)
339{
340 struct generic_message_t * msg;
341 int r;
342 char * msg_content;
343 size_t msg_length;
344
345 msg = msg_info->msg_data;
346 if (msg->msg_message != NULL) {
347 return mailmessage_generic_fetch_header(msg_info, result, result_len);
348 }
349 else {
350 r = mboxdriver_fetch_header(get_ancestor_session(msg_info),
351 msg_info->msg_index,
352 &msg_content, &msg_length);
353 if (r != MAIL_NO_ERROR)
354 return r;
355
356 * result = msg_content;
357 * result_len = msg_length;
358
359 return MAIL_NO_ERROR;
360 }
361}