Charles.Forsyth20060303-partialeea662d19 years agoHistory
198 lines · 3.6 KB · C
RawDownload
#include <lib9.h>#include "styxserver.h" /* * An in-memory file server * allowing truncation, removal on closure, wstat and * all other file operations */ char *fsremove(Qid); Styxserver *server; char*fsopen(Qid *qid, int mode){	Styxfile *f; 	f = styxfindfile(server, qid->path);	if(mode&OTRUNC){	/* truncate on open */		styxfree(f->u);		f->u = nil;		f->d.length = 0;	}	return nil;} char*fsclose(Qid qid, int mode){	if(mode&ORCLOSE)	/* remove on close */		return fsremove(qid);	return nil;} char *fscreate(Qid *qid, char *name, int perm, int mode){	int isdir;	Styxfile *f; 	USED(mode);	isdir = perm&DMDIR;	if(isdir)		f = styxadddir(server, qid->path, -1, name, perm, "inferno");	else		f = styxaddfile(server, qid->path, -1, name, perm, "inferno");	if(f == nil)		return Eexist;	f->u = nil;	f->d.length = 0;	*qid = f->d.qid;	return nil;} char *fsremove(Qid qid){	Styxfile *f; 	f = styxfindfile(server, qid.path);	if((f->d.qid.type&QTDIR) && f->child != nil)		return "directory not empty";	styxfree(f->u);	styxrmfile(server, qid.path);		return nil;} char *fsread(Qid qid, char *buf, ulong *n, vlong off){	int m;	Styxfile *f; 	f = styxfindfile(server, qid.path);	m = f->d.length;	if(off >= m)		*n = 0;	else{		if(off + *n > m)			*n = m-off;		memmove(buf, (char*)f->u+off, *n);	}	return nil;} char*fswrite(Qid qid, char *buf, ulong *n, vlong off){	Styxfile *f;	vlong m, p;	char *u; 	f = styxfindfile(server, qid.path);	m = f->d.length;	p = off + *n;	if(p > m){	/* just grab a larger piece of memory */		u = styxmalloc(p);		if(u == nil)			return "out of memory";		memset(u, 0, p);		memmove(u, f->u, m);		styxfree(f->u);		f->u = u;		f->d.length = p;	}	memmove((char*)f->u+off, buf, *n);	return nil;} char*fswstat(Qid qid, Dir *d){	Styxfile *f, *tf;	Client *c;	int owner; 	/* the most complicated operation when fully allowed */ 	c = styxclient(server);	f = styxfindfile(server, qid.path);	owner = strcmp(c->uname, f->d.uid) == 0;	if(d->name != nil && strcmp(d->name, f->d.name) != 0){		/* need write permission in parent directory */		if(!styxperm(f->parent, c->uname, OWRITE))			return Eperm;		if((tf = styxaddfile(server, f->parent->d.qid.path, -1, d->name, 0, "")) == nil){			/* file with same name exists */			return Eexist;		}		else{			/* undo above addfile */			styxrmfile(server, tf->d.qid.path);		}		/* ok to change name now */		styxfree(f->d.name);		f->d.name = strdup(d->name);		}	if(d->uid != nil && strcmp(d->uid, f->d.uid) != 0){		if(!owner)			return Eperm;		styxfree(f->d.uid);		f->d.uid = strdup(d->uid);	}	if(d->gid != nil && strcmp(d->gid, f->d.gid) != 0){		if(!owner)			return Eperm;		styxfree(f->d.gid);		f->d.gid = strdup(d->gid);	}	if(d->mode != ~0 && d->mode != f->d.mode){		if(!owner)			return Eperm;		if(d->mode&DMDIR != f->d.mode&DMDIR)			return Eperm;	/* cannot change file->directory or vice-verse */		f->d.mode = d->mode;	}	if(d->mtime != ~0 && d->mtime != f->d.mtime){		if(!owner)			return Eperm;		f->d.mtime = d->mtime;	}	/* all other file attributes cannot be changed by wstat */	return nil;} Styxops ops = {	nil,			/* newclient */	nil,			/* freeclient */ 	nil,			/* attach */	nil,			/* walk */	fsopen,		/* open */	fscreate,		/* create */	fsread,		/* read */	fswrite,		/* write */	fsclose,		/* close */	fsremove,	/* remove */	nil,			/* stat */	fswstat,		/* wstat */}; main(int argc, char **argv){	Styxserver s; 	USED(argc);	USED(argv);	server = &s;	styxdebug();	styxinit(&s, &ops, "6701", 0777, 1);	for(;;){		styxwait(&s);		styxprocess(&s);	}	return 0;}