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.c | 435 |
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 | |||
52 | static inline struct mbox_session_state_data * | ||
53 | session_get_data(mailsession * session) | ||
54 | { | ||
55 | return session->sess_data; | ||
56 | } | ||
57 | |||
58 | static inline struct mailmbox_folder * | ||
59 | session_get_mbox_session(mailsession * session) | ||
60 | { | ||
61 | return session_get_data(session)->mbox_folder; | ||
62 | } | ||
63 | |||
64 | static inline struct mbox_cached_session_state_data * | ||
65 | cached_session_get_data(mailsession * session) | ||
66 | { | ||
67 | return session->sess_data; | ||
68 | } | ||
69 | |||
70 | static inline mailsession * | ||
71 | cached_session_get_ancestor(mailsession * session) | ||
72 | { | ||
73 | return cached_session_get_data(session)->mbox_ancestor; | ||
74 | } | ||
75 | |||
76 | static inline struct mbox_session_state_data * | ||
77 | cached_session_get_ancestor_data(mailsession * session) | ||
78 | { | ||
79 | return cached_session_get_ancestor(session)->sess_data; | ||
80 | } | ||
81 | |||
82 | static inline struct mailmbox_folder * | ||
83 | cached_session_get_mbox_session(mailsession * session) | ||
84 | { | ||
85 | return session_get_mbox_session(cached_session_get_ancestor(session)); | ||
86 | } | ||
87 | |||
88 | |||
89 | int 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 | |||
124 | int 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 | |||
147 | int 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 | |||
187 | int | ||
188 | mboxdriver_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 = # | ||
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 | |||
237 | int | ||
238 | mboxdriver_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 | |||
262 | int 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 | |||
284 | int 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 | |||
363 | static 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 | |||
371 | static 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 | |||
379 | static 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 | |||
387 | static 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 | |||
416 | int 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 | |||
428 | int 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 | } | ||