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

gnot/chan.c (diff list | history)

1990/03091/sys/src/9/gnot/chan.c:149,1551990/0321/sys/src/9/gnot/chan.c:149,155 (short | long)
1990/03091    
	Mtab *mt, *mz; 
	Mount *mnt, *omnt, *nmnt, *pmnt; 
	Pgrp *pg; 
	int isnew; 
1990/0321    
	int islast; 
1990/03091    
 
	if(CHDIR & (old->qid^new->qid)) 
		error(0, Emount); 
1990/03091/sys/src/9/gnot/chan.c:157,1661990/0321/sys/src/9/gnot/chan.c:157,171
1990/03091    
		error(0, Emount); 
 
	mz = 0; 
	isnew = 0; 
1990/0321    
	islast = 0; 
	mnt = 0; 
1990/03091    
	pg = u->p->pgrp; 
	lock(pg); 
	if(waserror()){ 
1990/0321    
		if(mnt){ 
			mnt->c = 0;	/* caller will close new */ 
			closemount(mnt); 
		} 
1990/03091    
		unlock(pg); 
		nexterror(); 
	} 
1990/03091/sys/src/9/gnot/chan.c:171,1881990/0321/sys/src/9/gnot/chan.c:176,193
1990/03091    
	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/03091    
			goto Found; 
1990/0321    
		} 
1990/03091    
	} 
	isnew = 1; 
	if(mz == 0){ 
		if(i == conf.nmtab) 
			error(0, Enomount); 
		mz = &pg->mtab[i]; 
		pg->nmtab++; 
1990/0321    
		islast++; 
1990/03091    
	} 
	mz->mnt = 0; 
	mz->c = old; 
	mt = mz; 
 
    Found: 
1990/03091/sys/src/9/gnot/chan.c:244,2511990/0321/sys/src/9/gnot/chan.c:249,260
1990/03091    
	} 
 
	incref(new); 
	if(isnew) 
1990/0321    
	if(mz){ 
		mz->c = old; 
1990/03091    
		incref(old); 
1990/0321    
	} 
	if(islast) 
		pg->nmtab++; 
1990/03091    
	unlock(pg); 
	poperror(); 
	return mnt->mountid; 
1990/03091/sys/src/9/gnot/chan.c:286,2921990/0321/sys/src/9/gnot/chan.c:295,301
1990/03091    
    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/03091    
		unlock(pg); 
		return c; 
	} 
1990/03091/sys/src/9/gnot/chan.c:333,3391990/0321/sys/src/9/gnot/chan.c:342,348
1990/03091    
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
			print("walk: changed underfoot?\n"); 
1990/0321    
			pprint("walk: changed underfoot?\n"); 
1990/03091    
			unlock(pg); 
			goto Notfound; 
		} 
1990/03091/sys/src/9/gnot/chan.c:353,3581990/0321/sys/src/9/gnot/chan.c:362,368
1990/03091    
		if(!first) 
			close(c); 
		nc->mnt = mnt; 
1990/0321    
		nc->mountid = mnt->mountid; 
1990/03091    
		c = nc; 
		first = 0; 
		goto Again; 
