1 /*
2 ** Copyright 2004-2007 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <ctype.h>
14 #include <fcntl.h>
15 #if HAVE_UNISTD_H
16 #include <unistd.h>
17 #endif
18 #if HAVE_UTIME_H
19 #include <utime.h>
20 #endif
21 #if TIME_WITH_SYS_TIME
22 #include <sys/time.h>
23 #include <time.h>
24 #else
25 #if HAVE_SYS_TIME_H
26 #include <sys/time.h>
27 #else
28 #include <time.h>
29 #endif
30 #endif
31
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #include "config.h"
36 #include "maildir/maildirnewshared.h"
37
38
39 static struct maildir_shindex_cache *shared_cache=NULL;
40
shared_cache_free(struct maildir_shindex_cache * c)41 static void shared_cache_free(struct maildir_shindex_cache *c)
42 {
43 while (c)
44 {
45 struct maildir_shindex_cache *p=c;
46 size_t i;
47
48 c=c->next;
49
50 free(p->hierarchy);
51 if (p->records)
52 {
53 for (i=0; i<p->nrecords; i++)
54 free(p->records[i].name);
55 free(p->records);
56 }
57 maildir_newshared_close(&p->indexfile);
58 free(p);
59 }
60 }
61
62 static struct maildir_shindex_cache *do_shared_cache_read(const char *indexfile,
63 const char *subhier);
64
65 struct maildir_shindex_cache *
maildir_shared_cache_read(struct maildir_shindex_cache * parent,const char * indexfile,const char * subhierarchy)66 maildir_shared_cache_read(struct maildir_shindex_cache *parent,
67 const char *indexfile,
68 const char *subhierarchy)
69 {
70 struct maildir_shindex_cache *p;
71
72 if (parent && parent->next && subhierarchy &&
73 strcmp(parent->next->hierarchy, subhierarchy) == 0)
74 {
75 return parent->next; /* That was easy */
76 }
77
78 if (!parent && shared_cache)
79 {
80 return shared_cache;
81 }
82
83 if (!indexfile)
84 {
85 indexfile=maildir_shared_index_file();
86 if (!indexfile)
87 return NULL;
88 subhierarchy="";
89 }
90
91
92 if (!subhierarchy)
93 return NULL;
94 /* Should not happen, bad usage. subhierarchy allowed to be NULL only
95 ** when indexfile is also NULL */
96
97 p=do_shared_cache_read(indexfile, subhierarchy);
98
99 if (!p)
100 return NULL;
101
102 if (!parent)
103 {
104 shared_cache_free(shared_cache);
105 shared_cache=p;
106 }
107 else
108 {
109 shared_cache_free(parent->next);
110 parent->next=p;
111 }
112 return p;
113 }
114
115 struct maildir_shindex_temp_record {
116 struct maildir_shindex_temp_record *next;
117 struct maildir_shindex_record rec;
118 };
119
shared_cache_read_cb(struct maildir_newshared_enum_cb * ptr)120 static int shared_cache_read_cb(struct maildir_newshared_enum_cb *ptr)
121 {
122 struct maildir_shindex_temp_record *r;
123 struct maildir_shindex_temp_record **list=
124 (struct maildir_shindex_temp_record **)ptr->cb_arg;
125
126 if ((r=malloc(sizeof(struct maildir_shindex_temp_record))) == NULL ||
127 (r->rec.name=strdup(ptr->name)) == NULL)
128 {
129 if (r)
130 free(r);
131 perror("malloc");
132 return -1;
133 }
134
135 r->rec.offset=ptr->startingpos;
136 r->next= *list;
137 *list=r;
138 return 0;
139 }
140
do_shared_cache_read(const char * indexfile,const char * subhier)141 static struct maildir_shindex_cache *do_shared_cache_read(const char *indexfile,
142 const char *subhier)
143 {
144 struct maildir_shindex_temp_record *rec=NULL;
145 size_t n;
146 struct maildir_shindex_cache *c;
147 int eof;
148 int rc;
149
150 if ((c=malloc(sizeof(struct maildir_shindex_cache))) == NULL ||
151 (c->hierarchy=strdup(subhier)) == NULL)
152 {
153 if (c)
154 free(c);
155 perror("malloc");
156 return NULL;
157 }
158
159 if (maildir_newshared_open(indexfile, &c->indexfile) < 0)
160 {
161 free(c->hierarchy);
162 free(c);
163 return NULL;
164 }
165
166 n=0;
167
168 while ((rc=maildir_newshared_next(&c->indexfile, &eof,
169 shared_cache_read_cb, &rec)) == 0)
170 {
171 if (eof)
172 break;
173 ++n;
174 }
175
176 if (rc)
177 {
178 free(c->hierarchy);
179 free(c);
180 while (rec)
181 {
182 struct maildir_shindex_temp_record *r=rec;
183
184 rec=rec->next;
185
186 free(r->rec.name);
187 free(r);
188 }
189 return NULL;
190 }
191
192 /* Now, convert from list to array */
193
194 c->nrecords=n;
195 c->records=NULL;
196 c->next=NULL;
197
198 if (n)
199 {
200 if ((c->records=malloc(sizeof(*c->records)*n)) == NULL)
201 {
202
203 free(c->hierarchy);
204 free(c);
205 while (rec)
206 {
207 struct maildir_shindex_temp_record *r=rec;
208
209 rec=rec->next;
210
211 free(r->rec.name);
212 free(r);
213 }
214 return NULL;
215 }
216
217 n=0;
218 while (rec)
219 {
220 struct maildir_shindex_temp_record *r=rec;
221
222 rec=rec->next;
223 c->records[n]= r->rec;
224
225 free(r);
226 ++n;
227 }
228 }
229
230 return c;
231 }
232
233
234
235
236
237
238