summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/mbox/mboxdriver_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/mbox/mboxdriver_tools.c435
1 files changed, 435 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
new file mode 100644
index 0000000..dc38cbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mbox/mboxdriver_tools.c
@@ -0,0 +1,435 @@
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_tools.h"
37
38#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42
43#include "maildriver_types.h"
44#include "mailmbox.h"
45#include "mboxdriver_cached.h"
46#include "mboxdriver.h"
47#include "generic_cache.h"
48#include "mailmessage.h"
49#include "imfcache.h"
50#include "mail_cache_db.h"
51
52static inline struct mbox_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct mailmbox_folder *
59session_get_mbox_session(mailsession * session)
60{
61 return session_get_data(session)->mbox_folder;
62}
63
64static inline struct mbox_cached_session_state_data *
65cached_session_get_data(mailsession * session)
66{
67 return session->sess_data;
68}
69
70static inline mailsession *
71cached_session_get_ancestor(mailsession * session)
72{
73 return cached_session_get_data(session)->mbox_ancestor;
74}
75
76static inline struct mbox_session_state_data *
77cached_session_get_ancestor_data(mailsession * session)
78{
79 return cached_session_get_ancestor(session)->sess_data;
80}
81
82static inline struct mailmbox_folder *
83cached_session_get_mbox_session(mailsession * session)
84{
85 return session_get_mbox_session(cached_session_get_ancestor(session));
86}
87
88
89int mboxdriver_mbox_error_to_mail_error(int error)
90{
91 switch (error) {
92 case MAILMBOX_NO_ERROR:
93 return MAIL_NO_ERROR;
94
95 case MAILMBOX_ERROR_PARSE:
96 return MAIL_ERROR_PARSE;
97
98 case MAILMBOX_ERROR_INVAL:
99 return MAIL_ERROR_INVAL;
100
101 case MAILMBOX_ERROR_FILE_NOT_FOUND:
102 return MAIL_ERROR_PARSE;
103
104 case MAILMBOX_ERROR_MEMORY:
105 return MAIL_ERROR_MEMORY;
106
107 case MAILMBOX_ERROR_TEMPORARY_FILE:
108 return MAIL_ERROR_PARSE;
109
110 case MAILMBOX_ERROR_FILE:
111 return MAIL_ERROR_FILE;
112
113 case MAILMBOX_ERROR_MSG_NOT_FOUND:
114 return MAIL_ERROR_MSG_NOT_FOUND;
115
116 case MAILMBOX_ERROR_READONLY:
117 return MAIL_ERROR_READONLY;
118
119 default:
120 return MAIL_ERROR_INVAL;
121 }
122}
123
124int mboxdriver_fetch_msg(mailsession * session, uint32_t index,
125 char ** result, size_t * result_len)
126{
127 int r;
128 char * msg_content;
129 size_t msg_length;
130 struct mailmbox_folder * folder;
131
132 folder = session_get_mbox_session(session);
133 if (folder == NULL)
134 return MAIL_ERROR_BAD_STATE;
135
136 r = mailmbox_fetch_msg(folder, index, &msg_content, &msg_length);
137 if (r != MAILMBOX_NO_ERROR)
138 return mboxdriver_mbox_error_to_mail_error(r);
139
140 * result = msg_content;
141 * result_len = msg_length;
142
143 return MAIL_NO_ERROR;
144}
145
146
147int mboxdriver_fetch_size(mailsession * session, uint32_t index,
148 size_t * result)
149{
150 struct mailmbox_folder * folder;
151 int r;
152 char * data;
153 size_t len;
154 int res;
155
156 folder = session_get_mbox_session(session);
157 if (folder == NULL) {
158 res = MAIL_ERROR_FETCH;
159 goto err;
160 }
161
162 r = mailmbox_validate_read_lock(folder);
163 if (r != MAILMBOX_NO_ERROR) {
164 res = mboxdriver_mbox_error_to_mail_error(r);
165 goto err;
166 }
167
168 r = mailmbox_fetch_msg_no_lock(folder, index, &data, &len);
169 if (r != MAILMBOX_NO_ERROR) {
170 res = mboxdriver_mbox_error_to_mail_error(r);
171 goto unlock;
172 }
173
174 mailmbox_read_unlock(folder);
175
176 * result = len;
177
178 return MAIL_NO_ERROR;
179
180 unlock:
181 mailmbox_read_unlock(folder);
182 err:
183 return res;
184}
185
186
187int
188mboxdriver_get_cached_flags(struct mail_cache_db * cache_db,
189 MMAPString * mmapstr,
190 mailsession * session,
191 uint32_t num,
192 struct mail_flags ** result)
193{
194 int r;
195 char keyname[PATH_MAX];
196 struct mail_flags * flags;
197 int res;
198 struct mailmbox_msg_info * info;
199 struct mailmbox_folder * folder;
200 chashdatum key;
201 chashdatum data;
202
203 folder = cached_session_get_mbox_session(session);
204 if (folder == NULL) {
205 res = MAIL_ERROR_BAD_STATE;
206 goto err;
207 }
208
209 key.data = &num;
210 key.len = sizeof(num);
211
212 r = chash_get(folder->mb_hash, &key, &data);
213 if (r < 0) {
214 res = MAIL_ERROR_MSG_NOT_FOUND;
215 goto err;
216 }
217
218 info = data.data;
219
220 snprintf(keyname, PATH_MAX, "%u-%lu-flags", num,
221 (unsigned long) info->msg_body_len);
222
223 r = generic_cache_flags_read(cache_db, mmapstr, keyname, &flags);
224 if (r != MAIL_NO_ERROR) {
225 res = r;
226 goto err;
227 }
228
229 * result = flags;
230
231 return MAIL_NO_ERROR;
232
233 err:
234 return res;
235}
236
237int
238mboxdriver_write_cached_flags(struct mail_cache_db * cache_db,
239 MMAPString * mmapstr,
240 char * uid,
241 struct mail_flags * flags)
242{
243 int r;
244 char keyname[PATH_MAX];
245 int res;
246
247 snprintf(keyname, PATH_MAX, "%s-flags", uid);
248
249 r = generic_cache_flags_write(cache_db, mmapstr, keyname, flags);
250 if (r != MAIL_NO_ERROR) {
251 res = r;
252 goto err;
253 }
254
255 return MAIL_NO_ERROR;
256
257 err:
258 return res;
259}
260
261
262int mboxdriver_fetch_header(mailsession * session, uint32_t index,
263 char ** result, size_t * result_len)
264{
265 int r;
266 char * msg_content;
267 size_t msg_length;
268 struct mailmbox_folder * folder;
269
270 folder = session_get_mbox_session(session);
271 if (folder == NULL)
272 return MAIL_ERROR_BAD_STATE;
273
274 r = mailmbox_fetch_msg_headers(folder, index, &msg_content, &msg_length);
275 if (r != MAILMBOX_NO_ERROR)
276 return mboxdriver_mbox_error_to_mail_error(r);
277
278 * result = msg_content;
279 * result_len = msg_length;
280
281 return MAIL_NO_ERROR;
282}
283
284int mbox_get_locked_messages_list(struct mailmbox_folder * folder,
285 mailsession * session,
286 mailmessage_driver * driver,
287 int (* lock)(struct mailmbox_folder *),
288 int (* unlock)(struct mailmbox_folder *),
289 struct mailmessage_list ** result)
290{
291 struct mailmessage_list * env_list;
292 unsigned int i;
293 int r;
294 int res;
295 carray * tab;
296
297 tab = carray_new(128);
298 if (tab == NULL) {
299 res = MAIL_ERROR_MEMORY;
300 goto err;
301 }
302
303 r = lock(folder);
304 if (r != MAIL_NO_ERROR) {
305 res = r;
306 goto free;
307 }
308
309 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
310 struct mailmbox_msg_info * msg_info;
311 mailmessage * msg;
312
313 msg_info = carray_get(folder->mb_tab, i);
314 if (msg_info == NULL)
315 continue;
316
317 if (msg_info->msg_deleted)
318 continue;
319
320 msg = mailmessage_new();
321 if (msg == NULL) {
322 res = MAIL_ERROR_MEMORY;
323 goto unlock;
324 }
325
326 r = mailmessage_init(msg, session, driver, msg_info->msg_uid,
327 msg_info->msg_size - msg_info->msg_start_len);
328 if (r != MAIL_NO_ERROR) {
329 res = r;
330 goto unlock;
331 }
332
333 r = carray_add(tab, msg, NULL);
334 if (r < 0) {
335 mailmessage_free(msg);
336 res = MAIL_ERROR_MEMORY;
337 goto unlock;
338 }
339 }
340
341 env_list = mailmessage_list_new(tab);
342 if (env_list == NULL) {
343 res = MAIL_ERROR_MEMORY;
344 goto unlock;
345 }
346
347 unlock(folder);
348
349 * result = env_list;
350
351 return MAIL_NO_ERROR;
352
353 unlock:
354 unlock(folder);
355 free:
356 for(i = 0 ; i < carray_count(tab) ; i ++)
357 mailmessage_free(carray_get(tab, i));
358 carray_free(tab);
359 err:
360 return res;
361}
362
363static int release_read_mbox(struct mailmbox_folder * folder)
364{
365 int r;
366
367 r = mailmbox_read_unlock(folder);
368 return mboxdriver_mbox_error_to_mail_error(r);
369}
370
371static int acquire_read_mbox(struct mailmbox_folder * folder)
372{
373 int r;
374
375 r = mailmbox_validate_read_lock(folder);
376 return mboxdriver_mbox_error_to_mail_error(r);
377}
378
379static int release_write_mbox(struct mailmbox_folder * folder)
380{
381 int r;
382
383 r = mailmbox_write_unlock(folder);
384 return mboxdriver_mbox_error_to_mail_error(r);
385}
386
387static int acquire_write_mbox(struct mailmbox_folder * folder)
388{
389 int r;
390 int res;
391
392 r = mailmbox_validate_write_lock(folder);
393 if (r != MAILMBOX_NO_ERROR) {
394 res = mboxdriver_mbox_error_to_mail_error(r);
395 goto err;
396 }
397
398 if (folder->mb_written_uid < folder->mb_max_uid) {
399 r = mailmbox_expunge_no_lock(folder);
400 if (r != MAILMBOX_NO_ERROR) {
401 res = mboxdriver_mbox_error_to_mail_error(r);
402 goto unlock;
403 }
404 }
405
406 return MAIL_NO_ERROR;
407
408 unlock:
409 mailmbox_write_unlock(folder);
410 err:
411 return res;
412}
413
414/* get message list with all valid written UID */
415
416int mbox_get_uid_messages_list(struct mailmbox_folder * folder,
417 mailsession * session,
418 mailmessage_driver * driver,
419 struct mailmessage_list ** result)
420{
421 return mbox_get_locked_messages_list(folder, session, driver,
422 acquire_write_mbox, release_write_mbox, result);
423}
424
425
426/* get message list */
427
428int mbox_get_messages_list(struct mailmbox_folder * folder,
429 mailsession * session,
430 mailmessage_driver * driver,
431 struct mailmessage_list ** result)
432{
433 return mbox_get_locked_messages_list(folder, session, driver,
434 acquire_read_mbox, release_read_mbox, result);
435}