summaryrefslogtreecommitdiffabout
path: root/kmicromail
Unidiff
Diffstat (limited to 'kmicromail') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/maildir/maildir.c25
-rw-r--r--kmicromail/libetpan/mh/mailmh.c12
2 files changed, 26 insertions, 11 deletions
diff --git a/kmicromail/libetpan/maildir/maildir.c b/kmicromail/libetpan/maildir/maildir.c
index 0e038b1..1ef0b7a 100644
--- a/kmicromail/libetpan/maildir/maildir.c
+++ b/kmicromail/libetpan/maildir/maildir.c
@@ -1,729 +1,740 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001 - 2003 - DINH Viet Hoa 4 * Copyright (C) 2001 - 2003 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 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 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * $Id$ 33 * $Id$
34 */ 34 */
35 35
36#include "maildir.h" 36#include "maildir.h"
37 37
38#include <string.h> 38#include <string.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <stdio.h> 40#include <stdio.h>
41#include <unistd.h> 41#include <unistd.h>
42#include <sys/types.h> 42#include <sys/types.h>
43#include <dirent.h> 43#include <dirent.h>
44#include <time.h> 44#include <time.h>
45#include <sys/stat.h> 45#include <sys/stat.h>
46#include <sys/mman.h> 46#include <sys/mman.h>
47 47
48#ifdef LIBETPAN_SYSTEM_BASENAME 48#ifdef LIBETPAN_SYSTEM_BASENAME
49#include <libgen.h> 49#include <libgen.h>
50#endif 50#endif
51 51
52/* 52/*
53 We suppose the maildir mailbox remains on one unique filesystem. 53 We suppose the maildir mailbox remains on one unique filesystem.
54*/ 54*/
55 55
56struct maildir * maildir_new(const char * path) 56struct maildir * maildir_new(const char * path)
57{ 57{
58 struct maildir * md; 58 struct maildir * md;
59 59
60 md = malloc(sizeof(* md)); 60 md = malloc(sizeof(* md));
61 if (md == NULL) 61 if (md == NULL)
62 goto err; 62 goto err;
63 63
64 md->mdir_counter = 0; 64 md->mdir_counter = 0;
65 md->mdir_mtime_new = (time_t) -1; 65 md->mdir_mtime_new = (time_t) -1;
66 md->mdir_mtime_cur = (time_t) -1; 66 md->mdir_mtime_cur = (time_t) -1;
67 67
68 md->mdir_pid = getpid(); 68 md->mdir_pid = getpid();
69 gethostname(md->mdir_hostname, sizeof(md->mdir_hostname)); 69 gethostname(md->mdir_hostname, sizeof(md->mdir_hostname));
70 strncpy(md->mdir_path, path, sizeof(md->mdir_path)); 70 strncpy(md->mdir_path, path, sizeof(md->mdir_path));
71 md->mdir_path[PATH_MAX - 1] = '\0'; 71 md->mdir_path[PATH_MAX - 1] = '\0';
72 72
73 md->mdir_msg_list = carray_new(128); 73 md->mdir_msg_list = carray_new(128);
74 if (md->mdir_msg_list == NULL) 74 if (md->mdir_msg_list == NULL)
75 goto free; 75 goto free;
76 76
77 md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE); 77 md->mdir_msg_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYNONE);
78 if (md->mdir_msg_hash == NULL) 78 if (md->mdir_msg_hash == NULL)
79 goto free_msg_list; 79 goto free_msg_list;
80 80
81 return md; 81 return md;
82 82
83 free_msg_list: 83 free_msg_list:
84 carray_free(md->mdir_msg_list); 84 carray_free(md->mdir_msg_list);
85 free: 85 free:
86 free(md); 86 free(md);
87 err: 87 err:
88 return NULL; 88 return NULL;
89} 89}
90 90
91static void maildir_flush(struct maildir * md, int msg_new); 91static void maildir_flush(struct maildir * md, int msg_new);
92 92
93void maildir_free(struct maildir * md) 93void maildir_free(struct maildir * md)
94{ 94{
95 maildir_flush(md, 0); 95 maildir_flush(md, 0);
96 maildir_flush(md, 1); 96 maildir_flush(md, 1);
97 chash_free(md->mdir_msg_hash); 97 chash_free(md->mdir_msg_hash);
98 carray_free(md->mdir_msg_list); 98 carray_free(md->mdir_msg_list);
99 free(md); 99 free(md);
100} 100}
101 101
102#define MAX_TRY_ALLOC 32 102#define MAX_TRY_ALLOC 32
103 103
104static char * maildir_get_new_message_filename(struct maildir * md, 104static char * maildir_get_new_message_filename(struct maildir * md,
105 char * tmpfile) 105 char * tmpfile)
106{ 106{
107 char filename[PATH_MAX]; 107 char filename[PATH_MAX];
108 char basename[PATH_MAX]; 108 char basename[PATH_MAX];
109 int k; 109 int k;
110 time_t now; 110 time_t now;
111 111 struct stat f_stat;
112 now = time(NULL); 112 now = time(NULL);
113 k = 0; 113 k = 0;
114
115 fprintf(stderr,"maildir_get_new_message_filename: %s \n", tmpfile);
114 while (k < MAX_TRY_ALLOC) { 116 while (k < MAX_TRY_ALLOC) {
115 snprintf(basename, sizeof(basename), "%lu.%u_%u.%s", 117 snprintf(basename, sizeof(basename), "%lu.%u_%u.%s",
116 (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname); 118 (unsigned long) now, md->mdir_pid, md->mdir_counter, md->mdir_hostname);
117 snprintf(filename, sizeof(filename), "%s/tmp/%s", 119 snprintf(filename, sizeof(filename), "%s/tmp/%s",
118 md->mdir_path, basename); 120 md->mdir_path, basename);
119 121 fprintf(stderr,"filename %s \n", filename);
120 if (link(tmpfile, filename) == 0) { 122 // LR changed following lines
123 if ( stat( filename, &f_stat ) == -1 ) {
124 //if (link(tmpfile, filename) == 0) {
121 char * dup_filename; 125 char * dup_filename;
122 126
123 dup_filename = strdup(filename); 127 dup_filename = strdup(filename);
124 if (dup_filename == NULL) { 128 if (dup_filename == NULL) {
125 unlink(filename); 129 //unlink(filename);
126 return NULL; 130 return NULL;
127 } 131 }
128 132 fprintf(stderr,"filename %s %s \n", tmpfile,dup_filename);
129 unlink(tmpfile); 133 //unlink(tmpfile);
134 rename (tmpfile,dup_filename );
130 md->mdir_counter ++; 135 md->mdir_counter ++;
131 136
132 return dup_filename; 137 return dup_filename;
133 } 138 }
134 139
135 md->mdir_counter ++; 140 md->mdir_counter ++;
136 k ++; 141 k ++;
137 } 142 }
138 143
139 return NULL; 144 return NULL;
140} 145}
141 146
142 147
143static void msg_free(struct maildir_msg * msg) 148static void msg_free(struct maildir_msg * msg)
144{ 149{
145 free(msg->msg_uid); 150 free(msg->msg_uid);
146 free(msg->msg_filename); 151 free(msg->msg_filename);
147 free(msg); 152 free(msg);
148} 153}
149 154
150/* 155/*
151 msg_new() 156 msg_new()
152 157
153 filename is given without path 158 filename is given without path
154*/ 159*/
155 160
156static struct maildir_msg * msg_new(char * filename, int new_msg) 161static struct maildir_msg * msg_new(char * filename, int new_msg)
157{ 162{
158 struct maildir_msg * msg; 163 struct maildir_msg * msg;
159 char * p; 164 char * p;
160 int flags; 165 int flags;
161 size_t uid_len; 166 size_t uid_len;
162 char * begin_uid; 167 char * begin_uid;
163 168
164 /* name of file : xxx-xxx_xxx-xxx:2,SRFT */ 169 /* name of file : xxx-xxx_xxx-xxx:2,SRFT */
165 170
166 msg = malloc(sizeof(* msg)); 171 msg = malloc(sizeof(* msg));
167 if (msg == NULL) 172 if (msg == NULL)
168 goto err; 173 goto err;
169 174
170 msg->msg_filename = strdup(filename); 175 msg->msg_filename = strdup(filename);
171 if (msg->msg_filename == NULL) 176 if (msg->msg_filename == NULL)
172 goto free; 177 goto free;
173 178
174 begin_uid = filename; 179 begin_uid = filename;
175 180
176 uid_len = strlen(begin_uid); 181 uid_len = strlen(begin_uid);
177 182
178 flags = 0; 183 flags = 0;
179 p = strstr(filename, ":2,"); 184 p = strstr(filename, ":2,");
180 if (p != NULL) { 185 if (p != NULL) {
181 uid_len = p - begin_uid; 186 uid_len = p - begin_uid;
182 187
183 p += 3; 188 p += 3;
184 189
185 /* parse flags */ 190 /* parse flags */
186 while (* p != '\0') { 191 while (* p != '\0') {
187 switch (* p) { 192 switch (* p) {
188 case 'S': 193 case 'S':
189 flags |= MAILDIR_FLAG_SEEN; 194 flags |= MAILDIR_FLAG_SEEN;
190 break; 195 break;
191 case 'R': 196 case 'R':
192 flags |= MAILDIR_FLAG_REPLIED; 197 flags |= MAILDIR_FLAG_REPLIED;
193 break; 198 break;
194 case 'F': 199 case 'F':
195 flags |= MAILDIR_FLAG_FLAGGED; 200 flags |= MAILDIR_FLAG_FLAGGED;
196 break; 201 break;
197 case 'T': 202 case 'T':
198 flags |= MAILDIR_FLAG_TRASHED; 203 flags |= MAILDIR_FLAG_TRASHED;
199 break; 204 break;
200 } 205 }
201 p ++; 206 p ++;
202 } 207 }
203 } 208 }
204 209
205 if (new_msg) 210 if (new_msg)
206 flags |= MAILDIR_FLAG_NEW; 211 flags |= MAILDIR_FLAG_NEW;
207 212
208 msg->msg_flags = flags; 213 msg->msg_flags = flags;
209 214
210 msg->msg_uid = malloc(uid_len + 1); 215 msg->msg_uid = malloc(uid_len + 1);
211 if (msg->msg_uid == NULL) 216 if (msg->msg_uid == NULL)
212 goto free_filename; 217 goto free_filename;
213 218
214 strncpy(msg->msg_uid, begin_uid, uid_len); 219 strncpy(msg->msg_uid, begin_uid, uid_len);
215 msg->msg_uid[uid_len] = '\0'; 220 msg->msg_uid[uid_len] = '\0';
216 221
217 return msg; 222 return msg;
218 223
219 free_filename: 224 free_filename:
220 free(msg->msg_filename); 225 free(msg->msg_filename);
221 free: 226 free:
222 free(msg); 227 free(msg);
223 err: 228 err:
224 return NULL; 229 return NULL;
225} 230}
226 231
227static void maildir_flush(struct maildir * md, int msg_new) 232static void maildir_flush(struct maildir * md, int msg_new)
228{ 233{
229 unsigned int i; 234 unsigned int i;
230 235
231 i = 0; 236 i = 0;
232 while (i < carray_count(md->mdir_msg_list)) { 237 while (i < carray_count(md->mdir_msg_list)) {
233 struct maildir_msg * msg; 238 struct maildir_msg * msg;
234 int delete; 239 int delete;
235 240
236 msg = carray_get(md->mdir_msg_list, i); 241 msg = carray_get(md->mdir_msg_list, i);
237 242
238 if (msg_new) { 243 if (msg_new) {
239 delete = 0; 244 delete = 0;
240 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 245 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
241 delete = 1; 246 delete = 1;
242 } 247 }
243 else { 248 else {
244 delete = 1; 249 delete = 1;
245 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 250 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
246 delete = 0; 251 delete = 0;
247 } 252 }
248 253
249 if (delete) { 254 if (delete) {
250 chashdatum key; 255 chashdatum key;
251 256
252 key.data = msg->msg_uid; 257 key.data = msg->msg_uid;
253 key.len = strlen(msg->msg_uid); 258 key.len = strlen(msg->msg_uid);
254 chash_delete(md->mdir_msg_hash, &key, NULL); 259 chash_delete(md->mdir_msg_hash, &key, NULL);
255 260
256 carray_delete(md->mdir_msg_list, i); 261 carray_delete(md->mdir_msg_list, i);
257 msg_free(msg); 262 msg_free(msg);
258 } 263 }
259 else { 264 else {
260 i ++; 265 i ++;
261 } 266 }
262 } 267 }
263} 268}
264 269
265static int add_message(struct maildir * md, 270static int add_message(struct maildir * md,
266 char * filename, int is_new) 271 char * filename, int is_new)
267{ 272{
268 struct maildir_msg * msg; 273 struct maildir_msg * msg;
269 chashdatum key; 274 chashdatum key;
270 chashdatum value; 275 chashdatum value;
271 unsigned int i; 276 unsigned int i;
272 int res; 277 int res;
273 int r; 278 int r;
274 279
280 fprintf(stderr,"add_message filename: %s \n", filename);
275 msg = msg_new(filename, is_new); 281 msg = msg_new(filename, is_new);
276 if (msg == NULL) { 282 if (msg == NULL) {
277 res = MAILDIR_ERROR_MEMORY; 283 res = MAILDIR_ERROR_MEMORY;
278 goto err; 284 goto err;
279 } 285 }
280 286
281 r = carray_add(md->mdir_msg_list, msg, &i); 287 r = carray_add(md->mdir_msg_list, msg, &i);
282 if (r < 0) { 288 if (r < 0) {
283 res = MAILDIR_ERROR_MEMORY; 289 res = MAILDIR_ERROR_MEMORY;
284 goto free_msg; 290 goto free_msg;
285 } 291 }
286 292
287 key.data = msg->msg_uid; 293 key.data = msg->msg_uid;
288 key.len = strlen(msg->msg_uid); 294 key.len = strlen(msg->msg_uid);
289 value.data = msg; 295 value.data = msg;
290 value.len = 0; 296 value.len = 0;
291 297
292 r = chash_set(md->mdir_msg_hash, &key, &value, NULL); 298 r = chash_set(md->mdir_msg_hash, &key, &value, NULL);
293 if (r < 0) { 299 if (r < 0) {
294 res = MAILDIR_ERROR_MEMORY; 300 res = MAILDIR_ERROR_MEMORY;
295 goto delete; 301 goto delete;
296 } 302 }
297 303
298 return MAILDIR_NO_ERROR; 304 return MAILDIR_NO_ERROR;
299 305
300 delete: 306 delete:
301 carray_delete(md->mdir_msg_list, i); 307 carray_delete(md->mdir_msg_list, i);
302 free_msg: 308 free_msg:
303 msg_free(msg); 309 msg_free(msg);
304 err: 310 err:
305 return res; 311 return res;
306} 312}
307 313
308static int add_directory(struct maildir * md, char * path, int is_new) 314static int add_directory(struct maildir * md, char * path, int is_new)
309{ 315{
310 DIR * d; 316 DIR * d;
311 struct dirent * entry; 317 struct dirent * entry;
312 int res; 318 int res;
313 int r; 319 int r;
314 char filename[PATH_MAX]; 320 char filename[PATH_MAX];
315 321
316 d = opendir(path); 322 d = opendir(path);
317 if (d == NULL) { 323 if (d == NULL) {
318 res = MAILDIR_ERROR_DIRECTORY; 324 res = MAILDIR_ERROR_DIRECTORY;
319 goto err; 325 goto err;
320 } 326 }
321 327
322 while ((entry = readdir(d)) != NULL) { 328 while ((entry = readdir(d)) != NULL) {
323 struct stat stat_info; 329 struct stat stat_info;
324 330
325 snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name); 331 snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
326 r = stat(filename, &stat_info); 332 r = stat(filename, &stat_info);
327 if (r < 0) 333 if (r < 0)
328 continue; 334 continue;
329 335
330 if (S_ISDIR(stat_info.st_mode)) 336 if (S_ISDIR(stat_info.st_mode))
331 continue; 337 continue;
332 338
333 r = add_message(md, entry->d_name, is_new); 339 r = add_message(md, entry->d_name, is_new);
334 if (r != MAILDIR_NO_ERROR) { 340 if (r != MAILDIR_NO_ERROR) {
335 /* ignore errors */ 341 /* ignore errors */
336 } 342 }
337 } 343 }
338 344
339 closedir(d); 345 closedir(d);
340 346
341 return MAILDIR_NO_ERROR; 347 return MAILDIR_NO_ERROR;
342 348
343 err: 349 err:
344 return res; 350 return res;
345} 351}
346 352
347int maildir_update(struct maildir * md) 353int maildir_update(struct maildir * md)
348{ 354{
349 struct stat stat_info; 355 struct stat stat_info;
350 char path_new[PATH_MAX]; 356 char path_new[PATH_MAX];
351 char path_cur[PATH_MAX]; 357 char path_cur[PATH_MAX];
352 int r; 358 int r;
353 int res; 359 int res;
354 360
355 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); 361 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
356 snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path); 362 snprintf(path_cur, sizeof(path_cur), "%s/cur", md->mdir_path);
357 363
358 /* did new/ changed ? */ 364 /* did new/ changed ? */
359 365
360 r = stat(path_new, &stat_info); 366 r = stat(path_new, &stat_info);
361 if (r < 0) { 367 if (r < 0) {
362 res = MAILDIR_ERROR_DIRECTORY; 368 res = MAILDIR_ERROR_DIRECTORY;
363 goto free; 369 goto free;
364 } 370 }
365 371
366 if (md->mdir_mtime_new != stat_info.st_mtime) { 372 if (md->mdir_mtime_new != stat_info.st_mtime) {
367 md->mdir_mtime_new = stat_info.st_mtime; 373 md->mdir_mtime_new = stat_info.st_mtime;
368 374
369 maildir_flush(md, 1); 375 maildir_flush(md, 1);
370 376
371 /* messages in new */ 377 /* messages in new */
372 r = add_directory(md, path_new, 1); 378 r = add_directory(md, path_new, 1);
373 if (r != MAILDIR_NO_ERROR) { 379 if (r != MAILDIR_NO_ERROR) {
374 res = r; 380 res = r;
375 goto free; 381 goto free;
376 } 382 }
377 } 383 }
378 384
379 /* did cur/ changed ? */ 385 /* did cur/ changed ? */
380 386
381 r = stat(path_cur, &stat_info); 387 r = stat(path_cur, &stat_info);
382 if (r < 0) { 388 if (r < 0) {
383 res = MAILDIR_ERROR_DIRECTORY; 389 res = MAILDIR_ERROR_DIRECTORY;
384 goto free; 390 goto free;
385 } 391 }
386 392
387 if (md->mdir_mtime_cur != stat_info.st_mtime) { 393 if (md->mdir_mtime_cur != stat_info.st_mtime) {
388 md->mdir_mtime_cur = stat_info.st_mtime; 394 md->mdir_mtime_cur = stat_info.st_mtime;
389 395
390 maildir_flush(md, 0); 396 maildir_flush(md, 0);
391 397
392 /* messages in cur */ 398 /* messages in cur */
393 r = add_directory(md, path_cur, 0); 399 r = add_directory(md, path_cur, 0);
394 if (r != MAILDIR_NO_ERROR) { 400 if (r != MAILDIR_NO_ERROR) {
395 res = r; 401 res = r;
396 goto free; 402 goto free;
397 } 403 }
398 } 404 }
399 405
400 return MAILDIR_NO_ERROR; 406 return MAILDIR_NO_ERROR;
401 407
402 free: 408 free:
403 maildir_flush(md, 0); 409 maildir_flush(md, 0);
404 maildir_flush(md, 1); 410 maildir_flush(md, 1);
405 md->mdir_mtime_cur = (time_t) -1; 411 md->mdir_mtime_cur = (time_t) -1;
406 md->mdir_mtime_new = (time_t) -1; 412 md->mdir_mtime_new = (time_t) -1;
407 return res; 413 return res;
408} 414}
409 415
410#ifndef LIBETPAN_SYSTEM_BASENAME 416#ifndef LIBETPAN_SYSTEM_BASENAME
411static char * libetpan_basename(char * filename) 417static char * libetpan_basename(char * filename)
412{ 418{
413 char * next; 419 char * next;
414 char * p; 420 char * p;
415 421
416 p = filename; 422 p = filename;
417 next = strchr(p, '/'); 423 next = strchr(p, '/');
418 424
419 while (next != NULL) { 425 while (next != NULL) {
420 p = next; 426 p = next;
421 next = strchr(p + 1, '/'); 427 next = strchr(p + 1, '/');
422 } 428 }
423 429
424 if (p == filename) 430 if (p == filename)
425 return filename; 431 return filename;
426 else 432 else
427 return p + 1; 433 return p + 1;
428} 434}
429#else 435#else
430#define libetpan_basename(a) basename(a) 436#define libetpan_basename(a) basename(a)
431#endif 437#endif
432 438
433int maildir_message_add_uid(struct maildir * md, 439int maildir_message_add_uid(struct maildir * md,
434 const char * message, size_t size, 440 const char * message, size_t size,
435 char * uid, size_t max_uid_len) 441 char * uid, size_t max_uid_len)
436{ 442{
437 char path_new[PATH_MAX]; 443 char path_new[PATH_MAX];
438 char tmpname[PATH_MAX]; 444 char tmpname[PATH_MAX];
439 int fd; 445 int fd;
440 int r; 446 int r;
441 char * mapping; 447 char * mapping;
442 char * delivery_tmp_name; 448 char * delivery_tmp_name;
443 char * delivery_tmp_basename; 449 char * delivery_tmp_basename;
444 char delivery_new_name[PATH_MAX]; 450 char delivery_new_name[PATH_MAX];
445 char * delivery_new_basename; 451 char * delivery_new_basename;
446 int res; 452 int res;
447 struct stat stat_info; 453 struct stat stat_info;
448 454
455 fprintf(stderr,"maildir_message_add_uid for uid: %s \n", uid);
449 r = maildir_update(md); 456 r = maildir_update(md);
450 if (r != MAILDIR_NO_ERROR) { 457 if (r != MAILDIR_NO_ERROR) {
451 res = r; 458 res = r;
452 goto err; 459 goto err;
453 } 460 }
454 461
455 /* write to tmp/ with a classic temporary file */ 462 /* write to tmp/ with a classic temporary file */
456 463
457 snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX", 464 snprintf(tmpname, sizeof(tmpname), "%s/tmp/etpan-maildir-XXXXXX",
458 md->mdir_path); 465 md->mdir_path);
459 fd = mkstemp(tmpname); 466 fd = mkstemp(tmpname);
460 if (fd < 0) { 467 if (fd < 0) {
461 res = MAILDIR_ERROR_FILE; 468 res = MAILDIR_ERROR_FILE;
462 goto err; 469 goto err;
463 } 470 }
464 471
465 r = ftruncate(fd, size); 472 r = ftruncate(fd, size);
466 if (r < 0) { 473 if (r < 0) {
467 res = MAILDIR_ERROR_FILE; 474 res = MAILDIR_ERROR_FILE;
468 goto close; 475 goto close;
469 } 476 }
470 477
471 mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 478 mapping = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
472 if (mapping == MAP_FAILED) { 479 if (mapping == MAP_FAILED) {
473 res = MAILDIR_ERROR_FILE; 480 res = MAILDIR_ERROR_FILE;
474 goto close; 481 goto close;
475 } 482 }
476 483
477 memcpy(mapping, message, size); 484 memcpy(mapping, message, size);
478 485
479 msync(mapping, size, MS_SYNC); 486 msync(mapping, size, MS_SYNC);
480 munmap(mapping, size); 487 munmap(mapping, size);
481 488
482 close(fd); 489 close(fd);
483 490
484 /* write to tmp/ with maildir standard name */ 491 /* write to tmp/ with maildir standard name */
485 492
486 delivery_tmp_name = maildir_get_new_message_filename(md, tmpname); 493 delivery_tmp_name = maildir_get_new_message_filename(md, tmpname);
487 if (delivery_tmp_name == NULL) { 494 if (delivery_tmp_name == NULL) {
488 res = MAILDIR_ERROR_FILE; 495 res = MAILDIR_ERROR_FILE;
489 goto unlink; 496 goto unlink;
490 } 497 }
491 498
492 /* write to new/ with maildir standard name */ 499 /* write to new/ with maildir standard name */
493 500
494 strncpy(tmpname, delivery_tmp_name, sizeof(tmpname)); 501 strncpy(tmpname, delivery_tmp_name, sizeof(tmpname));
495 tmpname[sizeof(tmpname) - 1] = '\0'; 502 tmpname[sizeof(tmpname) - 1] = '\0';
496 503
497 delivery_tmp_basename = libetpan_basename(tmpname); 504 delivery_tmp_basename = libetpan_basename(tmpname);
498 505
499 snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s", 506 snprintf(delivery_new_name, sizeof(delivery_new_name), "%s/new/%s",
500 md->mdir_path, delivery_tmp_basename); 507 md->mdir_path, delivery_tmp_basename);
501 508
502 r = link(delivery_tmp_name, delivery_new_name); 509 r = link(delivery_tmp_name, delivery_new_name);
503 if (r < 0) { 510 if (r < 0) {
504 res = MAILDIR_ERROR_FILE; 511 res = MAILDIR_ERROR_FILE;
505 goto unlink_tmp; 512 goto unlink_tmp;
506 } 513 }
507 514
508 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path); 515 snprintf(path_new, sizeof(path_new), "%s/new", md->mdir_path);
509 r = stat(path_new, &stat_info); 516 r = stat(path_new, &stat_info);
510 if (r < 0) { 517 if (r < 0) {
511 unlink(delivery_new_name); 518 unlink(delivery_new_name);
512 res = MAILDIR_ERROR_FILE; 519 res = MAILDIR_ERROR_FILE;
513 goto unlink_tmp; 520 goto unlink_tmp;
514 } 521 }
515 522
516 md->mdir_mtime_new = stat_info.st_mtime; 523 md->mdir_mtime_new = stat_info.st_mtime;
517 524
518 delivery_new_basename = libetpan_basename(delivery_new_name); 525 delivery_new_basename = libetpan_basename(delivery_new_name);
519 526
520 r = add_message(md, delivery_new_basename, 1); 527 r = add_message(md, delivery_new_basename, 1);
521 if (r != MAILDIR_NO_ERROR) { 528 if (r != MAILDIR_NO_ERROR) {
522 unlink(delivery_new_name); 529 unlink(delivery_new_name);
523 res = MAILDIR_ERROR_FILE; 530 res = MAILDIR_ERROR_FILE;
524 goto unlink_tmp; 531 goto unlink_tmp;
525 } 532 }
526 533
527 if (uid != NULL) 534 if (uid != NULL)
528 strncpy(uid, delivery_new_basename, max_uid_len); 535 strncpy(uid, delivery_new_basename, max_uid_len);
529 536
530 unlink(delivery_tmp_name); 537 unlink(delivery_tmp_name);
531 free(delivery_tmp_name); 538 free(delivery_tmp_name);
532 539
533 return MAILDIR_NO_ERROR; 540 return MAILDIR_NO_ERROR;
534 541
535 unlink_tmp: 542 unlink_tmp:
536 unlink(delivery_tmp_name); 543 unlink(delivery_tmp_name);
537 free(delivery_tmp_name); 544 free(delivery_tmp_name);
538 goto err; 545 goto err;
539 close: 546 close:
540 close(fd); 547 close(fd);
541 unlink: 548 unlink:
542 unlink(tmpname); 549 unlink(tmpname);
543 err: 550 err:
544 return res; 551 return res;
545} 552}
546 553
547int maildir_message_add(struct maildir * md, 554int maildir_message_add(struct maildir * md,
548 const char * message, size_t size) 555 const char * message, size_t size)
549{ 556{
550 return maildir_message_add_uid(md, message, size, 557 return maildir_message_add_uid(md, message, size,
551 NULL, 0); 558 NULL, 0);
552} 559}
553 560
554int maildir_message_add_file_uid(struct maildir * md, int fd, 561int maildir_message_add_file_uid(struct maildir * md, int fd,
555 char * uid, size_t max_uid_len) 562 char * uid, size_t max_uid_len)
556{ 563{
557 char * message; 564 char * message;
558 struct stat buf; 565 struct stat buf;
559 int r; 566 int r;
560 567
568 fprintf(stderr,"maildir_message_add_file_uid: %s \n", uid);
561 if (fstat(fd, &buf) == -1) 569 if (fstat(fd, &buf) == -1)
562 return MAILDIR_ERROR_FILE; 570 return MAILDIR_ERROR_FILE;
563 571
564 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 572 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
565 if (message == MAP_FAILED) 573 if (message == MAP_FAILED)
566 return MAILDIR_ERROR_FILE; 574 return MAILDIR_ERROR_FILE;
567 575
568 r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len); 576 r = maildir_message_add_uid(md, message, buf.st_size, uid, max_uid_len);
569 577
570 munmap(message, buf.st_size); 578 munmap(message, buf.st_size);
571 579
572 return r; 580 return r;
573} 581}
574 582
575int maildir_message_add_file(struct maildir * md, int fd) 583int maildir_message_add_file(struct maildir * md, int fd)
576{ 584{
585 fprintf(stderr,"maildir_message_add_file \n");
577 return maildir_message_add_file_uid(md, fd, 586 return maildir_message_add_file_uid(md, fd,
578 NULL, 0); 587 NULL, 0);
579} 588}
580 589
581char * maildir_message_get(struct maildir * md, const char * uid) 590char * maildir_message_get(struct maildir * md, const char * uid)
582{ 591{
583 chashdatum key; 592 chashdatum key;
584 chashdatum value; 593 chashdatum value;
585 char filename[PATH_MAX]; 594 char filename[PATH_MAX];
586 char * dup_filename; 595 char * dup_filename;
587 struct maildir_msg * msg; 596 struct maildir_msg * msg;
588 char * dir; 597 char * dir;
589 int r; 598 int r;
590 599
600 fprintf(stderr,"maildir_message_get for uid: %s \n", uid);
591 key.data = (void *) uid; 601 key.data = (void *) uid;
592 key.len = strlen(uid); 602 key.len = strlen(uid);
593 r = chash_get(md->mdir_msg_hash, &key, &value); 603 r = chash_get(md->mdir_msg_hash, &key, &value);
594 if (r < 0) 604 if (r < 0)
595 return NULL; 605 return NULL;
596 606
597 msg = value.data; 607 msg = value.data;
598 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 608 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
599 dir = "new"; 609 dir = "new";
600 else 610 else
601 dir = "cur"; 611 dir = "cur";
602 612
603 snprintf(filename, sizeof(filename), "%s/%s/%s", 613 snprintf(filename, sizeof(filename), "%s/%s/%s",
604 md->mdir_path, dir, msg->msg_filename); 614 md->mdir_path, dir, msg->msg_filename);
605 615
606 dup_filename = strdup(filename); 616 dup_filename = strdup(filename);
607 if (dup_filename == NULL) 617 if (dup_filename == NULL)
608 return NULL; 618 return NULL;
609 619
610 return dup_filename; 620 return dup_filename;
611} 621}
612 622
613int maildir_message_remove(struct maildir * md, const char * uid) 623int maildir_message_remove(struct maildir * md, const char * uid)
614{ 624{
615 chashdatum key; 625 chashdatum key;
616 chashdatum value; 626 chashdatum value;
617 char filename[PATH_MAX]; 627 char filename[PATH_MAX];
618 struct maildir_msg * msg; 628 struct maildir_msg * msg;
619 char * dir; 629 char * dir;
620 int r; 630 int r;
621 int res; 631 int res;
622 632
633 fprintf(stderr,"maildir_message_remove for uid: %s \n", uid);
623 key.data = (void *) uid; 634 key.data = (void *) uid;
624 key.len = strlen(uid); 635 key.len = strlen(uid);
625 r = chash_get(md->mdir_msg_hash, &key, &value); 636 r = chash_get(md->mdir_msg_hash, &key, &value);
626 if (r < 0) { 637 if (r < 0) {
627 res = MAILDIR_ERROR_NOT_FOUND; 638 res = MAILDIR_ERROR_NOT_FOUND;
628 goto err; 639 goto err;
629 } 640 }
630 641
631 msg = value.data; 642 msg = value.data;
632 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 643 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
633 dir = "new"; 644 dir = "new";
634 else 645 else
635 dir = "cur"; 646 dir = "cur";
636 647
637 snprintf(filename, sizeof(filename), "%s/%s/%s", 648 snprintf(filename, sizeof(filename), "%s/%s/%s",
638 md->mdir_path, dir, msg->msg_filename); 649 md->mdir_path, dir, msg->msg_filename);
639 650
640 r = unlink(filename); 651 r = unlink(filename);
641 if (r < 0) { 652 if (r < 0) {
642 res = MAILDIR_ERROR_FILE; 653 res = MAILDIR_ERROR_FILE;
643 goto err; 654 goto err;
644 } 655 }
645 656
646 return MAILDIR_NO_ERROR; 657 return MAILDIR_NO_ERROR;
647 658
648 err: 659 err:
649 return res; 660 return res;
650} 661}
651 662
652int maildir_message_change_flags(struct maildir * md, 663int maildir_message_change_flags(struct maildir * md,
653 const char * uid, int new_flags) 664 const char * uid, int new_flags)
654{ 665{
655 chashdatum key; 666 chashdatum key;
656 chashdatum value; 667 chashdatum value;
657 char filename[PATH_MAX]; 668 char filename[PATH_MAX];
658 struct maildir_msg * msg; 669 struct maildir_msg * msg;
659 char * dir; 670 char * dir;
660 int r; 671 int r;
661 char new_filename[PATH_MAX]; 672 char new_filename[PATH_MAX];
662 char flag_str[5]; 673 char flag_str[5];
663 size_t i; 674 size_t i;
664 int res; 675 int res;
665 676 fprintf(stderr,"maildir_message_change_flags for uid: %s \n", uid);
666 key.data = (void *) uid; 677 key.data = (void *) uid;
667 key.len = strlen(uid); 678 key.len = strlen(uid);
668 r = chash_get(md->mdir_msg_hash, &key, &value); 679 r = chash_get(md->mdir_msg_hash, &key, &value);
669 if (r < 0) { 680 if (r < 0) {
670 res = MAILDIR_ERROR_NOT_FOUND; 681 res = MAILDIR_ERROR_NOT_FOUND;
671 goto err; 682 goto err;
672 } 683 }
673 684
674 msg = value.data; 685 msg = value.data;
675 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0) 686 if ((msg->msg_flags & MAILDIR_FLAG_NEW) != 0)
676 dir = "new"; 687 dir = "new";
677 else 688 else
678 dir = "cur"; 689 dir = "cur";
679 690
680 snprintf(filename, sizeof(filename), "%s/%s/%s", 691 snprintf(filename, sizeof(filename), "%s/%s/%s",
681 md->mdir_path, dir, msg->msg_filename); 692 md->mdir_path, dir, msg->msg_filename);
682 693
683 if ((new_flags & MAILDIR_FLAG_NEW) != 0) 694 if ((new_flags & MAILDIR_FLAG_NEW) != 0)
684 dir = "new"; 695 dir = "new";
685 else 696 else
686 dir = "cur"; 697 dir = "cur";
687 698
688 i = 0; 699 i = 0;
689 if ((new_flags & MAILDIR_FLAG_SEEN) != 0) { 700 if ((new_flags & MAILDIR_FLAG_SEEN) != 0) {
690 flag_str[i] = 'S'; 701 flag_str[i] = 'S';
691 i ++; 702 i ++;
692 } 703 }
693 if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) { 704 if ((new_flags & MAILDIR_FLAG_REPLIED) != 0) {
694 flag_str[i] = 'R'; 705 flag_str[i] = 'R';
695 i ++; 706 i ++;
696 } 707 }
697 if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) { 708 if ((new_flags & MAILDIR_FLAG_FLAGGED) != 0) {
698 flag_str[i] = 'F'; 709 flag_str[i] = 'F';
699 i ++; 710 i ++;
700 } 711 }
701 if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) { 712 if ((new_flags & MAILDIR_FLAG_TRASHED) != 0) {
702 flag_str[i] = 'T'; 713 flag_str[i] = 'T';
703 i ++; 714 i ++;
704 } 715 }
705 flag_str[i] = 0; 716 flag_str[i] = 0;
706 717
707 if (flag_str[0] == '\0') 718 if (flag_str[0] == '\0')
708 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s", 719 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s",
709 md->mdir_path, dir, msg->msg_uid); 720 md->mdir_path, dir, msg->msg_uid);
710 else 721 else
711 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s", 722 snprintf(new_filename, sizeof(new_filename), "%s/%s/%s:2,%s",
712 md->mdir_path, dir, msg->msg_uid, flag_str); 723 md->mdir_path, dir, msg->msg_uid, flag_str);
713 724
714 if (strcmp(filename, new_filename) == 0) 725 if (strcmp(filename, new_filename) == 0)
715 return MAILDIR_NO_ERROR; 726 return MAILDIR_NO_ERROR;
716 727
717 r = link(filename, new_filename); 728 r = link(filename, new_filename);
718 if (r < 0) { 729 if (r < 0) {
719 res = MAILDIR_ERROR_FILE; 730 res = MAILDIR_ERROR_FILE;
720 goto err; 731 goto err;
721 } 732 }
722 733
723 unlink(filename); 734 unlink(filename);
724 735
725 return MAILDIR_NO_ERROR; 736 return MAILDIR_NO_ERROR;
726 737
727 err: 738 err:
728 return res; 739 return res;
729} 740}
diff --git a/kmicromail/libetpan/mh/mailmh.c b/kmicromail/libetpan/mh/mailmh.c
index 119f217..5e2b4cc 100644
--- a/kmicromail/libetpan/mh/mailmh.c
+++ b/kmicromail/libetpan/mh/mailmh.c
@@ -1,981 +1,985 @@
1/* 1/*
2 * libEtPan! -- a mail stuff library 2 * libEtPan! -- a mail stuff library
3 * 3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa 4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its 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 16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission. 17 * from this software without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
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 }
403 } 403 }
404 else if (S_ISDIR(buf.st_mode)) { 404 else if (S_ISDIR(buf.st_mode)) {
405 struct mailmh_folder * subfolder; 405 struct mailmh_folder * subfolder;
406 unsigned int array_index; 406 unsigned int array_index;
407 chashdatum key; 407 chashdatum key;
408 chashdatum data; 408 chashdatum data;
409 409
410 if (ent->d_name[0] == '.') { 410 if (ent->d_name[0] == '.') {
411 if (ent->d_name[1] == 0) 411 if (ent->d_name[1] == 0)
412 continue; 412 continue;
413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0)) 413 if ((ent->d_name[1] == '.') && (ent->d_name[2] == 0))
414 continue; 414 continue;
415 } 415 }
416 416
417 key.data = ent->d_name; 417 key.data = ent->d_name;
418 key.len = strlen(ent->d_name); 418 key.len = strlen(ent->d_name);
419 r = chash_get(folder->fl_subfolders_hash, &key, &data); 419 r = chash_get(folder->fl_subfolders_hash, &key, &data);
420 if (r < 0) { 420 if (r < 0) {
421 subfolder = mailmh_folder_new(folder, ent->d_name); 421 subfolder = mailmh_folder_new(folder, ent->d_name);
422 if (subfolder == NULL) { 422 if (subfolder == NULL) {
423 res = MAILMH_ERROR_MEMORY; 423 res = MAILMH_ERROR_MEMORY;
424 goto closedir; 424 goto closedir;
425 } 425 }
426 426
427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index); 427 r = carray_add(folder->fl_subfolders_tab, subfolder, &array_index);
428 if (r < 0) { 428 if (r < 0) {
429 mailmh_folder_free(subfolder); 429 mailmh_folder_free(subfolder);
430 res = MAILMH_ERROR_MEMORY; 430 res = MAILMH_ERROR_MEMORY;
431 goto closedir; 431 goto closedir;
432 } 432 }
433 subfolder->fl_array_index = array_index; 433 subfolder->fl_array_index = array_index;
434 434
435 key.data = subfolder->fl_filename; 435 key.data = subfolder->fl_filename;
436 key.len = strlen(subfolder->fl_filename); 436 key.len = strlen(subfolder->fl_filename);
437 data.data = subfolder; 437 data.data = subfolder;
438 data.len = 0; 438 data.len = 0;
439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL); 439 r = chash_set(folder->fl_subfolders_hash, &key, &data, NULL);
440 if (r < 0) { 440 if (r < 0) {
441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index); 441 carray_delete_fast(folder->fl_subfolders_tab, subfolder->fl_array_index);
442 mailmh_folder_free(subfolder); 442 mailmh_folder_free(subfolder);
443 res = MAILMH_ERROR_MEMORY; 443 res = MAILMH_ERROR_MEMORY;
444 goto closedir; 444 goto closedir;
445 } 445 }
446 } 446 }
447 } 447 }
448 } 448 }
449 } 449 }
450 while (ent != NULL); 450 while (ent != NULL);
451 451
452 folder->fl_max_index = max_index; 452 folder->fl_max_index = max_index;
453 453
454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences")); 454 mh_seq = malloc(strlen(folder->fl_filename) + 2 + sizeof(".mh_sequences"));
455 if (mh_seq == NULL) { 455 if (mh_seq == NULL) {
456 res = MAILMH_ERROR_MEMORY; 456 res = MAILMH_ERROR_MEMORY;
457 goto closedir; 457 goto closedir;
458 } 458 }
459 strcpy(mh_seq, folder->fl_filename); 459 strcpy(mh_seq, folder->fl_filename);
460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S); 460 strcat(mh_seq, MAIL_DIR_SEPARATOR_S);
461 strcat(mh_seq, ".mh_sequences"); 461 strcat(mh_seq, ".mh_sequences");
462 462
463 if (stat(mh_seq, &buf) == -1) { 463 if (stat(mh_seq, &buf) == -1) {
464 int fd; 464 int fd;
465 465
466 fd = creat(mh_seq, S_IRUSR | S_IWUSR); 466 fd = creat(mh_seq, S_IRUSR | S_IWUSR);
467 if (fd != -1) 467 if (fd != -1)
468 close(fd); 468 close(fd);
469 } 469 }
470 free(mh_seq); 470 free(mh_seq);
471 471
472 closedir(d); 472 closedir(d);
473 473
474 return MAILMH_NO_ERROR; 474 return MAILMH_NO_ERROR;
475 475
476 closedir: 476 closedir:
477 closedir(d); 477 closedir(d);
478 err: 478 err:
479 return res; 479 return res;
480} 480}
481 481
482int mailmh_folder_add_subfolder(struct mailmh_folder * parent, 482int mailmh_folder_add_subfolder(struct mailmh_folder * parent,
483 const char * name) 483 const char * name)
484{ 484{
485 char * foldername; 485 char * foldername;
486 int r; 486 int r;
487 struct mailmh_folder * folder; 487 struct mailmh_folder * folder;
488 unsigned int array_index; 488 unsigned int array_index;
489 chashdatum key; 489 chashdatum key;
490 chashdatum data; 490 chashdatum data;
491 491
492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2); 492 foldername = malloc(strlen(parent->fl_filename) + strlen(name) + 2);
493 if (foldername == NULL) 493 if (foldername == NULL)
494 return MAILMH_ERROR_MEMORY; 494 return MAILMH_ERROR_MEMORY;
495 strcpy(foldername, parent->fl_filename); 495 strcpy(foldername, parent->fl_filename);
496 strcat(foldername, MAIL_DIR_SEPARATOR_S); 496 strcat(foldername, MAIL_DIR_SEPARATOR_S);
497 strcat(foldername, name); 497 strcat(foldername, name);
498 498
499 r = mkdir(foldername, 0700); 499 r = mkdir(foldername, 0700);
500 free(foldername); 500 free(foldername);
501 501
502 if (r < 0) 502 if (r < 0)
503 return MAILMH_ERROR_FOLDER; 503 return MAILMH_ERROR_FOLDER;
504 504
505 folder = mailmh_folder_new(parent, name); 505 folder = mailmh_folder_new(parent, name);
506 if (folder == NULL) 506 if (folder == NULL)
507 return MAILMH_ERROR_MEMORY; 507 return MAILMH_ERROR_MEMORY;
508 508
509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index); 509 r = carray_add(parent->fl_subfolders_tab, folder, &array_index);
510 if (r < 0) { 510 if (r < 0) {
511 mailmh_folder_free(folder); 511 mailmh_folder_free(folder);
512 return MAILMH_ERROR_MEMORY; 512 return MAILMH_ERROR_MEMORY;
513 } 513 }
514 folder->fl_array_index = array_index; 514 folder->fl_array_index = array_index;
515 515
516 key.data = folder->fl_filename; 516 key.data = folder->fl_filename;
517 key.len = strlen(folder->fl_filename); 517 key.len = strlen(folder->fl_filename);
518 data.data = folder; 518 data.data = folder;
519 data.len = 0; 519 data.len = 0;
520 520
521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL); 521 r = chash_set(parent->fl_subfolders_hash, &key, &data, NULL);
522 if (r < 0) { 522 if (r < 0) {
523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index); 523 carray_delete_fast(folder->fl_subfolders_tab, folder->fl_array_index);
524 mailmh_folder_free(folder); 524 mailmh_folder_free(folder);
525 return MAILMH_ERROR_MEMORY; 525 return MAILMH_ERROR_MEMORY;
526 } 526 }
527 527
528 return MAILMH_NO_ERROR; 528 return MAILMH_NO_ERROR;
529} 529}
530 530
531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder) 531int mailmh_folder_remove_subfolder(struct mailmh_folder * folder)
532{ 532{
533 struct mailmh_folder * parent; 533 struct mailmh_folder * parent;
534 chashdatum key; 534 chashdatum key;
535 chashdatum data; 535 chashdatum data;
536 int r; 536 int r;
537 537
538 parent = folder->fl_parent; 538 parent = folder->fl_parent;
539 539
540 key.data = folder->fl_filename; 540 key.data = folder->fl_filename;
541 key.len = strlen(folder->fl_filename); 541 key.len = strlen(folder->fl_filename);
542 542
543 r = chash_get(parent->fl_subfolders_hash, &key, &data); 543 r = chash_get(parent->fl_subfolders_hash, &key, &data);
544 if (r < 0) 544 if (r < 0)
545 return MAILMH_ERROR_FOLDER; 545 return MAILMH_ERROR_FOLDER;
546 546
547 chash_delete(parent->fl_subfolders_hash, &key, NULL); 547 chash_delete(parent->fl_subfolders_hash, &key, NULL);
548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index); 548 carray_delete_fast(parent->fl_subfolders_tab, folder->fl_array_index);
549 549
550 mailmh_folder_free(folder); 550 mailmh_folder_free(folder);
551 551
552 return MAILMH_NO_ERROR; 552 return MAILMH_NO_ERROR;
553 553
554} 554}
555 555
556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder, 556int mailmh_folder_rename_subfolder(struct mailmh_folder * src_folder,
557 struct mailmh_folder * dst_folder, 557 struct mailmh_folder * dst_folder,
558 const char * new_name) 558 const char * new_name)
559{ 559{
560 int r; 560 int r;
561 struct mailmh_folder * folder; 561 struct mailmh_folder * folder;
562 struct mailmh_folder * parent; 562 struct mailmh_folder * parent;
563 char * new_foldername; 563 char * new_foldername;
564 564
565 parent = src_folder->fl_parent; 565 parent = src_folder->fl_parent;
566 if (parent == NULL) 566 if (parent == NULL)
567 return MAILMH_ERROR_RENAME; 567 return MAILMH_ERROR_RENAME;
568 568
569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name)); 569 new_foldername = malloc(strlen(dst_folder->fl_filename) + 2 + strlen(new_name));
570 if (new_foldername == NULL) 570 if (new_foldername == NULL)
571 return MAILMH_ERROR_MEMORY; 571 return MAILMH_ERROR_MEMORY;
572 572
573 strcpy(new_foldername, dst_folder->fl_filename); 573 strcpy(new_foldername, dst_folder->fl_filename);
574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S); 574 strcat(new_foldername, MAIL_DIR_SEPARATOR_S);
575 strcat(new_foldername, new_name); 575 strcat(new_foldername, new_name);
576 576
577 r = rename(src_folder->fl_filename, new_foldername); 577 r = rename(src_folder->fl_filename, new_foldername);
578 free(new_foldername); 578 free(new_foldername);
579 if (r < 0) 579 if (r < 0)
580 return MAILMH_ERROR_RENAME; 580 return MAILMH_ERROR_RENAME;
581 581
582 r = mailmh_folder_remove_subfolder(src_folder); 582 r = mailmh_folder_remove_subfolder(src_folder);
583 if (r != MAILMH_NO_ERROR) 583 if (r != MAILMH_NO_ERROR)
584 return r; 584 return r;
585 585
586 folder = mailmh_folder_new(dst_folder, new_name); 586 folder = mailmh_folder_new(dst_folder, new_name);
587 if (folder == NULL) 587 if (folder == NULL)
588 return MAILMH_ERROR_MEMORY; 588 return MAILMH_ERROR_MEMORY;
589 589
590 r = carray_add(parent->fl_subfolders_tab, folder, NULL); 590 r = carray_add(parent->fl_subfolders_tab, folder, NULL);
591 if (r < 0) { 591 if (r < 0) {
592 mailmh_folder_free(folder); 592 mailmh_folder_free(folder);
593 return MAILMH_ERROR_MEMORY; 593 return MAILMH_ERROR_MEMORY;
594 } 594 }
595 595
596 return MAILMH_NO_ERROR; 596 return MAILMH_NO_ERROR;
597} 597}
598 598
599#define MAX_TRY_ALLOC 32 599#define MAX_TRY_ALLOC 32
600 600
601/* initial file MUST be in the same directory */ 601/* initial file MUST be in the same directory */
602 602
603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder, 603static int mailmh_folder_alloc_msg(struct mailmh_folder * folder,
604 char * filename, uint32_t * result) 604 char * filename, uint32_t * result)
605{ 605{
606 uint32_t max; 606 uint32_t max;
607 uint32_t k; 607 uint32_t k;
608 char * new_filename; 608 char * new_filename;
609 size_t len; 609 size_t len;
610 struct stat f_stat;
610 611
611 len = strlen(folder->fl_filename) + 20; 612 len = strlen(folder->fl_filename) + 20;
612 new_filename = malloc(len); 613 new_filename = malloc(len);
613 if (new_filename == NULL) 614 if (new_filename == NULL)
614 return MAILMH_ERROR_MEMORY; 615 return MAILMH_ERROR_MEMORY;
615 616
616 max = folder->fl_max_index + 1; 617 max = folder->fl_max_index + 1;
617 618
619 //fprintf(stderr,"mailmh_folder_alloc_msg filename: %s \n", filename);
618 k = 0; 620 k = 0;
619 while (k < MAX_TRY_ALLOC) { 621 while (k < MAX_TRY_ALLOC) {
620 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename, 622 snprintf(new_filename, len, "%s%c%lu", folder->fl_filename,
621 MAIL_DIR_SEPARATOR, (unsigned long) (max + k)); 623 MAIL_DIR_SEPARATOR, (unsigned long) (max + k));
622 624 //fprintf(stderr,"mailmh_folder_alloc_msg new_filename: %s \n", new_filename);
623 if (link(filename, new_filename) == 0) { 625 if ( stat( new_filename, &f_stat ) == -1 ) {
626 // if (link(filename, new_filename) == 0) {
624 int r; 627 int r;
625 628 //fprintf(stderr,"filename found \n");
629 //unlink(filename);
630 rename (filename,new_filename );
626 free(new_filename); 631 free(new_filename);
627 unlink(filename);
628 632
629 if (k > MAX_TRY_ALLOC / 2) { 633 if (k > MAX_TRY_ALLOC / 2) {
630 r = mailmh_folder_update(folder); 634 r = mailmh_folder_update(folder);
631 /* ignore errors */ 635 /* ignore errors */
632 } 636 }
633 637
634 * result = max + k; 638 * result = max + k;
635 639
636 folder->fl_max_index = max + k; 640 folder->fl_max_index = max + k;
637 641
638 return MAILMH_NO_ERROR; 642 return MAILMH_NO_ERROR;
639 } 643 }
640 else if (errno == EXDEV) { 644 else if (errno == EXDEV) {
641 free(filename); 645 free(filename);
642 return MAILMH_ERROR_FOLDER; 646 return MAILMH_ERROR_FOLDER;
643 } 647 }
644 k ++; 648 k ++;
645 } 649 }
646 650
647 free(new_filename); 651 free(new_filename);
648 652
649 return MAILMH_ERROR_FOLDER; 653 return MAILMH_ERROR_FOLDER;
650} 654}
651 655
652int mailmh_folder_get_message_filename(struct mailmh_folder * folder, 656int mailmh_folder_get_message_filename(struct mailmh_folder * folder,
653 uint32_t index, char ** result) 657 uint32_t index, char ** result)
654{ 658{
655 char * filename; 659 char * filename;
656 int len; 660 int len;
657 661
658#if 0 662#if 0
659 r = mailmh_folder_update(folder); 663 r = mailmh_folder_update(folder);
660 if (r != MAILMH_NO_ERROR) 664 if (r != MAILMH_NO_ERROR)
661 return r; 665 return r;
662#endif 666#endif
663 667
664 len = strlen(folder->fl_filename) + 20; 668 len = strlen(folder->fl_filename) + 20;
665 filename = malloc(len); 669 filename = malloc(len);
666 if (filename == NULL) 670 if (filename == NULL)
667 return MAILMH_ERROR_MEMORY; 671 return MAILMH_ERROR_MEMORY;
668 672
669 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR, 673 snprintf(filename, len, "%s%c%lu", folder->fl_filename, MAIL_DIR_SEPARATOR,
670 (unsigned long) index); 674 (unsigned long) index);
671 675
672 * result = filename; 676 * result = filename;
673 677
674 return MAILMH_NO_ERROR;; 678 return MAILMH_NO_ERROR;;
675} 679}
676 680
677 681
678int mailmh_folder_get_message_fd(struct mailmh_folder * folder, 682int mailmh_folder_get_message_fd(struct mailmh_folder * folder,
679 uint32_t index, int flags, int * result) 683 uint32_t index, int flags, int * result)
680{ 684{
681 char * filename; 685 char * filename;
682 int fd; 686 int fd;
683 int r; 687 int r;
684 688
685#if 0 689#if 0
686 r = mailmh_folder_update(folder); 690 r = mailmh_folder_update(folder);
687 if (r != MAILMH_NO_ERROR) 691 if (r != MAILMH_NO_ERROR)
688 return r; 692 return r;
689#endif 693#endif
690 694
691 r = mailmh_folder_get_message_filename(folder, index, &filename); 695 r = mailmh_folder_get_message_filename(folder, index, &filename);
692 if (r != MAILMH_NO_ERROR) 696 if (r != MAILMH_NO_ERROR)
693 return r; 697 return r;
694 698
695 fd = open(filename, flags); 699 fd = open(filename, flags);
696 free(filename); 700 free(filename);
697 if (fd == -1) 701 if (fd == -1)
698 return MAILMH_ERROR_MSG_NOT_FOUND; 702 return MAILMH_ERROR_MSG_NOT_FOUND;
699 703
700 * result = fd; 704 * result = fd;
701 705
702 return MAILMH_NO_ERROR; 706 return MAILMH_NO_ERROR;
703} 707}
704 708
705int mailmh_folder_get_message_size(struct mailmh_folder * folder, 709int mailmh_folder_get_message_size(struct mailmh_folder * folder,
706 uint32_t index, size_t * result) 710 uint32_t index, size_t * result)
707{ 711{
708 int r; 712 int r;
709 char * filename; 713 char * filename;
710 struct stat buf; 714 struct stat buf;
711 715
712 r = mailmh_folder_get_message_filename(folder, index, &filename); 716 r = mailmh_folder_get_message_filename(folder, index, &filename);
713 if (r != MAILMH_NO_ERROR) 717 if (r != MAILMH_NO_ERROR)
714 return r; 718 return r;
715 719
716 r = stat(filename, &buf); 720 r = stat(filename, &buf);
717 free(filename); 721 free(filename);
718 if (r < 0) 722 if (r < 0)
719 return MAILMH_ERROR_FILE; 723 return MAILMH_ERROR_FILE;
720 724
721 * result = buf.st_size; 725 * result = buf.st_size;
722 726
723 return MAILMH_NO_ERROR; 727 return MAILMH_NO_ERROR;
724} 728}
725 729
726int mailmh_folder_add_message_uid(struct mailmh_folder * folder, 730int mailmh_folder_add_message_uid(struct mailmh_folder * folder,
727 const char * message, size_t size, 731 const char * message, size_t size,
728 uint32_t * pindex) 732 uint32_t * pindex)
729{ 733{
730 char * tmpname; 734 char * tmpname;
731 int fd; 735 int fd;
732 size_t namesize; 736 size_t namesize;
733 size_t left; 737 size_t left;
734 ssize_t res; 738 ssize_t res;
735 struct mailmh_msg_info * msg_info; 739 struct mailmh_msg_info * msg_info;
736 uint32_t index; 740 uint32_t index;
737 int error; 741 int error;
738 int r; 742 int r;
739 unsigned int array_index; 743 unsigned int array_index;
740 struct stat buf; 744 struct stat buf;
741 chashdatum key; 745 chashdatum key;
742 chashdatum data; 746 chashdatum data;
743 747
744#if 0 748#if 0
745 r = mailmh_folder_update(folder); 749 r = mailmh_folder_update(folder);
746 if (r != MAILMH_NO_ERROR) { 750 if (r != MAILMH_NO_ERROR) {
747 error = r; 751 error = r;
748 goto err; 752 goto err;
749 } 753 }
750#endif 754#endif
751 755
752 namesize = strlen(folder->fl_filename) + 20; 756 namesize = strlen(folder->fl_filename) + 20;
753 tmpname = malloc(namesize); 757 tmpname = malloc(namesize);
754 snprintf(tmpname, namesize, "%s%ctmpXXXXXX", 758 snprintf(tmpname, namesize, "%s%ctmpXXXXXX",
755 folder->fl_filename, MAIL_DIR_SEPARATOR); 759 folder->fl_filename, MAIL_DIR_SEPARATOR);
756 fd = mkstemp(tmpname); 760 fd = mkstemp(tmpname);
757 if (fd < 0) { 761 if (fd < 0) {
758 error = MAILMH_ERROR_FILE; 762 error = MAILMH_ERROR_FILE;
759 goto free; 763 goto free;
760 } 764 }
761 765
762 left = size; 766 left = size;
763 while (left > 0) { 767 while (left > 0) {
764 res = write(fd, message, left); 768 res = write(fd, message, left);
765 if (res == -1) { 769 if (res == -1) {
766 close(fd); 770 close(fd);
767 error = MAILMH_ERROR_FILE; 771 error = MAILMH_ERROR_FILE;
768 goto free; 772 goto free;
769 } 773 }
770 774
771 left -= res; 775 left -= res;
772 } 776 }
773 close(fd); 777 close(fd);
774 778
775 r = stat(tmpname, &buf); 779 r = stat(tmpname, &buf);
776 if (r < 0) { 780 if (r < 0) {
777 error = MAILMH_ERROR_FILE; 781 error = MAILMH_ERROR_FILE;
778 goto free; 782 goto free;
779 } 783 }
780 784
781 r = mailmh_folder_alloc_msg(folder, tmpname, &index); 785 r = mailmh_folder_alloc_msg(folder, tmpname, &index);
782 if (r != MAILMH_NO_ERROR) { 786 if (r != MAILMH_NO_ERROR) {
783 unlink(tmpname); 787 unlink(tmpname);
784 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG; 788 error = MAILMH_ERROR_COULD_NOT_ALLOC_MSG;
785 goto free; 789 goto free;
786 } 790 }
787 free(tmpname); 791 free(tmpname);
788 792
789 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime); 793 msg_info = mailmh_msg_info_new(index, size, buf.st_mtime);
790 if (msg_info == NULL) { 794 if (msg_info == NULL) {
791 mailmh_folder_remove_message(folder, index); 795 mailmh_folder_remove_message(folder, index);
792 error = MAILMH_ERROR_MEMORY; 796 error = MAILMH_ERROR_MEMORY;
793 goto err; 797 goto err;
794 } 798 }
795 799
796 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index); 800 r = carray_add(folder->fl_msgs_tab, msg_info, &array_index);
797 if (r < 0) { 801 if (r < 0) {
798 mailmh_folder_remove_message(folder, index); 802 mailmh_folder_remove_message(folder, index);
799 mailmh_msg_info_free(msg_info); 803 mailmh_msg_info_free(msg_info);
800 error = MAILMH_ERROR_MEMORY; 804 error = MAILMH_ERROR_MEMORY;
801 goto err; 805 goto err;
802 } 806 }
803 msg_info->msg_array_index = array_index; 807 msg_info->msg_array_index = array_index;
804 808
805#if 0 809#if 0
806 r = cinthash_add(folder->fl_msgs_hash, index, msg_info); 810 r = cinthash_add(folder->fl_msgs_hash, index, msg_info);
807#endif 811#endif
808 key.data = &index; 812 key.data = &index;
809 key.len = sizeof(index); 813 key.len = sizeof(index);
810 data.data = msg_info; 814 data.data = msg_info;
811 data.len = 0; 815 data.len = 0;
812 816
813 if (pindex != NULL) 817 if (pindex != NULL)
814 * pindex = index; 818 * pindex = index;
815 819
816 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL); 820 r = chash_set(folder->fl_msgs_hash, &key, &data, NULL);
817 if (r < 0) { 821 if (r < 0) {
818 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 822 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
819 mailmh_msg_info_free(msg_info); 823 mailmh_msg_info_free(msg_info);
820 error = MAILMH_ERROR_MEMORY; 824 error = MAILMH_ERROR_MEMORY;
821 goto err; 825 goto err;
822 } 826 }
823 827
824 return MAILMH_NO_ERROR; 828 return MAILMH_NO_ERROR;
825 829
826 free: 830 free:
827 free(tmpname); 831 free(tmpname);
828 err: 832 err:
829 return error; 833 return error;
830} 834}
831 835
832int mailmh_folder_add_message(struct mailmh_folder * folder, 836int mailmh_folder_add_message(struct mailmh_folder * folder,
833 const char * message, size_t size) 837 const char * message, size_t size)
834{ 838{
835 return mailmh_folder_add_message_uid(folder, message, size, NULL); 839 return mailmh_folder_add_message_uid(folder, message, size, NULL);
836} 840}
837 841
838int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder, 842int mailmh_folder_add_message_file_uid(struct mailmh_folder * folder,
839 int fd, uint32_t * pindex) 843 int fd, uint32_t * pindex)
840{ 844{
841 char * message; 845 char * message;
842 struct stat buf; 846 struct stat buf;
843 int r; 847 int r;
844 848
845#if 0 849#if 0
846 r = mailmh_folder_update(folder); 850 r = mailmh_folder_update(folder);
847 if (r != MAILMH_NO_ERROR) 851 if (r != MAILMH_NO_ERROR)
848 return r; 852 return r;
849#endif 853#endif
850 854
851 if (fstat(fd, &buf) == -1) 855 if (fstat(fd, &buf) == -1)
852 return MAILMH_ERROR_FILE; 856 return MAILMH_ERROR_FILE;
853 857
854 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); 858 message = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
855 if (message == MAP_FAILED) 859 if (message == MAP_FAILED)
856 return MAILMH_ERROR_FILE; 860 return MAILMH_ERROR_FILE;
857 861
858 r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex); 862 r = mailmh_folder_add_message_uid(folder, message, buf.st_size, pindex);
859 863
860 munmap(message, buf.st_size); 864 munmap(message, buf.st_size);
861 865
862 return r; 866 return r;
863} 867}
864 868
865int mailmh_folder_add_message_file(struct mailmh_folder * folder, 869int mailmh_folder_add_message_file(struct mailmh_folder * folder,
866 int fd) 870 int fd)
867{ 871{
868 return mailmh_folder_add_message_file_uid(folder, fd, NULL); 872 return mailmh_folder_add_message_file_uid(folder, fd, NULL);
869} 873}
870 874
871int mailmh_folder_remove_message(struct mailmh_folder * folder, 875int mailmh_folder_remove_message(struct mailmh_folder * folder,
872 uint32_t index) 876 uint32_t index)
873{ 877{
874 char * filename; 878 char * filename;
875 struct mailmh_msg_info * msg_info; 879 struct mailmh_msg_info * msg_info;
876 int res; 880 int res;
877 int r; 881 int r;
878 chashdatum key; 882 chashdatum key;
879 chashdatum data; 883 chashdatum data;
880 884
881#if 0 885#if 0
882 r = mailmh_folder_update(folder); 886 r = mailmh_folder_update(folder);
883 if (r != MAILMH_NO_ERROR) { 887 if (r != MAILMH_NO_ERROR) {
884 res = r; 888 res = r;
885 goto err; 889 goto err;
886 } 890 }
887#endif 891#endif
888 892
889 r = mailmh_folder_get_message_filename(folder, index, &filename); 893 r = mailmh_folder_get_message_filename(folder, index, &filename);
890 if (filename == NULL) { 894 if (filename == NULL) {
891 res = r; 895 res = r;
892 goto err; 896 goto err;
893 } 897 }
894 898
895 if (unlink(filename) == -1) { 899 if (unlink(filename) == -1) {
896 res = MAILMH_ERROR_FILE; 900 res = MAILMH_ERROR_FILE;
897 goto free; 901 goto free;
898 } 902 }
899 903
900 key.data = &index; 904 key.data = &index;
901 key.len = sizeof(index); 905 key.len = sizeof(index);
902 r = chash_get(folder->fl_msgs_hash, &key, &data); 906 r = chash_get(folder->fl_msgs_hash, &key, &data);
903#if 0 907#if 0
904 msg_info = cinthash_find(folder->fl_msgs_hash, index); 908 msg_info = cinthash_find(folder->fl_msgs_hash, index);
905#endif 909#endif
906 if (r == 0) { 910 if (r == 0) {
907 msg_info = data.data; 911 msg_info = data.data;
908 912
909 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index); 913 carray_delete_fast(folder->fl_msgs_tab, msg_info->msg_array_index);
910#if 0 914#if 0
911 cinthash_remove(folder->fl_msgs_hash, index); 915 cinthash_remove(folder->fl_msgs_hash, index);
912#endif 916#endif
913 chash_delete(folder->fl_msgs_hash, &key, NULL); 917 chash_delete(folder->fl_msgs_hash, &key, NULL);
914 } 918 }
915 919
916 return MAILMH_NO_ERROR; 920 return MAILMH_NO_ERROR;
917 921
918 free: 922 free:
919 free(filename); 923 free(filename);
920 err: 924 err:
921 return res; 925 return res;
922} 926}
923 927
924 928
925int mailmh_folder_move_message(struct mailmh_folder * dest_folder, 929int mailmh_folder_move_message(struct mailmh_folder * dest_folder,
926 struct mailmh_folder * src_folder, 930 struct mailmh_folder * src_folder,
927 uint32_t index) 931 uint32_t index)
928{ 932{
929 int fd; 933 int fd;
930 char * filename; 934 char * filename;
931 int r; 935 int r;
932 936
933#if 0 937#if 0
934 r = mailmh_folder_update(dest_folder); 938 r = mailmh_folder_update(dest_folder);
935 if (r != MAILMH_NO_ERROR) 939 if (r != MAILMH_NO_ERROR)
936 return r; 940 return r;
937 r = mailmh_folder_update(src_folder); 941 r = mailmh_folder_update(src_folder);
938 if (r != MAILMH_NO_ERROR) 942 if (r != MAILMH_NO_ERROR)
939 return r; 943 return r;
940#endif 944#endif
941 945
942 /* move on the same filesystem */ 946 /* move on the same filesystem */
943 r = mailmh_folder_get_message_filename(src_folder, index, &filename); 947 r = mailmh_folder_get_message_filename(src_folder, index, &filename);
944 if (r != MAILMH_NO_ERROR) 948 if (r != MAILMH_NO_ERROR)
945 return r; 949 return r;
946 950
947 r = mailmh_folder_alloc_msg(dest_folder, filename, &index); 951 r = mailmh_folder_alloc_msg(dest_folder, filename, &index);
948 free(filename); 952 free(filename);
949 if (r == MAILMH_NO_ERROR) 953 if (r == MAILMH_NO_ERROR)
950 return MAILMH_NO_ERROR; 954 return MAILMH_NO_ERROR;
951 955
952 /* move on the different filesystems */ 956 /* move on the different filesystems */
953 r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd); 957 r = mailmh_folder_get_message_fd(src_folder, index, O_RDONLY, &fd);
954 if (r != MAILMH_NO_ERROR) 958 if (r != MAILMH_NO_ERROR)
955 return r; 959 return r;
956 960
957 r = mailmh_folder_add_message_file(dest_folder, fd); 961 r = mailmh_folder_add_message_file(dest_folder, fd);
958 if (r != MAILMH_NO_ERROR) { 962 if (r != MAILMH_NO_ERROR) {
959 close(fd); 963 close(fd);
960 return r; 964 return r;
961 } 965 }
962 966
963 close(fd); 967 close(fd);
964 968
965 r = mailmh_folder_remove_message(src_folder, index); 969 r = mailmh_folder_remove_message(src_folder, index);
966 970
967 return MAILMH_NO_ERROR; 971 return MAILMH_NO_ERROR;
968} 972}
969 973
970unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder) 974unsigned int mailmh_folder_get_message_number(struct mailmh_folder * folder)
971{ 975{
972 unsigned int i; 976 unsigned int i;
973 unsigned int count; 977 unsigned int count;
974 978
975 count = 0; 979 count = 0;
976 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++) 980 for(i = 0 ; i < carray_count(folder->fl_msgs_tab) ; i ++)
977 if (carray_get(folder->fl_msgs_tab, i) != NULL) 981 if (carray_get(folder->fl_msgs_tab, i) != NULL)
978 count ++; 982 count ++;
979 983
980 return count; 984 return count;
981} 985}