diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/flashfs/request.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/flashfs/request.c')
-rwxr-xr-x | sys/src/cmd/aux/flashfs/request.c | 422 |
1 files changed, 422 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/flashfs/request.c b/sys/src/cmd/aux/flashfs/request.c new file mode 100755 index 000000000..3023f1c5c --- /dev/null +++ b/sys/src/cmd/aux/flashfs/request.c @@ -0,0 +1,422 @@ +#include <u.h> +#include <libc.h> +#include <auth.h> +#include <fcall.h> +#include <thread.h> +#include <9p.h> +#include "flashfs.h" + +static Srv flashsrv; + +typedef struct State State; + +struct State +{ + Entry *e; + Dirr *r; +}; + +#define writeable(e) ((e)->mode & 0222) + +static State * +state(Entry *e) +{ + State *s; + + s = emalloc9p(sizeof(State)); + s->e = e; + s->r = nil; + return s; +} + +static void +destroy(Fid *f) +{ + State *s; + + s = f->aux; + if(s == nil) /* Tauth fids have no state */ + return; + + f->aux = nil; + if(s->e) + edestroy(s->e); + if(s->r) + edirclose(s->r); + free(s); +} + +static void +trace(Req *) +{ + edump(); +} + +/** T_ **/ + +static void +flattach(Req *r) +{ + root->ref++; + r->ofcall.qid = eqid(root); + r->fid->qid = r->ofcall.qid; + r->fid->aux = state(root); + respond(r, nil); +} + +static void +flopen(Req *r) +{ + Jrec j; + int m, p; + Entry *e; + State *s; + char *err; + + s = r->fid->aux; + e = s->e; + m = e->mode; + m = (m | (m >> 3) | (m >> 6)) & 7; + switch(r->ifcall.mode & 3) { + case OREAD: + p = AREAD; + break; + case OWRITE: + p = AWRITE; + break; + case ORDWR: + p = AREAD|AWRITE; + break; + case OEXEC: + p = AEXEC; + break; + default: + p = 0; + break; + } + + if((p & m) != p) { + respond(r, Eperm); + return; + } + + if(readonly && (p & AWRITE) != 0) { + respond(r, Erofs); + return; + } + + r->ofcall.qid = eqid(e); + if(r->ofcall.qid.type & QTDIR) { + if((p & AWRITE) != 0) { + respond(r, Eisdir); + return; + } + s->r = ediropen(s->e); + } + else if(r->ifcall.mode & OTRUNC) { + err = need(Ntrunc); + if(err != nil) { + respond(r, err); + return; + } + j.type = FT_trunc; + j.tnum = e->fnum; + j.mtime = now(); + etrunc(e, 0, j.mtime); + j.fnum = e->fnum; + j.parent = e->parent->fnum; + j.mode = e->mode; + strcpy(j.name, e->name); + put(&j, 1); + } + + respond(r, nil); +} + +static void +flcreate(Req *r) +{ + Jrec j; + State *s; + char *err; + Entry *e, *f; + + if(readonly) { + respond(r, Erofs); + return; + } + + s = r->fid->aux; + e = s->e; + if((e->mode & DMDIR) == 0) { + respond(r, Eisdir); + return; + } + + if(!writeable(e)) { + respond(r, Eperm); + return; + } + + if(strlen(r->ifcall.name) > MAXNSIZE) { + respond(r, "filename too long"); + return; + } + + err = need(Ncreate); + if(err != nil) { + respond(r, err); + return; + } + + j.type = FT_create; + j.mtime = now(); + j.parent = e->fnum; + j.mode = r->ifcall.perm; + strcpy(j.name, r->ifcall.name); + + f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, j.mtime, &err); + if(f == nil) { + respond(r, err); + return; + } + + j.fnum = f->fnum; + put(&j, 1); + s->e = f; + r->ofcall.qid = eqid(f); + respond(r, nil); +} + +static void +flread(Req *r) +{ + Entry *e; + State *s; + + s = r->fid->aux; + e = s->e; + + if(e->mode & DMDIR) + r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count); + else + r->ofcall.count = eread(e, eparity, r->ofcall.data, r->ifcall.count, r->ifcall.offset); + + respond(r, nil); +} + +static void +flwrite(Req *r) +{ + Jrec j; + uchar *a; + Entry *e; + State *s; + Extent *x; + char *err; + ulong c, n, o, mtime; + + c = r->ifcall.count; + o = r->ifcall.offset; + a = (uchar *)r->ifcall.data; + + if(c == 0) { + respond(r, nil); + return; + } + + if(o + c >= MAXFSIZE) { + respond(r, "file too big"); + return; + } + + if(used + c > limit) { + respond(r, "filesystem full"); + return; + } + + r->ofcall.count = c; + s = r->fid->aux; + e = s->e; + mtime = now(); + + for(;;) { + n = c; + if(n > maxwrite) + n = maxwrite; + + err = need(Nwrite + n); + if(err != nil) { + respond(r, err); + return; + } + + x = emalloc9p(sizeof(Extent)); + x->size = n; + x->off = o; + ewrite(e, x, eparity, mtime); + j.type = FT_WRITE; + j.fnum = e->fnum; + j.size = n; + j.offset = o; + j.mtime = mtime; + putw(&j, 1, x, a); + c -= n; + + if(c == 0) + break; + + o += n; + a += n; + } + + respond(r, nil); +} + +static void +flremove(Req *r) +{ + Jrec j; + State *s; + Entry *e; + char *d, *err; + + if(readonly) { + respond(r, Erofs); + return; + } + + s = r->fid->aux; + e = s->e; + if(writeable(e->parent)) { + err = need(Nremove); + if(err != nil) { + respond(r, err); + return; + } + + d = eremove(e); + if(d == nil) { + j.type = FT_REMOVE; + j.fnum = e->fnum; + put(&j, 0); + } + respond(r, d); + } + else + respond(r, Eperm); +} + +static void +flstat(Req *r) +{ + State *s; + + s = r->fid->aux; + estat(s->e, &r->d, 1); + respond(r, nil); +} + +static void +flwstat(Req *r) +{ + int m; + Jrec j; + State *s; + Entry *e; + char *err; + + s = r->fid->aux; + e = s->e; + + if(readonly) { + respond(r, Erofs); + return; + } + + if(e->fnum == 0) { + respond(r, Eperm); + return; + } + + m = r->d.mode & 0777; + if(m != (e->mode & 0777)) { + err = need(Nchmod); + if(err != nil) { + respond(r, err); + return; + } + + echmod(e, m, 0); + j.type = FT_chmod; + j.mode = m; + j.fnum = e->fnum; + j.mnum = e->mnum; + put(&j, 0); + } + respond(r, nil); +} + +static void +flwalk(Req *r) +{ + int i; + State *s; + char *err; + Entry *e, *f; + + if(r->ifcall.fid != r->ifcall.newfid) + r->newfid->aux = state(nil); + + s = r->fid->aux; + e = s->e; + f = e; + e->ref++; + err = nil; + for(i = 0; i < r->ifcall.nwname; i++) { + f = ewalk(e, r->ifcall.wname[i], &err); + if(f) { + r->ofcall.wqid[i] = eqid(f); + e = f; + } + else { + e->ref--; + break; + } + } + r->ofcall.nwqid = i; + if (i) err = nil; + + if(f) { + if(r->ifcall.fid != r->ifcall.newfid) { + s = r->newfid->aux; + s->e = f; + r->newfid->qid = eqid(f); + } + else { + s = r->fid->aux; + s->e->ref--; + s->e = f; + r->fid->qid = eqid(f); + } + } + respond(r, err); +} + +void +serve(char *mount) +{ + flashsrv.attach = flattach; + flashsrv.open = flopen; + flashsrv.create = flcreate; + flashsrv.read = flread; + flashsrv.write = flwrite; + flashsrv.remove = flremove; + flashsrv.stat = flstat; + flashsrv.wstat = flwstat; + flashsrv.walk = flwalk; + + flashsrv.destroyfid = destroy; + flashsrv.destroyreq = trace; + postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE); +} |