maildir-keywords.c revision 0ea17cea21df405e6e74a167d08e1ff0ee95dd13
/* Copyright (C) 2005 Timo Sirainen */
/* 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. */
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 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 fd;
return 0;
/* 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) {
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_push();
t_pop();
}
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;
}