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;
}