1 #include "all.h" 2 3 Filsys* 4 fsstr(char *p) 5 { 6 Filsys *fs; 7 8 for(fs=filsys; fs->name; fs++) 9 if(strcmp(fs->name, p) == 0) 10 return fs; 11 return 0; 12 } 13 14 void 15 fileinit(Chan *cp) 16 { 17 File *f; 18 Tlock *t; 19 20 loop: 21 lock(&cp->flock); 22 f = cp->flist; 23 if(!f) { 24 unlock(&cp->flock); 25 return; 26 } 27 cp->flist = f->next; 28 unlock(&cp->flock); 29 30 qlock(f); 31 if(t = f->tlock) { 32 t->time = 0; 33 f->tlock = 0; 34 } 35 if(f->open & FREMOV) 36 doremove(f, 0); 37 freewp(f->wpath); 38 f->open = 0; 39 f->cp = 0; 40 qunlock(f); 41 42 goto loop; 43 } 44 45 /* 46 * returns a locked file structure 47 */ 48 File* 49 filep(Chan *cp, int fid, int flag) 50 { 51 File *f, *prev; 52 53 if(fid == NOF) 54 return 0; 55 56 loop: 57 lock(&cp->flock); 58 for(prev=0,f=cp->flist; f; prev=f,f=f->next) { 59 if(f->fid != fid) 60 continue; 61 if(prev) { 62 prev->next = f->next; 63 f->next = cp->flist; 64 cp->flist = f; 65 } 66 goto out; 67 } 68 if(flag) { 69 f = newfp(cp); 70 if(f) { 71 f->fid = fid; 72 goto out; 73 } 74 } 75 unlock(&cp->flock); 76 return 0; 77 78 out: 79 unlock(&cp->flock); 80 qlock(f); 81 if(f->fid != fid) { 82 qunlock(f); 83 goto loop; 84 } 85 return f; 86 } 87 88 /* 89 * always called with cp->flock locked 90 */ 91 File* 92 newfp(Chan *cp) 93 { 94 static first; 95 File *f; 96 int start, i; 97 98 i = first; 99 start = i; 100 do { 101 f = &files[i]; 102 i++; 103 if(i >= conf.nfile) 104 i = 0; 105 if(f->cp) 106 continue; 107 lock(&newfplock); 108 if(f->cp) { 109 unlock(&newfplock); 110 continue; 111 } 112 f->cp = cp; 113 f->next = cp->flist; 114 f->wpath = 0; 115 f->tlock = 0; 116 cp->flist = f; 117 first = i; 118 unlock(&newfplock); 119 return f; 120 } while(i != start); 121 122 print("%d: out of files\n", cp->chan); 123 return 0; 124 } 125 126 void 127 freefp(File *fp) 128 { 129 Chan *cp; 130 File *f, *prev; 131 132 if(!fp || !(cp = fp->cp)) 133 return; 134 lock(&cp->flock); 135 for(prev=0,f=cp->flist; f; prev=f,f=f->next) { 136 if(f != fp) 137 continue; 138 if(prev) 139 prev->next = f->next; 140 else 141 cp->flist = f->next; 142 f->cp = 0; 143 break; 144 } 145 unlock(&cp->flock); 146 } 147 148 int 149 iaccess(File *f, Dentry *d, int m) 150 { 151 if(wstatallow) 152 return 0; 153 /* 154 * other is easiest 155 */ 156 if(m & d->mode) 157 return 0; 158 /* 159 * owner is next 160 */ 161 if(f->uid == d->uid) 162 if((m<<6) & d->mode) 163 return 0; 164 /* 165 * group membership is hard 166 */ 167 if(ingroup(f->uid, d->gid)) 168 if((m<<3) & d->mode) 169 return 0; 170 return 1; 171 } 172 173 Tlock* 174 tlocked(Iobuf *p, Dentry *d) 175 { 176 Tlock *t, *t1; 177 long qpath, tim; 178 Device dev; 179 180 tim = toytime(); 181 qpath = d->qid.path; 182 dev = p->dev; 183 t1 = 0; 184 for(t=tlocks+NTLOCK-1; t>=tlocks; t--) { 185 if(t->qpath == qpath) 186 if(t->time >= tim) 187 if(devcmp(t->dev, dev) == 0) 188 return 0; /* its locked */ 189 if(!t1 && t->time < tim) 190 t1 = t; /* steal first lock */ 191 } 192 if(t1) { 193 t1->dev = dev; 194 t1->qpath = qpath; 195 t1->time = tim + TLOCK; 196 } 197 /* botch 198 * out of tlock nodes simulates 199 * a locked file 200 */ 201 return t1; 202 } 203 204 Wpath* 205 newwp(void) 206 { 207 static int si = 0; 208 int i; 209 Wpath *w, *sw, *ew; 210 211 i = si + 1; 212 if(i < 0 || i >= conf.nwpath) 213 i = 0; 214 si = i; 215 sw = &wpaths[i]; 216 ew = &wpaths[conf.nwpath]; 217 for(w=sw;;) { 218 w++; 219 if(w >= ew) 220 w = &wpaths[0]; 221 if(w == sw) { 222 print("out of wpaths\n"); 223 return 0; 224 } 225 if(w->refs) 226 continue; 227 lock(&wpathlock); 228 if(w->refs) { 229 unlock(&wpathlock); 230 continue; 231 } 232 w->refs = 1; 233 w->up = 0; 234 unlock(&wpathlock); 235 return w; 236 } 237 238 } 239 240 void 241 freewp(Wpath *w) 242 { 243 lock(&wpathlock); 244 for(; w; w=w->up) 245 w->refs--; 246 unlock(&wpathlock); 247 } 248 249 Qid 250 newqid(Device dev) 251 { 252 Iobuf *p; 253 Superb *sb; 254 Qid qid; 255 256 p = getbuf(dev, superaddr(dev), Bread|Bmod); 257 if(!p || checktag(p, Tsuper, QPSUPER)) 258 panic("newqid: super block"); 259 sb = (Superb*)p->iobuf; 260 sb->qidgen++; 261 qid.path = sb->qidgen; 262 qid.version = 0; 263 putbuf(p); 264 return qid; 265 } 266 267 /* 268 * what are legal characters in a name? 269 * only disallow control characters. 270 * a) utf avoids control characters. 271 * b) '/' may not be the separator 272 */ 273 int 274 checkname(char *n) 275 { 276 int i, c; 277 278 for(i=0; i<NAMELEN; i++) { 279 c = *n & 0xff; 280 if(c == 0) { 281 if(i == 0) 282 return 1; 283 memset(n, 0, NAMELEN-i); 284 return 0; 285 } 286 if(c <= 040) 287 return 1; 288 n++; 289 } 290 return 1; /* too long */ 291 } 292 293 void 294 bfree(Device dev, long addr, int d) 295 { 296 Iobuf *p; 297 long a; 298 int i; 299 300 if(!addr) 301 return; 302 if(d > 0) { 303 d--; 304 p = getbuf(dev, addr, Bread); 305 if(p) { 306 for(i=INDPERBUF-1; i>=0; i--) { 307 a = ((long*)p->iobuf)[i]; 308 bfree(dev, a, d); 309 } 310 putbuf(p); 311 } 312 } 313 /* 314 * stop outstanding i/o 315 */ 316 p = getbuf(dev, addr, Bprobe); 317 if(p) { 318 p->flags &= ~(Bmod|Bimm); 319 putbuf(p); 320 } 321 /* 322 * dont put written worm 323 * blocks into free list 324 */ 325 if(nofree(dev, addr)) 326 return; 327 p = getbuf(dev, superaddr(dev), Bread|Bmod); 328 if(!p || checktag(p, Tsuper, QPSUPER)) 329 panic("bfree: super block"); 330 addfree(dev, addr, (Superb*)p->iobuf); 331 putbuf(p); 332 } 333 334 long 335 balloc(Device dev, int tag, long qid) 336 { 337 Iobuf *bp, *p; 338 Superb *sb; 339 long a; 340 int n; 341 342 p = getbuf(dev, superaddr(dev), Bread|Bmod); 343 if(!p || checktag(p, Tsuper, QPSUPER)) 344 panic("balloc: super block"); 345 sb = (Superb*)p->iobuf; 346 347 loop: 348 n = --sb->fbuf.nfree; 349 sb->tfree--; 350 if(n < 0 || n >= FEPERBUF) 351 panic("balloc: bad freelist"); 352 a = sb->fbuf.free[n]; 353 if(n <= 0) { 354 if(a == 0) { 355 sb->tfree = 0; 356 sb->fbuf.nfree = 1; 357 if(devgrow(dev, sb)) 358 goto loop; 359 putbuf(p); 360 return 0; 361 } 362 bp = getbuf(dev, a, Bread); 363 if(!bp || checktag(bp, Tfree, QPNONE)) { 364 if(bp) 365 putbuf(bp); 366 putbuf(p); 367 return 0; 368 } 369 memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(long)); 370 putbuf(bp); 371 } 372 bp = getbuf(dev, a, Bmod); 373 memset(bp->iobuf, 0, RBUFSIZE); 374 settag(bp, tag, qid); 375 if(tag == Tind1 || tag == Tind2 || tag == Tdir) 376 bp->flags |= Bimm; 377 putbuf(bp); 378 putbuf(p); 379 return a; 380 } 381 382 void 383 addfree(Device dev, long addr, Superb *sb) 384 { 385 int n; 386 Iobuf *p; 387 388 if(addr >= sb->fsize){ 389 print("addfree: bad addr %lux\n", addr); 390 return; 391 } 392 n = sb->fbuf.nfree; 393 if(n < 0 || n > FEPERBUF) 394 panic("addfree: bad freelist"); 395 if(n >= FEPERBUF) { 396 p = getbuf(dev, addr, Bmod); 397 if(p == 0) 398 panic("addfree: getbuf"); 399 memmove(p->iobuf, &sb->fbuf, (FEPERBUF+1)*sizeof(long)); 400 settag(p, Tfree, QPNONE); 401 putbuf(p); 402 n = 0; 403 } 404 sb->fbuf.free[n++] = addr; 405 sb->fbuf.nfree = n; 406 sb->tfree++; 407 if(addr >= sb->fsize) 408 sb->fsize = addr+1; 409 } 410 411 int 412 Cconv(Op *o) 413 { 414 Chan *cp; 415 char s[20]; 416 417 cp = *(Chan**)o->argp; 418 sprint(s, "C%d.%.3d", cp->type, cp->chan); 419 strconv(s, o, o->f1, o->f2); 420 return sizeof(cp); 421 } 422 423 int 424 Dconv(Op *o) 425 { 426 Device d; 427 char s[20]; 428 429 d = *(Device*)o->argp; 430 sprint(s, "D%d.%d.%d.%d", d.type, d.ctrl, d.unit, d.part); 431 strconv(s, o, o->f1, o->f2); 432 return sizeof(d); 433 } 434 435 int 436 Fconv(Op *o) 437 { 438 Filta a; 439 char s[30]; 440 441 a = *(Filta*)o->argp; 442 443 sprint(s, "%6lud %6lud %6lud", 444 fdf(a.f->filter[0], a.scale*60), 445 fdf(a.f->filter[1], a.scale*600), 446 fdf(a.f->filter[2], a.scale*6000)); 447 strconv(s, o, o->f1, o->f2); 448 return sizeof(Filta); 449 } 450 451 int 452 Gconv(Op *o) 453 { 454 int t; 455 char s[20]; 456 457 t = *(int*)o->argp; 458 strcpy(s, "<badtag>"); 459 if(t >= 0 && t < MAXTAG) 460 sprint(s, "%s", tagnames[t]); 461 strconv(s, o, o->f1, o->f2); 462 return sizeof(t); 463 } 464 465 void 466 formatinit(void) 467 { 468 469 fmtinstall('C', Cconv); /* print channels */ 470 fmtinstall('D', Dconv); /* print devices */ 471 fmtinstall('F', Fconv); /* print filters */ 472 fmtinstall('G', Gconv); /* print tags */ 473 fmtinstall('T', Tconv); /* print times */ 474 } 475 476 int 477 devcmp(Device d1, Device d2) 478 { 479 480 if(d1.type == d2.type) 481 if(d1.ctrl == d2.ctrl) 482 if(d1.unit == d2.unit) 483 if(d1.part == d2.part) 484 return 0; 485 return 1; 486 } 487 488 void 489 rootream(Device dev, long addr) 490 { 491 Iobuf *p; 492 Dentry *d; 493 494 p = getbuf(dev, addr, Bmod|Bimm); 495 memset(p->iobuf, 0, RBUFSIZE); 496 settag(p, Tdir, QPROOT); 497 d = getdir(p, 0); 498 strcpy(d->name, "/"); 499 d->uid = -1; 500 d->gid = -1; 501 d->mode = DALLOC | DDIR | 502 ((DREAD|DWRITE|DEXEC) << 6) | 503 ((DREAD|DWRITE|DEXEC) << 3) | 504 ((DREAD|DWRITE|DEXEC) << 0); 505 d->qid = QID(QPROOT|QPDIR,0); 506 d->atime = time(); 507 d->mtime = d->atime; 508 putbuf(p); 509 } 510 511 int 512 superok(Device dev, long addr, int set) 513 { 514 Iobuf *p; 515 Superb *s; 516 int ok; 517 518 p = getbuf(dev, addr, Bread|Bmod|Bimm); 519 s = (Superb*)p->iobuf; 520 ok = s->fsok; 521 s->fsok = set; 522 putbuf(p); 523 return ok; 524 } 525 526 void 527 superream(Device dev, long addr) 528 { 529 Iobuf *p; 530 Superb *s; 531 long i; 532 533 p = getbuf(dev, addr, Bmod|Bimm); 534 memset(p->iobuf, 0, RBUFSIZE); 535 settag(p, Tsuper, QPSUPER); 536 537 s = (Superb*)p->iobuf; 538 s->fstart = 1; 539 s->fsize = devsize(dev); 540 s->fbuf.nfree = 1; 541 s->qidgen = 10; 542 for(i=s->fsize-1; i>=addr+2; i--) 543 addfree(dev, i, s); 544 putbuf(p); 545 } 546 547 /* 548 * returns 1 if n is prime 549 * used for adjusting lengths 550 * of hashing things. 551 * there is no need to be clever 552 */ 553 int 554 prime(long n) 555 { 556 long i; 557 558 if((n%2) == 0) 559 return 0; 560 for(i=3;; i+=2) { 561 if((n%i) == 0) 562 return 0; 563 if(i*i >= n) 564 return 1; 565 } 566 } 567 568 void 569 hexdump(void *a, int n) 570 { 571 char s1[30], s2[4]; 572 uchar *p; 573 int i; 574 575 p = a; 576 s1[0] = 0; 577 for(i=0; i<n; i++) { 578 sprint(s2, " %.2ux", p[i]); 579 strcat(s1, s2); 580 if((i&7) == 7) { 581 print("%s\n", s1); 582 s1[0] = 0; 583 } 584 } 585 if(s1[0]) 586 print("%s\n", s1); 587 } 588