plan 9 kernel history: overview | file list | diff list

2000/0326/port/chan.c (diff list | history)

1990/0227/sys/src/9/port/chan.c:78,831990/0303/sys/src/9/port/chan.c:78,85 (short | long)
1990/0227    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
1990/0303    
		c->mchan = 0; 
		c->mqid = 0; 
1990/0227    
		return c; 
	} 
	unlock(&chanalloc); 
1990/0303/sys/src/9/port/chan.c:149,1551990/0321/sys/src/9/port/chan.c:149,155 (short | long)
1990/0227    
	Mtab *mt, *mz; 
	Mount *mnt, *omnt, *nmnt, *pmnt; 
	Pgrp *pg; 
	int isnew; 
1990/0321    
	int islast; 
1990/0227    
 
	if(CHDIR & (old->qid^new->qid)) 
		error(0, Emount); 
1990/0303/sys/src/9/port/chan.c:157,1661990/0321/sys/src/9/port/chan.c:157,171
1990/0227    
		error(0, Emount); 
 
	mz = 0; 
	isnew = 0; 
1990/0321    
	islast = 0; 
	mnt = 0; 
1990/0227    
	pg = u->p->pgrp; 
	lock(pg); 
	if(waserror()){ 
1990/0321    
		if(mnt){ 
			mnt->c = 0;	/* caller will close new */ 
			closemount(mnt); 
		} 
1990/0227    
		unlock(pg); 
		nexterror(); 
	} 
1990/0303/sys/src/9/port/chan.c:171,1881990/0321/sys/src/9/port/chan.c:176,193
1990/0227    
	for(i=0; i<pg->nmtab; i++,mt++){ 
		if(mt->c==0 && mz==0) 
			mz = mt; 
		else if(eqchan(mt->c, old, CHDIR|QPATH)) 
1990/0321    
		else if(eqchan(mt->c, old, CHDIR|QPATH)){ 
			mz = 0; 
1990/0227    
			goto Found; 
1990/0321    
		} 
1990/0227    
	} 
	isnew = 1; 
	if(mz == 0){ 
		if(i == conf.nmtab) 
			error(0, Enomount); 
		mz = &pg->mtab[i]; 
		pg->nmtab++; 
1990/0321    
		islast++; 
1990/0227    
	} 
	mz->mnt = 0; 
	mz->c = old; 
	mt = mz; 
 
    Found: 
1990/0303/sys/src/9/port/chan.c:244,2511990/0321/sys/src/9/port/chan.c:249,260
1990/0227    
	} 
 
	incref(new); 
	if(isnew) 
1990/0321    
	if(mz){ 
		mz->c = old; 
1990/0227    
		incref(old); 
1990/0321    
	} 
	if(islast) 
		pg->nmtab++; 
1990/0227    
	unlock(pg); 
	poperror(); 
	return mnt->mountid; 
1990/0303/sys/src/9/port/chan.c:286,2921990/0321/sys/src/9/port/chan.c:295,301
1990/0227    
    Found: 
	lock(pg); 
	if(!eqchan(mt->c, c, CHDIR|QPATH)){	/* table changed underfoot */ 
		print("domount: changed underfoot?\n"); 
1990/0321    
		pprint("domount: changed underfoot?\n"); 
1990/0227    
		unlock(pg); 
		return c; 
	} 
1990/0303/sys/src/9/port/chan.c:333,3391990/0321/sys/src/9/port/chan.c:342,348
1990/0227    
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
			print("walk: changed underfoot?\n"); 
1990/0321    
			pprint("walk: changed underfoot?\n"); 
1990/0227    
			unlock(pg); 
			goto Notfound; 
		} 
1990/0303/sys/src/9/port/chan.c:353,3581990/0321/sys/src/9/port/chan.c:362,368
1990/0227    
		if(!first) 
			close(c); 
		nc->mnt = mnt; 
1990/0321    
		nc->mountid = mnt->mountid; 
1990/0227    
		c = nc; 
		first = 0; 
		goto Again; 
