⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maildirquota.c

📁 相当优秀的 UNIX 进程管理工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: maildirquota.c,v 1.7 2003/12/19 05:16:36 tomcollins Exp $ * Copyright (C) 1999-2003 Inter7 Internet Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * *//* include files */#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <dirent.h>#include <errno.h>#include <time.h>#include <sys/uio.h>#include "vauth.h"#include "vpopmail.h"#include "vlimits.h"#include "maildirquota.h"#include "config.h"/* private functions - no name clashes with courier */static char *makenewmaildirsizename(const char *, int *);static int countcurnew(const char *, time_t *, off_t *, unsigned *);static int countsubdir(const char *, const char *,		time_t *, off_t *, unsigned *);static int statcurnew(const char *, time_t *);static int statsubdir(const char *, const char *, time_t *);static int doaddquota(const char *, int, const char *, long, int, int);static int docheckquota(const char *dir, int *maildirsize_fdptr,	const char *quota_type, long xtra_size, int xtra_cnt, int *percentage);static int docount(const char *, time_t *, off_t *, unsigned *);static int maildir_checkquota(const char *dir, int *maildirsize_fdptr,	const char *quota_type, long xtra_size, int xtra_cnt);static int maildir_addquota(const char *dir, int maildirsize_fd,	const char *quota_type, long maildirsize_size, int maildirsize_cnt);static int maildir_safeopen(const char *path, int mode, int perm);static char *str_pid_t(pid_t t, char *arg);static char *str_time_t(time_t t, char *arg);static int maildir_parsequota(const char *n, unsigned long *s);#define  NUMBUFSIZE      60#define	MDQUOTA_SIZE	'S'	/* Total size of all messages in maildir */#define	MDQUOTA_BLOCKS	'B'	/* Total # of blocks for all messages in				maildir -- NOT IMPLEMENTED */#define	MDQUOTA_COUNT	'C'	/* Total number of messages in maildir *//* bk: add domain limits functionality */int domain_over_maildirquota(const char *userdir){struct  stat    stat_buf;char	domdir[MAX_PW_DIR];char	*p;char	domain[256];unsigned long size = 0;unsigned long maxsize = 0;int	cnt = 0;int	maxcnt = 0;struct vlimits limits;        if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&                stat_buf.st_size > 0)        {		/* locate the domain directory */		p = maildir_to_email(userdir);		if (p == NULL) return -1;		p = strchr (p, '@');		if (p == NULL) return -1;		strcpy(domain, p + 1);		/* get the domain quota */		if (vget_limits(domain, &limits)) return 0;		/* convert from MB to bytes */		maxsize = limits.diskquota * 1024 * 1024;		maxcnt = limits.maxmsgcount;		if (vget_assign (domain, domdir, sizeof(domdir), NULL, NULL) == NULL)			return -1;		/* get the domain usage */		if (readdomainquota(domdir, &size, &cnt)) return -1;		/* check if either quota (size/count) would be exceeded */		if (maxsize > 0 && (size + stat_buf.st_size) > maxsize) return 1;		else if (maxcnt > 0 && cnt >= maxcnt) return 1;        }        return 0;}int readdomainquota(const char *dir, long *sizep, int *cntp){int tries;char	checkdir[256];DIR	*dirp;struct dirent *de;	if (dir == NULL || sizep == NULL || cntp == NULL)		return -1;	*sizep = 0;	*cntp = 0;	dirp=opendir(dir);	while (dirp && (de=readdir(dirp)) != 0)	{		if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))			continue;#ifdef USERS_BIG_DIR		if (strlen(de->d_name) == 1) {			/* recursive call for hashed directory */			snprintf (checkdir, sizeof(checkdir), "%s/%s", dir, de->d_name);			if (readdomainquota (checkdir, sizep, cntp) == -1) {				return -1;			}		} else#endif		{			snprintf(checkdir, sizeof(checkdir), "%s/%s/Maildir/", dir, de->d_name);			tries = 5;			while (tries-- && readuserquota(checkdir, sizep, cntp))			{				if (errno != EAGAIN) return -1;				sleep(1);			}			if (tries <= 0)				return -1;		}	}	if (dirp)	{#if	CLOSEDIR_VOID		closedir(dirp);#else		if (closedir(dirp))		{			return (-1);		}#endif	}	return 0;}int wrapreaduserquota(const char* dir, off_t *sizep, int *cntp){time_t	tm;time_t	maxtime;DIR	*dirp;struct dirent *de;	maxtime=0;	if (countcurnew(dir, &maxtime, sizep, cntp))	{		return (-1);	}	dirp=opendir(dir);	while (dirp && (de=readdir(dirp)) != 0)	{		if (countsubdir(dir, de->d_name, &maxtime, sizep, cntp))		{			closedir(dirp);			return (-1);		}	}	if (dirp)	{#if	CLOSEDIR_VOID		closedir(dirp);#else		if (closedir(dirp))		{			return (-1);		}#endif	}	/* make sure nothing changed while calculating this... */	tm=0;	if (statcurnew(dir, &tm))	{		return (-1);	}	dirp=opendir(dir);	while (dirp && (de=readdir(dirp)) != 0)	{		if (statsubdir(dir, de->d_name, &tm))		{			closedir(dirp);			return (-1);		}	}	if (dirp)	{#if	CLOSEDIR_VOID		closedir(dirp);#else		if (closedir(dirp))		{			return (-1);		}#endif	}	if (tm != maxtime)	/* Race condition, someone changed something */	{		errno=EAGAIN;		return (-1);	}	errno=0;	return 0;}int readuserquota(const char* dir, long *sizep, int *cntp){	int retval;	off_t s;		s = (off_t) *sizep;	retval = wrapreaduserquota(dir, &s, cntp);	*sizep = (long) s;	return retval;}int user_over_maildirquota( const char *dir, const char *q){struct  stat    stat_buf;int     quotafd;int     ret_value;        if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&                stat_buf.st_size > 0 && *q)        {                if (maildir_checkquota(dir, &quotafd, q, stat_buf.st_size, 1)                        && errno != EAGAIN)                {                        if (quotafd >= 0)       close(quotafd);                        ret_value = 1;                } else {                        maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1);                        if (quotafd >= 0)       close(quotafd);                        ret_value = 0;                }        } else {                ret_value = 0;        }        return(ret_value);}void add_warningsize_to_quota( const char *dir, const char *q){struct  stat    stat_buf;int     quotafd;char    quotawarnmsg[500];        snprintf(quotawarnmsg, sizeof(quotawarnmsg), "%s/%s/.quotawarn.msg", VPOPMAILDIR, DOMAINS_DIR);        if (stat(quotawarnmsg, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&                stat_buf.st_size > 0 && *q)        {                maildir_checkquota(dir, &quotafd, q, stat_buf.st_size, 1);                if (quotafd >= 0)       close(quotafd);                maildir_addquota(dir, quotafd, q,                     stat_buf.st_size, 1);                if (quotafd >= 0)       close(quotafd);        }}/* Read the maildirsize file */static int maildirsize_read(const char *filename,	/* The filename */	int *fdptr,	/* Keep the file descriptor open */	off_t *sizeptr,	/* Grand total of maildir size */	unsigned *cntptr, /* Grand total of message count */	unsigned *nlines, /* # of lines in maildirsize */	struct stat *statptr)	/* The stats on maildirsize */{ char buf[5120]; int f; char *p; unsigned l; int n; int first;	if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0)		return (-1);	p=buf;	l=sizeof(buf);	while (l)	{		n=read(f, p, l);		if (n < 0)		{			close(f);			return (-1);		}		if (n == 0)	break;		p += n;		l -= n;	}	if (l == 0 || fstat(f, statptr))	/* maildir too big */	{		close(f);		return (-1);	}	*sizeptr=0;	*cntptr=0;	*nlines=0;	*p=0;	p=buf;	first=1;	while (*p)	{	long n=0;	int c=0;	char	*q=p;		while (*p)			if (*p++ == '\n')			{				p[-1]=0;				break;			}		if (first)		{			first=0;			continue;		}		sscanf(q, "%ld %d", &n, &c);		*sizeptr += n;		*cntptr += c;		++ *nlines;	}	*fdptr=f;	return (0);}static int qcalc(off_t s, unsigned n, const char *quota, int *percentage){off_t i;int	spercentage=0;int	npercentage=0;	errno=ENOSPC;	while (quota && *quota)	{		int x=1;		if (*quota < '0' || *quota > '9')		{			++quota;			continue;		}		i=0;		while (*quota >= '0' && *quota <= '9')			i=i*10 + (*quota++ - '0');		switch (*quota)	{		default:			if (i < s)			{				*percentage=100;				return (-1);			}			/*			** For huge quotas, over 20mb,			** divide numerator & denominator by 1024 to prevent			** an overflow when multiplying by 100			*/			x=1;			if (i > 20000000) x=1024;			spercentage = i ? (s/x) * 100 / (i/x):100;			break;		case 'C':			if (i < n)			{				*percentage=100;				return (-1);			}			/* Ditto */			x=1;			if (i > 20000000) x=1024;			npercentage = i ? ((off_t)n/x) * 100 / (i/x):100;			break;		}	}	*percentage = spercentage > npercentage ? spercentage:npercentage;	return (0);}static int maildir_checkquota(const char *dir,	int *maildirsize_fdptr,	const char *quota_type,	long xtra_size,	int xtra_cnt){int	dummy;	return (docheckquota(dir, maildirsize_fdptr, quota_type,		xtra_size, xtra_cnt, &dummy));}int vmaildir_readquota(const char *dir, const char *quota_type){int	percentage=0;int	fd=-1;	(void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage);	if (fd >= 0)		close(fd);	return (percentage);}static int docheckquota(const char *dir,	int *maildirsize_fdptr,	const char *quota_type,	long xtra_size,	int xtra_cnt,	int *percentage){char	*checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));char	*newmaildirsizename;struct stat stat_buf;int	maildirsize_fd;off_t	maildirsize_size;unsigned maildirsize_cnt;unsigned maildirsize_nlines;int	n;time_t	tm;time_t	maxtime;DIR	*dirp;struct dirent *de;	if (checkfolder == 0)	return (-1);	*maildirsize_fdptr= -1;	strcat(strcpy(checkfolder, dir), "/maildirfolder");	if (stat(checkfolder, &stat_buf) == 0)	/* Go to parent */	{		strcat(strcpy(checkfolder, dir), "/..");		n=docheckquota(checkfolder, maildirsize_fdptr,			quota_type, xtra_size, xtra_cnt, percentage);		free(checkfolder);		return (n);	}	if (!quota_type || !*quota_type)	return (0);	strcat(strcpy(checkfolder, dir), "/maildirsize");	time(&tm);	if (maildirsize_read(checkfolder, &maildirsize_fd,		&maildirsize_size, &maildirsize_cnt,		&maildirsize_nlines, &stat_buf) == 0)	{		n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,			quota_type, percentage);		if (n == 0)		{			free(checkfolder);			*maildirsize_fdptr=maildirsize_fd;			return (0);		}		close(maildirsize_fd);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -