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

1999/0629/port/chan.c (diff list | history)

1999/0501/sys/src/9/port/chan.c:5,101999/0629/sys/src/9/port/chan.c:5,15 (short | long | prev | next)
1990/0227    
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
1999/0629    
enum 
{ 
	CNAMESLOP	= 20 
}; 
 
1992/0620    
struct 
{ 
1990/0227    
	Lock; 
1999/0501/sys/src/9/port/chan.c:13,181999/0629/sys/src/9/port/chan.c:18,25
1993/0501    
	Chan	*list; 
1990/0227    
}chanalloc; 
 
1999/0629    
#define SEP(c) ((c) == 0 || (c) == '/') 
 
1990/0227    
int 
incref(Ref *r) 
{ 
1999/0501/sys/src/9/port/chan.c:100,1121999/0629/sys/src/9/port/chan.c:107,179
1998/0829    
	c->uri = 0; 
1992/0620    
	c->aux = 0; 
	c->mchan = 0; 
1993/0501    
	c->path = 0; 
1993/1013    
	c->mcp = 0; 
1992/0620    
	c->mqid = (Qid){0, 0}; 
1999/0629    
	c->name = 0; 
1992/0620    
	return c; 
1990/0227    
} 
 
1999/0629    
static Ref ncname; 
 
Cname* 
newcname(char *s) 
{ 
	Cname *n; 
	int i; 
 
	n = smalloc(sizeof(Cname)); 
	i = strlen(s); 
	n->len = i; 
	n->alen = i+CNAMESLOP; 
	n->s = smalloc(n->alen); 
	memmove(n->s, s, i+1); 
	n->ref = 1; 
	incref(&ncname); 
	return n; 
} 
 
1997/1210    
void 
1999/0629    
cnameclose(Cname *n) 
{ 
	if(n == 0) 
		return; 
	if(decref(n)) 
		return; 
	decref(&ncname); 
	free(n->s); 
	free(n); 
} 
 
Cname* 
addelem(Cname *n, char *s) 
{ 
	int i, a; 
	char *t; 
	Cname *new; 
 
	if(n->ref > 1){ 
		/* copy on write */ 
		new = newcname(n->s); 
		cnameclose(n); 
		n = new; 
	} 
 
	i = strlen(s); 
	if(n->len+1+i+1 < n->alen){ 
		a = n->len+1+i+1 + CNAMESLOP; 
		t = smalloc(a); 
		memmove(t, n->s, n->len+1); 
		free(n->s); 
		n->s = t; 
		n->alen = a; 
	} 
	n->s[n->len++] = '/'; 
	memmove(n->s+n->len, s, i+1); 
	n->len += i; 
	return n; 
} 
 
void 
1992/0320    
chanfree(Chan *c) 
{ 
	c->flag = CFREE; 
1999/0501/sys/src/9/port/chan.c:121,1381999/0629/sys/src/9/port/chan.c:188,194
1998/0829    
		c->mh = nil; 
	} 
 
1993/0501    
	/* 
	 * Channel can be closed before a path is created or the last 
	 * channel in a mount which has already cleared its pt names 
	 */ 
1998/0416    
	if(c->path) { 
		if (c->path->ref <= 0) { 
1998/0512    
			char buf[100]; 
			ptpath(c->path, buf, sizeof(buf)); 
			print("decref %s\n", buf); 
		} 
1993/0501    
		decref(c->path); 
1998/0512    
	} 
1999/0629    
	cnameclose(c->name); 
1993/0501    
 
1992/0320    
	lock(&chanalloc); 
	c->next = chanalloc.free; 
1999/0501/sys/src/9/port/chan.c:333,3391999/0629/sys/src/9/port/chan.c:389,401
1990/0227    
Chan* 
1997/0327    
cclone(Chan *c, Chan *nc) 
1990/0227    
{ 
1997/0327    
	return devtab[c->type]->clone(c, nc); 
1999/0629    
	nc = devtab[c->type]->clone(c, nc); 
	if(nc != nil){ 
		nc->name = c->name; 
		if(c->name) 
			incref(c->name); 
	} 
	return nc; 
1990/0227    
} 
 
1991/0427    
Chan* 
1999/0501/sys/src/9/port/chan.c:411,4161999/0629/sys/src/9/port/chan.c:473,493
1991/1011    
} 
1990/0914    
 
1998/0224    
int 
1999/0629    
walkname(Chan **cp, char *name, int domnt) 
{ 
	Chan *c; 
 
	if(walk(cp, name, domnt) < 0) 
		return -1; 
	c = *cp; 
	if(c->name == nil) 
		c->name = newcname(name); 
	else 
		c->name = addelem(c->name, name); 
	return 0; 
} 
 
int 
1998/0224    
walk(Chan **cp, char *name, int domnt) 
1991/1011    
{ 
1998/0224    
	Chan *c, *ac; 
1999/0501/sys/src/9/port/chan.c:563,5681999/0629/sys/src/9/port/chan.c:640,695
1990/0914    
} 
 
1990/0227    
/* 
1999/0629    
 * In place, rewrite name to compress multiple /, eliminate ., and process .. 
 */ 
