ref: 5b0200652a0fccf9b4eeeb518dbdb698f9bda71f
parent: ef7604325ba923d67906222b2130f76e067b7fbb
author: Ori Bernstein <[email protected]>
date: Wed Nov 22 01:13:43 EST 2023
fs: do the rest of the error handling conversion
--- a/blk.c
+++ b/blk.c
@@ -1076,6 +1076,7 @@
syncblk(qe.b);
dropblk(qe.b);
}
+ assert(estacksz() == 0);
}
}
--- a/check.c
+++ b/check.c
@@ -181,7 +181,7 @@
checkfs(int fd)
{
int ok, height;
- char *e, pfx[1], name[Keymax+1];
+ char pfx[1], name[Keymax+1];
Tree *t;
Scan s;
Blk *b;
@@ -198,17 +198,9 @@
}
pfx[0] = Klabel;
btnewscan(&s, pfx, 1);
- if((e = btenter(&fs->snap, &s)) != nil){
- fprint(fd, "scanning snapshots: %s\n", e);
- return 0;
- }
+ btenter(&fs->snap, &s);
while(1){
- if((e = btnext(&s, &s.kv)) != nil){
- fprint(fd, "invalid snapshot tree: %s\n", e);
- ok = 0;
- break;
- }
- if(s.done)
+ if(!btnext(&s, &s.kv))
break;
memcpy(name, s.kv.k+1, s.kv.nk-1);
name[s.kv.nk-1] = 0;
--- a/cons.c
+++ b/cons.c
@@ -103,7 +103,6 @@
static void
refreshusers(int fd, char **, int)
{
- char *e;
Mount *mnt;
if((mnt = getmount("adm")) == nil){
@@ -110,11 +109,13 @@
fprint(fd, "load users: missing 'adm'\n");
return;
}
- e = loadusers(fd, mnt->root);
- if(e != nil)
- fprint(fd, "load users: %s\n", e);
- else
- fprint(fd, "refreshed users\n");
+ if(waserror()){
+ fprint(fd, "load users: %s\n", errmsg());
+ clunkmount(mnt);
+ return;
+ }
+ loadusers(fd, mnt->root);
+ fprint(fd, "refreshed users\n");
clunkmount(mnt);
}
@@ -213,7 +214,7 @@
static void
showent(int fd, char **ap, int na)
{
- char *e, *p, *name, kbuf[Keymax], kvbuf[Kvmax];
+ char *p, *name, kbuf[Keymax], kvbuf[Kvmax];
Tree *t;
Kvp kv;
Key k;
@@ -226,37 +227,26 @@
}
pqid = strtoll(ap[0], nil, 16);
name = na == 2 ? ap[1] : nil;
- if((p = packdkey(kbuf, sizeof(kbuf), pqid, name)) == nil){
- fprint(fd, "could not pack key\n");
- goto Out;
- }
+ p = packdkey(kbuf, sizeof(kbuf), pqid, name);
k.k = kbuf;
k.nk = p - kbuf;
if(name != nil){
- if((e = btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf))) != nil){
- fprint(fd, "lookup failed: %s\n", e);
- goto Out;
+ if(!btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf))){
+ fprint(fd, "lookup failed: %s\n", name);
+ closesnap(t);
+ return;
}
fprint(fd, "%P\n", &kv);
}else{
btnewscan(&s, k.k, k.nk);
- if((e = btenter(t, &s)) != nil){
- fprint(fd, "scan failed: %s\n", e);
- goto Out;
- }
+ btenter(t, &s);
while(1){
- if((e = btnext(&s, &kv)) != nil){
- fprint(fd, "scan failed: %s\n", e);
- btexit(&s);
- goto Out;
- }
- if(s.done)
+ if(!btnext(&s, &kv))
break;
fprint(fd, "%P\n", &kv);
}
btexit(&s);
}
-Out:
closesnap(t);
}
--- a/dat.h
+++ b/dat.h
@@ -156,6 +156,7 @@
extern char Edir[];
extern char Esyntax[];
extern char Enouser[];
+extern char Enogrp[];
extern char Efsize[];
extern char Ebadu[];
extern char Erdonly[];
@@ -682,7 +683,7 @@
vlong offset; /* last read offset */
char first;
- char done;
+ char donescan;
char overflow;
char present;
int ht;
--- a/dump.c
+++ b/dump.c
@@ -375,7 +375,7 @@
void
showsnap(int fd, char **ap, int na)
{
- char *e, pfx[Snapsz];
+ char pfx[Snapsz];
vlong id;
Scan s;
uint flg;
@@ -387,18 +387,10 @@
pfx[0] = Klabel;
sz = 1;
btnewscan(&s, pfx, sz);
- if((e = btenter(&fs->snap, &s)) != nil){
- fprint(fd, "scan: %s\n", e);
- btexit(&s);
- return;
- }
+ btenter(&fs->snap, &s);
while(1){
- if((e = btnext(&s, &s.kv)) != nil){
- fprint(fd, "scan: %s\n", e);
+ if(!btnext(&s, &s.kv))
break;
- }
- if(s.done)
- break;
flg = UNPACK32(s.kv.v+1+8);
fprint(fd, "label: %P 0x%x\n", &s.kv, flg);
}
@@ -414,18 +406,10 @@
PACK64(pfx+1, id);
}
btnewscan(&s, pfx, sz);
- if((e = btenter(&fs->snap, &s)) != nil){
- fprint(fd, "scan: %s\n", e);
- btexit(&s);
- return;
- }
+ btenter(&fs->snap, &s);
while(1){
- if((e = btnext(&s, &s.kv)) != nil){
- fprint(fd, "scan: %s\n", e);
+ if(!btnext(&s, &s.kv))
break;
- }
- if(s.done)
- break;
fprint(fd, "snap: %P\n", &s.kv);
if(unpacktree(&t, s.kv.v, s.kv.nv) == nil){
fprint(fd, "unpack: garbled tree\n");
@@ -439,7 +423,7 @@
void
showdlist(int fd, char** ap, int na)
{
- char *p, *e, *err, pfx[Kvmax];
+ char *p, *e, pfx[Kvmax];
Dlist dl;
Bptr hd;
Scan s;
@@ -455,17 +439,9 @@
PACK64(pfx+1, id);
}
btnewscan(&s, pfx, sz);
- if((err = btenter(&fs->snap, &s)) != nil){
- fprint(fd, "scan: %s\n", err);
- btexit(&s);
- return;
- }
+ btenter(&fs->snap, &s);
while(1){
- if((e = btnext(&s, &s.kv)) != nil){
- fprint(fd, "scan: %s\n", e);
- break;
- }
- if(s.done)
+ if(!btnext(&s, &s.kv))
break;
fprint(fd, "dlist: %P\n", &s.kv);
kv2dlist(&s.kv, &dl);
--- a/error.c
+++ b/error.c
@@ -27,6 +27,7 @@
char Edir[] = "invalid directory";
char Esyntax[] = "syntax error";
char Enouser[] = "user does not exist";
+char Enogrp[] = "group does not exist";
char Efsize[] = "file too big";
char Ebadu[] = "attach -- unknown user or failed authentication";
char Erdonly[] = "file system read only";
--- a/fns.h
+++ b/fns.h
@@ -68,10 +68,10 @@
Mount* getmount(char*);
void clunkmount(Mount*);
-char* updatesnap(Tree**, Tree*, char*);
-char* tagsnap(Tree*, char*, int);
-char* delsnap(Tree*, vlong, char*);
-char* freedl(Dlist*, int);
+void updatesnap(Tree**, Tree*, char*);
+void tagsnap(Tree*, char*, int);
+void delsnap(Tree*, vlong, char*);
+void freedl(Dlist*, int);
Tree* opensnap(char*, int*);
void closesnap(Tree*);
@@ -84,21 +84,21 @@
int scandead(Dlist*, int, void(*)(Bptr, void*), void*);
int endfs(void);
int compresslog(Arena*);
-char* flushdlcache(int);
+void flushdlcache(int);
void setval(Blk*, Kvp*);
Conn* newconn(int, int);
int walk1(Tree*, vlong, char*, Qid*, vlong*);
-char* loadusers(int, Tree*);
+void loadusers(int, Tree*);
User* uid2user(int);
User* name2user(char*);
-char* btupsert(Tree*, Msg*, int);
-char* btlookup(Tree*, Key*, Kvp*, char*, int);
+void btupsert(Tree*, Msg*, int);
+int btlookup(Tree*, Key*, Kvp*, char*, int);
void btnewscan(Scan*, char*, int);
-char* btenter(Tree*, Scan*);
-char* btnext(Scan*, Kvp*);
+void btenter(Tree*, Scan*);
+int btnext(Scan*, Kvp*);
void btexit(Scan*);
int checkflag(Blk *b, int);
@@ -146,13 +146,10 @@
_Noreturn void nexterror(void);
#define waserror() (setjmp(*_waserror()))
#define errmsg() (((Errctx*)*errctx)->err)
-#define poperror() (((Errctx*)*errctx)->nerrlab--)
+#define poperror() assert(((Errctx*)*errctx)->nerrlab-- > 0)
+#define estacksz() (((Errctx*)*errctx)->nerrlab)
-char* pack8(int*, char*, char*, uchar);
-char* pack16(int*, char*, char*, ushort);
-char* pack32(int*, char*, char*, uint);
-char* pack64(int*, char*, char*, uvlong);
-char* packstr(int*, char*, char*, char*);
+char* packstr(char*, char*, char*);
int dir2kv(vlong, Xdir*, Kvp*, char*, int);
int dir2statbuf(Xdir*, char*, int);
@@ -183,13 +180,7 @@
char* unpackdkey(char*, int, vlong*);
Tree* unpacktree(Tree*, char*, int);
char* unpacksb(Gefs*, char*, int);
-
-/* void* is a bit hacky, but we want both signed and unsigned to work */
-char* unpack8(int*, char*, char*, void*);
-char* unpack16(int*, char*, char*, void*);
-char* unpack32(int*, char*, char*, void*);
-char* unpack64(int*, char*, char*, void*);
-char* unpackstr(int*, char*, char*, char**);
+char* unpackstr(char*, char*, char**);
/* fmt */
int Bconv(Fmt*);
--- a/fs.c
+++ b/fs.c
@@ -18,13 +18,12 @@
Key k;
err = 0;
- if((p = packdkey(kbuf, sizeof(kbuf), up, name)) == nil)
- return -1;
+ p = packdkey(kbuf, sizeof(kbuf), up, name);
k.k = kbuf;
k.nk = p - kbuf;
if(err)
return -1;
- if(btlookup(t, &k, &kv, rbuf, sizeof(rbuf)) != nil)
+ if(!btlookup(t, &k, &kv, rbuf, sizeof(rbuf)))
return -1;
if(kv2dir(&kv, &d) == -1)
return -1;
@@ -38,9 +37,12 @@
{
Tree *t, *s;
Mount *mnt;
- char *e;
lock(&fs->mountlk);
+ if(waserror()){
+ unlock(&fs->mountlk);
+ nexterror();
+ }
t = nil;
*pred = -1;
*bp = (Bptr){-1, -1, -1};
@@ -55,6 +57,7 @@
if(t == nil && (t = opensnap(a->old, nil)) == nil){
fprint(a->fd, "snap: open '%s': does not exist\n", a->old);
unlock(&fs->mountlk);
+ poperror();
return;
}
if(a->delete){
@@ -69,11 +72,7 @@
*bp = t->bp;
unlock(&t->lk);
}
- if((e = delsnap(t, t->succ, a->old)) != nil){
- fprint(a->fd, "snap: error deleting '%s': %s\n", a->new, e);
- unlock(&fs->mountlk);
- return;
- }
+ delsnap(t, t->succ, a->old);
}else{
if((s = opensnap(a->new, nil)) != nil){
fprint(a->fd, "snap: already exists '%s'\n", a->new);
@@ -81,14 +80,11 @@
unlock(&fs->mountlk);
return;
}
- if((e = tagsnap(t, a->new, a->mutable)) != nil){
- fprint(a->fd, "snap: error creating '%s': %s\n", a->new, e);
- unlock(&fs->mountlk);
- return;
- }
+ tagsnap(t, a->new, a->mutable);
}
closesnap(t);
unlock(&fs->mountlk);
+ poperror();
/* we probably want explicit snapshots to get synced */
if(a->delete)
fprint(a->fd, "deleted: %s\n", a->old);
@@ -240,31 +236,25 @@
}
-static char*
+static int
lookup(Mount *mnt, Key *k, Kvp *kv, char *buf, int nbuf)
{
- char *e;
Tree *r;
if(mnt == nil)
- return Eattach;
-
+ error(Eattach);
r = agetp(&mnt->root);
- e = btlookup(r, k, kv, buf, nbuf);
- return e;
+ return btlookup(r, k, kv, buf, nbuf);
}
-static char*
+static void
upsert(Mount *mnt, Msg *m, int nm)
{
- char *e;
-
if(!mnt->mutable)
- return Erdonly;
+ error(Erdonly);
if(mnt->root->nlbl != 1 || mnt->root->nref != 0)
- if((e = updatesnap(&mnt->root, mnt->root, mnt->name)) != nil)
- return e;
- return btupsert(mnt->root, m, nm);
+ updatesnap(&mnt->root, mnt->root, mnt->name);
+ btupsert(mnt->root, m, nm);
}
/*
@@ -290,7 +280,7 @@
static int
readb(Fid *f, char *d, vlong o, vlong n, vlong sz)
{
- char *e, buf[17], kvbuf[17+32];
+ char buf[17], kvbuf[17+32];
vlong fb, fo;
Bptr bp;
Blk *b;
@@ -311,19 +301,13 @@
PACK64(k.k+1, f->qpath);
PACK64(k.k+9, fb);
- e = lookup(f->mnt, &k, &kv, kvbuf, sizeof(kvbuf));
- if(e != nil){
- if(e != Esrch){
- werrstr(e);
- return -1;
- }
+ if(!lookup(f->mnt, &k, &kv, kvbuf, sizeof(kvbuf))){
memset(d, 0, n);
return n;
}
bp = unpackbp(kv.v, kv.nv);
- if((b = getblk(bp, GBraw)) == nil)
- return -1;
+ b = getblk(bp, GBraw);
memcpy(d, b->buf+fo, n);
dropblk(b);
return n;
@@ -332,7 +316,7 @@
static int
writeb(Fid *f, Msg *m, Bptr *ret, char *s, vlong o, vlong n, vlong sz)
{
- char *e, buf[Kvmax];
+ char buf[Kvmax];
vlong fb, fo;
Blk *b, *t;
Bptr bp;
@@ -346,22 +330,15 @@
PACK64(m->k+9, fb);
b = newdblk(f->mnt->root, Tdat, f->qpath);
- if(b == nil)
- return -1;
t = nil;
- e = lookup(f->mnt, m, &kv, buf, sizeof(buf));
- if(e == nil){
+ if(lookup(f->mnt, m, &kv, buf, sizeof(buf))){
bp = unpackbp(kv.v, kv.nv);
if(fb < sz && (fo != 0 || n != Blksz)){
- if((t = getblk(bp, GBraw)) == nil)
- return -1;
+ t = getblk(bp, GBraw);
memcpy(b->buf, t->buf, Blksz);
dropblk(t);
}
freeblk(f->mnt->root, nil, bp);
- }else if(e != Esrch){
- werrstr("%s", e);
- return -1;
}
if(fo+n > Blksz)
n = Blksz-fo;
@@ -445,7 +422,6 @@
goto Out;
}
if((t = opensnap(name, &mnt->mutable)) == nil){
- werrstr("%s", Enosnap);
free(mnt->name);
free(mnt);
mnt = nil;
@@ -776,6 +752,10 @@
rerror(m, Eauth);
return;
}
+ if(strcmp(m->uname, "none") == 0){
+ rerror(m, Enone);
+ return;
+ }
if((de = mallocz(sizeof(Dent), 1)) == nil){
rerror(m, Enomem);
return;
@@ -910,12 +890,15 @@
int uid;
de = nil;
+ mnt = nil;
+ if(waserror()){
+ rerror(m, errmsg());
+ goto Err;
+ }
if(m->aname[0] == '\0')
m->aname = "main";
- if((mnt = getmount(m->aname)) == nil){
- rerror(m, "%r");
- goto Out;
- }
+ if((mnt = getmount(m->aname)) == nil)
+ error(Enosnap);
rlock(&fs->userlk);
n = m->uname;
@@ -927,8 +910,7 @@
n = "adm";
if((u = name2user(n)) == nil){
runlock(&fs->userlk);
- rerror(m, Enouser);
- goto Out;
+ error(Enouser);
}
uid = u->id;
runlock(&fs->userlk);
@@ -936,50 +918,36 @@
if(m->afid != NOFID){
r.data = nil;
r.count = 0;
- if((af = getfid(m->conn, m->afid)) == nil){
- rerror(m, Enofid);
- goto Out;
- }
- if((e = authread(af, &r, nil, 0)) != nil){
- rerror(m, e);
+ if((af = getfid(m->conn, m->afid)) == nil)
+ error(Enofid);
+ if(waserror()){
putfid(af);
- goto Out;
+ nexterror();
}
- if(af->uid != uid){
- rerror(m, Ebadu);
- putfid(af);
- goto Out;
- }
+ if((e = authread(af, &r, nil, 0)) != nil)
+ error(e);
+ if(af->uid != uid)
+ error(Ebadu);
+ poperror();
putfid(af);
- }else if(!fs->noauth){
- rerror(m, Ebadu);
- goto Out;
- }
+ }else if(!fs->noauth && strcmp(m->uname, "none") != 0)
+ error(Ebadu);
if(strcmp(m->aname, "dump") == 0){
memset(&d, 0, sizeof(d));
filldumpdir(&d);
}else{
- if((p = packdkey(dbuf, sizeof(dbuf), -1ULL, "")) == nil){
- rerror(m, Elength);
- goto Out;
- }
+ if((p = packdkey(dbuf, sizeof(dbuf), -1ULL, "")) == nil)
+ error(Elength);
dk.k = dbuf;
dk.nk = p - dbuf;
t = agetp(&mnt->root);
- if((e = btlookup(t, &dk, &kv, kvbuf, sizeof(kvbuf))) != nil){
- rerror(m, e);
- goto Out;
- }
- if(kv2dir(&kv, &d) == -1){
- rerror(m, Efs);
- goto Out;
- }
+ if(!btlookup(t, &dk, &kv, kvbuf, sizeof(kvbuf)))
+ error(Enosnap);
+ kv2dir(&kv, &d);
}
- if((de = getdent(-1, &d)) == nil){
- rerror(m, Efs);
- goto Out;
- }
+ if((de = getdent(-1, &d)) == nil)
+ error(Efs);
memset(&f, 0, sizeof(Fid));
f.fid = NOFID;
@@ -993,42 +961,38 @@
f.duid = d.uid;
f.dgid = d.gid;
f.dmode = d.mode;
- if(dupfid(m->conn, m->fid, &f) == nil){
- rerror(m, Efid);
- goto Out;
- }
+ if(dupfid(m->conn, m->fid, &f) == nil)
+ error(Efid);
r.type = Rattach;
r.qid = d.qid;
respond(m, &r);
+ poperror();
-Out:
- clunkdent(de);
+Err: clunkdent(de);
clunkmount(mnt);
}
-static char*
+static int
findparent(Fid *f, vlong *qpath, char **name, char *buf, int nbuf)
{
- char *p, *e, kbuf[Keymax];
+ char *p, kbuf[Keymax];
Kvp kv;
Key k;
- if((p = packsuper(kbuf, sizeof(kbuf), f->pqpath)) == nil)
- return Elength;
+ p = packsuper(kbuf, sizeof(kbuf), f->pqpath);
k.k = kbuf;
k.nk = p - kbuf;
- if((e = lookup(f->mnt, &k, &kv, buf, nbuf)) != nil)
- return e;
- if((*name = unpackdkey(kv.v, kv.nv, qpath)) == nil)
- return Efs;
- return nil;
+ if(!lookup(f->mnt, &k, &kv, buf, nbuf))
+ return 0;
+ *name = unpackdkey(kv.v, kv.nv, qpath);
+ return 1;
}
static void
fswalk(Fmsg *m)
{
- char *p, *e, *name, kbuf[Maxent], kvbuf[Kvmax];
+ char *p, *name, kbuf[Maxent], kvbuf[Kvmax];
int duid, dgid, dmode;
vlong up, prev;
Fid *o, *f;
@@ -1044,12 +1008,13 @@
rerror(m, Enofid);
return;
}
- if(o->mode != -1){
- rerror(m, Einuse);
+ if(waserror()){
+ rerror(m, errmsg());
putfid(o);
return;
}
- e = nil;
+ if(o->mode != -1)
+ error(Einuse);
mnt = o->mnt;
up = o->qpath;
prev = o->qpath;
@@ -1061,24 +1026,18 @@
dmode = d.mode;
r.type = Rwalk;
for(i = 0; i < m->nwname; i++){
- if(fsaccess(o, d.mode, d.uid, d.gid, DMEXEC) != 0){
- rerror(m, Eperm);
- putfid(o);
- return;
- }
+ if(fsaccess(o, d.mode, d.uid, d.gid, DMEXEC) != 0)
+ error(Eperm);
name = m->wname[i];
if(d.qid.path == Qdump){
- if((mnt = getmount(m->wname[i])) == nil){
- rerror(m, Esrch);
- putfid(o);
- return;
- }
- if((p = packdkey(kbuf, sizeof(kbuf), -1ULL, "")) == nil){
- rerror(m, Elength);
+ if((mnt = getmount(m->wname[i])) == nil)
+ error(Esrch);
+ if(waserror()){
clunkmount(mnt);
- putfid(o);
- return;
+ nexterror();
}
+ p = packdkey(kbuf, sizeof(kbuf), -1ULL, "");
+ poperror();
}else{
if(strcmp(m->wname[i], "..") == 0){
if(o->pqpath == Qdump){
@@ -1088,17 +1047,11 @@
dgid = d.gid;
dmode = d.mode;
goto Found;
- }else if((e = findparent(o, &prev, &name, kbuf, sizeof(kbuf))) != nil){
- rerror(m, e);
- putfid(o);
- return;
}
+ if(!findparent(o, &prev, &name, kbuf, sizeof(kbuf)))
+ error(Esrch);
}
- if((p = packdkey(kbuf, sizeof(kbuf), prev, name)) == nil){
- rerror(m, Elength);
- putfid(o);
- return;
- }
+ p = packdkey(kbuf, sizeof(kbuf), prev, name);
}
duid = d.uid;
dgid = d.gid;
@@ -1105,13 +1058,9 @@
dmode = d.mode;
k.k = kbuf;
k.nk = p - kbuf;
- if((e = lookup(mnt, &k, &kv, kvbuf, sizeof(kvbuf))) != nil)
+ if(!lookup(mnt, &k, &kv, kvbuf, sizeof(kvbuf)))
break;
- if(kv2dir(&kv, &d) == -1){
- rerror(m, Efs);
- putfid(o);
- return;
- }
+ kv2dir(&kv, &d);
Found:
up = prev;
prev = d.qid.path;
@@ -1118,22 +1067,20 @@
r.wqid[i] = d.qid;
}
r.nwqid = i;
- if(i == 0 && m->nwname != 0){
- rerror(m, e);
- putfid(o);
- return;
- }
+ if(i == 0 && m->nwname != 0)
+ error(Esrch);
f = o;
if(m->fid != m->newfid && i == m->nwname){
- if((f = dupfid(m->conn, m->newfid, o)) == nil){
- rerror(m, Efid);
- putfid(o);
- return;
- }
+ if((f = dupfid(m->conn, m->newfid, o)) == nil)
+ error(Efid);
putfid(o);
}
if(i > 0 && i == m->nwname){
lock(f);
+ if(waserror()){
+ unlock(f);
+ nexterror();
+ }
if(up == Qdump)
dent = getdent(-1ULL, &d);
else
@@ -1141,10 +1088,7 @@
if(dent == nil){
if(f != o)
clunkfid(m->conn, f);
- rerror(m, Enomem);
- unlock(f);
- putfid(f);
- return;
+ error(Enomem);
}
if(mnt != f->mnt){
clunkmount(f->mnt);
@@ -1158,9 +1102,11 @@
f->duid = duid;
f->dgid = dgid;
f->dmode = dmode;
+ poperror();
unlock(f);
}
respond(m, &r);
+ poperror();
putfid(f);
}
@@ -1176,18 +1122,19 @@
rerror(m, Enofid);
return;
}
- rlock(f->dent);
- n = dir2statbuf(f->dent, buf, sizeof(buf));
- runlock(f->dent);
- if(n == -1){
- rerror(m, "stat: %r");
+ if(waserror()){
+ rerror(m, errmsg());
putfid(f);
return;
}
+ rlock(f->dent);
+ n = dir2statbuf(f->dent, buf, sizeof(buf));
+ runlock(f->dent);
r.type = Rstat;
r.stat = (uchar*)buf;
r.nstat = n;
respond(m, &r);
+ poperror();
putfid(f);
}
@@ -1195,7 +1142,7 @@
fswstat(Fmsg *m, int id, Amsg **ao)
{
char rnbuf[Kvmax], opbuf[Kvmax], upbuf[Upksz];
- char *p, *e, strs[65535];
+ char *p, strs[65535];
int op, nm, rename, truncate;
vlong oldlen;
Qid old;
@@ -1209,6 +1156,7 @@
Key k;
User *u;
+ *ao = nil;
rename = 0;
truncate = 0;
if((f = getfid(m->conn, m->fid)) == nil){
@@ -1218,18 +1166,18 @@
de = f->dent;
truncwait(de, id);
wlock(de);
- if(de->gone){
- rerror(m, Ephase);
- goto Out;
+ if(waserror()){
+ rerror(m, errmsg());
+ free(*ao);
+ *ao = nil;
+ goto Err;
}
- if((de->qid.type & QTAUTH) || (de->qid.path & Qdump)){
- rerror(m, Emode);
- goto Out;
- }
- if(convM2D(m->stat, m->nstat, &d, strs) <= BIT16SZ){
- rerror(m, Edir);
- goto Out;
- }
+ if(de->gone)
+ error(Ephase);
+ if((de->qid.type & QTAUTH) || (de->qid.path & Qdump))
+ error(Emode);
+ if(convM2D(m->stat, m->nstat, &d, strs) <= BIT16SZ)
+ error(Edir);
t = agetp(&f->mnt->root);
n = de->Xdir;
@@ -1239,40 +1187,28 @@
/* check validity of updated fields and construct Owstat message */
if(d.qid.path != ~0 || d.qid.vers != ~0){
- if(d.qid.path != de->qid.path){
- rerror(m, Ewstatp);
- goto Out;
- }
- if(d.qid.vers != de->qid.vers){
- rerror(m, Ewstatv);
- goto Out;
- }
+ if(d.qid.path != de->qid.path)
+ error(Ewstatp);
+ if(d.qid.vers != de->qid.vers)
+ error(Ewstatv);
}
if(*d.name != '\0'){
if(strcmp(d.name, de->name) != 0){
rename = 1;
- if(okname(d.name) == -1){
- rerror(m, Ename);
- goto Out;
- }
- if(walk1(t, f->dent->up, d.name, &old, &oldlen) == 0){
- rerror(m, Eexist);
- goto Out;
- }
+ if(okname(d.name) == -1)
+ error(Ename);
+ if(walk1(t, f->dent->up, d.name, &old, &oldlen) == 0)
+ error(Eexist);
n.name = d.name;
}
}
if(d.length != ~0){
- if(d.length < 0){
- rerror(m, Ewstatl);
- goto Out;
- }
+ if(d.length < 0)
+ error(Ewstatl);
if(d.length != de->length){
if(d.length < de->length){
- if((*ao = malloc(sizeof(Amsg))) == nil){
- rerror(m, Enomem);
- goto Out;
- }
+ if((*ao = malloc(sizeof(Amsg))) == nil)
+ error(Enomem);
aincl(&de->ref, 1);
aincl(&f->mnt->ref, 1);
(*ao)->op = AOclear;
@@ -1291,14 +1227,10 @@
}
}
if(d.mode != ~0){
- if((d.mode^de->mode) & DMDIR){
- rerror(m, Ewstatd);
- goto Out;
- }
- if(d.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
- rerror(m, Ewstatb);
- goto Out;
- }
+ if((d.mode^de->mode) & DMDIR)
+ error(Ewstatd);
+ if(d.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777))
+ error(Ewstatb);
if(d.mode != de->mode){
n.mode = d.mode;
n.qid.type = d.mode>>24;
@@ -1320,8 +1252,7 @@
u = name2user(d.uid);
if(u == nil){
runlock(&fs->userlk);
- rerror(m, Enouser);
- goto Out;
+ error(Enouser);
}
n.uid = u->id;
runlock(&fs->userlk);
@@ -1336,8 +1267,7 @@
u = name2user(d.gid);
if(u == nil){
runlock(&fs->userlk);
- rerror(m, Enouser);
- goto Out;
+ error(Enogrp);
}
n.gid = u->id;
runlock(&fs->userlk);
@@ -1353,38 +1283,23 @@
p += 4;
/* check permissions */
- if(rename){
- if(fsaccess(f, f->dmode, f->duid, f->dgid, DMWRITE) == -1){
- rerror(m, Eperm);
- goto Out;
- }
- }
- if(op & Owsize){
- if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1){
- rerror(m, Eperm);
- goto Out;
- }
- }
- if(op & (Owmode|Owmtime)){
- if(!permissive && f->uid != de->uid && !groupleader(f->uid, de->gid)){
- rerror(m, Ewstato);
- goto Out;
- }
- }
- if(op & Owuid){
- if(!permissive){
- rerror(m, Ewstatu);
- goto Out;
- }
- }
- if(op & Owgid){
+ if(rename)
+ if(fsaccess(f, f->dmode, f->duid, f->dgid, DMWRITE) == -1)
+ error(Eperm);
+ if(op & Owsize)
+ if(fsaccess(f, de->mode, de->uid, de->gid, DMWRITE) == -1)
+ error(Eperm);
+ if(op & (Owmode|Owmtime))
+ if(!permissive && f->uid != de->uid && !groupleader(f->uid, de->gid))
+ error(Ewstato);
+ if(op & Owuid)
+ if(!permissive)
+ error(Ewstatu);
+ if(op & Owgid)
if(!permissive
&& !(f->uid == de->uid && ingroup(f->uid, n.gid))
- && !(groupleader(f->uid, de->gid) && groupleader(f->uid, n.gid))){
- rerror(m, Ewstatg);
- goto Out;
- }
- }
+ && !(groupleader(f->uid, de->gid) && groupleader(f->uid, n.gid)))
+ error(Ewstatg);
/* update directory entry */
nm = 0;
@@ -1396,10 +1311,7 @@
nm++;
mb[nm].op = Oinsert;
- if(dir2kv(f->pqpath, &n, &mb[nm], rnbuf, sizeof(rnbuf)) == -1){
- rerror(m, Efs);
- goto Out;
- }
+ dir2kv(f->pqpath, &n, &mb[nm], rnbuf, sizeof(rnbuf));
k = mb[nm].Key;
nm++;
@@ -1421,12 +1333,7 @@
nm++;
}
assert(nm <= nelem(mb));
- if((e = upsert(f->mnt, mb, nm)) != nil){
- qunlock(&de->trunclk);
- wunlock(de);
- rerror(m, e);
- goto Out;
- }
+ upsert(f->mnt, mb, nm);
de->Xdir = n;
if(rename)
@@ -1434,9 +1341,9 @@
r.type = Rwstat;
respond(m, &r);
+ poperror();
-Out:
- if(!truncate)
+Err: if(!truncate)
qunlock(&de->trunclk);
wunlock(de);
putfid(f);
@@ -1468,7 +1375,7 @@
static void
fscreate(Fmsg *m)
{
- char *p, *e, buf[Kvmax], upkbuf[Keymax], upvbuf[Inlmax];
+ char *p, buf[Kvmax], upkbuf[Keymax], upvbuf[Inlmax];
Dent *de;
vlong oldlen;
Qid old;
@@ -1491,6 +1398,11 @@
return;
}
lock(f);
+ if(waserror()){
+ rerror(m, errmsg());
+ goto Err;
+
+ }
if(f->mode != -1){
rerror(m, Einuse);
goto Out;
@@ -1554,10 +1466,7 @@
mb[nm].nv = p - upvbuf;
nm++;
}
- if((e = upsert(f->mnt, mb, nm)) != nil){
- rerror(m, e);
- goto Out;
- }
+ upsert(f->mnt, mb, nm);
de = getdent(f->qpath, &d);
if(de == nil){
@@ -1568,17 +1477,13 @@
f->pqpath = f->qpath;
f->qpath = d.qid.path;
f->dent = de;
- unlock(f);
- putfid(f);
r.type = Rcreate;
r.qid = d.qid;
r.iounit = f->iounit;
respond(m, &r);
- return;
-
-Out:
- unlock(f);
+Out: poperror();
+Err: unlock(f);
putfid(f);
return;
}
@@ -1592,16 +1497,15 @@
if(f->dent->qid.type == QTFILE)
return nil;
+
t = agetp(&f->mnt->root);
packdkey(pfx, sizeof(pfx), f->qpath, nil);
btnewscan(&s, pfx, sizeof(pfx));
- if((e = btenter(t, &s)) != nil)
- goto Out;
- if((e = btnext(&s, &s.kv)) != nil)
- goto Out;
- if(!s.done)
+ btenter(t, &s);
+ if(btnext(&s, &s.kv))
e = Enempty;
-Out:
+ else
+ e = nil;
btexit(&s);
return e;
}
@@ -1609,11 +1513,10 @@
static void
fsremove(Fmsg *m, int id, Amsg **ao)
{
- char upbuf[Upksz];
+ char *e, upbuf[Upksz];
Fcall r;
Msg mb[2];
Fid *f;
- char *e;
if((f = getfid(m->conn, m->fid)) == nil){
rerror(m, Enofid);
@@ -1623,16 +1526,19 @@
truncwait(f->dent, id);
wlock(f->dent);
- if(f->dent->gone){
- e = Ephase;
- goto Error;
+ *ao = nil;
+ if(waserror()){
+ rerror(m, errmsg());
+ free(*ao);
+ *ao = nil;
+ goto Err;
}
+ if(f->dent->gone)
+ error(Ephase);
if((e = candelete(f)) != nil)
- goto Error;
- if(fsaccess(f, f->dmode, f->duid, f->dgid, DMWRITE) == -1){
- e = Eperm;
- goto Error;
- }
+ error(e);
+ if(fsaccess(f, f->dmode, f->duid, f->dgid, DMWRITE) == -1)
+ error(Eperm);
mb[0].op = Odelete;
mb[0].k = f->dent->k;
mb[0].nk = f->dent->nk;
@@ -1644,11 +1550,10 @@
mb[1].nk = Upksz;
mb[1].nv = 0;
- if((e = upsert(f->mnt, mb, 1)) != nil)
- goto Error;
+ upsert(f->mnt, mb, 1);
if(f->dent->qid.type == QTFILE){
if((*ao = malloc(sizeof(Amsg))) == nil)
- goto Error;
+ error(Enomem);
aincl(&f->mnt->ref, 1);
(*ao)->op = AOclear;
(*ao)->mnt = f->mnt;
@@ -1658,25 +1563,19 @@
(*ao)->dent = nil;
}
f->dent->gone = 1;
- qunlock(&f->dent->trunclk);
- wunlock(f->dent);
-
r.type = Rremove;
respond(m, &r);
- putfid(f);
- return;
-
-Error:
- qunlock(&f->dent->trunclk);
+ poperror();
+Err: qunlock(&f->dent->trunclk);
wunlock(f->dent);
- rerror(m, e);
putfid(f);
+ return;
}
static void
fsopen(Fmsg *m, int id, Amsg **ao)
{
- char *p, *e, buf[Kvmax];
+ char *p, buf[Kvmax];
int mbits;
Fcall r;
Xdir d;
@@ -1689,38 +1588,32 @@
rerror(m, Enofid);
return;
}
-
+ if(waserror()){
+ rerror(m, errmsg());
+ putfid(f);
+ return;
+ }
if((f->qpath & Qdump) != 0){
filldumpdir(&d);
}else{
- if((e = lookup(f->mnt, f->dent, &kv, buf, sizeof(buf))) != nil){
- rerror(m, e);
- putfid(f);
- return;
- }
- if(kv2dir(&kv, &d) == -1){
- rerror(m, Efs);
- putfid(f);
- return;
- }
+ if(!lookup(f->mnt, f->dent, &kv, buf, sizeof(buf)))
+ error(Esrch);
+ kv2dir(&kv, &d);
}
wlock(f->dent);
- if(f->dent->gone){
- rerror(m, Ephase);
-Disallow: wunlock(f->dent);
- putfid(f);
- return;
+ if(waserror()){
+ wunlock(f->dent);
+ nexterror();
}
+ if(f->dent->gone)
+ error(Ephase);
if(f->dent->qid.type & QTEXCL)
- if(f->dent->ref != 1){
- rerror(m, Elocked);
- goto Disallow;
- }
- if(fsaccess(f, d.mode, d.uid, d.gid, mbits) == -1){
- rerror(m, Eperm);
- goto Disallow;
- }
+ if(f->dent->ref != 1)
+ error(Elocked);
+ if(fsaccess(f, d.mode, d.uid, d.gid, mbits) == -1)
+ error(Eperm);
f->dent->length = d.length;
+ poperror();
wunlock(f->dent);
r.type = Ropen;
r.qid = d.qid;
@@ -1728,17 +1621,10 @@
lock(f);
if(f->mode != -1){
- rerror(m, Einuse);
unlock(f);
- putfid(f);
- return;
+ error(Einuse);
}
f->mode = mode2bits(m->mode);
-// if(!fs->rdonly && (m->mode == OEXEC)){
-// lock(&fs->root.lk);
-// f->root = fs->root;
-// unlock(&fs->root.lk);
-// }
if(m->mode & OTRUNC){
truncwait(f->dent, id);
wlock(f->dent);
@@ -1755,10 +1641,13 @@
mb.nk = f->dent->nk;
mb.v = buf;
mb.nv = p - buf;
- if((*ao = malloc(sizeof(Amsg))) == nil){
- e = Enomem;
- goto Error;
+ if(waserror()){
+ qunlock(&f->dent->trunclk);
+ wunlock(f->dent);
+ nexterror();
}
+ if((*ao = malloc(sizeof(Amsg))) == nil)
+ error(Enomem);
aincl(&f->mnt->ref, 1);
(*ao)->op = AOclear;
(*ao)->mnt = f->mnt;
@@ -1766,17 +1655,13 @@
(*ao)->off = 0;
(*ao)->length = f->dent->length;
(*ao)->dent = nil;
- if((e = upsert(f->mnt, &mb, 1)) != nil){
-Error: qunlock(&f->dent->trunclk);
- wunlock(f->dent);
- rerror(m, e);
- putfid(f);
- return;
- }
+ upsert(f->mnt, &mb, 1);
qunlock(&f->dent->trunclk);
wunlock(f->dent);
+ poperror();
}
unlock(f);
+ poperror();
respond(m, &r);
putfid(f);
}
@@ -1784,7 +1669,7 @@
static char*
readsnap(Fmsg *m, Fid *f, Fcall *r)
{
- char pfx[1], *p, *e;
+ char pfx[1], *p;
int n, ns;
Scan *s;
Xdir d;
@@ -1804,7 +1689,7 @@
f->scan = s;
unlock(f);
}
- if(s->done){
+ if(s->donescan){
r->count = 0;
return nil;
}
@@ -1823,12 +1708,9 @@
p += ns;
n -= ns;
}
- if((e = btenter(&fs->snap, s)) != nil)
- return e;
+ btenter(&fs->snap, s);
while(1){
- if((e = btnext(s, &s->kv)) != nil)
- return e;
- if(s->done)
+ if(!btnext(s, &s->kv))
break;
memcpy(d.name, s->kv.k+1, s->kv.nk-1);
d.name[s->kv.nk-1] = 0;
@@ -1848,7 +1730,7 @@
static char*
readdir(Fmsg *m, Fid *f, Fcall *r)
{
- char pfx[Dpfxsz], *p, *e;
+ char pfx[Dpfxsz], *p;
int n, ns;
Tree *t;
Scan *s;
@@ -1869,7 +1751,7 @@
f->scan = s;
unlock(f);
}
- if(s->done){
+ if(s->donescan){
r->count = 0;
return nil;
}
@@ -1884,12 +1766,9 @@
p += ns;
n -= ns;
}
- if((e = btenter(t, s)) != nil)
- return e;
+ btenter(t, s);
while(1){
- if((e = btnext(s, &s->kv)) != nil)
- return e;
- if(s->done)
+ if(!btnext(s, &s->kv))
break;
if((ns = kv2statbuf(&s->kv, p, n)) == -1){
s->overflow = 1;
@@ -1997,23 +1876,20 @@
}
truncwait(f->dent, id);
wlock(f->dent);
- if(f->dent->gone){
- rerror(m, Ephase);
+ if(waserror()){
+ rerror(m, errmsg());
qunlock(&f->dent->trunclk);
wunlock(f->dent);
putfid(f);
return;
}
+ if(f->dent->gone)
+ error(Ephase);
if(f->dent->qid.type == QTAUTH){
e = authwrite(f, &r, m->data, m->count);
if(e != nil)
- rerror(m, e);
- else
- respond(m, &r);
- qunlock(&f->dent->trunclk);
- wunlock(f->dent);
- putfid(f);
- return;
+ error(e);
+ goto Out;
}
w = 0;
@@ -2028,17 +1904,14 @@
kv[i].nk = sizeof(kbuf[i]);
kv[i].v = vbuf[i];
kv[i].nv = sizeof(vbuf[i]);
- n = writeb(f, &kv[i], &bp[i], p, o, c, f->dent->length);
- if(n == -1){
- for(j = 0; j < i; j++)
- freeblk(t, nil, bp[i]);
- qunlock(&f->dent->trunclk);
- wunlock(f->dent);
- fprint(2, "%r");
- putfid(f);
- abort();
- return;
+ if(waserror()){
+ if(!fs->rdonly)
+ for(j = 0; j < i; j++)
+ freeblk(t, nil, bp[i]);
+ nexterror();
}
+ n = writeb(f, &kv[i], &bp[i], p, o, c, f->dent->length);
+ poperror();
w += n;
p += n;
o += n;
@@ -2067,21 +1940,16 @@
kv[i].v = sbuf;
kv[i].nv = p - sbuf;
- if((e = upsert(f->mnt, kv, i+1)) != nil){
- rerror(m, e);
- qunlock(&f->dent->trunclk);
- wunlock(f->dent);
- putfid(f);
- abort();
- return;
- }
- qunlock(&f->dent->trunclk);
- wunlock(f->dent);
+ upsert(f->mnt, kv, i+1);
r.type = Rwrite;
r.count = w;
+Out:
+ poperror();
respond(m, &r);
- putfid(f);
+ qunlock(&f->dent->trunclk);
+ wunlock(f->dent);
+ putfid(f);
}
void
@@ -2182,6 +2050,7 @@
respond(m, &r);
break;
}
+ assert(estacksz() == 0);
}
}
@@ -2209,7 +2078,8 @@
case Topen: fsopen(m, id, &a); break;
default: abort(); break;
}
- epochend(id);
+ assert(estacksz() == 0);
+ epochend(id);
qunlock(&fs->mutlk);
epochclean();
@@ -2233,6 +2103,7 @@
case Tstat: fsstat(m); break;
case Topen: fsopen(m, id, nil); break;
}
+ assert(estacksz() == 0);
epochend(id);
}
}
@@ -2298,7 +2169,7 @@
void
runsweep(int id, void*)
{
- char *e, buf[Offksz];
+ char buf[Offksz];
Bptr bp, nb, *oldhd;
vlong off, pred;
Mount *mnt;
@@ -2362,16 +2233,26 @@
break;
case AOsnap:
+ if(waserror()){
+ fprint(2, "taking snap: %s\n", errmsg());
+ ainc(&fs->rdonly);
+ }
qlock(&fs->mutlk);
+ if(waserror()){
+ qunlock(&fs->mutlk);
+ nexterror();
+ }
epochstart(id);
snapfs(am, &bp, &pred);
sync();
epochend(id);
+ poperror();
qunlock(&fs->mutlk);
if(pred != -1){
epochwait();
sweeptree(bp, pred);
}
+ poperror();
break;
case AOclear:
@@ -2386,8 +2267,7 @@
PACK64(m.k+9, off);
m.v = nil;
m.nv = 0;
- if((e = upsert(am->mnt, &m, 1)) != nil)
- broke("reading %B: %s", bp, e);
+ upsert(am->mnt, &m, 1);
epochend(id);
qunlock(&fs->mutlk);
epochclean();
@@ -2399,6 +2279,7 @@
clunkmount(am->mnt);
break;
}
+ assert(estacksz() == 0);
free(am);
}
}
--- a/load.c
+++ b/load.c
@@ -57,7 +57,6 @@
Mount *dump;
Arena *a;
Bptr bp;
- char *e;
Tree *t;
int i, k;
@@ -110,6 +109,13 @@
sysfatal("load log %B: %r", a->loghd);
}
+ if(waserror())
+ sysfatal("load fs: %s\n", errmsg());
+ if((t = opensnap("adm", nil)) == nil)
+ sysfatal("load users: no adm label");
+ loadusers(2, t);
+ poperror();
+
fprint(2, "load %s:\n", dev);
fprint(2, "\tsnaptree:\t%B\n", fs->snap.bp);
fprint(2, "\tnarenas:\t%d\n", fs->narena);
@@ -118,9 +124,5 @@
fprint(2, "\tnextgen:\t%lld\n", fs->nextgen);
fprint(2, "\tblocksize:\t%lld\n", Blksz);
fprint(2, "\tcachesz:\t%lld MiB\n", fs->cmax*Blksz/MiB);
- if((t = opensnap("adm", nil)) == nil)
- sysfatal("load users: no adm label");
- if((e = loadusers(2, t)) != nil)
- sysfatal("load users: %s\n", e);
closesnap(t);
}
--- a/pack.c
+++ b/pack.c
@@ -6,124 +6,30 @@
#include "dat.h"
#include "fns.h"
-char*
-unpack8(int *err, char *p, char *e, void *v)
-{
- if (e - p < 1 || *err){
- *err = 1;
- return p;
- }
- *(uchar*)v = p[0];
- return p+1;
-}
-
-char*
-unpack16(int *err, char *p, char *e, void *v)
-{
- if (e - p < 2 || *err){
- *err = 1;
- return p;
- }
- *(ushort*)v = UNPACK16(p);
- return p+2;
-}
-
-char*
-unpack32(int *err, char *p, char *e, void *v)
-{
- if (e - p < 4 || *err){
- *err = 1;
- return p;
- }
- *(uint*)v = UNPACK32(p);
- return p+4;
-}
-
-char*
-unpack64(int *err, char *p, char *e, void *v)
-{
- if (e - p < 8 || *err){
- *err = 1;
- return p;
- }
- *(uvlong*)v = UNPACK64(p);
- return p+8;
-}
-
/* Terminated so we can use them directly in C */
char*
-unpackstr(int *err, char *p, char *e, char **s)
+unpackstr(char *p, char *e, char **s)
{
int n;
- if (e - p < 3 || *err){
- *err = 1;
- return p;
- }
+ if (e - p < 3)
+ error(Elength);
n = UNPACK16(p);
- if(e - p < n + 3 || p[n+2] != 0){
- *err = 1;
- return p;
- }
+ if(e - p < n + 3 || p[n+2] != 0)
+ error(Efs);
*s = p+2;
return p+3+n;
}
-char*
-pack8(int *err, char *p, char *e, uchar v)
-{
- if (e - p < 1 || *err){
- *err = 1;
- return p;
- }
- p[0] = v;
- return p+1;
-}
-
-char*
-pack16(int *err, char *p, char *e, ushort v)
-{
- if (e - p < 2 || *err){
- *err = 1;
- return p;
- }
- PACK16(p, v);
- return p+2;
-}
-
-char*
-pack32(int *err, char *p, char *e, uint v)
-{
- if (e - p < 4 || *err){
- *err = 1;
- return p;
- }
- PACK32(p, v);
- return p+4;
-}
-
-char*
-pack64(int *err, char *p, char *e, uvlong v)
-{
- if (e - p < 8 || *err){
- *err = 1;
- return p;
- }
- PACK64(p, v);
- return p+8;
-}
-
/* Terminated so we can use them directly in C */
char*
-packstr(int *err, char *p, char *e, char *s)
+packstr(char *p, char *e, char *s)
{
int n;
n = strlen(s);
- if (e - p < n+3 || *err){
- *err = 1;
- return p;
- }
+ if (e - p < n+3)
+ error(Elength);
PACK16(p, n); p += 2;
memmove(p, s, n); p += n;
*p = 0; p += 1;
@@ -135,13 +41,11 @@
{
char *ek, *ev, *eb;
- if((ek = packdkey(buf, nbuf, up, d->name)) == nil)
- return -1;
+ ek = packdkey(buf, nbuf, up, d->name);
kv->k = buf;
kv->nk = ek - buf;
eb = buf + nbuf;
- if((ev = packdval(ek, eb - ek, d)) == nil)
- return -1;
+ ev = packdval(ek, eb - ek, d);
kv->v = ek;
kv->nv = ev - ek;
return 0;
@@ -151,16 +55,12 @@
packdkey(char *p, int sz, vlong up, char *name)
{
char *ep;
- int err;
- err = 0;
ep = p + sz;
- p = pack8(&err, p, ep, Kent);
- p = pack64(&err, p, ep, up);
+ PACK8(p, Kent); p += 1;
+ PACK64(p, up); p += 8;
if(name != nil)
- p = packstr(&err, p, ep, name);
- if(err)
- return nil;
+ p = packstr(p, ep, name);
return p;
}
@@ -167,16 +67,15 @@
char*
unpackdkey(char *p, int sz, vlong *up)
{
- char t, *ep, *name;
- int err;
+ char key, *ep, *name;
- err = 0;
ep = p + sz;
- p = unpack8(&err, p, ep, &t);
- p = unpack64(&err, p, ep, up);
- p = unpackstr(&err, p, ep, &name);
- if(err || t != Kent || p != ep)
- return nil;
+ assert(sz > 9);
+ key = UNPACK8(p); p += 1;
+ *up = UNPACK64(p); p += 8;
+ assert(key == Kent);
+ p = unpackstr(p, ep, &name);
+ assert(p <= ep);
return name;
}
@@ -184,14 +83,11 @@
packsuper(char *p, int sz, vlong up)
{
char *ep;
- int err;
- err = 0;
- ep = p + sz;
- p = pack8(&err, p, ep, Kup);
- p = pack64(&err, p, ep, up);
- if(err)
- return nil;
+ ep = p+sz;
+ PACK8(p, Kup); p += 1;
+ PACK64(p, up); p += 8;
+ assert(p <= ep);
return p;
}
@@ -199,23 +95,20 @@
packdval(char *p, int sz, Xdir *d)
{
char *e;
- int err;
- err = 0;
e = p + sz;
- p = pack64(&err, p, e, d->flag);
- p = pack64(&err, p, e, d->qid.path);
- p = pack32(&err, p, e, d->qid.vers);
- p = pack8(&err, p, e, d->qid.type);
- p = pack32(&err, p, e, d->mode);
- p = pack64(&err, p, e, d->atime);
- p = pack64(&err, p, e, d->mtime);
- p = pack64(&err, p, e, d->length);
- p = pack32(&err, p, e, d->uid);
- p = pack32(&err, p, e, d->gid);
- p = pack32(&err, p, e, d->muid);
- if(err)
- return nil;
+ PACK64(p, d->flag); p += 8;
+ PACK64(p, d->qid.path); p += 8;
+ PACK32(p, d->qid.vers); p += 4;
+ PACK8(p, d->qid.type); p += 1;
+ PACK32(p, d->mode); p += 4;
+ PACK64(p, d->atime); p += 8;
+ PACK64(p, d->mtime); p += 8;
+ PACK64(p, d->length); p += 8;
+ PACK32(p, d->uid); p += 4;
+ PACK32(p, d->gid); p += 4;
+ PACK32(p, d->muid); p += 4;
+ assert(p <= e);
return p;
}
@@ -223,43 +116,30 @@
kv2dir(Kvp *kv, Xdir *d)
{
char *k, *ek, *v, *ev;
- int err;
memset(d, 0, sizeof(Xdir));
- err = 0;
k = kv->k + 9;
ek = kv->k + kv->nk;
- k = unpackstr(&err, k, ek, &d->name);
- if(err){
- werrstr("key too small [%d]", kv->nk);
- return -1;
- }
+ k = unpackstr(k, ek, &d->name);
v = kv->v;
ev = v + kv->nv;
- v = unpack64(&err, v, ev, &d->flag);
- v = unpack64(&err, v, ev, &d->qid.path);
- v = unpack32(&err, v, ev, &d->qid.vers);
- v = unpack8(&err, v, ev, &d->qid.type);
- v = unpack32(&err, v, ev, &d->mode);
- v = unpack64(&err, v, ev, &d->atime);
- v = unpack64(&err, v, ev, &d->mtime);
- v = unpack64(&err, v, ev, &d->length);
- v = unpack32(&err, v, ev, &d->uid);
- v = unpack32(&err, v, ev, &d->gid);
- v = unpack32(&err, v, ev, &d->muid);
- if(err){
- werrstr("val too small [%s]", d->name);
- return -1;
- }
- if(k != ek){
- werrstr("invalid path");
- return -1;
- }
- if(v != ev){
- werrstr("stat full of fuck");
- return -1;
- }
+ d->flag = UNPACK64(v); v += 8;
+ d->qid.path = UNPACK64(v); v += 8;
+ d->qid.vers = UNPACK32(v); v += 4;
+ d->qid.type = UNPACK8(v); v += 1;
+ d->mode = UNPACK32(v); v += 4;
+ d->atime = UNPACK64(v); v += 8;
+ d->mtime = UNPACK64(v); v += 8;
+ d->length = UNPACK64(v); v += 8;
+ d->uid = UNPACK32(v); v += 4;
+ d->gid = UNPACK32(v); v += 4;
+ d->muid = UNPACK32(v); v += 4;
+ assert(v <= ev);
+ if(k != ek)
+ error(Efs);
+ if(v != ev)
+ error(Efs);
return 0;
}
--- a/snap.c
+++ b/snap.c
@@ -7,7 +7,7 @@
#include "fns.h"
#include "atomic.h"
-static char*
+static void
dlsync(Dlist *dl)
{
char kvbuf[512];
@@ -14,14 +14,14 @@
Msg m;
if(dl->ins == nil)
- return nil;
+ return;
if(!checkflag(dl->ins, Bdirty))
- return nil;
+ return;
enqueue(dl->ins);
m.op = Oinsert;
dlist2kv(dl, &m, kvbuf, sizeof(kvbuf));
- return btupsert(&fs->snap, &m, 1);
+ btupsert(&fs->snap, &m, 1);
}
static void
@@ -81,7 +81,11 @@
if((dl = dlcacheget(gen, bgen)) != nil)
return dl;
if((dl = mallocz(sizeof(Dlist), 1)) == nil)
- return nil;
+ error(Enomem);
+ if(waserror()){
+ free(dl);
+ nexterror();
+ }
kbuf[0] = Kdlist;
PACK64(kbuf+1, gen);
PACK64(kbuf+9, bgen);
@@ -89,12 +93,10 @@
k.nk = sizeof(kbuf);
/* load up existing dlist */
- if(btlookup(&fs->snap, &k, &kv, kvbuf, sizeof(kvbuf)) == nil){
+ if(btlookup(&fs->snap, &k, &kv, kvbuf, sizeof(kvbuf))){
kv2dlist(&kv, dl);
- if(dl->hd.addr != -1 && (dl->ins = getblk(dl->hd, 0)) == nil){
- free(dl);
- return nil;
- }
+ if(dl->hd.addr != -1)
+ dl->ins = getblk(dl->hd, 0);
goto Found;
}
@@ -107,10 +109,8 @@
m.op = Oinsert;
dlist2kv(dl, &m, kvbuf, sizeof(kvbuf));
- if(btupsert(&fs->snap, &m, 1) != nil){
- free(dl);
- return nil;
- }
+ btupsert(&fs->snap, &m, 1);
+ poperror();
Found:
h = ihash(gen) ^ ihash(bgen);
p = &fs->dlcache[h % fs->dlcmax];
@@ -143,10 +143,10 @@
fs->dlhead = dl;
}
-char*
+void
freedl(Dlist *dl, int docontents)
{
- char *e, buf[Kvmax];
+ char buf[Kvmax];
Bptr bp, fb;
Msg m;
Blk *b;
@@ -156,12 +156,10 @@
if(dl != &fs->snapdl){
m.op = Odelete;
dlist2kv(dl, &m, buf, sizeof(buf));
- if((e = btupsert(&fs->snap, &m, 1)) != nil)
- return e;
+ btupsert(&fs->snap, &m, 1);
}
while(bp.addr != -1){
- if((b = getblk(bp, 0)) == nil)
- return Efs;
+ b = getblk(bp, 0);
if(docontents){
for(p = b->data; p != b->data+b->logsz; p += 8){
fb.addr = UNPACK64(p);
@@ -174,21 +172,25 @@
freeblk(&fs->snap, b, b->bp);
dropblk(b);
}
- return nil;
}
-static char*
+static void
mergedl(vlong merge, vlong gen, vlong bgen)
{
- char *e, buf[2][Kvmax];
+ char buf[2][Kvmax];
Dlist *d, *m;
Msg msg[2];
Blk *b;
- if((d = getdl(merge, bgen)) == nil)
- return Enomem;
- if((m = getdl(gen, bgen)) == nil)
- return Enomem;
+ d = nil;
+ m = nil;
+ if(waserror()){
+ putdl(m);
+ putdl(d);
+ nexterror();
+ }
+ d = getdl(merge, bgen);
+ m = getdl(gen, bgen);
/*
* If the dest dlist didn't exist,
* just move the merge dlist over
@@ -210,8 +212,6 @@
b = holdblk(d->ins);
else
b = getblk(d->tl, 0);
- if(b == nil)
- return Efs;
b->logp = m->hd;
setflag(b, Bdirty);
enqueue(b);
@@ -221,16 +221,16 @@
dlist2kv(m, &msg[0], buf[0], sizeof(buf[0]));
msg[1].op = Oinsert;
dlist2kv(d, &msg[1], buf[1], sizeof(buf[1]));
- e = btupsert(&fs->snap, msg, 2);
+ btupsert(&fs->snap, msg, 2);
putdl(m);
putdl(d);
- return e;
+ poperror();
}
-static char*
+static void
reclaimblocks(vlong gen, vlong succ, vlong prev)
{
- char *e, pfx[9];
+ char pfx[9];
Dlist dl;
Scan s;
@@ -237,26 +237,24 @@
pfx[0] = Kdlist;
PACK64(pfx+1, gen);
btnewscan(&s, pfx, sizeof(pfx));
- if((e = btenter(&fs->snap, &s)) != nil)
- return e;
+ btenter(&fs->snap, &s);
+ if(waserror()){
+ btexit(&s);
+ nexterror();
+ }
while(1){
- if((e = btnext(&s, &s.kv)) != nil)
+ if(!btnext(&s, &s.kv))
break;
- if(s.done)
- break;
kv2dlist(&s.kv, &dl);
if(succ != -1 && dl.bgen <= prev)
- e = mergedl(succ, dl.gen, dl.bgen);
+ mergedl(succ, dl.gen, dl.bgen);
else if(dl.bgen <= prev)
- e = mergedl(prev, dl.gen, dl.bgen);
+ mergedl(prev, dl.gen, dl.bgen);
else
- e = freedl(&dl, 1);
- if(e != nil)
- break;
+ freedl(&dl, 1);
}
btexit(&s);
- return e;
}
/*
@@ -267,10 +265,10 @@
* If it has one successor and no label, then
* it will be merged with that successor.
*/
-char*
+void
delsnap(Tree *t, vlong succ, char *name)
{
- char buf[4][Kvmax], *e;
+ char *p, buf[4][Kvmax];
int nm, deltree;
Mount *mnt;
Msg m[4];
@@ -281,13 +279,12 @@
if(strcmp(name, "dump") == 0
|| strcmp(name, "empty") == 0
|| strcmp(name, "adm") == 0)
- return Ename;
+ error(Ename);
m[nm].op = Odelete;
m[nm].k = buf[nm];
- if((e = packlbl(buf[nm], sizeof(buf[nm]), name)) == nil)
- return Ename;
- m[nm].nk = e - m[nm].k;
+ p = packlbl(buf[nm], sizeof(buf[nm]), name);
+ m[nm].nk = p - m[nm].k;
m[nm].v = nil;
m[nm].nv = 0;
t->nlbl--;
@@ -306,20 +303,16 @@
}
m[nm].op = Odelete;
m[nm].k = buf[nm];
- if((e = packsnap(buf[nm], sizeof(buf[nm]), t->gen)) == nil)
- return Ename;
- m[nm].nk = e - m[nm].k;
+ p = packsnap(buf[nm], sizeof(buf[nm]), t->gen);
+ m[nm].nk = p - m[nm].k;
m[nm].v = nil;
m[nm].nv = 0;
nm++;
}
assert(nm <= nelem(m));
- if((e = flushdlcache(1)) != nil)
- return e;
- if((e = btupsert(&fs->snap, m, nm)) != nil)
- return e;
- if((e = reclaimblocks(t->gen, succ, t->pred)) != nil)
- return e;
+ flushdlcache(1);
+ btupsert(&fs->snap, m, nm);
+ reclaimblocks(t->gen, succ, t->pred);
if(deltree){
for(mnt = fs->mounts; mnt != nil; mnt = mnt->next){
if(mnt->root->gen == t->succ)
@@ -328,7 +321,6 @@
mnt->root->succ = t->succ;
}
}
- return nil;
}
/*
@@ -336,7 +328,7 @@
* its reference count. This labelled snapshot
* will show up in the dump.
*/
-char*
+void
tagsnap(Tree *t, char *name, int mutable)
{
char buf[3][Kvmax];
@@ -347,12 +339,17 @@
if(strcmp(name, "dump") == 0
|| strcmp(name, "empty") == 0
|| strcmp(name, "adm") == 0)
- return Ename;
+ error(Ename);
i = 0;
+ n = nil;
+ if(waserror()){
+ free(n);
+ nexterror();
+ }
if(mutable){
if((n = mallocz(sizeof(Tree), 1)) == nil)
- return Enomem;
+ error(Enomem);
n->memref = 1;
n->dirty = 0;
n->nlbl = 1;
@@ -387,7 +384,9 @@
lbl2kv(name, t->gen, 0, &m[i], buf[i], sizeof(buf[i]));
i++;
}
- return btupsert(&fs->snap, m, i);
+ btupsert(&fs->snap, m, i);
+ poperror();
+ free(n);
}
/*
@@ -397,16 +396,16 @@
* list; once it's observable by a derived snapshot it must be
* immutable.
*/
-char*
+void
updatesnap(Tree **r, Tree *o, char *lbl)
{
- char buf[4][Kvmax], *e;
+ char buf[4][Kvmax];
Msg m[4];
Tree *t;
int i;
if(!o->dirty)
- return nil;
+ return;
/* update the old kvp */
o->nlbl--;
@@ -415,7 +414,11 @@
/* create the new one */
if((t = mallocz(sizeof(Tree), 1)) == nil)
- return Enomem;
+ error(Enomem);
+ if(waserror()){
+ free(t);
+ nexterror();
+ }
t->memref = 1;
t->dirty = 0;
@@ -445,10 +448,7 @@
m[i].op = Oinsert;
lbl2kv(lbl, t->gen, Lmut, &m[i], buf[i], sizeof(buf[i]));
i++;
- if((e = btupsert(&fs->snap, m, i)) != nil){
- free(t);
- return e;
- }
+ btupsert(&fs->snap, m, i);
/* only update the dirty status after we sync */
o->dirty = 0;
@@ -458,7 +458,7 @@
delsnap(o, t->gen, nil);
closesnap(o);
asetp(r, t);
- return nil;
+ poperror();
}
/*
@@ -479,7 +479,7 @@
return nil;
k.k = buf;
k.nk = p - buf;
- if(btlookup(&fs->snap, &k, &kv, buf, sizeof(buf)) != nil)
+ if(!btlookup(&fs->snap, &k, &kv, buf, sizeof(buf)))
return nil;
assert(kv.nv == 1+8+4);
gen = UNPACK64(kv.v + 1);
@@ -488,21 +488,21 @@
*mut = !!(flg&Lmut);
if((t = mallocz(sizeof(Tree), 1)) == nil)
- goto Error;
- if((p = packsnap(buf, sizeof(buf), gen)) == nil)
- goto Error;
+ error(Enomem);
+ if(waserror()){
+ free(t);
+ nexterror();
+ }
+ p = packsnap(buf, sizeof(buf), gen);
k.k = buf;
k.nk = p - buf;
- if(btlookup(&fs->snap, &k, &kv, buf, sizeof(buf)) != nil)
- abort();
- if(unpacktree(t, kv.v, kv.nv) == nil)
- abort();
+ if(!btlookup(&fs->snap, &k, &kv, buf, sizeof(buf)))
+ broke(Efs);
+ unpacktree(t, kv.v, kv.nv);
t->memref = 1;
t->memgen = aincv(&fs->nextgen, 1);
+ poperror();
return t;
-Error:
- free(t);
- return nil;
}
/*
@@ -523,16 +523,14 @@
limbo(f);
}
-char*
+void
flushdlcache(int clear)
{
Dlist *dl, *n;
- char *e;
for(dl = fs->dlhead; dl != nil; dl = n){
n = dl->cnext;
- if((e = dlsync(dl)) != nil)
- return e;
+ dlsync(dl);
if(clear){
if(dl->ins != nil)
dropblk(dl->ins);
@@ -544,7 +542,6 @@
fs->dltail = nil;
memset(fs->dlcache, 0, fs->dlcmax*sizeof(Dlist*));
}
- return nil;
}
/*
--- a/tree.c
+++ b/tree.c
@@ -654,7 +654,7 @@
if(waserror()){
efreeblk(t, l);
efreeblk(t, r);
- return;
+ nexterror();
}
l = newblk(t, b->type);
r = newblk(t, b->type);
@@ -752,7 +752,7 @@
if(waserror()){
efreeblk(t, l);
efreeblk(t, r);
- return;
+ nexterror();
}
l = newblk(t, b->type);
r = newblk(t, b->type);
@@ -794,6 +794,7 @@
p->op = POsplit;
p->nl = l;
p->nr = r;
+ poperror();
}
static void
@@ -885,7 +886,7 @@
if(waserror()){
efreeblk(t, l);
efreeblk(t, r);
- return;
+ nexterror();
}
l = newblk(t, a->type);
r = newblk(t, a->type);
@@ -1201,7 +1202,7 @@
}
-char*
+void
btupsert(Tree *t, Msg *msg, int nmsg)
{
int i, npath, npull, dh, sz, height;
@@ -1219,8 +1220,9 @@
npath = 0;
if(waserror()){
freepath(t, path, npath);
- return errmsg();
+ nexterror();
}
+int eb;
Again:
b = getroot(t, &height);
@@ -1227,7 +1229,7 @@
if(b->type == Tpivot && !filledbuf(b, nmsg, sz)){
fastupsert(t, b, msg, nmsg);
poperror();
- return nil;
+ return;
}
/*
@@ -1237,7 +1239,7 @@
*/
npath = 0;
if((path = calloc((height + 2), sizeof(Path))) == nil)
- return Enomem;
+ error(Enomem);
path[npath].b = nil;
path[npath].idx = -1;
path[npath].midx = -1;
@@ -1292,7 +1294,6 @@
if(npull != nmsg)
goto Again;
poperror();
- return nil;
}
Blk*
@@ -1309,7 +1310,7 @@
return getblk(bp, 0);
}
-char*
+int
btlookup(Tree *t, Key *k, Kvp *r, char *buf, int nbuf)
{
int i, j, h, ok, same;
@@ -1316,15 +1317,12 @@
Blk *b, **p;
Bptr bp;
Msg m;
- char *err;
- if((b = getroot(t, &h)) == nil)
- return Efs;
+ b = getroot(t, &h);
if((p = calloc(h, sizeof(Blk*))) == nil){
dropblk(b);
- return Enomem;
+ error(Enomem);
}
- err = Esrch;
ok = 0;
p[0] = holdblk(b);
for(i = 1; i < h; i++){
@@ -1331,10 +1329,7 @@
if(blksearch(p[i-1], k, r, &same) == -1)
break;
bp = unpackbp(r->v, r->nv);
- if((p[i] = getblk(bp, 0)) == nil){
- err = Efs;
- goto Out;
- }
+ p[i] = getblk(bp, 0);
}
if(p[h-1] != nil)
blksearch(p[h-1], k, r, &ok);
@@ -1356,22 +1351,20 @@
ok = apply(r, &m, buf, nbuf);
}
}
- if(ok)
- err = nil;
-Out:
for(i = 0; i < h; i++)
if(p[i] != nil)
dropblk(p[i]);
dropblk(b);
free(p);
- return err;
+ return ok;
}
void
btnewscan(Scan *s, char *pfx, int npfx)
{
+ memset(s, 0, sizeof(*s));
s->first = 1;
- s->done = 0;
+ s->donescan = 0;
s->offset = 0;
s->pfx.k = s->pfxbuf;
s->pfx.nk = npfx;
@@ -1382,7 +1375,7 @@
cpkey(&s->kv, &s->pfx, s->kvbuf, sizeof(s->kvbuf));
}
-char*
+void
btenter(Tree *t, Scan *s)
{
int i, same;
@@ -1392,13 +1385,12 @@
Blk *b;
Kvp v;
- if(s->done)
- return nil;
- if((b = getroot(t, &s->ht)) == nil)
- return Eio;
+ if(s->donescan)
+ return;
+ b = getroot(t, &s->ht);
if((s->path = calloc(s->ht, sizeof(Scanp))) == nil){
dropblk(b);
- return Enomem;
+ error(Enomem);
}
p = s->path;
p[0].b = b;
@@ -1420,17 +1412,15 @@
}
}
bp = unpackbp(v.v, v.nv);
- if((b = getblk(bp, 0)) == nil)
- return Eio;
+ b = getblk(bp, 0);
p[i+1].b = b;
}else if(p[i].vi == -1 || !same || !s->first)
p[i].vi++;
}
s->first = 0;
- return nil;
}
-char *
+int
btnext(Scan *s, Kvp *r)
{
int i, j, h, ok, start, bufsrc;
@@ -1444,8 +1434,12 @@
h = s->ht;
start = h;
bufsrc = -1;
- if(s->done)
- return nil;
+ if(s->donescan)
+ return 0;
+ if(waserror()){
+ btexit(s);
+ nexterror();
+ }
/* load up the correct blocks for the scan */
for(i = h-1; i >= 0; i--){
if(p[i].b != nil
@@ -1452,8 +1446,9 @@
&&(p[i].vi < p[i].b->nval || p[i].bi < p[i].b->nbuf))
break;
if(i == 0){
- s->done = 1;
- return nil;
+ s->donescan = 1;
+ poperror();
+ return 0;
}
if(p[i].b != nil)
dropblk(p[i].b);
@@ -1468,8 +1463,7 @@
for(i = start; i < h; i++){
getval(p[i-1].b, p[i-1].vi, &kv);
bp = unpackbp(kv.v, kv.nv);
- if((p[i].b = getblk(bp, 0)) == nil)
- return "error reading block";
+ p[i].b = getblk(bp, 0);
}
/* find the minimum key along the path up */
@@ -1491,8 +1485,9 @@
}
}
if(m.nk < s->pfx.nk || memcmp(m.k, s->pfx.k, s->pfx.nk) != 0){
- s->done = 1;
- return nil;
+ s->donescan = 1;
+ poperror();
+ return 0;
}
/* scan all messages applying to the message */
@@ -1511,9 +1506,10 @@
p[i].bi++;
}
}
+ poperror();
if(!ok)
goto Again;
- return nil;
+ return 1;
}
void
--- a/user.c
+++ b/user.c
@@ -9,7 +9,7 @@
static char*
slurp(Tree *t, vlong path, vlong len)
{
- char *e, *ret, buf[Offksz], kvbuf[Offksz + Ptrsz];
+ char *ret, buf[Offksz], kvbuf[Offksz + Ptrsz];
vlong o;
Blk *b;
Bptr bp;
@@ -17,7 +17,7 @@
Kvp kv;
if((ret = malloc(len + 1)) == nil)
- return Enomem;
+ error(Enomem);
k.k = buf;
k.nk = Offksz;
for(o = 0; o < len; o += Blksz){
@@ -24,11 +24,10 @@
k.k[0] = Kdat;
PACK64(k.k+1, path);
PACK64(k.k+9, o);
- if((e = btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf))) != nil)
- return e;
+ if(!btlookup(t, &k, &kv, kvbuf, sizeof(kvbuf)))
+ error(Esrch);
bp = unpackbp(kv.v, kv.nv);
- if((b = getblk(bp, GBraw)) == nil)
- return Eio;
+ b = getblk(bp, GBraw);
if(len - o >= Blksz)
memcpy(ret + o, b->buf, Blksz);
else
@@ -216,7 +215,7 @@
}
-char*
+void
loadusers(int fd, Tree *t)
{
char *s, *e;
@@ -224,16 +223,16 @@
Qid q;
if(walk1(t, -1, "", &q, &len) == -1)
- return Efs;
+ error(Efs);
if(walk1(t, q.path, "users", &q, &len) == -1)
- return Eio;
+ error(Esrch);
if(q.type != QTFILE)
- return Etype;
+ error(Etype);
if(len >= 1*MiB)
- return Efsize;
- if((s = slurp(t, q.path, len)) == nil)
- return Eio;
+ error(Efsize);
+ s = slurp(t, q.path, len);
e = parseusers(fd, s);
+ if(e != nil)
+ error(e);
free(s);
- return e;
}