Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"lib.h"
3
#include	"dat.h"
4
#include	"fns.h"
5
#include	"error.h"
6
 
7
int chandebug=0;		/* toggled by sysr1 */
8
QLock chanprint;		/* probably asking for trouble (deadlocks) -rsc */
9
 
10
int domount(Chan**, Mhead**);
11
 
12
void
13
dumpmount(void)		/* DEBUGGING */
14
{
15
	Pgrp *pg;
16
	Mount *t;
17
	Mhead **h, **he, *f;
18
 
19
	if(up == nil){
20
		print("no process for dumpmount\n");
21
		return;
22
	}
23
	pg = up->pgrp;
24
	if(pg == nil){
25
		print("no pgrp for dumpmount\n");
26
		return;
27
	}
28
	rlock(&pg->ns);
29
	if(waserror()) {
30
		runlock(&pg->ns);
31
		nexterror();
32
	}
33
 
34
	he = &pg->mnthash[MNTHASH];
35
	for(h = pg->mnthash; h < he; h++) {
36
		for(f = *h; f; f = f->hash) {
37
			print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f,
38
				f->from->name->s, f->from->qid.path,
39
				f->from->qid.vers, devtab[f->from->type]->dc,
40
				f->from->dev);
41
			for(t = f->mount; t; t = t->next)
42
				print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->name->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);
43
		}
44
	}
45
	poperror();
46
	runlock(&pg->ns);
47
}
48
 
49
 
50
char*
51
c2name(Chan *c)		/* DEBUGGING */
52
{
53
	if(c == nil)
54
		return "<nil chan>";
55
	if(c->name == nil)
56
		return "<nil name>";
57
	if(c->name->s == nil)
58
		return "<nil name.s>";
59
	return c->name->s;
60
}
61
 
62
enum
63
{
64
	CNAMESLOP	= 20
65
};
66
 
67
struct
68
{
69
	Lock lk;
70
	int	fid;
71
	Chan	*free;
72
	Chan	*list;
73
}chanalloc;
74
 
75
typedef struct Elemlist Elemlist;
76
 
77
struct Elemlist
78
{
79
	char	*name;	/* copy of name, so '/' can be overwritten */
80
	int	nelems;
81
	char	**elems;
82
	int	*off;
83
	int	mustbedir;
84
};
85
 
86
#define SEP(c) ((c) == 0 || (c) == '/')
87
void cleancname(Cname*);
88
 
89
int
90
isdotdot(char *p)
91
{
92
	return p[0]=='.' && p[1]=='.' && p[2]=='\0';
93
}
94
 
95
int
96
incref(Ref *r)
97
{
98
	int x;
99
 
100
	lock(&r->lk);
101
	x = ++r->ref;
102
	unlock(&r->lk);
103
	return x;
104
}
105
 
106
int
107
decref(Ref *r)
108
{
109
	int x;
110
 
111
	lock(&r->lk);
112
	x = --r->ref;
113
	unlock(&r->lk);
114
	if(x < 0)
115
		panic("decref, pc=0x%p", getcallerpc(&r));
116
 
117
	return x;
118
}
119
 
120
/*
121
 * Rather than strncpy, which zeros the rest of the buffer, kstrcpy
122
 * truncates if necessary, always zero terminates, does not zero fill,
123
 * and puts ... at the end of the string if it's too long.  Usually used to
124
 * save a string in up->genbuf;
125
 */
126
void
127
kstrcpy(char *s, char *t, int ns)
128
{
129
	int nt;
130
 
131
	nt = strlen(t);
132
	if(nt+1 <= ns){
133
		memmove(s, t, nt+1);
134
		return;
135
	}
136
	/* too long */
137
	if(ns < 4){
138
		/* but very short! */
139
		strncpy(s, t, ns);
140
		return;
141
	}
142
	/* truncate with ... at character boundary (very rare case) */
143
	memmove(s, t, ns-4);
144
	ns -= 4;
145
	s[ns] = '\0';
146
	/* look for first byte of UTF-8 sequence by skipping continuation bytes */
147
	while(ns>0 && (s[--ns]&0xC0)==0x80)
148
		;
149
	strcpy(s+ns, "...");
150
}
151
 
152
int
153
emptystr(char *s)
154
{
155
	if(s == nil)
156
		return 1;
157
	if(s[0] == '\0')
158
		return 1;
159
	return 0;
160
}
161
 
162
/*
163
 * Atomically replace *p with copy of s
164
 */
165
void
166
kstrdup(char **p, char *s)
167
{
168
	int n;
169
	char *t, *prev;
170
 
171
	n = strlen(s)+1;
172
	/* if it's a user, we can wait for memory; if not, something's very wrong */
173
	if(up){
174
		t = smalloc(n);
175
		setmalloctag(t, getcallerpc(&p));
176
	}else{
177
		t = malloc(n);
178
		if(t == nil)
179
			panic("kstrdup: no memory");
180
	}
181
	memmove(t, s, n);
182
	prev = *p;
183
	*p = t;
184
	free(prev);
185
}
186
 
187
void
188
chandevreset(void)
189
{
190
	int i;
191
 
192
	for(i=0; devtab[i] != nil; i++)
193
		devtab[i]->reset();
194
}
195
 
196
void
197
chandevinit(void)
198
{
199
	int i;
200
 
201
	for(i=0; devtab[i] != nil; i++)
202
		devtab[i]->init();
203
}
204
 
205
void
206
chandevshutdown(void)
207
{
208
	int i;
209
 
210
	/* shutdown in reverse order */
211
	for(i=0; devtab[i] != nil; i++)
212
		;
213
	for(i--; i >= 0; i--)
214
		devtab[i]->shutdown();
215
}
216
 
