1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <fcall.h> 5 #include <thread.h> 6 #include <9p.h> 7 #include "flashfs.h" 8 9 static Srv flashsrv; 10 11 typedef struct State State; 12 13 struct State 14 { 15 Entry *e; 16 Dirr *r; 17 }; 18 19 #define writeable(e) ((e)->mode & 0222) 20 21 static State * 22 state(Entry *e) 23 { 24 State *s; 25 26 s = emalloc9p(sizeof(State)); 27 s->e = e; 28 s->r = nil; 29 return s; 30 } 31 32 static void 33 destroy(Fid *f) 34 { 35 State *s; 36 37 s = f->aux; 38 if(s->e) 39 edestroy(s->e); 40 if(s->r) 41 edirclose(s->r); 42 free(s); 43 } 44 45 static void 46 trace(Req *) 47 { 48 edump(); 49 } 50 51 /** T_ **/ 52 53 static void 54 flattach(Req *r) 55 { 56 root->ref++; 57 r->ofcall.qid = eqid(root); 58 r->fid->aux = state(root); 59 respond(r, nil); 60 } 61 62 static void 63 flopen(Req *r) 64 { 65 int m, p; 66 Entry *e; 67 State *s; 68 69 s = r->fid->aux; 70 e = s->e; 71 m = e->mode; 72 m = (m | (m >> 3) | (m >> 6)) & 7; 73 switch(r->ifcall.mode & 3) { 74 case OREAD: 75 p = AREAD; 76 break; 77 case OWRITE: 78 p = AWRITE; 79 break; 80 case ORDWR: 81 p = AREAD|AWRITE; 82 break; 83 case OEXEC: 84 p = AEXEC; 85 break; 86 default: 87 p = 0; 88 break; 89 } 90 91 if((p & m) != p) { 92 respond(r, Eperm); 93 return; 94 } 95 96 if(readonly && (p & AWRITE) != 0) { 97 respond(r, Erofs); 98 return; 99 } 100 101 r->ofcall.qid = eqid(e); 102 if(r->ofcall.qid.type & QTDIR) 103 s->r = ediropen(s->e); 104 else if(r->ifcall.mode & OTRUNC) 105 etrunc(e, 0, time(0)); 106 107 respond(r, nil); 108 } 109 110 static void 111 flcreate(Req *r) 112 { 113 State *s; 114 char *err; 115 Entry *e, *f; 116 117 if(readonly) { 118 respond(r, Erofs); 119 return; 120 } 121 122 s = r->fid->aux; 123 e = s->e; 124 if(!writeable(e)) { 125 respond(r, Eperm); 126 return; 127 } 128 129 f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, time(0), &err); 130 if(f == nil) { 131 respond(r, err); 132 return; 133 } 134 135 s->e = f; 136 r->ofcall.qid = eqid(f); 137 respond(r, nil); 138 } 139 140 static void 141 flread(Req *r) 142 { 143 Entry *e; 144 State *s; 145 146 s = r->fid->aux; 147 e = s->e; 148 149 if(e->mode & DMDIR) 150 r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count); 151 else 152 r->ofcall.count = 0; 153 154 respond(r, nil); 155 } 156 157 static void 158 flwrite(Req *r) 159 { 160 if(r->ifcall.offset + r->ifcall.count >= MAXFSIZE) { 161 respond(r, "file too big"); 162 return; 163 } 164 165 r->ofcall.count = r->ifcall.count; 166 respond(r, nil); 167 } 168 169 static void 170 flremove(Req *r) 171 { 172 State *s; 173 Entry *e; 174 175 if(readonly) { 176 respond(r, Erofs); 177 return; 178 } 179 180 s = r->fid->aux; 181 e = s->e; 182 if(writeable(e->parent)) 183 respond(r, eremove(e)); 184 else 185 respond(r, Eperm); 186 } 187 188 static void 189 flstat(Req *r) 190 { 191 State *s; 192 193 s = r->fid->aux; 194 estat(s->e, &r->d, 1); 195 respond(r, nil); 196 } 197 198 static void 199 flwstat(Req *r) 200 { 201 int m; 202 State *s; 203 Entry *e; 204 205 s = r->fid->aux; 206 e = s->e; 207 m = r->d.mode & 0777; 208 if(m != (e->mode & 0777)) 209 echmod(e, m, 0); 210 respond(r, nil); 211 } 212 213 static void 214 flwalk(Req *r) 215 { 216 int i; 217 State *s; 218 char *err; 219 Entry *e, *f; 220 221 if(readonly) { 222 respond(r, Erofs); 223 return; 224 } 225 226 if(r->ifcall.fid != r->ifcall.newfid) 227 r->newfid->aux = state(nil); 228 229 s = r->fid->aux; 230 e = s->e; 231 f = e; 232 e->ref++; 233 err = nil; 234 for(i = 0; i < r->ifcall.nwname; i++) { 235 f = ewalk(e, r->ifcall.wname[i], &err); 236 if(f) { 237 r->ofcall.wqid[i] = eqid(f); 238 e = f; 239 } 240 else { 241 e->ref--; 242 break; 243 } 244 } 245 r->ofcall.nwqid = i; 246 247 if(f) { 248 if(r->ifcall.fid != r->ifcall.newfid) { 249 s = r->newfid->aux; 250 s->e = f; 251 r->newfid->qid = eqid(f); 252 } 253 else { 254 s = r->fid->aux; 255 s->e->ref--; 256 s->e = f; 257 r->fid->qid = eqid(f); 258 } 259 } 260 respond(r, err); 261 } 262 263 void 264 serve(char *mount) 265 { 266 flashsrv.attach = flattach; 267 flashsrv.open = flopen; 268 flashsrv.create = flcreate; 269 flashsrv.read = flread; 270 flashsrv.write = flwrite; 271 flashsrv.remove = flremove; 272 flashsrv.stat = flstat; 273 flashsrv.wstat = flwstat; 274 flashsrv.walk = flwalk; 275 276 flashsrv.destroyfid = destroy; 277 flashsrv.destroyreq = trace; 278 einit(); 279 postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE); 280 } 281