summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/mh/mailmh.c473
1 files changed, 239 insertions, 234 deletions
diff --git a/kmicromail/libetpan/mh/mailmh.c b/kmicromail/libetpan/mh/mailmh.c
index 5e2b4cc..1087ce1 100644
--- a/kmicromail/libetpan/mh/mailmh.c
+++ b/kmicromail/libetpan/mh/mailmh.c
@@ -31,822 +31,827 @@
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36#include "mailmh.h" 36#include "mailmh.h"
37 37
38/* 38/*
39perfs : 39perfs :
40 40
41/net/home/dinh/Mail/inbox/sylpheed 686 41/net/home/dinh/Mail/inbox/sylpheed 686
42 42
432724 /net/home/dinh/Mail/inbox/sylpheed 432724 /net/home/dinh/Mail/inbox/sylpheed
44 44
45bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null 45bart:~/LibEtPan/libetpan/tests> time ./mhtest >/dev/null
46 46
47real 0m0.385s 47real 0m0.385s
48user 0m0.270s 48user 0m0.270s
49sys 0m0.110s 49sys 0m0.110s
50 50
51*/ 51*/
52 52
53#include <dirent.h> 53#include <dirent.h>
54#include <sys/stat.h> 54#include <sys/stat.h>
55#include <errno.h> 55#include <errno.h>
56#include <unistd.h> 56#include <unistd.h>
57#include <sys/mman.h> 57#include <sys/mman.h>
58#include <fcntl.h> 58#include <fcntl.h>
59#include <stdio.h> 59#include <stdio.h>
60#include <stdlib.h> 60#include <stdlib.h>
61#include <string.h> 61#include <string.h>
62 62
63#include "libetpan-config.h" 63#include "libetpan-config.h"
64 64
65struct mailmh * mailmh_new(const char * foldername) 65struct mailmh * mailmh_new(const char * foldername)
66{ 66{
67 struct mailmh * f; 67 struct mailmh * f;
68 68
69 f = malloc(sizeof(*f)); 69 f = malloc(sizeof(*f));
70 if (f == NULL) 70 if (f == NULL)
71 return NULL; 71 return NULL;
72 72
73 f->mh_main = mailmh_folder_new(NULL, foldername); 73 f->mh_main = mailmh_folder_new(NULL, foldername);
74 if (f->mh_main == NULL) { 74 if (f->mh_main == NULL) {
75 free(f); 75 free(f);
76 return NULL; 76 return NULL;
77 } 77 }
78 78
79 return f; 79 return f;
80} 80}
81 81
82void mailmh_free(struct mailmh * f) 82void mailmh_free(struct mailmh * f)
83{ 83{
84 mailmh_folder_free(f->mh_main); 84 mailmh_folder_free(f->mh_main);
85 free(f); 85 free(f);
86} 86}
87 87
88 88
89 89
90struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size, 90struct mailmh_msg_info * mailmh_msg_info_new(uint32_t index, size_t size,
91 time_t mtime) 91 time_t mtime)
92{ 92{
93 struct mailmh_msg_info * msg_info; 93 struct mailmh_msg_info * msg_info;
94 94
95 msg_info = malloc(sizeof(* msg_info)); 95 msg_info = malloc(sizeof(* msg_info));
96 if (msg_info == NULL) 96 if (msg_info == NULL)
97 return NULL; 97 return NULL;
98 msg_info->msg_index = index; 98 msg_info->msg_index = index;
99 msg_info->msg_size = size; 99 msg_info->msg_size = size;
100 msg_info->msg_mtime = mtime; 100 msg_info->msg_mtime = mtime;
101 101
102 msg_info->msg_array_index = 0; 102 msg_info->msg_array_index = 0;
103 103
104 return msg_info; 104 return msg_info;
105} 105}
106 106
107void mailmh_msg_info_free(struct mailmh_msg_info * msg_info) 107void mailmh_msg_info_free(struct mailmh_msg_info * msg_info)
108{ 108{
109 free(msg_info); 109 free(msg_info);
110} 110}
111 111
112struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent, 112struct mailmh_folder * mailmh_folder_new(struct mailmh_folder * parent,
113 const char * name) 113 const char * name)
114{ 114{
115 char * filename; 115 char * filename;
116 char * parent_filename; 116 char * parent_filename;
117 117
118 struct mailmh_folder * folder; 118 struct mailmh_folder * folder;
119 119
120 folder = malloc(sizeof(* folder)); 120 folder = malloc(sizeof(* folder));
121 if (folder == NULL) 121 if (folder == NULL)
122 goto err; 122 goto err;
123 123
124 if (parent == NULL) { 124 if (parent == NULL) {
125 filename = strdup(name); 125 filename = strdup(name);
126 if (filename == NULL) 126 if (filename == NULL)
127 goto free_folder; 127 goto free_folder;
128 } 128 }
129 else { 129 else {
130 parent_filename = parent->fl_filename; 130 parent_filename = parent->fl_filename;
131 filename = malloc(strlen(parent_filename) + strlen(name) + 2); 131 filename = malloc(strlen(parent_filename) + strlen(name) + 2);
132 if (filename == NULL) 132 if (filename == NULL)
133 goto free_folder; 133 goto free_folder;
134 134
135 strcpy(filename, parent_filename); 135 strcpy(filename, parent_filename);
136 strcat(filename, MAIL_DIR_SEPARATOR_S); 136 strcat(filename, MAIL_DIR_SEPARATOR_S);
137 strcat(filename, name); 137 strcat(filename, name);
138 } 138 }
139 139
140 folder->fl_filename = filename; 140 folder->fl_filename = filename;
141 141
142 folder->fl_name = strdup(name); 142 folder->fl_name = strdup(name);
143 if (folder->fl_name == NULL) 143 if (folder->fl_name == NULL)
144 goto free_filename; 144 goto free_filename;
145 145
146 folder->fl_msgs_tab = carray_new(128); 146 folder->fl_msgs_tab = carray_new(128);
147 if (folder->fl_msgs_tab == NULL) 147 if (folder->fl_msgs_tab == NULL)
148 goto free_name; 148 goto free_name;
149 149
150#if 0 150#if 0
151 folder->fl_msgs_hash = cinthash_new(128); 151 folder->fl_msgs_hash = cinthash_new(128);
152 if (folder->fl_msgs_hash == NULL) 152 if (folder->fl_msgs_hash == NULL)
153 goto free_msgs_tab; 153 goto free_msgs_tab;
154#endif 154#endif
155 folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY); 155 folder->fl_msgs_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
156 if (folder->fl_msgs_hash == NULL) 156 if (folder->fl_msgs_hash == NULL)
157 goto free_msgs_tab; 157 goto free_msgs_tab;
158 158
159 folder->fl_subfolders_tab = carray_new(128); 159 folder->fl_subfolders_tab = carray_new(128);
160 if (folder->fl_subfolders_tab == NULL) 160 if (folder->fl_subfolders_tab == NULL)
161 goto free_msgs_hash; 161 goto free_msgs_hash;
162 162
163 folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE); 163 folder->fl_subfolders_hash = chash_new(128, CHASH_COPYNONE);
164 if (folder->fl_subfolders_hash == NULL) 164 if (folder->fl_subfolders_hash == NULL)
165 goto free_subfolders_tab; 165 goto free_subfolders_tab;
166 166
167 folder->fl_mtime = 0; 167 folder->fl_mtime = 0;
168 folder->fl_parent = parent; 168 folder->fl_parent = parent;
169 folder->fl_max_index = 0; 169 folder->fl_max_index = 0;
170 170
171 return folder; 171 return folder;
172 172
173 free_subfolders_tab: 173 free_subfolders_tab:
174 carray_free(folder->fl_subfolders_tab); 174 carray_free(folder->fl_subfolders_tab);
175 free_msgs_hash: 175 free_msgs_hash:
176#if 0 176#if 0
177 cinthash_free(folder->fl_msgs_hash); 177 cinthash_free(folder->fl_msgs_hash);
178#endif 178#endif
179 chash_free(folder->fl_msgs_hash); 179 chash_free(folder->fl_msgs_hash);
180 free_msgs_tab: 180 free_msgs_tab:
181 carray_free(folder->fl_msgs_tab); 181 carray_free(folder->fl_msgs_tab);
182 free_name: 182 free_name:
183 free(folder->fl_name); 183 free(folder->fl_name);
184 free_filename: 184 free_filename:
185 free(folder->fl_filename); 185 free(folder->fl_filename);
186 free_folder: 186 free_folder:
187 free(folder); 187 free(folder);
188 err: 188 err:
189 return NULL; 189 return NULL;
190} 190}
191 191
192void mailmh_folder_free(struct mailmh_folder * folder) 192void mailmh_folder_free(struct mailmh_folder * folder)
193{ 193{
194 unsigned int i; 194 unsigned int i;
195 195
196 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) { 196 for(i = 0 ; i < carray_count(folder->fl_subfolders_tab) ; i++) {
197 struct mailmh_folder * subfolder; 197 struct mailmh_folder * subfolder;
198 198
199 subfolder = carray_get(folder->fl_subfolders_tab, i); 199 subfolder = carray_get(folder->fl_subfolders_tab, i);
200 if (subfolder != NULL) 200 if (subfolder != NULL)
201 mailmh_folder_free(subfolder); 201 mailmh_folder_free(subfolder);
202 } 202 }
203 carray_free(folder->fl_subfolders_tab); 203 carray_free(folder->fl_subfolders_tab);
204 chash_free(folder->fl_subfolders_hash); 204 chash_free(folder->fl_subfolders_hash);
205 205
206 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) { 206 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i++) {
207 struct mailmh_msg_info * msg_info; 207 struct mailmh_msg_info * msg_info;
208 208
209 msg_info = carray_get(folder->fl_msgs_tab, i); 209 msg_info = carray_get(folder->fl_msgs_tab, i);
210 if (msg_info != NULL) 210 if (msg_info != NULL)
211 mailmh_msg_info_free(msg_info); 211 mailmh_msg_info_free(msg_info);
212 } 212 }
213 carray_free(folder->fl_msgs_tab); 213 carray_free(folder->fl_msgs_tab);
214 chash_free(folder->fl_msgs_hash); 214 chash_free(folder->fl_msgs_hash);
215#if 0 215#if 0
216 cinthash_free(folder->fl_msgs_hash); 216 cinthash_free(folder->fl_msgs_hash);
217#endif 217#endif
218 218
219 free(folder->fl_filename); 219 free(folder->fl_filename);
220 free(folder->fl_name); 220 free(folder->fl_name);
221 221
222 free(folder); 222 free(folder);
223} 223}
224 224
225struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root, 225struct mailmh_folder * mailmh_folder_find(struct mailmh_folder * root,
226 const char * filename) 226 const char * filename)
227{ 227{
228 int r; 228 int r;
229 char pathname[PATH_MAX]; 229 char pathname[PATH_MAX];
230 char * p; 230 char * p;
231 chashdatum key; 231 chashdatum key;
232 chashdatum data; 232 chashdatum data;
233 struct mailmh_folder * folder; 233 struct mailmh_folder * folder;
234 char * start; 234 char * start;
235 235
236 if (strcmp(root->fl_filename, filename) == 0) 236 if (strcmp(root->fl_filename, filename) == 0)
237 return root; 237 return root;
238 238
239#if 0 239#if 0
240 r = mailmh_folder_update(root); 240 r = mailmh_folder_update(root);
241 if (r != MAILMH_NO_ERROR) 241 if (r != MAILMH_NO_ERROR)
242 return NULL; 242 return NULL;
243#endif 243#endif
244 244
245#if 0 245#if 0
246 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) { 246 for(i = 0 ; i < root->fl_subfolders_tab->len ; i++) {
247 struct mailmh_folder * subfolder; 247 struct mailmh_folder * subfolder;
248 248
249 subfolder = carray_get(root->fl_subfolders_tab, i); 249 subfolder = carray_get(root->fl_subfolders_tab, i);
250 if (subfolder != NULL) 250 if (subfolder != NULL)
251 if (strncmp(subfolder->fl_filename, filename, 251 if (strncmp(subfolder->fl_filename, filename,
252 strlen(subfolder->fl_filename)) == 0) 252 strlen(subfolder->fl_filename)) == 0)
253 return mailmh_folder_find(subfolder, filename); 253 return mailmh_folder_find(subfolder, filename);
254 } 254 }
255#endif 255#endif
256 strncpy(pathname, filename, PATH_MAX); 256 strncpy(pathname, filename, PATH_MAX);
257 pathname[PATH_MAX - 1] = 0; 257 pathname[PATH_MAX - 1] = 0;
258 start = pathname + strlen(root->fl_filename) + 1; 258 start = pathname + strlen(root->fl_filename) + 1;
259 259
260 p = strchr(start, MAIL_DIR_SEPARATOR); 260 p = strchr(start, MAIL_DIR_SEPARATOR);
261 if (p != NULL) { 261 if (p != NULL) {
262 * p = 0; 262 * p = 0;
263 263
264 root = mailmh_folder_find(root, pathname); 264 root = mailmh_folder_find(root, pathname);
265 if (root != NULL) { 265 if (root != NULL) {
266 folder = mailmh_folder_find(root, filename); 266 folder = mailmh_folder_find(root, filename);
267 if (folder == NULL) 267 if (folder == NULL)
268 return NULL; 268 return NULL;
269 return folder; 269 return folder;
270 } 270 }
271 271
272 return NULL; 272 return NULL;
273 } 273 }
274 else { 274 else {
275 key.data = pathname; 275 key.data = pathname;
276 key.len = strlen(pathname); 276 key.len = strlen(pathname);
277 r = chash_get(root->fl_subfolders_hash, &key, &data); 277 r = chash_get(root->fl_subfolders_hash, &key, &data);
278 if (r < 0) 278 if (r < 0)
279 return NULL; 279 return NULL;
280 280
281 return data.data; 281 return data.data;
282 } 282 }
283} 283}
284 284
285int mailmh_folder_update(struct mailmh_folder * folder) 285int mailmh_folder_update(struct mailmh_folder * folder)
286{ 286{
287 DIR * d; 287 DIR * d;
288 struct dirent * ent; 288 struct dirent * ent;
289 struct stat buf; 289 struct stat buf;
290 char * mh_seq; 290 char * mh_seq;
291 char filename[PATH_MAX]; 291 char filename[PATH_MAX];
292 int res; 292 int res;
293 int r; 293 int r;
294 uint32_t max_index; 294 uint32_t max_index;
295#if 0 295#if 0
296 int add_folder; 296 int add_folder;
297#endif 297#endif
298 unsigned int i; 298 unsigned int i;
299 299
300 if (stat(folder->fl_filename, &buf) == -1) { 300 if (stat(folder->fl_filename, &buf) == -1) {
301 res = MAILMH_ERROR_FOLDER; 301 res = MAILMH_ERROR_FOLDER;
302 goto err; 302 goto err;
303 } 303 }
304 304
305 if (folder->fl_mtime == buf.st_mtime) { 305 if (folder->fl_mtime == buf.st_mtime) {
306 res = MAILMH_NO_ERROR; 306 res = MAILMH_NO_ERROR;
307 goto err; 307 goto err;
308 } 308 }
309 309
310 folder->fl_mtime = buf.st_mtime; 310 folder->fl_mtime = buf.st_mtime;
311 311
312 d = opendir(folder->fl_filename); 312 d = opendir(folder->fl_filename);
313 if (d == NULL) { 313 if (d == NULL) {
314 res = MAILMH_ERROR_FOLDER; 314 res = MAILMH_ERROR_FOLDER;
315 goto err; 315 goto err;
316 } 316 }
317 317
318 max_index = 0; 318 max_index = 0;
319 319
320#if 0 320#if 0
321 if (folder->fl_subfolders_tab->len == 0) 321 if (folder->fl_subfolders_tab->len == 0)
322 add_folder = 1; 322 add_folder = 1;
323 else 323 else
324 add_folder = 0; 324 add_folder = 0;
325#endif 325#endif
326 326
327 /* clear the message list */ 327 /* clear the message list */
328 328
329 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) { 329 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) {
330 struct mailmh_msg_info * msg_info; 330 struct mailmh_msg_info * msg_info;
331 chashdatum key; 331 chashdatum key;
332 332
333 msg_info = carray_get(folder->fl_msgs_tab, i); 333 msg_info = carray_get(folder->fl_msgs_tab, i);
334 if (msg_info == NULL) 334 if (msg_info == NULL)
335 continue; 335 continue;
336 336
337#if 0 337#if 0
338 cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index); 338 cinthash_remove(folder->fl_msgs_hash, msg_info->msg_index);
339#endif 339#endif
340 key.data = &msg_info->msg_index; 340 key.data = &msg_info->msg_index;
341 key.len = sizeof(msg_info->msg_index); 341 key.len = sizeof(msg_info->msg_index);
342 chash_delete(folder->fl_msgs_hash, &key, NULL); 342 chash_delete(folder->fl_msgs_hash, &key, NULL);
343 343
344 mailmh_msg_info_free(msg_info); 344 mailmh_msg_info_free(msg_info);
345 } 345 }
346 346
347 carray_set_size(folder->fl_msgs_tab, 0); 347 carray_set_size(folder->fl_msgs_tab, 0);
348 348
349 do { 349 do {
350 uint32_t index; 350 uint32_t index;
351 351
352 ent = readdir(d); 352 ent = readdir(d);
353 353
354 if (ent != NULL) { 354 if (ent != NULL) {
355 355
356 snprintf(filename, PATH_MAX, 356 snprintf(filename, PATH_MAX,
357 "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name); 357 "%s%c%s", folder->fl_filename, MAIL_DIR_SEPARATOR, ent->d_name);
358 358
359 if (stat(filename, &buf) == -1) 359 if (stat(filename, &buf) == -1)
360 continue; 360 continue;
361 361
362 if (S_ISREG(buf.st_mode)) { 362 if (S_ISREG(buf.st_mode)) {
363 index = strtoul(ent->d_name, NULL, 10); 363 index = strtoul(ent->d_name, NULL, 10);
364 if (index != 0) { 364 if (index != 0) {
365 struct mailmh_msg_info * msg_info; 365 struct mailmh_msg_info * msg_info;
366 unsigned int array_index; 366 unsigned int array_index;
367 chashdatum key; 367 chashdatum key;
368 chashdatum data; 368 chashdatum data;
369 369
370 msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime); 370 msg_info = mailmh_msg_info_new(index, buf.st_size, buf.st_mtime);
371 if (msg_info == NULL) { 371 if (msg_info == NULL) {
372 res = MAILMH_ERROR_MEMORY; 372 res = MAILMH_ERROR_MEMORY;
373 goto closedir; 373 goto closedir;
374 } 374 }
375 375
376 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); 376 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
377 if (r < 0) { 377 if (r < 0) {
378 mailmh_msg_info_free(msg_info); 378 mailmh_msg_info_free(msg_info);
379 res = MAILMH_ERROR_MEMORY; 379 res = MAILMH_ERROR_MEMORY;
380 goto closedir; 380 goto closedir;
381 } 381 }
382 msg_info->msg_array_index = array_index; 382 msg_info->msg_array_index = array_index;
383 383
384 if (index > max_index) 384 if (index > max_index)
385 max_index = index; 385 max_index = index;
386 386
387#if 0 387#if 0
388 r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info); 388 r = cinthash_add(folder->fl_msgs_hash, msg_info->msg_index, msg_info);
389#endif 389#endif
390 key.data = &msg_info->msg_index; 390 key.data = &msg_info->msg_index;
391 key.len = sizeof(msg_info->msg_index); 391 key.len = sizeof(msg_info->msg_index);
392 data.data = msg_info; 392 data.data = msg_info;
393 data.len = 0; 393 data.len = 0;
394 394
395 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); 395 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
396 if (r < 0) { 396 if (r < 0) {
397 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 397 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
398 mailmh_msg_info_free(msg_info); 398 mailmh_msg_info_free(msg_info);
399 res = MAILMH_ERROR_MEMORY; 399 res = MAILMH_ERROR_MEMORY;
400 goto closedir; 400 goto closedir;
401 } 401 }
402 } 402 //LR memory leak? added next line
403 } 403 //mailmh_msg_info_free(msg_info);
404 else if (S_ISDIR(buf.st_mode)) { 404 //it seems so that it should be freed later,
405 struct mailmh_folder * subfolder; 405 // but it is not in every case
406 unsigned int array_index; 406 //PENDING fixme in ompi somewhere
407 chashdatum key; 407 }
408 chashdatum data; 408 }
409 409 else if (S_ISDIR(buf.st_mode)) {
410 if (ent->d_name[0] == '.') { 410 struct mailmh_folder * subfolder;
411 if (ent->d_name[1] == 0) 411 unsigned int array_index;
412 continue; 412 chashdatum key;
413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) 413 chashdatum data;
414 continue; 414
415 } 415 if (ent->d_name[0] == '.') {
416 416 if (ent->d_name[1] == 0)
417 key.data = ent->d_name; 417 continue;
418 key.len = strlen(ent->d_name); 418 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))
419 r = chash_get(folder->fl_subfolders_hash, &key, &data); 419 continue;
420 if (r < 0) { 420 }
421 subfolder = mailmh_folder_new(folder, ent->d_name); 421
422 if (subfolder == NULL) { 422 key.data = ent->d_name;
423 res = MAILMH_ERROR_MEMORY; 423 key.len = strlen(ent->d_name);
424 goto closedir; 424 r = chash_get(folder->fl_subfolders_hash, &key, &data);
425 } 425 if (r < 0) {
426 subfolder = mailmh_folder_new(folder, ent->d_name);
427 if (subfolder == NULL) {
428 res = MAILMH_ERROR_MEMORY;
429 goto closedir;
430 }
426 431
427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); 432 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index);
428 if (r < 0) { 433 if (r < 0) {
429 mailmh_folder_free(subfolder); 434 mailmh_folder_free(subfolder);
430 res = MAILMH_ERROR_MEMORY; 435 res = MAILMH_ERROR_MEMORY;
431 goto closedir; 436 goto closedir;
432 } 437 }
433 subfolder->fl_array_index = array_index; 438 subfolder->fl_array_index = array_index;
434 439
435 key.data = subfolder->fl_filename; 440 key.data = subfolder->fl_filename;
436 key.len = strlen(subfolder->fl_filename); 441 key.len = strlen(subfolder->fl_filename);
437 data.data = subfolder; 442 data.data = subfolder;
438 data.len = 0; 443 data.len = 0;
439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); 444 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL);
440 if (r < 0) { 445 if (r < 0) {
441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); 446 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index);
442 mailmh_folder_free(subfolder); 447 mailmh_folder_free(subfolder);
443 res = MAILMH_ERROR_MEMORY; 448 res = MAILMH_ERROR_MEMORY;
444 goto closedir; 449 goto closedir;
445 } 450 }
446 } 451 }
447 } 452 }
453 }
448 } 454 }
449 } 455 while (ent != NULL);
450 while (ent != NULL);
451 456
452 folder->fl_max_index = max_index; 457 folder->fl_max_index = max_index;
453 458
454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); 459 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences"));
455 if (mh_seq == NULL) { 460 if (mh_seq == NULL) {
456 res = MAILMH_ERROR_MEMORY; 461 res = MAILMH_ERROR_MEMORY;
457 goto closedir; 462 goto closedir;
458 } 463 }
459 strcpy(mh_seq, folder->fl_filename); 464 strcpy(mh_seq, folder->fl_filename);
460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S); 465 strcat(mh_seq, MAIL_DIR_SEPARATOR_S);
461 strcat(mh_seq, ".mh_sequences"); 466 strcat(mh_seq, ".mh_sequences");
462 467
463 if (stat(mh_seq, &buf) == -1) { 468 if (stat(mh_seq, &buf) == -1) {
464 int fd; 469 int fd;
465 470
466 fd = creat(mh_seq, S_IRUSR | S_IWUSR); 471 fd = creat(mh_seq, S_IRUSR | S_IWUSR);
467 if (fd != -1) 472 if (fd != -1)
468 close(fd); 473 close(fd);
469 } 474 }
470 free(mh_seq); 475 free(mh_seq);
471 476
472 closedir(d); 477 closedir(d);
473 478
474 return MAILMH_NO_ERROR; 479 return MAILMH_NO_ERROR;
475 480
476 closedir: 481 closedir:
477 closedir(d); 482 closedir(d);
478 err: 483 err:
479 return res; 484 return res;
480} 485}
481 486
482int mailmh_folder_add_subfolder(struct mailmh_folder * parent, 487int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
483 const char * name) 488 const char * name)
484{ 489{
485 char * foldername; 490 char * foldername;
486 int r; 491 int r;
487 struct mailmh_folder * folder; 492 struct mailmh_folder * folder;
488 unsigned int array_index; 493 unsigned int array_index;
489 chashdatum key; 494 chashdatum key;
490 chashdatum data; 495 chashdatum data;
491 496
492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); 497 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2);
493 if (foldername == NULL) 498 if (foldername == NULL)
494 return MAILMH_ERROR_MEMORY; 499 return MAILMH_ERROR_MEMORY;
495 strcpy(foldername, parent->fl_filename); 500 strcpy(foldername, parent->fl_filename);
496 strcat(foldername, MAIL_DIR_SEPARATOR_S); 501 strcat(foldername, MAIL_DIR_SEPARATOR_S);
497 strcat(foldername, name); 502 strcat(foldername, name);
498 503
499 r = mkdir(foldername, 0700); 504 r = mkdir(foldername, 0700);
500 free(foldername); 505 free(foldername);
501 506
502 if (r < 0) 507 if (r < 0)
503 return MAILMH_ERROR_FOLDER; 508 return MAILMH_ERROR_FOLDER;
504 509
505 folder = mailmh_folder_new(parent, name); 510 folder = mailmh_folder_new(parent, name);
506 if (folder == NULL) 511 if (folder == NULL)
507 return MAILMH_ERROR_MEMORY; 512 return MAILMH_ERROR_MEMORY;
508 513
509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index); 514 r = carray_add(parent->fl_subfolders_tab, folder, &array_index);
510 if (r < 0) { 515 if (r < 0) {
511 mailmh_folder_free(folder); 516 mailmh_folder_free(folder);
512 return MAILMH_ERROR_MEMORY; 517 return MAILMH_ERROR_MEMORY;
513 } 518 }
514 folder->fl_array_index = array_index; 519 folder->fl_array_index = array_index;
515 520
516 key.data = folder->fl_filename; 521 key.data = folder->fl_filename;
517 key.len = strlen(folder->fl_filename); 522 key.len = strlen(folder->fl_filename);
518 data.data = folder; 523 data.data = folder;
519 data.len = 0; 524 data.len = 0;
520 525
521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); 526 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL);
522 if (r < 0) { 527 if (r < 0) {
523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); 528 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index);
524 mailmh_folder_free(folder); 529 mailmh_folder_free(folder);
525 return MAILMH_ERROR_MEMORY; 530 return MAILMH_ERROR_MEMORY;
526 } 531 }
527 532
528 return MAILMH_NO_ERROR; 533 return MAILMH_NO_ERROR;
529} 534}
530 535
531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) 536int mailmh_folder_remove_subfolder(struct mailmh_folder * folder)
532{ 537{
533 struct mailmh_folder * parent; 538 struct mailmh_folder * parent;
534 chashdatum key; 539 chashdatum key;
535 chashdatum data; 540 chashdatum data;
536 int r; 541 int r;
537 542
538 parent = folder->fl_parent; 543 parent = folder->fl_parent;
539 544
540 key.data = folder->fl_filename; 545 key.data = folder->fl_filename;
541 key.len = strlen(folder->fl_filename); 546 key.len = strlen(folder->fl_filename);
542 547
543 r = chash_get(parent->fl_subfolders_hash, &key, &data); 548 r = chash_get(parent->fl_subfolders_hash, &key, &data);
544 if (r < 0) 549 if (r < 0)
545 return MAILMH_ERROR_FOLDER; 550 return MAILMH_ERROR_FOLDER;
546 551
547 chash_delete(parent->fl_subfolders_hash, &key, NULL); 552 chash_delete(parent->fl_subfolders_hash, &key, NULL);
548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); 553 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index);
549 554
550 mailmh_folder_free(folder); 555 mailmh_folder_free(folder);
551 556
552 return MAILMH_NO_ERROR; 557 return MAILMH_NO_ERROR;
553 558
554} 559}
555 560
556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, 561int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
557 struct mailmh_folder * dst_folder, 562 struct mailmh_folder * dst_folder,
558 const char * new_name) 563 const char * new_name)
559{ 564{
560 int r; 565 int r;
561 struct mailmh_folder * folder; 566 struct mailmh_folder * folder;
562 struct mailmh_folder * parent; 567 struct mailmh_folder * parent;
563 char * new_foldername; 568 char * new_foldername;
564 569
565 parent = src_folder->fl_parent; 570 parent = src_folder->fl_parent;
566 if (parent == NULL) 571 if (parent == NULL)
567 return MAILMH_ERROR_RENAME; 572 return MAILMH_ERROR_RENAME;
568 573
569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); 574 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name));
570 if (new_foldername == NULL) 575 if (new_foldername == NULL)
571 return MAILMH_ERROR_MEMORY; 576 return MAILMH_ERROR_MEMORY;
572 577
573 strcpy(new_foldername, dst_folder->fl_filename); 578 strcpy(new_foldername, dst_folder->fl_filename);
574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S); 579 strcat(new_foldername, MAIL_DIR_SEPARATOR_S);
575 strcat(new_foldername, new_name); 580 strcat(new_foldername, new_name);
576 581
577 r = rename(src_folder->fl_filename, new_foldername); 582 r = rename(src_folder->fl_filename, new_foldername);
578 free(new_foldername); 583 free(new_foldername);
579 if (r < 0) 584 if (r < 0)
580 return MAILMH_ERROR_RENAME; 585 return MAILMH_ERROR_RENAME;
581 586
582 r = mailmh_folder_remove_subfolder(src_folder); 587 r = mailmh_folder_remove_subfolder(src_folder);
583 if (r != MAILMH_NO_ERROR) 588 if (r != MAILMH_NO_ERROR)
584 return r; 589 return r;
585 590
586 folder = mailmh_folder_new(dst_folder, new_name); 591 folder = mailmh_folder_new(dst_folder, new_name);
587 if (folder == NULL) 592 if (folder == NULL)
588 return MAILMH_ERROR_MEMORY; 593 return MAILMH_ERROR_MEMORY;
589 594
590 r = carray_add(parent->fl_subfolders_tab, folder, NULL); 595 r = carray_add(parent->fl_subfolders_tab, folder, NULL);
591 if (r < 0) { 596 if (r < 0) {
592 mailmh_folder_free(folder); 597 mailmh_folder_free(folder);
593 return MAILMH_ERROR_MEMORY; 598 return MAILMH_ERROR_MEMORY;
594 } 599 }
595 600
596 return MAILMH_NO_ERROR; 601 return MAILMH_NO_ERROR;
597} 602}
598 603
599#define MAX_TRY_ALLOC 32 604#define MAX_TRY_ALLOC 32
600 605
601/* initial file MUST be in the same directory */ 606/* initial file MUST be in the same directory */
602 607
603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, 608static int mailmh_folder_alloc_msg(struct mailmh_folder * folder,
604 char * filename, uint32_t * result) 609 char * filename, uint32_t * result)
605{ 610{
606 uint32_t max; 611 uint32_t max;
607 uint32_t k; 612 uint32_t k;
608 char * new_filename; 613 char * new_filename;
609 size_t len; 614 size_t len;
610 struct stat f_stat; 615 struct stat f_stat;
611 616
612 len = strlen(folder->fl_filename) + 20; 617 len = strlen(folder->fl_filename) + 20;
613 new_filename = malloc(len); 618 new_filename = malloc(len);
614 if (new_filename == NULL) 619 if (new_filename == NULL)
615 return MAILMH_ERROR_MEMORY; 620 return MAILMH_ERROR_MEMORY;
616 621
617 max = folder->fl_max_index + 1; 622 max = folder->fl_max_index + 1;
618 623
619 //fprintf(stderr,"mailmh_folder_alloc_msg filename: %s \n", filename); 624 //fprintf(stderr,"mailmh_folder_alloc_msg filename: %s \n", filename);
620 k = 0; 625 k = 0;
621 while (k < MAX_TRY_ALLOC) { 626 while (k < MAX_TRY_ALLOC) {
622 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, 627 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename,
623 MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); 628 MAIL_DIR_SEPARATOR, (unsigned long) (max + k));
624 //fprintf(stderr,"mailmh_folder_alloc_msg new_filename: %s \n", new_filename); 629 //fprintf(stderr,"mailmh_folder_alloc_msg new_filename: %s \n", new_filename);
625 if ( stat( new_filename, &f_stat ) == -1 ) { 630 if ( stat( new_filename, &f_stat ) == -1 ) {
626 // if (link(filename, new_filename) == 0) { 631 // if (link(filename, new_filename) == 0) {
627 int r; 632 int r;
628 //fprintf(stderr,"filename found \n"); 633 //fprintf(stderr,"filename found \n");
629 //unlink(filename); 634 //unlink(filename);
630 rename (filename,new_filename ); 635 rename (filename,new_filename );
631 free(new_filename); 636 free(new_filename);
632 637
633 if (k > MAX_TRY_ALLOC / 2) { 638 if (k > MAX_TRY_ALLOC / 2) {
634 r = mailmh_folder_update(folder); 639 r = mailmh_folder_update(folder);
635 /* ignore errors */ 640 /* ignore errors */
636 } 641 }
637 642
638 * result = max + k; 643 * result = max + k;
639 644
640 folder->fl_max_index = max + k; 645 folder->fl_max_index = max + k;
641 646
642 return MAILMH_NO_ERROR; 647 return MAILMH_NO_ERROR;
643 } 648 }
644 else if (errno == EXDEV) { 649 else if (errno == EXDEV) {
645 free(filename); 650 free(filename);
646 return MAILMH_ERROR_FOLDER; 651 return MAILMH_ERROR_FOLDER;
647 } 652 }
648 k ++; 653 k ++;
649 } 654 }
650 655
651 free(new_filename); 656 free(new_filename);
652 657
653 return MAILMH_ERROR_FOLDER; 658 return MAILMH_ERROR_FOLDER;
654} 659}
655 660
656int mailmh_folder_get_message_filename(struct mailmh_folder * folder, 661int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
657 uint32_t index, char ** result) 662 uint32_t index, char ** result)
658{ 663{
659 char * filename; 664 char * filename;
660 int len; 665 int len;
661 666
662#if 0 667#if 0
663 r = mailmh_folder_update(folder); 668 r = mailmh_folder_update(folder);
664 if (r != MAILMH_NO_ERROR) 669 if (r != MAILMH_NO_ERROR)
665 return r; 670 return r;
666#endif 671#endif
667 672
668 len = strlen(folder->fl_filename) + 20; 673 len = strlen(folder->fl_filename) + 20;
669 filename = malloc(len); 674 filename = malloc(len);
670 if (filename == NULL) 675 if (filename == NULL)
671 return MAILMH_ERROR_MEMORY; 676 return MAILMH_ERROR_MEMORY;
672 677
673 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, 678 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR,
674 (unsigned long) index); 679 (unsigned long) index);
675 680
676 * result = filename; 681 * result = filename;
677 682
678 return MAILMH_NO_ERROR;; 683 return MAILMH_NO_ERROR;;
679} 684}
680 685
681 686
682int mailmh_folder_get_message_fd(struct mailmh_folder * folder, 687int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
683 uint32_t index, int flags, int * result) 688 uint32_t index, int flags, int * result)
684{ 689{
685 char * filename; 690 char * filename;
686 int fd; 691 int fd;
687 int r; 692 int r;
688 693
689#if 0 694#if 0
690 r = mailmh_folder_update(folder); 695 r = mailmh_folder_update(folder);
691 if (r != MAILMH_NO_ERROR) 696 if (r != MAILMH_NO_ERROR)
692 return r; 697 return r;
693#endif 698#endif
694 699
695 r = mailmh_folder_get_message_filename(folder, index, &filename); 700 r = mailmh_folder_get_message_filename(folder, index, &filename);
696 if (r != MAILMH_NO_ERROR) 701 if (r != MAILMH_NO_ERROR)
697 return r; 702 return r;
698 703
699 fd = open(filename, flags); 704 fd = open(filename, flags);
700 free(filename); 705 free(filename);
701 if (fd == -1) 706 if (fd == -1)
702 return MAILMH_ERROR_MSG_NOT_FOUND; 707 return MAILMH_ERROR_MSG_NOT_FOUND;
703 708
704 * result = fd; 709 * result = fd;
705 710
706 return MAILMH_NO_ERROR; 711 return MAILMH_NO_ERROR;
707} 712}
708 713
709int mailmh_folder_get_message_size(struct mailmh_folder * folder, 714int mailmh_folder_get_message_size(struct mailmh_folder * folder,
710 uint32_t index, size_t * result) 715 uint32_t index, size_t * result)
711{ 716{
712 int r; 717 int r;
713 char * filename; 718 char * filename;
714 struct stat buf; 719 struct stat buf;
715 720
716 r = mailmh_folder_get_message_filename(folder, index, &filename); 721 r = mailmh_folder_get_message_filename(folder, index, &filename);
717 if (r != MAILMH_NO_ERROR) 722 if (r != MAILMH_NO_ERROR)
718 return r; 723 return r;
719 724
720 r = stat(filename, &buf); 725 r = stat(filename, &buf);
721 free(filename); 726 free(filename);
722 if (r < 0) 727 if (r < 0)
723 return MAILMH_ERROR_FILE; 728 return MAILMH_ERROR_FILE;
724 729
725 * result = buf.st_size; 730 * result = buf.st_size;
726 731
727 return MAILMH_NO_ERROR; 732 return MAILMH_NO_ERROR;
728} 733}
729 734
730int mailmh_folder_add_message_uid(struct mailmh_folder * folder, 735int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
731 const char * message, size_t size, 736 const char * message, size_t size,
732 uint32_t * pindex) 737 uint32_t * pindex)
733{ 738{
734 char * tmpname; 739 char * tmpname;
735 int fd; 740 int fd;
736 size_t namesize; 741 size_t namesize;
737 size_t left; 742 size_t left;
738 ssize_t res; 743 ssize_t res;
739 struct mailmh_msg_info * msg_info; 744 struct mailmh_msg_info * msg_info;
740 uint32_t index; 745 uint32_t index;
741 int error; 746 int error;
742 int r; 747 int r;
743 unsigned int array_index; 748 unsigned int array_index;
744 struct stat buf; 749 struct stat buf;
745 chashdatum key; 750 chashdatum key;
746 chashdatum data; 751 chashdatum data;
747 752
748#if 0 753#if 0
749 r = mailmh_folder_update(folder); 754 r = mailmh_folder_update(folder);
750 if (r != MAILMH_NO_ERROR) { 755 if (r != MAILMH_NO_ERROR) {
751 error = r; 756 error = r;
752 goto err; 757 goto err;
753 } 758 }
754#endif 759#endif
755 760
756 namesize = strlen(folder->fl_filename) + 20; 761 namesize = strlen(folder->fl_filename) + 20;
757 tmpname = malloc(namesize); 762 tmpname = malloc(namesize);
758 snprintf(tmpname, namesize, "%s%ctmpXXXXXX", 763 snprintf(tmpname, namesize, "%s%ctmpXXXXXX",
759 folder->fl_filename, MAIL_DIR_SEPARATOR); 764 folder->fl_filename, MAIL_DIR_SEPARATOR);
760 fd = mkstemp(tmpname); 765 fd = mkstemp(tmpname);
761 if (fd < 0) { 766 if (fd < 0) {
762 error = MAILMH_ERROR_FILE; 767 error = MAILMH_ERROR_FILE;
763 goto free; 768 goto free;
764 } 769 }
765 770
766 left = size; 771 left = size;
767 while (left > 0) { 772 while (left > 0) {
768 res = write(fd, message, left); 773 res = write(fd, message, left);
769 if (res == -1) { 774 if (res == -1) {
770 close(fd); 775 close(fd);
771 error = MAILMH_ERROR_FILE; 776 error = MAILMH_ERROR_FILE;
772 goto free; 777 goto free;
773 } 778 }
774 779
775 left -= res; 780 left -= res;
776 } 781 }
777 close(fd); 782 close(fd);
778 783
779 r = stat(tmpname, &buf); 784 r = stat(tmpname, &buf);
780 if (r < 0) { 785 if (r < 0) {
781 error = MAILMH_ERROR_FILE; 786 error = MAILMH_ERROR_FILE;
782 goto free; 787 goto free;
783 } 788 }
784 789
785 r = mailmh_folder_alloc_msg(folder, tmpname, &index); 790 r = mailmh_folder_alloc_msg(folder, tmpname, &index);
786 if (r != MAILMH_NO_ERROR) { 791 if (r != MAILMH_NO_ERROR) {
787 unlink(tmpname); 792 unlink(tmpname);
788 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; 793 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG;
789 goto free; 794 goto free;
790 } 795 }
791 free(tmpname); 796 free(tmpname);
792 797
793 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); 798 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime);
794 if (msg_info == NULL) { 799 if (msg_info == NULL) {
795 mailmh_folder_remove_message(folder, index); 800 mailmh_folder_remove_message(folder, index);
796 error = MAILMH_ERROR_MEMORY; 801 error = MAILMH_ERROR_MEMORY;
797 goto err; 802 goto err;
798 } 803 }
799 804
800 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); 805 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
801 if (r < 0) { 806 if (r < 0) {
802 mailmh_folder_remove_message(folder, index); 807 mailmh_folder_remove_message(folder, index);
803 mailmh_msg_info_free(msg_info); 808 mailmh_msg_info_free(msg_info);
804 error = MAILMH_ERROR_MEMORY; 809 error = MAILMH_ERROR_MEMORY;
805 goto err; 810 goto err;
806 } 811 }
807 msg_info->msg_array_index = array_index; 812 msg_info->msg_array_index = array_index;
808 813
809#if 0 814#if 0
810 r = cinthash_add(folder->fl_msgs_hash, index, msg_info); 815 r = cinthash_add(folder->fl_msgs_hash, index, msg_info);
811#endif 816#endif
812 key.data = &index; 817 key.data = &index;
813 key.len = sizeof(index); 818 key.len = sizeof(index);
814 data.data = msg_info; 819 data.data = msg_info;
815 data.len = 0; 820 data.len = 0;
816 821
817 if (pindex != NULL) 822 if (pindex != NULL)
818 * pindex = index; 823 * pindex = index;
819 824
820 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); 825 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
821 if (r < 0) { 826 if (r < 0) {
822 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 827 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
823 mailmh_msg_info_free(msg_info); 828 mailmh_msg_info_free(msg_info);
824 error = MAILMH_ERROR_MEMORY; 829 error = MAILMH_ERROR_MEMORY;
825 goto err; 830 goto err;
826 } 831 }
827 832
828 return MAILMH_NO_ERROR; 833 return MAILMH_NO_ERROR;
829 834
830 free: 835 free:
831 free(tmpname); 836 free(tmpname);
832 err: 837 err:
833 return error; 838 return error;
834} 839}
835 840
836int mailmh_folder_add_message(struct mailmh_folder * folder, 841int mailmh_folder_add_message(struct mailmh_folder * folder,
837 const char * message, size_t size) 842 const char * message, size_t size)
838{ 843{
839 return mailmh_folder_add_message_uid(folder, message, size, NULL); 844 return mailmh_folder_add_message_uid(folder, message, size, NULL);
840} 845}
841 846
842int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, 847int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
843 int fd, uint32_t * pindex) 848 int fd, uint32_t * pindex)
844{ 849{
845 char * message; 850 char * message;
846 struct stat buf; 851 struct stat buf;
847 int r; 852 int r;
848 853
849#if 0 854#if 0
850 r = mailmh_folder_update(folder); 855 r = mailmh_folder_update(folder);
851 if (r != MAILMH_NO_ERROR) 856 if (r != MAILMH_NO_ERROR)
852 return r; 857 return r;