maildir-keywords.c revision ba3d9eeb0bec6ed8465d68fa2480ad085559b580
/* Copyright (c) 2005-2008 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 "file-dotlock.h"
#include "write-full.h"
#include "nfs-workarounds.h"
#include "maildir-storage.h"
#include "maildir-uidlist.h"
#include "maildir-keywords.h"
#include <stdlib.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_DEFINE(idx_to_chr, char);
unsigned int chridx_to_idx[MAILDIR_MAX_KEYWORDS];
};
{
struct maildir_keywords *mk;
return mk;
}
struct maildir_keywords *
{
struct maildir_keywords *mk;
const char *dir;
return mk;
}
{
}
{
}
{
const char **strp;
/* 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
{
void *p;
if (p == NULL) {
return -1;
if (maildir_keywords_sync(mk) < 0)
return -1;
if (p == NULL)
return -1;
}
return POINTER_CAST_TO(p, int)-1;
}
static void
unsigned int chridx)
{
const char **strp;
char *new_name;
}
static int
{
const char *const *keywords;
unsigned int i, count;
int idx;
if (idx >= 0)
return idx;
/* we couldn't open the dovecot-keywords file. */
return -1;
}
/* see if we are full */
for (i = 0; i < count; i++) {
break;
}
return -1;
return -1;
return i;
}
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;
}
"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 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;
}
{
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;
int chridx;
if (*chr_p != '\0')
return *chr_p;
if (chridx < 0)
return '\0';
return *chr_p;
}