1 #include "all.h"
2 #include "io.h"
3
4 enum {
5 Slop = 256, /* room at the start of a message buf for proto hdrs */
6 };
7
8 Filsys*
fsstr(char * p)9 fsstr(char *p)
10 {
11 Filsys *fs;
12
13 for(fs=filsys; fs->name; fs++)
14 if(strcmp(fs->name, p) == 0)
15 return fs;
16 return 0;
17 }
18
19 Filsys*
dev2fs(Device * dev)20 dev2fs(Device *dev)
21 {
22 Filsys *fs;
23
24 for(fs=filsys; fs->name; fs++)
25 if(fs->dev == dev)
26 return fs;
27 return 0;
28 }
29
30 /*
31 * allocate 'count' contiguous channels
32 * of type 'type' and return pointer to base
33 */
34 Chan*
fs_chaninit(int type,int count,int data)35 fs_chaninit(int type, int count, int data)
36 {
37 uchar *p;
38 Chan *cp, *icp;
39 int i;
40
41 p = malloc(count * (sizeof(Chan)+data));
42 icp = (Chan*)p;
43 for(i = 0; i < count; i++) {
44 cp = (Chan*)p;
45 cp->next = chans;
46 chans = cp;
47 cp->type = type;
48 cp->chan = cons.chano;
49 cons.chano++;
50 strncpy(cp->whoname, "<none>", sizeof cp->whoname);
51 wlock(&cp->reflock);
52 wunlock(&cp->reflock);
53 rlock(&cp->reflock);
54 runlock(&cp->reflock);
55
56 p += sizeof(Chan);
57 if(data){
58 cp->pdata = p;
59 p += data;
60 }
61 }
62 return icp;
63 }
64
65 void
fileinit(Chan * cp)66 fileinit(Chan *cp)
67 {
68 File *f, *prev;
69 Tlock *t;
70 int h;
71
72 loop:
73 lock(&flock);
74 for (h=0; h < nelem(flist); h++)
75 for (prev=0, f = flist[h]; f; prev=f, f=f->next) {
76 if(f->cp != cp)
77 continue;
78 if(prev) {
79 prev->next = f->next;
80 f->next = flist[h];
81 flist[h] = f;
82 }
83 flist[h] = f->next;
84 unlock(&flock);
85
86 qlock(f);
87 if(t = f->tlock) {
88 if(t->file == f)
89 t->time = 0; /* free the lock */
90 f->tlock = 0;
91 }
92 if(f->open & FREMOV)
93 doremove(f, 0);
94 freewp(f->wpath);
95 f->open = 0;
96 authfree(f->auth);
97 f->auth = 0;
98 f->cp = 0;
99 qunlock(f);
100 goto loop;
101 }
102 unlock(&flock);
103 }
104
105 enum { NOFID = (ulong)~0 };
106
107 /*
108 * returns a locked file structure
109 */
110 File*
filep(Chan * cp,ulong fid,int flag)111 filep(Chan *cp, ulong fid, int flag)
112 {
113 File *f;
114 int h;
115
116 if(fid == NOFID)
117 return 0;
118
119 h = (long)(uintptr)cp + fid;
120 if(h < 0)
121 h = ~h;
122 h %= nelem(flist);
123
124 loop:
125 lock(&flock);
126 for(f=flist[h]; f; f=f->next)
127 if(f->fid == fid && f->cp == cp){
128 /*
129 * Already in use is an error
130 * when called from attach or clone (walk
131 * in 9P2000). The console uses FID[12] and
132 * never clunks them so catch that case.
133 */
134 if(flag == 0 || cp == cons.chan)
135 goto out;
136 unlock(&flock);
137 return 0;
138 }
139
140 if(flag) {
141 f = newfp();
142 if(f) {
143 f->fid = fid;
144 f->cp = cp;
145 f->wpath = 0;
146 f->tlock = 0;
147 f->doffset = 0;
148 f->dslot = 0;
149 f->auth = 0;
150 f->next = flist[h];
151 flist[h] = f;
152 goto out;
153 }
154 }
155 unlock(&flock);
156 return 0;
157
158 out:
159 unlock(&flock);
160 qlock(f);
161 if(f->fid == fid && f->cp == cp)
162 return f;
163 qunlock(f);
164 goto loop;
165 }
166
167 /*
168 * always called with flock locked
169 */
170 File*
newfp(void)171 newfp(void)
172 {
173 static int first;
174 File *f;
175 int start, i;
176
177 i = first;
178 start = i;
179 do {
180 f = &files[i];
181 i++;
182 if(i >= conf.nfile)
183 i = 0;
184 if(f->cp)
185 continue;
186 first = i;
187 return f;
188 } while(i != start);
189
190 print("out of files\n");
191 return 0;
192 }
193
194 void
freefp(File * fp)195 freefp(File *fp)
196 {
197 Chan *cp;
198 File *f, *prev;
199 int h;
200
201 if(!fp || !(cp = fp->cp))
202 return;
203
204 h = (long)(uintptr)cp + fp->fid;
205 if(h < 0)
206 h = ~h;
207 h %= nelem(flist);
208
209 lock(&flock);
210 for(prev=0,f=flist[h]; f; prev=f,f=f->next)
211 if(f == fp) {
212 if(prev)
213 prev->next = f->next;
214 else
215 flist[h] = f->next;
216 break;
217 }
218 fp->cp = 0;
219 unlock(&flock);
220 }
221
222 int
iaccess(File * f,Dentry * d,int m)223 iaccess(File *f, Dentry *d, int m)
224 {
225 /* uid none gets only other permissions */
226 if(f->uid != 0) {
227 /*
228 * owner
229 */
230 if(f->uid == d->uid)
231 if((m<<6) & d->mode)
232 return 0;
233 /*
234 * group membership
235 */
236 if(ingroup(f->uid, d->gid))
237 if((m<<3) & d->mode)
238 return 0;
239 }
240
241 /*
242 * other
243 */
244 if(m & d->mode) {
245 if((d->mode & DDIR) && (m == DEXEC))
246 return 0;
247 if(!ingroup(f->uid, 9999))
248 return 0;
249 }
250
251 /*
252 * various forms of superuser
253 */
254 if(wstatallow)
255 return 0;
256 if(duallow != 0 && duallow == f->uid)
257 if((d->mode & DDIR) && (m == DREAD || m == DEXEC))
258 return 0;
259
260 return 1;
261 }
262
263 Tlock*
tlocked(Iobuf * p,Dentry * d)264 tlocked(Iobuf *p, Dentry *d)
265 {
266 Tlock *t, *t1;
267 Off qpath;
268 Timet tim;
269 Device *dev;
270
271 tim = toytime();
272 qpath = d->qid.path;
273 dev = p->dev;
274
275 again:
276 t1 = 0;
277 for(t=tlocks+NTLOCK-1; t>=tlocks; t--) {
278 if(t->qpath == qpath)
279 if(t->time >= tim)
280 if(t->dev == dev)
281 return nil; /* its locked */
282 if(t1 != nil && t->time == 0)
283 t1 = t; /* remember free lock */
284 }
285 if(t1 == 0) {
286 // reclaim old locks
287 lock(&tlocklock);
288 for(t=tlocks+NTLOCK-1; t>=tlocks; t--)
289 if(t->time < tim) {
290 t->time = 0;
291 t1 = t;
292 }
293 unlock(&tlocklock);
294 }
295 if(t1) {
296 lock(&tlocklock);
297 if(t1->time != 0) {
298 unlock(&tlocklock);
299 goto again;
300 }
301 t1->dev = dev;
302 t1->qpath = qpath;
303 t1->time = tim + TLOCK;
304 unlock(&tlocklock);
305 }
306 /* botch
307 * out of tlock nodes simulates
308 * a locked file
309 */
310 return t1;
311 }
312
313 Wpath*
newwp(void)314 newwp(void)
315 {
316 static int si = 0;
317 int i;
318 Wpath *w, *sw, *ew;
319
320 i = si + 1;
321 if(i < 0 || i >= conf.nwpath)
322 i = 0;
323 si = i;
324 sw = &wpaths[i];
325 ew = &wpaths[conf.nwpath];
326 for(w=sw;;) {
327 w++;
328 if(w >= ew)
329 w = &wpaths[0];
330 if(w == sw) {
331 print("out of wpaths\n");
332 return 0;
333 }
334 if(w->refs)
335 continue;
336 lock(&wpathlock);
337 if(w->refs) {
338 unlock(&wpathlock);
339 continue;
340 }
341 w->refs = 1;
342 w->up = 0;
343 unlock(&wpathlock);
344 return w;
345 }
346
347 }
348
349 void
freewp(Wpath * w)350 freewp(Wpath *w)
351 {
352 lock(&wpathlock);
353 for(; w; w=w->up)
354 w->refs--;
355 unlock(&wpathlock);
356 }
357
358 Off
qidpathgen(Device * dev)359 qidpathgen(Device *dev)
360 {
361 Iobuf *p;
362 Superb *sb;
363 Off path;
364
365 p = getbuf(dev, superaddr(dev), Brd|Bmod);
366 if(!p || checktag(p, Tsuper, QPSUPER))
367 panic("newqid: super block");
368 sb = (Superb*)p->iobuf;
369 sb->qidgen++;
370 path = sb->qidgen;
371 putbuf(p);
372 return path;
373 }
374
375 /* truncating to length > 0 */
376 static void
truncfree(Truncstate * ts,Device * dev,int d,Iobuf * p,int i)377 truncfree(Truncstate *ts, Device *dev, int d, Iobuf *p, int i)
378 {
379 int pastlast;
380 Off a;
381
382 pastlast = ts->pastlast;
383 a = ((Off *)p->iobuf)[i];
384 if (d > 0 || pastlast)
385 buffree(dev, a, d, ts);
386 if (pastlast) {
387 ((Off *)p->iobuf)[i] = 0;
388 p->flags |= Bmod|Bimm;
389 } else if (d == 0 && ts->relblk == ts->lastblk)
390 ts->pastlast = 1;
391 if (d == 0)
392 ts->relblk++;
393 }
394
395 /*
396 * free the block at `addr' on dev.
397 * if it's an indirect block (d [depth] > 0),
398 * first recursively free all the blocks it names.
399 *
400 * ts->relblk is the block number within the file of this
401 * block (or the first data block eventually pointed to via
402 * this indirect block).
403 */
404 void
buffree(Device * dev,Off addr,int d,Truncstate * ts)405 buffree(Device *dev, Off addr, int d, Truncstate *ts)
406 {
407 Iobuf *p;
408 Off a;
409 int i, pastlast;
410
411 if(!addr)
412 return;
413 pastlast = (ts == nil? 1: ts->pastlast);
414 /*
415 * if this is an indirect block, recurse and free any
416 * suitable blocks within it (possibly via further indirect blocks).
417 */
418 if(d > 0) {
419 d--;
420 p = getbuf(dev, addr, Brd);
421 if(p) {
422 if (ts == nil) /* common case: create */
423 for(i=INDPERBUF-1; i>=0; i--) {
424 a = ((Off *)p->iobuf)[i];
425 buffree(dev, a, d, nil);
426 }
427 else /* wstat truncation */
428 for (i = 0; i < INDPERBUF; i++)
429 truncfree(ts, dev, d, p, i);
430 putbuf(p);
431 }
432 }
433 if (!pastlast)
434 return;
435 /*
436 * having zeroed the pointer to this block, add it to the free list.
437 * stop outstanding i/o
438 */
439 p = getbuf(dev, addr, Bprobe);
440 if(p) {
441 p->flags &= ~(Bmod|Bimm);
442 putbuf(p);
443 }
444 /*
445 * dont put written worm
446 * blocks into free list
447 */
448 if(dev->type == Devcw) {
449 i = cwfree(dev, addr);
450 if(i)
451 return;
452 }
453 p = getbuf(dev, superaddr(dev), Brd|Bmod);
454 if(!p || checktag(p, Tsuper, QPSUPER))
455 panic("buffree: super block");
456 addfree(dev, addr, (Superb*)p->iobuf);
457 putbuf(p);
458 }
459
460 Off
bufalloc(Device * dev,int tag,long qid,int uid)461 bufalloc(Device *dev, int tag, long qid, int uid)
462 {
463 Iobuf *bp, *p;
464 Superb *sb;
465 Off a, n;
466
467 p = getbuf(dev, superaddr(dev), Brd|Bmod);
468 if(!p || checktag(p, Tsuper, QPSUPER)) {
469 print("bufalloc: super block\n");
470 if(p)
471 putbuf(p);
472 return 0;
473 }
474 sb = (Superb*)p->iobuf;
475
476 loop:
477 n = --sb->fbuf.nfree;
478 sb->tfree--;
479 if(n < 0 || n >= FEPERBUF) {
480 print("bufalloc: %Z: bad freelist\n", dev);
481 n = 0;
482 sb->fbuf.free[0] = 0;
483 }
484 a = sb->fbuf.free[n];
485 if(n <= 0) {
486 if(a == 0) {
487 sb->tfree = 0;
488 sb->fbuf.nfree = 1;
489 if(dev->type == Devcw) {
490 n = uid;
491 if(n < 0 || n >= nelem(growacct))
492 n = 0;
493 growacct[n]++;
494 if(cwgrow(dev, sb, uid))
495 goto loop;
496 }
497 putbuf(p);
498 print("fs %Z full uid=%d\n", dev, uid);
499 return 0;
500 }
501 bp = getbuf(dev, a, Brd);
502 if(!bp || checktag(bp, Tfree, QPNONE)) {
503 if(bp)
504 putbuf(bp);
505 putbuf(p);
506 return 0;
507 }
508 sb->fbuf = *(Fbuf*)bp->iobuf;
509 putbuf(bp);
510 }
511
512 bp = getbuf(dev, a, Bmod);
513 memset(bp->iobuf, 0, RBUFSIZE);
514 settag(bp, tag, qid);
515 if(tag == Tind1 || tag == Tind2 ||
516 #ifndef COMPAT32
517 tag == Tind3 || tag == Tind4 || /* add more Tind tags here ... */
518 #endif
519 tag == Tdir)
520 bp->flags |= Bimm;
521 putbuf(bp);
522 putbuf(p);
523 return a;
524 }
525
526 /*
527 * what are legal characters in a name?
528 * only disallow control characters.
529 * a) utf avoids control characters.
530 * b) '/' may not be the separator
531 */
532 int
checkname(char * n)533 checkname(char *n)
534 {
535 int i, c;
536
537 for(i=0; i<NAMELEN; i++) {
538 c = *n & 0xff;
539 if(c == 0) {
540 if(i == 0)
541 return 1;
542 memset(n, 0, NAMELEN-i);
543 return 0;
544 }
545 if(c <= 040)
546 return 1;
547 n++;
548 }
549 return 1; /* too long */
550 }
551
552 void
addfree(Device * dev,Off addr,Superb * sb)553 addfree(Device *dev, Off addr, Superb *sb)
554 {
555 int n;
556 Iobuf *p;
557
558 n = sb->fbuf.nfree;
559 if(n < 0 || n > FEPERBUF)
560 panic("addfree: bad freelist");
561 if(n >= FEPERBUF) {
562 p = getbuf(dev, addr, Bmod|Bimm);
563 if(p == 0)
564 panic("addfree: getbuf");
565 *(Fbuf*)p->iobuf = sb->fbuf;
566 settag(p, Tfree, QPNONE);
567 putbuf(p);
568 n = 0;
569 }
570 sb->fbuf.free[n++] = addr;
571 sb->fbuf.nfree = n;
572 sb->tfree++;
573 if(addr >= sb->fsize)
574 sb->fsize = addr+1;
575 }
576
577 /*
578 static int
579 Yfmt(Fmt* fmt)
580 {
581 Chan *cp;
582 char s[20];
583
584 cp = va_arg(fmt->args, Chan*);
585 sprint(s, "C%d.%.3d", cp->type, cp->chan);
586 return fmtstrcpy(fmt, s);
587 }
588 */
589
590 static int
Zfmt(Fmt * fmt)591 Zfmt(Fmt* fmt)
592 {
593 Device *d;
594 int c, c1;
595 char s[100];
596
597 d = va_arg(fmt->args, Device*);
598 if(d == nil) {
599 sprint(s, "Z***");
600 goto out;
601 }
602 c = c1 = '\0';
603 switch(d->type) {
604 default:
605 sprint(s, "D%d", d->type);
606 break;
607 case Devwren:
608 c = 'w';
609 /* fallthrough */
610 case Devworm:
611 if (c == '\0')
612 c = 'r';
613 /* fallthrough */
614 case Devlworm:
615 if (c == '\0')
616 c = 'l';
617 if(d->wren.ctrl == 0 && d->wren.lun == 0)
618 sprint(s, "%c%d", c, d->wren.targ);
619 else
620 sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ,
621 d->wren.lun);
622 break;
623 case Devmcat:
624 c = '(';
625 c1 = ')';
626 /* fallthrough */
627 case Devmlev:
628 if (c == '\0') {
629 c = '[';
630 c1 = ']';
631 }
632 /* fallthrough */
633 case Devmirr:
634 if (c == '\0') {
635 c = '{';
636 c1 = '}';
637 }
638 if(d->cat.first == d->cat.last)
639 sprint(s, "%c%Z%c", c, d->cat.first, c1);
640 else if(d->cat.first->link == d->cat.last)
641 sprint(s, "%c%Z%Z%c", c, d->cat.first, d->cat.last, c1);
642 else
643 sprint(s, "%c%Z-%Z%c", c, d->cat.first, d->cat.last, c1);
644 break;
645 case Devro:
646 sprint(s, "o%Z%Z", d->ro.parent->cw.c, d->ro.parent->cw.w);
647 break;
648 case Devcw:
649 sprint(s, "c%Z%Z", d->cw.c, d->cw.w);
650 break;
651 case Devjuke:
652 sprint(s, "j%Z%Z", d->j.j, d->j.m);
653 break;
654 case Devfworm:
655 sprint(s, "f%Z", d->fw.fw);
656 break;
657 case Devpart:
658 sprint(s, "p(%Z)%ld.%ld", d->part.d, d->part.base, d->part.size);
659 break;
660 case Devswab:
661 sprint(s, "x%Z", d->swab.d);
662 break;
663 case Devnone:
664 sprint(s, "n");
665 break;
666 }
667 out:
668 return fmtstrcpy(fmt, s);
669 }
670
671 static int
Gfmt(Fmt * fmt)672 Gfmt(Fmt* fmt)
673 {
674 int t;
675 char *s;
676
677 t = va_arg(fmt->args, int);
678 s = "<badtag>";
679 if(t >= 0 && t < MAXTAG)
680 s = tagnames[t];
681 return fmtstrcpy(fmt, s);
682 }
683
684 void
formatinit(void)685 formatinit(void)
686 {
687 quotefmtinstall();
688 // fmtinstall('Y', Yfmt); /* print channels */
689 fmtinstall('Z', Zfmt); /* print devices */
690 fmtinstall('G', Gfmt); /* print tags */
691 fmtinstall('T', Tfmt); /* print times */
692 // fmtinstall('E', eipfmt); /* print ether addresses */
693 fmtinstall('I', eipfmt); /* print ip addresses */
694 }
695
696 void
rootream(Device * dev,Off addr)697 rootream(Device *dev, Off addr)
698 {
699 Iobuf *p;
700 Dentry *d;
701
702 p = getbuf(dev, addr, Bmod|Bimm);
703 memset(p->iobuf, 0, RBUFSIZE);
704 settag(p, Tdir, QPROOT);
705 d = getdir(p, 0);
706 strcpy(d->name, "/");
707 d->uid = -1;
708 d->gid = -1;
709 d->mode = DALLOC | DDIR |
710 ((DREAD|DEXEC) << 6) |
711 ((DREAD|DEXEC) << 3) |
712 ((DREAD|DEXEC) << 0);
713 d->qid = QID9P1(QPROOT|QPDIR,0);
714 d->atime = time(nil);
715 d->mtime = d->atime;
716 d->muid = 0;
717 putbuf(p);
718 }
719
720 void
superream(Device * dev,Off addr)721 superream(Device *dev, Off addr)
722 {
723 Iobuf *p;
724 Superb *s;
725 Off i;
726
727 p = getbuf(dev, addr, Bmod|Bimm);
728 memset(p->iobuf, 0, RBUFSIZE);
729 settag(p, Tsuper, QPSUPER);
730
731 s = (Superb*)p->iobuf;
732 s->fstart = 2;
733 s->fsize = devsize(dev);
734 s->fbuf.nfree = 1;
735 s->qidgen = 10;
736 for(i = s->fsize-1; i >= addr+2; i--)
737 addfree(dev, i, s);
738 putbuf(p);
739 }
740
741 struct
742 {
743 Lock;
744 Msgbuf *smsgbuf;
745 Msgbuf *lmsgbuf;
746 } msgalloc;
747
748 /*
749 * pre-allocate some message buffers at boot time.
750 * if this supply is exhausted, more will be allocated as needed.
751 */
752 void
mbinit(void)753 mbinit(void)
754 {
755 Msgbuf *mb;
756 Rabuf *rb;
757 int i;
758
759 lock(&msgalloc);
760 unlock(&msgalloc);
761 msgalloc.lmsgbuf = 0;
762 msgalloc.smsgbuf = 0;
763 for(i=0; i<conf.nlgmsg; i++) {
764 mb = malloc(sizeof(Msgbuf));
765 mb->magic = Mbmagic;
766 mb->xdata = malloc(LARGEBUF+Slop);
767 mb->flags = LARGE;
768 mbfree(mb);
769 cons.nlarge++;
770 }
771 for(i=0; i<conf.nsmmsg; i++) {
772 mb = malloc(sizeof(Msgbuf));
773 mb->magic = Mbmagic;
774 mb->xdata = malloc(SMALLBUF+Slop);
775 mb->flags = 0;
776 mbfree(mb);
777 cons.nsmall++;
778 }
779 memset(mballocs, 0, sizeof(mballocs));
780
781 lock(&rabuflock);
782 unlock(&rabuflock);
783 rabuffree = 0;
784 for(i=0; i<1000; i++) {
785 rb = malloc(sizeof(*rb));
786 rb->link = rabuffree;
787 rabuffree = rb;
788 }
789 }
790
791 Msgbuf*
mballoc(int count,Chan * cp,int category)792 mballoc(int count, Chan *cp, int category)
793 {
794 Msgbuf *mb;
795
796 lock(&msgalloc);
797 if(count > SMALLBUF) {
798 if(count > LARGEBUF)
799 panic("msgbuf count");
800 mb = msgalloc.lmsgbuf;
801 if(mb == nil) {
802 mb = malloc(sizeof(Msgbuf));
803 mb->xdata = malloc(LARGEBUF+Slop);
804 cons.nlarge++;
805 } else
806 msgalloc.lmsgbuf = mb->next;
807 mb->flags = LARGE;
808 } else {
809 mb = msgalloc.smsgbuf;
810 if(mb == nil) {
811 mb = malloc(sizeof(Msgbuf));
812 mb->xdata = malloc(SMALLBUF+Slop);
813 cons.nsmall++;
814 } else
815 msgalloc.smsgbuf = mb->next;
816 mb->flags = 0;
817 }
818 mballocs[category]++;
819 unlock(&msgalloc);
820 mb->magic = Mbmagic;
821 mb->count = count;
822 mb->chan = cp;
823 mb->next = 0;
824 mb->param = 0;
825 mb->category = category;
826 mb->data = mb->xdata+Slop;
827 return mb;
828 }
829
830 void
mbfree(Msgbuf * mb)831 mbfree(Msgbuf *mb)
832 {
833 if(mb == nil)
834 return;
835 assert(mb->magic == Mbmagic);
836 if (mb->magic != Mbmagic)
837 panic("mbfree: bad magic 0x%lux", mb->magic);
838 if(mb->flags & BTRACE)
839 print("mbfree: BTRACE cat=%d flags=%ux, caller %#p\n",
840 mb->category, mb->flags, getcallerpc(&mb));
841
842 if(mb->flags & FREE)
843 panic("mbfree already free");
844
845 lock(&msgalloc);
846 mballocs[mb->category]--;
847 mb->flags |= FREE;
848 if(mb->flags & LARGE) {
849 mb->next = msgalloc.lmsgbuf;
850 msgalloc.lmsgbuf = mb;
851 } else {
852 mb->next = msgalloc.smsgbuf;
853 msgalloc.smsgbuf = mb;
854 }
855 mb->data = 0;
856 mb->magic = 0;
857 unlock(&msgalloc);
858 }
859
860 /*
861 * returns 1 if n is prime
862 * used for adjusting lengths
863 * of hashing things.
864 * there is no need to be clever
865 */
866 int
prime(vlong n)867 prime(vlong n)
868 {
869 long i;
870
871 if((n%2) == 0)
872 return 0;
873 for(i=3;; i+=2) {
874 if((n%i) == 0)
875 return 0;
876 if((vlong)i*i >= n)
877 return 1;
878 }
879 }
880
881 char*
getwrd(char * word,char * line)882 getwrd(char *word, char *line)
883 {
884 int c, n;
885
886 while(isascii(*line) && isspace(*line) && *line != '\n')
887 line++;
888 for(n = 0; n < Maxword; n++) {
889 c = *line;
890 if(c == '\0' || isascii(c) && isspace(c))
891 break;
892 line++;
893 *word++ = c;
894 }
895 *word = 0;
896 return line;
897 }
898
899 void
hexdump(void * a,int n)900 hexdump(void *a, int n)
901 {
902 char s1[30], s2[4];
903 uchar *p;
904 int i;
905
906 p = a;
907 s1[0] = 0;
908 for(i = 0; i < n; i++) {
909 sprint(s2, " %.2ux", p[i]);
910 strcat(s1, s2);
911 if((i&7) == 7) {
912 print("%s\n", s1);
913 s1[0] = 0;
914 }
915 }
916 if(s1[0])
917 print("%s\n", s1);
918 }
919
920 void*
fs_recv(Queue * q,int)921 fs_recv(Queue *q, int)
922 {
923 void *a;
924 int i, c;
925
926 if(q == nil)
927 panic("recv null q");
928 qlock(q);
929 q->waitedfor = 1;
930 while((c = q->count) <= 0)
931 rsleep(&q->empty);
932 i = q->loc;
933 a = q->args[i];
934 i++;
935 if(i >= q->size)
936 i = 0;
937 q->loc = i;
938 q->count = c-1;
939 rwakeup(&q->full); /* no longer full */
940 qunlock(q);
941 return a;
942 }
943
944 void
fs_send(Queue * q,void * a)945 fs_send(Queue *q, void *a)
946 {
947 int i, c;
948
949 if(q == nil)
950 panic("send null q");
951 if(!q->waitedfor) {
952 for (i = 0; i < 5 && !q->waitedfor; i++)
953 sleep(1000);
954 if(!q->waitedfor) {
955 /* likely a bug; don't wait forever */
956 print("no readers yet for %s q\n", q->name);
957 abort();
958 }
959 }
960 qlock(q);
961 while((c = q->count) >= q->size)
962 rsleep(&q->full);
963 i = q->loc + c;
964 if(i >= q->size)
965 i -= q->size;
966 q->args[i] = a;
967 q->count = c+1;
968 rwakeup(&q->empty); /* no longer empty */
969 qunlock(q);
970 }
971
972 Queue*
newqueue(int size,char * name)973 newqueue(int size, char *name)
974 {
975 Queue *q;
976
977 q = malloc(sizeof(Queue) + (size-1)*sizeof(void*));
978 q->size = size;
979 q->full.l = q->empty.l = &q->QLock;
980 q->name = name;
981 return q;
982 }
983
984 int
devread(Device * d,Off b,void * c)985 devread(Device *d, Off b, void *c)
986 {
987 int e;
988
989 for (;;)
990 switch(d->type) {
991 case Devcw:
992 return cwread(d, b, c);
993
994 case Devjuke:
995 d = d->j.m;
996 break;
997
998 case Devro:
999 return roread(d, b, c);
1000
1001 case Devwren:
1002 return wrenread(d, b, c);
1003
1004 case Devworm:
1005 case Devlworm:
1006 return wormread(d, b, c);
1007
1008 case Devfworm:
1009 return fwormread(d, b, c);
1010
1011 case Devmcat:
1012 return mcatread(d, b, c);
1013
1014 case Devmlev:
1015 return mlevread(d, b, c);
1016
1017 case Devmirr:
1018 return mirrread(d, b, c);
1019
1020 case Devpart:
1021 return partread(d, b, c);
1022
1023 case Devswab:
1024 e = devread(d->swab.d, b, c);
1025 if(e == 0)
1026 swab(c, 0);
1027 return e;
1028
1029 case Devnone:
1030 print("read from device none(%lld)\n", (Wideoff)b);
1031 return 1;
1032 default:
1033 panic("illegal device in devread: %Z %lld",
1034 d, (Wideoff)b);
1035 return 1;
1036 }
1037 }
1038
1039 int
devwrite(Device * d,Off b,void * c)1040 devwrite(Device *d, Off b, void *c)
1041 {
1042 int e;
1043
1044 /*
1045 * set readonly to non-0 to prevent all writes;
1046 * mainly for trying dangerous experiments.
1047 */
1048 if (readonly)
1049 return 0;
1050 for (;;)
1051 switch(d->type) {
1052 case Devcw:
1053 return cwwrite(d, b, c);
1054
1055 case Devjuke:
1056 d = d->j.m;
1057 break;
1058
1059 case Devro:
1060 print("write to ro device %Z(%lld)\n", d, (Wideoff)b);
1061 return 1;
1062
1063 case Devwren:
1064 return wrenwrite(d, b, c);
1065
1066 case Devworm:
1067 case Devlworm:
1068 return wormwrite(d, b, c);
1069
1070 case Devfworm:
1071 return fwormwrite(d, b, c);
1072
1073 case Devmcat:
1074 return mcatwrite(d, b, c);
1075
1076 case Devmlev:
1077 return mlevwrite(d, b, c);
1078
1079 case Devmirr:
1080 return mirrwrite(d, b, c);
1081
1082 case Devpart:
1083 return partwrite(d, b, c);
1084
1085 case Devswab:
1086 swab(c, 1);
1087 e = devwrite(d->swab.d, b, c);
1088 swab(c, 0);
1089 return e;
1090
1091 case Devnone:
1092 /* checktag() can generate blocks with type devnone */
1093 return 0;
1094 default:
1095 panic("illegal device in devwrite: %Z %lld",
1096 d, (Wideoff)b);
1097 return 1;
1098 }
1099 }
1100
1101 Devsize
devsize(Device * d)1102 devsize(Device *d)
1103 {
1104 for (;;)
1105 switch(d->type) {
1106 case Devcw:
1107 case Devro:
1108 return cwsize(d);
1109
1110 case Devjuke:
1111 d = d->j.m;
1112 break;
1113
1114 case Devwren:
1115 return wrensize(d);
1116
1117 case Devworm:
1118 case Devlworm:
1119 return wormsize(d);
1120
1121 case Devfworm:
1122 return fwormsize(d);
1123
1124 case Devmcat:
1125 return mcatsize(d);
1126
1127 case Devmlev:
1128 return mlevsize(d);
1129
1130 case Devmirr:
1131 return mirrsize(d);
1132
1133 case Devpart:
1134 return partsize(d);
1135
1136 case Devswab:
1137 d = d->swab.d;
1138 break;
1139 default:
1140 panic("illegal device in devsize: %Z", d);
1141 return 0;
1142 }
1143 }
1144
1145 /* result is malloced */
1146 char *
sdof(Device * d)1147 sdof(Device *d)
1148 {
1149 static char name[256];
1150
1151 for (;;)
1152 switch(d->type) {
1153 case Devjuke:
1154 d = d->j.j; /* robotics */
1155 break;
1156 case Devwren:
1157 snprint(name, sizeof name, "/dev/sd%d%d", d->wren.ctrl,
1158 d->wren.targ);
1159 return strdup(name);
1160 case Devswab:
1161 d = d->swab.d;
1162 break;
1163 default:
1164 panic("illegal device in sdof: %Z", d);
1165 return nil;
1166 }
1167 }
1168
1169 Off
superaddr(Device * d)1170 superaddr(Device *d)
1171 {
1172 for (;;)
1173 switch(d->type) {
1174 default:
1175 return SUPER_ADDR;
1176 case Devcw:
1177 case Devro:
1178 return cwsaddr(d);
1179 case Devswab:
1180 d = d->swab.d;
1181 break;
1182 }
1183 }
1184
1185 Off
getraddr(Device * d)1186 getraddr(Device *d)
1187 {
1188 for (;;)
1189 switch(d->type) {
1190 default:
1191 return ROOT_ADDR;
1192 case Devcw:
1193 case Devro:
1194 return cwraddr(d);
1195 case Devswab:
1196 d = d->swab.d;
1197 break;
1198 }
1199 }
1200
1201 void
devream(Device * d,int top)1202 devream(Device *d, int top)
1203 {
1204 Device *l;
1205
1206 loop:
1207 print("\tdevream: %Z %d\n", d, top);
1208 switch(d->type) {
1209 default:
1210 print("ream: unknown dev type %Z\n", d);
1211 return;
1212
1213 case Devcw:
1214 devream(d->cw.w, 0);
1215 devream(d->cw.c, 0);
1216 if(top) {
1217 wlock(&mainlock);
1218 cwream(d);
1219 wunlock(&mainlock);
1220 }
1221 devinit(d);
1222 return;
1223
1224 case Devfworm:
1225 devream(d->fw.fw, 0);
1226 fwormream(d);
1227 break;
1228
1229 case Devpart:
1230 devream(d->part.d, 0);
1231 break;
1232
1233 case Devmlev:
1234 case Devmcat:
1235 case Devmirr:
1236 for(l=d->cat.first; l; l=l->link)
1237 devream(l, 0);
1238 break;
1239
1240 case Devjuke:
1241 case Devworm:
1242 case Devlworm:
1243 case Devwren:
1244 break;
1245
1246 case Devswab:
1247 d = d->swab.d;
1248 goto loop;
1249 }
1250 devinit(d);
1251 if(top) {
1252 wlock(&mainlock);
1253 rootream(d, ROOT_ADDR);
1254 superream(d, SUPER_ADDR);
1255 wunlock(&mainlock);
1256 }
1257 }
1258
1259 void
devrecover(Device * d)1260 devrecover(Device *d)
1261 {
1262 for (;;) {
1263 print("recover: %Z\n", d);
1264 switch(d->type) {
1265 default:
1266 print("recover: unknown dev type %Z\n", d);
1267 return;
1268
1269 case Devcw:
1270 wlock(&mainlock); /* recover */
1271 cwrecover(d);
1272 wunlock(&mainlock);
1273 return;
1274
1275 case Devswab:
1276 d = d->swab.d;
1277 break;
1278 }
1279 }
1280 }
1281
1282 void
devinit(Device * d)1283 devinit(Device *d)
1284 {
1285 for (;;) {
1286 if(d->init)
1287 return;
1288 d->init = 1;
1289 print("\tdevinit %Z\n", d);
1290 switch(d->type) {
1291 default:
1292 print("devinit unknown device %Z\n", d);
1293 return;
1294
1295 case Devro:
1296 cwinit(d->ro.parent);
1297 return;
1298
1299 case Devcw:
1300 cwinit(d);
1301 return;
1302
1303 case Devjuke:
1304 jukeinit(d);
1305 return;
1306
1307 case Devwren:
1308 wreninit(d);
1309 return;
1310
1311 case Devworm:
1312 case Devlworm:
1313 return;
1314
1315 case Devfworm:
1316 fworminit(d);
1317 return;
1318
1319 case Devmcat:
1320 mcatinit(d);
1321 return;
1322
1323 case Devmlev:
1324 mlevinit(d);
1325 return;
1326
1327 case Devmirr:
1328 mirrinit(d);
1329 return;
1330
1331 case Devpart:
1332 partinit(d);
1333 return;
1334
1335 case Devswab:
1336 d = d->swab.d;
1337 break;
1338
1339 case Devnone:
1340 print("devinit of Devnone\n");
1341 return;
1342 }
1343 }
1344 }
1345
1346 void
swab2(void * c)1347 swab2(void *c)
1348 {
1349 uchar *p;
1350 int t;
1351
1352 p = c;
1353
1354 t = p[0];
1355 p[0] = p[1];
1356 p[1] = t;
1357 }
1358
1359 void
swab4(void * c)1360 swab4(void *c)
1361 {
1362 uchar *p;
1363 int t;
1364
1365 p = c;
1366
1367 t = p[0];
1368 p[0] = p[3];
1369 p[3] = t;
1370
1371 t = p[1];
1372 p[1] = p[2];
1373 p[2] = t;
1374 }
1375
1376 void
swab8(void * c)1377 swab8(void *c)
1378 {
1379 uchar *p;
1380 int t;
1381
1382 p = c;
1383
1384 t = p[0];
1385 p[0] = p[7];
1386 p[7] = t;
1387
1388 t = p[1];
1389 p[1] = p[6];
1390 p[6] = t;
1391
1392 t = p[2];
1393 p[2] = p[5];
1394 p[5] = t;
1395
1396 t = p[3];
1397 p[3] = p[4];
1398 p[4] = t;
1399 }
1400
1401 /*
1402 * swab a block
1403 * flag = 0 -- convert from foreign to native
1404 * flag = 1 -- convert from native to foreign
1405 */
1406 void
swab(void * c,int flag)1407 swab(void *c, int flag)
1408 {
1409 uchar *p;
1410 Tag *t;
1411 int i, j;
1412 Dentry *d;
1413 Cache *h;
1414 Bucket *b;
1415 Superb *s;
1416 Fbuf *f;
1417 Off *l;
1418
1419 /* swab the tag */
1420 p = (uchar*)c;
1421 t = (Tag*)(p + BUFSIZE);
1422 if(!flag) {
1423 swab2(&t->pad);
1424 swab2(&t->tag);
1425 swaboff(&t->path);
1426 }
1427
1428 /* swab each block type */
1429 switch(t->tag) {
1430
1431 default:
1432 print("no swab for tag=%G rw=%d\n", t->tag, flag);
1433 for(j=0; j<16; j++)
1434 print(" %.2x", p[BUFSIZE+j]);
1435 print("\n");
1436 for(i=0; i<16; i++) {
1437 print("%.4x", i*16);
1438 for(j=0; j<16; j++)
1439 print(" %.2x", p[i*16+j]);
1440 print("\n");
1441 }
1442 panic("swab");
1443 break;
1444
1445 case Tsuper:
1446 s = (Superb*)p;
1447 swaboff(&s->fbuf.nfree);
1448 for(i=0; i<FEPERBUF; i++)
1449 swaboff(&s->fbuf.free[i]);
1450 swaboff(&s->fstart);
1451 swaboff(&s->fsize);
1452 swaboff(&s->tfree);
1453 swaboff(&s->qidgen);
1454 swaboff(&s->cwraddr);
1455 swaboff(&s->roraddr);
1456 swaboff(&s->last);
1457 swaboff(&s->next);
1458 break;
1459
1460 case Tdir:
1461 for(i=0; i<DIRPERBUF; i++) {
1462 d = (Dentry*)p + i;
1463 swab2(&d->uid);
1464 swab2(&d->gid);
1465 swab2(&d->mode);
1466 swab2(&d->muid);
1467 swaboff(&d->qid.path);
1468 swab4(&d->qid.version);
1469 swaboff(&d->size);
1470 for(j=0; j<NDBLOCK; j++)
1471 swaboff(&d->dblock[j]);
1472 for (j = 0; j < NIBLOCK; j++)
1473 swaboff(&d->iblocks[j]);
1474 swab4(&d->atime);
1475 swab4(&d->mtime);
1476 }
1477 break;
1478
1479 case Tind1:
1480 case Tind2:
1481 #ifndef COMPAT32
1482 case Tind3:
1483 case Tind4:
1484 /* add more Tind tags here ... */
1485 #endif
1486 l = (Off *)p;
1487 for(i=0; i<INDPERBUF; i++) {
1488 swaboff(l);
1489 l++;
1490 }
1491 break;
1492
1493 case Tfree:
1494 f = (Fbuf*)p;
1495 swaboff(&f->nfree);
1496 for(i=0; i<FEPERBUF; i++)
1497 swaboff(&f->free[i]);
1498 break;
1499
1500 case Tbuck:
1501 for(i=0; i<BKPERBLK; i++) {
1502 b = (Bucket*)p + i;
1503 swab4(&b->agegen);
1504 for(j=0; j<CEPERBK; j++) {
1505 swab2(&b->entry[j].age);
1506 swab2(&b->entry[j].state);
1507 swaboff(&b->entry[j].waddr);
1508 }
1509 }
1510 break;
1511
1512 case Tcache:
1513 h = (Cache*)p;
1514 swaboff(&h->maddr);
1515 swaboff(&h->msize);
1516 swaboff(&h->caddr);
1517 swaboff(&h->csize);
1518 swaboff(&h->fsize);
1519 swaboff(&h->wsize);
1520 swaboff(&h->wmax);
1521 swaboff(&h->sbaddr);
1522 swaboff(&h->cwraddr);
1523 swaboff(&h->roraddr);
1524 swab4(&h->toytime);
1525 swab4(&h->time);
1526 break;
1527
1528 case Tnone: // unitialized
1529 case Tfile: // someone elses problem
1530 case Tvirgo: // bit map -- all bytes
1531 case Tconfig: // configuration string -- all bytes
1532 break;
1533 }
1534
1535 /* swab the tag */
1536 if(flag) {
1537 swab2(&t->pad);
1538 swab2(&t->tag);
1539 swaboff(&t->path);
1540 }
1541 }
1542