1634 lines · 31.9 KB · C
RawDownload
#include	"u.h"#include	"lib.h"#include	"dat.h"#include	"fns.h"#include	"error.h" enum{	PATHSLOP	= 20,	PATHMSLOP	= 20,}; static struct Chanalloc{	Lock	lk;	int	fid;	Chan	*free;	Chan	*list;}chanalloc; typedef struct Elemlist Elemlist; struct Elemlist{	char	*aname;	/* original name */	char	*name;	/* copy of name, so '/' can be overwritten */	int	nelems;	char	**elems;	int	*off;	int	mustbedir;	int	nerror;	int	prefix;}; char*chanpath(Chan *c){	if(c == nil)		return "<nil chan>";	if(c->path == nil)		return "<nil path>";	if(c->path->s == nil)		return "<nil path.s>";	return c->path->s;} intisdotdot(char *p){	return p[0]=='.' && p[1]=='.' && p[2]=='\0';} intincref(Ref *r){	int x;	lock(&r->lk);	x = ++r->ref;	unlock(&r->lk);	return x;} intdecref(Ref *r){	int x;	lock(&r->lk);	x = --r->ref;	unlock(&r->lk);	if(x < 0)		panic("decref, pc=0x%p", getcallerpc(&r));	return x;} /* * Rather than strncpy, which zeros the rest of the buffer, kstrcpy * truncates if necessary, always zero terminates, does not zero fill, * and puts ... at the end of the string if it's too long.  Usually used to * save a string in up->genbuf; */voidkstrcpy(char *s, char *t, int ns){	int nt; 	nt = strlen(t);	if(nt < ns){		memmove(s, t, nt);		s[nt] = '\0';		return;	}	/* too long, truncate */	nt = ns-1;	memmove(s, t, nt);	s[nt] = '\0';	/* append ... if there is space */	ns -= 4;	if(ns < 0)		return;	/* look for first byte of UTF-8 sequence by skipping continuation bytes */	while(ns>0 && (s[--ns]&0xC0)==0x80)		;	strcpy(s+ns, "...");} intemptystr(char *s){	if(s == nil)		return 1;	if(s[0] == '\0')		return 1;	return 0;} /* * Atomically replace *p with copy of s */voidkstrdup(char **p, char *s){	int n;	char *t, *prev; 	n = strlen(s);	/* if it's a user, we can wait for memory; if not, something's very wrong */	if(up != nil)		t = smalloc(n+1);	else{		t = malloc(n+1);		if(t == nil)			panic("kstrdup: no memory");	}	setmalloctag(t, getcallerpc(&p));	memmove(t, s, n);	t[n] = '\0';	prev = *p;	*p = t;	free(prev);} voidchandevreset(void){	int i; 	for(i=0; devtab[i] != nil; i++)		devtab[i]->reset();} voidchandevinit(void){	int i; 	for(i=0; devtab[i] != nil; i++)		devtab[i]->init();} voidchandevshutdown(void){	int i;		/* shutdown in reverse order */	for(i=0; devtab[i] != nil; i++)		;	for(i--; i >= 0; i--)		devtab[i]->shutdown();} Chan*newchan(void){	Chan *c; 	lock(&chanalloc.lk);	c = chanalloc.free;	if(c != nil){		chanalloc.free = c->next;		c->next = nil;	} else {		unlock(&chanalloc.lk);		c = smalloc(sizeof(Chan));		lock(&chanalloc.lk);		c->link = chanalloc.list;		chanalloc.list = c;	}	if(c->fid == 0)		c->fid = ++chanalloc.fid;	unlock(&chanalloc.lk); 	/* if you get an error before associating with a dev,	   close calls rootclose, a nop */	c->type = 0;	c->flag = 0;	c->ref.ref = 1;	c->dev = 0;	c->offset = 0;	c->devoffset = 0;	c->iounit = 0;	c->umh = nil;	c->umc = nil;	c->uri = 0;	c->dri = 0;	c->dirrock = nil;	c->nrock = 0;	c->mrock = 0;	c->ismtpt = 0;	c->mux = nil;	c->aux = nil;	c->mchan = nil;	memset(&c->mqid, 0, sizeof(c->mqid));	c->path = nil; 	return c;} Path*newpath(char *s){	int i;	Path *p; 	p = smalloc(sizeof(Path));	i = strlen(s);	p->len = i;	p->alen = i+PATHSLOP;	p->s = smalloc(p->alen);	memmove(p->s, s, i+1);	p->ref.ref = 1; 	/*	 * Cannot use newpath for arbitrary names because the mtpt 	 * array will not be populated correctly.  The names #/ and / are	 * allowed, but other names with / in them draw warnings.	 */	if(strchr(s, '/') != nil && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0)		print("newpath: %s from %#p\n", s, getcallerpc(&s)); 	p->mlen = 1;	p->malen = PATHMSLOP;	p->mtpt = smalloc(p->malen*sizeof p->mtpt[0]);	return p;} static Path*copypath(Path *p){	int i;	Path *pp;		pp = smalloc(sizeof(Path));	pp->ref.ref = 1;		pp->len = p->len;	pp->alen = p->alen;	pp->s = smalloc(p->alen);	memmove(pp->s, p->s, p->len+1);		pp->mlen = p->mlen;	pp->malen = p->malen;	pp->mtpt = smalloc(p->malen*sizeof pp->mtpt[0]);	for(i=0; i<pp->mlen; i++){		pp->mtpt[i] = p->mtpt[i];		if(pp->mtpt[i] != nil)			incref(&pp->mtpt[i]->ref);	} 	return pp;} voidpathclose(Path *p){	int i; 	if(p == nil || decref(&p->ref))		return;	for(i=0; i<p->mlen; i++)		if(p->mtpt[i] != nil)			cclose(p->mtpt[i]);	free(p->mtpt);	free(p->s);	free(p);} /* * In place, rewrite name to compress multiple /, eliminate ., and process .. * (Really only called to remove a trailing .. that has been added. * Otherwise would need to update n->mtpt as well.) */static voidfixdotdotname(Path *p){	char *r; 	if(p->s[0] == '#'){		r = strchr(p->s, '/');		if(r == nil)			return;		cleanname(r); 		/*		 * The correct name is #i rather than #i/,		 * but the correct name of #/ is #/.		 */		if(strcmp(r, "/")==0 && p->s[1] != '/')			*r = '\0';	}else		cleanname(p->s);	p->len = strlen(p->s);} static Path*uniquepath(Path *p){	Path *new;		if(p->ref.ref > 1){		/* copy on write */		new = copypath(p);		pathclose(p);		p = new;	}	return p;} static Path*addelem(Path *p, char *s, Chan *from){	char *t;	int a, i;	Chan *c, **tt; 	if(s[0]=='.' && s[1]=='\0')		return p; 	p = uniquepath(p); 	i = strlen(s);	a = p->len+1+i+1;	if(a > p->alen){		a += PATHSLOP;		t = smalloc(a);		memmove(t, p->s, p->len+1);		free(p->s);		p->s = t;		p->alen = a;	}	/* don't insert extra slash if one is present */	if(p->len>0 && p->s[p->len-1]!='/' && s[0]!='/')		p->s[p->len++] = '/';	memmove(p->s+p->len, s, i+1);	p->len += i;	if(isdotdot(s)){		fixdotdotname(p);		if(p->mlen > 1 && (c = p->mtpt[--p->mlen]) != nil){			p->mtpt[p->mlen] = nil;			cclose(c);		}	}else{		if(p->mlen >= p->malen){			p->malen = p->mlen+1+PATHMSLOP;			tt = smalloc(p->malen*sizeof tt[0]);			memmove(tt, p->mtpt, p->mlen*sizeof tt[0]);			free(p->mtpt);			p->mtpt = tt;		}		p->mtpt[p->mlen++] = from;		if(from != nil)			incref(&from->ref);	}	return p;} voidchanfree(Chan *c){	c->flag = CFREE; 	if(c->dirrock != nil){		free(c->dirrock);		c->dirrock = nil;		c->nrock = 0;		c->mrock = 0;	}	if(c->umh != nil){		putmhead(c->umh);		c->umh = nil;	}	if(c->umc != nil){		cclose(c->umc);		c->umc = nil;	}	if(c->mux != nil){		muxclose(c->mux);		c->mux = nil;	}	if(c->mchan != nil){		cclose(c->mchan);		c->mchan = nil;	} 	pathclose(c->path);	c->path = nil; 	lock(&chanalloc.lk);	c->next = chanalloc.free;	chanalloc.free = c;	unlock(&chanalloc.lk);} voidcclose(Chan *c){	if(c == nil || c->ref.ref < 1 || c->flag&CFREE)		panic("cclose %#p", getcallerpc(&c)); 	if(decref(&c->ref))		return; 	if(!waserror()){		devtab[c->type]->close(c);		poperror();	}	chanfree(c);} /* * Make sure we have the only copy of c.  (Copy on write.) */Chan*cunique(Chan *c){	Chan *nc; 	if(c->ref.ref != 1){		nc = cclone(c);		cclose(c);		c = nc;	} 	if(c->umh != nil){	//BUG		print("cunique umh != nil from %#p\n", getcallerpc(&c));		putmhead(c->umh);		c->umh = nil;	} 	return c;} inteqqid(Qid a, Qid b){	return a.path==b.path && a.vers==b.vers;} inteqchan(Chan *a, Chan *b, int skipvers){	if(a->qid.path != b->qid.path)		return 0;	if(!skipvers && a->qid.vers!=b->qid.vers)		return 0;	if(a->type != b->type)		return 0;	if(a->dev != b->dev)		return 0;	return 1;} inteqchantdqid(Chan *a, int type, int dev, Qid qid, int skipvers){	if(a->qid.path != qid.path)		return 0;	if(!skipvers && a->qid.vers!=qid.vers)		return 0;	if(a->type != type)		return 0;	if(a->dev != dev)		return 0;	return 1;} Mhead*newmhead(Chan *from){	Mhead *mh; 	mh = smalloc(sizeof(Mhead));	mh->ref.ref = 1;	mh->from = from;	incref(&from->ref);	return mh;} /* * This is necessary because there are many

Lines 1–500 of 1634.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t