xref: /plan9/sys/src/cmd/cwfs/sub.c (revision eba00c1180f26027fec6be9f76c54eccfce0d97b)
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