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: imfcache.c,v 1.20 2009/07/23 19:46:46 hoa Exp $
34  */
35 
36 #ifdef HAVE_CONFIG_H
37 #	include <config.h>
38 #endif
39 
40 #include "imfcache.h"
41 
42 #include <stdlib.h>
43 #include <string.h>
44 
45 static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * indx,
46 				     struct mailimf_field * field);
47 static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * indx,
48 					 struct mailimf_orig_date * date);
49 static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * indx,
50 					 struct mailimf_date_time * date_time);
51 static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * indx,
52 				    struct mailimf_from * from);
53 static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * indx,
54 				      struct mailimf_sender * sender);
55 static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * indx,
56 					struct mailimf_reply_to * reply_to);
57 static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * indx,
58 				  struct mailimf_to * to);
59 static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * indx,
60 				  struct mailimf_cc * to);
61 static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * indx,
62 				   struct mailimf_bcc * to);
63 static int mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * indx,
64 					  struct mailimf_message_id * message_id);
65 static int mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * indx,
66 					   clist * list);
67 static int mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * indx,
68 					   struct mailimf_in_reply_to *
69 					   in_reply_to);
70 static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * indx,
71 					  struct mailimf_references * references);
72 static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * indx,
73 				       struct mailimf_subject * subject);
74 static int mailimf_cache_address_list_write(MMAPString * mmapstr,
75 					    size_t * indx,
76 					    struct mailimf_address_list *
77 					    addr_list);
78 static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * indx,
79 				       struct mailimf_address * addr);
80 static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * indx,
81 				     struct mailimf_group * group);
82 static int mailimf_cache_mailbox_list_write(MMAPString * mmapstr,
83 					    size_t * indx,
84 					    struct mailimf_mailbox_list * mb_list);
85 static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * indx,
86 				       struct mailimf_mailbox * mb);
87 
88 
89 static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * indx,
90 				    struct mailimf_field ** result);
91 static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * indx,
92 					struct mailimf_orig_date ** result);
93 static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * indx,
94 					struct mailimf_date_time ** result);
95 static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * indx,
96 				   struct mailimf_from ** result);
97 static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * indx,
98 				     struct mailimf_sender ** result);
99 static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * indx,
100 				       struct mailimf_reply_to ** result);
101 static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * indx,
102 				 struct mailimf_to ** result);
103 static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * indx,
104 				 struct mailimf_cc ** result);
105 static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * indx,
106 				  struct mailimf_bcc ** result);
107 static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * indx,
108 					 struct mailimf_message_id ** result);
109 static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * indx,
110 					  clist ** result);
111 static int
112 mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * indx,
113 			       struct mailimf_in_reply_to ** result);
114 
115 static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * indx,
116 					 struct mailimf_references ** result);
117 static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * indx,
118 				      struct mailimf_subject ** result);
119 static int mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * indx,
120 					   struct mailimf_address_list ** result);
121 static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * indx,
122 				      struct mailimf_address ** result);
123 static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * indx,
124 				    struct mailimf_group ** result);
125 static int
126 mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * indx,
127 				struct mailimf_mailbox_list ** result);
128 static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * indx,
129 				      struct mailimf_mailbox ** result);
130 
131 enum {
132   CACHE_NULL_POINTER = 0,
133   CACHE_NOT_NULL     = 1
134 };
135 
mail_serialize_clear(MMAPString * mmapstr,size_t * indx)136 int mail_serialize_clear(MMAPString * mmapstr, size_t * indx)
137 {
138   if (mmap_string_set_size(mmapstr, 0) == NULL)
139     return MAIL_ERROR_MEMORY;
140 
141   * indx = 0;
142 
143   return MAIL_NO_ERROR;
144 }
145 
mail_serialize_write(MMAPString * mmapstr,size_t * indx,char * buf,size_t size)146 int mail_serialize_write(MMAPString * mmapstr, size_t * indx,
147 			 char * buf, size_t size)
148 {
149   if (mmap_string_append_len(mmapstr, buf, size) == NULL)
150     return MAIL_ERROR_MEMORY;
151 
152   * indx = * indx + size;
153 
154   return MAIL_NO_ERROR;
155 }
156 
mail_serialize_read(MMAPString * mmapstr,size_t * indx,char * buf,size_t size)157 int mail_serialize_read(MMAPString * mmapstr, size_t * indx,
158 			char * buf, size_t size)
159 {
160   size_t cur_token;
161 
162   cur_token = * indx;
163 
164   if (cur_token + size > mmapstr->len)
165     return MAIL_ERROR_STREAM;
166 
167   memcpy(buf, mmapstr->str + cur_token, size);
168   * indx = cur_token + size;
169 
170   return MAIL_NO_ERROR;
171 }
172 
mailimf_cache_int_write(MMAPString * mmapstr,size_t * indx,uint32_t value)173 int mailimf_cache_int_write(MMAPString * mmapstr, size_t * indx,
174 			    uint32_t value)
175 {
176   unsigned char ch;
177   int r;
178   int i;
179 
180   for(i = 0 ; i < 4 ; i ++) {
181     ch = value % 256;
182 
183     r = mail_serialize_write(mmapstr, indx, (char *) &ch, 1);
184     if (r != MAIL_NO_ERROR)
185       return r;
186     value /= 256;
187   }
188 
189   return MAIL_NO_ERROR;
190 }
191 
mailimf_cache_int_read(MMAPString * mmapstr,size_t * indx,uint32_t * result)192 int mailimf_cache_int_read(MMAPString * mmapstr, size_t * indx,
193 			   uint32_t * result)
194 {
195   unsigned char ch;
196   uint32_t value;
197   int i;
198   int r;
199 
200   value = 0;
201   for(i = 0 ; i < 4 ; i ++) {
202     r = mail_serialize_read(mmapstr, indx, (char *) &ch, 1);
203     if (r != MAIL_NO_ERROR)
204       return r;
205     value = value | ch << (i << 3);
206   }
207 
208   * result = value;
209 
210   return MAIL_NO_ERROR;
211 }
212 
213 
mailimf_cache_string_write(MMAPString * mmapstr,size_t * indx,char * str,size_t length)214 int mailimf_cache_string_write(MMAPString * mmapstr, size_t * indx,
215 			       char * str, size_t length)
216 {
217   int r;
218 
219   if (str == NULL) {
220     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER);
221     if (r != MAIL_NO_ERROR)
222       return r;
223   }
224   else {
225     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL);
226     if (r != MAIL_NO_ERROR)
227       return r;
228 
229     r = mailimf_cache_int_write(mmapstr, indx, (uint32_t) length);
230     if (r != MAIL_NO_ERROR)
231       return r;
232 
233     if (length != 0) {
234       r = mail_serialize_write(mmapstr, indx, str, length);
235       if (r != MAIL_NO_ERROR)
236         return MAIL_ERROR_FILE;
237     }
238   }
239 
240   return MAIL_NO_ERROR;
241 }
242 
mailimf_cache_string_read(MMAPString * mmapstr,size_t * indx,char ** result)243 int mailimf_cache_string_read(MMAPString * mmapstr, size_t * indx,
244 			      char ** result)
245 {
246   int r;
247   uint32_t length;
248   char * str;
249   uint32_t type;
250 
251   r = mailimf_cache_int_read(mmapstr, indx, &type);
252   if (r != MAIL_NO_ERROR)
253     return r;
254 
255   if (type == CACHE_NULL_POINTER) {
256     str = NULL;
257   }
258   else {
259     r = mailimf_cache_int_read(mmapstr, indx, &length);
260     if (r != MAIL_NO_ERROR)
261       return r;
262 
263     str = malloc(length + 1);
264     if (str == NULL)
265       return MAIL_ERROR_MEMORY;
266 
267     r = mail_serialize_read(mmapstr, indx, str, length);
268     if (r != MAIL_NO_ERROR) {
269       free(str);
270       return MAIL_ERROR_FILE;
271     }
272 
273     str[length] = 0;
274   }
275 
276   * result = str;
277 
278   return MAIL_NO_ERROR;
279 }
280 
mailimf_cache_fields_write(MMAPString * mmapstr,size_t * indx,struct mailimf_fields * fields)281 int mailimf_cache_fields_write(MMAPString * mmapstr, size_t * indx,
282 			       struct mailimf_fields * fields)
283 {
284   clistiter * cur;
285   int r;
286 
287   r = mailimf_cache_int_write(mmapstr, indx,
288       clist_count(fields->fld_list));
289   if (r != MAIL_NO_ERROR)
290     return r;
291 
292   for(cur = clist_begin(fields->fld_list) ; cur != NULL ;
293       cur = clist_next(cur)) {
294     r = mailimf_cache_field_write(mmapstr, indx, clist_content(cur));
295     if (r != MAIL_NO_ERROR)
296       return r;
297   }
298 
299   return MAIL_NO_ERROR;
300 }
301 
mailimf_cache_fields_read(MMAPString * mmapstr,size_t * indx,struct mailimf_fields ** result)302 int mailimf_cache_fields_read(MMAPString * mmapstr, size_t * indx,
303 			      struct mailimf_fields ** result)
304 {
305   clist * list;
306   int r;
307   uint32_t count;
308   uint32_t i;
309   struct mailimf_fields * fields;
310   int res;
311 
312   r = mailimf_cache_int_read(mmapstr, indx, &count);
313   if (r != MAIL_NO_ERROR) {
314     res = r;
315     goto err;
316   }
317 
318   list = clist_new();
319   if (list == NULL) {
320     res = MAIL_ERROR_MEMORY;
321     goto err;
322   }
323 
324   for(i = 0 ; i < count ; i++) {
325     struct mailimf_field * field;
326 
327     field = NULL;
328     r = mailimf_cache_field_read(mmapstr, indx, &field);
329     if (r != MAIL_NO_ERROR) {
330       res = r;
331       goto free_list;
332     }
333 
334     r = clist_append(list, field);
335     if (r < 0) {
336       mailimf_field_free(field);
337       res = MAIL_ERROR_MEMORY;
338       goto free_list;
339     }
340   }
341 
342   fields = mailimf_fields_new(list);
343   if (fields == NULL) {
344     res = MAIL_ERROR_MEMORY;
345     goto free_list;
346   }
347 
348   * result = fields;
349 
350   return MAIL_NO_ERROR;
351 
352  free_list:
353   clist_foreach(list, (clist_func) mailimf_field_free, NULL);
354   clist_free(list);
355  err:
356   return res;
357 }
358 
359 
mailimf_cache_field_write(MMAPString * mmapstr,size_t * indx,struct mailimf_field * field)360 static int mailimf_cache_field_write(MMAPString * mmapstr, size_t * indx,
361 				     struct mailimf_field * field)
362 {
363   int r;
364 
365   r = mailimf_cache_int_write(mmapstr, indx, field->fld_type);
366   if (r != MAIL_NO_ERROR)
367     return r;
368 
369   switch (field->fld_type) {
370   case MAILIMF_FIELD_ORIG_DATE:
371     r = mailimf_cache_orig_date_write(mmapstr, indx,
372         field->fld_data.fld_orig_date);
373     break;
374   case MAILIMF_FIELD_FROM:
375     r = mailimf_cache_from_write(mmapstr, indx,
376         field->fld_data.fld_from);
377     break;
378   case MAILIMF_FIELD_SENDER:
379     r = mailimf_cache_sender_write(mmapstr, indx,
380         field->fld_data.fld_sender);
381     break;
382   case MAILIMF_FIELD_REPLY_TO:
383     r = mailimf_cache_reply_to_write(mmapstr, indx,
384         field->fld_data.fld_reply_to);
385     break;
386   case MAILIMF_FIELD_TO:
387     r = mailimf_cache_to_write(mmapstr, indx,
388         field->fld_data.fld_to);
389     break;
390   case MAILIMF_FIELD_CC:
391     r = mailimf_cache_cc_write(mmapstr, indx,
392         field->fld_data.fld_cc);
393     break;
394   case MAILIMF_FIELD_BCC:
395     r = mailimf_cache_bcc_write(mmapstr, indx,
396         field->fld_data.fld_bcc);
397     break;
398   case MAILIMF_FIELD_MESSAGE_ID:
399     r = mailimf_cache_message_id_write(mmapstr, indx,
400         field->fld_data.fld_message_id);
401     break;
402   case MAILIMF_FIELD_IN_REPLY_TO:
403     r = mailimf_cache_in_reply_to_write(mmapstr, indx,
404         field->fld_data.fld_in_reply_to);
405     break;
406   case MAILIMF_FIELD_REFERENCES:
407     r = mailimf_cache_references_write(mmapstr, indx,
408         field->fld_data.fld_references);
409     break;
410   case MAILIMF_FIELD_SUBJECT:
411     r = mailimf_cache_subject_write(mmapstr, indx,
412         field->fld_data.fld_subject);
413     break;
414   default:
415     r = 0;
416     break;
417   }
418 
419   if (r != MAIL_NO_ERROR)
420     return r;
421 
422   return MAIL_NO_ERROR;
423 }
424 
425 
mailimf_cache_field_read(MMAPString * mmapstr,size_t * indx,struct mailimf_field ** result)426 static int mailimf_cache_field_read(MMAPString * mmapstr, size_t * indx,
427 				    struct mailimf_field ** result)
428 {
429   int r;
430   uint32_t type;
431   struct mailimf_orig_date * orig_date;
432   struct mailimf_from * from;
433   struct mailimf_sender * sender;
434   struct mailimf_to * to;
435   struct mailimf_reply_to * reply_to;
436   struct mailimf_cc * cc;
437   struct mailimf_bcc * bcc;
438   struct mailimf_message_id * message_id;
439   struct mailimf_in_reply_to * in_reply_to;
440   struct mailimf_references * references;
441   struct mailimf_subject * subject;
442   struct mailimf_field * field;
443   int res;
444 
445   orig_date = NULL;
446   from = NULL;
447   sender = NULL;
448   to = NULL;
449   reply_to = NULL;
450   cc = NULL;
451   bcc = NULL;
452   message_id = NULL;
453   in_reply_to = NULL;
454   references = NULL;
455   subject = NULL;
456   field = NULL;
457 
458   r = mailimf_cache_int_read(mmapstr, indx, &type);
459   if (r != MAIL_NO_ERROR) {
460     res = r;
461     goto err;
462   }
463 
464   switch (type) {
465   case MAILIMF_FIELD_ORIG_DATE:
466     r = mailimf_cache_orig_date_read(mmapstr, indx, &orig_date);
467     break;
468   case MAILIMF_FIELD_FROM:
469     r = mailimf_cache_from_read(mmapstr, indx, &from);
470     break;
471   case MAILIMF_FIELD_SENDER:
472     r = mailimf_cache_sender_read(mmapstr, indx, &sender);
473     break;
474   case MAILIMF_FIELD_REPLY_TO:
475     r = mailimf_cache_reply_to_read(mmapstr, indx, &reply_to);
476     break;
477   case MAILIMF_FIELD_TO:
478     r = mailimf_cache_to_read(mmapstr, indx, &to);
479     break;
480   case MAILIMF_FIELD_CC:
481     r = mailimf_cache_cc_read(mmapstr, indx, &cc);
482     break;
483   case MAILIMF_FIELD_BCC:
484     r = mailimf_cache_bcc_read(mmapstr, indx, &bcc);
485     break;
486   case MAILIMF_FIELD_MESSAGE_ID:
487     r = mailimf_cache_message_id_read(mmapstr, indx, &message_id);
488     break;
489   case MAILIMF_FIELD_IN_REPLY_TO:
490     r = mailimf_cache_in_reply_to_read(mmapstr, indx, &in_reply_to);
491     break;
492   case MAILIMF_FIELD_REFERENCES:
493     r = mailimf_cache_references_read(mmapstr, indx, &references);
494     break;
495   case MAILIMF_FIELD_SUBJECT:
496     r = mailimf_cache_subject_read(mmapstr, indx, &subject);
497     break;
498   default:
499     r = MAIL_ERROR_INVAL;
500     break;
501   }
502 
503   if (r != MAIL_NO_ERROR) {
504     res = r;
505     goto free;
506   }
507 
508   field = mailimf_field_new(type, NULL, NULL, NULL, NULL, NULL,
509       NULL, NULL, NULL, orig_date, from, sender, reply_to,
510       to, cc, bcc, message_id,
511       in_reply_to, references,
512       subject, NULL, NULL, NULL);
513   if (field == NULL) {
514     res = MAIL_ERROR_MEMORY;
515     goto free;
516   }
517 
518   * result = field;
519 
520   return MAIL_NO_ERROR;
521 
522  free:
523   if (orig_date != NULL)
524     mailimf_orig_date_free(orig_date);
525   if (from != NULL)
526     mailimf_from_free(from);
527   if (sender != NULL)
528     mailimf_sender_free(sender);
529   if (reply_to != NULL)
530     mailimf_reply_to_free(reply_to);
531   if (to != NULL)
532     mailimf_to_free(to);
533   if (cc != NULL)
534     mailimf_cc_free(cc);
535   if (bcc != NULL)
536     mailimf_bcc_free(bcc);
537   if (message_id != NULL)
538     mailimf_message_id_free(message_id);
539   if (in_reply_to != NULL)
540     mailimf_in_reply_to_free(in_reply_to);
541   if (references != NULL)
542     mailimf_references_free(references);
543   if (subject != NULL)
544     mailimf_subject_free(subject);
545  err:
546   return res;
547 }
548 
mailimf_cache_orig_date_write(MMAPString * mmapstr,size_t * indx,struct mailimf_orig_date * date)549 static int mailimf_cache_orig_date_write(MMAPString * mmapstr, size_t * indx,
550 					 struct mailimf_orig_date * date)
551 {
552   return mailimf_cache_date_time_write(mmapstr, indx, date->dt_date_time);
553 }
554 
mailimf_cache_orig_date_read(MMAPString * mmapstr,size_t * indx,struct mailimf_orig_date ** result)555 static int mailimf_cache_orig_date_read(MMAPString * mmapstr, size_t * indx,
556 					struct mailimf_orig_date ** result)
557 {
558   int r;
559   struct mailimf_date_time * date_time;
560   struct mailimf_orig_date * orig_date;
561 
562   r = mailimf_cache_date_time_read(mmapstr, indx, &date_time);
563   if (r != MAIL_NO_ERROR)
564     return r;
565 
566   orig_date = mailimf_orig_date_new(date_time);
567   if (orig_date == NULL) {
568     mailimf_date_time_free(date_time);
569     return MAIL_ERROR_MEMORY;
570   }
571 
572   * result = orig_date;
573 
574   return MAIL_NO_ERROR;
575 }
576 
mailimf_cache_date_time_write(MMAPString * mmapstr,size_t * indx,struct mailimf_date_time * date_time)577 static int mailimf_cache_date_time_write(MMAPString * mmapstr, size_t * indx,
578 					 struct mailimf_date_time * date_time)
579 {
580   int r;
581 
582   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_day);
583   if (r != MAIL_NO_ERROR)
584     return r;
585 
586   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_month);
587   if (r != MAIL_NO_ERROR)
588     return r;
589 
590   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_year);
591   if (r != MAIL_NO_ERROR)
592     return r;
593 
594   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_hour);
595   if (r != MAIL_NO_ERROR)
596     return r;
597 
598   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_min);
599   if (r != MAIL_NO_ERROR)
600     return r;
601 
602   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_sec);
603   if (r != MAIL_NO_ERROR)
604     return r;
605 
606   r = mailimf_cache_int_write(mmapstr, indx, date_time->dt_zone);
607   if (r != MAIL_NO_ERROR)
608     return r;
609 
610   return MAIL_NO_ERROR;
611 }
612 
mailimf_cache_date_time_read(MMAPString * mmapstr,size_t * indx,struct mailimf_date_time ** result)613 static int mailimf_cache_date_time_read(MMAPString * mmapstr, size_t * indx,
614 					struct mailimf_date_time ** result)
615 {
616   int r;
617   uint32_t day;
618   uint32_t month;
619   uint32_t year;
620   uint32_t hour;
621   uint32_t min;
622   uint32_t sec;
623   uint32_t zone;
624   struct mailimf_date_time * date_time;
625 
626   r = mailimf_cache_int_read(mmapstr, indx, &day);
627   if (r != MAIL_NO_ERROR)
628     return r;
629 
630   r = mailimf_cache_int_read(mmapstr, indx, &month);
631   if (r != MAIL_NO_ERROR)
632     return r;
633 
634   r = mailimf_cache_int_read(mmapstr, indx, &year);
635   if (r != MAIL_NO_ERROR)
636     return r;
637 
638   r = mailimf_cache_int_read(mmapstr, indx, &hour);
639   if (r != MAIL_NO_ERROR)
640     return r;
641 
642   r = mailimf_cache_int_read(mmapstr, indx, &min);
643   if (r != MAIL_NO_ERROR)
644     return r;
645 
646   r = mailimf_cache_int_read(mmapstr, indx, &sec);
647   if (r != MAIL_NO_ERROR)
648     return r;
649 
650   r = mailimf_cache_int_read(mmapstr, indx, &zone);
651   if (r != MAIL_NO_ERROR)
652     return r;
653 
654   date_time = mailimf_date_time_new(day, month, year, hour, min, sec, zone);
655   if (date_time == NULL)
656     return MAIL_ERROR_MEMORY;
657 
658   * result = date_time;
659 
660   return MAIL_NO_ERROR;
661 
662 }
663 
664 
mailimf_cache_from_write(MMAPString * mmapstr,size_t * indx,struct mailimf_from * from)665 static int mailimf_cache_from_write(MMAPString * mmapstr, size_t * indx,
666 				    struct mailimf_from * from)
667 {
668   return mailimf_cache_mailbox_list_write(mmapstr, indx, from->frm_mb_list);
669 }
670 
mailimf_cache_from_read(MMAPString * mmapstr,size_t * indx,struct mailimf_from ** result)671 static int mailimf_cache_from_read(MMAPString * mmapstr, size_t * indx,
672 				   struct mailimf_from ** result)
673 {
674   struct mailimf_mailbox_list * mb_list;
675   struct mailimf_from * from;
676   int r;
677 
678   r = mailimf_cache_mailbox_list_read(mmapstr, indx, &mb_list);
679   if (r != MAIL_NO_ERROR)
680     return r;
681 
682   from = mailimf_from_new(mb_list);
683   if (from == NULL) {
684     mailimf_mailbox_list_free(mb_list);
685     return MAIL_ERROR_MEMORY;
686   }
687 
688   * result = from;
689 
690   return MAIL_NO_ERROR;
691 }
692 
mailimf_cache_sender_write(MMAPString * mmapstr,size_t * indx,struct mailimf_sender * sender)693 static int mailimf_cache_sender_write(MMAPString * mmapstr, size_t * indx,
694 				      struct mailimf_sender * sender)
695 {
696   return mailimf_cache_mailbox_write(mmapstr, indx, sender->snd_mb);
697 }
698 
mailimf_cache_sender_read(MMAPString * mmapstr,size_t * indx,struct mailimf_sender ** result)699 static int mailimf_cache_sender_read(MMAPString * mmapstr, size_t * indx,
700 				     struct mailimf_sender ** result)
701 {
702   int r;
703   struct mailimf_mailbox * mb;
704   struct mailimf_sender * sender;
705 
706   r = mailimf_cache_mailbox_read(mmapstr, indx, &mb);
707   if (r != MAIL_NO_ERROR)
708     return r;
709 
710   sender = mailimf_sender_new(mb);
711   if (sender == NULL) {
712     mailimf_mailbox_free(mb);
713     return MAIL_ERROR_MEMORY;
714   }
715 
716   * result = sender;
717 
718   return MAIL_NO_ERROR;
719 }
720 
mailimf_cache_reply_to_write(MMAPString * mmapstr,size_t * indx,struct mailimf_reply_to * reply_to)721 static int mailimf_cache_reply_to_write(MMAPString * mmapstr, size_t * indx,
722 					struct mailimf_reply_to * reply_to)
723 {
724   return mailimf_cache_address_list_write(mmapstr, indx,
725       reply_to->rt_addr_list);
726 }
727 
mailimf_cache_reply_to_read(MMAPString * mmapstr,size_t * indx,struct mailimf_reply_to ** result)728 static int mailimf_cache_reply_to_read(MMAPString * mmapstr, size_t * indx,
729 				       struct mailimf_reply_to ** result)
730 {
731   int r;
732   struct mailimf_address_list * addr_list;
733   struct mailimf_reply_to * reply_to;
734 
735   r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list);
736   if (r != MAIL_NO_ERROR)
737     return r;
738 
739   reply_to = mailimf_reply_to_new(addr_list);
740   if (reply_to == NULL) {
741     mailimf_address_list_free(addr_list);
742     return MAIL_ERROR_MEMORY;
743   }
744 
745   * result = reply_to;
746 
747   return MAIL_NO_ERROR;
748 }
749 
mailimf_cache_to_write(MMAPString * mmapstr,size_t * indx,struct mailimf_to * to)750 static int mailimf_cache_to_write(MMAPString * mmapstr, size_t * indx,
751 				  struct mailimf_to * to)
752 {
753   return mailimf_cache_address_list_write(mmapstr, indx, to->to_addr_list);
754 }
755 
mailimf_cache_to_read(MMAPString * mmapstr,size_t * indx,struct mailimf_to ** result)756 static int mailimf_cache_to_read(MMAPString * mmapstr, size_t * indx,
757 				 struct mailimf_to ** result)
758 {
759   int r;
760   struct mailimf_address_list * addr_list;
761   struct mailimf_to * to;
762 
763   r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list);
764   if (r != MAIL_NO_ERROR)
765     return r;
766 
767   to = mailimf_to_new(addr_list);
768   if (to == NULL) {
769     mailimf_address_list_free(addr_list);
770     return MAIL_ERROR_MEMORY;
771   }
772 
773   * result = to;
774 
775   return MAIL_NO_ERROR;
776 }
777 
mailimf_cache_cc_write(MMAPString * mmapstr,size_t * indx,struct mailimf_cc * cc)778 static int mailimf_cache_cc_write(MMAPString * mmapstr, size_t * indx,
779 				  struct mailimf_cc * cc)
780 {
781   return mailimf_cache_address_list_write(mmapstr, indx, cc->cc_addr_list);
782 }
783 
mailimf_cache_cc_read(MMAPString * mmapstr,size_t * indx,struct mailimf_cc ** result)784 static int mailimf_cache_cc_read(MMAPString * mmapstr, size_t * indx,
785     struct mailimf_cc ** result)
786 {
787   int r;
788   struct mailimf_address_list * addr_list;
789   struct mailimf_cc * cc;
790 
791   r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list);
792   if (r != MAIL_NO_ERROR)
793     return r;
794 
795   cc = mailimf_cc_new(addr_list);
796   if (cc == NULL) {
797     mailimf_address_list_free(addr_list);
798     return MAIL_ERROR_MEMORY;
799   }
800 
801   * result = cc;
802 
803   return MAIL_NO_ERROR;
804 }
805 
mailimf_cache_bcc_write(MMAPString * mmapstr,size_t * indx,struct mailimf_bcc * bcc)806 static int mailimf_cache_bcc_write(MMAPString * mmapstr, size_t * indx,
807 				   struct mailimf_bcc * bcc)
808 {
809   return mailimf_cache_address_list_write(mmapstr, indx, bcc->bcc_addr_list);
810 }
811 
mailimf_cache_bcc_read(MMAPString * mmapstr,size_t * indx,struct mailimf_bcc ** result)812 static int mailimf_cache_bcc_read(MMAPString * mmapstr, size_t * indx,
813 				  struct mailimf_bcc ** result)
814 {
815   int r;
816   struct mailimf_address_list * addr_list;
817   struct mailimf_bcc * bcc;
818 
819   r = mailimf_cache_address_list_read(mmapstr, indx, &addr_list);
820   if (r != MAIL_NO_ERROR)
821     return r;
822 
823   bcc = mailimf_bcc_new(addr_list);
824   if (bcc == NULL) {
825     mailimf_address_list_free(addr_list);
826     return MAIL_ERROR_MEMORY;
827   }
828 
829   * result = bcc;
830 
831   return MAIL_NO_ERROR;
832 }
833 
834 static int
mailimf_cache_message_id_write(MMAPString * mmapstr,size_t * indx,struct mailimf_message_id * message_id)835 mailimf_cache_message_id_write(MMAPString * mmapstr, size_t * indx,
836 			       struct mailimf_message_id * message_id)
837 {
838   return mailimf_cache_string_write(mmapstr, indx,
839       message_id->mid_value, strlen(message_id->mid_value));
840 }
841 
mailimf_cache_message_id_read(MMAPString * mmapstr,size_t * indx,struct mailimf_message_id ** result)842 static int mailimf_cache_message_id_read(MMAPString * mmapstr, size_t * indx,
843 					 struct mailimf_message_id ** result)
844 {
845   struct mailimf_message_id * message_id;
846   char * str;
847   int r;
848 
849   r = mailimf_cache_string_read(mmapstr, indx, &str);
850   if (r != MAIL_NO_ERROR)
851     return r;
852 
853   message_id = mailimf_message_id_new(str);
854   if (message_id == NULL) {
855     free(str);
856     return MAIL_ERROR_MEMORY;
857   }
858 
859   * result = message_id;
860 
861   return MAIL_NO_ERROR;
862 }
863 
864 static int
mailimf_cache_msg_id_list_write(MMAPString * mmapstr,size_t * indx,clist * list)865 mailimf_cache_msg_id_list_write(MMAPString * mmapstr, size_t * indx,
866 				clist * list)
867 {
868   clistiter * cur;
869   int r;
870 
871   r = mailimf_cache_int_write(mmapstr, indx, clist_count(list));
872   if (r != MAIL_NO_ERROR)
873     return r;
874 
875   for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
876     char * msgid;
877 
878     msgid = clist_content(cur);
879 
880     r = mailimf_cache_string_write(mmapstr, indx, msgid, strlen(msgid));
881     if (r != MAIL_NO_ERROR)
882       return r;
883   }
884 
885   return MAIL_NO_ERROR;
886 }
887 
mailimf_cache_msg_id_list_read(MMAPString * mmapstr,size_t * indx,clist ** result)888 static int mailimf_cache_msg_id_list_read(MMAPString * mmapstr, size_t * indx,
889 					  clist ** result)
890 {
891   clist * list;
892   int r;
893   uint32_t count;
894   uint32_t i;
895   int res;
896 
897   r = mailimf_cache_int_read(mmapstr, indx, &count);
898   if (r != MAIL_NO_ERROR) {
899     res = r;
900     goto err;
901   }
902 
903   list = clist_new();
904   if (list == NULL) {
905     res = MAIL_ERROR_MEMORY;
906     goto err;
907   }
908 
909   for(i = 0 ; i < count ; i++) {
910     char * msgid;
911 
912     r = mailimf_cache_string_read(mmapstr, indx, &msgid);
913     if (r != MAIL_NO_ERROR) {
914       res = r;
915       goto err;
916     }
917 
918     r = clist_append(list, msgid);
919     if (r < 0) {
920       free(msgid);
921       res = MAIL_ERROR_MEMORY;
922       goto free_list;
923     }
924   }
925 
926   * result = list;
927 
928   return MAIL_NO_ERROR;
929 
930  free_list:
931   clist_foreach(list, (clist_func) free, NULL);
932   clist_free(list);
933  err:
934   return res;
935 }
936 
937 static int
mailimf_cache_in_reply_to_write(MMAPString * mmapstr,size_t * indx,struct mailimf_in_reply_to * in_reply_to)938 mailimf_cache_in_reply_to_write(MMAPString * mmapstr, size_t * indx,
939 				struct mailimf_in_reply_to * in_reply_to)
940 {
941   return mailimf_cache_msg_id_list_write(mmapstr, indx,
942       in_reply_to->mid_list);
943 }
944 
mailimf_cache_in_reply_to_read(MMAPString * mmapstr,size_t * indx,struct mailimf_in_reply_to ** result)945 static int mailimf_cache_in_reply_to_read(MMAPString * mmapstr, size_t * indx,
946 					  struct mailimf_in_reply_to ** result)
947 {
948   int r;
949   clist * msg_id_list;
950   struct mailimf_in_reply_to * in_reply_to;
951 
952   r = mailimf_cache_msg_id_list_read(mmapstr, indx, &msg_id_list);
953   if (r != MAIL_NO_ERROR)
954     return r;
955 
956   in_reply_to = mailimf_in_reply_to_new(msg_id_list);
957   if (in_reply_to == NULL) {
958     clist_foreach(msg_id_list, (clist_func) free, NULL);
959     clist_free(msg_id_list);
960     return MAIL_ERROR_MEMORY;
961   }
962 
963   * result = in_reply_to;
964 
965   return MAIL_NO_ERROR;
966 }
967 
mailimf_cache_references_write(MMAPString * mmapstr,size_t * indx,struct mailimf_references * references)968 static int mailimf_cache_references_write(MMAPString * mmapstr, size_t * indx,
969 					  struct mailimf_references * references)
970 {
971   return mailimf_cache_msg_id_list_write(mmapstr, indx,
972       references->mid_list);
973 }
974 
mailimf_cache_references_read(MMAPString * mmapstr,size_t * indx,struct mailimf_references ** result)975 static int mailimf_cache_references_read(MMAPString * mmapstr, size_t * indx,
976 					 struct mailimf_references ** result)
977 {
978   int r;
979   clist * msg_id_list;
980   struct mailimf_references * references;
981 
982   r = mailimf_cache_msg_id_list_read(mmapstr, indx, &msg_id_list);
983   if (r != MAIL_NO_ERROR)
984     return r;
985 
986   references = mailimf_references_new(msg_id_list);
987   if (references == NULL) {
988     clist_foreach(msg_id_list, (clist_func) free, NULL);
989     clist_free(msg_id_list);
990     return MAIL_ERROR_MEMORY;
991   }
992 
993   * result = references;
994 
995   return MAIL_NO_ERROR;
996 }
997 
998 
mailimf_cache_subject_write(MMAPString * mmapstr,size_t * indx,struct mailimf_subject * subject)999 static int mailimf_cache_subject_write(MMAPString * mmapstr, size_t * indx,
1000 				       struct mailimf_subject * subject)
1001 {
1002   return mailimf_cache_string_write(mmapstr, indx,
1003       subject->sbj_value, strlen(subject->sbj_value));
1004 }
1005 
mailimf_cache_subject_read(MMAPString * mmapstr,size_t * indx,struct mailimf_subject ** result)1006 static int mailimf_cache_subject_read(MMAPString * mmapstr, size_t * indx,
1007 				      struct mailimf_subject ** result)
1008 {
1009   char * str;
1010   struct mailimf_subject * subject;
1011   int r;
1012 
1013   r = mailimf_cache_string_read(mmapstr, indx, &str);
1014   if (r != MAIL_NO_ERROR)
1015     return r;
1016 
1017   if (str == NULL) {
1018     str = strdup("");
1019     if (str == NULL)
1020       return MAIL_ERROR_MEMORY;
1021   }
1022 
1023   subject = mailimf_subject_new(str);
1024   if (subject == NULL) {
1025     free(str);
1026     return MAIL_ERROR_MEMORY;
1027   }
1028 
1029   * result = subject;
1030 
1031   return MAIL_NO_ERROR;
1032 }
1033 
1034 
1035 static int
mailimf_cache_address_list_write(MMAPString * mmapstr,size_t * indx,struct mailimf_address_list * addr_list)1036 mailimf_cache_address_list_write(MMAPString * mmapstr, size_t * indx,
1037 				 struct mailimf_address_list * addr_list)
1038 {
1039   clistiter * cur;
1040   int r;
1041 
1042   if (addr_list == NULL) {
1043     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER);
1044     if (r != MAIL_NO_ERROR)
1045       return r;
1046   }
1047   else {
1048     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL);
1049     if (r != MAIL_NO_ERROR)
1050       return r;
1051 
1052     r = mailimf_cache_int_write(mmapstr, indx,
1053         clist_count(addr_list->ad_list));
1054     if (r != MAIL_NO_ERROR)
1055       return r;
1056 
1057     for(cur = clist_begin(addr_list->ad_list) ; cur != NULL ;
1058         cur = clist_next(cur)) {
1059       struct mailimf_address * addr;
1060 
1061       addr = clist_content(cur);
1062 
1063       r = mailimf_cache_address_write(mmapstr, indx, addr);
1064       if (r != MAIL_NO_ERROR)
1065 	return r;
1066     }
1067   }
1068 
1069   return MAIL_NO_ERROR;
1070 }
1071 
1072 static int
mailimf_cache_address_list_read(MMAPString * mmapstr,size_t * indx,struct mailimf_address_list ** result)1073 mailimf_cache_address_list_read(MMAPString * mmapstr, size_t * indx,
1074 				struct mailimf_address_list ** result)
1075 {
1076   struct mailimf_address_list * addr_list;
1077   uint32_t count;
1078   uint32_t i;
1079   int r;
1080   clist * list;
1081   int res;
1082   uint32_t type;
1083 
1084   r = mailimf_cache_int_read(mmapstr, indx, &type);
1085   if (r != MAIL_NO_ERROR) {
1086     res = r;
1087     goto err;
1088   }
1089 
1090   if (type == CACHE_NULL_POINTER) {
1091     * result = NULL;
1092     return MAIL_NO_ERROR;
1093   }
1094 
1095   r = mailimf_cache_int_read(mmapstr, indx, &count);
1096   if (r != MAIL_NO_ERROR) {
1097     res = r;
1098     goto err;
1099   }
1100 
1101   list = clist_new();
1102   if (list == NULL) {
1103     res = MAIL_ERROR_MEMORY;
1104     goto err;
1105   }
1106 
1107   for(i = 0 ; i < count ; i++) {
1108     struct mailimf_address * addr;
1109 
1110     r = mailimf_cache_address_read(mmapstr, indx, &addr);
1111     if (r != MAIL_NO_ERROR) {
1112       res = r;
1113       goto free_list;
1114     }
1115 
1116     r = clist_append(list, addr);
1117     if (r < 0) {
1118       mailimf_address_free(addr);
1119       res = MAIL_ERROR_MEMORY;
1120       goto free_list;
1121     }
1122   }
1123 
1124   addr_list = mailimf_address_list_new(list);
1125   if (addr_list == NULL) {
1126     res = MAIL_ERROR_MEMORY;
1127     goto free_list;
1128   }
1129 
1130   * result = addr_list;
1131 
1132   return MAIL_NO_ERROR;
1133 
1134  free_list:
1135   clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1136   clist_free(list);
1137  err:
1138   return res;
1139 }
1140 
mailimf_cache_address_write(MMAPString * mmapstr,size_t * indx,struct mailimf_address * addr)1141 static int mailimf_cache_address_write(MMAPString * mmapstr, size_t * indx,
1142 				       struct mailimf_address * addr)
1143 {
1144   int r;
1145 
1146   r = mailimf_cache_int_write(mmapstr, indx, addr->ad_type);
1147   if (r != MAIL_NO_ERROR)
1148     return r;
1149 
1150   switch(addr->ad_type) {
1151   case MAILIMF_ADDRESS_MAILBOX:
1152     r = mailimf_cache_mailbox_write(mmapstr, indx, addr->ad_data.ad_mailbox);
1153     if (r != MAIL_NO_ERROR)
1154       return r;
1155 
1156     break;
1157 
1158   case MAILIMF_ADDRESS_GROUP:
1159     r = mailimf_cache_group_write(mmapstr, indx, addr->ad_data.ad_group);
1160     if (r != MAIL_NO_ERROR)
1161       return r;
1162 
1163     break;
1164   }
1165 
1166   return MAIL_NO_ERROR;
1167 }
1168 
mailimf_cache_address_read(MMAPString * mmapstr,size_t * indx,struct mailimf_address ** result)1169 static int mailimf_cache_address_read(MMAPString * mmapstr, size_t * indx,
1170 				      struct mailimf_address ** result)
1171 {
1172   uint32_t type;
1173   int r;
1174   struct mailimf_mailbox * mailbox;
1175   struct mailimf_group * group;
1176   struct mailimf_address * addr;
1177 
1178   r = mailimf_cache_int_read(mmapstr, indx, &type);
1179   if (r != MAIL_NO_ERROR)
1180     return r;
1181 
1182   mailbox = NULL;
1183   group = NULL;
1184 
1185   switch (type) {
1186   case MAILIMF_ADDRESS_MAILBOX:
1187     r = mailimf_cache_mailbox_read(mmapstr, indx, &mailbox);
1188     if (r != MAIL_NO_ERROR)
1189       return r;
1190 
1191     break;
1192 
1193   case MAILIMF_ADDRESS_GROUP:
1194     r = mailimf_cache_group_read(mmapstr, indx, &group);
1195     if (r != MAIL_NO_ERROR)
1196       return r;
1197 
1198     break;
1199   }
1200 
1201   addr = mailimf_address_new(type, mailbox, group);
1202   if (addr == NULL)
1203     goto free;
1204 
1205   * result = addr;
1206 
1207   return MAIL_NO_ERROR;
1208 
1209  free:
1210   if (mailbox != NULL)
1211     mailimf_mailbox_free(mailbox);
1212   if (group != NULL)
1213     mailimf_group_free(group);
1214   return MAIL_ERROR_MEMORY;
1215 }
1216 
mailimf_cache_group_write(MMAPString * mmapstr,size_t * indx,struct mailimf_group * group)1217 static int mailimf_cache_group_write(MMAPString * mmapstr, size_t * indx,
1218 				     struct mailimf_group * group)
1219 {
1220   int r;
1221 
1222   r = mailimf_cache_string_write(mmapstr, indx, group->grp_display_name,
1223 			   strlen(group->grp_display_name));
1224   if (r != MAIL_NO_ERROR)
1225     return r;
1226 
1227   r = mailimf_cache_mailbox_list_write(mmapstr, indx, group->grp_mb_list);
1228   if (r != MAIL_NO_ERROR)
1229     return r;
1230 
1231   return MAIL_NO_ERROR;
1232 }
1233 
mailimf_cache_group_read(MMAPString * mmapstr,size_t * indx,struct mailimf_group ** result)1234 static int mailimf_cache_group_read(MMAPString * mmapstr, size_t * indx,
1235 				    struct mailimf_group ** result)
1236 {
1237   int r;
1238   char * display_name;
1239   struct mailimf_mailbox_list * mb_list;
1240   struct mailimf_group * group;
1241   int res;
1242 
1243   r = mailimf_cache_string_read(mmapstr, indx, &display_name);
1244   if (r != MAIL_NO_ERROR) {
1245     res = r;
1246     goto err;
1247   }
1248 
1249   r = mailimf_cache_mailbox_list_read(mmapstr, indx, &mb_list);
1250   if (r != MAIL_NO_ERROR) {
1251     res = r;
1252     goto free_dsp_name;
1253   }
1254 
1255   group = mailimf_group_new(display_name, mb_list);
1256   if (group == NULL) {
1257     res = MAIL_ERROR_MEMORY;
1258     goto free_mb_list;
1259   }
1260 
1261   * result = group;
1262 
1263   return MAIL_NO_ERROR;
1264 
1265  free_mb_list:
1266   mailimf_mailbox_list_free(mb_list);
1267  free_dsp_name:
1268   free(display_name);
1269  err:
1270   return res;
1271 }
1272 
1273 static int
mailimf_cache_mailbox_list_write(MMAPString * mmapstr,size_t * indx,struct mailimf_mailbox_list * mb_list)1274 mailimf_cache_mailbox_list_write(MMAPString * mmapstr, size_t * indx,
1275 				 struct mailimf_mailbox_list * mb_list)
1276 {
1277   clistiter * cur;
1278   int r;
1279 
1280   if (mb_list == NULL) {
1281     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NULL_POINTER);
1282     if (r != MAIL_NO_ERROR)
1283       return r;
1284   }
1285   else {
1286     r = mailimf_cache_int_write(mmapstr, indx, CACHE_NOT_NULL);
1287     if (r != MAIL_NO_ERROR)
1288       return r;
1289 
1290     r = mailimf_cache_int_write(mmapstr, indx,
1291         clist_count(mb_list->mb_list));
1292     if (r != MAIL_NO_ERROR)
1293       return r;
1294 
1295     for(cur = clist_begin(mb_list->mb_list) ; cur != NULL ;
1296         cur = clist_next(cur)) {
1297       struct mailimf_mailbox * mb;
1298 
1299       mb = clist_content(cur);
1300 
1301       r = mailimf_cache_mailbox_write(mmapstr, indx, mb);
1302       if (r != MAIL_NO_ERROR)
1303         return r;
1304     }
1305   }
1306 
1307   return MAIL_NO_ERROR;
1308 }
1309 
1310 static int
mailimf_cache_mailbox_list_read(MMAPString * mmapstr,size_t * indx,struct mailimf_mailbox_list ** result)1311 mailimf_cache_mailbox_list_read(MMAPString * mmapstr, size_t * indx,
1312 				struct mailimf_mailbox_list ** result)
1313 {
1314   clist * list;
1315   int r;
1316   uint32_t count;
1317   uint32_t i;
1318   struct mailimf_mailbox_list * mb_list;
1319   int res;
1320   uint32_t type;
1321 
1322   r = mailimf_cache_int_read(mmapstr, indx, &type);
1323   if (r != MAIL_NO_ERROR) {
1324     res = r;
1325     goto err;
1326   }
1327 
1328   if (type == CACHE_NULL_POINTER) {
1329     * result = NULL;
1330     return MAIL_NO_ERROR;
1331   }
1332 
1333   r = mailimf_cache_int_read(mmapstr, indx, &count);
1334   if (r != MAIL_NO_ERROR) {
1335     res = r;
1336     goto err;
1337   }
1338 
1339   list = clist_new();
1340   if (list == NULL) {
1341     res = MAIL_ERROR_MEMORY;
1342     goto err;
1343   }
1344 
1345   for(i = 0 ; i < count ; i++) {
1346     struct mailimf_mailbox * mb;
1347 
1348     r = mailimf_cache_mailbox_read(mmapstr, indx, &mb);
1349     if (r != MAIL_NO_ERROR) {
1350       res = r;
1351       goto free_list;
1352     }
1353 
1354     r = clist_append(list, mb);
1355     if (r < 0) {
1356       mailimf_mailbox_free(mb);
1357       res = MAIL_ERROR_MEMORY;
1358       goto free_list;
1359     }
1360   }
1361 
1362   mb_list = mailimf_mailbox_list_new(list);
1363   if (mb_list == NULL) {
1364     res = MAIL_ERROR_MEMORY;
1365     goto free_list;
1366   }
1367 
1368   * result = mb_list;
1369 
1370   return MAIL_NO_ERROR;
1371 
1372  free_list:
1373   clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1374   clist_free(list);
1375  err:
1376   return res;
1377 }
1378 
mailimf_cache_mailbox_write(MMAPString * mmapstr,size_t * indx,struct mailimf_mailbox * mb)1379 static int mailimf_cache_mailbox_write(MMAPString * mmapstr, size_t * indx,
1380 				       struct mailimf_mailbox * mb)
1381 {
1382   int r;
1383 
1384   if (mb->mb_display_name) {
1385     r = mailimf_cache_string_write(mmapstr, indx,
1386         mb->mb_display_name, strlen(mb->mb_display_name));
1387     if (r != MAIL_NO_ERROR)
1388       return r;
1389   }
1390   else {
1391     r = mailimf_cache_string_write(mmapstr, indx, NULL, 0);
1392     if (r != MAIL_NO_ERROR)
1393       return r;
1394   }
1395 
1396   r = mailimf_cache_string_write(mmapstr, indx,
1397       mb->mb_addr_spec, strlen(mb->mb_addr_spec));
1398   if (r != MAIL_NO_ERROR)
1399     return r;
1400 
1401   return MAIL_NO_ERROR;
1402 }
1403 
mailimf_cache_mailbox_read(MMAPString * mmapstr,size_t * indx,struct mailimf_mailbox ** result)1404 static int mailimf_cache_mailbox_read(MMAPString * mmapstr, size_t * indx,
1405 				      struct mailimf_mailbox ** result)
1406 {
1407   int r;
1408   char * dsp_name;
1409   char * addr_spec;
1410   struct mailimf_mailbox * mb;
1411 
1412   dsp_name = NULL;
1413 
1414   r = mailimf_cache_string_read(mmapstr, indx, &dsp_name);
1415   if (r != MAIL_NO_ERROR)
1416     return r;
1417 
1418   r = mailimf_cache_string_read(mmapstr, indx, &addr_spec);
1419   if (r != MAIL_NO_ERROR)
1420     goto free_dsp_name;
1421 
1422   mb = mailimf_mailbox_new(dsp_name, addr_spec);
1423   if (mb == NULL)
1424     goto free_addr;
1425 
1426   * result = mb;
1427 
1428   return MAIL_NO_ERROR;
1429 
1430  free_addr:
1431   free(addr_spec);
1432  free_dsp_name:
1433   if (dsp_name != NULL)
1434     free(dsp_name);
1435   return MAIL_ERROR_MEMORY;
1436 }
1437