bool index_storage_is_readonly(struct mailbox *box)
{
- if ((box->flags & MAILBOX_FLAG_READONLY) != 0)
- return TRUE;
-
- if (box->backend_readonly) {
- /* return read-only only if there are no private flags
- (that are stored in index files) */
- if (mailbox_get_private_flags_mask(box) == 0)
- return TRUE;
- }
- return FALSE;
+ return (box->flags & MAILBOX_FLAG_READONLY) != 0;
}
bool index_storage_allow_new_keywords(struct mailbox *box)
static int maildir_mailbox_open_existing(struct mailbox *box)
{
struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
- const char *box_path = mailbox_get_path(box);
mbox->uidlist = maildir_uidlist_init(mbox);
mbox->keywords = maildir_keywords_init(mbox);
mbox);
}
- if (access(t_strconcat(box_path, "/cur", NULL), W_OK) < 0 &&
- errno == EACCES)
- mbox->box.backend_readonly = TRUE;
if (index_storage_mailbox_open(box, FALSE) < 0)
return -1;
return 0;
}
+static bool maildir_storage_is_readonly(struct mailbox *box)
+{
+ struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
+
+ if (index_storage_is_readonly(box))
+ return TRUE;
+
+ if (maildir_is_backend_readonly(mbox)) {
+ /* return read-only only if there are no private flags
+ (that are stored in index files) */
+ if (mailbox_get_private_flags_mask(box) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
static int maildir_mailbox_open(struct mailbox *box)
{
const char *box_path = mailbox_get_path(box);
return mbox->_private_flags_mask;
}
+bool maildir_is_backend_readonly(struct maildir_mailbox *mbox)
+{
+ if (!mbox->backend_readonly_set) {
+ const char *box_path = mailbox_get_path(&mbox->box);
+
+ mbox->backend_readonly_set = TRUE;
+ if (access(t_strconcat(box_path, "/cur", NULL), W_OK) < 0 &&
+ errno == EACCES)
+ mbox->backend_readonly = TRUE;
+ }
+ return mbox->backend_readonly;
+}
+
struct mail_storage maildir_storage = {
.name = MAILDIR_STORAGE_NAME,
.class_flags = 0,
struct mailbox maildir_mailbox = {
.v = {
- index_storage_is_readonly,
+ maildir_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
maildir_mailbox_open,
unsigned int synced:1;
unsigned int syncing_commit:1;
unsigned int private_flags_mask_set:1;
+ unsigned int backend_readonly:1;
+ unsigned int backend_readonly_set:1;
};
extern struct mail_vfuncs maildir_mail_vfuncs;
bool maildir_set_deleted(struct mailbox *box);
uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list);
int maildir_lose_unexpected_dir(struct mail_storage *storage, const char *path);
+bool maildir_is_backend_readonly(struct maildir_mailbox *mbox);
struct mail_save_context *
maildir_save_alloc(struct mailbox_transaction_context *_t);
maildir_keywords_sync_init(mbox->keywords, _box->index);
ctx->sync_changes =
index_sync_changes_init(ctx->sync_ctx, ctx->view, ctx->trans,
- mbox->box.backend_readonly);
+ maildir_is_backend_readonly(mbox));
ctx->start_time = time(NULL);
*ctx_r = ctx;
if (mbox->mbox_file_stream != NULL) {
/* read-only mbox stream */
- i_assert(mbox->box.backend_readonly);
+ i_assert(mbox_is_backend_readonly(mbox));
return 0;
}
fd = open(mailbox_get_path(&mbox->box),
- mbox->box.backend_readonly ? O_RDONLY : O_RDWR);
- if (fd == -1 && errno == EACCES && !mbox->box.backend_readonly) {
- mbox->box.backend_readonly = TRUE;
+ mbox_is_backend_readonly(mbox) ? O_RDONLY : O_RDWR);
+ if (fd == -1 && errno == EACCES && !mbox->backend_readonly) {
+ mbox->backend_readonly = TRUE;
fd = open(mailbox_get_path(&mbox->box), O_RDONLY);
}
if (mbox->mbox_file_stream != NULL) {
/* read-only mbox stream */
- i_assert(mbox->mbox_fd == -1 && mbox->box.backend_readonly);
+ i_assert(mbox->mbox_fd == -1 && mbox_is_backend_readonly(mbox));
} else {
if (mbox->mbox_fd == -1) {
if (mbox_file_open(mbox) < 0)
if (ibox->recent_flags_count > 0 &&
(mbox->box.flags & MAILBOX_FLAG_KEEP_RECENT) != 0 &&
- mbox->mbox_fd != -1 && !mbox->box.backend_readonly) {
+ mbox->mbox_fd != -1 && !mbox_is_backend_readonly(mbox)) {
/* we've seen recent messages which we want to keep recent.
keep file's atime lower than mtime so \Marked status
gets shown while listing */
if (mbox->mbox_file_stream != NULL) {
if (mbox->mbox_fd == -1) {
/* read-only mbox stream */
- i_assert(mbox->box.backend_readonly);
+ i_assert(mbox_is_backend_readonly(mbox));
i_stream_seek(mbox->mbox_file_stream, 0);
} else {
i_stream_destroy(&mbox->mbox_file_stream);
if (mbox->mbox_fd == -1 && mbox->mbox_file_stream != NULL) {
/* read-only mbox stream. no need to lock. */
- i_assert(mbox->box.backend_readonly);
+ i_assert(mbox_is_backend_readonly(mbox));
mbox->mbox_lock_type = lock_type;
return 1;
}
bool empty = FALSE;
int ret;
- if (ctx->mbox->box.backend_readonly) {
+ if (mbox_is_backend_readonly(ctx->mbox)) {
mail_storage_set_error(storage, MAIL_ERROR_PERM,
"Read-only mbox");
return -1;
const char *rootdir, *box_path = mailbox_get_path(box);
bool move_to_memory;
- if (access(box_path, R_OK|W_OK) < 0) {
- if (errno != EACCES) {
- mbox_set_syscall_error(mbox, "access()");
- return -1;
- }
- mbox->box.backend_readonly = TRUE;
- }
move_to_memory = want_memory_indexes(mbox->storage, box_path);
if (box->inbox_any || strcmp(box->name, "INBOX") == 0) {
return mbox_mailbox_open_finish(mbox, move_to_memory);
}
+static bool mbox_storage_is_readonly(struct mailbox *box)
+{
+ struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
+
+ if (index_storage_is_readonly(box))
+ return TRUE;
+
+ if (mbox_is_backend_readonly(mbox)) {
+ /* return read-only only if there are no private flags
+ (that are stored in index files) */
+ if (mailbox_get_private_flags_mask(box) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
static int mbox_mailbox_open(struct mailbox *box)
{
struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
if (box->input != NULL) {
i_stream_ref(box->input);
mbox->mbox_file_stream = box->input;
- mbox->box.backend_readonly = TRUE;
+ mbox->backend_readonly = TRUE;
+ mbox->backend_readonly_set = TRUE;
mbox->no_mbox_file = TRUE;
return mbox_mailbox_open_finish(mbox, FALSE);
}
if (box->view != NULL) {
hdr = mail_index_get_header(box->view);
if ((hdr->flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0 &&
- !mbox->box.backend_readonly) {
+ !mbox_is_backend_readonly(mbox)) {
/* we've done changes to mbox which haven't been
written yet. do it now. */
sync_flags |= MBOX_SYNC_REWRITE;
mbox_transaction_unlock(box, lock_id);
}
+bool mbox_is_backend_readonly(struct mbox_mailbox *mbox)
+{
+ if (!mbox->backend_readonly_set) {
+ mbox->backend_readonly_set = TRUE;
+ if (access(mailbox_get_path(&mbox->box), R_OK|W_OK) < 0 &&
+ errno == EACCES)
+ mbox->backend_readonly = TRUE;
+ }
+ return mbox->backend_readonly;
+}
+
struct mail_storage mbox_storage = {
.name = MBOX_STORAGE_NAME,
.class_flags = MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE |
struct mailbox mbox_mailbox = {
.v = {
- index_storage_is_readonly,
+ mbox_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
mbox_mailbox_open,
unsigned int mbox_used_privileges:1;
unsigned int mbox_privileged_locking:1;
unsigned int syncing:1;
+ unsigned int backend_readonly:1;
+ unsigned int backend_readonly_set:1;
};
struct mbox_transaction_context {
struct mail_index_transaction_commit_result *result);
void mbox_transaction_save_rollback(struct mail_save_context *ctx);
+bool mbox_is_backend_readonly(struct mbox_mailbox *mbox);
+
#endif
int ret, changed;
bool delay_writes, readonly;
- readonly = mbox->box.backend_readonly ||
+ readonly = mbox_is_backend_readonly(mbox) ||
(flags & MBOX_SYNC_READONLY) != 0;
delay_writes = readonly ||
((flags & MBOX_SYNC_REWRITE) == 0 &&
/* try as read-only */
if (mbox_lock(mbox, F_RDLCK, lock_id) <= 0)
return -1;
- mbox->box.backend_readonly = readonly = TRUE;
+ mbox->backend_readonly = readonly = TRUE;
+ mbox->backend_readonly_set = TRUE;
delay_writes = TRUE;
}
}
unsigned int opened:1;
/* Mailbox was deleted while we had it open. */
unsigned int mailbox_deleted:1;
- /* we've discovered there aren't enough permissions to modify mailbox */
- unsigned int backend_readonly:1;
/* Mailbox is being deleted */
unsigned int deleting:1;
/* Mailbox was already marked as deleted within this allocation. */
box->opened = FALSE;
box->mailbox_deleted = FALSE;
- box->backend_readonly = FALSE;
array_clear(&box->search_results);
}