summaryrefslogtreecommitdiff
path: root/tools/styxtest/styxtest.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 20:52:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 20:52:35 +0000
commit46439007cf417cbd9ac8049bb4122c890097a0fa (patch)
tree6fdb25e5f3a2b6d5657eb23b35774b631d4d97e4 /tools/styxtest/styxtest.c
parent37da2899f40661e3e9631e497da8dc59b971cbd0 (diff)
20060303-partial
Diffstat (limited to 'tools/styxtest/styxtest.c')
-rw-r--r--tools/styxtest/styxtest.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/tools/styxtest/styxtest.c b/tools/styxtest/styxtest.c
new file mode 100644
index 00000000..a6cca89f
--- /dev/null
+++ b/tools/styxtest/styxtest.c
@@ -0,0 +1,198 @@
+#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;
+}
+