[dovecot-cvs] dovecot/src/plugins/quota Makefile.am, 1.2, 1.3 quota-fs.c, NONE, 1.1 quota-fs.h, NONE, 1.1 quota.c, 1.1, 1.2

cras at dovecot.org cras at dovecot.org
Wed Dec 14 23:34:03 EET 2005


Update of /var/lib/cvs/dovecot/src/plugins/quota
In directory talvi:/tmp/cvs-serv3106/src/plugins/quota

Modified Files:
	Makefile.am quota.c 
Added Files:
	quota-fs.c quota-fs.h 
Log Message:
quotactl() quota checking support



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/quota/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	10 Dec 2005 22:25:06 -0000	1.2
+++ Makefile.am	14 Dec 2005 21:34:01 -0000	1.3
@@ -11,6 +11,7 @@
 
 libquota_plugin_la_SOURCES = \
 	quota.c \
+	quota-fs.c \
 	quota-dict.c \
 	quota-dirsize.c \
         quota-plugin.c \
@@ -18,6 +19,7 @@
 
 noinst_HEADERS = \
 	quota.h \
+	quota-fs.h \
 	quota-plugin.h \
 	quota-private.h
 

--- NEW FILE: quota-fs.c ---
/* Copyright (C) 2005 Timo Sirainen */

/* Only for reporting filesystem quota */

#include "lib.h"
#include "str.h"
#include "quota-private.h"
#include "quota-fs.h"

#ifdef HAVE_FS_QUOTA

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#define MTAB_PATH "/etc/mtab"

struct fs_quota {
	struct quota quota;

	pool_t pool;
	const char *device;
	const char *error;

	unsigned int blk_size;
	uid_t uid;

	struct quota_root root;
};

struct fs_quota_root_iter {
	struct quota_root_iter iter;

	int sent;
};

extern struct quota fs_quota;

static const char *path_to_device(const char *path, unsigned int *blk_size_r)
{
#ifdef HAVE_STATFS_MNTFROMNAME
	struct statfs buf;

	if (statfs(path, &buf) < 0) {
		i_error("statfs(%s) failed: %m", path);
		return NULL;
	}

	*blk_size_r = buf.f_bsize;
	return t_strdup(buf.f_mntfromname);
#else
	struct mntent *ent;
	struct stat st, st2;
	const char *dev = NULL;
	FILE *f;

	if (stat(path, &st) < 0) {
		i_error("stat(%s) failed: %m", path);
		return NULL;
	}
	*blk_size_r = st.st_blksize;

	f = fopen(MTAB_PATH, "r");
	if (f == NULL) {
		i_error("open(%s) failed: %m", MTAB_PATH);
		return NULL;
	}
	while ((ent = getmntent(f)) != NULL) {
		if (strcmp(ent->mnt_type, MNTTYPE_SWAP) == 0 ||
		    strcmp(ent->mnt_type, MNTTYPE_IGNORE) == 0)
			continue;

		if (stat(ent->mnt_fsname, &st2) == 0 &&
		    CMP_DEV_T(st.st_dev, st2.st_dev)) {
			dev = t_strdup(ent->mnt_fsname);
			break;
		}
	}
	endmntent(f);
	return dev;
#endif
}

static struct quota *fs_quota_init(const char *data)
{
	struct fs_quota *quota;
	const char *device;
	pool_t pool;
	unsigned int blk_size = 0;

	device = path_to_device(data, &blk_size);

	if (getenv("DEBUG") != NULL) {
		i_info("fs quota path = %s", data);
		i_info("fs quota block device = %s",
		       device == NULL ? "(unknown)" : device);
	}

	if (device == NULL)
		return NULL;

	pool = pool_alloconly_create("quota", 1024);
	quota = p_new(pool, struct fs_quota, 1);
	quota->pool = pool;
	quota->quota = fs_quota;
	quota->device = p_strdup(pool, device);
	quota->uid = geteuid();
	quota->blk_size = blk_size;

	quota->root.quota = &quota->quota;
	return &quota->quota;
}

static void fs_quota_deinit(struct quota *_quota)
{
	struct fs_quota *quota = (struct fs_quota *)_quota;

	pool_unref(quota->pool);
}

static struct quota_root_iter *
fs_quota_root_iter_init(struct quota *quota,
			struct mailbox *box __attr_unused__)
{
	struct fs_quota_root_iter *iter;

	iter = i_new(struct fs_quota_root_iter, 1);
	iter->iter.quota = quota;
	return &iter->iter;
}

static struct quota_root *
fs_quota_root_iter_next(struct quota_root_iter *_iter)
{
	struct fs_quota_root_iter *iter =
		(struct fs_quota_root_iter *)_iter;
	struct fs_quota *quota = (struct fs_quota *)_iter->quota;

	if (iter->sent)
		return NULL;

	iter->sent = TRUE;
	return &quota->root;
}

static int fs_quota_root_iter_deinit(struct quota_root_iter *iter)
{
	i_free(iter);
	return 0;
}

static struct quota_root *
fs_quota_root_lookup(struct quota *_quota, const char *name)
{
	struct fs_quota *quota = (struct fs_quota *)_quota;

	if (*name == '\0')
		return &quota->root;
	else
		return NULL;
}

static const char *
fs_quota_root_get_name(struct quota_root *root __attr_unused__)
{
	return "";
}

static const char *const *
fs_quota_root_get_resources(struct quota_root *root __attr_unused__)
{
	static const char *resources[] = { QUOTA_NAME_STORAGE, NULL };

	return resources;
}

