mail-index.c revision 0bd15afe9cadd09b01e68b493b30c9d7e92b4095
/* Copyright (c) 2003-2014 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "buffer.h"
#include "eacces-error.h"
#include "hash.h"
#include "str-sanitize.h"
#include "mmap-util.h"
#include "nfs-workarounds.h"
#include "read-full.h"
#include "write-full.h"
#include "mail-index-alloc-cache.h"
#include "mail-index-private.h"
#include "mail-index-view-private.h"
#include "mail-index-sync-private.h"
#include "mail-index-modseq.h"
#include "mail-transaction-log.h"
#include "mail-cache.h"
#include <stdio.h>
#include <stddef.h>
#include <time.h>
struct mail_index_module_register mail_index_module_register = { 0 };
{
struct mail_index *index;
128, 2, 1);
return index;
}
{
}
enum fsync_mode mode,
enum mail_index_fsync_mask mask)
{
}
{
}
enum file_lock_method lock_method,
unsigned int max_timeout_secs)
{
}
{
const struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext rext;
if (default_record_size != 0 && default_record_align == 0) {
i_panic("mail_index_ext_register(%s): "
"Invalid record alignment", name);
}
return ext_id;
}
{
const struct mail_index_registered_ext *extensions;
unsigned int i, count;
for (i = 0; i < count; i++) {
*ext_id_r = i;
return TRUE;
}
}
return FALSE;
}
void *context)
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
struct mail_index_registered_ext *rext;
}
{
}
{
mail_index_sync_lost_handler_t *const *handlers;
unsigned int i, count;
for (i = 0; i < count; i++) {
break;
}
}
}
{
char *key;
void *value;
/* keywords_hash keeps a name => index mapping of keywords.
Keywords are never removed from it, so the index values are valid
for the lifetime of the mail_index. */
return TRUE;
}
return FALSE;
}
const char *keyword,
unsigned int *idx_r)
{
char *keyword_dup;
return;
POINTER_CAST(*idx_r));
/* keep the array NULL-terminated, but the NULL itself invisible */
}
{
}
struct mail_keywords *
const char *const keywords[])
{
struct mail_keywords *k;
if (count == 0) {
k->refcount = 1;
return k;
}
/* @UNSAFE */
k = i_malloc(sizeof(struct mail_keywords) +
k->refcount = 1;
/* look up the keywords from index. they're never removed from there
so we can permanently store indexes to them. */
/* ignore if this is a duplicate */
for (i = 0; i < src; i++) {
break;
}
if (i == src)
dest++;
}
return k;
}
struct mail_keywords *
const ARRAY_TYPE(keyword_indexes)
{
struct mail_keywords *k;
const unsigned int *indexes;
if (count == 0) {
k->refcount = 1;
return k;
}
/* @UNSAFE */
k = i_malloc(sizeof(struct mail_keywords) +
k->refcount = 1;
/* copy but skip duplicates */
for (i = 0; i < src; i++) {
break;
}
if (i == src)
}
return k;
}
{
}
{
}
{
/* Note that our caller must close index->fd by itself. */
else {
}
}
return -1;
}
/* have to create it */
return 0;
}
return 1;
}
static int
{
int ret;
if (MAIL_INDEX_IS_IN_MEMORY(index))
return 0;
if (ret == 0) {
/* it's corrupted - recreate it */
}
}
return ret;
}
{
const char *path;
int fd;
/* stale temp file. unlink and recreate rather than overwriting,
just to make sure locking problems won't cause corruption */
return -1;
}
}
if (fd == -1) {
return -1;
}
return fd;
}
enum mail_index_open_flags flags)
{
int ret;
if (ret == 0) {
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
return 0;
/* if dovecot.index exists, read it first so that we can get
the correct indexid and log sequence */
(void)mail_index_try_open(index);
/* Create a new indexid for us. If we're opening index
into memory, index->map doesn't exist yet. */
}
/* log creation could have changed it if someone else
just created it. */
}
}
if (ret >= 0) {
if (ret == 0) {
/* corrupted */
if (ret == 0) {
}
}
}
if (ret < 0) {
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
return -1;
if (mail_index_move_to_memory(index) < 0)
return -1;
}
}
return 1;
}
static int
enum mail_index_open_flags flags)
{
int ret;
/* index was marked corrupted. we'll probably need to
recreate the files. */
return ret;
}
index->open_count++;
return 1;
}
{
int ret;
if (index->open_count > 0) {
/* doesn't exist and create flag not used */
}
return ret;
}
i_strdup("(in-memory index)") :
if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
i_fatal("nfs flush requires mail_fsync=always");
if ((flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0 &&
(flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0)
i_fatal("nfs flush requires mmap_disable=yes");
/* NOTE: increase open_count only after mail_index_open_files().
it's used elsewhere to check if we're doing an initial opening
of the index files */
/* doesn't exist and create flag not used */
return ret;
}
index->open_count++;
return 1;
}
enum mail_index_open_flags flags)
{
int ret;
return ret < 0 ? -1 : 0;
}
{
}
}
{
}
{
if (--index->open_count == 0)
}
{
const char *path;
int last_errno = 0;
return 0;
/* main index */
last_errno = errno;
/* logs */
last_errno = errno;
last_errno = errno;
/* cache */
last_errno = errno;
if (last_errno == 0)
return 0;
else {
errno = last_errno;
return -1;
}
}
{
if (MAIL_INDEX_IS_IN_MEMORY(index))
return 0;
return mail_index_try_open_only(index);
return 0;
return -1;
}
if (!ESTALE_FSTAT(errno)) {
return -1;
}
/* the same file */
return 1;
}
/* new file, new locks. the old fd can keep its locks, they don't
matter anymore as no-one's going to modify the file. */
return mail_index_try_open_only(index);
}
{
int ret;
return ret <= 0 ? -1 : 0;
}
{
}
{
else {
}
}
{
return MAIL_INDEX_IS_IN_MEMORY(index);
}
{
struct mail_index_map *map;
if (MAIL_INDEX_IS_IN_MEMORY(index))
return -1;
/* set the index as being into memory */
/* index was never even opened. just mark it as being in
memory and let the caller re-open the index. */
return -1;
}
/* move index map to memory */
}
/* move transaction log to memory */
}
}
return 0;
}
{
}
}
{
}
{
return -1;
if (*mtime_r == 0) {
return -1;
}
}
return 0;
}
{
/* no gid changing */
return;
/* success */
return;
/* group and world permissions are the same, so group doesn't
really matter. ignore silently. */
return;
}
else {
index->gid_origin));
}
/* continue, but change permissions so that only the common
subset of group and world is used. this makes sure no one
gets any extra permissions. */
}
const char *function)
{
}
const char *filepath,
const char *function)
{
const char *errstr;
return;
}
else
} else {
" (process was started with ulimit -f limit)";
}
}
{
}
{
}
}