mailbox-list-index.c revision 66ecc94150cbce23aad3240135e0782e0a74d479
/* Copyright (c) 2006-2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "crc32.h"
#include "ioloop.h"
#include "str.h"
#include "file-cache.h"
#include "file-dotlock.h"
#include "mmap-util.h"
#include "write-full.h"
#include "nfs-workarounds.h"
#include "mail-index-private.h"
#include "mailbox-list-index-private.h"
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
struct mailbox_list_iter_path {
const struct mailbox_list_dir_record *dir;
unsigned int pos;
unsigned int name_path_len;
};
struct mailbox_list_index_view {
struct mailbox_list_index *index;
struct mail_index_view *mail_view;
};
struct mailbox_list_iter_ctx {
struct mailbox_list_index_view *view;
unsigned int recurse_level;
struct mailbox_list_iter_path cur;
unsigned int failed:1;
};
static const struct dotlock_settings default_dotlock_set = {
};
const char *function)
{
return -1;
}
{
}
}
{
}
}
const char *str)
{
i_error("Corrupted mailbox list index file %s: %s",
return -1;
}
static int
const struct mailbox_list_index_header *hdr)
{
return -1;
"header_size is too small");
}
"header_size is too large");
}
if (hdr->uid_validity == 0) {
"uid_validity is 0");
}
/* index already marked as corrupted */
return -1;
}
return 0;
}
{
const struct mailbox_list_index_header *hdr;
if (!index->mmap_disable) {
return -1;
}
}
if (!index->mmap_disable &&
return -1;
}
} else {
if (ret < 0) {
"file_cache_read()");
return -1;
}
}
return 0;
}
return 0;
}
return 1;
}
{
return 1;
if (mailbox_list_index_map(index) <= 0)
return -1;
return 1;
/* outside the file */
return 0;
}
static void
struct mailbox_list_index_header *hdr,
{
}
{
return 1;
return 1;
return -1;
}
return 1;
return -1;
}
}
{
struct mailbox_list_index_header hdr;
0, &dotlock);
if (fd == -1) {
"file_dotlock_open()");
return -1;
}
/* if the file has been recreated by someone else,
retry opening it */
if (ret != 0) {
(void)file_dotlock_delete(&dotlock);
return ret < 0 ? -1 : 0;
}
}
(void)file_dotlock_delete(&dotlock);
return -1;
}
(void)file_dotlock_delete(&dotlock);
return -1;
}
if (file_dotlock_replace(&dotlock,
"file_dotlock_replace()");
return -1;
}
if (ret == 0) {
i_error("Self-created mailbox list index file %s was corrupted",
return -1;
}
return ret;
}
static int
{
int ret;
return -1;
}
} else {
if (ret != 0) {
if (ret < 0)
return ret;
}
}
if (ret <= 0)
return ret;
}
{
int ret;
/* file was recreated by someone else, try reopening */
}
return ret < 0 ? -1 : 0;
}
struct mailbox_list_index *
struct mail_index *mail_index)
{
struct mailbox_list_index *index;
return index;
}
{
}
struct mailbox_list_index_lookup_key {
struct mailbox_list_index *index;
const char *name;
bool *failed;
};
static int
const struct mailbox_list_record *rec,
const char **name_r)
{
const char *name;
"record name_offset (%u) points outside file "
return -1;
}
/* get name length. don't bother checking if it's not NUL-terminated,
because practically it always is even if the file is corrupted.
just make sure we don't crash if it happens. */
if (*name_r == '\0') {
return -1;
}
return 0;
}
const struct mailbox_list_dir_record **dir_r)
{
const struct mailbox_list_dir_record *dir;
int ret;
do {
sizeof(*dir));
if (ret <= 0) {
if (ret < 0)
return -1;
"dir_offset points outside file");
}
if ((cur_offset % 4) != 0) {
"dir_offset not 32bit aligned");
}
"next_offset points backwards");
}
"dir count too large");
}
"dir_size is smaller than record count");
}
} while (cur_offset != 0);
if (ret <= 0) {
if (ret < 0)
return -1;
"dir points outside file");
}
*offset = cur_offset;
return 0;
}
{
int ret;
return -1;
return 1;
T_BEGIN {
const char *name;
ret = 0;
} else {
}
} T_END;
return ret;
}
const struct mailbox_list_dir_record *dir,
const char *name,
const struct mailbox_list_record **rec_r)
{
const struct mailbox_list_record *rec;
struct mailbox_list_index_lookup_key key;
/* binary search the current hierarchy level name. the values are
sorted primarily by their hash value and secondarily by the actual
name */
if (failed)
return -1;
return 0;
return 1;
}
static int
const struct mailbox_list_record **rec_r)
{
const struct mailbox_list_dir_record *dir;
const char *p, *hier_name;
int ret;
/* root doesn't exist in the file yet */
return 0;
}
return -1;
if (ret <= 0)
return ret;
if (p == NULL) {
/* found it */
return 1;
}
/* recurse to children */
if (dir_offset == 0)
return 0;
}
{
int ret;
if (ret < 0)
return -1;
if (mailbox_list_index_map(index) < 0)
ret = -1;
return ret;
}
return mailbox_list_index_open_or_create(index);
}
struct mail_index_view *mail_view,
struct mailbox_list_index_view **view_r)
{
struct mailbox_list_index_view *view;
const struct mail_index_header *mail_hdr;
"uid_validity mismatch in file %s: %u != %u",
return -1;
}
return 0;
}
{
}
{
const struct mailbox_list_record *rec;
int ret;
if (ret == 0) {
/* not found, see if it's found after a refresh */
return ret;
}
return ret;
}
struct mailbox_list_iter_ctx *
const char *path, int recurse_level)
{
struct mailbox_list_iter_ctx *ctx;
const struct mail_index_header *mail_hdr;
const struct mailbox_list_record *rec;
int ret;
(unsigned int)recurse_level;
} else {
}
if (ret < 0)
else {
}
}
/* root doesn't exist */
}
return ctx;
}
struct mailbox_list_index_info *info_r)
{
const struct mailbox_list_iter_path *cur;
const struct mailbox_list_record *recs;
unsigned int count;
return -1;
/* no mailboxes */
return 0;
}
for (;;) {
if (count == 0) {
/* we're done */
return 0;
}
/* go back to parent path */
} else {
break;
}
}
T_BEGIN {
const char *name;
else {
}
}
} T_END;
return -1;
/* recurse into children */
return -1;
}
} else {
}
return 1;
}
{
}