217
Chan*
218
newchan(void)
219
{
220
	Chan *c;
221
 
222
	lock(&chanalloc.lk);
223
	c = chanalloc.free;
224
	if(c != 0)
225
		chanalloc.free = c->next;
226
	unlock(&chanalloc.lk);
227
 
228
	if(c == nil) {
229
		c = smalloc(sizeof(Chan));
230
		lock(&chanalloc.lk);
231
		c->fid = ++chanalloc.fid;
232
		c->link = chanalloc.list;
233
		chanalloc.list = c;
234
		unlock(&chanalloc.lk);
235
	}
236
 
237
	/* if you get an error before associating with a dev,
238
	   close calls rootclose, a nop */
239
	c->type = 0;
240
	c->flag = 0;
241
	c->ref.ref = 1;
242
	c->dev = 0;
243
	c->offset = 0;
244
	c->iounit = 0;
245
	c->umh = 0;
246
	c->uri = 0;
247
	c->dri = 0;
248
	c->aux = 0;
249
	c->mchan = 0;
250
	c->mcp = 0;
251
	c->mux = 0;
252
	memset(&c->mqid, 0, sizeof(c->mqid));
253
	c->name = 0;
254
	return c;
255
}
256
 
257
static Ref ncname;
258
 
259
Cname*
260
newcname(char *s)
261
{
262
	Cname *n;
263
	int i;
264
 
265
	n = smalloc(sizeof(Cname));
266
	i = strlen(s);
267
	n->len = i;
268
	n->alen = i+CNAMESLOP;
269
	n->s = smalloc(n->alen);
270
	memmove(n->s, s, i+1);
271
	n->ref.ref = 1;
272
	incref(&ncname);
273
	return n;
274
}
275
 
276
void
277
cnameclose(Cname *n)
278
{
279
	if(n == nil)
280
		return;
281
	if(decref(&n->ref))
282
		return;
283
	decref(&ncname);
284
	free(n->s);
285
	free(n);
286
}
287
 
