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.
Showing
6 changed files
with
235 additions
and
48 deletions
... | @@ -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, | ... | ... |
-
Please register or sign in to post a comment