summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/flashfs/request.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/cmd/aux/flashfs/request.c422
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);
+}