index-storage.c revision 0b4e1043e596bfb36d999dacbf1d4d63ee96d75f
/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "istream.h"
#include "ioloop.h"
#include "str.h"
#include "imap-parser.h"
#include "mkdir-parents.h"
#include "mail-index-alloc-cache.h"
#include "mail-index-private.h"
#include "mail-index-modseq.h"
#include "mailbox-log.h"
#include "mailbox-list-private.h"
#include "index-storage.h"
#include "index-mail.h"
#include "index-thread-private.h"
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define LOCK_NOTIFY_INTERVAL 30
struct index_storage_module index_storage_module =
const char *name)
{
unsigned int n = 0;
return 0;
break;
"mkdir(%s) failed: %m", index_dir);
return -1;
}
/* create the parent directory first */
return -1;
}
return 0;
}
static struct mail_index *
{
const char *index_dir, *mailbox_path;
if (*index_dir == '\0')
}
enum mail_cache_decision_type dec)
{
const char *const *arr;
int i;
return;
for (i = 0; i < MAIL_INDEX_CACHE_FIELD_COUNT; i++) {
*arr) == 0) {
break;
}
}
if (i == MAIL_INDEX_CACHE_FIELD_COUNT) {
i_error("%s: Invalid cache field name '%s', ignoring ",
}
}
}
{
static bool initialized = FALSE;
if (!initialized) {
initialized = TRUE;
set_cache_decisions("mail_cache_fields",
set_cache_decisions("mail_never_cache_fields",
}
sizeof(global_cache_fields));
}
unsigned int secs_left)
{
const char *str;
/* if notify type changes, print the message immediately */
/* first override notification, show it */
} else {
return;
}
}
switch (notify_type) {
case MAILBOX_LOCK_NOTIFY_NONE:
break;
break;
"%u seconds", secs_left);
break;
break;
"will override in %u seconds", secs_left);
break;
}
}
{
}
{
enum file_lock_method lock_method =
int ret;
if (move_to_memory)
if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
"Couldn't create index file");
return -1;
}
}
return -1;
}
if (ret <= 0 || move_to_memory) {
if ((index_flags & MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY) != 0) {
return -1;
}
/* try opening once more. it should be created
directly into memory now. */
lock_method) < 0)
i_panic("in-memory index creation failed");
}
}
sizeof(struct index_vsize_header), 0,
sizeof(uint64_t));
if (hook_mailbox_opened != NULL)
return -1;
}
}
return 0;
}
enum mailbox_flags flags,
const char *index_prefix)
{
struct index_mailbox_context *ibox;
const char *path;
if (box->file_create_mode == 0)
}
enum mailbox_feature feature)
{
if ((feature & MAILBOX_FEATURE_CONDSTORE) != 0) {
if (mailbox_open(box) < 0)
return -1;
T_BEGIN {
} T_END;
}
return 0;
}
{
ibox->recent_flags_prev_uid = 0;
ibox->recent_flags_count = 0;
ibox->sync_last_check = 0;
}
{
}
const struct mailbox_update *update)
{
const struct mail_cache_field *old_fields;
struct mail_cache_field field;
unsigned int i, j, old_count;
&old_count);
/* There shouldn't be many fields, so don't worry about O(n^2). */
for (i = 0; field_names[i] != NULL; i++) {
/* see if it's an existing field */
for (j = 0; j < old_count; j++) {
break;
}
if (j != old_count) {
field = old_fields[j];
/* new header */
} else {
/* new unknown field. we can't do anything about
this since we don't know its type */
}
}
if (array_count(&new_fields) > 0) {
}
}
const struct mailbox_update *update)
{
const struct mail_index_header *hdr;
struct mail_index_view *view;
struct mail_index_transaction *trans;
int ret;
if (mailbox_open(box) < 0)
return -1;
/* make sure we get the latest index info */
if (update->uid_validity != 0 &&
if (hdr->uid_validity != 0) {
/* UIDVALIDITY change requires index to be reset */
}
}
if (update->min_next_uid != 0 &&
}
if (update->min_highest_modseq != 0 &&
}
return ret;
}
{
enum mail_error error;
return 0;
return -1;
}
/* failed directory deletion, but mailbox deletion succeeded.
this was probably maildir++, which internally deleted the
directory as well. add changelog record about that too. */
return 0;
}
{
/* \noselect mailbox, try deleting only the directory */
}
return -1;
/* Make sure the indexes are closed before trying to delete the
directory that contains them. It can still fail with some NFS
implementations if indexes are opened by another session, but
that can't really be helped. */
return -1;
}
}
bool rename_children)
{
rename_children) < 0) {
return -1;
}
/* we'll track mailbox names, instead of GUIDs. We may be renaming a
non-selectable mailbox (directory), which doesn't even have a GUID */
return 0;
}
{
return TRUE;
if (box->backend_readonly) {
/* return read-only only if there are no private flags
(that are stored in index files) */
if (box->private_flags_mask == 0)
return TRUE;
}
return FALSE;
}
{
/* FIXME: return FALSE if we're full */
return !index_storage_is_readonly(box);
}
{
}
const char **error_r)
{
unsigned int i, idx;
/* if it already exists, skip validity checks */
return TRUE;
if (*keyword == '\0') {
*error_r = "Empty keywords not allowed";
return FALSE;
}
/* these are IMAP-specific restrictions, but for now IMAP is all we
care about */
for (i = 0; keyword[i] != '\0'; i++) {
if (IS_ATOM_SPECIAL((unsigned char)keyword[i])) {
*error_r = "Invalid characters in keyword";
return FALSE;
}
if ((unsigned char)keyword[i] >= 0x80) {
*error_r = "8bit characters in keyword";
return FALSE;
}
}
*error_r = "Keyword length too long";
return FALSE;
}
return TRUE;
}
static struct mail_keywords *
const char *const keywords[])
{
ARRAY_DEFINE(valid_keywords, const char *);
const char *error;
}
}
{
const char *error;
unsigned int i;
continue;
if (!skip_invalid) {
return -1;
}
/* found invalid keywords, do this the slow way */
T_BEGIN {
} T_END;
return 0;
}
return 0;
}
struct mail_keywords *
{
}
{
}
{
}
{
}