1990/03091/sys/src/9/gnot/chan.c:391,3971990/0321/sys/src/9/gnot/chan.c:401,407
1990/03091    
	} 
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
		print("createdir: changed underfoot?\n"); 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/03091    
		error(0, Enocreate); 
	} 
	do{ 
1990/0321/sys/src/9/gnot/chan.c:134,1401990/0603/sys/src/9/gnot/chan.c:134,140 (short | long)
1990/03091    
	nmnt->mountid = omnt->mountid; 
	nmnt->next = omnt->next; 
	if(nmnt->next) 
		incref(nmnt); 
1990/0603    
		incref(nmnt->next); 
1990/03091    
	nmnt->c = omnt->c; 
	incref(nmnt->c); 
	omnt->ref--; 
1990/0321/sys/src/9/gnot/chan.c:207,2201990/0603/sys/src/9/gnot/chan.c:207,218
1990/03091    
		/* fall through */ 
 
	case MREPL: 
		omnt = mt->mnt; 
		if(omnt) 
			incref(omnt); 
		mnt->next = omnt; 
1990/0603    
		mnt->next = mt->mnt; 
1990/03091    
		mt->mnt = mnt; 
		mnt->term = 1; 
		if((flag&MORDER) == MBEFORE) 
			mnt->term = 0; 
1990/0603    
		else 
			mnt->term = 1; 
1990/03091    
		break; 
 
	/* 
1990/0603/sys/src/9/gnot/chan.c:127,1331990/0604/sys/src/9/gnot/chan.c:127,132 (short | long)
1990/03091    
{ 
	Mount *nmnt; 
 
	print("mount copy on write\n"); 
	nmnt = newmount(); 
	lock(nmnt); 
	nmnt->term = omnt->term; 
1990/0604/sys/src/9/gnot/chan.c:72,771990/0707/sys/src/9/gnot/chan.c:72,78 (short | long)
1990/03091    
	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/03091    
		c->flag = 0; 
		c->ref = 1; 
		unlock(&chanalloc); 
1990/0707/sys/src/9/gnot/chan.c:447,4531990/08101/sys/src/9/gnot/chan.c:447,453 (short | long)
1990/03091    
		mntok = 0; 
		if(!((ulong)name & KZERO)) 
			validaddr((ulong)(name+1), 2, 0); 
		if(name[1]=='|' || ('A'<=name[1] && name[1]<='Z')) 
1990/08101    
		if(name[1]=='|' || name[1]=='M') 
1990/03091    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
		if(t == -1) 
1990/08101/sys/src/9/gnot/chan.c:511,5161990/08141/sys/src/9/gnot/chan.c:511,518 (short | long)
1990/03091    
		c = nc; 
	Open: 
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/03091    
		break; 
 
	case Amount: 
1990/08101/sys/src/9/gnot/chan.c:533,5381990/08141/sys/src/9/gnot/chan.c:535,542
1990/03091    
		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/03091    
		break; 
 
	default: 
1990/08141/sys/src/9/gnot/chan.c:340,3461990/0820/sys/src/9/gnot/chan.c:340,346 (short | long)
1990/03091    
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
1990/0321    
			pprint("walk: changed underfoot?\n"); 
1990/0820    
			pprint("walk: changed underfoot? '%s'\n", name); 
1990/03091    
			unlock(pg); 
			goto Notfound; 
		} 
1990/08141/sys/src/9/gnot/chan.c:431,4421990/0820/sys/src/9/gnot/chan.c:431,443
1990/03091    
{ 
	Chan *c, *nc; 
	int t; 
	int mntok; 
1990/0820    
	int mntok, isdot; 
1990/03091    
	char *elem = u->elem; 
 
	if(name[0] == 0) 
		error(0, Enonexist); 
	mntok = 1; 
1990/0820    
	isdot = 0; 
1990/03091    
	if(name[0] == '/'){ 
		c = clone(u->slash, 0); 
		/* 
1990/08141/sys/src/9/gnot/chan.c:459,4661990/0820/sys/src/9/gnot/chan.c:460,471
1990/03091    
		}else 
			name = nextelem(name, elem); 
		c = (*devtab[t].attach)(elem); 
	}else 
1990/0820    
	}else{ 
1990/03091    
		c = clone(u->dot, 0); 
1990/0820    
		name = skipslash(name);	/* eat leading ./ */ 
		if(*name == 0) 
			isdot = 1; 
	} 
1990/03091    
 
	if(waserror()){ 
		close(c); 
1990/08141/sys/src/9/gnot/chan.c:468,4751990/0820/sys/src/9/gnot/chan.c:473,481
1990/03091    
	} 
 
	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/03091    
		c = domount(c);			/* see case Atodir below */ 
 
	/* 
1990/08141/sys/src/9/gnot/chan.c:482,4871990/0820/sys/src/9/gnot/chan.c:488,494
1990/03091    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/0820    
 
1990/03091    
	/* 
	 * Last element; act according to type of access. 
	 */ 
1990/08141/sys/src/9/gnot/chan.c:488,4961990/0820/sys/src/9/gnot/chan.c:495,507
1990/03091    
 
	switch(amode){ 
	case Aaccess: 
		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/03091    
		break; 
 
	case Atodir: 
1990/08141/sys/src/9/gnot/chan.c:506,5141990/0820/sys/src/9/gnot/chan.c:517,529
1990/03091    
		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/03091    
	Open: 
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
1990/08141/sys/src/9/gnot/chan.c:527,5321990/0820/sys/src/9/gnot/chan.c:542,549
1990/03091    
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
			error(0, Eisdir); 
1990/03091    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
			omode |= OTRUNC; 
1990/08141/sys/src/9/gnot/chan.c:552,5611990/0820/sys/src/9/gnot/chan.c:569,587
1990/03091    
char* 
skipslash(char *name) 
{ 
1990/0820    
    Again: 
1990/03091    
	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/03091    
	} 
	return name; 
} 
1990/0820/sys/src/9/gnot/chan.c:432,4411990/0821/sys/src/9/gnot/chan.c:432,457 (short | long)
1990/03091    
	Chan *c, *nc; 
	int t; 
1990/0820    
	int mntok, isdot; 
1990/03091    
	char *elem = u->elem; 
1990/0821    
	char *p; 
	char *elem; 