288
Cname*
289
addelem(Cname *n, char *s)
290
{
291
	int i, a;
292
	char *t;
293
	Cname *new;
294
 
295
	if(s[0]=='.' && s[1]=='\0')
296
		return n;
297
 
298
	if(n->ref.ref > 1){
299
		/* copy on write */
300
		new = newcname(n->s);
301
		cnameclose(n);
302
		n = new;
303
	}
304
 
305
	i = strlen(s);
306
	if(n->len+1+i+1 > n->alen){
307
		a = n->len+1+i+1 + CNAMESLOP;
308
		t = smalloc(a);
309
		memmove(t, n->s, n->len+1);
310
		free(n->s);
311
		n->s = t;
312
		n->alen = a;
313
	}
314
	if(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/')	/* don't insert extra slash if one is present */
315
		n->s[n->len++] = '/';
316
	memmove(n->s+n->len, s, i+1);
317
	n->len += i;
318
	if(isdotdot(s))
319
		cleancname(n);
320
	return n;
321
}
322
 
323
void
324
chanfree(Chan *c)
325
{
326
	c->flag = CFREE;
327
 
328
	if(c->umh != nil){
329
		putmhead(c->umh);
330
		c->umh = nil;
331
	}
332
	if(c->umc != nil){
333
		cclose(c->umc);
334
		c->umc = nil;
335
	}
336
	if(c->mux != nil){
337
		muxclose(c->mux);
338
		c->mux = nil;
339
	}
340
	if(c->mchan != nil){
341
		cclose(c->mchan);
342
		c->mchan = nil;
343
	}
344
 
345
	cnameclose(c->name);
346
 
347
	lock(&chanalloc.lk);
348
	c->next = chanalloc.free;
349
	chanalloc.free = c;
350
	unlock(&chanalloc.lk);
351
}
352
 
353
void
354
cclose(Chan *c)
355
{
356
	if(c->flag&CFREE)
357
		panic("cclose %p", getcallerpc(&c));
358
 
359
	if(decref(&c->ref))
360
		return;
361
 
362
	if(!waserror()){
363
		devtab[c->type]->close(c);
364
		poperror();
365
	}
366
	chanfree(c);
367
}
368
 
369
/*
370
 * Make sure we have the only copy of c.  (Copy on write.)
371
 */
372
Chan*
373
cunique(Chan *c)
374
{
375
	Chan *nc;
376
 
377
	if(c->ref.ref != 1) {
378
		nc = cclone(c);
379
		cclose(c);
380
		c = nc;
381
	}
382
 
383
	return c;
384
}
385
 
386
int
387
eqqid(Qid a, Qid b)
388
{
389
	return a.path==b.path && a.vers==b.vers;
390
}
391
 
392
int
393
eqchan(Chan *a, Chan *b, int pathonly)
394
{
395
	if(a->qid.path != b->qid.path)
396
		return 0;
397
	if(!pathonly && a->qid.vers!=b->qid.vers)
398
		return 0;
399
	if(a->type != b->type)
400
		return 0;
401
	if(a->dev != b->dev)
402
		return 0;
403
	return 1;
404
}
405
 
406
int
407
eqchantdqid(Chan *a, int type, int dev, Qid qid, int pathonly)
408
{
409
	if(a->qid.path != qid.path)
410
		return 0;
411
	if(!pathonly && a->qid.vers!=qid.vers)
412
		return 0;
413
	if(a->type != type)
414
		return 0;
415
	if(a->dev != dev)
416
		return 0;
417
	return 1;
418
}
419
 
420
Mhead*
421
newmhead(Chan *from)
422
{
423
	Mhead *mh;
424
 
425
	mh = smalloc(sizeof(Mhead));
426
	mh->ref.ref = 1;
427
	mh->from = from;
428
	incref(&from->ref);
429
 
430
/*
431
	n = from->name->len;
432
	if(n >= sizeof(mh->fromname))
433
		n = sizeof(mh->fromname)-1;
434
	memmove(mh->fromname, from->name->s, n);
435
	mh->fromname[n] = 0;
436
*/
437
	return mh;
438
}
439
 
440
int
441
cmount(Chan **newp, Chan *old, int flag, char *spec)
442
{
443
	Pgrp *pg;
444
	int order, flg;
445
	Mhead *m, **l, *mh;
446
	Mount *nm, *f, *um, **h;
447
	Chan *new;
448
 
449
	if(QTDIR & (old->qid.type^(*newp)->qid.type))
450
		error(Emount);
451
 
452
if(old->umh)print("cmount old extra umh\n");
453
 
454
	order = flag&MORDER;
455
 
456
	if((old->qid.type&QTDIR)==0 && order != MREPL)
457
		error(Emount);
458
 
459
	new = *newp;
460
	mh = new->umh;
461
 
462
	/*
463
	 * Not allowed to bind when the old directory
464
	 * is itself a union.  (Maybe it should be allowed, but I don't see
465
	 * what the semantics would be.)
466
	 *
467
	 * We need to check mh->mount->next to tell unions apart from
468
	 * simple mount points, so that things like
469
	 *	mount -c fd /root
470
	 *	bind -c /root /
471
	 * work.  The check of mount->mflag catches things like
472
	 *	mount fd /root
473
	 *	bind -c /root /
474
	 * 
475
	 * This is far more complicated than it should be, but I don't
476
	 * see an easier way at the moment.		-rsc
477
	 */
478
	if((flag&MCREATE) && mh && mh->mount
479
	&& (mh->mount->next || !(mh->mount->mflag&MCREATE)))
480
		error(Emount);
481
 
482
	pg = up->pgrp;
483
	wlock(&pg->ns);
484
 
485
	l = &MOUNTH(pg, old->qid);
486
	for(m = *l; m; m = m->hash) {
487
		if(eqchan(m->from, old, 1))
488
			break;
489
		l = &m->hash;
490
	}
491
 
492
	if(m == nil) {
493
		/*
494
		 *  nothing mounted here yet.  create a mount
495
		 *  head and add to the hash table.
496
		 */
497
		m = newmhead(old);
498
		*l = m;
499
 
500
		/*
501
		 *  if this is a union mount, add the old
502
		 *  node to the mount chain.
503
		 */
504
		if(order != MREPL)
505
			m->mount = newmount(m, old, 0, 0);
506
	}
507
	wlock(&m->lock);
508
	if(waserror()){
509
		wunlock(&m->lock);
510
		nexterror();
511
	}
512
	wunlock(&pg->ns);
513
 
514
	nm = newmount(m, new, flag, spec);
515
	if(mh != nil && mh->mount != nil) {
516
		/*
517
		 *  copy a union when binding it onto a directory
518
		 */
519
		flg = order;
520
		if(order == MREPL)
521
			flg = MAFTER;
522
		h = &nm->next;
523
		um = mh->mount;
524
		for(um = um->next; um; um = um->next) {
525
			f = newmount(m, um->to, flg, um->spec);
526
			*h = f;
527
			h = &f->next;
528
		}
529
	}
530
 
531
	if(m->mount && order == MREPL) {
532
		mountfree(m->mount);
533
		m->mount = 0;
534
	}
535
 
536
	if(flag & MCREATE)
537
		nm->mflag |= MCREATE;
538
 
539
	if(m->mount && order == MAFTER) {
540
		for(f = m->mount; f->next; f = f->next)
541
			;
542
		f->next = nm;
543
	}
544
	else {
545
		for(f = nm; f->next; f = f->next)
546
			;
547
		f->next = m->mount;
548
		m->mount = nm;
549
	}
550
 
551
	wunlock(&m->lock);
552
	poperror();
553
	return nm->mountid;
554
}
555
 
556
void
557
cunmount(Chan *mnt, Chan *mounted)
558
{
559
	Pgrp *pg;
560
	Mhead *m, **l;
561
	Mount *f, **p;
562
 
563
	if(mnt->umh)	/* should not happen */
564
		print("cunmount newp extra umh %p has %p\n", mnt, mnt->umh);
565
 
566
	/*
567
	 * It _can_ happen that mounted->umh is non-nil, 
568
	 * because mounted is the result of namec(Aopen)
569
	 * (see sysfile.c:/^sysunmount).
570
	 * If we open a union directory, it will have a umh.
571
	 * Although surprising, this is okay, since the
572
	 * cclose will take care of freeing the umh.
573
	 */
574
 
575
	pg = up->pgrp;
576
	wlock(&pg->ns);
577
 
578
	l = &MOUNTH(pg, mnt->qid);
579
	for(m = *l; m; m = m->hash) {
580
		if(eqchan(m->from, mnt, 1))
581
			break;
582
		l = &m->hash;
583
	}
584
 
585
	if(m == 0) {
586
		wunlock(&pg->ns);
587
		error(Eunmount);
588
	}
589
 
590
	wlock(&m->lock);
591
	if(mounted == 0) {
592
		*l = m->hash;
593
		wunlock(&pg->ns);
594
		mountfree(m->mount);
595
		m->mount = nil;
596
		cclose(m->from);
597
		wunlock(&m->lock);
598
		putmhead(m);
599
		return;
600
	}
601
 
602
	p = &m->mount;
603
	for(f = *p; f; f = f->next) {
604
		/* BUG: Needs to be 2 pass */
605
		if(eqchan(f->to, mounted, 1) ||
606
		  (f->to->mchan && eqchan(f->to->mchan, mounted, 1))) {
607
			*p = f->next;
608
			f->next = 0;
609
			mountfree(f);
610
			if(m->mount == nil) {
611
				*l = m->hash;
612
				cclose(m->from);
613
				wunlock(&m->lock);
614
				wunlock(&pg->ns);
615
				putmhead(m);
616
				return;
617
			}
618
			wunlock(&m->lock);
619
			wunlock(&pg->ns);
620
			return;
621
		}
622
		p = &f->next;
623
	}
624
	wunlock(&m->lock);
625
	wunlock(&pg->ns);
626
	error(Eunion);
627
}
628
 
629
Chan*
630
cclone(Chan *c)
631
{
632
	Chan *nc;
633
	Walkqid *wq;
634
 
635
	wq = devtab[c->type]->walk(c, nil, nil, 0);
636
	if(wq == nil)
637
		error("clone failed");
638
	nc = wq->clone;
639
	free(wq);
640
	nc->name = c->name;
641
	if(c->name)
642
		incref(&c->name->ref);
643
	return nc;
644
}
645
 
646
int
647
findmount(Chan **cp, Mhead **mp, int type, int dev, Qid qid)
648
{
649
	Pgrp *pg;
650
	Mhead *m;
651
 
652
	pg = up->pgrp;
653
	rlock(&pg->ns);
654
	for(m = MOUNTH(pg, qid); m; m = m->hash){
655
		rlock(&m->lock);
656
if(m->from == nil){
657
	print("m %p m->from 0\n", m);
658
	runlock(&m->lock);
659
	continue;
660
}
661
		if(eqchantdqid(m->from, type, dev, qid, 1)) {
662
			runlock(&pg->ns);
663
			if(mp != nil){
664
				incref(&m->ref);
665
				if(*mp != nil)
666
					putmhead(*mp);
667
				*mp = m;
668
			}
669
			if(*cp != nil)
670
				cclose(*cp);
671
			incref(&m->mount->to->ref);
672
			*cp = m->mount->to;
673
			runlock(&m->lock);
674
			return 1;
675
		}
676
		runlock(&m->lock);
677
	}
678
 
679
	runlock(&pg->ns);
680
	return 0;
681
}
682
 
683
int
684
domount(Chan **cp, Mhead **mp)
685
{
686
	return findmount(cp, mp, (*cp)->type, (*cp)->dev, (*cp)->qid);
687
}
688
 
689
Chan*
690
undomount(Chan *c, Cname *name)
691
{
692
	Chan *nc;
693
	Pgrp *pg;
694
	Mount *t;
695
	Mhead **h, **he, *f;
696
 
697
	pg = up->pgrp;
698
	rlock(&pg->ns);
699
	if(waserror()) {
700
		runlock(&pg->ns);
701
		nexterror();
702
	}
703
 
704
	he = &pg->mnthash[MNTHASH];
705
	for(h = pg->mnthash; h < he; h++) {
706
		for(f = *h; f; f = f->hash) {
707
			if(strcmp(f->from->name->s, name->s) != 0)
708
				continue;
709
			for(t = f->mount; t; t = t->next) {
710
				if(eqchan(c, t->to, 1)) {
711
					/*
712
					 * We want to come out on the left hand side of the mount
713
					 * point using the element of the union that we entered on.
714
					 * To do this, find the element that has a from name of
715
					 * c->name->s.
716
					 */
717
					if(strcmp(t->head->from->name->s, name->s) != 0)
718
						continue;
719
					nc = t->head->from;
720
					incref(&nc->ref);
721
					cclose(c);
722
					c = nc;
723
					break;
724
				}
725
			}
726
		}
727
	}
728
	poperror();
729
	runlock(&pg->ns);
730
	return c;
731
}
732
 
733
/*
734
 * Either walks all the way or not at all.  No partial results in *cp.
735
 * *nerror is the number of names to display in an error message.
736
 */
737
static char Edoesnotexist[] = "does not exist";
738
int
739
walk(Chan **cp, char **names, int nnames, int nomount, int *nerror)
740
{
741
	int dev, dotdot, i, n, nhave, ntry, type;
742
	Chan *c, *nc;
743
	Cname *cname;
744
	Mount *f;
745
	Mhead *mh, *nmh;
746
	Walkqid *wq;
747
 
748
	c = *cp;
749
	incref(&c->ref);
750
	cname = c->name;
751
	incref(&cname->ref);
752
	mh = nil;
753
 
754
	/*
755
	 * While we haven't gotten all the way down the path:
756
	 *    1. step through a mount point, if any
757
	 *    2. send a walk request for initial dotdot or initial prefix without dotdot
758
	 *    3. move to the first mountpoint along the way.
759
	 *    4. repeat.
760
	 *
761
	 * An invariant is that each time through the loop, c is on the undomount
762
	 * side of the mount point, and c's name is cname.
763
	 */
764
	for(nhave=0; nhave<nnames; nhave+=n){
765
		if((c->qid.type&QTDIR)==0){
766
			if(nerror)
767
				*nerror = nhave;
768
			cnameclose(cname);
769
			cclose(c);
770
			strcpy(up->errstr, Enotdir);
771
			if(mh != nil)
772
{print("walk 1\n");
773
				putmhead(mh);
774
}
775
			return -1;
776
		}
777
		ntry = nnames - nhave;
778
		if(ntry > MAXWELEM)
779
			ntry = MAXWELEM;
780
		dotdot = 0;
781
		for(i=0; i<ntry; i++){
782
			if(isdotdot(names[nhave+i])){
783
				if(i==0) {
784
					dotdot = 1;
785
					ntry = 1;
786
				} else
787
					ntry = i;
788
				break;
789
			}
790
		}
791
 
792
		if(!dotdot && !nomount)
793
			domount(&c, &mh);
794
 
795
		type = c->type;
796
		dev = c->dev;
797
 
798
		if((wq = devtab[type]->walk(c, nil, names+nhave, ntry)) == nil){
799
			/* try a union mount, if any */
800
			if(mh && !nomount){
801
				/*
802
				 * mh->mount == c, so start at mh->mount->next
803
				 */
804
				rlock(&mh->lock);
805
				for(f = mh->mount->next; f; f = f->next)
806
					if((wq = devtab[f->to->type]->walk(f->to, nil, names+nhave, ntry)) != nil)
807
						break;
808
				runlock(&mh->lock);
809
				if(f != nil){
810
					type = f->to->type;
811
					dev = f->to->dev;
812
				}
813
			}
814
			if(wq == nil){
815
				cclose(c);
816
				cnameclose(cname);
817
				if(nerror)
818
					*nerror = nhave+1;
819
				if(mh != nil)
820
					putmhead(mh);
821
				return -1;
822
			}
823
		}
824
 
825
		nmh = nil;
826
		if(dotdot) {
827
			assert(wq->nqid == 1);
828
			assert(wq->clone != nil);
829
 
830
			cname = addelem(cname, "..");
831
			nc = undomount(wq->clone, cname);
832
			n = 1;
833
		} else {
834
			nc = nil;
835
			if(!nomount)
836
				for(i=0; i<wq->nqid && i<ntry-1; i++)
837
					if(findmount(&nc, &nmh, type, dev, wq->qid[i]))
838
						break;
839
			if(nc == nil){	/* no mount points along path */
840
				if(wq->clone == nil){
841
					cclose(c);
842
					cnameclose(cname);
843
					if(wq->nqid==0 || (wq->qid[wq->nqid-1].type&QTDIR)){
844
						if(nerror)
845
							*nerror = nhave+wq->nqid+1;
846
						strcpy(up->errstr, Edoesnotexist);
847
					}else{
848
						if(nerror)
849
							*nerror = nhave+wq->nqid;
850
						strcpy(up->errstr, Enotdir);
851
					}
852
					free(wq);
853
					if(mh != nil)
854
						putmhead(mh);
855
					return -1;
856
				}
857
				n = wq->nqid;
858
				nc = wq->clone;
859
			}else{		/* stopped early, at a mount point */
860
				if(wq->clone != nil){
861
					cclose(wq->clone);
862
					wq->clone = nil;
863
				}
864
				n = i+1;
865
			}
866
			for(i=0; i<n; i++)
867
				cname = addelem(cname, names[nhave+i]);
868
		}
869
		cclose(c);
870
		c = nc;
871
		putmhead(mh);
872
		mh = nmh;
873
		free(wq);
874
	}
875
 
876
	putmhead(mh);
877
 
878
	c = cunique(c);
879
 
880
	if(c->umh != nil){	//BUG
881
		print("walk umh\n");
882
		putmhead(c->umh);
883
		c->umh = nil;
884
	}
885
 
886
	cnameclose(c->name);
887
	c->name = cname;
888
 
889
	cclose(*cp);
890
	*cp = c;
891
	if(nerror)
892
		*nerror = 0;
893
	return 0;
894
}
895
 
896
/*
897
 * c is a mounted non-creatable directory.  find a creatable one.
898
 */
899
Chan*
900
createdir(Chan *c, Mhead *m)
901
{
902
	Chan *nc;
903
	Mount *f;
904
 
905
	rlock(&m->lock);
906
	if(waserror()) {
907
		runlock(&m->lock);
908
		nexterror();
909
	}
910
	for(f = m->mount; f; f = f->next) {
911
		if(f->mflag&MCREATE) {
912
			nc = cclone(f->to);
913
			runlock(&m->lock);
914
			poperror();
915
			cclose(c);
916
			return nc;
917
		}
918
	}
919
	error(Enocreate);
920
	return 0;
921
}
922
 
923
void
924
saveregisters(void)
925
{
926
}
927
 
928
/*
929
 * In place, rewrite name to compress multiple /, eliminate ., and process ..
930
 */
931
void
932
cleancname(Cname *n)
933
{
934
	char *p;
935
 
936
	if(n->s[0] == '#'){
937
		p = strchr(n->s, '/');
938
		if(p == nil)
939
			return;
940
		cleanname(p);
941
 
942
		/*
943
		 * The correct name is #i rather than #i/,
944
		 * but the correct name of #/ is #/.
945
		 */
946
		if(strcmp(p, "/")==0 && n->s[1] != '/')
947
			*p = '\0';
948
	}else
949
		cleanname(n->s);
950
	n->len = strlen(n->s);
951
}
952
 
953
static void
954
growparse(Elemlist *e)
955
{
956
	char **new;
957
	int *inew;
958
	enum { Delta = 8 };
959
 
960
	if(e->nelems % Delta == 0){
961
		new = smalloc((e->nelems+Delta) * sizeof(char*));
962
		memmove(new, e->elems, e->nelems*sizeof(char*));
963
		free(e->elems);
964
		e->elems = new;
965
		inew = smalloc((e->nelems+Delta+1) * sizeof(int));
966
		memmove(inew, e->off, e->nelems*sizeof(int));
967
		free(e->off);
968
		e->off = inew;
969
	}
970
}
971
 
972
/*
973
 * The name is known to be valid.
974
 * Copy the name so slashes can be overwritten.
975
 * An empty string will set nelem=0.
976
 * A path ending in / or /. or /.//./ etc. will have
977
 * e.mustbedir = 1, so that we correctly
978
 * reject, e.g., "/adm/users/." when /adm/users is a file
979
 * rather than a directory.
980
 */
981
static void
982
parsename(char *name, Elemlist *e)
983
{
984
	char *slash;
985
 
986
	kstrdup(&e->name, name);
987
	name = e->name;
988
	e->nelems = 0;
989
	e->elems = nil;
990
	e->off = smalloc(sizeof(int));
991
	e->off[0] = skipslash(name) - name;
992
	for(;;){
993
		name = skipslash(name);
994
		if(*name=='\0'){
995
			e->mustbedir = 1;
996
			break;
997
		}
998
		growparse(e);
999
		e->elems[e->nelems++] = name;
1000
		slash = utfrune(name, '/');
1001
		if(slash == nil){
1002
			e->off[e->nelems] = name+strlen(name) - e->name;
1003
			e->mustbedir = 0;
1004
			break;
1005
		}
1006
		e->off[e->nelems] = slash - e->name;
1007
		*slash++ = '\0';
1008
		name = slash;
1009
	}
1010
}
1011
 
1012
void*
1013
mymemrchr(void *va, int c, long n)
1014
{
1015
	uchar *a, *e;
1016
 
1017
	a = va;
1018
	for(e=a+n-1; e>a; e--)
1019
		if(*e == c)
1020
			return e;
1021
	return nil;
1022
}
1023
 
1024
/*
1025
 * Turn a name into a channel.
1026
 * &name[0] is known to be a valid address.  It may be a kernel address.
1027
 *
1028
 * Opening with amode Aopen, Acreate, or Aremove guarantees
1029
 * that the result will be the only reference to that particular fid.
1030
 * This is necessary since we might pass the result to
1031
 * devtab[]->remove().
1032
 *
1033
 * Opening Atodir, Amount, or Aaccess does not guarantee this.
1034
 *
1035
 * Opening Aaccess can, under certain conditions, return a
1036
 * correct Chan* but with an incorrect Cname attached.
1037
 * Since the functions that open Aaccess (sysstat, syswstat, sys_stat)
1038
 * do not use the Cname*, this avoids an unnecessary clone.
1039
 */
1040
Chan*
1041
namec(char *aname, int amode, int omode, ulong perm)
1042
{
1043
	int n, prefix, len, t, nomount, npath;
1044
	Chan *c, *cnew;
1045
	Cname *cname;
1046
	Elemlist e;
1047
	Rune r;
1048
	Mhead *m;
1049
	char *createerr, tmperrbuf[ERRMAX];
1050
	char *name;
1051
 
1052
	name = aname;
1053
	if(name[0] == '\0')
1054
		error("empty file name");
1055
	validname(name, 1);
1056
 
1057
	/*
1058
	 * Find the starting off point (the current slash, the root of
1059
	 * a device tree, or the current dot) as well as the name to
1060
	 * evaluate starting there.
1061
	 */
1062
	nomount = 0;
1063
	switch(name[0]){
1064
	case '/':
1065
		c = up->slash;
1066
		incref(&c->ref);
1067
		break;
1068
 
1069
	case '#':
1070
		nomount = 1;
1071
		up->genbuf[0] = '\0';
1072
		n = 0;
1073
		while(*name!='\0' && (*name != '/' || n < 2)){
1074
			if(n >= sizeof(up->genbuf)-1)
1075
				error(Efilename);
1076
			up->genbuf[n++] = *name++;
1077
		}
1078
		up->genbuf[n] = '\0';
1079
		/*
1080
		 *  noattach is sandboxing.
1081
		 *
1082
		 *  the OK exceptions are:
1083
		 *	|  it only gives access to pipes you create
1084
		 *	d  this process's file descriptors
1085
		 *	e  this process's environment
1086
		 *  the iffy exceptions are:
1087
		 *	c  time and pid, but also cons and consctl
1088
		 *	p  control of your own processes (and unfortunately
1089
		 *	   any others left unprotected)
1090
		 */
1091
		n = chartorune(&r, up->genbuf+1)+1;
1092
		/* actually / is caught by parsing earlier */
1093
		if(utfrune("M", r))
1094
			error(Enoattach);
1095
		if(up->pgrp->noattach && utfrune("|decp", r)==nil)
1096
			error(Enoattach);
1097
		t = devno(r, 1);
1098
		if(t == -1)
1099
			error(Ebadsharp);
1100
		c = devtab[t]->attach(up->genbuf+n);
1101
		break;
1102
 
1103
	default:
1104
		c = up->dot;
1105
		incref(&c->ref);
1106
		break;
1107
	}
1108
	prefix = name - aname;
1109
 
1110
	e.name = nil;
1111
	e.elems = nil;
1112
	e.off = nil;
1113
	e.nelems = 0;
1114
	if(waserror()){
1115
		cclose(c);
1116
		free(e.name);
1117
		free(e.elems);
1118
		free(e.off);
1119
//dumpmount();
1120
		nexterror();
1121
	}
1122
 
1123
	/*
1124
	 * Build a list of elements in the path.
1125
	 */
1126
	parsename(name, &e);
1127
 
1128
	/*
1129
	 * On create, ....
1130
	 */
1131
	if(amode == Acreate){
1132
		/* perm must have DMDIR if last element is / or /. */
1133
		if(e.mustbedir && !(perm&DMDIR)){
1134
			npath = e.nelems;
1135
			strcpy(tmperrbuf, "create without DMDIR");
1136
			goto NameError;
1137
		}
1138
 
1139
		/* don't try to walk the last path element just yet. */
1140
		if(e.nelems == 0)
1141
			error(Eexist);
1142
		e.nelems--;
1143
	}
1144
 
1145
	if(walk(&c, e.elems, e.nelems, nomount, &npath) < 0){
1146
		if(npath < 0 || npath > e.nelems){
1147
			print("namec %s walk error npath=%d\n", aname, npath);
1148
			nexterror();
1149
		}
1150
		strcpy(tmperrbuf, up->errstr);
1151
	NameError:
1152
		len = prefix+e.off[npath];
1153
		if(len < ERRMAX/3 || (name=mymemrchr(aname, '/', len))==nil || name==aname)
1154
			snprint(up->genbuf, sizeof up->genbuf, "%.*s", len, aname);
1155
		else
1156
			snprint(up->genbuf, sizeof up->genbuf, "...%.*s", (int)(len-(name-aname)), name);
1157
		snprint(up->errstr, ERRMAX, "%#q %s", up->genbuf, tmperrbuf);
1158
		nexterror();
1159
	}
1160
 
1161
	if(e.mustbedir && !(c->qid.type&QTDIR)){
1162
		npath = e.nelems;
1163
		strcpy(tmperrbuf, "not a directory");
1164
		goto NameError;
1165
	}
1166
 
1167
	if(amode == Aopen && (omode&3) == OEXEC && (c->qid.type&QTDIR)){
1168
		npath = e.nelems;
1169
		error("cannot exec directory");
1170
	}
1171
 
1172
	switch(amode){
1173
	case Aaccess:
1174
		if(!nomount)
1175
			domount(&c, nil);
1176
		break;
1177
 
1178
	case Abind:
1179
		m = nil;
1180
		if(!nomount)
1181
			domount(&c, &m);
1182
		if(c->umh != nil)
1183
			putmhead(c->umh);
1184
		c->umh = m;
1185
		break;
1186
 
1187
	case Aremove:
1188
	case Aopen:
1189
	Open:
1190
		/* save the name; domount might change c */
1191
		cname = c->name;
1192
		incref(&cname->ref);
1193
		m = nil;
1194
		if(!nomount)
1195
			domount(&c, &m);
1196
 
1197
		/* our own copy to open or remove */
1198
		c = cunique(c);
1199
 
1200
		/* now it's our copy anyway, we can put the name back */
1201
		cnameclose(c->name);
1202
		c->name = cname;
1203
 
1204
		switch(amode){
1205
		case Aremove:
1206
			putmhead(m);
1207
			break;
1208
 
1209
		case Aopen:
1210
		case Acreate:
1211
if(c->umh != nil){
1212
	print("cunique umh Open\n");
1213
	putmhead(c->umh);
1214
	c->umh = nil;
1215
}
1216
 
1217
			/* only save the mount head if it's a multiple element union */
1218
			if(m && m->mount && m->mount->next)
1219
				c->umh = m;
1220
			else
1221
				putmhead(m);
1222
 
1223
			/* save registers else error() in open has wrong value of c saved */
1224
			saveregisters();
1225
 
1226
			if(omode == OEXEC)
1227
				c->flag &= ~CCACHE;
1228
 
1229
			c = devtab[c->type]->open(c, omode&~OCEXEC);
1230
 
1231
			if(omode & OCEXEC)
1232
				c->flag |= CCEXEC;
1233
			if(omode & ORCLOSE)
1234
				c->flag |= CRCLOSE;
1235
			break;
1236
		}
1237
		break;
1238
 
1239
	case Atodir:
1240
		/*
1241
		 * Directories (e.g. for cd) are left before the mount point,
1242
		 * so one may mount on / or . and see the effect.
1243
		 */
1244
		if(!(c->qid.type & QTDIR))
1245
			error(Enotdir);
1246
		break;
1247
 
1248
	case Amount:
1249
		/*
1250
		 * When mounting on an already mounted upon directory,
1251
		 * one wants subsequent mounts to be attached to the
1252
		 * original directory, not the replacement.  Don't domount.
1253
		 */
1254
		break;
1255
 
1256
	case Acreate:
1257
		/*
1258
		 * We've already walked all but the last element.
1259
		 * If the last exists, try to open it OTRUNC.
1260
		 * If omode&OEXCL is set, just give up.
1261
		 */
1262
		e.nelems++;
1263
		if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) == 0){
1264
			if(omode&OEXCL)
1265
				error(Eexist);
1266
			omode |= OTRUNC;
1267
			goto Open;
1268
		}
1269
 
1270
		/*
1271
		 * The semantics of the create(2) system call are that if the
1272
		 * file exists and can be written, it is to be opened with truncation.
1273
		 * On the other hand, the create(5) message fails if the file exists.
1274
		 * If we get two create(2) calls happening simultaneously, 
1275
		 * they might both get here and send create(5) messages, but only 
1276
		 * one of the messages will succeed.  To provide the expected create(2)
1277
		 * semantics, the call with the failed message needs to try the above
1278
		 * walk again, opening for truncation.  This correctly solves the 
1279
		 * create/create race, in the sense that any observable outcome can
1280
		 * be explained as one happening before the other.
1281
		 * The create/create race is quite common.  For example, it happens
1282
		 * when two rc subshells simultaneously update the same
1283
		 * environment variable.
1284
		 *
1285
		 * The implementation still admits a create/create/remove race:
1286
		 * (A) walk to file, fails
1287
		 * (B) walk to file, fails
1288
		 * (A) create file, succeeds, returns 
1289
		 * (B) create file, fails
1290
		 * (A) remove file, succeeds, returns
1291
		 * (B) walk to file, return failure.
1292
		 *
1293
		 * This is hardly as common as the create/create race, and is really
1294
		 * not too much worse than what might happen if (B) got a hold of a
1295
		 * file descriptor and then the file was removed -- either way (B) can't do
1296
		 * anything with the result of the create call.  So we don't care about this race.
1297
		 *
1298
		 * Applications that care about more fine-grained decision of the races
1299
		 * can use the OEXCL flag to get at the underlying create(5) semantics;
1300
		 * by default we provide the common case.
1301
		 *
1302
		 * We need to stay behind the mount point in case we
1303
		 * need to do the first walk again (should the create fail).
1304
		 *
1305
		 * We also need to cross the mount point and find the directory
1306
		 * in the union in which we should be creating.
1307
		 *
1308
		 * The channel staying behind is c, the one moving forward is cnew.
1309
		 */
1310
		m = nil;
1311
		cnew = nil;	/* is this assignment necessary? */
1312
		if(!waserror()){	/* try create */
1313
			if(!nomount && findmount(&cnew, &m, c->type, c->dev, c->qid))
1314
				cnew = createdir(cnew, m);
1315
			else{
1316
				cnew = c;
1317
				incref(&cnew->ref);
1318
			}
1319
 
1320
			/*
1321
			 * We need our own copy of the Chan because we're
1322
			 * about to send a create, which will move it.  Once we have
1323
			 * our own copy, we can fix the name, which might be wrong
1324
			 * if findmount gave us a new Chan.
1325
			 */
1326
			cnew = cunique(cnew);
1327
			cnameclose(cnew->name);
1328
			cnew->name = c->name;
1329
			incref(&cnew->name->ref);
1330
 
1331
			devtab[cnew->type]->create(cnew, e.elems[e.nelems-1], omode&~(OEXCL|OCEXEC), perm);
1332
			poperror();
1333
			if(omode & OCEXEC)
1334
				cnew->flag |= CCEXEC;
1335
			if(omode & ORCLOSE)
1336
				cnew->flag |= CRCLOSE;
1337
			if(m)
1338
				putmhead(m);
1339
			cclose(c);
1340
			c = cnew;
1341
			c->name = addelem(c->name, e.elems[e.nelems-1]);
1342
			break;
1343
		}else{		/* create failed */
1344
			cclose(cnew);
1345
			if(m)
1346
				putmhead(m);
1347
			if(omode & OEXCL)
1348
				nexterror();
1349
			/* save error */
1350
			createerr = up->errstr;
1351
			up->errstr = tmperrbuf;
1352
			/* note: we depend that walk does not error */
1353
			if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
1354
				up->errstr = createerr;
1355
				error(createerr);	/* report true error */
1356
			}
1357
			up->errstr = createerr;
1358
			omode |= OTRUNC;
1359
			goto Open;
1360
		}
