static int maildir_keywords_commit(struct maildir_keywords *mk) { const struct mailbox_permissions *perm; struct dotlock *dotlock; const char *lock_path; mode_t old_mask; int i, fd; mk->synced = FALSE; if (!mk->changed || mk->mbox == NULL) return 0; lock_path = t_strconcat(mk->path, ".lock", NULL); i_unlink_if_exists(lock_path); perm = mailbox_get_permissions(&mk->mbox->box); for (i = 0;; i++) { /* we could just create the temp file directly, but doing it this ways avoids potential problems with overwriting contents in malicious symlinks */ old_mask = umask(0777 & ~perm->file_create_mode); fd = file_dotlock_open(&mk->dotlock_settings, mk->path, DOTLOCK_CREATE_FLAG_NONBLOCK, &dotlock); umask(old_mask); if (fd != -1) break; if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) { mail_storage_set_critical(mk->storage, "file_dotlock_open(%s) failed: %m", mk->path); return -1; } /* the control dir doesn't exist. create it unless the whole mailbox was just deleted. */ if (!maildir_set_deleted(&mk->mbox->box)) return -1; } if (maildir_keywords_write_fd(mk, lock_path, fd) < 0) { file_dotlock_delete(&dotlock); return -1; } if (file_dotlock_replace(&dotlock, 0) < 0) { mail_storage_set_critical(mk->storage, "file_dotlock_replace(%s) failed: %m", mk->path); return -1; } mk->changed = FALSE; return 0; }
static int maildir_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st_r) { struct mailbox *box = &mbox->box; int i; for (i = 0;; i++) { if (nfs_safe_stat(path, st_r) == 0) return 0; if (errno != ENOENT || i == MAILDIR_DELETE_RETRY_COUNT) break; if (!maildir_set_deleted(box)) return -1; /* try again */ } mail_storage_set_critical(box->storage, "stat(%s) failed: %m", path); return -1; }