shithub: riscv

Download patch

ref: fd78f6722efb439b9dd640886096f8f2b3c2f8f0
parent: 00fbdd622aeb6ab3665a9970d7acb6bdd225028b
author: cinap_lenrek <[email protected]>
date: Sat Apr 8 18:50:17 EDT 2017

upas/common: deliver mail to mdir as .tmp file and rename after it has been fully written

theres a race condition when mail delivery to mdir is slow,
then upas/fs sees partial mail file and caches the truncated
file size.

to avoid this, delivery will create the new mail file with
the .tmp extension (which is ignored by upas/fs) and after
everything has been written, rename it to the final name.

--- a/sys/src/cmd/upas/common/common.h
+++ b/sys/src/cmd/upas/common/common.h
@@ -41,7 +41,7 @@
 /* folder.c */
 Biobuf	*openfolder(char*, long);
 int	closefolder(Biobuf*);
-int	appendfolder(Biobuf*, char*, long*, int);
+int	appendfolder(Biobuf*, char*, int);
 int	fappendfolder(char*, long, char *, int);
 int	fappendfile(char*, char*, int);
 char*	foldername(char*, char*, char*);
--- a/sys/src/cmd/upas/common/folder.c
+++ b/sys/src/cmd/upas/common/folder.c
@@ -12,6 +12,7 @@
 	int	type;
 	Biobuf	*out;
 	Mlock	*l;
+	long	t;
 };
 static Folder ftab[5];
 
@@ -44,12 +45,12 @@
 	r = 0;
 	if(f->l)
 		sysunlock(f->l);
-	if(f->out)
+	if(f->out){
 		r |= Bterm(f->out);
-	if(f->ofd > 0){
-		close(f->ofd);
 		free(f->out);
 	}
+	if(f->ofd >= 0)
+		close(f->ofd);
 	memset(f, 0, sizeof *f);
 	return r;
 }
@@ -59,7 +60,7 @@
 {
 	Folder *f;
 
-	f = getfolder(0);
+	f = getfolder(nil);
 	f->l = syslock(s);		/* traditional botch: ignore failure */
 	if((f->ofd = open(s, OWRITE)) == -1)
 	if((f->ofd = create(s, OWRITE|OEXCL, DMAPPEND|0600)) == -1){
@@ -79,13 +80,13 @@
 static Biobuf*
 mdiropen(char *s, long t)
 {
-	char buf[64];
-	long i;
+	char buf[Pathlen];
 	Folder *f;
+	int i;
 
-	f = getfolder(0);
+	f = getfolder(nil);
 	for(i = 0; i < 100; i++){
-		snprint(buf, sizeof buf, "%s/%lud.%.2ld", s, t, i);
+		snprint(buf, sizeof buf, "%s/%lud.%.2d.tmp", s, t, i);
 		if((f->ofd = create(buf, OWRITE|OEXCL, DMAPPEND|0660)) != -1)
 			goto found;
 	}
@@ -96,6 +97,7 @@
 	f->out = malloc(sizeof *f->out);
 	Binit(f->out, f->ofd, OWRITE);
 	f->type = Mdir;
+	f->t = t;
 	return f->out;
 }
 
@@ -122,32 +124,31 @@
 }
 
 int
-renamefolder(Biobuf *b, long t)
+closefolder(Biobuf *b)
 {
 	char buf[32];
-	int i;
-	Dir d;
 	Folder *f;
+	Dir d;
+	int i;
 
+	if(b == nil)
+		return 0;
 	f = getfolder(b);
 	if(f->type != Mdir)
-		return 0;
-	for(i = 0; i < 100; i++){
-		nulldir(&d);
-		snprint(buf, sizeof buf, "%lud.%.2d", t, i);
-		d.name = buf;
-		if(dirfwstat(Bfildes(b), &d) > 0)
-			return 0;
+		return putfolder(f);
+	if(Bflush(b) == 0){
+		for(i = 0; i < 100; i++){
+			nulldir(&d);
+			snprint(buf, sizeof buf, "%lud.%.2d", f->t, i);
+			d.name = buf;
+			if(dirfwstat(f->ofd, &d) > 0)
+				return putfolder(f);
+		}
 	}
+	putfolder(f);
 	return -1;
 }
 
-int
-closefolder(Biobuf *b)
-{
-	return putfolder(getfolder(b));
-}
-
 /*
  * escape "From " at the beginning of a line;
  * translate \r\n to \n for imap
@@ -181,7 +182,7 @@
 }
 
 int
-appendfolder(Biobuf *b, char *addr, long *t, int fd)
+appendfolder(Biobuf *b, char *addr, int fd)
 {
 	char *s;
 	int r;
@@ -194,9 +195,9 @@
 	Binit(&bin, fd, OREAD);
 	s = Brdstr(&bin, '\n', 0);
 	if(!s || strncmp(s, "From ", 5))
-		Bprint(f->out, "From %s %.28s\n", addr, ctime(*t));
+		Bprint(f->out, "From %s %.28s\n", addr, ctime(f->t));
 	else if(fromtotm(s, &tm) >= 0)
-		*t = tm2sec(&tm);
+		f->t = tm2sec(&tm);
 	if(s)
 		Bwrite(f->out, s, strlen(s));
 	free(s);
@@ -207,16 +208,13 @@
 int
 fappendfolder(char *addr, long t, char *s, int fd)
 {
-	long t0, r;
 	Biobuf *b;
+	int r;
 
 	b = openfolder(s, t);
 	if(b == nil)
 		return -1;
-	t0 = t;
-	r = appendfolder(b, addr, &t, fd);
-	if(t != t0)
-		renamefolder(b, t);
+	r = appendfolder(b, addr, fd);
 	r |= closefolder(b);
 	return r;
 }