From 508b796b2719e6c8275a2a1b737c9798d380d25f Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 14 Mar 2017 23:06:39 +0100 Subject: [PATCH] upas/fs: fix more locking bugs, remove debugging clutter, remove planb mbox code --- sys/src/cmd/upas/fs/fs.c | 182 +++++--------- sys/src/cmd/upas/fs/mbox.c | 13 +- sys/src/cmd/upas/fs/mkfile | 1 - sys/src/cmd/upas/fs/planb.c | 484 ------------------------------------ 4 files changed, 66 insertions(+), 614 deletions(-) delete mode 100644 sys/src/cmd/upas/fs/planb.c diff --git a/sys/src/cmd/upas/fs/fs.c b/sys/src/cmd/upas/fs/fs.c index e34cfa25e..3137b9d9a 100644 --- a/sys/src/cmd/upas/fs/fs.c +++ b/sys/src/cmd/upas/fs/fs.c @@ -173,31 +173,6 @@ sanembmsg(Mailbox *mb, Message *m) } } -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 @@ main(int argc, char *argv[]) } 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 @@ doclone(Fid *f, int nfid) 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 @@ dowalk(Fid *f, char *name) { 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,15 +888,19 @@ sanefid(f); 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) msgincref(gettopmsg(f->mb, f->m)); switch(t){ case Qtop: - if(f->mb != nil) + if(f->mb) mboxincref(f->mb); break; case Qmbox: @@ -936,17 +913,16 @@ sanefid(f); 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; 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 @@ sanefid(f); 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 @@ rwalk(Fid *f) char *rv; int i; -sanefid(f); if(f->open) return Eisopen; @@ -1038,7 +1013,6 @@ sanefid(f); /* we only error out if no walk */ if(i > 0) rv = nil; -sanefid(f); return rv; } @@ -1056,10 +1030,12 @@ ropen(Fid *f) /* 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,20 +1058,24 @@ readtopdir(Fid*, uchar *buf, long off, int cnt, int blen) long pos; Mailbox *mb; + qlock(&mbllock); + n = 0; pos = 0; mkstat(&d, nil, nil, Qctl); m = convD2M(&d, &buf[n], blen); if(off <= pos){ if(m <= BIT16SZ || m > cnt) - return 0; + goto out; n += m; cnt -= m; } 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 @@ readtopdir(Fid*, uchar *buf, long off, int cnt, int blen) } pos += m; } +out: + qlock(&mbllock); return n; } @@ -1116,6 +1098,10 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen) 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 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen) if(off == 0){ if(m <= BIT16SZ || m > cnt){ f->fptr = nil; - return 0; + goto out; } n += m; cnt -= m; @@ -1160,7 +1146,8 @@ readmboxdir(Fid *f, uchar *buf, long off, int cnt, int blen) f->foff = pos; f->fptr = msg; f->fvers = f->mb->vers; - +out: + qunlock(f->mb); return n; } @@ -1172,6 +1159,7 @@ readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen) long pos; Message *msg; + qlock(f->mb); n = 0; pos = 0; for(i = 0; i < Qmax; i++){ @@ -1179,7 +1167,7 @@ readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen) 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 @@ readmsgdir(Fid *f, uchar *buf, long off, int cnt, int blen) } pos += m; } - +out: + qunlock(f->mb); return n; } @@ -1223,20 +1212,13 @@ rread(Fid *f) 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 @@ rwrite(Fid *f) 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 @@ rwrite(Fid *f) 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 @@ rwrite(Fid *f) 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 @@ rclunk(Fid *f) { 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 @@ sanefid(f); 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 @@ rstat(Fid *f) { 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 @@ newfid(int fid) 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 @@ io(void) } 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; @@ -1861,25 +1816,6 @@ hashmboxrefs(Mailbox *mb) 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 post(char *name, char *envname, int srvfd) { diff --git a/sys/src/cmd/upas/fs/mbox.c b/sys/src/cmd/upas/fs/mbox.c index 903f4650f..a7d850542 100644 --- a/sys/src/cmd/upas/fs/mbox.c +++ b/sys/src/cmd/upas/fs/mbox.c @@ -52,7 +52,6 @@ static Mailboxinit *boxinit[] = { imap4mbox, pop3mbox, mdirmbox, -// planbmbox, plan9mbox, }; @@ -66,7 +65,7 @@ syncmbox(Mailbox *mb, int doplumb) 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 @@ mboxrename(char *a, char *b, int flags) 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 @@ mboxrename(char *a, char *b, int flags) 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 @@ newmbox(char *path, char *name, int flags, Mailbox **r) int i; Mailbox *mb, **l; + if(r) + *r = nil; initheaders(); mb = emalloc(sizeof *mb); mb->idxsem = 1; @@ -1146,6 +1145,7 @@ msgincref(Message *m) void msgdecref(Mailbox *mb, Message *m) { + assert(!canqlock(mb)); assert(m->refs > 0); m->refs--; if(m->refs == 0){ @@ -1202,6 +1202,7 @@ mboxdecref(Mailbox *mb) qunlock(mb); } + /* just space over \r. sleezy but necessary for ms email. */ int deccr(char *x, int len) diff --git a/sys/src/cmd/upas/fs/mkfile b/sys/src/cmd/upas/fs/mkfile index 814787a07..577bc9718 100644 --- a/sys/src/cmd/upas/fs/mkfile +++ b/sys/src/cmd/upas/fs/mkfile @@ -14,7 +14,6 @@ OFILES=\ mdir.$O\ mtree.$O\ plan9.$O\ - planb.$O\ pop3.$O\ ref.$O\ remove.$O\ diff --git a/sys/src/cmd/upas/fs/planb.c b/sys/src/cmd/upas/fs/planb.c deleted file mode 100644 index fbe2ac251..000000000 --- a/sys/src/cmd/upas/fs/planb.c +++ /dev/null @@ -1,484 +0,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 -#include -#include -#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; -} -- 2.44.0