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 == nil) /* Tauth fids have no state */ 39 return; 40 41 f->aux = nil; 42 if(s->e) 43 edestroy(s->e); 44 if(s->r) 45 edirclose(s->r); 46 free(s); 47 } 48 49 static void 50 trace(Req *) 51 { 52 edump(); 53 } 54 55 /** T_ **/ 56 57 static void 58 flattach(Req *r) 59 { 60 root->ref++; 61 r->ofcall.qid = eqid(root); 62 r->fid->qid = r->ofcall.qid; 63 r->fid->aux = state(root); 64 respond(r, nil); 65 } 66 67 static void 68 flopen(Req *r) 69 { 70 Jrec j; 71 int m, p; 72 Entry *e; 73 State *s; 74 char *err; 75 76 s = r->fid->aux; 77 e = s->e; 78 m = e->mode; 79 m = (m | (m >> 3) | (m >> 6)) & 7; 80 switch(r->ifcall.mode & 3) { 81 case OREAD: 82 p = AREAD; 83 break; 84 case OWRITE: 85 p = AWRITE; 86 break; 87 case ORDWR: 88 p = AREAD|AWRITE; 89 break; 90 case OEXEC: 91 p = AEXEC; 92 break; 93 default: 94 p = 0; 95 break; 96 } 97 98 if((p & m) != p) { 99 respond(r, Eperm); 100 return; 101 } 102 103 if(readonly && (p & AWRITE) != 0) { 104 respond(r, Erofs); 105 return; 106 } 107 108 r->ofcall.qid = eqid(e); 109 if(r->ofcall.qid.type & QTDIR) { 110 if((p & AWRITE) != 0) { 111 respond(r, Eisdir); 112 return; 113 } 114 s->r = ediropen(s->e); 115 } 116 else if(r->ifcall.mode & OTRUNC) { 117 err = need(Ntrunc); 118 if(err != nil) { 119 respond(r, err); 120 return; 121 } 122 j.type = FT_trunc; 123 j.tnum = e->fnum; 124 j.mtime = now(); 125 etrunc(e, 0, j.mtime); 126 j.fnum = e->fnum; 127 j.parent = e->parent->fnum; 128 j.mode = e->mode; 129 strcpy(j.name, e->name); 130 put(&j, 1); 131 } 132 133 respond(r, nil); 134 } 135 136 static void 137 flcreate(Req *r) 138 { 139 Jrec j; 140 State *s; 141 char *err; 142 Entry *e, *f; 143 144 if(readonly) { 145 respond(r, Erofs); 146 return; 147 } 148 149 s = r->fid->aux; 150 e = s->e; 151 if((e->mode & DMDIR) == 0) { 152 respond(r, Eisdir); 153 return; 154 } 155 156 if(!writeable(e)) { 157 respond(r, Eperm); 158 return; 159 } 160 161 if(strlen(r->ifcall.name) > MAXNSIZE) { 162 respond(r, "filename too long"); 163 return; 164 } 165 166 err = need(Ncreate); 167 if(err != nil) { 168 respond(r, err); 169 return; 170 } 171 172 j.type = FT_create; 173 j.mtime = now(); 174 j.parent = e->fnum; 175 j.mode = r->ifcall.perm; 176 strcpy(j.name, r->ifcall.name); 177 178 f = ecreate(e, r->ifcall.name, 0, r->ifcall.perm, j.mtime, &err); 179 if(f == nil) { 180 respond(r, err); 181 return; 182 } 183 184 j.fnum = f->fnum; 185 put(&j, 1); 186 s->e = f; 187 r->ofcall.qid = eqid(f); 188 respond(r, nil); 189 } 190 191 static void 192 flread(Req *r) 193 { 194 Entry *e; 195 State *s; 196 197 s = r->fid->aux; 198 e = s->e; 199 200 if(e->mode & DMDIR) 201 r->ofcall.count = edirread(s->r, r->ofcall.data, r->ifcall.count); 202 else 203 r->ofcall.count = eread(e, eparity, r->ofcall.data, r->ifcall.count, r->ifcall.offset); 204 205 respond(r, nil); 206 } 207 208 static void 209 flwrite(Req *r) 210 { 211 Jrec j; 212 uchar *a; 213 Entry *e; 214 State *s; 215 Extent *x; 216 char *err; 217 ulong c, n, o, mtime; 218 219 c = r->ifcall.count; 220 o = r->ifcall.offset; 221 a = (uchar *)r->ifcall.data; 222 223 if(c == 0) { 224 respond(r, nil); 225 return; 226 } 227 228 if(o + c >= MAXFSIZE) { 229 respond(r, "file too big"); 230 return; 231 } 232 233 if(used + c > limit) { 234 respond(r, "filesystem full"); 235 return; 236 } 237 238 r->ofcall.count = c; 239 s = r->fid->aux; 240 e = s->e; 241 mtime = now(); 242 243 for(;;) { 244 n = c; 245 if(n > maxwrite) 246 n = maxwrite; 247 248 err = need(Nwrite + n); 249 if(err != nil) { 250 respond(r, err); 251 return; 252 } 253 254 x = emalloc9p(sizeof(Extent)); 255 x->size = n; 256 x->off = o; 257 ewrite(e, x, eparity, mtime); 258 j.type = FT_WRITE; 259 j.fnum = e->fnum; 260 j.size = n; 261 j.offset = o; 262 j.mtime = mtime; 263 putw(&j, 1, x, a); 264 c -= n; 265 266 if(c == 0) 267 break; 268 269 o += n; 270 a += n; 271 } 272 273 respond(r, nil); 274 } 275 276 static void 277 flremove(Req *r) 278 { 279 Jrec j; 280 State *s; 281 Entry *e; 282 char *d, *err; 283 284 if(readonly) { 285 respond(r, Erofs); 286 return; 287 } 288 289 s = r->fid->aux; 290 e = s->e; 291 if(writeable(e->parent)) { 292 err = need(Nremove); 293 if(err != nil) { 294 respond(r, err); 295 return; 296 } 297 298 d = eremove(e); 299 if(d == nil) { 300 j.type = FT_REMOVE; 301 j.fnum = e->fnum; 302 put(&j, 0); 303 } 304 respond(r, d); 305 } 306 else 307 respond(r, Eperm); 308 } 309 310 static void 311 flstat(Req *r) 312 { 313 State *s; 314 315 s = r->fid->aux; 316 estat(s->e, &r->d, 1); 317 respond(r, nil); 318 } 319 320 static void 321 flwstat(Req *r) 322 { 323 int m; 324 Jrec j; 325 State *s; 326 Entry *e; 327 char *err; 328 329 s = r->fid->aux; 330 e = s->e; 331 332 if(readonly) { 333 respond(r, Erofs); 334 return; 335 } 336 337 if(e->fnum == 0) { 338 respond(r, Eperm); 339 return; 340 } 341 342 m = r->d.mode & 0777; 343 if(m != (e->mode & 0777)) { 344 err = need(Nchmod); 345 if(err != nil) { 346 respond(r, err); 347 return; 348 } 349 350 echmod(e, m, 0); 351 j.type = FT_chmod; 352 j.mode = m; 353 j.fnum = e->fnum; 354 j.mnum = e->mnum; 355 put(&j, 0); 356 } 357 respond(r, nil); 358 } 359 360 static void 361 flwalk(Req *r) 362 { 363 int i; 364 State *s; 365 char *err; 366 Entry *e, *f; 367 368 if(r->ifcall.fid != r->ifcall.newfid) 369 r->newfid->aux = state(nil); 370 371 s = r->fid->aux; 372 e = s->e; 373 f = e; 374 e->ref++; 375 err = nil; 376 for(i = 0; i < r->ifcall.nwname; i++) { 377 f = ewalk(e, r->ifcall.wname[i], &err); 378 if(f) { 379 r->ofcall.wqid[i] = eqid(f); 380 e = f; 381 } 382 else { 383 e->ref--; 384 break; 385 } 386 } 387 r->ofcall.nwqid = i; 388 if (i) err = nil; 389 390 if(f) { 391 if(r->ifcall.fid != r->ifcall.newfid) { 392 s = r->newfid->aux; 393 s->e = f; 394 r->newfid->qid = eqid(f); 395 } 396 else { 397 s = r->fid->aux; 398 s->e->ref--; 399 s->e = f; 400 r->fid->qid = eqid(f); 401 } 402 } 403 respond(r, err); 404 } 405 406 void 407 serve(char *mount) 408 { 409 flashsrv.attach = flattach; 410 flashsrv.open = flopen; 411 flashsrv.create = flcreate; 412 flashsrv.read = flread; 413 flashsrv.write = flwrite; 414 flashsrv.remove = flremove; 415 flashsrv.stat = flstat; 416 flashsrv.wstat = flwstat; 417 flashsrv.walk = flwalk; 418 419 flashsrv.destroyfid = destroy; 420 flashsrv.destroyreq = trace; 421 postmountsrv(&flashsrv, "brzr", mount, MREPL|MCREATE); 422 } 423