1990/0303/sys/src/9/port/chan.c:391,3971990/0321/sys/src/9/port/chan.c:401,407
1990/0227    
	} 
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
		print("createdir: changed underfoot?\n"); 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/0227    
		error(0, Enocreate); 
	} 
	do{ 
1990/0321/sys/src/9/port/chan.c:490,4971990/0513/sys/src/9/port/chan.c:490,499 (short | long)
1990/0227    
 
	switch(amode){ 
	case Aaccess: 
		if((nc=walk(c, elem, mntok)) == 0) 
1990/0513    
		if((nc=walk(c, elem, mntok)) == 0){ 
			print("%d pc %lux\n", u->nerrlab, u->errlab[u->nerrlab-1].pc); 
1990/0227    
			error(0, Enonexist); 
1990/0513    
		} 
1990/0227    
		c = nc; 
		break; 
 
1990/0513/sys/src/9/port/chan.c:490,4991990/0515/sys/src/9/port/chan.c:490,497 (short | long)
1990/0227    
 
	switch(amode){ 
	case Aaccess: 
1990/0513    
		if((nc=walk(c, elem, mntok)) == 0){ 
			print("%d pc %lux\n", u->nerrlab, u->errlab[u->nerrlab-1].pc); 
1990/0515    
		if((nc=walk(c, elem, mntok)) == 0) 
1990/0227    
			error(0, Enonexist); 
1990/0513    
		} 
1990/0227    
		c = nc; 
		break; 
 
1990/0515/sys/src/9/port/chan.c:134,1401990/0603/sys/src/9/port/chan.c:134,140 (short | long)
1990/0227    
	nmnt->mountid = omnt->mountid; 
	nmnt->next = omnt->next; 
	if(nmnt->next) 
		incref(nmnt); 
1990/0603    
		incref(nmnt->next); 
1990/0227    
	nmnt->c = omnt->c; 
	incref(nmnt->c); 
	omnt->ref--; 
1990/0515/sys/src/9/port/chan.c:207,2201990/0603/sys/src/9/port/chan.c:207,218
1990/0227    
		/* fall through */ 
 
	case MREPL: 
		omnt = mt->mnt; 
		if(omnt) 
			incref(omnt); 
		mnt->next = omnt; 
1990/0603    
		mnt->next = mt->mnt; 
1990/0227    
		mt->mnt = mnt; 
		mnt->term = 1; 
		if((flag&MORDER) == MBEFORE) 
			mnt->term = 0; 
1990/0603    
		else 
			mnt->term = 1; 
1990/0227    
		break; 
 
	/* 
1990/0603/sys/src/9/port/chan.c:127,1331990/0617/sys/src/9/port/chan.c:127,132 (short | long)
1990/0227    
{ 
	Mount *nmnt; 
 
	print("mount copy on write\n"); 
	nmnt = newmount(); 
	lock(nmnt); 
	nmnt->term = omnt->term; 
1990/0617/sys/src/9/port/chan.c:72,771990/0707/sys/src/9/port/chan.c:72,78 (short | long)
1990/0227    
	lock(&chanalloc); 
	if(c = chanalloc.free){		/* assign = */ 
		chanalloc.free = c->next; 
1990/0707    
		c->type = 0;	/* if closed before changed, this calls rooterror, a nop */ 
1990/0227    
		c->flag = 0; 
		c->ref = 1; 
		unlock(&chanalloc); 
1990/0707/sys/src/9/port/chan.c:447,4531990/08141/sys/src/9/port/chan.c:447,453 (short | long)
1990/0227    
		mntok = 0; 
		if(!((ulong)name & KZERO)) 
			validaddr((ulong)(name+1), 2, 0); 
		if(name[1]=='|' || ('A'<=name[1] && name[1]<='Z')) 
1990/08141    
		if(name[1]=='|' || name[1]=='M') 
1990/0227    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
		if(t == -1) 
1990/0707/sys/src/9/port/chan.c:511,5161990/08141/sys/src/9/port/chan.c:511,518
1990/0227    
		c = nc; 
	Open: 
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	case Amount: 
1990/0707/sys/src/9/port/chan.c:533,5381990/08141/sys/src/9/port/chan.c:535,542
1990/0227    
		if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) 
			c = createdir(c); 
		(*devtab[c->type].create)(c, elem, omode, perm); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	default: 
1990/08141/sys/src/9/port/chan.c:340,3461990/0820/sys/src/9/port/chan.c:340,346 (short | long)
1990/0227    
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
1990/0321    
			pprint("walk: changed underfoot?\n"); 
1990/0820    
			pprint("walk: changed underfoot? '%s'\n", name); 
1990/0227    
			unlock(pg); 
			goto Notfound; 
		} 
1990/08141/sys/src/9/port/chan.c:431,4421990/0820/sys/src/9/port/chan.c:431,443
1990/0227    
{ 
	Chan *c, *nc; 
	int t; 
	int mntok; 
1990/0820    
	int mntok, isdot; 
1990/0227    
	char *elem = u->elem; 
 
	if(name[0] == 0) 
		error(0, Enonexist); 
	mntok = 1; 
1990/0820    
	isdot = 0; 
1990/0227    
	if(name[0] == '/'){ 
		c = clone(u->slash, 0); 
		/* 
1990/08141/sys/src/9/port/chan.c:459,4661990/0820/sys/src/9/port/chan.c:460,471
1990/0227    
		}else 
			name = nextelem(name, elem); 
		c = (*devtab[t].attach)(elem); 
	}else 
1990/0820    
	}else{ 
1990/0227    
		c = clone(u->dot, 0); 
1990/0820    
		name = skipslash(name);	/* eat leading ./ */ 
		if(*name == 0) 
			isdot = 1; 
	} 
1990/0227    
 
	if(waserror()){ 
		close(c); 
1990/08141/sys/src/9/port/chan.c:468,4751990/0820/sys/src/9/port/chan.c:473,481
1990/0227    
	} 
 
	name = nextelem(name, elem); 
	if(mntok) 
	if(!(amode==Amount && elem[0]==0))	/* don't domount on dot or slash */ 
1990/0820    
 
	if(mntok && !isdot) 
	if(!(amode==Amount && elem[0]==0))	/* don't domount on slash */ 
1990/0227    
		c = domount(c);			/* see case Atodir below */ 
 
	/* 
1990/08141/sys/src/9/port/chan.c:482,4871990/0820/sys/src/9/port/chan.c:488,494
1990/0227    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/0820    
 
1990/0227    
	/* 
	 * Last element; act according to type of access. 
	 */ 
1990/08141/sys/src/9/port/chan.c:488,4961990/0820/sys/src/9/port/chan.c:495,507
1990/0227    
 
	switch(amode){ 
	case Aaccess: 
1990/0515    
		if((nc=walk(c, elem, mntok)) == 0) 
1990/0227    
			error(0, Enonexist); 
		c = nc; 
1990/0820    
		if(isdot) 
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
				error(0, Enonexist); 
			c = nc; 
		} 
1990/0227    
		break; 
 
	case Atodir: 
1990/08141/sys/src/9/port/chan.c:506,5141990/0820/sys/src/9/port/chan.c:517,529
1990/0227    
		break; 
 
	case Aopen: 
		if((nc=walk(c, elem, mntok)) == 0) 
			error(0, Enonexist); 
		c = nc; 
1990/0820    
		if(isdot) 
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
				error(0, Enonexist); 
			c = nc; 
		} 
1990/0227    
	Open: 
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
1990/08141/sys/src/9/port/chan.c:527,5321990/0820/sys/src/9/port/chan.c:542,549
1990/0227    
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
			error(0, Eisdir); 
1990/0227    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
			omode |= OTRUNC; 
1990/08141/sys/src/9/port/chan.c:552,5611990/0820/sys/src/9/port/chan.c:569,587
1990/0227    
char* 
skipslash(char *name) 
{ 
1990/0820    
    Again: 
1990/0227    
	while(*name == '/'){ 
		if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) 
			validaddr((ulong)name+1, 1, 0); 
		name++; 
1990/0820    
	} 
	if(*name == '.'){ 
		if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) 
			validaddr((ulong)name+1, 1, 0); 
		if(name[1]==0 || name[1]=='/'){ 
			name++; 
			goto Again; 
		} 
1990/0227    
	} 
	return name; 
} 
1990/0820/sys/src/9/port/chan.c:432,4411990/0821/sys/src/9/port/chan.c:432,457 (short | long)
1990/0227    
	Chan *c, *nc; 
	int t; 
1990/0820    
	int mntok, isdot; 
1990/0227    
	char *elem = u->elem; 
1990/0821    
	char *p; 
	char *elem; 
1990/0227    
 
	if(name[0] == 0) 
		error(0, Enonexist); 
1990/0821    
 
	/* 
	 * Make sure all of name is o.k.  first byte is validated 
	 * externally so if it's a kernel address we know it's o.k. 
	 */ 
	if(!((ulong)name & KZERO)){ 
		p = name; 
		t = BY2PG-((ulong)p&(BY2PG-1)); 
		while(vmemchr(p, 0, t) == 0){ 
			p += t; 
			t = BY2PG; 
		} 
	} 
 
	elem = u->elem; 
1990/0227    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1990/0227    
	if(name[0] == '/'){ 
1990/0820/sys/src/9/port/chan.c:446,4531990/0821/sys/src/9/port/chan.c:462,467
1990/0227    
		name = skipslash(name); 
	}else if(name[0] == '#'){ 
		mntok = 0; 
		if(!((ulong)name & KZERO)) 
			validaddr((ulong)(name+1), 2, 0); 
1990/08141    
		if(name[1]=='|' || name[1]=='M') 
1990/0227    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
1990/0820/sys/src/9/port/chan.c:570,5881990/0821/sys/src/9/port/chan.c:584,595
1990/0227    
skipslash(char *name) 
{ 
1990/0820    
    Again: 
1990/0227    
	while(*name == '/'){ 
		if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) 
			validaddr((ulong)name+1, 1, 0); 
1990/0821    
	while(*name == '/') 
1990/0227    
		name++; 
1990/0821    
	if(*name=='.' && (name[1]==0 || name[1]=='/')){ 
		name++; 
		goto Again; 
1990/0820    
	} 
	if(*name == '.'){ 
		if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) 
			validaddr((ulong)name+1, 1, 0); 
		if(name[1]==0 || name[1]=='/'){ 
			name++; 
			goto Again; 
		} 
1990/0227    
	} 
	return name; 
} 
 
1990/0820/sys/src/9/port/chan.c:600,6061990/0821/sys/src/9/port/chan.c:607,612
1990/0227    
 * name[0] should not be a slash. 
 * Advance name to next element in path, copying current element into elem. 
 * Return pointer to next element, skipping slashes. 
 * &name[0] is known to be a valid address. 
 */ 
char* 
nextelem(char *name, char *elem) 
1990/0820/sys/src/9/port/chan.c:610,6181990/0821/sys/src/9/port/chan.c:616,624
1990/0227    
 
	if(*name == '/') 
		error(0, Efilename); 
	end = vmemchr(name, 0, NAMELEN); 
1990/0821    
	end = memchr(name, 0, NAMELEN); 