1361
		panic("namec: not reached");				
1362
 
1363
	default:
1364
		panic("unknown namec access %d\n", amode);
1365
	}
1366
 
1367
	poperror();
1368
 
1369
	/* place final element in genbuf for e.g. exec */
1370
	if(e.nelems > 0)
1371
		kstrcpy(up->genbuf, e.elems[e.nelems-1], sizeof up->genbuf);
1372
	else
1373
		kstrcpy(up->genbuf, ".", sizeof up->genbuf);
1374
	free(e.name);
1375
	free(e.elems);
1376
	free(e.off);
1377
 
1378
	return c;
1379
}
1380
 
1381
/*
1382
 * name is valid. skip leading / and ./ as much as possible
1383
 */
1384
char*
1385
skipslash(char *name)
1386
{
1387
	while(name[0]=='/' || (name[0]=='.' && (name[1]==0 || name[1]=='/')))
1388
		name++;
1389
	return name;
1390
}
1391
 
1392
char isfrog[256]={
1393
	/*NUL*/	1, 1, 1, 1, 1, 1, 1, 1,	/* 0 */
1394
	/*BKS*/	1, 1, 1, 1, 1, 1, 1, 1, /* 0x08 */
1395
	/*DLE*/	1, 1, 1, 1, 1, 1, 1, 1, /* 0x10 */
1396
	/*CAN*/	1, 1, 1, 1, 1, 1, 1, 1, /* 0x18 */
1397
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
1398
		0, 0, 0, 0, 0, 0, 0, 1, /* 0x28 (1 is '/', 0x2F) */
1399
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */
1400
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x38 */
1401
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
1402
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x48 */
1403
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
1404
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x58 */
1405
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */
1406
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x68 */
1407
		0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
1408
		0, 0, 0, 0, 0, 0, 0, 1, /* 0x78 (1 is DEL, 0x7F) */
1409
};
1410
 