1990/03091    
 
	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/03091    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1990/03091    
	if(name[0] == '/'){ 
1990/0820/sys/src/9/gnot/chan.c:446,4531990/0821/sys/src/9/gnot/chan.c:462,467
1990/03091    
		name = skipslash(name); 
	}else if(name[0] == '#'){ 
		mntok = 0; 
		if(!((ulong)name & KZERO)) 
			validaddr((ulong)(name+1), 2, 0); 
1990/08101    
		if(name[1]=='|' || name[1]=='M') 
1990/03091    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
1990/0820/sys/src/9/gnot/chan.c:570,5881990/0821/sys/src/9/gnot/chan.c:584,595
1990/03091    
skipslash(char *name) 
{ 
1990/0820    
    Again: 
1990/03091    
	while(*name == '/'){ 
		if(((ulong)name&KZERO)==0 && (((ulong)name+1)&(BY2PG-1))==0) 
			validaddr((ulong)name+1, 1, 0); 
1990/0821    
	while(*name == '/') 
1990/03091    
		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/03091    
	} 
	return name; 
} 
 
1990/0820/sys/src/9/gnot/chan.c:600,6061990/0821/sys/src/9/gnot/chan.c:607,612
1990/03091    
 * 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/gnot/chan.c:610,6181990/0821/sys/src/9/gnot/chan.c:616,624
1990/03091    
 
	if(*name == '/') 
		error(0, Efilename); 
	end = vmemchr(name, 0, NAMELEN); 
1990/0821    
	end = memchr(name, 0, NAMELEN); 
1990/03091    
	if(end == 0){ 
		end = vmemchr(name, '/', NAMELEN); 
1990/0821    
		end = memchr(name, '/', NAMELEN); 
1990/03091    
		if(end == 0) 
			error(0, Efilename); 
	}else{ 
1990/0821/sys/src/9/gnot/chan.c:96,1061990/0914/sys/src/9/gnot/chan.c:96,109 (short | long)
1990/03091    
void 
close(Chan *c) 
{ 
1990/0914    
	if(c->flag & CFREE) 
		panic("close"); 
1990/03091    
	if(decref(c) == 0){ 
		if(!waserror()){ 
			(*devtab[c->type].close)(c); 
			poperror(); 
		} 
1990/0914    
		c->flag = CFREE; 
1990/03091    
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
1990/0821/sys/src/9/gnot/chan.c:369,3791990/0914/sys/src/9/gnot/chan.c:372,392
1990/03091    
	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/03091    
	if(!first) 
		close(ac); 
 
	if(domnt) 
		return domount(c); 
1990/0914    
 
1990/03091    
	return c; 
 
    Notfound: 
1990/0821/sys/src/9/gnot/chan.c:422,4271990/0914/sys/src/9/gnot/chan.c:435,445
1990/03091    
	return nc; 
} 
 
1990/0914    
void 
saveregisters(void) 
{ 
} 
 
1990/03091    
/* 
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
1990/0821/sys/src/9/gnot/chan.c:539,5441990/0914/sys/src/9/gnot/chan.c:557,563
1990/0820    
			c = nc; 
		} 
1990/03091    
	Open: 
1990/0914    
		saveregisters();	/* else error() in open has wrong value of c saved */ 
1990/03091    
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/0914/sys/src/9/gnot/chan.c:374,3801990/09141/sys/src/9/gnot/chan.c:374,379 (short | long)
1990/03091    
 
1990/0914    
	if(domnt){ 
		if(waserror()){ 
			print("domount error\n"); 
			if(!first) 
				close(c); 
			return 0; 
1990/09141/sys/src/9/gnot/chan.c:479,4851990/1006/sys/src/9/gnot/chan.c:479,485 (short | long)
1990/03091    
		name = skipslash(name); 
	}else if(name[0] == '#'){ 
		mntok = 0; 
1990/08101    
		if(name[1]=='|' || name[1]=='M') 
1990/1006    
		if(name[1]=='M') 
1990/03091    
			error(0, Enonexist); 
		t = devno(name[1], 1); 
		if(t == -1) 
1990/1006/sys/src/9/gnot/chan.c:14,321990/1104/sys/src/9/gnot/chan.c:14,36 (short | long)
1990/03091    
int 
incref(Ref *r) 
{ 
1990/1104    
	int x; 
 
1990/03091    
	lock(r); 
	r->ref++; 
1990/1104    
	x = ++r->ref; 
1990/03091    
	unlock(r); 
	return r->ref; 
1990/1104    
	return x; 
1990/03091    
} 
 
int 
decref(Ref *r) 
{ 
1990/1104    
	int x; 
 
1990/03091    
	lock(r); 
	r->ref--; 
1990/1104    
	x = --r->ref; 
1990/03091    
	unlock(r); 
	return r->ref; 
1990/1104    
	return x; 
1990/03091    
} 
 
void 
1990/1104/sys/src/9/gnot/chan.c:80,851990/11062/sys/src/9/gnot/chan.c:80,86 (short | long)
1990/03091    
		c->flag = 0; 
		c->ref = 1; 
		unlock(&chanalloc); 
1990/11062    
		c->dev = 0; 
1990/03091    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
1990/11062/sys/src/9/gnot/chan.c:85,911990/11211/sys/src/9/gnot/chan.c:85,91 (short | long)
1990/03091    
		c->mnt = 0; 
		c->stream = 0; 
		c->mchan = 0; 
		c->mqid = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/03091    
		return c; 
	} 
	unlock(&chanalloc); 
1990/11062/sys/src/9/gnot/chan.c:117,1261990/11211/sys/src/9/gnot/chan.c:117,134
1990/03091    
} 
 
int 
eqchan(Chan *a, Chan *b, long qmask) 
1990/11211    
eqqid(Qid a, Qid b) 
1990/03091    
{ 
	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/03091    
		return 0; 
1990/11211    
	if(!pathonly && a->qid.vers!=b->qid.vers) 
		return 0; 
1990/03091    
	if(a->type != b->type) 
		return 0; 
	if(a->dev != b->dev) 
1990/11062/sys/src/9/gnot/chan.c:159,1681990/11211/sys/src/9/gnot/chan.c:167,176
1990/03091    
	Pgrp *pg; 
1990/0321    
	int islast; 
1990/03091    
 
	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/03091    
 
	mz = 0; 
1990/0321    
	islast = 0; 
1990/11062/sys/src/9/gnot/chan.c:191,1971990/11211/sys/src/9/gnot/chan.c:199,205
1990/03091    
	} 
	if(mz == 0){ 
		if(i == conf.nmtab) 
			error(0, Enomount); 
1990/11211    
			error(Enomount); 
1990/03091    
		mz = &pg->mtab[i]; 
1990/0321    
		islast++; 
1990/03091    
	} 
1990/11062/sys/src/9/gnot/chan.c:211,2171990/11211/sys/src/9/gnot/chan.c:219,225
1990/03091    
	 */ 
	case MBEFORE: 
		if(mt->mnt == 0) 
			error(0, Enotunion); 
1990/11211    
			error(Enotunion); 
1990/03091    
		/* fall through */ 
 
	case MREPL: 
1990/11062/sys/src/9/gnot/chan.c:228,2341990/11211/sys/src/9/gnot/chan.c:236,242
1990/03091    
	 */ 
	case MAFTER: 
		if(mt->mnt == 0) 
			error(0, Enotunion); 
1990/11211    
			error(Enotunion); 
1990/03091    
		omnt = mt->mnt; 
		pmnt = 0; 
		while(!omnt->term){ 
1990/11062/sys/src/9/gnot/chan.c:417,4271990/11211/sys/src/9/gnot/chan.c:425,435
1990/03091    
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/03091    
		error(0, Enocreate); 
1990/11211    
		error(Enocreate); 
1990/03091    
	} 
	do{ 
		if(mnt->term) 
			error(0, Enocreate); 
1990/11211    
			error(Enocreate); 
1990/03091    
		mnt = mnt->next; 
	}while(!(mnt->c->flag&CCREATE)); 
	mc = mnt->c; 
1990/11062/sys/src/9/gnot/chan.c:458,4641990/11211/sys/src/9/gnot/chan.c:466,472
1990/0821    
	char *elem; 
1990/03091    
 
	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/11062/sys/src/9/gnot/chan.c:485,4941990/11211/sys/src/9/gnot/chan.c:493,502
1990/03091    
	}else if(name[0] == '#'){ 
		mntok = 0; 
1990/1006    
		if(name[1]=='M') 
1990/03091    
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/03091    
		t = devno(name[1], 1); 
		if(t == -1) 
			error(0, Ebadsharp); 
1990/11211    
			error(Ebadsharp); 
1990/03091    
		name += 2; 
		if(*name == '/'){ 
			name = skipslash(name); 
1990/11062/sys/src/9/gnot/chan.c:520,5261990/11211/sys/src/9/gnot/chan.c:528,534
1990/03091    
	 */ 
	while(*name){ 
		if((nc=walk(c, elem, mntok)) == 0) 
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/03091    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/11062/sys/src/9/gnot/chan.c:535,5411990/11211/sys/src/9/gnot/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/03091    
		break; 
1990/11062/sys/src/9/gnot/chan.c:546,5551990/11211/sys/src/9/gnot/chan.c:554,563
1990/03091    
		 * 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/03091    
		c = nc; 
		if(!(c->qid & CHDIR)) 
			error(0, Enotdir); 
1990/11211    
		if(!(c->qid.path & CHDIR)) 
			error(Enotdir); 
1990/03091    
		break; 
 
	case Aopen: 
1990/11062/sys/src/9/gnot/chan.c:557,5631990/11211/sys/src/9/gnot/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/03091    
	Open: 
1990/11062/sys/src/9/gnot/chan.c:574,5861990/11211/sys/src/9/gnot/chan.c:582,594
1990/03091    
		 * the replacement. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
			error(0, Enonexist); 
1990/11211    
			error(Enonexist); 
1990/03091    
		c = nc; 
		break; 
 
	case Acreate: 
1990/0820    
		if(isdot) 
			error(0, Eisdir); 
1990/11211    
			error(Eisdir); 
1990/03091    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
			omode |= OTRUNC; 
1990/11062/sys/src/9/gnot/chan.c:638,6491990/11211/sys/src/9/gnot/chan.c:646,657
1990/03091    
	char *end, *e; 
 
	if(*name == '/') 
		error(0, Efilename); 
1990/11211    
		error(Efilename); 
1990/0821    
	end = memchr(name, 0, NAMELEN); 
1990/03091    
	if(end == 0){ 
1990/0821    
		end = memchr(name, '/', NAMELEN); 
1990/03091    
		if(end == 0) 
			error(0, Efilename); 
1990/11211    
			error(Efilename); 
1990/03091    
	}else{ 
		e = memchr(name, '/', end-name); 
		if(e) 
1990/11062/sys/src/9/gnot/chan.c:652,6581990/11211/sys/src/9/gnot/chan.c:660,666
1990/03091    
	while(name < end){ 
		c = *name++; 
		if((c&0x80) || isfrog[c]) 
			error(0, Ebadchar); 
1990/11211    
			error(Ebadchar); 
1990/03091    
		*elem++ = c; 
	} 
	*elem = 0; 
1990/11062/sys/src/9/gnot/chan.c:662,6681990/11211/sys/src/9/gnot/chan.c:670,676
1990/03091    
void 
isdir(Chan *c) 
{ 
	if(c->qid & CHDIR) 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/03091    
		return; 
	error(0, Enotdir); 
1990/11211    
	error(Enotdir); 
1990/03091    
} 
1990/11211/sys/src/9/gnot/chan.c:192,1981990/1122/sys/src/9/gnot/chan.c:192,198 (short | long)
1990/03091    
	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/03091    
			goto Found; 
1990/0321    
		} 
1990/11211/sys/src/9/gnot/chan.c:296,3021990/1122/sys/src/9/gnot/chan.c:296,302
1990/03091    
	 */ 
	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/03091    
			goto Found; 
	/* 
	 * No; c is unaffected 
1990/11211/sys/src/9/gnot/chan.c:308,3141990/1122/sys/src/9/gnot/chan.c:308,314
1990/03091    
	 */ 
    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/03091    
		unlock(pg); 
		return c; 
1990/1122/sys/src/9/gnot/chan.c:1,6761990/1210/sys/src/9/gnot/chan.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:34 2005
1990/03091    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
                 
                 
struct{ 
	Lock; 
	Chan	*free; 
}chanalloc; 
                 
int 
incref(Ref *r) 
{ 
1990/1104    
	int x; 
                 
1990/03091    
	lock(r); 
1990/1104    
	x = ++r->ref; 
1990/03091    
	unlock(r); 
1990/1104    
	return x; 
1990/03091    
} 
                 
int 
decref(Ref *r) 
{ 
1990/1104    
	int x; 
                 
1990/03091    
	lock(r); 
1990/1104    
	x = --r->ref; 
1990/03091    
	unlock(r); 
1990/1104    
	return x; 
1990/03091    
} 
                 
void 
chaninit(void) 
{ 
	int i; 
	Chan *c; 
                 
	chanalloc.free = ialloc(conf.nchan*sizeof(Chan), 0); 
                 
	c = chanalloc.free; 
	for(i=0; i<conf.nchan-1; i++,c++){ 
		c->fid = i; 
		c->next = c+1; 
	} 
	c->next = 0; 
} 
                 
void 
chandevreset(void) 
{ 
	int i; 
                 
	for(i=0; i<strlen(devchar); i++) 
		(*devtab[i].reset)(); 
} 
                 
void 
chandevinit(void) 
{ 
	int i; 
                 
	for(i=0; i<strlen(devchar); i++) 
		(*devtab[i].init)(); 
} 
                 
Chan* 
newchan(void) 
{ 
	Chan *c; 
                 
loop: 
	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/03091    
		c->flag = 0; 
		c->ref = 1; 
		unlock(&chanalloc); 
1990/11062    
		c->dev = 0; 
1990/03091    
		c->offset = 0; 
		c->mnt = 0; 
		c->stream = 0; 
		c->mchan = 0; 
1990/11211    
		c->mqid = (Qid){0, 0}; 
1990/03091    
		return c; 
	} 
	unlock(&chanalloc); 
	print("no chans\n"); 
	if(u == 0) 
		panic("newchan"); 
	u->p->state = Wakeme; 
	alarm(1000, wakeme, u->p); 
	sched(); 
	goto loop; 
} 
                 
void 
close(Chan *c) 
{ 
1990/0914    
	if(c->flag & CFREE) 
		panic("close"); 
1990/03091    
	if(decref(c) == 0){ 
		if(!waserror()){ 
			(*devtab[c->type].close)(c); 
			poperror(); 
		} 
1990/0914    
		c->flag = CFREE; 
1990/03091    
		lock(&chanalloc); 
		c->next = chanalloc.free; 
		chanalloc.free = c; 
		unlock(&chanalloc); 
	} 
} 
                 
int 
1990/11211    
eqqid(Qid a, Qid b) 
1990/03091    
{ 
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/03091    
		return 0; 
1990/11211    
	if(!pathonly && a->qid.vers!=b->qid.vers) 
		return 0; 
1990/03091    
	if(a->type != b->type) 
		return 0; 
	if(a->dev != b->dev) 
		return 0; 
	return 1; 
} 
                 
/* 
 * omnt is locked.  return with nmnt locked. 
 */ 
Mount* 
mountsplit(Mount *omnt) 
{ 
	Mount *nmnt; 
                 
	nmnt = newmount(); 
	lock(nmnt); 
	nmnt->term = omnt->term; 
	nmnt->mountid = omnt->mountid; 
	nmnt->next = omnt->next; 
	if(nmnt->next) 
1990/0603    
		incref(nmnt->next); 
1990/03091    
	nmnt->c = omnt->c; 
	incref(nmnt->c); 
	omnt->ref--; 
	unlock(omnt); 
	return nmnt; 
} 
                 
int 
mount(Chan *new, Chan *old, int flag) 
{ 
	int i; 
	Mtab *mt, *mz; 
	Mount *mnt, *omnt, *nmnt, *pmnt; 
	Pgrp *pg; 
1990/0321    
	int islast; 
1990/03091    
                 
1990/11211    
	if(CHDIR & (old->qid.path^new->qid.path)) 
		error(Emount); 
	if((old->qid.path&CHDIR)==0 && (flag&MORDER)!=MREPL) 
		error(Emount); 
1990/03091    
                 
	mz = 0; 
1990/0321    
	islast = 0; 
	mnt = 0; 
1990/03091    
	pg = u->p->pgrp; 
	lock(pg); 
	if(waserror()){ 
1990/0321    
		if(mnt){ 
			mnt->c = 0;	/* caller will close new */ 
			closemount(mnt); 
		} 
1990/03091    
		unlock(pg); 
		nexterror(); 
	} 
	/* 
	 * Is old already in mount table? 
	 */ 
	mt = pg->mtab; 
	for(i=0; i<pg->nmtab; i++,mt++){ 
		if(mt->c==0 && mz==0) 
			mz = mt; 
1990/1122    
		else if(eqchan(mt->c, old, 1)){ 
1990/0321    
			mz = 0; 
1990/03091    
			goto Found; 
1990/0321    
		} 
1990/03091    
	} 
	if(mz == 0){ 
		if(i == conf.nmtab) 
1990/11211    
			error(Enomount); 
1990/03091    
		mz = &pg->mtab[i]; 
1990/0321    
		islast++; 
1990/03091    
	} 
	mz->mnt = 0; 
	mt = mz; 
                 
    Found: 
	new->flag = CMOUNT; 
	if(flag & MCREATE) 
		new->flag |= CCREATE; 
	mnt = newmount(); 
	mnt->c = new; 
                 
	switch(flag & MORDER){ 
	/* 
	 * These two always go at head of list 
	 */ 
	case MBEFORE: 
		if(mt->mnt == 0) 
1990/11211    
			error(Enotunion); 
1990/03091    
		/* fall through */ 
                 
	case MREPL: 
1990/0603    
		mnt->next = mt->mnt; 
1990/03091    
		mt->mnt = mnt; 
		if((flag&MORDER) == MBEFORE) 
			mnt->term = 0; 
1990/0603    
		else 
			mnt->term = 1; 
1990/03091    
		break; 
                 
	/* 
	 * This one never goes at head of list 
	 */ 
	case MAFTER: 
		if(mt->mnt == 0) 
1990/11211    
			error(Enotunion); 
1990/03091    
		omnt = mt->mnt; 
		pmnt = 0; 
		while(!omnt->term){ 
			lock(omnt); 
			if(omnt->ref > 1){ 
				omnt = mountsplit(omnt); 
				if(pmnt) 
					pmnt->next = omnt; 
				else 
					mt->mnt = omnt; 
			} 
			unlock(omnt); 
			nmnt = omnt->next; 
			if(nmnt == 0) 
				panic("MAFTER term"); 
			pmnt = omnt; 
			omnt = nmnt; 
		} 
		mnt->next = omnt->next; 
		omnt->next = mnt; 
		mnt->term = 1; 
		omnt->term = 0; 
		break; 
	} 
                 
	incref(new); 
1990/0321    
	if(mz){ 
		mz->c = old; 
1990/03091    
		incref(old); 
1990/0321    
	} 
	if(islast) 
		pg->nmtab++; 
1990/03091    
	unlock(pg); 
	poperror(); 
	return mnt->mountid; 
} 
                 
Chan* 
clone(Chan *c, Chan *nc) 
{ 
	return (*devtab[c->type].clone)(c, nc); 
} 
                 
Chan* 
domount(Chan *c) 
{ 
	int i; 
	ulong mntid; 
	Mtab *mt; 
	Mount *mnt; 
	Pgrp *pg; 
	Chan *nc, *mc; 
                 
	pg = u->p->pgrp; 
	/* 
	 * Is c in in mount table? 
	 */ 
	mt = pg->mtab; 
	for(i=0; i<pg->nmtab; i++,mt++) 
1990/1122    
		if(mt->c && eqchan(mt->c, c, 1)) 
1990/03091    
			goto Found; 
	/* 
	 * No; c is unaffected 
	 */ 
	return c; 
                 
	/* 
	 * Yes; move c through table 
	 */ 
    Found: 
	lock(pg); 
1990/1122    
	if(!eqchan(mt->c, c, 1)){	/* table changed underfoot */ 
1990/0321    
		pprint("domount: changed underfoot?\n"); 
1990/03091    
		unlock(pg); 
		return c; 
	} 
	mnt = mt->mnt; 
	mntid = mnt->mountid; 
	mc = mnt->c; 
	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; 
} 
                 
Chan* 
walk(Chan *ac, char *name, int domnt) 
{ 
	Mount *mnt; 
	int first = 1; 
	Chan *c = ac; 
	Chan *nc, *mc; 
	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){ 
			unlock(pg); 
			goto Notfound; 
		} 
		if(c->mountid != mnt->mountid){ 
1990/0820    
			pprint("walk: changed underfoot? '%s'\n", name); 
1990/03091    
			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/03091    
		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; 
		} 
		c = domount(c); 
		poperror(); 
	} 
                 
1990/03091    
	if(!first) 
		close(ac); 
                 
1990/0914    
                 
1990/03091    
	return c; 
                 
    Notfound: 
	if(!first) 
		close(c); 
	return 0; 
} 
                 
/* 
 * c is a mounted non-creatable directory.  find a creatable one. 
 */ 
Chan* 
createdir(Chan *c) 
{ 
	Mount *mnt; 
	Pgrp *pg = u->p->pgrp; 
	Chan *mc, *nc; 
                 
	lock(pg); 
	if(waserror()){ 
		unlock(pg); 
		nexterror(); 
	} 
	mnt = c->mnt; 
	if(c->mountid != mnt->mountid){ 
1990/0321    
		pprint("createdir: changed underfoot?\n"); 
1990/11211    
		error(Enocreate); 
1990/03091    
	} 
	do{ 
		if(mnt->term) 
1990/11211    
			error(Enocreate); 
1990/03091    
		mnt = mnt->next; 
	}while(!(mnt->c->flag&CCREATE)); 
	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; 
} 
                 
1990/0914    
void 
saveregisters(void) 
{ 
} 
                 
1990/03091    
/* 
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
 */ 
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; 
1990/03091    
                 
	if(name[0] == 0) 
1990/11211    
		error(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/03091    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1990/03091    
	if(name[0] == '/'){ 
		c = clone(u->slash, 0); 
		/* 
		 * Skip leading slashes. 
		 */ 
		name = skipslash(name); 
	}else if(name[0] == '#'){ 
		mntok = 0; 
1990/1006    
		if(name[1]=='M') 
1990/11211    
			error(Enonexist); 
1990/03091    
		t = devno(name[1], 1); 
		if(t == -1) 
1990/11211    
			error(Ebadsharp); 
1990/03091    
		name += 2; 
		if(*name == '/'){ 
			name = skipslash(name); 
			elem[0]=0; 
		}else 
			name = nextelem(name, elem); 
		c = (*devtab[t].attach)(elem); 
1990/0820    
	}else{ 
1990/03091    
		c = clone(u->dot, 0); 
1990/0820    
		name = skipslash(name);	/* eat leading ./ */ 
		if(*name == 0) 
			isdot = 1; 
	} 
1990/03091    
                 
	if(waserror()){ 
		close(c); 
		nexterror(); 
	} 
                 
	name = nextelem(name, elem); 
1990/0820    
                 
	if(mntok && !isdot) 
	if(!(amode==Amount && elem[0]==0))	/* don't domount on slash */ 
1990/03091    
		c = domount(c);			/* see case Atodir below */ 
                 
	/* 
	 * How to treat the last element of the name depends on the operation. 
	 * Therefore do all but the last element by the easy algorithm. 
	 */ 
	while(*name){ 
		if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
			error(Enonexist); 
1990/03091    
		c = nc; 
		name = nextelem(name, elem); 
	} 
1990/0820    
                 
1990/03091    
	/* 
	 * Last element; act according to type of access. 
	 */ 
                 
	switch(amode){ 
	case Aaccess: 
1990/0820    
		if(isdot) 
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/03091    
		break; 
                 
	case Atodir: 
		/* 
		 * 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) 
1990/11211    
			error(Enonexist); 
1990/03091    
		c = nc; 
1990/11211    
		if(!(c->qid.path & CHDIR)) 
			error(Enotdir); 
1990/03091    
		break; 
                 
	case Aopen: 
1990/0820    
		if(isdot) 
			c = domount(c); 
		else{ 
			if((nc=walk(c, elem, mntok)) == 0) 
1990/11211    
				error(Enonexist); 
1990/0820    
			c = nc; 
		} 
1990/03091    
	Open: 
1990/0914    
		saveregisters();	/* else error() in open has wrong value of c saved */ 
1990/03091    
		c = (*devtab[c->type].open)(c, omode); 
1990/08141    
		if(omode & OCEXEC) 
			c->flag |= CCEXEC; 
1990/03091    
		break; 
                 
	case Amount: 
		/* 
		 * When mounting on an already mounted upon directory, one wants 
		 * the second mount to be attached to the original directory, not 
		 * the replacement. 
		 */ 
		if((nc=walk(c, elem, 0)) == 0) 
1990/11211    
			error(Enonexist); 
1990/03091    
		c = nc; 
		break; 
                 
	case Acreate: 
1990/0820    
		if(isdot) 
1990/11211    
			error(Eisdir); 
1990/03091    
		if((nc=walk(c, elem, 1)) != 0){ 
			c = nc; 
			omode |= OTRUNC; 
			goto Open; 
		} 
		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/03091    
		break; 
                 
	default: 
		panic("unknown namec access %d\n", amode); 
	} 
	poperror(); 
	return c; 
} 
                 
/* 
 * name[0] is addressable. 
 */ 
char* 
skipslash(char *name) 
{ 
1990/0820    
    Again: 
1990/0821    
	while(*name == '/') 
1990/03091    
		name++; 
1990/0821    
	if(*name=='.' && (name[1]==0 || name[1]=='/')){ 
		name++; 
		goto Again; 
1990/0820    
	} 
1990/03091    
	return name; 
} 
                 
char isfrog[]={ 
	/*NUL*/	1, 1, 1, 1, 1, 1, 1, 1, 
	/*BKS*/	1, 1, 1, 1, 1, 1, 1, 1, 
	/*DLE*/	1, 1, 1, 1, 1, 1, 1, 1, 
	/*CAN*/	1, 1, 1, 1, 1, 1, 1, 1, 
	[' ']	1, 
	['/']	1, 
	[0x7f]	1, 
}; 
                 
/* 
 * 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. 
 */ 
char* 
nextelem(char *name, char *elem) 
{ 
	int i, user, c; 
	char *end, *e; 
                 
	if(*name == '/') 
1990/11211    
		error(Efilename); 
1990/0821    
	end = memchr(name, 0, NAMELEN); 
1990/03091    
	if(end == 0){ 
1990/0821    
		end = memchr(name, '/', NAMELEN); 
1990/03091    
		if(end == 0) 
1990/11211    
			error(Efilename); 
1990/03091    
	}else{ 
		e = memchr(name, '/', end-name); 
		if(e) 
			end = e; 
	} 
	while(name < end){ 
		c = *name++; 
		if((c&0x80) || isfrog[c]) 
1990/11211    
			error(Ebadchar); 
1990/03091    
		*elem++ = c; 
	} 
	*elem = 0; 
	return skipslash(name); 
} 
                 
void 
isdir(Chan *c) 
{ 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/03091    
		return; 
1990/11211    
	error(Enotdir); 
1990/03091    
} 


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