Commit 89d93a75 89d93a75c4abec10b9cfe0041eaf654d00f0a0ee by Sergey Poznyakoff

Fix the use of erad-only maildir folders. Imap4d improvements.

New imap4d statement "retain-groups" instructs it to retain the
named supplementary user groups when switching to the user
privileges (previously, imap4d just switched to <user>:mail).
Read-only mailboxes are handled graciously: SELECT succeeds on
such mailboxes, bug marks them explicitly as read-only.

* imap4d/imap4d.c (user_retain_groups): New global.
New config statement "retain-groups".
(mu_get_user_groups): New function.
(imap4d_session_setup0): Use mu_switch_to_privs instead of
just setuid.
* imap4d/list.c (imap4d_list): Fix handling of
  LIST "" "/path/to/mbox"
* imap4d/select.c (imap4d_select0): Retry opening in read-only
mode if failed to open for read-write.
* libproto/maildir/mbox.c (maildir_mkfilename)
(mk_info_filename): Change return value and signature. All uses
changed.
(maildir_scan0): Don't shuffle messages if mailbox is opened
read-only.
* libproto/maildir/folder.c: Update call to maildir_mkfilename.
* libproto/maildir/maildir.h (maildir_mkfilename): Change
prototype.
1 parent 6074d4d8
...@@ -35,6 +35,8 @@ enum tls_mode tls_mode; ...@@ -35,6 +35,8 @@ enum tls_mode tls_mode;
35 int login_disabled; /* Disable LOGIN command */ 35 int login_disabled; /* Disable LOGIN command */
36 int create_home_dir; /* Create home directory if it does not 36 int create_home_dir; /* Create home directory if it does not
37 exist */ 37 exist */
38 mu_list_t user_retain_groups;
39
38 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 40 int home_dir_mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
39 41
40 int mailbox_mode[NS_MAX]; 42 int mailbox_mode[NS_MAX];
...@@ -247,6 +249,31 @@ cb_mailbox_mode (void *data, mu_config_value_t *val) ...@@ -247,6 +249,31 @@ cb_mailbox_mode (void *data, mu_config_value_t *val)
247 return 0; 249 return 0;
248 } 250 }
249 251
252 static int
253 cb2_group (const char *gname, void *data)
254 {
255 mu_list_t list = data;
256 struct group *group;
257
258 group = getgrnam (gname);
259 if (!group)
260 mu_error (_("unknown group: %s"), gname);
261 else
262 mu_list_append (list, (void*)group->gr_gid);
263 return 0;
264 }
265
266 static int
267 cb_group (void *data, mu_config_value_t *arg)
268 {
269 mu_list_t *plist = data;
270
271 if (!*plist)
272 mu_list_create (plist);
273 return mu_cfg_string_value_cb (arg, cb2_group, *plist);
274 }
275
276
250 struct imap4d_srv_config 277 struct imap4d_srv_config
251 { 278 {
252 struct mu_srv_config m_cfg; 279 struct mu_srv_config m_cfg;
...@@ -392,6 +419,9 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -392,6 +419,9 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
392 { "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode, 419 { "home-dir-mode", mu_cfg_callback, NULL, 0, cb_mode,
393 N_("File mode for creating user home directories (octal)."), 420 N_("File mode for creating user home directories (octal)."),
394 N_("mode") }, 421 N_("mode") },
422 { "retain-groups", mu_cfg_callback, &user_retain_groups, 0, cb_group,
423 N_("Retain these supplementary groups when switching to user privileges"),
424 N_("groups: list of string") },
395 #ifdef WITH_TLS 425 #ifdef WITH_TLS
396 { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls, 426 { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls,
397 N_("Kind of TLS encryption to use") }, 427 N_("Kind of TLS encryption to use") },
...@@ -424,6 +454,48 @@ static struct mu_cfg_param imap4d_cfg_param[] = { ...@@ -424,6 +454,48 @@ static struct mu_cfg_param imap4d_cfg_param[] = {
424 }; 454 };
425 455
426 int 456 int
457 mu_get_user_groups (const char *user, mu_list_t retain, mu_list_t *pgrouplist)
458 {
459 int rc;
460 struct group *gr;
461 mu_list_t list;
462
463 if (!*pgrouplist)
464 {
465 rc = mu_list_create (pgrouplist);
466 if (rc)
467 {
468 mu_error(_("%s: cannot create list: %s"),
469 "mu_get_user_groups", mu_strerror (rc));
470 return rc;
471 }
472 }
473
474 list = *pgrouplist;
475 setgrent ();
476 for (rc = 0; rc == 0 && (gr = getgrent ()); )
477 {
478 char **p;
479 for (p = gr->gr_mem; *p; p++)
480 if (strcmp (*p, user) == 0)
481 {
482 if (retain && mu_list_locate (retain, (void*)gr->gr_gid, NULL))
483 continue;
484
485 /* FIXME: Avoid duplicating gids */
486 rc = mu_list_append (list, (void*)gr->gr_gid);
487 if (rc)
488 mu_error(_("%s: cannot append to list: %s"),
489 "mu_get_user_groups",
490 mu_strerror (rc));
491 break;
492 }
493 }
494 endgrent ();
495 return rc;
496 }
497
498 int
427 imap4d_session_setup0 () 499 imap4d_session_setup0 ()
428 { 500 {
429 if (auth_deny_user_list && 501 if (auth_deny_user_list &&
...@@ -502,7 +574,48 @@ imap4d_session_setup0 () ...@@ -502,7 +574,48 @@ imap4d_session_setup0 ()
502 } 574 }
503 575
504 if (auth_data->change_uid) 576 if (auth_data->change_uid)
505 setuid (auth_data->uid); 577 {
578 struct group *gr;
579 mu_list_t groups = NULL;
580 int rc;
581 uid_t uid;
582
583 uid = getuid ();
584 if (uid != auth_data->uid)
585 {
586 rc = mu_list_create (&groups);
587 if (rc)
588 {
589 mu_error(_("cannot create list: %s"), mu_strerror (rc));
590 free (imap4d_homedir);
591 free (real_homedir);
592 return 1;
593 }
594 mu_list_append (groups, (void*)auth_data->gid);
595
596 rc = mu_get_user_groups (auth_data->name, user_retain_groups,
597 &groups);
598 if (rc)
599 {
600 /* FIXME: When mu_get_user_groups goes to the library, add a
601 diag message here */
602 free (imap4d_homedir);
603 free (real_homedir);
604 return 1;
605 }
606 gr = getgrnam ("mail");
607 rc = mu_switch_to_privs (auth_data->uid, gr->gr_gid, groups);
608 mu_list_destroy (&groups);
609 if (rc)
610 {
611 mu_error (_("can't switch to user %s privileges: %s"),
612 auth_data->name, mu_strerror (rc));
613 free (imap4d_homedir);
614 free (real_homedir);
615 return 1;
616 }
617 }
618 }
506 619
507 util_chdir (imap4d_homedir); 620 util_chdir (imap4d_homedir);
508 namespace_init_session (imap4d_homedir); 621 namespace_init_session (imap4d_homedir);
......
...@@ -157,6 +157,7 @@ imap4d_list (struct imap4d_session *session, ...@@ -157,6 +157,7 @@ imap4d_list (struct imap4d_session *session,
157 "LIST (\\NoSelect) \"%c\" \"\"", 157 "LIST (\\NoSelect) \"%c\" \"\"",
158 MU_HIERARCHY_DELIMITER); 158 MU_HIERARCHY_DELIMITER);
159 } 159 }
160
160 /* There is only one mailbox in the "INBOX" hierarchy ... INBOX. */ 161 /* There is only one mailbox in the "INBOX" hierarchy ... INBOX. */
161 else if (mu_c_strcasecmp (ref, "INBOX") == 0 162 else if (mu_c_strcasecmp (ref, "INBOX") == 0
162 || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0)) 163 || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0))
...@@ -168,8 +169,8 @@ imap4d_list (struct imap4d_session *session, ...@@ -168,8 +169,8 @@ imap4d_list (struct imap4d_session *session,
168 int status; 169 int status;
169 mu_folder_t folder; 170 mu_folder_t folder;
170 char *cwd; 171 char *cwd;
171 char *p, *q;
172 struct refinfo refinfo; 172 struct refinfo refinfo;
173 size_t seglen;
173 174
174 switch (*wcard) 175 switch (*wcard)
175 { 176 {
...@@ -209,12 +210,10 @@ imap4d_list (struct imap4d_session *session, ...@@ -209,12 +210,10 @@ imap4d_list (struct imap4d_session *session,
209 /* Move any directory not containing a wildcard into the reference 210 /* Move any directory not containing a wildcard into the reference
210 So (ref = ~guest, wcard = Mail/folder1/%.vf) --> 211 So (ref = ~guest, wcard = Mail/folder1/%.vf) -->
211 (ref = ~guest/Mail/folder1, wcard = %.vf). */ 212 (ref = ~guest/Mail/folder1, wcard = %.vf). */
212 for (p = wcard; (q = strpbrk (p, "/%*")) && *q == '/'; p = q + 1) 213 seglen = strcspn (wcard, "%*");
213 ;
214 214
215 if (p > wcard) 215 if (seglen)
216 { 216 {
217 size_t seglen = p - wcard;
218 size_t reflen = strlen (ref); 217 size_t reflen = strlen (ref);
219 int addslash = (reflen > 0 && ref[reflen-1] != '/'); 218 int addslash = (reflen > 0 && ref[reflen-1] != '/');
220 size_t len = seglen + reflen + addslash + 1; 219 size_t len = seglen + reflen + addslash + 1;
...@@ -235,6 +234,21 @@ imap4d_list (struct imap4d_session *session, ...@@ -235,6 +234,21 @@ imap4d_list (struct imap4d_session *session,
235 return io_completion_response (command, RESP_NO, 234 return io_completion_response (command, RESP_NO,
236 "The requested item could not be found."); 235 "The requested item could not be found.");
237 } 236 }
237
238 /* FIXME */
239 if (wcard[0] == 0)
240 {
241 char *p = strrchr (ref, '/');
242 if (p && p[1])
243 {
244 *p++ = 0;
245 wcard = p;
246
247 p = strrchr (cwd, '/');
248 *p = 0;
249 }
250 }
251
238 status = mu_folder_create (&folder, cwd); 252 status = mu_folder_create (&folder, cwd);
239 if (status) 253 if (status)
240 { 254 {
......
...@@ -64,13 +64,17 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname, ...@@ -64,13 +64,17 @@ imap4d_select0 (struct imap4d_command *command, const char *mboxname,
64 if (!mailbox_name) 64 if (!mailbox_name)
65 return io_completion_response (command, RESP_NO, "Couldn't open mailbox"); 65 return io_completion_response (command, RESP_NO, "Couldn't open mailbox");
66 66
67 if (flags & MU_STREAM_RDWR) 67 if (flags & MU_STREAM_WRITE)
68 { 68 {
69 status = manlock_open_mailbox (&mbox, mailbox_name, 1, flags); 69 status = manlock_open_mailbox (&mbox, mailbox_name, 1, flags);
70 if (status)
71 flags &= ~MU_STREAM_WRITE;
70 } 72 }
71 else 73
74 if (!(flags & MU_STREAM_WRITE))
72 { 75 {
73 status = mu_mailbox_create_default (&mbox, mailbox_name); 76 status = mu_mailbox_create_default (&mbox, mailbox_name);
77
74 if (status) 78 if (status)
75 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default", 79 mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_create_default",
76 mailbox_name, 80 mailbox_name,
......
...@@ -40,7 +40,12 @@ static int ...@@ -40,7 +40,12 @@ static int
40 dir_exists (const char *name, const char *suf) 40 dir_exists (const char *name, const char *suf)
41 { 41 {
42 struct stat st; 42 struct stat st;
43 char *s = maildir_mkfilename (name, suf, NULL); 43 int rc;
44 char *s;
45
46 rc = maildir_mkfilename (name, suf, NULL, &s);
47 if (rc)
48 return 0;/* FIXME: error message */
44 49
45 if (stat (s, &st) < 0) 50 if (stat (s, &st) < 0)
46 return 0; 51 return 0;
......
...@@ -21,5 +21,5 @@ ...@@ -21,5 +21,5 @@
21 #define CURSUF "cur" 21 #define CURSUF "cur"
22 #define NEWSUF "new" 22 #define NEWSUF "new"
23 23
24 extern char *maildir_mkfilename (const char *dir, const char *suffix, 24 int maildir_mkfilename (const char *dir, const char *suffix,
25 const char *name); 25 const char *name, char **retname);
......
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
68 #include <mailutils/sys/mailbox.h> 68 #include <mailutils/sys/mailbox.h>
69 #include <mailutils/sys/registrar.h> 69 #include <mailutils/sys/registrar.h>
70 #include <mailutils/sys/amd.h> 70 #include <mailutils/sys/amd.h>
71 #include <mailutils/io.h>
71 #include <maildir.h> 72 #include <maildir.h>
72 73
73 #ifndef PATH_MAX 74 #ifndef PATH_MAX
...@@ -237,8 +238,9 @@ read_random (void *buf, size_t size) ...@@ -237,8 +238,9 @@ read_random (void *buf, size_t size)
237 return rc != size; 238 return rc != size;
238 } 239 }
239 240
240 char * 241 int
241 maildir_mkfilename (const char *directory, const char *suffix, const char *name) 242 maildir_mkfilename (const char *directory, const char *suffix, const char *name,
243 char **ret_name)
242 { 244 {
243 size_t size = strlen (directory) + 1 + strlen (suffix) + 1; 245 size_t size = strlen (directory) + 1 + strlen (suffix) + 1;
244 char *tmp; 246 char *tmp;
...@@ -247,22 +249,25 @@ maildir_mkfilename (const char *directory, const char *suffix, const char *name) ...@@ -247,22 +249,25 @@ maildir_mkfilename (const char *directory, const char *suffix, const char *name)
247 size += 1 + strlen (name); 249 size += 1 + strlen (name);
248 250
249 tmp = malloc (size); 251 tmp = malloc (size);
252 if (!tmp)
253 return errno;
250 sprintf (tmp, "%s/%s", directory, suffix); 254 sprintf (tmp, "%s/%s", directory, suffix);
251 if (name) 255 if (name)
252 { 256 {
253 strcat (tmp, "/"); 257 strcat (tmp, "/");
254 strcat (tmp, name); 258 strcat (tmp, name);
255 } 259 }
256 return tmp; 260 *ret_name = tmp;
261 return 0;
257 } 262 }
258 263
259 static char * 264 static int
260 mk_info_filename (char *directory, char *suffix, char *name, int flags) 265 mk_info_filename (char *directory, char *suffix, char *name, int flags,
266 char **ret_name)
261 { 267 {
262 char fbuf[info_map_size + 1]; 268 char fbuf[info_map_size + 1];
263 char *tmp; 269 char *tmp;
264 int namelen; 270 int namelen;
265 size_t size;
266 271
267 tmp = strchr (name, ':'); 272 tmp = strchr (name, ':');
268 if (!tmp) 273 if (!tmp)
...@@ -270,16 +275,10 @@ mk_info_filename (char *directory, char *suffix, char *name, int flags) ...@@ -270,16 +275,10 @@ mk_info_filename (char *directory, char *suffix, char *name, int flags)
270 else 275 else
271 namelen = tmp - name; 276 namelen = tmp - name;
272 277
273 size = strlen (directory)
274 + 1 + strlen (suffix)
275 + 1 + namelen + 1;
276
277 flags_to_info (flags, fbuf); 278 flags_to_info (flags, fbuf);
278 size += 3 + strlen (fbuf);
279 279
280 tmp = malloc (size); 280 return mu_asprintf (ret_name, "%s/%s/%*.*s:2,%s",
281 sprintf (tmp, "%s/%s/%*.*s:2,%s", directory, suffix, namelen, namelen, name, fbuf); 281 directory, suffix, namelen, namelen, name, fbuf);
282 return tmp;
283 } 282 }
284 283
285 char * 284 char *
...@@ -335,8 +334,7 @@ static int ...@@ -335,8 +334,7 @@ static int
335 maildir_cur_message_name (struct _amd_message *amsg, char **pname) 334 maildir_cur_message_name (struct _amd_message *amsg, char **pname)
336 { 335 {
337 struct _maildir_message *msg = (struct _maildir_message *) amsg; 336 struct _maildir_message *msg = (struct _maildir_message *) amsg;
338 *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name); 337 return maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name, pname);
339 return 0;
340 } 338 }
341 339
342 static int 340 static int
...@@ -350,9 +348,11 @@ maildir_new_message_name (struct _amd_message *amsg, int flags, int expunge, ...@@ -350,9 +348,11 @@ maildir_new_message_name (struct _amd_message *amsg, int flags, int expunge,
350 *pname = NULL; 348 *pname = NULL;
351 } 349 }
352 else if (strcmp (msg->dir, CURSUF) == 0) 350 else if (strcmp (msg->dir, CURSUF) == 0)
353 *pname = mk_info_filename (amsg->amd->name, CURSUF, msg->file_name, flags); 351 return mk_info_filename (amsg->amd->name, CURSUF, msg->file_name, flags,
352 pname);
354 else 353 else
355 *pname = maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name); 354 return maildir_mkfilename (amsg->amd->name, msg->dir, msg->file_name,
355 pname);
356 return 0; 356 return 0;
357 } 357 }
358 358
...@@ -388,7 +388,16 @@ static void ...@@ -388,7 +388,16 @@ static void
388 maildir_delete_file (char *dirname, char *filename) 388 maildir_delete_file (char *dirname, char *filename)
389 { 389 {
390 struct stat st; 390 struct stat st;
391 char *name = maildir_mkfilename (dirname, filename, NULL); 391 char *name;
392 int rc;
393
394 rc = maildir_mkfilename (dirname, filename, NULL, &name);
395 if (rc)
396 {
397 mu_error ("maildir: failed to create file name: %s",
398 mu_strerror (errno));
399 return;
400 }
392 401
393 if (stat (name, &st) == 0) 402 if (stat (name, &st) == 0)
394 { 403 {
...@@ -429,15 +438,21 @@ maildir_create (struct _amd_data *amd, int flags) ...@@ -429,15 +438,21 @@ maildir_create (struct _amd_data *amd, int flags)
429 for (i = 0; i < 3; i++) 438 for (i = 0; i < 3; i++)
430 { 439 {
431 DIR *dir; 440 DIR *dir;
432 char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL); 441 int rc;
433 int rc = maildir_opendir (&dir, tmpname, 442 char *tmpname;
443
444 rc = maildir_mkfilename (amd->name, dirs[i], NULL, &tmpname);
445 if (rc)
446 return rc;
447
448 rc = maildir_opendir (&dir, tmpname,
434 PERMS | 449 PERMS |
435 mu_stream_flags_to_mode (amd->mailbox->flags, 450 mu_stream_flags_to_mode (amd->mailbox->flags,
436 1)); 451 1));
452 free (tmpname);
437 if (rc) 453 if (rc)
438 return rc; 454 return rc;
439 closedir (dir); 455 closedir (dir);
440 free (tmpname);
441 } 456 }
442 return 0; 457 return 0;
443 } 458 }
...@@ -454,9 +469,15 @@ maildir_msg_init (struct _amd_data *amd, struct _amd_message *amm) ...@@ -454,9 +469,15 @@ maildir_msg_init (struct _amd_data *amd, struct _amd_message *amm)
454 char *name, *fname; 469 char *name, *fname;
455 struct stat st; 470 struct stat st;
456 int i; 471 int i;
472 int rc;
457 473
458 name = maildir_uniq (amd, -1); 474 name = maildir_uniq (amd, -1);
459 fname = maildir_mkfilename (amd->name, NEWSUF, name); 475 rc = maildir_mkfilename (amd->name, NEWSUF, name, &fname);
476 if (rc)
477 {
478 free (name);
479 return rc;
480 }
460 481
461 msg->dir = TMPSUF; 482 msg->dir = TMPSUF;
462 483
...@@ -483,35 +504,41 @@ maildir_msg_finish_delivery (struct _amd_data *amd, struct _amd_message *amm, ...@@ -483,35 +504,41 @@ maildir_msg_finish_delivery (struct _amd_data *amd, struct _amd_message *amm,
483 const mu_message_t orig_msg) 504 const mu_message_t orig_msg)
484 { 505 {
485 struct _maildir_message *msg = (struct _maildir_message *) amm; 506 struct _maildir_message *msg = (struct _maildir_message *) amm;
486 char *oldname = maildir_mkfilename (amd->name, TMPSUF, msg->file_name); 507 char *oldname, *newname;
487 char *newname;
488 mu_attribute_t attr; 508 mu_attribute_t attr;
489 int flags; 509 int flags;
510 int rc;
511
512 rc = maildir_mkfilename (amd->name, TMPSUF, msg->file_name, &oldname);
513 if (rc)
514 return rc;
490 515
491 if (mu_message_get_attribute (orig_msg, &attr) == 0 516 if (mu_message_get_attribute (orig_msg, &attr) == 0
492 && mu_attribute_is_read (attr) 517 && mu_attribute_is_read (attr)
493 && mu_attribute_get_flags (attr, &flags) == 0) 518 && mu_attribute_get_flags (attr, &flags) == 0)
494 { 519 {
495 msg->dir = CURSUF; 520 msg->dir = CURSUF;
496 newname = mk_info_filename (amd->name, CURSUF, msg->file_name, flags); 521 rc = mk_info_filename (amd->name, CURSUF, msg->file_name, flags,
522 &newname);
497 } 523 }
498 else 524 else
499 { 525 {
500 msg->dir = NEWSUF; 526 msg->dir = NEWSUF;
501 newname = maildir_mkfilename (amd->name, NEWSUF, msg->file_name); 527 rc = maildir_mkfilename (amd->name, NEWSUF, msg->file_name, &newname);
502 } 528 }
503 529
530 if (rc == 0)
531 {
504 unlink (newname); 532 unlink (newname);
505 if (link (oldname, newname) == 0) 533 if (link (oldname, newname) == 0)
506 unlink (oldname); 534 unlink (oldname);
507 else 535 else
508 { 536 rc = errno; /* FIXME? */
509 return errno; /* FIXME? */
510 } 537 }
511 538
512 free (oldname); 539 free (oldname);
513 free (newname); 540 free (newname);
514 return 0; 541 return rc;
515 } 542 }
516 543
517 544
...@@ -523,7 +550,11 @@ maildir_flush (struct _amd_data *amd) ...@@ -523,7 +550,11 @@ maildir_flush (struct _amd_data *amd)
523 int rc; 550 int rc;
524 DIR *dir; 551 DIR *dir;
525 struct dirent *entry; 552 struct dirent *entry;
526 char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL); 553 char *tmpname;
554
555 rc = maildir_mkfilename (amd->name, TMPSUF, NULL, &tmpname);
556 if (rc)
557 return rc;
527 558
528 rc = maildir_opendir (&dir, tmpname, 559 rc = maildir_opendir (&dir, tmpname,
529 PERMS | 560 PERMS |
...@@ -561,6 +592,7 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir) ...@@ -561,6 +592,7 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir)
561 while ((entry = readdir (dir))) 592 while ((entry = readdir (dir)))
562 { 593 {
563 char *oldname, *newname; 594 char *oldname, *newname;
595 int rc;
564 596
565 switch (entry->d_name[0]) 597 switch (entry->d_name[0])
566 { 598 {
...@@ -568,9 +600,16 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir) ...@@ -568,9 +600,16 @@ maildir_deliver_new (struct _amd_data *amd, DIR *dir)
568 break; 600 break;
569 601
570 default: 602 default:
571 oldname = maildir_mkfilename (amd->name, NEWSUF, entry->d_name); 603 rc = maildir_mkfilename (amd->name, NEWSUF, entry->d_name, &oldname);
572 newname = mk_info_filename (amd->name, CURSUF, entry->d_name, 0); 604 if (rc)
573 rename (oldname, newname); 605 return rc;
606 rc = mk_info_filename (amd->name, CURSUF, entry->d_name, 0, &newname);
607 if (rc)
608 {
609 free (oldname);
610 return rc;
611 }
612 rename (oldname, newname); /* FIXME: Error code? */
574 free (oldname); 613 free (oldname);
575 free (newname); 614 free (newname);
576 } 615 }
...@@ -654,19 +693,27 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, ...@@ -654,19 +693,27 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
654 maildir_flush (amd); 693 maildir_flush (amd);
655 694
656 /* 2nd phase: Scan and deliver messages from new */ 695 /* 2nd phase: Scan and deliver messages from new */
657 name = maildir_mkfilename (amd->name, NEWSUF, NULL); 696 status = maildir_mkfilename (amd->name, NEWSUF, NULL, &name);
697 if (status)
698 return status;
658 699
659 status = maildir_opendir (&dir, name, 700 status = maildir_opendir (&dir, name,
660 PERMS | 701 PERMS |
661 mu_stream_flags_to_mode (mailbox->flags, 1)); 702 mu_stream_flags_to_mode (mailbox->flags, 1));
662 if (status == 0) 703 if (status == 0)
663 { 704 {
705 if (mailbox->flags & MU_STREAM_WRITE)
664 maildir_deliver_new (amd, dir); 706 maildir_deliver_new (amd, dir);
707 else
708 status = maildir_scan_dir (amd, dir, NEWSUF);
665 closedir (dir); 709 closedir (dir);
666 } 710 }
667 free (name); 711 free (name);
668 712
669 name = maildir_mkfilename (amd->name, CURSUF, NULL); 713 status = maildir_mkfilename (amd->name, CURSUF, NULL, &name);
714 if (status)
715 return status;
716
670 /* 3rd phase: Scan cur/ */ 717 /* 3rd phase: Scan cur/ */
671 status = maildir_opendir (&dir, name, 718 status = maildir_opendir (&dir, name,
672 PERMS | 719 PERMS |
...@@ -746,7 +793,11 @@ maildir_remove (struct _amd_data *amd) ...@@ -746,7 +793,11 @@ maildir_remove (struct _amd_data *amd)
746 793
747 for (i = 0; rc == 0 && i < 3; i++) 794 for (i = 0; rc == 0 && i < 3; i++)
748 { 795 {
749 char *name = maildir_mkfilename (amd->name, suf[i], NULL); 796 char *name;
797
798 rc = maildir_mkfilename (amd->name, suf[i], NULL, &name);
799 if (rc)
800 return rc;
750 rc = amd_remove_dir (name); 801 rc = amd_remove_dir (name);
751 if (rc) 802 if (rc)
752 mu_diag_output (MU_DIAG_WARNING, 803 mu_diag_output (MU_DIAG_WARNING,
......