static int
fs_quota_root_create(struct quota *_quota,
		     const char *name __attr_unused__,
		     struct quota_root **root_r __attr_unused__)
{
	struct fs_quota *quota = (struct fs_quota *)_quota;

        quota->error = "Permission denied";
	return -1;
}

static int
fs_quota_get_resource(struct quota_root *root, const char *name,
		      uint64_t *value_r, uint64_t *limit_r)
{
	struct fs_quota *quota = (struct fs_quota *)root->quota;
	struct dqblk dqblk;

	*value_r = 0;
	*limit_r = 0;

	if (strcasecmp(name, QUOTA_NAME_STORAGE) != 0)
		return 0;

	if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), quota->device,
		     quota->uid, (void *)&dqblk) < 0) {
		i_error("quotactl(Q_GETQUOTA, %s) failed: %m", quota->device);
		quota->error = "Internal quota error";
		return -1;
	}
	*value_r =  dqblk.dqb_curblocks * quota->blk_size / 1024;
	*limit_r = dqblk.dqb_bsoftlimit * quota->blk_size / 1024;
	return 1;
}

static int
fs_quota_set_resource(struct quota_root *root,
		      const char *name __attr_unused__,
		      uint64_t value __attr_unused__)
{
	struct fs_quota *quota = (struct fs_quota *)root->quota;

	quota->error = "Permission denied";
	return -1;
}

static struct quota_transaction_context *
fs_quota_transaction_begin(struct quota *quota)
{
	struct quota_transaction_context *ctx;

	ctx = i_new(struct quota_transaction_context, 1);
	ctx->quota = quota;
	return ctx;
}

static int
fs_quota_transaction_commit(struct quota_transaction_context *ctx)
{
	i_free(ctx);
	return 0;
}

static void
fs_quota_transaction_rollback(struct quota_transaction_context *ctx)
{
	i_free(ctx);
}

static int
fs_quota_try_alloc(struct quota_transaction_context *ctx __attr_unused__,
		   struct mail *mail __attr_unused__,
		   int *too_large_r __attr_unused__)
{
	/* no-op */
	return 1;
}

static void
fs_quota_alloc(struct quota_transaction_context *ctx __attr_unused__,
		struct mail *mail __attr_unused__)
{
	/* no-op */
}

static void
fs_quota_free(struct quota_transaction_context *ctx __attr_unused__,
	      struct mail *mail __attr_unused__)
{
	/* no-op */
}

static const char *fs_quota_last_error(struct quota *_quota)
{
	struct fs_quota *quota = (struct fs_quota *)_quota;

	return quota->error;
}

struct quota fs_quota = {
	"fs",

	fs_quota_init,
	fs_quota_deinit,

	fs_quota_root_iter_init,
	fs_quota_root_iter_next,
	fs_quota_root_iter_deinit,

	fs_quota_root_lookup,

	fs_quota_root_get_name,
	fs_quota_root_get_resources,

	fs_quota_root_create,
	fs_quota_get_resource,
	fs_quota_set_resource,

	fs_quota_transaction_begin,
	fs_quota_transaction_commit,
	fs_quota_transaction_rollback,

	fs_quota_try_alloc,
	fs_quota_alloc,
	fs_quota_free,

	fs_quota_last_error,

	ARRAY_INIT
};

#endif

--- NEW FILE: quota-fs.h ---
#ifndef __QUOTA_FS_H
#define __QUOTA_FS_H

#define HAVE_FS_QUOTA

#ifdef HAVE_SYS_QUOTA_H
#  include <sys/quota.h> /* Linux */
#elif defined(HAVE_SYS_FS_UFS_QUOTA_H)
#  include <sys/fs/ufs_quota.h> /* Solaris */
#elif defined(HAVE_UFS_UFS_QUOTA_H)
#  include <ufs/ufs/quota.h> /* BSDs */
#else
#  undef HAVE_FS_QUOTA
#endif

#ifdef HAVE_STATFS_MNTFROMNAME
#  include <sys/param.h> /* BSDs */
#  include <sys/mount.h>
#elif defined(HAVE_MNTENT_H)
#  include <mntent.h> /* Linux */
#elif defined(HAVE_SYS_MNTTAB_H)
#  include <sys/mnttab.h> /* Solaris */
#else
#  undef HAVE_FS_QUOTA
#endif

#endif

Index: quota.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/plugins/quota/quota.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- quota.c	10 Dec 2005 19:44:46 -0000	1.1
+++ quota.c	14 Dec 2005 21:34:01 -0000	1.2
@@ -3,13 +3,21 @@
 #include "lib.h"
 #include "array.h"
 #include "quota-private.h"
+#include "quota-fs.h"
 
 unsigned int quota_module_id = 0;
 
 extern struct quota dirsize_quota;
 extern struct quota dict_quota;
+extern struct quota fs_quota;
 
-static struct quota *quota_classes[] = { &dirsize_quota, &dict_quota };
+static struct quota *quota_classes[] = {
+	&dirsize_quota,
+	&dict_quota,
+#ifdef HAVE_FS_QUOTA
+	&fs_quota
+#endif
+};
 #define QUOTA_CLASS_COUNT (sizeof(quota_classes)/sizeof(quota_classes[0]))
 
 struct quota *quota_init(const char *data)
@@ -44,10 +52,11 @@
 
 void quota_deinit(struct quota *quota)
 {
-	array_t *module_contexts = &quota->quota_module_contexts;
+	/* make a copy, since quota is freed */
+	array_t module_contexts = quota->quota_module_contexts;
 
 	quota->deinit(quota);
-	array_free(module_contexts);
+	array_free(&module_contexts);
 }
 
 struct quota_root_iter *



More information about the dovecot-cvs mailing list