1 #include <lib9.h> 2 #include "styxserver.h" 3 4 /* 5 * An in-memory file server 6 * allowing truncation, removal on closure, wstat and 7 * all other file operations 8 */ 9 10 char *fsremove(Qid); 11 12 Styxserver *server; 13 14 char* 15 fsopen(Qid *qid, int mode) 16 { 17 Styxfile *f; 18 19 f = styxfindfile(server, qid->path); 20 if(mode&OTRUNC){ /* truncate on open */ 21 styxfree(f->u); 22 f->u = nil; 23 f->d.length = 0; 24 } 25 return nil; 26 } 27 28 char* 29 fsclose(Qid qid, int mode) 30 { 31 if(mode&ORCLOSE) /* remove on close */ 32 return fsremove(qid); 33 return nil; 34 } 35 36 char * 37 fscreate(Qid *qid, char *name, int perm, int mode) 38 { 39 int isdir; 40 Styxfile *f; 41 42 USED(mode); 43 isdir = perm&DMDIR; 44 if(isdir) 45 f = styxadddir(server, qid->path, -1, name, perm, "inferno"); 46 else 47 f = styxaddfile(server, qid->path, -1, name, perm, "inferno"); 48 if(f == nil) 49 return Eexist; 50 f->u = nil; 51 f->d.length = 0; 52 *qid = f->d.qid; 53 return nil; 54 } 55 56 char * 57 fsremove(Qid qid) 58 { 59 Styxfile *f; 60 61 f = styxfindfile(server, qid.path); 62 if((f->d.qid.type&QTDIR) && f->child != nil) 63 return "directory not empty"; 64 styxfree(f->u); 65 styxrmfile(server, qid.path); 66 return nil; 67 } 68 69 char * 70 fsread(Qid qid, char *buf, ulong *n, vlong off) 71 { 72 int m; 73 Styxfile *f; 74 75 f = styxfindfile(server, qid.path); 76 m = f->d.length; 77 if(off >= m) 78 *n = 0; 79 else{ 80 if(off + *n > m) 81 *n = m-off; 82 memmove(buf, (char*)f->u+off, *n); 83 } 84 return nil; 85 } 86 87 char* 88 fswrite(Qid qid, char *buf, ulong *n, vlong off) 89 { 90 Styxfile *f; 91 vlong m, p; 92 char *u; 93 94 f = styxfindfile(server, qid.path); 95 m = f->d.length; 96 p = off + *n; 97 if(p > m){ /* just grab a larger piece of memory */ 98 u = styxmalloc(p); 99 if(u == nil) 100 return "out of memory"; 101 memset(u, 0, p); 102 memmove(u, f->u, m); 103 styxfree(f->u); 104 f->u = u; 105 f->d.length = p; 106 } 107 memmove((char*)f->u+off, buf, *n); 108 return nil; 109 } 110 111 char* 112 fswstat(Qid qid, Dir *d) 113 { 114 Styxfile *f, *tf; 115 Client *c; 116 int owner; 117 118 /* the most complicated operation when fully allowed */ 119 120 c = styxclient(server); 121 f = styxfindfile(server, qid.path); 122 owner = strcmp(c->uname, f->d.uid) == 0; 123 if(d->name != nil && strcmp(d->name, f->d.name) != 0){ 124 /* need write permission in parent directory */ 125 if(!styxperm(f->parent, c->uname, OWRITE)) 126 return Eperm; 127 if((tf = styxaddfile(server, f->parent->d.qid.path, -1, d->name, 0, "")) == nil){ 128 /* file with same name exists */ 129 return Eexist; 130 } 131 else{ 132 /* undo above addfile */ 133 styxrmfile(server, tf->d.qid.path); 134 } 135 /* ok to change name now */ 136 styxfree(f->d.name); 137 f->d.name = strdup(d->name); 138 } 139 if(d->uid != nil && strcmp(d->uid, f->d.uid) != 0){ 140 if(!owner) 141 return Eperm; 142 styxfree(f->d.uid); 143 f->d.uid = strdup(d->uid); 144 } 145 if(d->gid != nil && strcmp(d->gid, f->d.gid) != 0){ 146 if(!owner) 147 return Eperm; 148 styxfree(f->d.gid); 149 f->d.gid = strdup(d->gid); 150 } 151 if(d->mode != ~0 && d->mode != f->d.mode){ 152 if(!owner) 153 return Eperm; 154 if(d->mode&DMDIR != f->d.mode&DMDIR) 155 return Eperm; /* cannot change file->directory or vice-verse */ 156 f->d.mode = d->mode; 157 } 158 if(d->mtime != ~0 && d->mtime != f->d.mtime){ 159 if(!owner) 160 return Eperm; 161 f->d.mtime = d->mtime; 162 } 163 /* all other file attributes cannot be changed by wstat */ 164 return nil; 165 } 166 167 Styxops ops = { 168 nil, /* newclient */ 169 nil, /* freeclient */ 170 171 nil, /* attach */ 172 nil, /* walk */ 173 fsopen, /* open */ 174 fscreate, /* create */ 175 fsread, /* read */ 176 fswrite, /* write */ 177 fsclose, /* close */ 178 fsremove, /* remove */ 179 nil, /* stat */ 180 fswstat, /* wstat */ 181 }; 182 183 main(int argc, char **argv) 184 { 185 Styxserver s; 186 187 USED(argc); 188 USED(argv); 189 server = &s; 190 styxdebug(); 191 styxinit(&s, &ops, "6701", 0777, 1); 192 for(;;){ 193 styxwait(&s); 194 styxprocess(&s); 195 } 196 return 0; 197 } 198 199