enum maildir_uidlist_rec_flag flags;
int move_new, ret = 1;
- src = t_str_new(1024);
- dest = t_str_new(1024);
-
dir = new_dir ? ctx->new_dir : ctx->cur_dir;
dirp = opendir(dir);
if (dirp == NULL) {
return -1;
}
+ t_push();
+ src = t_str_new(1024);
+ dest = t_str_new(1024);
+
move_new = new_dir && !mailbox_is_readonly(&ctx->ibox->box) &&
!ctx->ibox->keep_recent;
while ((dp = readdir(dirp)) != NULL) {
mail_storage_set_critical(storage,
"closedir(%s) failed: %m", dir);
}
+
+ t_pop();
return ret < 0 ? -1 : 0;
}
ctx->uidlist_sync_ctx =
maildir_uidlist_sync_init(ctx->ibox->uidlist, ctx->partial);
+ /* we have to lock uidlist immediately, otherwise there's race
+ conditions with other processes who might write older maildir
+ file list into uidlist.
+
+ alternative would be to lock it when new files are found, but
+ the directory scans _must_ be restarted then */
+ if (maildir_uidlist_try_lock(ctx->ibox->uidlist) < 0)
+ return -1;
+
if (maildir_scan_dir(ctx, TRUE) < 0)
return -1;
if (cur_changed) {
"file_dotlock_open(%s) failed: %m", path);
return -1;
}
-
uidlist->lock_fd = fd;
+
+ /* our view of uidlist must be up-to-date if we plan on changing it */
+ if (maildir_uidlist_update(uidlist) < 0)
+ return -1;
+
return 1;
}
iter = maildir_uidlist_iter_init(uidlist->ibox->uidlist);
while (maildir_uidlist_iter_next(iter, &uid, &flags, &filename)) {
+ /* avoid overflowing str buffer so we don't eat more memory
+ than we need. */
if (str_len(str) + MAX_INT_STRLEN +
- strlen(filename) + 2 >= 4096) {
+ strlen(filename) + 5 + 10 >= 4096) {
/* flush buffer */
if (write_full(uidlist->lock_fd,
str_data(str), str_len(str)) < 0) {
i_assert(!ctx->synced);
+ if (UIDLIST_IS_LOCKED(ctx->uidlist)) {
+ ctx->synced = TRUE;
+ return 1;
+ }
+
if (!ctx->uidlist->initial_read) {
/* first time reading the uidlist,
no locking yet */
ctx->failed = TRUE;
return -1;
}
- if (maildir_uidlist_update(ctx->uidlist) < 0) {
- ctx->failed = TRUE;
- return -1;
- }
ctx->synced = TRUE;
return 1;
if (!ctx->finished)
maildir_uidlist_sync_finish(ctx);
- if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked)
+ if (ctx->new_files_count != 0 && !ctx->failed && !ctx->locked) {
+ t_push();
ret = maildir_uidlist_rewrite(ctx->uidlist);
+ t_pop();
+ }
if (ctx->partial)
maildir_uidlist_mark_all(ctx->uidlist, FALSE);