acl-backend-vfile.c revision 086c52e4bcdc950e47ee331e1e07c9c10982a670
/* Copyright (c) 2006-2014 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "array.h"
#include "istream.h"
#include "nfs-workarounds.h"
#include "mail-storage-private.h"
#include "acl-cache.h"
#include "acl-backend-vfile.h"
#include <fcntl.h>
#include <unistd.h>
#define ACL_VFILE_DEFAULT_CACHE_SECS 30
static struct acl_backend *acl_backend_vfile_alloc(void)
{
struct acl_backend_vfile *backend;
}
static int
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
const char *const *tmp;
tmp++;
i_error("acl vfile: Invalid cache_secs value: %s",
*tmp + 11);
return -1;
}
} else {
return -1;
}
}
i_debug("acl vfile: Global ACL directory: %s",
}
sizeof(struct acl_backend_vfile_validity));
return 0;
}
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
}
}
static const char *
const char *name)
{
struct mail_storage *storage;
enum mailbox_list_path_type type;
if (*name == '\0')
return NULL;
/* ACL files are very important. try to keep them among the main
mail files. that's not possible though with a) if the mailbox is
a file or b) if the mailbox path doesn't point to filesystem. */
return NULL;
return FALSE;
} else {
return NULL;
}
/* verify that the directory isn't same as INBOX's directory.
this is mainly for Maildir. */
MAILBOX_LIST_PATH_TYPE_MAILBOX, &inbox) > 0 &&
/* can't have default ACLs with this setup */
return NULL;
}
return dir;
}
static struct acl_object *
const char *name)
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
struct acl_object_vfile *aclobj;
T_BEGIN {
}
} T_END;
}
static const char *
{
const char *p;
}
static int
struct acl_vfile_validity *validity)
{
/* use the cached value */
}
return 0;
}
return 1;
}
return -1;
}
return 1;
}
static bool
{
struct acl_backend_vfile *backend =
(struct acl_backend_vfile *)_backend;
int ret;
if (old_validity != NULL)
else
/* See if the mailbox exists. If we wanted recursive lookups we could
skip this, but at least for now we assume that if an existing
mailbox has no ACL it's equivalent to default ACLs. */
MAILBOX_LIST_PATH_TYPE_MAILBOX, &path) <= 0)
ret = -1;
else {
}
if (ret == 0 &&
}
}
return ret > 0;
}
static struct acl_object *
const char *child_name)
{
const char *parent;
/* stop at the first parent that
a) has global ACL file
b) has local ACL file
c) exists */
break;
child_name = parent;
}
/* use the root */
}
}
{
}
static int
bool *is_dir_r)
{
struct acl_rights rights;
unsigned int linenum;
if (fd == -1) {
i_debug("acl vfile: no access to file %s",
path);
} else {
return -1;
}
return 1;
}
i_close_fd(&fd);
return 0;
}
i_close_fd(&fd);
return -1;
}
/* we opened a directory. */
i_close_fd(&fd);
return 0;
}
linenum = 1;
T_BEGIN {
if (ret < 0) {
i_error("ACL file %s line %u: %s",
} else {
}
} T_END;
if (ret < 0)
break;
linenum++;
}
if (ret < 0) {
/* parsing failure */
} else if (input->stream_errno != 0) {
ret = 0;
else {
ret = -1;
}
} else {
ret = 0;
else {
ret = -1;
}
} else {
ret = 1;
}
}
return 0;
return -1;
}
return ret;
}
static int
struct acl_vfile_validity *validity)
{
unsigned int i;
int ret;
bool is_dir;
return 0;
for (i = 0;; i++) {
&is_dir);
if (ret != 0)
break;
if (is_dir) {
/* opened a directory. use dir/.DEFAULT instead */
} else {
/* ESTALE - try again */
}
}
return ret <= 0 ? -1 : 0;
}
static int
struct acl_vfile_validity *validity)
{
struct acl_backend_vfile *backend =
int ret;
return 1;
return 0;
/* it's a directory. use dir/.DEFAULT instead */
}
if (ret < 0) {
/* if the file used to exist, we have to re-read it */
}
return -1;
}
/* same timestamp, but if it was modified within the
same second we want to refresh it again later (but
do it only after a couple of seconds so we don't
keep re-reading it all the time within those
seconds) */
if (validity->last_read_time != 0 &&
return 0;
}
return 1;
}
{
struct acl_backend_vfile_validity *validity;
return -1;
else
*mtime_r = 0;
return 0;
}
{
struct acl_backend_vfile *backend =
struct acl_backend_vfile_validity *old_validity;
struct acl_backend_vfile_validity validity;
int ret;
if (ret == 0) {
}
if (ret <= 0)
return ret;
/* either global or local ACLs changed, need to re-read both */
} else {
}
&validity.global_validity) < 0)
return -1;
&validity.local_validity) < 0)
return -1;
/* update cache only after we've successfully read everything */
return 0;
}
{
struct acl_backend_vfile_validity *old_validity;
*last_changed_r = 0;
if (old_validity == NULL) {
return -1;
if (old_validity == NULL)
return 0;
}
return 0;
}
struct acl_backend_vfuncs acl_backend_vfile = {
};