⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
#include	"u.h"#include	"lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"error.h"int chandebug=0;		/* toggled by sysr1 */#define DBG if(chandebug)iprintenum{	PATHSLOP	= 20,	PATHMSLOP	= 20,};struct{	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;};#define SEP(c) ((c) == 0 || (c) == '/')/*static*/ voiddumpmount(void)		/* DEBUGGING */{	Pgrp *pg;	Mount *t;	Mhead **h, **he, *f;	if(up == nil){		print("no process for dumpmount\n");		return;	}	pg = up->pgrp;	if(pg == nil){		print("no pgrp for dumpmount\n");		return;	}	rlock(&pg->ns);	if(waserror()){		runlock(&pg->ns);		nexterror();	}	he = &pg->mnthash[MNTHASH];	for(h = pg->mnthash; h < he; h++){		for(f = *h; f; f = f->hash){			print("head: %p: %s 0x%llux.%lud %C %lud -> \n", f,				f->from->path->s, f->from->qid.path,				f->from->qid.vers, devtab[f->from->type]->dc,				f->from->dev);			for(t = f->mount; t; t = t->next)				print("\t%p: %s (umh %p) (path %.8llux dev %C %lud)\n", t, t->to->path->s, t->to->umh, t->to->qid.path, devtab[t->to->type]->dc, t->to->dev);		}	}	poperror();	runlock(&pg->ns);}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';}longincref(Ref *r){	long x;	lock(&r->lk);	x = ++r->ref;	unlock(&r->lk);	return x;}longdecref(Ref *r){	long x;	lock(&r->lk);	x = --r->ref;	unlock(&r->lk);	if(x < 0)		panic("decref pc=0x%lux", 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+1 <= ns){		memmove(s, t, nt+1);		return;	}	/* too long */	if(ns < 4){		/* but very short! */		strncpy(s, t, ns);		return;	}	/* truncate with ... at character boundary (very rare case) */	memmove(s, t, ns-4);	ns -= 4;	s[ns] = '\0';	/* 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)+1;	/* if it's a user, we can wait for memory; if not, something's very wrong */	if(up){		t = smalloc(n);		setmalloctag(t, getcallerpc(&p));	}else{		t = malloc(n);		if(t == nil)			panic("kstrdup: no memory");	}	memmove(t, s, n);	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 != 0)		chanalloc.free = c->next;	unlock(&chanalloc.lk);	if(c == nil){		c = smalloc(sizeof(Chan));		lock(&chanalloc.lk);		c->fid = ++chanalloc.fid;		c->link = chanalloc.list;		chanalloc.list = c;		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 = 0;	c->uri = 0;	c->dri = 0;	c->aux = 0;	c->mchan = 0;	c->mcp = 0;	c->mux = 0;	memset(&c->mqid, 0, sizeof(c->mqid));	c->path = 0;	c->ismtpt = 0;		return c;}Ref npath;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;	incref(&npath);	/*	 * 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, '/') && strcmp(s, "#/") != 0 && strcmp(s, "/") != 0)		print("newpath: %s from %lux\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;	incref(&npath);	DBG("copypath %s %p => %p\n", p->s, p, pp);		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])			incref(&pp->mtpt[i]->ref);	}	return pp;}voidpathclose(Path *p){	int i;		if(p == nil)		return;//XXX	DBG("pathclose %p %s ref=%ld =>", p, p->s, p->ref.ref);	for(i=0; i<p->mlen; i++)		DBG(" %p", p->mtpt[i]);	DBG("\n");	if(decref(&p->ref))		return;	decref(&npath);	free(p->s);	for(i=0; i<p->mlen; i++)		if(p->mtpt[i])			cclose(p->mtpt[i]);	free(p->mtpt);	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);	if(p->len+1+i+1 > p->alen){		a = p->len+1+i+1 + 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);		DBG("addelem %s .. => rm %p\n", p->s, p->mtpt[p->mlen-1]);		if(p->mlen>1 && (c = p->mtpt[--p->mlen])){			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;		}		DBG("addelem %s %s => add %p\n", p->s, s, from);		p->mtpt[p->mlen++] = from;		if(from)			incref(&from->ref);	}	return p;}voidchanfree(Chan *c){	c->flag = CFREE;	if(c->dirrock != nil){		free(c->dirrock);		c->dirrock = 0;		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->flag&CFREE)		panic("cclose %lux", getcallerpc(&c));	DBG("cclose %p name=%s ref=%ld\n", c, c->path->s, c->ref.ref);	if(decref(&c->ref))		return;	if(!waserror()){		devtab[c->type]->close(c);		poperror();	}	chanfree(c);}/* * Queue a chan to be closed by one of the clunk procs. */struct {	Chan *head;	Chan *tail;	int nqueued;	int nclosed;	Lock l;	QLock q;	Rendez r;} clunkq;void closeproc(void*);voidccloseq(Chan *c){	if(c->flag&CFREE)		panic("cclose %lux", getcallerpc(&c));	DBG("ccloseq %p name=%s ref=%ld\n", c, c->path->s, c->ref.ref);	if(decref(&c->ref))		return;	lock(&clunkq.l);	clunkq.nqueued++;	c->next = nil;	if(clunkq.head)		clunkq.tail->next = c;	else		clunkq.head = c;	clunkq.tail = c;	unlock(&clunkq.l);	if(!wakeup(&clunkq.r))		kproc("closeproc", closeproc, nil);	}static intclunkwork(void *v){	return clunkq.head != nil;}voidcloseproc(void *v){	Chan *c;	for(;;){		qlock(&clunkq.q);		if(clunkq.head == nil){			if(!waserror()){				tsleep(&clunkq.r, clunkwork, nil, 5000);				poperror();			}			if(clunkq.head == nil){				qunlock(&clunkq.q);				pexit("no work", 1);			}		}		lock(&clunkq.l);		c = clunkq.head;		clunkq.head = c->next;		clunkq.nclosed++;		unlock(&clunkq.l);		qunlock(&clunkq.q);		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;	}	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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -