diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /maildir/maildirkeywords2.c | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'maildir/maildirkeywords2.c')
| -rw-r--r-- | maildir/maildirkeywords2.c | 995 | 
1 files changed, 995 insertions, 0 deletions
| diff --git a/maildir/maildirkeywords2.c b/maildir/maildirkeywords2.c new file mode 100644 index 0000000..6923a7a --- /dev/null +++ b/maildir/maildirkeywords2.c @@ -0,0 +1,995 @@ +/* +** Copyright 2003-2007 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#if	HAVE_CONFIG_H +#include	"config.h" +#endif +#include	<stdio.h> +#include	<stdlib.h> +#include	<string.h> +#include	<errno.h> +#include	<ctype.h> + +#include	"maildir/config.h" +#include	"maildir/maildircreate.h" +#include	"maildir/maildirmisc.h" +#include	"maildir/maildirwatch.h" +#include	"numlib/numlib.h" + +#if	HAVE_UNISTD_H +#include	<unistd.h> +#endif +#include	"maildirkeywords.h" +#if HAVE_DIRENT_H +#include <dirent.h> +#define NAMLEN(dirent) strlen((dirent)->d_name) +#else +#define dirent direct +#define NAMLEN(dirent) (dirent)->d_namlen +#if HAVE_SYS_NDIR_H +#include <sys/ndir.h> +#endif +#if HAVE_SYS_DIR_H +#include <sys/dir.h> +#endif +#if HAVE_NDIR_H +#include <ndir.h> +#endif +#endif + + +int libmail_kwEnabled=1; + +struct keywordUpdateInfo { +	size_t highestN; +	size_t highestT; +	size_t totalCnt; +	int foundNewest; +}; + +static void scan_updates(const char *dir, +			 time_t t, +			 time_t tn, +			 struct maildir_kwReadInfo *info, +			 struct keywordUpdateInfo **updateInfo); + +static void read_updates(const char *dir, +			 struct maildir_kwReadInfo *info, +			 struct keywordUpdateInfo *updateInfo); + +static void purge_old_updates(const char *dir, +			      time_t tn, +			      struct maildir_kwReadInfo *info, +			      struct keywordUpdateInfo *updateInfo); + +static int save_updated_keywords(const char *maildir, const char *kwname, +				 struct maildir_kwReadInfo *info, +				 struct keywordUpdateInfo *updateInfo); + +static void doReadKeywords2(const char *maildir, const char *dir, +			    struct maildir_kwReadInfo *rki); + + +struct readLine { +	char *lineBuf; +	size_t lineBufSize; +	int errflag; +}; + +static void rl_init(struct readLine *p) +{ +	p->lineBuf=NULL; +	p->lineBufSize=0; +	p->errflag=0; +} + +static void rl_free(struct readLine *p) +{ +	if (p->lineBuf) +		free(p->lineBuf); +} + +static char *rl_read(struct readLine *p, FILE *f) +{ +	size_t n=0; +	int ch; + +	for (;;) +	{ +		if (n >= p->lineBufSize) +		{ +			size_t o= n + 1024; +			char *b= p->lineBuf ? realloc(p->lineBuf, o):malloc(o); + +			if (!b) +			{ +				p->errflag=1; +				return NULL; +			} + +			p->lineBuf=b; +			p->lineBufSize=o; +		} + +		if ((ch=getc(f)) == EOF || ch == '\n') +			break; +		p->lineBuf[n++]=(char)ch; +	} + +	p->lineBuf[n]=0; + +	return n == 0 && ch == EOF ? NULL:p->lineBuf; +} + +int maildir_kwRead(const char *maildir, +			  struct maildir_kwReadInfo *rki) +{ +	char *p=malloc(strlen(maildir)+sizeof("/" KEYWORDDIR)); + +	if (!p) +		return -1; + +	strcat(strcpy(p, maildir), "/" KEYWORDDIR); + +	rki->errorOccured=0; +	doReadKeywords2(maildir, p, rki); +	free(p); + +	return rki->errorOccured; +} + +static void doReadKeywords2(const char *maildir, const char *dir, +			   struct maildir_kwReadInfo *rki) +{ +	FILE *fp; +	char *kwname=malloc(strlen(dir)+sizeof("/:list")); +	struct keywordUpdateInfo *updateInfo; + +	time_t t=time(NULL); +	time_t tn=t/300; + +	rki->updateNeeded=0; +	rki->tryagain=0; + +	if (!kwname) +	{ +		rki->errorOccured= -1; +		return; +	} + +	strcat(strcpy(kwname, dir), "/:list"); + +	fp=fopen(kwname, "r"); + +	if (!fp) /* Maybe the keyword directory needs creating? */ +	{ +		struct stat stat_buf; + +		mkdir(dir, 0700); + +		/* Give it same mode as the maildir */ + +		if (stat(maildir, &stat_buf) == 0) +			chmod(dir, stat_buf.st_mode & 0777); +	} + +	/* +	** If keywords are disabled, we still need to create the keyword +	** directory, otherwise FAM-based IDLE will not work. +	*/ + +	if (!libmail_kwEnabled) +	{ +		if (fp) +			fclose(fp); +		free(kwname); +		return; +	} + +	if (fp && maildir_kwImport(fp, rki)) +		rki->updateNeeded=1; +	if (fp) +		fclose(fp); + +	updateInfo=malloc(sizeof(struct keywordUpdateInfo) +			  *( 1+(*rki->getMessageCount)(rki->voidarg))); + +	if (!updateInfo) +	{ +		free(kwname); +		return; +	} + +	scan_updates(dir, t, tn, rki, &updateInfo); +	read_updates(dir, rki, updateInfo); + +	if (!rki->tryagain && !rki->errorOccured) +	{ +		if (save_updated_keywords(maildir, kwname, rki, updateInfo) +		    == 0 && !rki->errorOccured) +			purge_old_updates(dir, tn, rki, updateInfo); +	} + +	free(updateInfo); +	free(kwname); +} + +int maildir_kwImport(FILE *fp, struct maildir_kwReadInfo *rki) +{ +	struct keywordIndex { +		struct keywordIndex *next; +		struct libmail_keywordEntry *kw; +	} *firstKw=NULL, *lastKw=NULL, **index; +	size_t numKw=0; +	struct libmail_kwMessage *tmpMsg; +	char *p; +	int rc=0; + +	struct readLine rl; + +	if ((tmpMsg=libmail_kwmCreate()) == NULL) +	{ +		rki->errorOccured=-1; +		return 0; +	} + +	rl_init(&rl); + +	while ((p=rl_read(&rl, fp)) != NULL && *p) +	{ +		struct keywordIndex *ki=malloc(sizeof(*firstKw)); + +		if (!ki) +		{ +			rki->errorOccured=-1; +			rl_free(&rl); +			libmail_kwmDestroy(tmpMsg); +			return 0; +		} + +		if (lastKw) +			lastKw->next=ki; +		else +			firstKw=ki; + +		lastKw=ki; +		ki->next=NULL; +		++numKw; + +		ki->kw=libmail_kweFind((*rki->getKeywordHashtable) +					(rki->voidarg), p, 1); +		if (libmail_kwmSet(tmpMsg, ki->kw) < 0) +		{ +			rki->errorOccured= -1; +			break; +		} +	} + +	if (rki->errorOccured || +	    (index=malloc(sizeof(*firstKw)*(numKw+1))) == NULL) +	{ +		while ((lastKw=firstKw) != NULL) +		{ +			firstKw=firstKw->next; +			free(lastKw); +		} +		libmail_kwmDestroy(tmpMsg); +		rki->errorOccured= -1; +		rl_free(&rl); +		return 0; +	} + +	numKw=0; + +	while (firstKw) +	{ +		index[numKw]=firstKw; +		++numKw; +		firstKw=firstKw->next; +	} +	index[numKw]=0; + +	if (p) +		while ((p=rl_read(&rl, fp)) != NULL) +		{ +			char *q=strchr(p, ':'); +			struct libmail_kwMessage **i; +			size_t l; +			size_t n; + +			if (!q) +			{ +				rc=1; +				continue; /* Crap */ +			} + +			*q++=0; + +			i= (*rki->findMessageByFilename)(p, 0, &n, +							 rki->voidarg); + +			if (!i) +			{ +				rc=1; +				continue; /* Stale data */ +			} + +			if (*i) /* Already have it */ +				libmail_kwmDestroy(*i); +			(*i)=NULL; + +			i=NULL; + +			while ((q=strtok(q, " ")) != NULL) +			{ +				l=atoi(q); +				q=NULL; + +				if (l < numKw) +				{ +					if (!i) +						i= (*rki-> +						    findMessageByFilename) +							(p, 1, &n, +							 rki->voidarg); +					/* Autocreate it */ + +					if (*i == NULL) /* ENOMEM */ +					{ +						rc= -1; +						break; +					} + +					if (libmail_kwmSet(*i, index[l]->kw) +					    < 0) +						rki->errorOccured= -1; +				} +			} +		} + +	rl_free(&rl); +	for (numKw=0; index[numKw]; numKw++) +		free(index[numKw]); + +	free(index); +	libmail_kwmDestroy(tmpMsg); +	return rc; +} + +/* See the README */ + +static void scan_updates(const char *dir, +			 time_t t, +			 time_t tn, +			 struct maildir_kwReadInfo *info, +			 struct keywordUpdateInfo **updateInfo) +{ +	DIR *dirp; +	struct dirent *de; +	unsigned long i; + +	size_t n= (*info->getMessageCount)(info->voidarg); + +	for (i=0; i<n; i++) +	{ +		(*updateInfo)[i].highestN=0; +		(*updateInfo)[i].highestT=0; +		(*updateInfo)[i].totalCnt=0; +		(*updateInfo)[i].foundNewest=0; +	} + +	dirp=opendir(dir); +	while (dirp && (de=readdir(dirp)) != NULL) +	{ +		struct libmail_kwMessage **i; +		unsigned long x=0; +		char *p, *q; +		size_t in; + +		if (de->d_name[0] == ':') +			continue; + +		if (de->d_name[0] != '.') +			i=(*info->findMessageByFilename) +				(de->d_name, 0, &in, info->voidarg); + +		else if ((x=libmail_atotime_t(de->d_name+1)) == 0) +		{ +			if (strncmp(de->d_name, ".tmp.", 5) == 0) +			{ +				if ((x=libmail_atotime_t(de->d_name+5)) != 0 +				    && x >= t - 120) +					continue; /* New scratch file */ + + +				p=malloc(strlen(dir)+strlen(de->d_name)+2); + +				if (!p) +				{ +					closedir(dirp); +					info->errorOccured= -1; +					return; +				} + +				strcat(strcat(strcpy(p, dir), "/"), +				       de->d_name); +				unlink(p); +				free(p); +			} +			continue; +		} +		else +		{ +			const char *p=strchr(de->d_name+1, '.'); + +			if (!p) +				continue; + +			i=(*info->findMessageByFilename) +				(p+1, 0, &in, info->voidarg); +		} + +		p=malloc(strlen(dir)+strlen(de->d_name)+2); + +		if (!p) +		{ +			closedir(dirp); +			info->errorOccured= -1; +			return; +		} + +		strcat(strcat(strcpy(p, dir), "/"), de->d_name); + +		if (!i) +		{ +			struct stat stat_buf; + +			if (stat(p, &stat_buf) == 0 && +			    stat_buf.st_mtime < t - 15 * 60) +				unlink(p); +			free(p); +			continue; +		} +		free(p); + + +		if (in >= n) +		{ +			/* libmail_kwgReadMaildir autocrerate */ +			 +			struct keywordUpdateInfo *u= +				realloc(*updateInfo, +					sizeof(**updateInfo) * (in+1)); + +			if (!u) +			{ +				closedir(dirp); +				info->errorOccured= -1; +				return; +			} + +			*updateInfo=u; + +			while (n <= in) +			{ + +				(*updateInfo)[n].highestN=0; +				(*updateInfo)[n].highestT=0; +				(*updateInfo)[n].totalCnt=0; +				(*updateInfo)[n].foundNewest=0; +				++n; +			} +		} + + +		if (de->d_name[0] != '.') +		{ +			x=tn+1; + +			(*updateInfo)[in].foundNewest=1; +		} + +		++(*updateInfo)[in].totalCnt; + +		if (x >= tn) +		{ +			if (x > (*updateInfo)[in].highestT) +				(*updateInfo)[in].highestT=x; +		} +		else if ((*updateInfo)[in].highestN < x) +		{ +			if ((*updateInfo)[in].highestN > 0) +			{ +				char b[NUMBUFSIZE]; +				char *r; + +				libmail_str_size_t((*updateInfo)[in].highestN, b); + +				r=de->d_name; +				if (*r == '.') +					r=strchr(r+1, '.')+1; + +				q=malloc(strlen(dir)+strlen(r)+ +					 strlen(b)+4); + +				if (!q) +				{ +					closedir(dirp); +					info->errorOccured= -1; +					return; +				} + +				sprintf(q, "%s/.%s.%s", dir, b, r); +				unlink(q); +				free(q); +			} + +			(*updateInfo)[in].highestN=x; +		} +	} + +	if (dirp) +		closedir(dirp); +} + +static void read_updates(const char *dir, +			 struct maildir_kwReadInfo *info, +			 struct keywordUpdateInfo *updateInfo) +{ +	unsigned long i; +	size_t msgCnt= (*info->getMessageCount)(info->voidarg); +	struct readLine rl; + +	struct libmail_kwHashtable *h= +		(*info->getKeywordHashtable)(info->voidarg); + +	rl_init(&rl); +	for (i=0; i<msgCnt; i++) +	{ +		size_t n=updateInfo[i].highestN; +		char *p, *q; +		char b[NUMBUFSIZE]; +		FILE *fp; +		struct libmail_kwMessage *km, **oldKm; +		const char *fn; + +		if (n < updateInfo[i].highestT) +			n=updateInfo[i].highestT; + +		if (n == 0) +			continue; + +		libmail_str_size_t(n, b); + +		fn= (*info->getMessageFilename)(i, info->voidarg); + +		if (!fn) +			continue; /* Shouldn't happen */ + +		p=malloc(strlen(dir)+strlen(b)+strlen(fn)+4); + +		if (!p) +		{ +			info->errorOccured= -1; +			rl_free(&rl); +			return; +		} + +		if (updateInfo[i].foundNewest) +			sprintf(p, "%s/%s", dir, fn); +		else +			sprintf(p, "%s/.%s.%s", dir, b, fn); + + +		q=strrchr(strrchr(p, '/'), MDIRSEP[0]); +		if (q) +			*q=0; + +		fp=fopen(p, "r"); +		free(p); + +		if (!fp) +		{ +			if (errno == ENOENT) +			{ +				info->tryagain=1; +				rl_free(&rl); +				return; +			} + +			continue; +		} + +		if ((km=libmail_kwmCreate()) == NULL) +		{ +			fclose(fp); +			info->errorOccured= -1; +			rl_free(&rl); +			return; +		} + +		while ((p=rl_read(&rl, fp)) != NULL && *p) +			if (libmail_kwmSetName(h, km, p) < 0) +			{ +				fclose(fp); +				info->errorOccured= -1; +				rl_free(&rl); +				return; +			} + +		if (km->firstEntry == NULL) +		{ +			oldKm= (*info->findMessageByIndex)(i, +							   0, info->voidarg); +			if (oldKm && *oldKm) +			{ +				info->updateNeeded=1; +				libmail_kwmDestroy(*oldKm); +				*oldKm=NULL; +			} +			libmail_kwmDestroy(km); +		} +		else +		{ +			oldKm= (*info->findMessageByIndex)(i, 1, +							   info->voidarg); + +			if (oldKm && *oldKm == NULL) +			{ +				info->updateNeeded=1; +				(*info->updateKeywords)(i, km, info->voidarg); +			} +			else if (!oldKm /* Shouldn't happen */ +			    || libmail_kwmCmp(*oldKm, km) == 0) +			{ +				libmail_kwmDestroy(km); +			} +			else +			{ +				info->updateNeeded=1; +				(*info->updateKeywords)(i, km, info->voidarg); +			} +		} + +		fclose(fp); +	} +	rl_free(&rl); +} + +struct saveUpdateInfo { +	FILE *fp; +	unsigned long counter; +}; + +static int saveKeywordList(struct libmail_keywordEntry *ke, +			   void *vp) +{ +	struct saveUpdateInfo *sui=(struct saveUpdateInfo *)vp; + +	fprintf(sui->fp, "%s\n", keywordName(ke)); + +	ke->u.userNum= sui->counter; + +	++sui->counter; +	return 0; +} + +int maildir_kwExport(FILE *fp, struct maildir_kwReadInfo *info) +{ +	struct saveUpdateInfo sui; +	size_t i, n; + +	sui.fp=fp; +	sui.counter=0; +	libmail_kwEnumerate((*info->getKeywordHashtable)(info->voidarg), +			 saveKeywordList, &sui); + +	if (sui.counter == 0) /* No keywords set for any message */ +		return 0; + +	fprintf(fp, "\n"); + +	n= (*info->getMessageCount)(info->voidarg); + +	for (i=0; i<n; i++) +	{ +		const char *p; + +		struct libmail_kwMessage **km= +			(*info->findMessageByIndex)(i, 0, info->voidarg); +		struct libmail_kwMessageEntry *kme; + +		if (!km || !*km || (*km)->firstEntry == NULL) +			continue; + +		for (p= (*info->getMessageFilename)(i, info->voidarg); +		     *p && *p != MDIRSEP[0]; p++) +			putc(*p, fp); + +		putc(':', fp); +		p=""; + +		for (kme=(*km)->firstEntry; kme; kme=kme->next) +		{ +			fprintf(fp, "%s%lu", p, kme->libmail_keywordEntryPtr +				->u.userNum); +			p=" "; +		} +		fprintf(fp, "\n"); +	} + +	return 1; +} + +static int save_updated_keywords(const char *maildir, const char *kwname, +				 struct maildir_kwReadInfo *info, +				 struct keywordUpdateInfo *updateInfo) +{ +	struct maildir_tmpcreate_info createInfo; +	FILE *fp; + +	if (!info->updateNeeded) +		return 0; + +	maildir_tmpcreate_init(&createInfo); + +	createInfo.maildir=maildir; +	createInfo.hostname=getenv("HOSTNAME"); +	createInfo.doordie=1; + +	if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL) +	{ +		perror("maildir_tmpcreate_fp"); +		return -1; +	} + +	if (maildir_kwExport(fp, info) == 0) +	{ +		fclose(fp); +		unlink(createInfo.tmpname); +		maildir_tmpcreate_free(&createInfo); +		unlink(kwname); +		return 0; +	} +	if (fflush(fp) < 0 || ferror(fp)) +	{ +		fclose(fp); +		unlink(createInfo.tmpname); +		perror(createInfo.tmpname); +		maildir_tmpcreate_free(&createInfo); +		return -1; +	} +	fclose(fp); + +	if (rename(createInfo.tmpname, kwname)) +	{ +		perror(createInfo.tmpname); +		unlink(createInfo.tmpname); +		perror(createInfo.tmpname); +		maildir_tmpcreate_free(&createInfo); +		return -1; +	} +	maildir_tmpcreate_free(&createInfo); +	return 0; +} + +static void purge_old_updates(const char *dir, +			      time_t tn, +			      struct maildir_kwReadInfo *info, +			      struct keywordUpdateInfo *updateInfo) +{ +	size_t i; + +	time_t x; + +	size_t n= (*info->getMessageCount)(info->voidarg); + +	for (i=0; i<n; i++) +	{ +		char *p, *q, *c; +		char b[NUMBUFSIZE]; + +		const char *fn= (*info->getMessageFilename)(i, info->voidarg); + +		if (!fn) +			continue; /* Shouldn't happen */ + +		if (updateInfo[i].foundNewest) +		{ +			size_t l; + +			x=tn+1; + +			libmail_str_size_t(x, b); + +			l=strlen(dir)+strlen(b)+strlen(fn)+4; + +			p=malloc(l); +			if (!p) +			{ +				info->errorOccured= -1; +				return; +			} + +			q=malloc(l); +			if (!q) +			{ +				free(p); +				info->errorOccured= -1; +				return; +			} + +			sprintf(p, "%s/%s", dir, fn); + +			sprintf(q, "%s/.%s.%s", dir, b, fn); + + +			c=strrchr(strrchr(p, '/'), MDIRSEP[0]); + +			if (c) *c=0; +			c=strrchr(strrchr(q, '/'), MDIRSEP[0]); + +			if (c) *c=0; + +			rename(p, q); +			free(q); +			free(p); +			continue; +		} + +		if (! (updateInfo[i].totalCnt == 1 && +		       updateInfo[i].highestN)) +			continue; + +		libmail_str_size_t(updateInfo[i].highestN, b); + +		p=malloc(strlen(dir)+strlen(b)+strlen(fn)+4); + +		if (!p) +		{ +			info->errorOccured= -1; +			return; +		} + +		sprintf(p, "%s/.%s.%s", dir, b, fn); + +		q=strrchr(strrchr(p, '/'), MDIRSEP[0]); +		if (q) *q=0; +		unlink(p); +		free(p); +	} +} + + +/***************/ + +static int maildir_kwSaveCommon(const char *maildir, +				const char *filename, +				struct libmail_kwMessage *newKeyword, +				const char **newKeywordArray, +				char **tmpname, +				char **newname, +				int tryAtomic); + +int maildir_kwSave(const char *maildir, +		   const char *filename, +		   struct libmail_kwMessage *newKeyword, +		   char **tmpname, +		   char **newname, +		   int tryAtomic) +{ +	return maildir_kwSaveCommon(maildir, filename, newKeyword, NULL, +				    tmpname, newname, tryAtomic); +} + +int maildir_kwSaveArray(const char *maildir, +			const char *filename, +			const char **flags, +			char **tmpname, +			char **newname, +			int tryAtomic) +{ +	return maildir_kwSaveCommon(maildir, filename, NULL, flags, +				    tmpname, newname, tryAtomic); +} + +static int maildir_kwSaveCommon(const char *maildir, +				const char *filename, +				struct libmail_kwMessage *newKeyword, +				const char **newKeywordArray, +				char **tmpname, +				char **newname, +				int tryAtomic) +{ +	struct maildir_tmpcreate_info createInfo; +	FILE *fp; +	char *n=malloc(strlen(maildir)+strlen(filename)+10+ +		       sizeof(KEYWORDDIR)), *p; +	struct libmail_kwMessageEntry *kme; + +	if (!n) +		return -1; + +	strcat(strcat(strcpy(n, maildir), +		      "/" KEYWORDDIR "/"), filename); + +	p=strrchr(strrchr(n, '/'), MDIRSEP[0]); +	if (p) +		*p=0; + +	 +	maildir_tmpcreate_init(&createInfo); + +	createInfo.maildir=maildir; +	createInfo.msgsize=0; +	createInfo.hostname=getenv("HOSTNAME"); +	createInfo.doordie=1; + +	if ((fp=maildir_tmpcreate_fp(&createInfo)) == NULL) +	{ +		free(n); +		return -1; +	} + +	if (newKeywordArray) +	{ +		size_t i; + +		for (i=0; newKeywordArray[i]; i++) +			fprintf(fp, "%s\n", newKeywordArray[i]); +	} +	else for (kme=newKeyword ? newKeyword->firstEntry:NULL; +		  kme; kme=kme->next) +		fprintf(fp, "%s\n", keywordName(kme->libmail_keywordEntryPtr)); + +	errno=EIO; + +	if (fflush(fp) < 0 || ferror(fp)) +	{ +		fclose(fp); +		free(n); +		return -1; +	} + +	fclose(fp); + +	*tmpname=createInfo.tmpname; +	createInfo.tmpname=NULL; +	*newname=n; +	maildir_tmpcreate_free(&createInfo); + +	if (tryAtomic) +	{ +		char timeBuf[NUMBUFSIZE]; + +		char *n=malloc(strlen(*tmpname) +			       + sizeof(KEYWORDDIR) + NUMBUFSIZE+10); + +		if (!n) +		{ +			free(*tmpname); +			free(*newname); +			return -1; +		} + +		strcat(strcat(strcat(strcpy(n, maildir), +				     "/" KEYWORDDIR "/.tmp."), +			      libmail_str_time_t(time(NULL), timeBuf)), +		       strrchr( *tmpname, '/')+1); + + +		if (rename( *tmpname, n) < 0) +		{ +			free(n); +			free(*tmpname); +			free(*newname); +			return -1; +		} + +		free (*tmpname); +		*tmpname=n; +	} +	return 0; +} | 
