ref: 508b796b2719e6c8275a2a1b737c9798d380d25f
parent: 163dccbac04a3c9ab132005ebb4a96a0e0baec0b
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Mar 14 19:06:39 EDT 2017
upas/fs: fix more locking bugs, remove debugging clutter, remove planb mbox code
--- a/sys/src/cmd/upas/fs/fs.c
+++ b/sys/src/cmd/upas/fs/fs.c
@@ -173,31 +173,6 @@
}
}
-static void
-sanefid(Fid *f)
-{
- if(f->m == 0)
- return;
- if(f->mtop){
- sanemsg(f->mtop);
- assert(f->mtop->refs > 0);
- }
- sanemsg(f->m);
- if(f->m)
- if(Topmsg(f->mb, f->m))
- assert(f->m->refs > 0);
-}
-
-void
-sanefids(void)
-{
- Fid *f;
-
- for(f = fids; f; f = f->next)
- if(f->busy)
- sanefid(f);
-}
-
static int
Afmt(Fmt *f)
{
@@ -427,7 +402,7 @@
}
if(mboxfile != nil)
- if(err = newmbox(mboxfile, "mbox", 0, 0))
+ if(err = newmbox(mboxfile, "mbox", 0, nil))
sysfatal("opening %s: %s", mboxfile, err);
switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG|RFREND)){
@@ -856,18 +831,19 @@
return nil;
nf->busy = 1;
nf->open = 0;
- if(nf->mb = f->mb)
+ nf->mb = f->mb;
+ if(nf->mb){
+ qlock(nf->mb);
mboxincref(nf->mb);
+ }
if(nf->m = f->m)
msgincref(gettopmsg(nf->mb, nf->m));
- if(nf->mtop = f->mtop){
- qlock(nf->mb);
+ if(nf->mtop = f->mtop)
msgincref(nf->mtop);
+ nf->qid = f->qid;
+ if(nf->mb){
qunlock(nf->mb);
}
- nf->qid = f->qid;
-sanefid(nf);
-sanefid(f);
return nf;
}
@@ -889,21 +865,18 @@
{
char *rv, *p;
int t, t1;
- Mailbox *omb, *mb;
+ Mailbox *mb;
Hash *h;
t = FILE(f->qid.path);
rv = Enotexist;
- omb = f->mb;
- if(omb)
- qlock(omb);
- else
- qlock(&mbllock);
+ qlock(&mbllock);
+ if(f->mb)
+ qlock(f->mb);
/* this must catch everything except . and .. */
retry:
-sanefid(f);
t1 = FILE(f->qid.path);
if((t1 == Qmbox || t1 == Qdir) && *name >= 'a' && *name <= 'z'){
h = hlook(f->qid.path, "xxx"); /* sleezy speedup */
@@ -915,8 +888,12 @@
if(h != nil){
if(f->m)
msgdecref(f->mb, gettopmsg(f->mb, f->m));
- if(f->mb && f->mb != h->mb)
+ if(f->mb && f->mb != h->mb){
+ qunlock(f->mb);
mboxdecref(f->mb);
+ }
+ if(h->mb && h->mb != f->mb)
+ qlock(h->mb);
f->mb = h->mb;
f->m = h->m;
if(f->m)
@@ -923,7 +900,7 @@
msgincref(gettopmsg(f->mb, f->m));
switch(t){
case Qtop:
- if(f->mb != nil)
+ if(f->mb)
mboxincref(f->mb);
break;
case Qmbox:
@@ -936,7 +913,6 @@
f->qid = h->qid;
if(t1 < Qmax)
f->qid.path = PATH(f->m->id, t1); /* sleezy speedup */
-sanefid(f);
rv = nil;
}else if((p = strchr(name, '.')) != nil && *name != '.'){
*p = 0;
@@ -943,10 +919,10 @@
goto retry;
}
- if(omb)
- qunlock(omb);
- else
- qunlock(&mbllock);
+ if(f->mb)
+ qunlock(f->mb);
+ qunlock(&mbllock);
+
if(rv == nil)
return rv;
@@ -967,9 +943,9 @@
f->qid.path = PATH(0, Qtop);
f->qid.type = QTDIR;
f->qid.vers = 0;
- qlock(&mbllock);
mb = f->mb;
f->mb = nil;
+ qlock(&mbllock);
mboxdecref(mb);
qunlock(&mbllock);
break;
@@ -1003,7 +979,6 @@
char *rv;
int i;
-sanefid(f);
if(f->open)
return Eisopen;
@@ -1038,7 +1013,6 @@
/* we only error out if no walk */
if(i > 0)
rv = nil;
-sanefid(f);
return rv;
}
@@ -1056,10 +1030,12 @@
/* make sure we've decoded */
if(file == Qbody){
+ qlock(f->mb);
cachebody(f->mb, f->m);
decode(f->m);
convert(f->m);
putcache(f->mb, f->m);
+ qunlock(f->mb);
}
rhdr.iounit = 0;
@@ -1082,6 +1058,8 @@
long pos;
Mailbox *mb;
+ qlock(&mbllock);
+
n = 0;
pos = 0;
mkstat(&d, nil, nil, Qctl);
@@ -1088,7 +1066,7 @@
m = convD2M(&d, &buf[n], blen);
if(off <= pos){
if(m <= BIT16SZ || m > cnt)
- return 0;
+ goto out;
n += m;
cnt -= m;
}
@@ -1095,7 +1073,9 @@
pos += m;
for(mb = mbl; mb != nil; mb = mb->next){
+ qlock(mb);
mkstat(&d, mb, nil, Qmbox);
+ qunlock(mb);
m = convD2M(&d, &buf[n], blen - n);
if(off <= pos){
if(m <= BIT16SZ || m > cnt)
@@ -1105,6 +1085,8 @@
}
pos += m;
}
+out:
+ qlock(&mbllock);
return n;
}
@@ -1116,6 +1098,10 @@
long pos;
Message *msg;
+ qlock(f->mb);
+ if(off == 0)
+ syncmbox(f->mb, 1);
+
n = 0;
if(f->mb->ctl){
mkstat(&d, f->mb, nil, Qmboxctl);
@@ -1123,7 +1109,7 @@
if(off == 0){
if(m <= BIT16SZ || m > cnt){
f->fptr = nil;
- return 0;
+ goto out;
}
n += m;
cnt -= m;
@@ -1160,7 +1146,8 @@
f->foff = pos;
f->fptr = msg;
f->fvers = f->mb->vers;
-
+out:
+ qunlock(f->mb);
return n;
}
@@ -1172,6 +1159,7 @@
long pos;
Message *msg;
+ qlock(f->mb);
n = 0;
pos = 0;
for(i = 0; i < Qmax; i++){
@@ -1179,7 +1167,7 @@
m = convD2M(&d, &buf[n], blen - n);
if(off <= pos){
if(m <= BIT16SZ || m > cnt)
- return n;
+ goto out;
n += m;
cnt -= m;
}
@@ -1196,7 +1184,8 @@
}
pos += m;
}
-
+out:
+ qunlock(f->mb);
return n;
}
@@ -1223,20 +1212,13 @@
cnt = messagesize - IOHDRSZ;
rhdr.data = (char*)mbuf;
-sanefid(f);
t = FILE(f->qid.path);
if(f->qid.type & QTDIR){
- if(t == Qtop){
- qlock(&mbllock);
+ if(t == Qtop)
n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
- qunlock(&mbllock);
- }else if(t == Qmbox) {
- qlock(f->mb);
- if(off == 0)
- syncmbox(f->mb, 1);
+ else if(t == Qmbox)
n = readmboxdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
- qunlock(f->mb);
- }else if(t == Qmboxctl)
+ else if(t == Qmboxctl)
n = 0;
else
n = readmsgdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
@@ -1318,7 +1300,6 @@
t = FILE(f->qid.path);
rhdr.count = thdr.count;
- sanefid(f);
if(thdr.count == 0)
return Ebadctl;
if(thdr.data[thdr.count - 1] == '\n')
@@ -1344,7 +1325,7 @@
flags = 0;
if(strcmp(argv[0], "create") == 0)
flags |= DMcreate;
- return newmbox(file, argv[2], flags, 0);
+ return newmbox(file, argv[2], flags, nil);
}
if(strcmp(argv[0], "close") == 0){
if(argc < 2)
@@ -1383,10 +1364,8 @@
return Ebadargs;
for(; *argv; argv++){
mboxpathbuf(file, sizeof file, getlog(), *argv);
- if(err = newmbox(file, nil, 0, 0))
+ if(err = newmbox(file, nil, 0, nil))
return err;
-// if(!mb->remove)
-// return "remove not implemented";
if(err = removembox(file, flags))
return err;
}
@@ -1437,23 +1416,22 @@
{
Mailbox *mb;
-sanefid(f);
f->busy = 1;
/* coherence(); */
f->fid = -1;
f->open = 0;
mb = f->mb;
- if(mb != nil)
+ if(mb){
qlock(mb);
+ }
if(f->mtop)
msgdecref(mb, f->mtop);
if(f->m)
msgdecref(mb, gettopmsg(mb, f->m));
f->m = f->mtop = nil;
- if(mb != nil){
+ if(mb){
f->mb = nil;
qunlock(mb);
- assert(mb->refs > 0);
qlock(&mbllock);
mboxdecref(mb);
qunlock(&mbllock);
@@ -1465,11 +1443,12 @@
char *
rremove(Fid *f)
{
-sanefid(f);
if(f->m != nil){
- if(f->m->deleted == 0)
+ qlock(f->mb);
+ if(!f->m->deleted)
mailplumb(f->mb, f->m, 1);
f->m->deleted = Deleted;
+ qunlock(f->mb);
}
return rclunk(f);
}
@@ -1479,15 +1458,15 @@
{
Dir d;
-sanefid(f);
- if(FILE(f->qid.path) == Qmbox){
+ if(f->mb)
qlock(f->mb);
+ if(FILE(f->qid.path) == Qmbox)
syncmbox(f->mb, 1);
- qunlock(f->mb);
- }
mkstat(&d, f->mb, f->m, FILE(f->qid.path));
rhdr.nstat = convD2M(&d, mbuf, messagesize - IOHDRSZ);
rhdr.stat = mbuf;
+ if(f->mb)
+ qunlock(f->mb);
return 0;
}
@@ -1521,19 +1500,6 @@
return f;
}
-int
-fidmboxrefs(Mailbox *mb)
-{
- Fid *f;
- int refs = 0;
-
- for(f = fids; f; f = f->next){
- if(f->mb == mb)
- refs++;
- }
- return refs;
-}
-
void
io(void)
{
@@ -1554,19 +1520,8 @@
}
for(;;){
- /*
- * reading from a pipe or a network device
- * will give an error after a few eof reads
- * however, we cannot tell the difference
- * between a zero-length read and an interrupt
- * on the processes writing to us,
- * so we wait for the error
- */
- checkmboxrefs();
n = read9pmsg(mfd[0], mdata, messagesize);
- if(n == 0)
- continue;
- if(n < 0)
+ if(n <= 0)
return;
if(convM2S(mdata, n, &thdr) == 0)
continue;
@@ -1859,25 +1814,6 @@
refs++;
qunlock(&hashlock);
return refs;
-}
-
-void
-checkmboxrefs(void)
-{
- int refs;
- Mailbox *mb;
-
-// qlock(&mbllock);
- for(mb = mbl; mb; mb = mb->next){
- qlock(mb);
- refs = fidmboxrefs(mb) + 1;
- if(refs != mb->refs){
- eprint("%s:%s ref mismatch got %d expected %d\n", mb->name, mb->path, refs, mb->refs);
- abort();
- }
- qunlock(mb);
- }
-// qunlock(&mbllock);
}
void
--- a/sys/src/cmd/upas/fs/mbox.c
+++ b/sys/src/cmd/upas/fs/mbox.c
@@ -52,7 +52,6 @@
imap4mbox,
pop3mbox,
mdirmbox,
-// planbmbox,
plan9mbox,
};
@@ -66,7 +65,7 @@
int n, d, y, a;
Message *m, *next;
- assert(canqlock(mb) == 0);
+ assert(!canqlock(mb));
a = mb->root->subname;
if(rdidxfile(mb, doplumb) == -2)
wridxfile(mb);
@@ -116,7 +115,7 @@
snprint(f1, sizeof f1, "%s", b);
err = newmbox(f0, nil, 0, &mb);
dprint("mboxrename %s %s -> %s\n", f0, f1, err);
- if(!err && !mb->rename)
+ if(err == nil && mb->rename == nil)
err = "rename not supported";
if(err)
goto done;
@@ -147,11 +146,9 @@
henter(PATH(0, Qtop), mb->name,
(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
done:
- if(!mb)
+ if(mb == nil)
return err;
qunlock(mb);
-// if(err)
-// mboxdecref(mb);
return err;
}
@@ -175,6 +172,8 @@
int i;
Mailbox *mb, **l;
+ if(r)
+ *r = nil;
initheaders();
mb = emalloc(sizeof *mb);
mb->idxsem = 1;
@@ -1146,6 +1145,7 @@
void
msgdecref(Mailbox *mb, Message *m)
{
+ assert(!canqlock(mb));
assert(m->refs > 0);
m->refs--;
if(m->refs == 0){
@@ -1201,6 +1201,7 @@
} else
qunlock(mb);
}
+
/* just space over \r. sleezy but necessary for ms email. */
int
--- a/sys/src/cmd/upas/fs/mkfile
+++ b/sys/src/cmd/upas/fs/mkfile
@@ -14,7 +14,6 @@
mdir.$O\
mtree.$O\
plan9.$O\
- planb.$O\
pop3.$O\
ref.$O\
remove.$O\
--- a/sys/src/cmd/upas/fs/planb.c
+++ /dev/null
@@ -1,484 +1,0 @@
-/*
- * Plan B (mail2fs) mail box format.
- *
- * BUG: this does not reconstruct the
- * raw text for attachments. So imap and others
- * will be unable to access any attachment using upas/fs.
- * As an aid, we add the path to the message directory
- * to the message body, so the user could build the path
- * for any attachment and open it.
- */
-
-#include "common.h"
-#include <ctype.h>
-#include <plumb.h>
-#include <libsec.h>
-#include "dat.h"
-
-static char*
-parseunix(Message *m)
-{
- char *s, *p, *q;
- int l;
- Tm tm;
-
- l = m->header - m->start;
- m->unixheader = smprint("%.*s", l, m->start);
- s = m->start + 5;
- if((p = strchr(s, ' ')) == nil)
- return s;
- *p = 0;
- m->unixfrom = strdup(s);
- *p++ = ' ';
- if(q = strchr(p, '\n'))
- *q = 0;
- if(strtotm(p, &tm) < 0)
- return p;
- if(q)
- *q = '\n';
- m->fileid = (uvlong)tm2sec(&tm) << 8;
- return 0;
-}
-
-static int
-readmessage(Message *m, char *msg)
-{
- int fd, n;
- char *buf, *name, *p;
- char hdr[128];
- Dir *d;
-
- buf = nil;
- d = nil;
- name = smprint("%s/raw", msg);
- if(name == nil)
- return -1;
- if(m->filename != nil)
- free(m->filename);
- m->filename = strdup(name);
- if(m->filename == nil)
- sysfatal("malloc: %r");
- fd = open(name, OREAD);
- if(fd < 0)
- goto Fail;
- n = read(fd, hdr, sizeof(hdr)-1);
- if(n <= 0)
- goto Fail;
- hdr[n] = 0;
- close(fd);
- fd = -1;
- p = strchr(hdr, '\n');
- if(p != nil)
- *++p = 0;
- if(strncmp(hdr, "From ", 5) != 0)
- goto Fail;
- free(name);
- name = smprint("%s/text", msg);
- if(name == nil)
- goto Fail;
- fd = open(name, OREAD);
- if(fd < 0)
- goto Fail;
- d = dirfstat(fd);
- if(d == nil)
- goto Fail;
- buf = malloc(strlen(hdr) + d->length + strlen(msg) + 10); /* few extra chars */
- if(buf == nil)
- goto Fail;
- strcpy(buf, hdr);
- p = buf+strlen(hdr);
- n = readn(fd, p, d->length);
- if(n < 0)
- goto Fail;
- sprint(p+n, "\n[%s]\n", msg);
- n += 2 + strlen(msg) + 2;
- close(fd);
- free(name);
- free(d);
- free(m->start);
- m->start = buf;
- m->lim = m->end = p+n;
- if(*(m->end-1) == '\n')
- m->end--;
- *m->end = 0;
- m->bend = m->rbend = m->end;
-
- return 0;
-Fail:
- if(fd >= 0)
- close(fd);
- free(name);
- free(buf);
- free(d);
- return -1;
-}
-
-/*
- * Deleted messages are kept as spam instead.
- */
-static void
-archive(Message *m)
-{
- char *dir, *p, *nname;
- Dir d;
-
- dir = strdup(m->filename);
- nname = nil;
- if(dir == nil)
- return;
- p = strrchr(dir, '/');
- if(p == nil)
- goto Fail;
- *p = 0;
- p = strrchr(dir, '/');
- if(p == nil)
- goto Fail;
- p++;
- if(*p < '0' || *p > '9')
- goto Fail;
- nname = smprint("s.%s", p);
- if(nname == nil)
- goto Fail;
- nulldir(&d);
- d.name = nname;
- dirwstat(dir, &d);
-Fail:
- free(dir);
- free(nname);
-}
-
-int
-purgembox(Mailbox *mb, int virtual)
-{
- Message *m, *next;
- int newdels;
-
- /* forget about what's no longer in the mailbox */
- newdels = 0;
- for(m = mb->root->part; m != nil; m = next){
- next = m->next;
- if(m->deleted > 0 && m->refs == 0){
- if(m->inmbox){
- newdels++;
- /*
- * virtual folders are virtual,
- * we do not archive
- */
- if(virtual == 0)
- archive(m);
- }
- delmessage(mb, m);
- }
- }
- return newdels;
-}
-
-static int
-mustshow(char* name)
-{
- if(isdigit(name[0]))
- return 1;
- if(0 && name[0] == 'a' && name[1] == '.')
- return 1;
- if(0 && name[0] == 's' && name[1] == '.')
- return 1;
- return 0;
-}
-
-static int
-readpbmessage(Mailbox *mb, char *msg, int doplumb, int *nnew)
-{
- Message *m, **l;
- char *x, *p;
-
- m = newmessage(mb->root);
- m->mallocd = 1;
- m->inmbox = 1;
- if(readmessage(m, msg) < 0){
- unnewmessage(mb, mb->root, m);
- return -1;
- }
- for(l = &mb->root->part; *l != nil; l = &(*l)->next)
- if(strcmp((*l)->filename, m->filename) == 0 &&
- *l != m){
- if((*l)->deleted < 0)
- (*l)->deleted = 0;
- delmessage(mb, m);
- mb->root->subname--;
- return -1;
- }
- m->header = m->end;
- if(x = strchr(m->start, '\n'))
- m->header = x + 1;
- if(p = parseunix(m))
- sysfatal("%s:%s naked From in body? [%s]", mb->path, (*l)->filename, p);
- m->mheader = m->mhend = m->header;
- parse(mb, m, 0, 0);
- if(m != *l && m->deleted != Dup){
- logmsg(m, "new");
- newcachehash(mb, m, doplumb);
- putcache(mb, m);
- nnew[0]++;
- }
-
- /* chain in */
- *l = m;
- if(doplumb)
- mailplumb(mb, m, 0);
- return 0;
-}
-
-static int
-dcmp(Dir *a, Dir *b)
-{
- char *an, *bn;
-
- an = a->name;
- bn = b->name;
- if(an[0] != 0 && an[1] == '.')
- an += 2;
- if(bn[0] != 0 && bn[1] == '.')
- bn += 2;
- return strcmp(an, bn);
-}
-
-static char*
-readpbmbox(Mailbox *mb, int doplumb, int *new)
-{
- char *month, *msg;
- int fd, i, j, nd, nmd;
- Dir *d, *md;
- static char err[ERRMAX];
-
- fd = open(mb->path, OREAD);
- if(fd < 0){
- errstr(err, sizeof err);
- return err;
- }
- nd = dirreadall(fd, &d);
- close(fd);
- if(nd > 0)
- qsort(d, nd, sizeof d[0], (int (*)(void*, void*))dcmp);
- for(i = 0; i < nd; i++){
- month = smprint("%s/%s", mb->path, d[i].name);
- if(month == nil)
- break;
- fd = open(month, OREAD);
- if(fd < 0){
- fprint(2, "%s: %s: %r\n", argv0, month);
- free(month);
- continue;
- }
- md = dirfstat(fd);
- if(md != nil && (md->qid.type & QTDIR) != 0){
- free(md);
- md = nil;
- nmd = dirreadall(fd, &md);
- for(j = 0; j < nmd; j++)
- if(mustshow(md[j].name)){
- msg = smprint("%s/%s", month, md[j].name);
- readpbmessage(mb, msg, doplumb, new);
- free(msg);
- }
- }
- close(fd);
- free(month);
- free(md);
- md = nil;
- }
- free(d);
- return nil;
-}
-
-static char*
-readpbvmbox(Mailbox *mb, int doplumb, int *new)
-{
- char *data, *ln, *p, *nln, *msg;
- int fd, nr;
- long sz;
- Dir *d;
- static char err[ERRMAX];
-
- fd = open(mb->path, OREAD);
- if(fd < 0){
- errstr(err, sizeof err);
- return err;
- }
- d = dirfstat(fd);
- if(d == nil){
- errstr(err, sizeof err);
- return err;
- }
- sz = d->length;
- free(d);
- if(sz > 2 * 1024 * 1024){
- sz = 2 * 1024 * 1024;
- fprint(2, "upas/fs: %s: bug: folder too big\n", mb->path);
- }
- data = malloc(sz+1);
- if(data == nil){
- errstr(err, sizeof err);
- return err;
- }
- nr = readn(fd, data, sz);
- close(fd);
- if(nr < 0){
- errstr(err, sizeof err);
- free(data);
- return err;
- }
- data[nr] = 0;
-
- for(ln = data; *ln != 0; ln = nln){
- nln = strchr(ln, '\n');
- if(nln != nil)
- *nln++ = 0;
- else
- nln = ln + strlen(ln);
- p = strchr(ln , ' ');
- if(p != nil)
- *p = 0;
- p = strchr(ln, '\t');
- if(p != nil)
- *p = 0;
- p = strstr(ln, "/text");
- if(p != nil)
- *p = 0;
- msg = smprint("/mail/box/%s/msgs/%s", user, ln);
- if(msg == nil){
- fprint(2, "upas/fs: malloc: %r\n");
- continue;
- }
- readpbmessage(mb, msg, doplumb, new);
- free(msg);
- }
- free(data);
- return nil;
-}
-
-static char*
-readmbox(Mailbox *mb, int doplumb, int virt, int *new)
-{
- char *mberr;
- int fd;
- Dir *d;
- Message *m;
- static char err[128];
-
- if(debug)
- fprint(2, "read mbox %s\n", mb->path);
- fd = open(mb->path, OREAD);
- if(fd < 0){
- errstr(err, sizeof(err));
- return err;
- }
-
- d = dirfstat(fd);
- if(d == nil){
- close(fd);
- errstr(err, sizeof(err));
- return err;
- }
- if(mb->d != nil){
- if(d->qid.path == mb->d->qid.path &&
- d->qid.vers == mb->d->qid.vers){
- close(fd);
- free(d);
- return nil;
- }
- free(mb->d);
- }
- close(fd);
- mb->d = d;
- mb->vers++;
- henter(PATH(0, Qtop), mb->name,
- (Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);
- snprint(err, sizeof err, "reading '%s'", mb->path);
- logmsg(nil, err, nil);
-
- for(m = mb->root->part; m != nil; m = m->next)
- if(m->deleted == 0)
- m->deleted = -1;
- if(virt == 0)
- mberr = readpbmbox(mb, doplumb, new);
- else
- mberr = readpbvmbox(mb, doplumb, new);
-
- /*
- * messages removed from the mbox; flag them to go.
- */
- for(m = mb->root->part; m != nil; m = m->next)
- if(m->deleted < 0 && doplumb){
- delmessage(mb, m);
- if(doplumb)
- mailplumb(mb, m, 1);
- }
- logmsg(nil, "mbox read");
- return mberr;
-}
-
-static char*
-mbsync(Mailbox *mb, int doplumb, int *new)
-{
- char *rv;
-
- rv = readmbox(mb, doplumb, 0, new);
- purgembox(mb, 0);
- return rv;
-}
-
-static char*
-mbvsync(Mailbox *mb, int doplumb, int *new)
-{
- char *rv;
-
- rv = readmbox(mb, doplumb, 1, new);
- purgembox(mb, 1);
- return rv;
-}
-
-char*
-planbmbox(Mailbox *mb, char *path)
-{
- char *list;
- static char err[64];
-
- if(access(path, AEXIST) < 0)
- return Enotme;
- list = smprint("%s/list", path);
- if(access(list, AEXIST) < 0){
- free(list);
- return Enotme;
- }
- free(list);
- mb->sync = mbsync;
- if(debug)
- fprint(2, "planb mbox %s\n", path);
- return nil;
-}
-
-char*
-planbvmbox(Mailbox *mb, char *path)
-{
- int fd, nr, i;
- char buf[64];
- static char err[64];
-
- fd = open(path, OREAD);
- if(fd < 0)
- return Enotme;
- nr = read(fd, buf, sizeof(buf)-1);
- close(fd);
- if(nr < 7)
- return Enotme;
- buf[nr] = 0;
- for(i = 0; i < 6; i++)
- if(buf[i] < '0' || buf[i] > '9')
- return Enotme;
- if(buf[6] != '/')
- return Enotme;
- mb->sync = mbvsync;
- if(debug)
- fprint(2, "planb virtual mbox %s\n", path);
- return nil;
-}