dict-file.c revision 2aed6c2062317d1750f59c5c88e77d9f10967462
/* Copyright (c) 2008-2012 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "hash.h"
#include "file-lock.h"
#include "file-dotlock.h"
#include "nfs-workarounds.h"
#include "istream.h"
#include "ostream.h"
#include "dict-private.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
struct file_dict {
enum file_lock_method lock_method;
char *path;
struct hash_table *hash;
int fd;
bool refreshed;
};
struct file_dict_iterate_path {
const char *path;
unsigned int len;
};
struct file_dict_iterate_context {
struct dict_iterate_context ctx;
struct hash_iterate_context *iter;
struct file_dict_iterate_path *paths;
enum dict_iterate_flags flags;
unsigned int failed:1;
};
enum file_dict_change_type {
};
struct file_dict_change {
enum file_dict_change_type type;
const char *key;
union {
const char *str;
long long diff;
} value;
};
struct file_dict_transaction_context {
struct dict_transaction_context ctx;
unsigned int atomic_inc_not_found:1;
};
static struct dotlock_settings file_dict_dotlock_settings = {
.stale_timeout = 60,
};
const char *username ATTR_UNUSED,
const char *base_dir ATTR_UNUSED)
{
const char *p;
if (p == NULL) {
/* no parameters */
} else {
if (strcmp(p, "lock=fcntl") == 0)
else if (strcmp(p, "lock=flock") == 0)
else
}
}
{
}
}
{
return TRUE;
return FALSE;
}
return TRUE;
}
/* file changed */
return TRUE;
}
return FALSE;
}
{
int open_type;
if (!file_dict_need_refresh(dict))
return 0;
}
return 0;
return -1;
}
return 1;
}
{
if (file_dict_open_latest(dict) < 0)
return -1;
return 0;
}
}
return 0;
}
{
if (file_dict_refresh(dict) < 0)
return -1;
}
static struct dict_iterate_context *
enum dict_iterate_flags flags)
{
struct file_dict_iterate_context *ctx;
unsigned int i, path_count;
for (i = 0; i < path_count; i++) {
}
if (file_dict_refresh(dict) < 0)
}
static const struct file_dict_iterate_path *
const char *key)
{
unsigned int i;
}
return NULL;
}
{
struct file_dict_iterate_context *ctx =
(struct file_dict_iterate_context *)_ctx;
const struct file_dict_iterate_path *path;
continue;
continue;
return TRUE;
}
return FALSE;
}
{
struct file_dict_iterate_context *ctx =
(struct file_dict_iterate_context *)_ctx;
return ret;
}
static struct dict_transaction_context *
{
struct file_dict_transaction_context *ctx;
}
{
const char *tmp;
void *orig_key, *orig_value;
const struct file_dict_change *change;
unsigned int new_len;
long long diff;
&orig_key, &orig_value)) {
} else {
}
break;
}
else {
}
/* fall through */
}
break;
} else {
}
break;
break;
}
}
}
static int
{
return -1;
}
/* group has different permissions from world.
preserve the group. */
i_error("fchown(%s, -1, %s) failed: %m",
return -1;
}
}
i_error("fchmod(%s, %o) failed: %m",
return -1;
}
}
return 0;
}
{
return -1;
}
}
static int
const char *dest_path)
{
const char *src_dir, *p;
if (p == NULL)
src_dir = ".";
else
return -1;
}
}
static int
{
int ret;
if (file_dict_open_latest(dict) < 0)
return -1;
/* quota file doesn't exist yet, we need to create it */
return -1;
}
}
do {
lock_r) <= 0) {
return -1;
}
/* check again if we need to reopen the file because it was
just replaced */
return ret < 0 ? -1 : 0;
}
{
struct hash_iterate_context *iter;
int fd = -1;
switch (dict->lock_method) {
case FILE_LOCK_METHOD_FCNTL:
case FILE_LOCK_METHOD_FLOCK:
return -1;
if (fd == -1) {
i_error("file dict commit: creat(%s) failed: %m",
return -1;
}
break;
case FILE_LOCK_METHOD_DOTLOCK:
&dotlock);
if (fd == -1) {
i_error("file dict commit: file_dotlock_open(%s) failed: %m",
return -1;
}
break;
}
/* refresh once more now that we're locked */
if (file_dict_refresh(dict) < 0) {
else {
i_close_fd(&fd);
file_unlock(&lock);
}
return -1;
}
/* preserve the permissions */
} else {
/* get initial permissions from parent directory */
}
}
if (o_stream_nfinish(output) < 0) {
i_close_fd(&fd);
return -1;
}
if (file_dotlock_replace(&dotlock,
i_close_fd(&fd);
return -1;
}
} else {
i_error("rename(%s, %s) failed: %m",
file_unlock(&lock);
i_close_fd(&fd);
return -1;
}
}
return 0;
}
static int
bool async ATTR_UNUSED,
void *context)
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
int ret;
if (file_dict_write_changes(ctx) < 0)
ret = -1;
else if (ctx->atomic_inc_not_found)
ret = 0;
else
ret = 1;
return ret;
}
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
}
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
struct file_dict_change *change;
}
const char *key)
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
struct file_dict_change *change;
}
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
struct file_dict_change *change;
}
static void
{
struct file_dict_transaction_context *ctx =
(struct file_dict_transaction_context *)_ctx;
struct file_dict_change *change;
}
struct dict dict_driver_file = {
.name = "file",
{
NULL,
}
};