void 
cleanname(Cname *n, int offset) 
{ 
	char *p, *q, *dotdot, *name; 
	int rooted; 
 
	name = n->s+offset; 
	rooted = name[0] == '/'; 
 
	/* 
	 * invariants: 
	 *	p points at beginning of path element we're considering. 
	 *	q points just past the last path element we wrote (no slash). 
	 *	dotdot points just past the point where .. cannot backtrack 
	 *		any further (no slash). 
	 */ 
	p = q = dotdot = name+rooted; 
	while(*p) { 
		if(p[0] == '/')	/* null element */ 
			p++; 
		else if(p[0] == '.' && SEP(p[1])) 
			p += 1;	/* don't count the separator in case it is nul */ 
		else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) { 
			p += 2; 
			if(q > dotdot) {	/* can backtrack */ 
				while(--q > dotdot && *q != '/') 
					; 
			} else if(!rooted) {	/* ``/..'' ≡ ``/'', but ``./../'' ≡ ``..'' */ 
				if(q != name) 
					*q++ = '/'; 
				*q++ = '.'; 
				*q++ = '.'; 
				dotdot = q; 
			} 
		} else {	/* real path element */ 
			if(q != name+rooted) 
				*q++ = '/'; 
			while((*q = *p) != '/' && *q != 0) 
				p++, q++; 
		} 
	} 
	if(q == name)	/* empty string is really ``.'' */ 
		*q++ = '.'; 
	*q = 0; 
	n->len = (q-name) + offset; 
} 
 
/* 
1990/0227    
 * Turn a name into a channel. 
 * &name[0] is known to be a valid address.  It may be a kernel address. 
 */ 
1999/0501/sys/src/9/port/chan.c:572,5781999/0629/sys/src/9/port/chan.c:699,706
1992/1217    
	Rune r; 
1990/0821    
	char *p; 
1992/0711    
	char *elem; 
1993/0501    
	int t, n; 
1999/0629    
	Cname *cname; 
	int t, n, newname; 
1993/0501    
	int mntok, isdot; 
1998/0224    
	Chan *c, *cc; 
1991/1105    
	char createerr[ERRLEN]; 
1999/0501/sys/src/9/port/chan.c:589,6031999/0629/sys/src/9/port/chan.c:717,740
1990/0821    
		} 
	} 
 
1999/0629    
	newname = 1; 
	cname = nil; 
	if(waserror()){ 
		cnameclose(cname); 
		nexterror(); 
	} 
 
1993/0501    
	elem = up->elem; 
1990/0227    
	mntok = 1; 
1990/0820    
	isdot = 0; 
1993/0501    
	switch(name[0]) { 
	case '/': 
1997/0327    
		c = cclone(up->slash, 0); 
1999/0629    
		cname = newcname(name);	/* save this before advancing */ 
1990/0227    
		name = skipslash(name); 
1999/0629    
		c = cclone(up->slash, 0); 
1993/0501    
		break; 
	case '#': 
1999/0629    
		cname = newcname(name);	/* save this before advancing */ 
1990/0227    
		mntok = 0; 
1993/0501    
		elem[0] = 0; 
		n = 0; 
1999/0501/sys/src/9/port/chan.c:611,6161999/0629/sys/src/9/port/chan.c:748,755
1995/0208    
				name = skipslash(name); 
				if(*name) 
					error(Efilename); 
1999/0629    
				poperror(); 
				cnameclose(cname); 
1995/0208    
				return c; 
			} 
			else { 
1999/0501/sys/src/9/port/chan.c:627,6321999/0629/sys/src/9/port/chan.c:766,773
1993/0501    
		name = skipslash(name); 
		break; 
	default: 
1999/0629    
		cname = newcname(up->dot->name->s); 
		cname = addelem(cname, name); 
1997/0327    
		c = cclone(up->dot, 0); 
1993/0501    
		name = skipslash(name); 
1990/0820    
		if(*name == 0) 
1999/0501/sys/src/9/port/chan.c:688,6941999/0629/sys/src/9/port/chan.c:829,838
1993/1017    
		if(omode == OEXEC) 
1993/1018    
			c->flag &= ~CCACHE; 
1998/0512    
 
1999/0629    
		cc = c; 
1999/0122    
		c = devtab[c->type]->open(c, omode&~OCEXEC); 
1999/0629    
		if(cc != c) 
			newname = 0; 
1993/1018    
 
1990/08141    
		if(omode & OCEXEC) 
1991/0427    
			c->flag |= CCEXEC; 
1999/0501/sys/src/9/port/chan.c:760,7651999/0629/sys/src/9/port/chan.c:904,923
1990/0227    
	default: 
		panic("unknown namec access %d\n", amode); 
	} 
1999/0629    
 
	poperror(); 
 
	/* peculiar workaround for #/ */ 
	if(newname){ 
		if(cname->s[0]=='#' && cname->s[1]=='/') 
			cleanname(cname, 2); 
		else 
			cleanname(cname, 0); 
		cnameclose(c->name); 
		c->name = cname; 
	}else 
		cnameclose(cname); 
 
1990/0227    
	poperror(); 
1991/0427    
	return c; 
1990/0227    
} 


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