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