maildir-keywords.c revision 32d69cb0794acf725c47e6d17145ec4eb0cd6e7f
/* Copyright (c) 2005-2016 Dovecot authors, see the included COPYING file */
/* note that everything here depends on uidlist file being locked the whole
time. that's why we don't have any locking of our own, or that we do things
that would be racy otherwise. */
#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "hash.h"
#include "str.h"
#include "istream.h"
#include "eacces-error.h"
#include "file-dotlock.h"
#include "write-full.h"
#include "nfs-workarounds.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include "maildir-keywords.h"
#include <utime.h>
/* how many seconds to wait before overriding dovecot-keywords.lock */
struct maildir_keywords {
struct maildir_mailbox *mbox;
struct mail_storage *storage;
char *path;
struct dotlock_settings dotlock_settings;
unsigned int synced:1;
unsigned int changed:1;
};
struct maildir_keywords_sync_ctx {
struct maildir_keywords *mk;
struct mail_index *index;
ARRAY(char) idx_to_chr;
unsigned int chridx_to_idx[MAILDIR_MAX_KEYWORDS];
bool readonly;
};
{
struct maildir_keywords *mk;
return mk;
}
struct maildir_keywords *
{
struct maildir_keywords *mk;
const char *dir;
i_unreached();
return mk;
}
{
}
{
}
{
const char **strp;
unsigned int idx;
int fd;
/* Remember that we rely on uidlist file locking in here. That's why
we rely on stat()'s timestamp and don't bother handling ESTALE
errors. */
/* file is updated only by replacing it, no need to flush
attribute cache */
}
return 0;
}
return -1;
}
/* hasn't changed */
return 0;
}
if (fd == -1) {
return 0;
}
return -1;
}
if (p == NULL) {
/* note that when converting .customflags file this
case happens in the first line. */
continue;
}
*p++ = '\0';
/* shouldn't happen */
continue;
}
/* save it */
}
return -1;
}
return 0;
}
static int
unsigned int *chridx_r)
{
void *value;
return 0;
if (maildir_keywords_sync(mk) < 0)
return -1;
return 0;
}
return 1;
}
static void
unsigned int chridx)
{
const char **strp;
char *new_name;
}
static int
unsigned int *chridx_r)
{
const char *const *keywords;
unsigned int i, count;
int ret;
return ret;
/* see if we are full */
for (i = 0; i < count; i++) {
break;
}
return -1;
return -1;
*chridx_r = i;
return 1;
}
static const char *
{
const char *const *keywords;
unsigned int count;
return NULL;
if (maildir_keywords_sync(mk) < 0)
return NULL;
}
}
{
const char *const *keywords;
unsigned int i, count;
for (i = 0; i < count; i++) {
}
"write_full(%s) failed: %m", path);
return -1;
}
"fstat(%s) failed: %m", path);
return -1;
}
} else {
"fchown(%s) failed: %m", path);
}
}
}
/* mtime must grow every time */
"utime(%s) failed: %m", path);
return -1;
}
}
"fsync(%s) failed: %m", path);
return -1;
}
return 0;
}
{
const struct mailbox_permissions *perm;
const char *lock_path;
int i, fd;
return 0;
for (i = 0;; i++) {
/* we could just create the temp file directly, but doing it
this ways avoids potential problems with overwriting
contents in malicious symlinks */
if (fd != -1)
break;
return -1;
}
/* the control dir doesn't exist. create it unless the whole
mailbox was just deleted. */
return -1;
}
return -1;
}
if (file_dotlock_replace(&dotlock, 0) < 0) {
return -1;
}
return 0;
}
struct maildir_keywords_sync_ctx *
struct mail_index *index)
{
struct maildir_keywords_sync_ctx *ctx;
return ctx;
}
struct maildir_keywords_sync_ctx *
struct mail_index *index)
{
struct maildir_keywords_sync_ctx *ctx;
return ctx;
}
{
T_BEGIN {
} T_END;
}
char keyword)
{
const char *name;
/* lookup / create */
/* name is lost. just generate one ourself. */
/* don't create a duplicate name.
keep changing the name until it doesn't exist */
}
}
return idx;
}
unsigned int idx)
{
const char *const *name_p;
char *chr_p;
unsigned int chridx;
int ret;
if (*chr_p != '\0')
return *chr_p;
if (ret <= 0)
return '\0';
return *chr_p;
}