1411
/*
1412
 * Check that the name
1413
 *  a) is in valid memory.
1414
 *  b) is shorter than 2^16 bytes, so it can fit in a 9P string field.
1415
 *  c) contains no frogs.
1416
 * The first byte is known to be addressible by the requester, so the
1417
 * routine works for kernel and user memory both.
1418
 * The parameter slashok flags whether a slash character is an error
1419
 * or a valid character.
1420
 */
1421
void
1422
validname(char *aname, int slashok)
1423
{
1424
	char *ename, *name;
1425
	int c;
1426
	Rune r;
1427
 
1428
	name = aname;
1429
/*
1430
	if(((ulong)name & KZERO) != KZERO) {
1431
		p = name;
1432
		t = BY2PG-((ulong)p&(BY2PG-1));
1433
		while((ename=vmemchr(p, 0, t)) == nil) {
1434
			p += t;
1435
			t = BY2PG;
1436
		}
1437
	}else
1438
*/
1439
		ename = memchr(name, 0, (1<<16));
1440
 
1441
	if(ename==nil || ename-name>=(1<<16))
1442
		error("name too long");
1443
 
1444
	while(*name){
1445
		/* all characters above '~' are ok */
1446
		c = *(uchar*)name;
1447
		if(c >= Runeself)
1448
			name += chartorune(&r, name);
1449
		else{
1450
			if(isfrog[c])
1451
				if(!slashok || c!='/'){
1452
					snprint(up->genbuf, sizeof(up->genbuf), "%s: %q", Ebadchar, aname);
1453
					error(up->genbuf);
1454
			}
1455
			name++;
1456
		}
1457
	}
1458
}
1459
 
1460
void
1461
isdir(Chan *c)
1462
{
1463
	if(c->qid.type & QTDIR)
1464
		return;
1465
	error(Enotdir);
1466
}
1467
 
1468
/*
1469
 * This is necessary because there are many
1470
 * pointers to the top of a given mount list:
1471
 *
1472
 *	- the mhead in the namespace hash table
1473
 *	- the mhead in chans returned from findmount:
1474
 *	  used in namec and then by unionread.
1475
 *	- the mhead in chans returned from createdir:
1476
 *	  used in the open/create race protect, which is gone.
1477
 *
1478
 * The RWlock in the Mhead protects the mount list it contains.
1479
 * The mount list is deleted when we cunmount.
1480
 * The RWlock ensures that nothing is using the mount list at that time.
1481
 *
1482
 * It is okay to replace c->mh with whatever you want as 
1483
 * long as you are sure you have a unique reference to it.
1484
 *
1485
 * This comment might belong somewhere else.
1486
 */
1487
void
1488
putmhead(Mhead *m)
1489
{
1490
	if(m && decref(&m->ref) == 0){
1491
		m->mount = (Mount*)0xCafeBeef;
1492
		free(m);
1493
	}
1494
}