1990/0227    
	if(end == 0){ 
		end = vmemchr(name, '/', NAMELEN); 
1990/0821    
		end = memchr(name, '/', NAMELEN); 
1990/0227    
		if(end == 0) 
			error(0, Efilename); 
	}else{ 
1990/0821/sys/src/9/port/chan.c:96,1061990/0907/sys/src/9/port/chan.c:96,109 (short | long)
1990/0227    
void 
close(Chan *c) 
{ 
1990/0907    
	if(c->flag & CFREE) 
		panic("close"); 
1990/0227    
	if(decref(c) == 0){ 
		if(!waserror()){ 
			(*devtab[c->type].close)(c); 
			poperror(); 
		} 
1990/0907    
		c->flag = CFREE; 
1990/0227    
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
1990/0907/sys/src/9/port/chan.c:372,3821990/0914/sys/src/9/port/chan.c:372,392 (short | long)
1990/0227    
	if(name[0])			/* walk succeeded */ 
		c->flag &= ~CMOUNT; 
 
1990/0914    
	if(domnt){ 
		if(waserror()){ 
			print("domount error\n"); 
			if(!first) 
				close(c); 
			return 0; 
		} 
		c = domount(c); 
		poperror(); 
	} 
 
1990/0227    
	if(!first) 
		close(ac); 
 
	if(domnt) 
		return domount(c); 
1990/0914    
 
1990/0227    
	return c; 
 
    Notfound: 
1990/0907/sys/src/9/port/chan.c:425,4301990/0914/sys/src/9/port/chan.c:435,445
1990/0227    
	return nc; 
} 
 
1990/0914    
void 
saveregisters(void) 
{ 
} 
 
1990/0227    
/* 
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
1990/0907/sys/src/9/port/chan.c:542,5471990/0914/sys/src/9/port/chan.c:557,563
1990/0820    
			c = nc; 
		} 
1990/0227    
	Open: 
1990/0914    
		saveregisters();	/* else error() in open has wrong value of c saved */ 
1990/0227    
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/0914/sys/src/9/port/chan.c:374,3801990/09141/sys/src/9/port/chan.c:374,379 (short | long)
1990/0227    
 
1990/0914    
	if(domnt){ 
		if(waserror()){ 
			print("domount error\n"); 
			if(!first) 
				close(c); 
			return 0; 
1990/09141/sys/src/9/port/chan.c:479,4851990/1009/sys/src/9/port/chan.c:479,485 (short | long)
1990/0227    
		name = skipslash(name); 
	}else if(name[0] == '#'){ 
		mntok = 0; 
1990/08141    
		if(name[1]=='|' || name[1]=='M') 
1990/1009    
		if(name[1]=='M') 
1990/0227    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
		if(t == -1) 
1990/1009/sys/src/9/port/chan.c:14,321990/1104/sys/src/9/port/chan.c:14,36 (short | long)
1990/0227    
int 
incref(Ref *r) 
{ 
1990/1104    
	int x; 
 
1990/0227    
	lock(r); 
	r->ref++; 
1990/1104    
	x = ++r->ref; 
1990/0227    
	unlock(r); 
	return r->ref; 
1990/1104    
	return x; 
1990/0227    
} 
 
int 
decref(Ref *r) 
{ 
1990/1104    
	int x; 
 
1990/0227    
	lock(r); 
	r->ref--; 
1990/1104    
	x = --r->ref; 
1990/0227    
	unlock(r); 
	return r->ref; 
1990/1104    
	return x; 
1990/0227    
} 
 
void 
1990/1104/sys/src/9/port/chan.c:80,901990/11211/sys/src/9/port/chan.c:80,91 (short | long)
1990/0227    
		c->flag = 0; 
		c->ref = 1; 
		unlock(&chanalloc); 
1990/11211    
		c->dev = 0; 
1990/0227    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
1990/0303    
		c->mchan = 0; 
		c->mqid = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/0227    
		return c; 
	} 
	unlock(&chanalloc); 
1990/1104/sys/src/9/port/chan.c:116,1251990/11211/sys/src/9/port/chan.c:117,134
1990/0227    
} 
 
int 
eqchan(Chan *a, Chan *b, long qmask) 
1990/11211    
eqqid(Qid a, Qid b) 
1990/0227    
{ 
	if((a->qid^b->qid) & qmask) 
1990/11211    
	return a.path==b.path && a.vers==b.vers; 
} 
 
int 
eqchan(Chan *a, Chan *b, int pathonly) 
{ 
	if(a->qid.path != b->qid.path) 
1990/0227    
		return 0; 
1990/11211    
	if(!pathonly && a->qid.vers!=b->qid.vers) 
		return 0; 
1990/0227    
	if(a->type != b->type) 
		return 0; 
	if(a->dev != b->dev) 
1990/1104/sys/src/9/port/chan.c:158,1671990/11211/sys/src/9/port/chan.c:167,176
1990/0227    
	Pgrp *pg; 
1990/0321    
	int islast; 
1990/0227    
 
	if(CHDIR & (old->qid^new->qid)) 
		error(0, Emount); 
	if((old->qid&CHDIR)==0 && (flag&MORDER)!=MREPL) 
		error(0, Emount); 
1990/11211    
	if(CHDIR & (old->qid.path^new->qid.path)) 
		error(Emount); 
	if((old->qid.path&CHDIR)==0 && (flag&MORDER)!=MREPL) 
		error(Emount); 
1990/0227    
 
	mz = 0; 
1990/0321    
	islast = 0; 
1990/1104/sys/src/9/port/chan.c:190,1961990/11211/sys/src/9/port/chan.c:199,205
1990/0227    
	} 
	if(mz == 0){ 
		if(i == conf.nmtab) 
			error(0, Enomount); 
1990/11211    
			error(Enomount); 
1990/0227    
		mz = &pg->mtab[i]; 
1990/0321    
		islast++; 
1990/0227    
	} 
1990/1104/sys/src/9/port/chan.c:210,2161990/11211/sys/src/9/port/chan.c:219,225
1990/0227    
	 */ 
	case MBEFORE: 
		if(mt->mnt == 0) 
			error(0, Enotunion); 
1990/11211    
			error(Enotunion); 
1990/0227    
		/* fall through */ 
 
	case MREPL: 
1990/1104/sys/src/9/port/chan.c:227,2331990/11211/sys/src/9/port/chan.c:236,242
1990/0227    
	 */ 
	case MAFTER: 
		if(mt->mnt == 0) 
			error(0, Enotunion); 
1990/11211    
			error(Enotunion); 
1990/0227    
		omnt = mt->mnt; 
		pmnt = 0; 
		while(!omnt->term){ 
1990/1104/sys/src/9/port/chan.c:416,4261990/11211/sys/src/9/port/chan.c:425,435
1990/0227    
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/0227    
		error(0, Enocreate); 
1990/11211    
		error(Enocreate); 
1990/0227    
	} 
	do{ 
		if(mnt->term) 
			error(0, Enocreate); 
1990/11211    
			error(Enocreate); 
1990/0227    
		mnt = mnt->next; 
	}while(!(mnt->c->flag&CCREATE)); 
	mc = mnt->c; 
1990/1104/sys/src/9/port/chan.c:457,4631990/11211/sys/src/9/port/chan.c:466,472
1990/0821    
	char *elem; 
1990/0227    
 
	if(name[0] == 0) 
		error(0, Enonexist); 
1990/11211    
		error(Enonexist); 
1990/0821    
 
	/* 
	 * Make sure all of name is o.k.  first byte is validated 
1990/1104/sys/src/9/port/chan.c:484,4931990/11211/sys/src/9/port/chan.c:493,502
1990/0227    
	}else if(name[0] == '#'){ 
		mntok = 0; 
1990/1009    
		if(name[1]=='M') 
1990/0227    
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/0227    
		t = devno(name[1], 1); 
		if(t == -1) 
			error(0, Ebadsharp); 
1990/11211    
			error(Ebadsharp); 
1990/0227    
		name += 2; 
		if(*name == '/'){ 
			name = skipslash(name); 
1990/1104/sys/src/9/port/chan.c:519,5251990/11211/sys/src/9/port/chan.c:528,534
1990/0227    
	 */ 
	while(*name){ 
		if((nc=walk(c, elem, mntok)) == 0) 
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/1104/sys/src/9/port/chan.c:534,5401990/11211/sys/src/9/port/chan.c:543,549
1990/0820    
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
				error(0, Enonexist); 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/0227    
		break; 
1990/1104/sys/src/9/port/chan.c:545,5541990/11211/sys/src/9/port/chan.c:554,563
1990/0227    
		 * so one may mount on / or . and see the effect. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
		if(!(c->qid & CHDIR)) 
			error(0, Enotdir); 
1990/11211    
		if(!(c->qid.path & CHDIR)) 
			error(Enotdir); 
1990/0227    
		break; 
 
	case Aopen: 
1990/1104/sys/src/9/port/chan.c:556,5621990/11211/sys/src/9/port/chan.c:565,571
1990/0820    
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
				error(0, Enonexist); 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/0227    
	Open: 
1990/1104/sys/src/9/port/chan.c:573,5851990/11211/sys/src/9/port/chan.c:582,594
1990/0227    
		 * the replacement. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
			error(0, Eisdir); 
1990/11211    
			error(Eisdir); 
1990/0227    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
			omode |= OTRUNC; 
1990/1104/sys/src/9/port/chan.c:637,6481990/11211/sys/src/9/port/chan.c:646,657
1990/0227    
	char *end, *e; 
 
	if(*name == '/') 
		error(0, Efilename); 
1990/11211    
		error(Efilename); 
1990/0821    
	end = memchr(name, 0, NAMELEN); 
1990/0227    
	if(end == 0){ 
1990/0821    
		end = memchr(name, '/', NAMELEN); 
1990/0227    
		if(end == 0) 
			error(0, Efilename); 
1990/11211    
			error(Efilename); 
1990/0227    
	}else{ 
		e = memchr(name, '/', end-name); 
		if(e) 
1990/1104/sys/src/9/port/chan.c:651,6571990/11211/sys/src/9/port/chan.c:660,666
1990/0227    
	while(name < end){ 
		c = *name++; 
		if((c&0x80) || isfrog[c]) 
			error(0, Ebadchar); 
1990/11211    
			error(Ebadchar); 
1990/0227    
		*elem++ = c; 
	} 
	*elem = 0; 
1990/1104/sys/src/9/port/chan.c:661,6671990/11211/sys/src/9/port/chan.c:670,676
1990/0227    
void 
isdir(Chan *c) 
{ 
	if(c->qid & CHDIR) 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return; 
	error(0, Enotdir); 
1990/11211    
	error(Enotdir); 
1990/0227    
} 
1990/11211/sys/src/9/port/chan.c:192,1981990/1122/sys/src/9/port/chan.c:192,198 (short | long)
1990/0227    
	for(i=0; i<pg->nmtab; i++,mt++){ 
		if(mt->c==0 && mz==0) 
			mz = mt; 
1990/0321    
		else if(eqchan(mt->c, old, CHDIR|QPATH)){ 
1990/1122    
		else if(eqchan(mt->c, old, 1)){ 
1990/0321    
			mz = 0; 
1990/0227    
			goto Found; 
1990/0321    
		} 
1990/11211/sys/src/9/port/chan.c:296,3021990/1122/sys/src/9/port/chan.c:296,302
1990/0227    
	 */ 
	mt = pg->mtab; 
	for(i=0; i<pg->nmtab; i++,mt++) 
		if(mt->c && eqchan(mt->c, c, CHDIR|QPATH)) 
1990/1122    
		if(mt->c && eqchan(mt->c, c, 1)) 
1990/0227    
			goto Found; 
	/* 
	 * No; c is unaffected 
1990/11211/sys/src/9/port/chan.c:308,3141990/1122/sys/src/9/port/chan.c:308,314
1990/0227    
	 */ 
    Found: 
	lock(pg); 
	if(!eqchan(mt->c, c, CHDIR|QPATH)){	/* table changed underfoot */ 
1990/1122    
	if(!eqchan(mt->c, c, 1)){	/* table changed underfoot */ 
1990/0321    
		pprint("domount: changed underfoot?\n"); 
1990/0227    
		unlock(pg); 
		return c; 
1990/1122/sys/src/9/port/chan.c:99,1181991/0413/sys/src/9/port/chan.c:99,126 (short | long)
1990/0227    
} 
 
void 
1991/0413    
freechan(Chan *c) 
{ 
	c->flag = CFREE; 
	lock(&chanalloc); 
	c->next = chanalloc.free; 
	chanalloc.free = c; 
	unlock(&chanalloc); 
} 
 
void 
1990/0227    
close(Chan *c) 
{ 
1990/0907    
	if(c->flag & CFREE) 
		panic("close"); 
1990/0227    
	if(decref(c) == 0){ 
		if(!waserror()){ 
			(*devtab[c->type].close)(c); 
			poperror(); 
1991/0413    
		if(waserror()) { 
			freechan(c); 
			nexterror(); 
1990/0227    
		} 
1990/0907    
		c->flag = CFREE; 
1990/0227    
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
		unlock(&chanalloc); 
1991/0413    
		(*devtab[c->type].close)(c); 
		freechan(c); 
		poperror(); 
1990/0227    
	} 
} 
 
1991/0413/sys/src/9/port/chan.c:101,1111991/0414/sys/src/9/port/chan.c:101,113 (short | long)
1990/0227    
void 
1991/0413    
freechan(Chan *c) 
{ 
	c->flag = CFREE; 
	lock(&chanalloc); 
	c->next = chanalloc.free; 
	chanalloc.free = c; 
	unlock(&chanalloc); 
1991/0414    
	if(decref(c) == 0){ 
		c->flag = CFREE; 
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
		unlock(&chanalloc); 
	} 
1991/0413    
} 
 
void 
1991/0413/sys/src/9/port/chan.c:114,1261991/0414/sys/src/9/port/chan.c:116,130
1990/0907    
	if(c->flag & CFREE) 
		panic("close"); 
1990/0227    
	if(decref(c) == 0){ 
1991/0413    
		if(waserror()) { 
			freechan(c); 
			nexterror(); 
1991/0414    
		if(!waserror()) { 
			(*devtab[c->type].close)(c); 
			poperror(); 
1990/0227    
		} 
1991/0413    
		(*devtab[c->type].close)(c); 
		freechan(c); 
		poperror(); 
1991/0414    
		c->flag = CFREE; 
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
		unlock(&chanalloc); 
1990/0227    
	} 
} 
 
1991/0414/sys/src/9/port/chan.c:530,5371991/0416/sys/src/9/port/chan.c:530,540 (short | long)
1990/0227    
 
	name = nextelem(name, elem); 
1990/0820    
 
	if(mntok && !isdot) 
	if(!(amode==Amount && elem[0]==0))	/* don't domount on slash */ 
1991/0416    
	/* 
	 *  If mounting, don't follow the mount entry for root or the 
	 *  current directory. 
	 */ 
	if(mntok && !isdot && !(amode==Amount && elem[0]==0)) 
1990/0227    
		c = domount(c);			/* see case Atodir below */ 
 
	/* 
1991/0414/sys/src/9/port/chan.c:548,5541991/0416/sys/src/9/port/chan.c:551,556
1990/0227    
	/* 
	 * Last element; act according to type of access. 
	 */ 
                 
	switch(amode){ 
	case Aaccess: 
1990/0820    
		if(isdot) 
1991/0416/sys/src/9/port/chan.c:84,891991/0421/sys/src/9/port/chan.c:84,91 (short | long)
1990/0227    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
1991/0421    
		c->aux = 0; 
		c->mntindex = 0; 
1990/0303    
		c->mchan = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/0227    
		return c; 
1991/0421/sys/src/9/port/chan.c:11,161991/0423/sys/src/9/port/chan.c:11,28 (short | long)
1990/0227    
	Chan	*free; 
}chanalloc; 
 
1991/0423    
/* 
 *  used by namec, domount, and walk to point 
 *  to the current mount entry during name resolution 
 */ 
typedef struct Finger	Finger; 
struct Finger { 
	Chan	*c;		/* channel we're walking */ 
	int	needcl;		/* true if we need to clone c before using it */ 
	Mount	*mnt;		/* last mount point we ran traversed */ 
	ulong	mountid;	/* id of that mount point */ 
}; 
 
1990/0227    
int 
incref(Ref *r) 
{ 
1991/0421/sys/src/9/port/chan.c:83,911991/0423/sys/src/9/port/chan.c:95,101
1990/11211    
		c->dev = 0; 
1990/0227    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
1991/0421    
		c->aux = 0; 
		c->mntindex = 0; 
1990/0303    
		c->mchan = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/0227    
		return c; 
1991/0421/sys/src/9/port/chan.c:294,3081991/0423/sys/src/9/port/chan.c:304,316
1990/0227    
	return (*devtab[c->type].clone)(c, nc); 
} 
 
Chan* 
domount(Chan *c) 
1991/0423    
void 
domount(Finger *f) 
1990/0227    
{ 
	int i; 
	ulong mntid; 
	Mtab *mt; 
	Mount *mnt; 
	Pgrp *pg; 
	Chan *nc, *mc; 
1991/0423    
	Chan *mc; 
1990/0227    
 
	pg = u->p->pgrp; 
	/* 
1991/0421/sys/src/9/port/chan.c:310,3211991/0423/sys/src/9/port/chan.c:318,329
1990/0227    
	 */ 
	mt = pg->mtab; 
	for(i=0; i<pg->nmtab; i++,mt++) 
1990/1122    
		if(mt->c && eqchan(mt->c, c, 1)) 
1991/0423    
		if(mt->c && eqchan(mt->c, f->c, 1)) 
1990/0227    
			goto Found; 
	/* 
	 * No; c is unaffected 
	 */ 
	return c; 
1991/0423    
	return; 
1990/0227    
 
	/* 
	 * Yes; move c through table 
1991/0421/sys/src/9/port/chan.c:322,4201991/0423/sys/src/9/port/chan.c:330,419
1990/0227    
	 */ 
    Found: 
	lock(pg); 
1990/1122    
	if(!eqchan(mt->c, c, 1)){	/* table changed underfoot */ 
1991/0423    
	if(!eqchan(mt->c, f->c, 1)){	/* table changed underfoot */ 
1990/0321    
		pprint("domount: changed underfoot?\n"); 
1990/0227    
		unlock(pg); 
		return c; 
1991/0423    
		return; 
1990/0227    
	} 
	mnt = mt->mnt; 
	mntid = mnt->mountid; 
	mc = mnt->c; 
1991/0423    
	f->mnt = mt->mnt; 
	f->mountid = f->mnt->mountid; 
	mc = mt->mnt->c; 
1990/0227    
	incref(mc); 
	unlock(pg); 
	if(waserror()){ 
		close(mc); 
		nexterror(); 
	} 
	nc = clone(mc, 0); 
	close(mc); 
	poperror(); 
	close(c); 
	nc->mnt = mnt; 
	nc->mountid = mntid; 
	return nc; 
1991/0423    
	close(f->c); 
	f->c = mc; 
	f->needcl = 1; 
1990/0227    
} 
 
Chan* 
walk(Chan *ac, char *name, int domnt) 
1991/0423    
int 
walk(Finger *f, char *name, int domnt) 
1990/0227    
{ 
	Mount *mnt; 
	int first = 1; 
	Chan *c = ac; 
	Chan *nc, *mc; 
1991/0423    
	Mount *mnt = f->mnt; 
	ulong mountid = f->mountid; 
	Chan *c = f->c; 
	Chan *mc; 
1990/0227    
	Pgrp *pg = u->p->pgrp; 
 
	/* 
	 * name may be empty if the file name is "/", "#c" etc. 
	 */ 
    Again: 
	if(name[0] && (*devtab[c->type].walk)(c, name)==0){ 
		if(!(c->flag&CMOUNT)) 
			goto Notfound; 
		mnt = c->mnt; 
		if(mnt == 0) 
			panic("walk"); 
		lock(pg); 
		if(mnt->term){ 
1991/0423    
	if(name[0]){ 
		for(;;){ 
			if(!first || f->needcl){ 
				mc = (*devtab[c->type].clwalk)(c, name); 
				if(mc){ 
					close(c); 
					c = mc; 
					break; 
				} 
			} else { 
				if((*devtab[c->type].walk)(c, name) != 0){ 
					break; 
				} 
			} 
			if(!(c->flag&CMOUNT)) 
				goto Notfound; 
			if(mnt == 0) 
				panic("walk");	/* ??? is this safe ??? */ 
			lock(pg); 
			if(mnt->term){ 
				unlock(pg); 
				goto Notfound; 
			} 
			if(mountid != mnt->mountid){ 
				pprint("walk: changed underfoot? '%s'\n", name); 
				unlock(pg); 
				goto Notfound; 
			} 
			mnt = mnt->next; 
			mountid = mnt->mountid; 
			mc = mnt->c; 
			incref(mc); 
1990/0227    
			unlock(pg); 
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
1990/0820    
			pprint("walk: changed underfoot? '%s'\n", name); 
1990/0227    
			unlock(pg); 
			goto Notfound; 
		} 
		mnt = mnt->next; 
		mc = mnt->c; 
		incref(mc); 
		unlock(pg); 
		if(waserror()){ 
			close(mc); 
			nexterror(); 
		} 
		if(mnt == 0) 
			panic("walk 1"); 
		nc = clone(mc, 0); 
		close(mc); 
		poperror(); 
		if(!first) 
			close(c); 
		nc->mnt = mnt; 
1990/0321    
		nc->mountid = mnt->mountid; 
1990/0227    
		c = nc; 
		first = 0; 
		goto Again; 
	} 
                 
	if(name[0])			/* walk succeeded */ 
		c->flag &= ~CMOUNT; 
                 
1990/0914    
	if(domnt){ 
		if(waserror()){ 
			if(!first) 
				close(c); 
			return 0; 
1991/0423    
			c = mc; 
			first = 0; 
1990/0914    
		} 
		c = domount(c); 
		poperror(); 
1991/0423    
 
		/* 
		 *  we get here only if we have a cloned and walked 
		 *  channel 
		 */ 
		if(!first) 
			close(f->c); 
		f->c = c; 
		f->needcl = 0; 
		f->mnt = 0; 
		c->flag &= ~CMOUNT; 
1990/0914    
	} 
 
1990/0227    
	if(!first) 
		close(ac); 
1991/0423    
	if(domnt) 
		domount(f); 
1990/0227    
 
1991/0423    
	return 1; 
1990/0914    
 
1990/0227    
	return c; 
                 
    Notfound: 
	if(!first) 
		close(c); 
1991/0421/sys/src/9/port/chan.c:422,4351991/0423/sys/src/9/port/chan.c:421,434
1990/0227    
} 
 
/* 
 * c is a mounted non-creatable directory.  find a creatable one. 
1991/0423    
 * f->c is a mounted non-creatable directory.  find a creatable one. 
1990/0227    
 */ 
Chan* 
createdir(Chan *c) 
1991/0423    
void 
createdir(Finger *f) 
1990/0227    
{ 
	Mount *mnt; 
	Pgrp *pg = u->p->pgrp; 
	Chan *mc, *nc; 
1991/0423    
	Chan *mc; 
1990/0227    
 
	lock(pg); 
	if(waserror()){ 
1991/0421/sys/src/9/port/chan.c:436,4431991/0423/sys/src/9/port/chan.c:435,442
1990/0227    
		unlock(pg); 
		nexterror(); 
	} 
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
1991/0423    
	mnt = f->mnt; 
	if(f->mountid != mnt->mountid){ 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/11211    
		error(Enocreate); 
1990/0227    
	} 
1991/0421/sys/src/9/port/chan.c:449,4641991/0423/sys/src/9/port/chan.c:448,457
1990/0227    
	mc = mnt->c; 
	incref(mc); 
	unlock(pg); 
	if(waserror()){ 
		close(mc); 
		nexterror(); 
	} 
	nc = clone(mc, 0); 
	poperror(); 
	close(c); 
	close(mc); 
	nc->mnt = mnt; 
	return nc; 
1991/0423    
	close(f->c); 
	f->needcl = 1; 
	f->c = mc; 
1990/0227    
} 
 
1990/0914    
void 
1991/0421/sys/src/9/port/chan.c:466,4711991/0423/sys/src/9/port/chan.c:459,477
1990/0914    
{ 
} 
 
1991/0423    
void 
doclone(Finger *f) 
{ 
	Chan *nc; 
 
	if(f->needcl == 0) 
		return; 
	nc = clone(f->c, 0); 
	close(f->c); 
	f->c = nc; 
	f->needcl = 0; 
} 
 
1990/0227    
/* 
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
1991/0421/sys/src/9/port/chan.c:473,4831991/0423/sys/src/9/port/chan.c:479,489
1990/0227    
Chan* 
namec(char *name, int amode, int omode, ulong perm) 
{ 
	Chan *c, *nc; 
	int t; 
1990/0820    
	int mntok, isdot; 
1990/0821    
	char *p; 
	char *elem; 
1991/0423    
	Finger f; 
1990/0227    
 
	if(name[0] == 0) 
1990/11211    
		error(Enonexist); 
1991/0421/sys/src/9/port/chan.c:498,5051991/0423/sys/src/9/port/chan.c:504,514
1990/0821    
	elem = u->elem; 
1990/0227    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1991/0423    
	f.mnt = 0; 
1990/0227    
	if(name[0] == '/'){ 
		c = clone(u->slash, 0); 
1991/0423    
		f.c = u->slash; 
		incref(f.c); 
		f.needcl = 1; 
1990/0227    
		/* 
		 * Skip leading slashes. 
		 */ 
1991/0421/sys/src/9/port/chan.c:517,5251991/0423/sys/src/9/port/chan.c:526,537
1990/0227    
			elem[0]=0; 
		}else 
			name = nextelem(name, elem); 
		c = (*devtab[t].attach)(elem); 
1991/0423    
		f.c = (*devtab[t].attach)(elem); 
		f.needcl = 0; 
1990/0820    
	}else{ 
1990/0227    
		c = clone(u->dot, 0); 
1991/0423    
		f.c = u->dot; 
		incref(f.c); 
		f.needcl = 1; 
1990/0820    
		name = skipslash(name);	/* eat leading ./ */ 
		if(*name == 0) 
			isdot = 1; 
1991/0421/sys/src/9/port/chan.c:526,5321991/0423/sys/src/9/port/chan.c:538,544
1990/0820    
	} 
1990/0227    
 
	if(waserror()){ 
		close(c); 
1991/0423    
		close(f.c); 
1990/0227    
		nexterror(); 
	} 
 
1991/0421/sys/src/9/port/chan.c:537,5431991/0423/sys/src/9/port/chan.c:549,555
1991/0416    
	 *  current directory. 
	 */ 
	if(mntok && !isdot && !(amode==Amount && elem[0]==0)) 
1990/0227    
		c = domount(c);			/* see case Atodir below */ 
1991/0423    
		domount(&f);		/* see case Atodir below */ 
1990/0227    
 
	/* 
	 * How to treat the last element of the name depends on the operation. 
1991/0421/sys/src/9/port/chan.c:544,5521991/0423/sys/src/9/port/chan.c:556,563
1990/0227    
	 * Therefore do all but the last element by the easy algorithm. 
	 */ 
	while(*name){ 
		if((nc=walk(c, elem, mntok)) == 0) 
1991/0423    
		if(walk(&f, elem, mntok) == 0) 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/0820    
 
1991/0421/sys/src/9/port/chan.c:556,5661991/0423/sys/src/9/port/chan.c:567,576
1990/0227    
	switch(amode){ 
	case Aaccess: 
1990/0820    
		if(isdot) 
			c = domount(c); 
1991/0423    
			domount(&f); 
1990/0820    
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
1991/0423    
			if(walk(&f, elem, mntok) == 0) 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/0227    
		break; 
 
1991/0421/sys/src/9/port/chan.c:569,5941991/0423/sys/src/9/port/chan.c:579,604
1990/0227    
		 * Directories (e.g. for cd) are left before the mount point, 
		 * so one may mount on / or . and see the effect. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
1991/0423    
		if(walk(&f, elem, 0) == 0) 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
1990/11211    
		if(!(c->qid.path & CHDIR)) 
1991/0423    
		if(!(f.c->qid.path & CHDIR)) 
1990/11211    
			error(Enotdir); 
1990/0227    
		break; 
 
	case Aopen: 
1990/0820    
		if(isdot) 
			c = domount(c); 
1991/0423    
			domount(&f); 
1990/0820    
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
1991/0423    
			if(walk(&f, elem, mntok) == 0) 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/0227    
	Open: 
1990/0914    
		saveregisters();	/* else error() in open has wrong value of c saved */ 
1990/0227    
		c = (*devtab[c->type].open)(c, omode); 
1991/0423    
		saveregisters(); /* else error() in open has wrong value of c saved */ 
		if(f.needcl) 
			doclone(&f); 
		f.c = (*devtab[f.c->type].open)(f.c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1991/0423    
			f.c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	case Amount: 
1991/0421/sys/src/9/port/chan.c:597,6271991/0423/sys/src/9/port/chan.c:607,643
1990/0227    
		 * the second mount to be attached to the original directory, not 
		 * the replacement. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
1991/0423    
		if(walk(&f, elem, 0) == 0) 
1990/11211    
			error(Enonexist); 
1990/0227    
		c = nc; 
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
1990/11211    
			error(Eisdir); 
1990/0227    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
1991/0423    
		if(walk(&f, elem, 1) != 0){ 
1990/0227    
			omode |= OTRUNC; 
			goto Open; 
		} 
		if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) 
			c = createdir(c); 
		(*devtab[c->type].create)(c, elem, omode, perm); 
1991/0423    
		if((f.c->flag&(CMOUNT|CCREATE)) == CMOUNT) 
			createdir(&f); 
		if(f.needcl) 
			doclone(&f); 
		(*devtab[f.c->type].create)(f.c, elem, omode, perm); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1991/0423    
			f.c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	default: 
		panic("unknown namec access %d\n", amode); 
	} 
1991/0423    
	if(f.needcl) 
		doclone(&f); 
1990/0227    
	poperror(); 
	return c; 
1991/0423    
	if(f.c->flag & CMOUNT){ 
		f.c->mnt = f.mnt; 
		f.c->mountid = f.mountid; 
	} 
	return f.c; 
1990/0227    
} 
 
/* 
1991/0423/sys/src/9/port/chan.c:111,1281991/0426/sys/src/9/port/chan.c:111,116 (short | long)
1990/0227    
} 
 
void 
1991/0413    
freechan(Chan *c) 
{ 
1991/0414    
	if(decref(c) == 0){ 
		c->flag = CFREE; 
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
		unlock(&chanalloc); 
	} 
1991/0413    
} 
                 
void 
1990/0227    
close(Chan *c) 
{ 
1990/0907    
	if(c->flag & CFREE) 
1991/0426/sys/src/9/port/chan.c:11,281991/0427/sys/src/9/port/chan.c:11,16 (short | long)
1990/0227    
	Chan	*free; 
}chanalloc; 
 
1991/0423    
/* 
 *  used by namec, domount, and walk to point 
 *  to the current mount entry during name resolution 
 */ 
typedef struct Finger	Finger; 
struct Finger { 
	Chan	*c;		/* channel we're walking */ 
	int	needcl;		/* true if we need to clone c before using it */ 
	Mount	*mnt;		/* last mount point we ran traversed */ 
	ulong	mountid;	/* id of that mount point */ 
}; 
                 
1990/0227    
int 
incref(Ref *r) 
{ 
1991/0426/sys/src/9/port/chan.c:95,1011991/0427/sys/src/9/port/chan.c:83,91
1990/11211    
		c->dev = 0; 
1990/0227    
		c->offset = 0; 
		c->mnt = 0; 
1991/0427    
		c->stream = 0; 
1991/0421    
		c->aux = 0; 
1991/0427    
		c->mntindex = 0; 
1990/0303    
		c->mchan = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/0227    
		return c; 
1991/0426/sys/src/9/port/chan.c:292,3041991/0427/sys/src/9/port/chan.c:282,296
1990/0227    
	return (*devtab[c->type].clone)(c, nc); 
} 
 
1991/0423    
void 
domount(Finger *f) 
1991/0427    
Chan* 
domount(Chan *c) 
1990/0227    
{ 
	int i; 
1991/0427    
	ulong mntid; 
1990/0227    
	Mtab *mt; 
1991/0427    
	Mount *mnt; 
1990/0227    
	Pgrp *pg; 
1991/0423    
	Chan *mc; 
1991/0427    
	Chan *nc, *mc; 
1990/0227    
 
	pg = u->p->pgrp; 
	/* 
1991/0426/sys/src/9/port/chan.c:306,3171991/0427/sys/src/9/port/chan.c:298,309
1990/0227    
	 */ 
	mt = pg->mtab; 
	for(i=0; i<pg->nmtab; i++,mt++) 
1991/0423    
		if(mt->c && eqchan(mt->c, f->c, 1)) 
1991/0427    
		if(mt->c && eqchan(mt->c, c, 1)) 
1990/0227    
			goto Found; 
	/* 
	 * No; c is unaffected 
	 */ 
1991/0423    
	return; 
1991/0427    
	return c; 
1990/0227    
 
	/* 
	 * Yes; move c through table 
1991/0426/sys/src/9/port/chan.c:318,4071991/0427/sys/src/9/port/chan.c:310,408
1990/0227    
	 */ 
    Found: 
	lock(pg); 
1991/0423    
	if(!eqchan(mt->c, f->c, 1)){	/* table changed underfoot */ 
1991/0427    
	if(!eqchan(mt->c, c, 1)){	/* table changed underfoot */ 
1990/0321    
		pprint("domount: changed underfoot?\n"); 
1990/0227    
		unlock(pg); 
1991/0423    
		return; 
1991/0427    
		return c; 
1990/0227    
	} 
1991/0423    
	f->mnt = mt->mnt; 
	f->mountid = f->mnt->mountid; 
	mc = mt->mnt->c; 
1991/0427    
	mnt = mt->mnt; 
	mntid = mnt->mountid; 
	mc = mnt->c; 
1990/0227    
	incref(mc); 
	unlock(pg); 
1991/0423    
	close(f->c); 
	f->c = mc; 
	f->needcl = 1; 
1991/0427    
	if(waserror()){ 
		close(mc); 
		nexterror(); 
	} 
	nc = clone(mc, 0); 
	close(mc); 
	poperror(); 
	close(c); 
	nc->mnt = mnt; 
	nc->mountid = mntid; 
	return nc; 
1990/0227    
} 
 
1991/0423    
int 
walk(Finger *f, char *name, int domnt) 
1991/0427    
Chan* 
walk(Chan *ac, char *name, int domnt) 
1990/0227    
{ 
1991/0427    
	Mount *mnt; 
1990/0227    
	int first = 1; 
1991/0423    
	Mount *mnt = f->mnt; 
	ulong mountid = f->mountid; 
	Chan *c = f->c; 
	Chan *mc; 
1991/0427    
	Chan *c = ac; 
	Chan *nc, *mc; 
1990/0227    
	Pgrp *pg = u->p->pgrp; 
 
	/* 
	 * name may be empty if the file name is "/", "#c" etc. 
	 */ 
1991/0423    
	if(name[0]){ 
		for(;;){ 
			if(!first || f->needcl){ 
				mc = (*devtab[c->type].clwalk)(c, name); 
				if(mc){ 
					close(c); 
					c = mc; 
					break; 
				} 
			} else { 
				if((*devtab[c->type].walk)(c, name) != 0){ 
					break; 
				} 
			} 
			if(!(c->flag&CMOUNT)) 
				goto Notfound; 
			if(mnt == 0) 
				panic("walk");	/* ??? is this safe ??? */ 
			lock(pg); 
			if(mnt->term){ 
				unlock(pg); 
				goto Notfound; 
			} 
			if(mountid != mnt->mountid){ 
				pprint("walk: changed underfoot? '%s'\n", name); 
				unlock(pg); 
				goto Notfound; 
			} 
			mnt = mnt->next; 
			mountid = mnt->mountid; 
			mc = mnt->c; 
			incref(mc); 
1991/0427    
    Again: 
	if(name[0] && (*devtab[c->type].walk)(c, name)==0){ 
		if(!(c->flag&CMOUNT)) 
			goto Notfound; 
		mnt = c->mnt; 
		if(mnt == 0) 
			panic("walk"); 
		lock(pg); 
		if(mnt->term){ 
1990/0227    
			unlock(pg); 
1990/0914    
			if(!first) 
				close(c); 
1991/0423    
			c = mc; 
			first = 0; 
1991/0427    
			goto Notfound; 
1990/0914    
		} 
1991/0423    
                 
		/* 
		 *  we get here only if we have a cloned and walked 
		 *  channel 
		 */ 
1991/0427    
		if(c->mountid != mnt->mountid){ 
			pprint("walk: changed underfoot? '%s'\n", name); 
			unlock(pg); 
			goto Notfound; 
		} 
		mnt = mnt->next; 
		mc = mnt->c; 
		incref(mc); 
		unlock(pg); 
		if(waserror()){ 
			close(mc); 
			nexterror(); 
		} 
		if(mnt == 0) 
			panic("walk 1"); 
		nc = clone(mc, 0); 
		close(mc); 
		poperror(); 
1991/0423    
		if(!first) 
			close(f->c); 
		f->c = c; 
		f->needcl = 0; 
		f->mnt = 0; 
1991/0427    
			close(c); 
		nc->mnt = mnt; 
		nc->mountid = mnt->mountid; 
		c = nc; 
		first = 0; 
		goto Again; 
	} 
 
	if(name[0])			/* walk succeeded */ 
1991/0423    
		c->flag &= ~CMOUNT; 
1991/0427    
 
	if(domnt){ 
		if(waserror()){ 
			if(!first) 
				close(c); 
			return 0; 
		} 
		c = domount(c); 
		poperror(); 
1990/0914    
	} 
 
1991/0423    
	if(domnt) 
		domount(f); 
1991/0427    
	if(!first) 
		close(ac); 
1990/0227    
 
1991/0423    
	return 1; 
1990/0914    
 
1991/0427    
	return c; 
 
1990/0227    
    Notfound: 
	if(!first) 
		close(c); 
1991/0426/sys/src/9/port/chan.c:409,4221991/0427/sys/src/9/port/chan.c:410,423
1990/0227    
} 
 
/* 
1991/0423    
 * f->c is a mounted non-creatable directory.  find a creatable one. 
1991/0427    
 * c is a mounted non-creatable directory.  find a creatable one. 
1990/0227    
 */ 
1991/0423    
void 
createdir(Finger *f) 
1991/0427    
Chan* 
createdir(Chan *c) 
1990/0227    
{ 
	Mount *mnt; 
	Pgrp *pg = u->p->pgrp; 
1991/0423    
	Chan *mc; 
1991/0427    
	Chan *mc, *nc; 
1990/0227    
 
	lock(pg); 
	if(waserror()){ 
1991/0426/sys/src/9/port/chan.c:423,4301991/0427/sys/src/9/port/chan.c:424,431
1990/0227    
		unlock(pg); 
		nexterror(); 
	} 
1991/0423    
	mnt = f->mnt; 
	if(f->mountid != mnt->mountid){ 
1991/0427    
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/11211    
		error(Enocreate); 
1990/0227    
	} 
1991/0426/sys/src/9/port/chan.c:436,4451991/0427/sys/src/9/port/chan.c:437,452
1990/0227    
	mc = mnt->c; 
	incref(mc); 
	unlock(pg); 
1991/0427    
	if(waserror()){ 
		close(mc); 
		nexterror(); 
	} 
	nc = clone(mc, 0); 
1990/0227    
	poperror(); 
1991/0423    
	close(f->c); 
	f->needcl = 1; 
	f->c = mc; 
1991/0427    
	close(c); 
	close(mc); 
	nc->mnt = mnt; 
	return nc; 
1990/0227    
} 
 
1990/0914    
void 
1991/0426/sys/src/9/port/chan.c:447,4651991/0427/sys/src/9/port/chan.c:454,459
1990/0914    
{ 
} 
 
1991/0423    
void 
doclone(Finger *f) 
{ 
	Chan *nc; 
                 
	if(f->needcl == 0) 
		return; 
	nc = clone(f->c, 0); 
	close(f->c); 
	f->c = nc; 
	f->needcl = 0; 
} 
                 
1990/0227    
/* 
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
1991/0426/sys/src/9/port/chan.c:467,4771991/0427/sys/src/9/port/chan.c:461,471
1990/0227    
Chan* 
namec(char *name, int amode, int omode, ulong perm) 
{ 
1991/0427    
	Chan *c, *nc, *cc; 
1990/0227    
	int t; 
1990/0820    
	int mntok, isdot; 
1990/0821    
	char *p; 
	char *elem; 
1991/0423    
	Finger f; 
1990/0227    
 
	if(name[0] == 0) 
1990/11211    
		error(Enonexist); 
1991/0426/sys/src/9/port/chan.c:492,5021991/0427/sys/src/9/port/chan.c:486,493
1990/0821    
	elem = u->elem; 
1990/0227    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1991/0423    
	f.mnt = 0; 
1990/0227    
	if(name[0] == '/'){ 
1991/0423    
		f.c = u->slash; 
		incref(f.c); 
		f.needcl = 1; 
1991/0427    
		c = clone(u->slash, 0); 
1990/0227    
		/* 
		 * Skip leading slashes. 
		 */ 
1991/0426/sys/src/9/port/chan.c:514,5251991/0427/sys/src/9/port/chan.c:505,513
1990/0227    
			elem[0]=0; 
		}else 
			name = nextelem(name, elem); 
1991/0423    
		f.c = (*devtab[t].attach)(elem); 
		f.needcl = 0; 
1991/0427    
		c = (*devtab[t].attach)(elem); 
1990/0820    
	}else{ 
1991/0423    
		f.c = u->dot; 
		incref(f.c); 
		f.needcl = 1; 
1991/0427    
		c = clone(u->dot, 0); 
1990/0820    
		name = skipslash(name);	/* eat leading ./ */ 
		if(*name == 0) 
			isdot = 1; 
1991/0426/sys/src/9/port/chan.c:526,5321991/0427/sys/src/9/port/chan.c:514,520
1990/0820    
	} 
1990/0227    
 
	if(waserror()){ 
1991/0423    
		close(f.c); 
1991/0427    
		close(c); 
1990/0227    
		nexterror(); 
	} 
 
1991/0426/sys/src/9/port/chan.c:537,5431991/0427/sys/src/9/port/chan.c:525,531
1991/0416    
	 *  current directory. 
	 */ 
	if(mntok && !isdot && !(amode==Amount && elem[0]==0)) 
1991/0423    
		domount(&f);		/* see case Atodir below */ 
1991/0427    
		c = domount(c);			/* see case Atodir below */ 
1990/0227    
 
	/* 
	 * How to treat the last element of the name depends on the operation. 
1991/0426/sys/src/9/port/chan.c:544,5511991/0427/sys/src/9/port/chan.c:532,540
1990/0227    
	 * Therefore do all but the last element by the easy algorithm. 
	 */ 
	while(*name){ 
1991/0423    
		if(walk(&f, elem, mntok) == 0) 
1991/0427    
		if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
			error(Enonexist); 
1991/0427    
		c = nc; 
1990/0227    
		name = nextelem(name, elem); 
	} 
1990/0820    
 
1991/0426/sys/src/9/port/chan.c:555,5641991/0427/sys/src/9/port/chan.c:544,554
1990/0227    
	switch(amode){ 
	case Aaccess: 
1990/0820    
		if(isdot) 
1991/0423    
			domount(&f); 
1991/0427    
			c = domount(c); 
1990/0820    
		else{ 
1991/0423    
			if(walk(&f, elem, mntok) == 0) 
1991/0427    
			if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
				error(Enonexist); 
1991/0427    
			c = nc; 
1990/0820    
		} 
1990/0227    
		break; 
 
1991/0426/sys/src/9/port/chan.c:567,5921991/0427/sys/src/9/port/chan.c:557,582
1990/0227    
		 * Directories (e.g. for cd) are left before the mount point, 
		 * so one may mount on / or . and see the effect. 
		 */ 
1991/0423    
		if(walk(&f, elem, 0) == 0) 
1991/0427    
		if((nc=walk(c, elem, 0)) == 0) 
1990/11211    
			error(Enonexist); 
1991/0423    
		if(!(f.c->qid.path & CHDIR)) 
1991/0427    
		c = nc; 
		if(!(c->qid.path & CHDIR)) 
1990/11211    
			error(Enotdir); 
1990/0227    
		break; 
 
	case Aopen: 
1990/0820    
		if(isdot) 
1991/0423    
			domount(&f); 
1991/0427    
			c = domount(c); 
1990/0820    
		else{ 
1991/0423    
			if(walk(&f, elem, mntok) == 0) 
1991/0427    
			if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
				error(Enonexist); 
1991/0427    
			c = nc; 
1990/0820    
		} 
1990/0227    
	Open: 
1991/0423    
		saveregisters(); /* else error() in open has wrong value of c saved */ 
		if(f.needcl) 
			doclone(&f); 
		f.c = (*devtab[f.c->type].open)(f.c, omode); 
1991/0427    
		saveregisters();	/* else error() in open has wrong value of c saved */ 
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
1991/0423    
			f.c->flag |= CCEXEC; 
1991/0427    
			c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	case Amount: 
1991/0426/sys/src/9/port/chan.c:595,6311991/0427/sys/src/9/port/chan.c:585,635
1990/0227    
		 * the second mount to be attached to the original directory, not 
		 * the replacement. 
		 */ 
1991/0423    
		if(walk(&f, elem, 0) == 0) 
1991/0427    
		if((nc=walk(c, elem, 0)) == 0) 
1990/11211    
			error(Enonexist); 
1991/0427    
		c = nc; 
1990/0227    
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
1990/11211    
			error(Eisdir); 
1991/0423    
		if(walk(&f, elem, 1) != 0){ 
1991/0427    
 
		/* 
		 *  Walk the element before trying to create it 
		 *  to see if it exists.  We clone the channel 
		 *  first, just in case someone is trying to 
		 *  use clwalk outside the kernel. 
		 */ 
		cc = clone(c, 0); 
		if(waserror()){ 
			close(cc); 
			nexterror(); 
		} 
		if((nc=walk(cc, elem, 1)) != 0){ 
			poperror(); 
			close(c); 
			c = nc; 
1990/0227    
			omode |= OTRUNC; 
			goto Open; 
		} 
1991/0423    
		if((f.c->flag&(CMOUNT|CCREATE)) == CMOUNT) 
			createdir(&f); 
		if(f.needcl) 
			doclone(&f); 
		(*devtab[f.c->type].create)(f.c, elem, omode, perm); 
1991/0427    
		close(cc); 
		poperror(); 
 
		/* 
		 *  the file didn't exist, try the create 
		 */ 
		if((c->flag&(CMOUNT|CCREATE)) == CMOUNT) 
			c = createdir(c); 
		(*devtab[c->type].create)(c, elem, omode, perm); 
1990/08141    
		if(omode & OCEXEC) 
1991/0423    
			f.c->flag |= CCEXEC; 
1991/0427    
			c->flag |= CCEXEC; 
1990/0227    
		break; 
 
	default: 
		panic("unknown namec access %d\n", amode); 
	} 
1991/0423    
	if(f.needcl) 
		doclone(&f); 
1990/0227    
	poperror(); 
1991/0423    
	if(f.c->flag & CMOUNT){ 
		f.c->mnt = f.mnt; 
		f.c->mountid = f.mountid; 
	} 
	return f.c; 
1991/0427    
	return c; 
1990/0227    
} 
 
/* 
1991/0427/sys/src/9/port/chan.c:30,351991/0705/sys/src/9/port/chan.c:30,37 (short | long)
1990/0227    
	lock(r); 
1990/1104    
	x = --r->ref; 
1990/0227    
	unlock(r); 
1991/0705    
	if(x < 0) 
		panic("decref"); 
1990/1104    
	return x; 
1990/0227    
} 
 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)