コード例 #1
0
ファイル: maildir.C プロジェクト: mcarbonneaux/courier-libs
int	Maildir::MaildirOpen(const char *dir, Mio &file, off_t s)
{
	Buffer	buf;
	struct maildirsize quotainfo;

	const char *quotap;

	Buffer quotabuf;

	quotabuf="MAILDIRQUOTA";	/* Reuse a convenient buffer */
	quotabuf= *GetVar(quotabuf);
	quotabuf += '\0';

	quotap=quotabuf;

	if (!*quotap)
		quotap=NULL;

	MaildirAbort();

AlarmTimer	abort_timer;
static long	counter=0;

	buf.set(counter++);
	buf += '\0';

	struct maildir_tmpcreate_info createInfo;

	maildir_tmpcreate_init(&createInfo);

	createInfo.maildir=dir;
	createInfo.uniq=(const char *)buf;
	createInfo.msgsize=s;
	createInfo.openmode=0666;

	abort_timer.Set( 24 * 60 * 60 );
	while (!abort_timer.Expired())
	{
		Buffer name_buf;

		name_buf="UMASK";
		const char *um=GetVarStr(name_buf);
		unsigned int umask_val=077;

		sscanf(um, "%o", &umask_val);

		umask_val=umask(umask_val);

		int f=maildir_tmpcreate_fd(&createInfo);
		umask(umask_val);

		if (f >= 0)
		{
			Buffer b;

			b="FLAGS";

			const char *flags=GetVarStr(b);

			tmpname=createInfo.tmpname;
			tmpname += '\0';

			if (flags)
			{
				const char *p=flags;

				while (*p)
				{
					if (strchr("DRSF", *p) == NULL)
					{
						f=0;
						break;
					}
					++p;
				}
			}

			if (flags && *flags)
			{
				newname=createInfo.curname;
				newname += ':';
				newname += '2';
				newname += ',';
				newname += flags;
			}
			else
			{
				newname=createInfo.newname;
			}

			newname += '\0';
			maildir_tmpcreate_free(&createInfo);

			file.fd(f);
			is_open=1;
			maildirRoot=dir;
			maildirRoot += '\0';

			if (maildir_quota_add_start(dir, &quotainfo, s,
						    1, quotap))
			{
				file.fd(-1);
				unlink( (const char *)tmpname );
				is_open=0;
				maildir_deliver_quota_warning(dir,
							      quota_warn_percent,
							      quota_warn_message);
				merr << "maildrop: maildir over quota.\n";
				return (-1);
			}

			maildir_quota_add_end(&quotainfo, s, 1);
			return (0);
		}

		if (errno != EAGAIN)
		{
			merr << "maildrop: " << dir << ": " << strerror(errno)
			     << "\n";
			return -1;
		}

		AlarmSleep	try_again(2);
	}

	merr << "maildrop: time out on maildir directory.\n";
	return (-1);
}
コード例 #2
0
ファイル: deliverquota.c プロジェクト: zixia/wmail
static long deliver(int fdin, const char *dir, long s,
		    int auto_create, int quota_warn_percent, const char *pfix,
		    const char *newquota)
{
	struct maildir_tmpcreate_info createInfo;
	char	buf[BUFSIZ];
	int	n;
	long	ss=0;
	int	fd;

	maildir_tmpcreate_init(&createInfo);

	createInfo.maildir=dir;
	createInfo.uniq=pfix;
	createInfo.msgsize=s;
	createInfo.doordie=1;

	while ((fd=maildir_tmpcreate_fd(&createInfo)) < 0)
	{
		if (errno == ENOENT && auto_create && maildir_mkdir(dir) == 0)
		{
			auto_create=0;
			continue;
		}

		perror(dir);
		exit(EX_TEMPFAIL);
	}

	while ((n=read(fdin, buf, sizeof(buf))) > 0)
	{
	char	*p=buf;

		ss += n;
		while (n)
		{
		int	l;

			if ((l=write(fd, p, n)) < 0)
			{
				close(fd);
				unlink(createInfo.tmpname);
				perror(createInfo.tmpname);
				exit(EX_IOERR);
			}
			p += l;
			n -= l;
		}
	}
	close(fd);
	if (n < 0)
	{
		unlink(createInfo.tmpname);
		perror(createInfo.tmpname);
		exit(EX_IOERR);
	}

	if (s != ss)
	{
		char	*qq;
		struct maildirsize info;

		if (s)	*strrchr(createInfo.newname, ',')=0;
		/* Zap incorrect size */
		qq=malloc(strlen(createInfo.newname)+100);
		if (!qq)
		{
			unlink(createInfo.tmpname);
			perror(createInfo.tmpname);
			exit(EX_OSERR);
		}
		sprintf(qq, "%s,S=%ld", createInfo.newname, ss-s);
		free(createInfo.newname);
		createInfo.newname=qq;

		if (maildirquota_countfolder(dir))
		{
			if (maildir_quota_add_start(dir, &info, ss-s, 1,
						    newquota))
			{
				unlink(createInfo.tmpname);
				printf("Mail quota exceeded.\n");
				exit(EX_NOPERM);
			}
			maildir_quota_add_end(&info, ss-s, 1);
		}
	}

	if (maildir_movetmpnew(createInfo.tmpname, createInfo.newname))
	{
		unlink(createInfo.tmpname);
		perror(createInfo.tmpname);
		exit(EX_IOERR);
	}
	maildir_tmpcreate_free(&createInfo);

	if (quota_warn_percent >= 0)
		maildir_deliver_quota_warning(dir, quota_warn_percent);

	return (ss);
}
コード例 #3
0
ファイル: maildir.C プロジェクト: mcarbonneaux/courier-libs
void	Maildir::MaildirSave()
{
	if (is_open)
	{
		Buffer keywords;

		keywords="KEYWORDS";
		keywords=*GetVar(keywords);
		keywords += '\0';

		const char *keywords_s=keywords;

		while (*keywords_s && *keywords_s == ',')
			++keywords_s;

		if (*keywords_s)
		{
			struct libmail_kwHashtable kwh;
			struct libmail_kwMessage *kwm;

			libmail_kwhInit(&kwh);

			if ((kwm=libmail_kwmCreate()) == NULL)
				throw strerror(errno);

			while (*keywords_s)
			{
				const char *p=keywords_s;

				while (*keywords_s && *keywords_s != ',')
					++keywords_s;

				char *n=new char [keywords_s - p + 1];

				if (!n)
				{
					libmail_kwmDestroy(kwm);
					throw strerror(errno);
				}

				memcpy(n, p, keywords_s - p);
				n[keywords_s - p]=0;

				while (*keywords_s && *keywords_s == ',')
					++keywords_s;

				if (libmail_kwmSetName(&kwh, kwm, n) < 0)
				{
					delete n;
					libmail_kwmDestroy(kwm);
					throw strerror(errno);
				}
				delete n;
			}

			char *tmpkname, *newkname;

			if (maildir_kwSave( (const char *)maildirRoot,
					    strrchr(newname, '/')+1, kwm,
					    &tmpkname, &newkname, 0) < 0)
			{
				libmail_kwmDestroy(kwm);
				throw "maildir_kwSave() failed.";
			}

			libmail_kwmDestroy(kwm);

			if (rename(tmpkname, newkname) < 0)
			{
				/* Maybe the keyword directory needs creating */

				struct stat stat_buf;

				if (stat(maildirRoot, &stat_buf) < 0)
				{
					free(tmpkname);
					free(newkname);
					throw strerror(errno);
				}

				char *keywordDir=strrchr(newkname, '/');

				*keywordDir=0;
				mkdir(newkname, 0700);
				chmod(newkname, stat_buf.st_mode & 0777);
				*keywordDir='/';

				if (rename(tmpkname, newkname) < 0)
				{
					free(tmpkname);
					free(newkname);
					throw strerror(errno);
				}
			}
			free(tmpkname);
			free(newkname);
		}

		Buffer dir;

		if (link( (const char *)tmpname, (const char *)newname) < 0)
		{
			if (errno == EXDEV){
				if(rename((const char *)tmpname, (const char *)newname) < 0)
					throw "rename() failed.";
				is_afs = 1;
			}
			else
			{
				throw "link() failed.";
			}
		}
		dir=newname;
		const char *p=dir;
		const char *q=strrchr(p, '/');

		if (q)
		{
			dir.Length(q-p);
			dir.push((char)0);

#if EXPLICITDIRSYNC
			int syncfd=open(dir, O_RDONLY);

			if (syncfd >= 0)
			{
				fsync(syncfd);
				close(syncfd);
			}
#endif

			dir.Length(q-p);
			dir += "/../";
			dir.push((char)0);

			maildir_deliver_quota_warning(dir, quota_warn_percent,
						      quota_warn_message);
		}
	}
}
コード例 #4
0
ファイル: deliverquota.c プロジェクト: zixia/wmail
int main(int argc, char **argv)
{
	const char *dir;
	struct	stat	stat_buf;
	int	auto_create = 0;
	int	quota_warn_percent = -1;
	int i;
	const char *quota=NULL;

	for (i=1; i<argc; i++)
	{
		if (strcmp(argv[i], "-c") == 0)
		{
			auto_create = 1;
			continue;
		}

		if (strcmp(argv[i], "-w") == 0 && argc - i > 1)
		{
			quota_warn_percent = atoi(argv[i+1]);
			++i;
			continue;
		}
		break;
	}
	if (i >= argc || quota_warn_percent < -1 || quota_warn_percent > 100)
	{
		fprintf(stderr, "Usage: %s [-c] [-w percent] maildir\n",
			argv[0]);
		exit(73);
	}

	dir=argv[i];

	++i;
	if (i < argc)
		quota=argv[i];

	if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
		stat_buf.st_size > 0)
	{
		struct maildirsize info;
		int doquota=maildirquota_countfolder(dir);

		if (doquota &&
		    maildir_quota_add_start(dir, &info, stat_buf.st_size, 1,
					    quota))
		{
			if (quota_warn_percent >= 0)
				maildir_deliver_quota_warning(dir, quota_warn_percent);
			printf("Mail quota exceeded.\n");
			exit(77);
		}
		deliver(0, dir, stat_buf.st_size,
			auto_create, quota_warn_percent, NULL, quota);

		if (doquota)
			maildir_quota_add_end(&info, stat_buf.st_size, 1);
		exit(0);
	}
	deliver(0, dir, 0, auto_create, quota_warn_percent, NULL, quota);
	exit(0);
}