]> git.lizzy.rs Git - plan9front.git/commitdiff
upas/fs: fix more locking bugs, remove debugging clutter, remove planb mbox code
authorcinap_lenrek <cinap_lenrek@felloff.net>
Tue, 14 Mar 2017 22:06:39 +0000 (23:06 +0100)
committercinap_lenrek <cinap_lenrek@felloff.net>
Tue, 14 Mar 2017 22:06:39 +0000 (23:06 +0100)
sys/src/cmd/upas/fs/fs.c
sys/src/cmd/upas/fs/mbox.c
sys/src/cmd/upas/fs/mkfile
sys/src/cmd/upas/fs/planb.c [deleted file]

index e34cfa25e80a9a9263eafccbc37355a799ad0cfb..3137b9d9a53f03581aa10c2b0b7015935e3e7670 100644 (file)
@@ -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)
 {
index 903f4650f17a849af840cdec1dfabca59b7e73f5..a7d850542ea432387fb87bd7238c5cfb8bde62de 100644 (file)
@@ -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)
index 814787a079b0adb083ad74279b3d10a1bc91b817..577bc9718413bff40c0b7ea42ec2d9975134e5e9 100644 (file)
@@ -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 (file)
index fbe2ac2..0000000
+++ /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 <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;
-}