289 lines · 4.0 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #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 voiddestroy(Fid *f){	State *s; 	s = f->aux;	if(s->e)		edestroy(s->e);	if(s->r)		edirclose(s->r);	free(s);} static voidtrace(Req *){	edump();} /** T_ **/ static voidflattach(Req *r){	root->ref++;	r->ofcall.qid = eqid(root);	r->fid->aux = state(root);	respond(r, nil);} static voidflopen(Req *r){	int m, p;	Entry *e;	State *s; 	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)		s->r = ediropen(s->e);	else if(r->ifcall.mode & OTRUNC)		etrunc(e, 0, time(0)); 	respond(r, nil);} static voidflcreate(Req *r){	State *s;	char *err;	Entry *e, *f; 	if(readonly) {		respond(r, Erofs);		return;	} 	s = r->fid->aux;	e = s->e;	if(!writeable(e)) {		respond(r, Eperm);		return;	} 	f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, time(0), &err);	if(f == nil) {		respond(r, err);		return;	} 	s->e = f;	r->ofcall.qid = eqid(f);	respond(r, nil);} static voidflread(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 = 0; 	respond(r, nil);} static voidflwrite(Req *r){	if(r->ifcall.offset + r->ifcall.count >= MAXFSIZE) {		respond(r, "file too big");		return;	} 	r->ofcall.count = r->ifcall.count;	respond(r, nil);} static voidflremove(Req *r){	State *s;	Entry *e; 	if(readonly) {		respond(r, Erofs);		return;	} 	s = r->fid->aux;	e = s->e;	if(writeable(e->parent))		respond(r, eremove(e));	else		respond(r, Eperm);} static voidflstat(Req *r){	State *s; 	s = r->fid->aux;	estat(s->e, &r->d, 1);	respond(r, nil);} static voidflwstat(Req *r){	int m;	State *s;	Entry *e; 	s = r->fid->aux;	e = s->e;	m = r->d.mode & 0777;	if(m != (e->mode & 0777))		echmod(e, m, 0);	respond(r, nil);} static voidflwalk(Req *r){	int i;	State *s;	char *err;	Entry *e, *f; 	if(readonly) {		respond(r, Erofs);		return;	} 	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(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);} voidserve(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;	einit();	postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE);}