static int fetch_mailbox_guid(struct fetch_cmd_context *ctx)
{
- uint8_t guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
- if (mailbox_get_guid(ctx->mail->box, guid) < 0)
+ if (mailbox_get_metadata(ctx->mail->box, MAILBOX_METADATA_GUID,
+ &metadata) < 0)
return -1;
- doveadm_print(mail_guid_128_to_string(guid));
+ doveadm_print(mail_guid_128_to_string(metadata.guid));
return 0;
}
#define ALL_STATUS_ITEMS \
(STATUS_MESSAGES | STATUS_RECENT | \
STATUS_UIDNEXT | STATUS_UIDVALIDITY | \
- STATUS_UNSEEN | STATUS_HIGHESTMODSEQ | STATUS_VIRTUAL_SIZE)
+ STATUS_UNSEEN | STATUS_HIGHESTMODSEQ)
+#define ALL_METADATA_ITEMS \
+ (MAILBOX_METADATA_VIRTUAL_SIZE | MAILBOX_METADATA_GUID)
#define TOTAL_STATUS_ITEMS \
- (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN | STATUS_VIRTUAL_SIZE)
+ (STATUS_MESSAGES | STATUS_RECENT | STATUS_UNSEEN)
+#define TOTAL_METADATA_ITEMS \
+ (MAILBOX_METADATA_VIRTUAL_SIZE)
struct status_cmd_context {
struct doveadm_mail_cmd_context ctx;
struct mail_search_args *search_args;
- enum mailbox_status_items items;
+
+ enum mailbox_status_items status_items;
+ enum mailbox_metadata_items metadata_items;
struct mailbox_status total_status;
+ struct mailbox_metadata total_metadata;
- unsigned int guid:1;
unsigned int total_sum:1;
};
const char *field = *fields;
if (strcmp(field, "all") == 0) {
- if (ctx->total_sum)
- ctx->items |= TOTAL_STATUS_ITEMS;
- else {
- ctx->items |= ALL_STATUS_ITEMS;
- ctx->guid = TRUE;
+ if (ctx->total_sum) {
+ ctx->status_items |= TOTAL_STATUS_ITEMS;
+ ctx->metadata_items |= TOTAL_METADATA_ITEMS;
+ } else {
+ ctx->status_items |= ALL_STATUS_ITEMS;
+ ctx->metadata_items |= ALL_METADATA_ITEMS;
}
} else if (strcmp(field, "messages") == 0)
- ctx->items |= STATUS_MESSAGES;
+ ctx->status_items |= STATUS_MESSAGES;
else if (strcmp(field, "recent") == 0)
- ctx->items |= STATUS_RECENT;
+ ctx->status_items |= STATUS_RECENT;
else if (strcmp(field, "uidnext") == 0)
- ctx->items |= STATUS_UIDNEXT;
+ ctx->status_items |= STATUS_UIDNEXT;
else if (strcmp(field, "uidvalidity") == 0)
- ctx->items |= STATUS_UIDVALIDITY;
+ ctx->status_items |= STATUS_UIDVALIDITY;
else if (strcmp(field, "unseen") == 0)
- ctx->items |= STATUS_UNSEEN;
+ ctx->status_items |= STATUS_UNSEEN;
else if (strcmp(field, "highestmodseq") == 0)
- ctx->items |= STATUS_HIGHESTMODSEQ;
+ ctx->status_items |= STATUS_HIGHESTMODSEQ;
else if (strcmp(field, "vsize") == 0)
- ctx->items |= STATUS_VIRTUAL_SIZE;
+ ctx->metadata_items |= MAILBOX_METADATA_VIRTUAL_SIZE;
else if (strcmp(field, "guid") == 0)
- ctx->guid = TRUE;
+ ctx->metadata_items |= MAILBOX_METADATA_GUID;
else
i_fatal("Unknown status field: %s", field);
if (ctx->total_sum &&
- ((ctx->items & ~TOTAL_STATUS_ITEMS) != 0 || ctx->guid))
+ ((ctx->status_items & ~TOTAL_STATUS_ITEMS) != 0 ||
+ (ctx->metadata_items & ~TOTAL_METADATA_ITEMS) != 0))
i_fatal("Status field %s can't be used with -t", field);
}
}
static void status_output(struct status_cmd_context *ctx, struct mailbox *box,
const struct mailbox_status *status,
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE])
+ const struct mailbox_metadata *metadata)
{
string_t *name;
doveadm_print(str_c(name));
}
- if ((ctx->items & STATUS_MESSAGES) != 0)
+ if ((ctx->status_items & STATUS_MESSAGES) != 0)
doveadm_print_num(status->messages);
- if ((ctx->items & STATUS_RECENT) != 0)
+ if ((ctx->status_items & STATUS_RECENT) != 0)
doveadm_print_num(status->recent);
- if ((ctx->items & STATUS_UIDNEXT) != 0)
+ if ((ctx->status_items & STATUS_UIDNEXT) != 0)
doveadm_print_num(status->uidnext);
- if ((ctx->items & STATUS_UIDVALIDITY) != 0)
+ if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
doveadm_print_num(status->uidvalidity);
- if ((ctx->items & STATUS_UNSEEN) != 0)
+ if ((ctx->status_items & STATUS_UNSEEN) != 0)
doveadm_print_num(status->unseen);
- if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0)
+ if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
doveadm_print_num(status->highest_modseq);
- if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0)
- doveadm_print_num(status->virtual_size);
- if (ctx->guid)
- doveadm_print(mail_guid_128_to_string(mailbox_guid));
+ if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
+ doveadm_print_num(metadata->virtual_size);
+ if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
+ doveadm_print(mail_guid_128_to_string(metadata->guid));
}
static void
status_sum(struct status_cmd_context *ctx,
- const struct mailbox_status *status)
+ const struct mailbox_status *status,
+ const struct mailbox_metadata *metadata)
{
struct mailbox_status *dest = &ctx->total_status;
dest->messages += status->messages;
dest->recent += status->recent;
dest->unseen += status->unseen;
- dest->virtual_size += status->virtual_size;
+ ctx->total_metadata.virtual_size += metadata->virtual_size;
}
static void
{
struct mailbox *box;
struct mailbox_status status;
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
string_t *mailbox_name = t_str_new(128);
if (imap_utf7_to_utf8(info->name, mailbox_name) < 0) {
str_append(mailbox_name, info->name);
}
- if (doveadm_mailbox_find_and_sync(ctx->ctx.cur_mail_user,
- str_c(mailbox_name), &box) < 0 ||
- mailbox_get_status(box, ctx->items, &status) < 0) {
+ box = doveadm_mailbox_find(ctx->ctx.cur_mail_user, str_c(mailbox_name));
+ if (mailbox_get_status(box, ctx->status_items, &status) < 0 ||
+ mailbox_get_metadata(box, ctx->metadata_items, &metadata) < 0) {
ctx->ctx.failed = TRUE;
+ mailbox_free(&box);
return;
}
- if (ctx->guid) {
- if (mailbox_get_guid(box, mailbox_guid) < 0)
- memset(mailbox_guid, 0, sizeof(mailbox_guid));
- }
if (!ctx->total_sum)
- status_output(ctx, box, &status, mailbox_guid);
+ status_output(ctx, box, &status, &metadata);
else
- status_sum(ctx, &status);
+ status_sum(ctx, &status, &metadata);
mailbox_free(&box);
}
}
doveadm_mail_list_iter_deinit(&iter);
- if (ctx->total_sum)
- status_output(ctx, NULL, &ctx->total_status, NULL);
+ if (ctx->total_sum) {
+ status_output(ctx, NULL, &ctx->total_status,
+ &ctx->total_metadata);
+ }
}
static void cmd_mailbox_status_init(struct doveadm_mail_cmd_context *_ctx,
doveadm_print_header("mailbox", "mailbox",
DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
}
- if ((ctx->items & STATUS_MESSAGES) != 0)
+ if ((ctx->status_items & STATUS_MESSAGES) != 0)
doveadm_print_header_simple("messages");
- if ((ctx->items & STATUS_RECENT) != 0)
+ if ((ctx->status_items & STATUS_RECENT) != 0)
doveadm_print_header_simple("recent");
- if ((ctx->items & STATUS_UIDNEXT) != 0)
+ if ((ctx->status_items & STATUS_UIDNEXT) != 0)
doveadm_print_header_simple("uidnext");
- if ((ctx->items & STATUS_UIDVALIDITY) != 0)
+ if ((ctx->status_items & STATUS_UIDVALIDITY) != 0)
doveadm_print_header_simple("uidvalidity");
- if ((ctx->items & STATUS_UNSEEN) != 0)
+ if ((ctx->status_items & STATUS_UNSEEN) != 0)
doveadm_print_header_simple("unseen");
- if ((ctx->items & STATUS_HIGHESTMODSEQ) != 0)
+ if ((ctx->status_items & STATUS_HIGHESTMODSEQ) != 0)
doveadm_print_header_simple("highestmodseq");
- if ((ctx->items & STATUS_VIRTUAL_SIZE) != 0)
+ if ((ctx->metadata_items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0)
doveadm_print_header_simple("vsize");
- if (ctx->guid)
+ if ((ctx->metadata_items & MAILBOX_METADATA_GUID) != 0)
doveadm_print_header_simple("guid");
}
struct doveadm_mail_iter *iter;
struct mailbox_transaction_context *trans;
struct mail *mail;
- uint8_t guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
const char *guid_str;
int ret = 0;
return -1;
mail = mail_alloc(trans, 0, NULL);
- if (mailbox_get_guid(mail->box, guid) < 0)
+
+ if (mailbox_get_metadata(mail->box, MAILBOX_METADATA_GUID,
+ &metadata) < 0)
ret = -1;
else {
- guid_str = mail_guid_128_to_string(guid);
+ guid_str = mail_guid_128_to_string(metadata.guid);
while (doveadm_mail_iter_next(iter, mail)) {
doveadm_print(guid_str);
T_BEGIN {
return ctx;
}
-static int mailbox_find_and_open(struct mail_user *user, const char *mailbox,
- struct mailbox **box_r)
+struct mailbox *
+doveadm_mailbox_find(struct mail_user *user, const char *mailbox)
{
struct mail_namespace *ns;
- struct mailbox *box;
string_t *str;
- const char *orig_mailbox = mailbox;
str = t_str_new(128);
if (imap_utf8_to_utf7(mailbox, str) < 0)
if (ns == NULL)
i_fatal("Can't find namespace for mailbox %s", mailbox);
- box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
- MAILBOX_FLAG_IGNORE_ACLS);
+ return mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_KEEP_RECENT |
+ MAILBOX_FLAG_IGNORE_ACLS);
+}
+
+static int
+doveadm_mailbox_find_and_open(struct mail_user *user, const char *mailbox,
+ struct mailbox **box_r)
+{
+ struct mailbox *box;
+
+ box = doveadm_mailbox_find(user, mailbox);
if (mailbox_open(box) < 0) {
- i_error("Opening mailbox %s failed: %s", orig_mailbox,
+ i_error("Opening mailbox %s failed: %s", mailbox,
mail_storage_get_last_error(mailbox_get_storage(box),
NULL));
mailbox_free(&box);
int doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
struct mailbox **box_r)
{
- if (mailbox_find_and_open(user, mailbox, box_r) < 0)
+ if (doveadm_mailbox_find_and_open(user, mailbox, box_r) < 0)
return -1;
if (mailbox_sync(*box_r, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
i_error("Syncing mailbox %s failed: %s", mailbox,
mail_storage_get_last_error(mailbox_get_storage(*box_r),
NULL));
+ mailbox_free(box_r);
return -1;
}
return 0;
struct mail_storage *storage;
struct mailbox *box;
- if (mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
+ if (doveadm_mailbox_find_and_open(user, ctx->mailbox, &box) < 0) {
_ctx->failed = TRUE;
return;
}
const char **error_r);
void doveadm_mail_server_flush(void);
+struct mailbox *
+doveadm_mailbox_find(struct mail_user *user, const char *mailbox);
int doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox,
struct mailbox **box_r);
struct mail_search_args *
MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
const enum mailbox_status_items status_items =
STATUS_UIDNEXT | STATUS_UIDVALIDITY |
- STATUS_HIGHESTMODSEQ | STATUS_CACHE_FIELDS;
+ STATUS_HIGHESTMODSEQ;
+ const enum mailbox_metadata_items metadata_items =
+ MAILBOX_METADATA_CACHE_FIELDS | MAILBOX_METADATA_GUID;
const struct mailbox_info *info;
const char *storage_name;
struct mailbox *box;
struct mailbox_status status;
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
struct local_dsync_mailbox_change *change;
struct local_dsync_dir_change *dir_change, change_lookup;
struct local_dsync_mailbox *old_lbox;
}
box = mailbox_alloc(info->ns->list, storage_name, flags);
- if (mailbox_sync(box, 0) < 0 ||
- mailbox_get_status(box, status_items, &status) < 0 ||
- mailbox_get_guid(box, mailbox_guid) < 0) {
+ if (mailbox_get_status(box, status_items, &status) < 0 ||
+ mailbox_get_metadata(box, metadata_items, &metadata) < 0) {
struct mail_storage *storage = mailbox_get_storage(box);
i_error("Failed to sync mailbox %s: %s", info->name,
return -1;
}
- change = hash_table_lookup(worker->mailbox_changes_hash, mailbox_guid);
+ change = hash_table_lookup(worker->mailbox_changes_hash, metadata.guid);
if (change != NULL) {
/* it shouldn't be marked as deleted, but drop it to be sure */
change->deleted_mailbox = FALSE;
}
- memcpy(dsync_box_r->mailbox_guid.guid, mailbox_guid,
+ memcpy(dsync_box_r->mailbox_guid.guid, metadata.guid,
sizeof(dsync_box_r->mailbox_guid.guid));
dsync_box_r->uid_validity = status.uidvalidity;
dsync_box_r->uid_next = status.uidnext;
dsync_box_r->highest_modseq = status.highest_modseq;
p_clear(iter->ret_pool);
- fields = array_get(status.cache_fields, &field_count);
+ fields = array_get(metadata.cache_fields, &field_count);
p_array_init(&dsync_box_r->cache_fields, iter->ret_pool, field_count);
for (i = 0; i < field_count; i++) {
const char *field_name = p_strdup(iter->ret_pool, fields[i]);
enum mailbox_flags flags = MAILBOX_FLAG_KEEP_RECENT;
struct local_dsync_mailbox *lbox;
struct mailbox *box;
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
lbox = hash_table_lookup(worker->mailbox_hash, guid);
if (lbox == NULL) {
box = mailbox_alloc(lbox->ns->list, lbox->storage_name, flags);
if (mailbox_sync(box, 0) < 0 ||
- mailbox_get_guid(box, mailbox_guid) < 0) {
+ mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
struct mail_storage *storage = mailbox_get_storage(box);
i_error("Failed to sync mailbox %s: %s", lbox->storage_name,
return -1;
}
- if (memcmp(mailbox_guid, guid->guid, sizeof(guid->guid)) != 0) {
+ if (memcmp(metadata.guid, guid->guid, sizeof(guid->guid)) != 0) {
i_error("Mailbox %s changed its GUID (%s -> %s)",
lbox->storage_name, dsync_guid_to_str(guid),
- mail_guid_128_to_string(mailbox_guid));
+ mail_guid_128_to_string(metadata.guid));
mailbox_free(&box);
return -1;
}
array_clear(&iter->expunges);
iter->expunges_set = TRUE;
- if (mailbox_get_status(box, STATUS_UIDNEXT, &status) < 0)
- i_unreached();
+ mailbox_get_open_status(box, STATUS_UIDNEXT, &status);
if (prev_uid + 1 >= status.uidnext) {
/* no expunged messages at the end of mailbox */
return FALSE;
}
str = t_str_ucase(str);
if (strcmp(str, "CONDSTORE") == 0) {
- client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
- str_append(reply, " CONDSTORE");
- }
- else if (strcmp(str, "QRESYNC") == 0) {
- client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
- MAILBOX_FEATURE_CONDSTORE);
- str_append(reply, " QRESYNC");
+ if (client_enable(cmd->client,
+ MAILBOX_FEATURE_CONDSTORE) == 0)
+ str_append(reply, " CONDSTORE");
+ } else if (strcmp(str, "QRESYNC") == 0) {
+ if (client_enable(cmd->client, MAILBOX_FEATURE_QRESYNC |
+ MAILBOX_FEATURE_CONDSTORE) == 0)
+ str_append(reply, " QRESYNC");
}
}
if (str_len(reply) > 9)
struct client *client = ctx->cmd->client;
struct mailbox_status status;
enum mailbox_flags flags = 0;
- int ret;
+ int ret = 0;
if (readonly)
flags |= MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT;
}
if (client->enabled_features != 0)
- mailbox_enable(ctx->box, client->enabled_features);
- if (mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
- client_send_storage_error(ctx->cmd,
- mailbox_get_storage(ctx->box));
- return -1;
- }
- if (mailbox_get_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
- STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
- STATUS_UIDNEXT | STATUS_KEYWORDS |
- STATUS_HIGHESTMODSEQ, &status) < 0) {
+ ret = mailbox_enable(ctx->box, client->enabled_features);
+ if (ret < 0 ||
+ mailbox_sync(ctx->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
client_send_storage_error(ctx->cmd,
mailbox_get_storage(ctx->box));
return -1;
}
+ mailbox_get_open_status(ctx->box, STATUS_MESSAGES | STATUS_RECENT |
+ STATUS_FIRST_UNSEEN_SEQ | STATUS_UIDVALIDITY |
+ STATUS_UIDNEXT | STATUS_KEYWORDS |
+ STATUS_HIGHESTMODSEQ, &status);
client->mailbox = ctx->box;
client->select_counter++;
if (ctx->condstore) {
/* Enable while no mailbox is opened to avoid sending
HIGHESTMODSEQ for previously opened mailbox */
- client_enable(client, MAILBOX_FEATURE_CONDSTORE);
+ (void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
}
ret = select_open(ctx, storage_name, readonly);
"Invalid modseq");
return FALSE;
}
- client_enable(ctx->cmd->client,
- MAILBOX_FEATURE_CONDSTORE);
+ (void)client_enable(ctx->cmd->client,
+ MAILBOX_FEATURE_CONDSTORE);
} else {
client_send_command_error(ctx->cmd,
"Unknown STORE modifier");
return TRUE;
}
-void client_enable(struct client *client, enum mailbox_feature features)
+int client_enable(struct client *client, enum mailbox_feature features)
{
struct mailbox_status status;
+ int ret;
if ((client->enabled_features & features) == features)
- return;
+ return 0;
client->enabled_features |= features;
if (client->mailbox == NULL)
- return;
+ return 0;
- mailbox_enable(client->mailbox, features);
- if ((features & MAILBOX_FEATURE_CONDSTORE) != 0) {
+ ret = mailbox_enable(client->mailbox, features);
+ if ((features & MAILBOX_FEATURE_CONDSTORE) != 0 && ret == 0) {
/* CONDSTORE being enabled while mailbox is selected.
Notify client of the latest HIGHESTMODSEQ. */
- if (mailbox_get_status(client->mailbox,
- STATUS_HIGHESTMODSEQ, &status) < 0)
- i_unreached();
- client_send_line(client, t_strdup_printf(
- "* OK [HIGHESTMODSEQ %llu] Highest",
- (unsigned long long)status.highest_modseq));
+ ret = mailbox_get_status(client->mailbox,
+ STATUS_HIGHESTMODSEQ, &status);
+ if (ret == 0) {
+ client_send_line(client, t_strdup_printf(
+ "* OK [HIGHESTMODSEQ %llu] Highest",
+ (unsigned long long)status.highest_modseq));
+ }
+ }
+ if (ret < 0) {
+ client_send_untagged_storage_error(client,
+ mailbox_get_storage(client->mailbox));
}
+ return ret;
}
struct imap_search_update *
have to wait for an existing SEARCH SAVE to finish. */
bool client_handle_search_save_ambiguity(struct client_command_context *cmd);
-void client_enable(struct client *client, enum mailbox_feature features);
+int client_enable(struct client *client, enum mailbox_feature features);
struct imap_search_update *
client_search_update_lookup(struct client *client, const char *tag,
mailbox_free(&box);
return -1;
}
- if (cmd->client->enabled_features != 0)
- mailbox_enable(box, cmd->client->enabled_features);
+ if (cmd->client->enabled_features != 0) {
+ if (mailbox_enable(box, cmd->client->enabled_features) < 0) {
+ client_send_storage_error(cmd, mailbox_get_storage(box));
+ mailbox_free(&box);
+ return -1;
+ }
+ }
*destbox_r = box;
return 0;
}
i_assert(array_count(ctx->qresync_sample_uidset) == count);
i_assert(count > 0);
- mailbox_get_status(ctx->box, STATUS_MESSAGES, &status);
+ mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
/* FIXME: we could do removals from the middle as well */
for (i = 0; i < count && seqs[i] <= status.messages; i++) {
uid_filter[i].seq2);
}
- mailbox_get_status(ctx->box, STATUS_UIDNEXT, &status);
+ mailbox_get_open_status(ctx->box, STATUS_UIDNEXT, &status);
seq_range_array_remove_range(expunged_uids, status.uidnext,
(uint32_t)-1);
fetch_modseq_init(struct imap_fetch_context *ctx, const char *name,
const struct imap_arg **args ATTR_UNUSED)
{
- client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
+ (void)client_enable(ctx->client, MAILBOX_FEATURE_CONDSTORE);
imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL,
fetch_modseq, NULL);
return TRUE;
if (ctx->have_modseqs) {
ctx->return_options |= SEARCH_RETURN_MODSEQ;
- client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
+ (void)client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
}
ctx->box = cmd->client->mailbox;
struct imap_status_items *items_r)
{
const char *item;
- enum mailbox_status_items items;
+ enum mailbox_status_items status = 0;
+ enum mailbox_metadata_items metadata = 0;
if (IMAP_ARG_IS_EOL(args)) {
client_send_command_error(cmd, "Empty status list.");
}
memset(items_r, 0, sizeof(*items_r));
- items = 0;
for (; !IMAP_ARG_IS_EOL(args); args++) {
if (!imap_arg_get_atom(args, &item)) {
/* list may contain only atoms */
item = t_str_ucase(item);
if (strcmp(item, "MESSAGES") == 0)
- items |= STATUS_MESSAGES;
+ status |= STATUS_MESSAGES;
else if (strcmp(item, "RECENT") == 0)
- items |= STATUS_RECENT;
+ status |= STATUS_RECENT;
else if (strcmp(item, "UIDNEXT") == 0)
- items |= STATUS_UIDNEXT;
+ status |= STATUS_UIDNEXT;
else if (strcmp(item, "UIDVALIDITY") == 0)
- items |= STATUS_UIDVALIDITY;
+ status |= STATUS_UIDVALIDITY;
else if (strcmp(item, "UNSEEN") == 0)
- items |= STATUS_UNSEEN;
+ status |= STATUS_UNSEEN;
else if (strcmp(item, "HIGHESTMODSEQ") == 0)
- items |= STATUS_HIGHESTMODSEQ;
+ status |= STATUS_HIGHESTMODSEQ;
else if (strcmp(item, "X-SIZE") == 0)
- items |= STATUS_VIRTUAL_SIZE;
+ metadata |= MAILBOX_METADATA_VIRTUAL_SIZE;
else if (strcmp(item, "X-GUID") == 0)
- items_r->guid = TRUE;
+ metadata |= MAILBOX_METADATA_GUID;
else {
client_send_tagline(cmd, t_strconcat(
"BAD Invalid status item ", item, NULL));
}
}
- items_r->mailbox_items = items;
+ items_r->status = status;
+ items_r->metadata = metadata;
return 0;
}
box = mailbox_alloc(ns->list, mailbox,
MAILBOX_FLAG_READONLY |
MAILBOX_FLAG_KEEP_RECENT);
- if (client->enabled_features != 0)
- mailbox_enable(box, client->enabled_features);
+ if (client->enabled_features != 0) {
+ if (mailbox_enable(box, client->enabled_features) < 0)
+ ret = -1;
+ }
}
- if ((items->mailbox_items & STATUS_HIGHESTMODSEQ) != 0)
- client_enable(client, MAILBOX_FEATURE_CONDSTORE);
+ if ((items->status & STATUS_HIGHESTMODSEQ) != 0)
+ (void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
- ret = mailbox_get_status(box, items->mailbox_items, &result_r->status);
- if (items->guid && ret == 0)
- ret = mailbox_get_guid(box, result_r->mailbox_guid);
+ ret = mailbox_get_status(box, items->status, &result_r->status);
+ if (items->metadata != 0 && ret == 0) {
+ ret = mailbox_get_metadata(box, items->metadata,
+ &result_r->metadata);
+ }
if (ret < 0) {
struct mail_storage *storage = mailbox_get_storage(box);
str_append(str, " (");
prefix_len = str_len(str);
- if ((items->mailbox_items & STATUS_MESSAGES) != 0)
+ if ((items->status & STATUS_MESSAGES) != 0)
str_printfa(str, "MESSAGES %u ", status->messages);
- if ((items->mailbox_items & STATUS_RECENT) != 0)
+ if ((items->status & STATUS_RECENT) != 0)
str_printfa(str, "RECENT %u ", status->recent);
- if ((items->mailbox_items & STATUS_UIDNEXT) != 0)
+ if ((items->status & STATUS_UIDNEXT) != 0)
str_printfa(str, "UIDNEXT %u ", status->uidnext);
- if ((items->mailbox_items & STATUS_UIDVALIDITY) != 0)
+ if ((items->status & STATUS_UIDVALIDITY) != 0)
str_printfa(str, "UIDVALIDITY %u ", status->uidvalidity);
- if ((items->mailbox_items & STATUS_UNSEEN) != 0)
+ if ((items->status & STATUS_UNSEEN) != 0)
str_printfa(str, "UNSEEN %u ", status->unseen);
- if ((items->mailbox_items & STATUS_HIGHESTMODSEQ) != 0) {
+ if ((items->status & STATUS_HIGHESTMODSEQ) != 0) {
str_printfa(str, "HIGHESTMODSEQ %llu ",
(unsigned long long)status->highest_modseq);
}
- if ((items->mailbox_items & STATUS_VIRTUAL_SIZE) != 0) {
+ if ((items->metadata & MAILBOX_METADATA_VIRTUAL_SIZE) != 0) {
str_printfa(str, "X-SIZE %llu ",
- (unsigned long long)status->virtual_size);
+ (unsigned long long)result->metadata.virtual_size);
}
- if (items->guid) {
+ if ((items->metadata & MAILBOX_METADATA_GUID) != 0) {
str_printfa(str, "X-GUID %s ",
- mail_guid_128_to_string(result->mailbox_guid));
+ mail_guid_128_to_string(result->metadata.guid));
}
if (str_len(str) != prefix_len)
#define IMAP_STATUS_H
struct imap_status_items {
- enum mailbox_status_items mailbox_items;
-
- unsigned int guid:1;
+ enum mailbox_status_items status;
+ enum mailbox_metadata_items metadata;
};
struct imap_status_result {
struct mailbox_status status;
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
};
int imap_status_parse_items(struct client_command_context *cmd,
int imap_sync_deinit(struct imap_sync_context *ctx,
struct client_command_context *sync_cmd)
{
- const enum mailbox_status_items status_items =
- STATUS_UIDVALIDITY | STATUS_MESSAGES | STATUS_RECENT |
- STATUS_HIGHESTMODSEQ;
struct client *client = ctx->client;
struct mailbox_status status;
struct mailbox_sync_status sync_status;
array_free(&ctx->expunges);
if (mailbox_sync_deinit(&ctx->sync_ctx, &sync_status) < 0 ||
- mailbox_get_status(ctx->box, status_items, &status) < 0 ||
ctx->failed) {
mailbox_transaction_rollback(&ctx->t);
array_free(&ctx->tmp_keywords);
i_free(ctx);
return -1;
}
+ mailbox_get_open_status(ctx->box, STATUS_UIDVALIDITY |
+ STATUS_MESSAGES | STATUS_RECENT |
+ STATUS_HIGHESTMODSEQ, &status);
ret = mailbox_transaction_commit(&ctx->t);
}
static int
-mdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+mdbox_mailbox_get_guid(struct mdbox_mailbox *mbox,
+ uint8_t guid[MAIL_GUID_128_SIZE])
{
- struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
struct mdbox_index_header hdr;
if (mdbox_read_header(mbox, &hdr) < 0)
if (mail_guid_128_is_empty(hdr.mailbox_guid)) {
/* regenerate it */
- if (mdbox_write_index_header(box, NULL, NULL) < 0 ||
+ if (mdbox_write_index_header(&mbox->box, NULL, NULL) < 0 ||
mdbox_read_header(mbox, &hdr) < 0)
return -1;
}
return 0;
}
+static int
+mdbox_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
+{
+ struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
+
+ if ((items & MAILBOX_METADATA_GUID) != 0) {
+ if (mdbox_mailbox_get_guid(mbox, metadata_r->guid) < 0)
+ return -1;
+ }
+ return index_mailbox_get_metadata(box, items, metadata_r);
+}
+
static int
mdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
{
mdbox_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
- mdbox_mailbox_get_guid,
+ mdbox_mailbox_get_metadata,
NULL,
NULL,
mdbox_storage_sync_init,
}
static int
-sdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+sdbox_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
{
struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
- memcpy(guid, mbox->mailbox_guid, MAIL_GUID_128_SIZE);
- return 0;
+ if ((items & MAILBOX_METADATA_GUID) != 0) {
+ memcpy(metadata_r->guid, mbox->mailbox_guid,
+ MAIL_GUID_128_SIZE);
+ }
+ return index_mailbox_get_metadata(box, items, metadata_r);
}
static int
sdbox_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
- sdbox_mailbox_get_guid,
+ sdbox_mailbox_get_metadata,
NULL,
NULL,
sdbox_storage_sync_init,
static void search_init_arg(struct mail_search_arg *arg,
struct index_search_context *ctx)
{
- uint8_t guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
bool match;
switch (arg->type) {
ctx->have_index_args = TRUE;
break;
case SEARCH_MAILBOX_GUID:
- if (mailbox_get_guid(ctx->box, guid) < 0) {
+ if (mailbox_get_metadata(ctx->box, MAILBOX_METADATA_GUID,
+ &metadata) < 0) {
/* result will be unknown */
break;
}
- match = strcmp(mail_guid_128_to_string(guid),
+ match = strcmp(mail_guid_128_to_string(metadata.guid),
arg->value.str) == 0;
if (match != arg->not)
arg->match_always = TRUE;
if (gettimeofday(&ctx->last_nonblock_timeval, NULL) < 0)
i_fatal("gettimeofday() failed: %m");
- mailbox_get_status(t->box, STATUS_MESSAGES, &status);
+ mailbox_get_open_status(t->box, STATUS_MESSAGES, &status);
ctx->mail_ctx.progress_max = status.messages;
i_array_init(&ctx->mail_ctx.results, 5);
#include "index-storage.h"
#include "mail-index-modseq.h"
+int index_storage_get_status(struct mailbox *box,
+ enum mailbox_status_items items,
+ struct mailbox_status *status_r)
+{
+ const struct mail_index_header *hdr;
+
+ memset(status_r, 0, sizeof(struct mailbox_status));
+
+ if (!box->opened) {
+ if (mailbox_open(box) < 0)
+ return -1;
+ if (mailbox_sync(box, 0) < 0)
+ return -1;
+ }
+
+ /* we can get most of the status items without any trouble */
+ hdr = mail_index_get_header(box->view);
+ status_r->messages = hdr->messages_count;
+ if ((items & STATUS_RECENT) != 0) {
+ status_r->recent = index_mailbox_get_recent_count(box);
+ i_assert(status_r->recent <= status_r->messages);
+ }
+ status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
+ status_r->uidvalidity = hdr->uid_validity;
+ status_r->uidnext = hdr->next_uid;
+ status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
+ if ((items & STATUS_HIGHESTMODSEQ) != 0) {
+ status_r->highest_modseq =
+ mail_index_modseq_get_highest(box->view);
+ if (status_r->highest_modseq == 0) {
+ /* modseqs not enabled yet, but we can't return 0 */
+ status_r->highest_modseq = 1;
+ }
+ }
+
+ if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
+ mail_index_lookup_first(box->view, 0, MAIL_SEEN,
+ &status_r->first_unseen_seq);
+ }
+
+ if ((items & STATUS_KEYWORDS) != 0)
+ status_r->keywords = mail_index_get_keywords(box->index);
+ return 0;
+}
+
static void
-index_storage_get_status_cache_fields(struct mailbox *box,
- struct mailbox_status *status_r)
+get_metadata_cache_fields(struct mailbox *box,
+ struct mailbox_metadata *metadata_r)
{
const struct mail_cache_field *fields;
enum mail_cache_decision_type dec;
if (dec != MAIL_CACHE_DECISION_NO)
array_append(cache_fields, &fields[i].name, 1);
}
- status_r->cache_fields = cache_fields;
+ metadata_r->cache_fields = cache_fields;
}
static int
-index_storage_virtual_size_add_new(struct mailbox *box,
- struct index_vsize_header *vsize_hdr)
+virtual_size_add_new(struct mailbox *box,
+ struct index_vsize_header *vsize_hdr)
{
struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
const struct mail_index_header *hdr;
}
static int
-index_storage_get_status_virtual_size(struct mailbox *box,
- struct mailbox_status *status_r)
+get_metadata_virtual_size(struct mailbox *box,
+ struct mailbox_metadata *metadata_r)
{
struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
struct index_vsize_header vsize_hdr;
+ struct mailbox_status status;
const void *data;
size_t size;
int ret;
+ mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_UIDNEXT, &status);
mail_index_get_header_ext(box->view, ibox->vsize_hdr_ext_id,
&data, &size);
if (size == sizeof(vsize_hdr))
memset(&vsize_hdr, 0, sizeof(vsize_hdr));
}
- if (vsize_hdr.highest_uid + 1 == status_r->uidnext &&
- vsize_hdr.message_count == status_r->messages) {
+ if (vsize_hdr.highest_uid + 1 == status.uidnext &&
+ vsize_hdr.message_count == status.messages) {
/* up to date */
- status_r->virtual_size = vsize_hdr.vsize;
+ metadata_r->virtual_size = vsize_hdr.vsize;
return 0;
}
- if (vsize_hdr.highest_uid >= status_r->uidnext) {
+ if (vsize_hdr.highest_uid >= status.uidnext) {
mail_storage_set_critical(box->storage,
"vsize-hdr has invalid highest-uid (%u >= %u)",
- vsize_hdr.highest_uid, status_r->uidnext);
+ vsize_hdr.highest_uid, status.uidnext);
memset(&vsize_hdr, 0, sizeof(vsize_hdr));
}
- ret = index_storage_virtual_size_add_new(box, &vsize_hdr);
- status_r->virtual_size = vsize_hdr.vsize;
+ ret = virtual_size_add_new(box, &vsize_hdr);
+ metadata_r->virtual_size = vsize_hdr.vsize;
return ret;
}
-int index_storage_get_status(struct mailbox *box,
- enum mailbox_status_items items,
- struct mailbox_status *status_r)
+int index_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
{
- const struct mail_index_header *hdr;
- int ret = 0;
-
- memset(status_r, 0, sizeof(struct mailbox_status));
-
- if (!box->opened) {
- if (mailbox_open(box) < 0)
- return -1;
- if (mailbox_sync(box, 0) < 0)
+ if ((items & MAILBOX_METADATA_CACHE_FIELDS) != 0)
+ get_metadata_cache_fields(box, metadata_r);
+ if ((items & MAILBOX_METADATA_VIRTUAL_SIZE) != 0) {
+ if (get_metadata_virtual_size(box, metadata_r) < 0)
return -1;
}
-
- /* we can get most of the status items without any trouble */
- hdr = mail_index_get_header(box->view);
- status_r->messages = hdr->messages_count;
- if ((items & STATUS_RECENT) != 0) {
- status_r->recent = index_mailbox_get_recent_count(box);
- i_assert(status_r->recent <= status_r->messages);
- }
- status_r->unseen = hdr->messages_count - hdr->seen_messages_count;
- status_r->uidvalidity = hdr->uid_validity;
- status_r->uidnext = hdr->next_uid;
- status_r->nonpermanent_modseqs = mail_index_is_in_memory(box->index);
- if ((items & STATUS_HIGHESTMODSEQ) != 0) {
- status_r->highest_modseq =
- mail_index_modseq_get_highest(box->view);
- if (status_r->highest_modseq == 0) {
- /* modseqs not enabled yet, but we can't return 0 */
- status_r->highest_modseq = 1;
- }
- }
-
- if ((items & STATUS_FIRST_UNSEEN_SEQ) != 0) {
- mail_index_lookup_first(box->view, 0, MAIL_SEEN,
- &status_r->first_unseen_seq);
- }
-
- if ((items & STATUS_KEYWORDS) != 0)
- status_r->keywords = mail_index_get_keywords(box->index);
- if ((items & STATUS_CACHE_FIELDS) != 0)
- index_storage_get_status_cache_fields(box, status_r);
- if ((items & STATUS_VIRTUAL_SIZE) != 0) {
- if (index_storage_get_status_virtual_size(box, status_r) < 0)
- ret = -1;
- }
- return ret;
+ return 0;
}
int index_storage_mailbox_delete(struct mailbox *box)
{
- uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
+ struct mailbox_metadata metadata;
if (!box->opened) {
/* \noselect mailbox, try deleting only the directory */
if (mailbox_mark_index_deleted(box, TRUE) < 0)
return -1;
- if (mailbox_get_guid(box, mailbox_guid) < 0)
+ if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
return -1;
/* Make sure the indexes are closed before trying to delete the
}
mailbox_list_add_change(box->list, MAILBOX_LOG_RECORD_DELETE_MAILBOX,
- mailbox_guid);
+ metadata.guid);
return index_storage_mailbox_delete_dir(box, TRUE);
}
struct mail *src_mail, uint32_t dest_seq)
{
T_BEGIN {
- struct mailbox_status src_status;
+ struct mailbox_metadata src_metadata;
const char *const *namep;
buffer_t *buf;
- index_storage_get_status(src_mail->box, STATUS_CACHE_FIELDS,
- &src_status);
+ if (mailbox_get_metadata(src_mail->box,
+ MAILBOX_METADATA_CACHE_FIELDS,
+ &src_metadata) < 0)
+ i_unreached();
buf = buffer_create_dynamic(pool_datastack_create(), 1024);
- array_foreach(src_status.cache_fields, namep) {
+ array_foreach(src_metadata.cache_fields, namep) {
mail_copy_cache_field(ctx, src_mail, dest_seq,
*namep, buf);
}
int index_storage_get_status(struct mailbox *box,
enum mailbox_status_items items,
struct mailbox_status *status_r);
+int index_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r);
struct mail_search_context *
index_storage_search_init(struct mailbox_transaction_context *t,
}
static int
-maildir_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+maildir_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
{
struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
- return maildir_uidlist_get_mailbox_guid(mbox->uidlist, guid);
+ if ((items & MAILBOX_METADATA_GUID) != 0) {
+ if (maildir_uidlist_get_mailbox_guid(mbox->uidlist,
+ metadata_r->guid) < 0)
+ return -1;
+ }
+ return index_mailbox_get_metadata(box, items, metadata_r);
}
static void maildir_mailbox_close(struct mailbox *box)
index_storage_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
- maildir_mailbox_get_guid,
+ maildir_mailbox_get_metadata,
maildir_list_index_has_changed,
maildir_list_index_update_sync,
maildir_storage_sync_init,
}
static int
-mbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+mbox_mailbox_get_guid(struct mbox_mailbox *mbox,
+ uint8_t guid[MAIL_GUID_128_SIZE])
{
- struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
-
- if (mail_index_is_in_memory(box->index)) {
- mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+ if (mail_index_is_in_memory(mbox->box.index)) {
+ mail_storage_set_error(mbox->box.storage, MAIL_ERROR_NOTPOSSIBLE,
"Mailbox GUIDs are not permanent without index files");
return -1;
}
return 0;
}
+static int
+mbox_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
+{
+ struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
+
+ if ((items & MAILBOX_METADATA_GUID) != 0) {
+ if (mbox_mailbox_get_guid(mbox, metadata_r->guid) < 0)
+ return -1;
+ }
+ return index_mailbox_get_metadata(box, items, metadata_r);
+}
+
static void mbox_notify_changes(struct mailbox *box)
{
struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
index_storage_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
- mbox_mailbox_get_guid,
+ mbox_mailbox_get_metadata,
NULL,
NULL,
mbox_storage_sync_init,
view = mail_index_view_open(ilist->mail_index);
if (mail_index_lookup_seq(view, uid, &seq)) {
- mailbox_get_status(box, CACHED_STATUS_ITEMS, &status);
+ mailbox_get_open_status(box, CACHED_STATUS_ITEMS, &status);
(void)index_list_update(ilist, box, view, seq, &status);
}
mail_index_view_close(&view);
int (*get_status)(struct mailbox *box, enum mailbox_status_items items,
struct mailbox_status *status_r);
- int (*get_guid)(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE]);
+ int (*get_metadata)(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r);
/* Lookup sync extension record and figure out if it mailbox has
changed since. Returns 1 = yes, 0 = no, -1 = error. */
return box->v.get_status(box, items, status_r);
}
-int mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
+void mailbox_get_open_status(struct mailbox *box,
+ enum mailbox_status_items items,
+ struct mailbox_status *status_r)
+{
+ i_assert(box->opened);
+ if (box->v.get_status(box, items, status_r) < 0)
+ i_unreached();
+}
+
+int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
{
- if (box->v.get_guid == NULL) {
- mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
- "Storage doesn't support mailbox GUIDs");
- return -1;
- }
if (!box->opened) {
if (mailbox_open(box) < 0)
return -1;
}
- if (box->v.get_guid(box, guid) < 0)
+ if (box->v.get_metadata(box, items, metadata_r) < 0)
return -1;
- i_assert(!mail_guid_128_is_empty(guid));
+ i_assert((items & MAILBOX_METADATA_GUID) == 0 ||
+ !mail_guid_128_is_empty(metadata_r->guid));
return 0;
}
STATUS_UNSEEN = 0x10,
STATUS_FIRST_UNSEEN_SEQ = 0x20,
STATUS_KEYWORDS = 0x40,
- STATUS_HIGHESTMODSEQ = 0x80,
- STATUS_CACHE_FIELDS = 0x100,
- STATUS_VIRTUAL_SIZE = 0x200
+ STATUS_HIGHESTMODSEQ = 0x80
+};
+
+enum mailbox_metadata_items {
+ MAILBOX_METADATA_GUID = 0x01,
+ MAILBOX_METADATA_VIRTUAL_SIZE = 0x02,
+ MAILBOX_METADATA_CACHE_FIELDS = 0x04
};
enum mailbox_search_result_flags {
uint32_t first_unseen_seq;
uint64_t highest_modseq;
- /* sum of virtual size of all messages in mailbox */
- uint64_t virtual_size;
const ARRAY_TYPE(keywords) *keywords;
- /* Fields that have "temp" or "yes" caching decision. */
- const ARRAY_TYPE(const_string) *cache_fields;
/* Modseqs aren't permanent (index is in memory) */
unsigned int nonpermanent_modseqs:1;
};
+struct mailbox_metadata {
+ uint8_t guid[MAIL_GUID_128_SIZE];
+ /* sum of virtual size of all messages in mailbox */
+ uint64_t virtual_size;
+ /* Fields that have "temp" or "yes" caching decision. */
+ const ARRAY_TYPE(const_string) *cache_fields;
+};
+
struct mailbox_update {
/* All non-zero fields are changed. */
uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
do forced CLOSE. */
bool mailbox_is_inconsistent(struct mailbox *box);
-/* Gets the mailbox status information. */
+/* Gets the mailbox status information, opening the mailbox if necessary. */
int mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
struct mailbox_status *status_r);
-/* Get mailbox GUID, creating it if necessary. */
-int mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE]);
+/* Gets the mailbox status, requires that mailbox is already opened. */
+void mailbox_get_open_status(struct mailbox *box,
+ enum mailbox_status_items items,
+ struct mailbox_status *status_r);
+/* Gets mailbox metadata */
+int mailbox_get_metadata(struct mailbox *box, enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r);
/* Returns a mask of flags that are private to user in this mailbox
(as opposed to flags shared between users). */
enum mail_flags mailbox_get_private_flags_mask(struct mailbox *box);
box_name = fts_box_get_root(box, &ns);
- mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
str_printfa(str, "uidv:%u+box:", status.uidvalidity);
solr_quote_http(str, box_name);
solr_add_ns_query_http(str, backend, ns);
box_name = fts_box_get_root(box, &ns);
- mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
str_printfa(str, "uidv:%u+box:", status.uidvalidity);
solr_quote_http(str, box_name);
solr_add_ns_query_http(str, backend, ns);
ctx->ctx.backend = backend;
ctx->cmd = str_new(default_pool, SOLR_CMDBUF_SIZE);
- mailbox_get_status(backend->box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(backend->box, STATUS_UIDVALIDITY, &status);
ctx->uid_validity = status.uidvalidity;
*ctx_r = &ctx->ctx;
{
struct mailbox_status status;
- mailbox_get_status(mail->box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(mail->box, STATUS_UIDVALIDITY, &status);
T_BEGIN {
string_t *cmd;
bool virtual;
virtual = strcmp(box->storage->name, "virtual") == 0;
- mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
str = t_str_new(256);
if (!virtual) {
return NULL;
}
- mailbox_get_status(box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(box, STATUS_UIDVALIDITY, &status);
if (storage->set->mmap_disable)
flags |= SQUAT_INDEX_FLAG_MMAP_DISABLE;
if (storage->set->mail_nfs_index)
ret = strcmp(vname, last_uids[uidi].mailbox);
if (ret == 0) {
/* match. check also that uidvalidity matches. */
- mailbox_get_status(boxes[boxi].box, STATUS_UIDVALIDITY,
- &status);
+ mailbox_get_open_status(boxes[boxi].box,
+ STATUS_UIDVALIDITY, &status);
if (status.uidvalidity != last_uids[uidi].uidvalidity) {
uidi++;
continue;
struct mailbox_status status;
int ret;
- mailbox_get_status(fctx->t->box, STATUS_MESSAGES | STATUS_UIDNEXT,
- &status);
+ mailbox_get_open_status(fctx->t->box, STATUS_MESSAGES | STATUS_UIDNEXT,
+ &status);
if (status.messages == fctx->fbox->last_messages_count &&
status.uidnext == fctx->fbox->last_uidnext) {
/* no new messages since last check */
ret = -1;
if (ret == 0) {
- mailbox_get_status(box, STATUS_MESSAGES | STATUS_UIDNEXT,
- &status);
+ mailbox_get_open_status(box, STATUS_MESSAGES | STATUS_UIDNEXT,
+ &status);
fbox->last_messages_count = status.messages;
fbox->last_uidnext = status.uidnext;
}
struct fts_mailbox *fbox = FTS_CONTEXT(ctx->transaction->box);
struct mailbox_status status;
- mailbox_get_status(ctx->transaction->box, STATUS_MESSAGES, &status);
+ mailbox_get_open_status(ctx->transaction->box,
+ STATUS_MESSAGES, &status);
fctx->seqs_set = FALSE;
ctx->seq = fctx->first_nonindexed_seq - 1;
return NULL;
t_array_init(&kw_strings, src_keywords->count + 1);
- mailbox_get_status(src_box, STATUS_KEYWORDS, &status);
+ mailbox_get_open_status(src_box, STATUS_KEYWORDS, &status);
for (i = 0; i < src_keywords->count; i++) {
kwp = array_idx(status.keywords, src_keywords->idx[i]);
}
static int
-virtual_mailbox_get_guid(struct mailbox *box,
- uint8_t guid[MAIL_GUID_128_SIZE] ATTR_UNUSED)
+virtual_mailbox_get_metadata(struct mailbox *box,
+ enum mailbox_metadata_items items,
+ struct mailbox_metadata *metadata_r)
{
- mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
- "Virtual mailboxes have no GUIDs");
- return -1;
+ if ((items & MAILBOX_METADATA_GUID) != 0) {
+ mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+ "Virtual mailboxes have no GUIDs");
+ return -1;
+ }
+ return index_mailbox_get_metadata(box, items, metadata_r);
}
static void
if (bbox == NULL)
return FALSE;
- mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
if (status.uidvalidity != backend_uidvalidity)
return FALSE;
index_storage_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
- virtual_mailbox_get_guid,
+ virtual_mailbox_get_metadata,
NULL,
NULL,
virtual_storage_sync_init,
unsigned int mailbox_offset;
uint64_t wanted_ondisk_highest_modseq;
- mailbox_get_status(bbox->box, STATUS_UIDVALIDITY |
- STATUS_HIGHESTMODSEQ, &status);
+ mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY |
+ STATUS_HIGHESTMODSEQ, &status);
wanted_ondisk_highest_modseq =
array_count(&bbox->sync_pending_removes) > 0 ? 0 :
status.highest_modseq;
if (mailbox_sync(bbox->box, sync_flags) < 0)
return -1;
- mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
virtual_backend_box_sync_mail_set(bbox);
if (status.uidvalidity != bbox->sync_uid_validity) {
/* UID validity changed since last sync (or this is
*failed_uid_r = 0;
- mailbox_get_status(client->mailbox, STATUS_UIDVALIDITY, &status);
+ mailbox_get_open_status(client->mailbox, STATUS_UIDVALIDITY, &status);
client->uid_validity = status.uidvalidity;
client->messages_count = status.messages;