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

📄 devsd.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
			return r;		}		i -= Qpart;		if(unit->part == nil || i >= unit->npart){			qunlock(&unit->ctl);			decref(&sdev->r);			break;		}		pp = &unit->part[i];		if(!pp->valid){			qunlock(&unit->ctl);			decref(&sdev->r);			return 0;		}		l = (pp->end - pp->start) * unit->secsize;		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), i, Qpart),			unit->vers+pp->vers, QTFILE);		if(emptystr(pp->perm.user))			kstrdup(&pp->perm.user, eve);		devdir(c, q, pp->perm.name, l, pp->perm.user, pp->perm.perm, dp);		qunlock(&unit->ctl);		decref(&sdev->r);		return 1;	case Qraw:	case Qctl:	case Qpart:		if((sdev = sdgetdev(DEV(c->qid))) == nil){			devdir(c, q, "unavailable", 0, eve, 0, dp);			return 1;		}		unit = sdev->unit[UNIT(c->qid)];		qlock(&unit->ctl);		r = sd2gen(c, TYPE(c->qid), dp);		qunlock(&unit->ctl);		decref(&sdev->r);		return r;	case Qtopctl:		return sd1gen(c, TYPE(c->qid), dp);	default:		break;	}	return -1;}static Chan*sdattach(char* spec){	Chan *c;	char *p;	SDev *sdev;	int idno, subno;	if(*spec == '\0'){		c = devattach(sddevtab.dc, spec);		mkqid(&c->qid, QID(0, 0, 0, Qtopdir), 0, QTDIR);		return c;	}	if(spec[0] != 's' || spec[1] != 'd')		error(Ebadspec);	idno = spec[2];	subno = strtol(&spec[3], &p, 0);	if(p == &spec[3])		error(Ebadspec);	if((sdev=sdgetdev(idno)) == nil)		error(Enonexist);	if(sdgetunit(sdev, subno) == nil){		decref(&sdev->r);		error(Enonexist);	}	c = devattach(sddevtab.dc, spec);	mkqid(&c->qid, QID(sdev->idno, subno, 0, Qunitdir), 0, QTDIR);	c->dev = (sdev->idno << UnitLOG) + subno;	decref(&sdev->r);	return c;}static Walkqid*sdwalk(Chan* c, Chan* nc, char** name, int nname){	return devwalk(c, nc, name, nname, nil, 0, sdgen);}static intsdstat(Chan* c, uchar* db, int n){	return devstat(c, db, n, nil, 0, sdgen);}static Chan*sdopen(Chan* c, int omode){	SDpart *pp;	SDunit *unit;	SDev *sdev;	uchar tp;	c = devopen(c, omode, 0, 0, sdgen);	if((tp = TYPE(c->qid)) != Qctl && tp != Qraw && tp != Qpart)		return c;	sdev = sdgetdev(DEV(c->qid));	if(sdev == nil)		error(Enonexist);	unit = sdev->unit[UNIT(c->qid)];	switch(TYPE(c->qid)){	case Qctl:		c->qid.vers = unit->vers;		break;	case Qraw:		c->qid.vers = unit->vers;		if(tas(&unit->rawinuse) != 0){			c->flag &= ~COPEN;			decref(&sdev->r);			error(Einuse);		}		unit->state = Rawcmd;		break;	case Qpart:		qlock(&unit->ctl);		if(waserror()){			qunlock(&unit->ctl);			c->flag &= ~COPEN;			decref(&sdev->r);			nexterror();		}		pp = &unit->part[PART(c->qid)];		c->qid.vers = unit->vers+pp->vers;		qunlock(&unit->ctl);		poperror();		break;	}	decref(&sdev->r);	return c;}static voidsdclose(Chan* c){	SDunit *unit;	SDev *sdev;	if(c->qid.type & QTDIR)		return;	if(!(c->flag & COPEN))		return;	switch(TYPE(c->qid)){	default:		break;	case Qraw:		sdev = sdgetdev(DEV(c->qid));		if(sdev){			unit = sdev->unit[UNIT(c->qid)];			unit->rawinuse = 0;			decref(&sdev->r);		}		break;	}}static longsdbio(Chan* c, int write, char* a, long len, uvlong off){	int nchange;	long l;	uchar *b;	SDpart *pp;	SDunit *unit;	SDev *sdev;	ulong max, nb, offset;	uvlong bno;	sdev = sdgetdev(DEV(c->qid));	if(sdev == nil){		decref(&sdev->r);		error(Enonexist);	}	unit = sdev->unit[UNIT(c->qid)];	if(unit == nil)		error(Enonexist);	nchange = 0;	qlock(&unit->ctl);	while(waserror()){		/* notification of media change; go around again */		if(strcmp(up->errstr, Eio) == 0 && unit->sectors == 0 && nchange++ == 0){			sdinitpart(unit);			continue;		}		/* other errors; give up */		qunlock(&unit->ctl);		decref(&sdev->r);		nexterror();	}	pp = &unit->part[PART(c->qid)];	if(unit->vers+pp->vers != c->qid.vers)		error(Echange);	/*	 * Check the request is within bounds.	 * Removeable drives are locked throughout the I/O	 * in case the media changes unexpectedly.	 * Non-removeable drives are not locked during the I/O	 * to allow the hardware to optimise if it can; this is	 * a little fast and loose.	 * It's assumed that non-removeable media parameters	 * (sectors, secsize) can't change once the drive has	 * been brought online.	 */	bno = (off/unit->secsize) + pp->start;	nb = ((off+len+unit->secsize-1)/unit->secsize) + pp->start - bno;	max = SDmaxio/unit->secsize;	if(nb > max)		nb = max;	if(bno+nb > pp->end)		nb = pp->end - bno;	if(bno >= pp->end || nb == 0){		if(write)			error(Eio);		qunlock(&unit->ctl);		decref(&sdev->r);		poperror();		return 0;	}	if(!(unit->inquiry[1] & 0x80)){		qunlock(&unit->ctl);		poperror();	}	b = sdmalloc(nb*unit->secsize);	if(b == nil)		error(Enomem);	if(waserror()){		sdfree(b);		if(!(unit->inquiry[1] & 0x80))			decref(&sdev->r);		/* gadverdamme! */		nexterror();	}	offset = off%unit->secsize;	if(offset+len > nb*unit->secsize)		len = nb*unit->secsize - offset;	if(write){		if(offset || (len%unit->secsize)){			l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);			if(l < 0)				error(Eio);			if(l < (nb*unit->secsize)){				nb = l/unit->secsize;				l = nb*unit->secsize - offset;				if(len > l)					len = l;			}		}		memmove(b+offset, a, len);		l = unit->dev->ifc->bio(unit, 0, 1, b, nb, bno);		if(l < 0)			error(Eio);		if(l < offset)			len = 0;		else if(len > l - offset)			len = l - offset;	}	else{		l = unit->dev->ifc->bio(unit, 0, 0, b, nb, bno);		if(l < 0)			error(Eio);		if(l < offset)			len = 0;		else if(len > l - offset)			len = l - offset;		memmove(a, b+offset, len);	}	sdfree(b);	poperror();	if(unit->inquiry[1] & 0x80){		qunlock(&unit->ctl);		poperror();	}	decref(&sdev->r);	return len;}static longsdrio(SDreq* r, void* a, long n){	void *data;	if(n >= SDmaxio || n < 0)		error(Etoobig);	data = nil;	if(n){		if((data = sdmalloc(n)) == nil)			error(Enomem);		if(r->write)			memmove(data, a, n);	}	r->data = data;	r->dlen = n;	if(waserror()){		sdfree(data);		r->data = nil;		nexterror();	}	if(r->unit->dev->ifc->rio(r) != SDok)		error(Eio);	if(!r->write && r->rlen > 0)		memmove(a, data, r->rlen);	sdfree(data);	r->data = nil;	poperror();	return r->rlen;}/* * SCSI simulation for non-SCSI devices */intsdsetsense(SDreq *r, int status, int key, int asc, int ascq){	int len;	SDunit *unit;	unit = r->unit;	unit->sense[2] = key;	unit->sense[12] = asc;	unit->sense[13] = ascq;	r->status = status;	if(status == SDcheck && !(r->flags & SDnosense)){		/* request sense case from sdfakescsi */		len = sizeof unit->sense;		if(len > sizeof r->sense-1)			len = sizeof r->sense-1;		memmove(r->sense, unit->sense, len);		unit->sense[2] = 0;		unit->sense[12] = 0;		unit->sense[13] = 0;		r->flags |= SDvalidsense;		return SDok;	}	return status;}intsdmodesense(SDreq *r, uchar *cmd, void *info, int ilen){	int len;	uchar *data;	/*	 * Fake a vendor-specific request with page code 0,	 * return the drive info.	 */	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)		return sdsetsense(r, SDcheck, 0x05, 0x24, 0);	len = (cmd[7]<<8)|cmd[8];	if(len == 0)		return SDok;	if(len < 8+ilen)		return sdsetsense(r, SDcheck, 0x05, 0x1A, 0);	if(r->data == nil || r->dlen < len)		return sdsetsense(r, SDcheck, 0x05, 0x20, 1);	data = r->data;	memset(data, 0, 8);	data[0] = ilen>>8;	data[1] = ilen;	if(ilen)		memmove(data+8, info, ilen);	r->rlen = 8+ilen;	return sdsetsense(r, SDok, 0, 0, 0);}intsdfakescsi(SDreq *r, void *info, int ilen){	uchar *cmd, *p;	uvlong len;	SDunit *unit;	cmd = r->cmd;	r->rlen = 0;	unit = r->unit;	/*	 * Rewrite read(6)/write(6) into read(10)/write(10).	 */	switch(cmd[0]){	case 0x08:	/* read */	case 0x0A:	/* write */		cmd[9] = 0;		cmd[8] = cmd[4];		cmd[7] = 0;		cmd[6] = 0;		cmd[5] = cmd[3];		cmd[4] = cmd[2];		cmd[3] = cmd[1] & 0x0F;		cmd[2] = 0;		cmd[1] &= 0xE0;		cmd[0] |= 0x20;		break;	}	/*	 * Map SCSI commands into ATA commands for discs.	 * Fail any command with a LUN except INQUIRY which	 * will return 'logical unit not supported'.	 */	if((cmd[1]>>5) && cmd[0] != 0x12)		return sdsetsense(r, SDcheck, 0x05, 0x25, 0);	switch(cmd[0]){	default:		return sdsetsense(r, SDcheck, 0x05, 0x20, 0);	case 0x00:	/* test unit ready */		return sdsetsense(r, SDok, 0, 0, 0);	case 0x03:	/* request sense */		if(cmd[4] < sizeof unit->sense)			len = cmd[4];		else			len = sizeof unit->sense;		if(r->data && r->dlen >= len){			memmove(r->data, unit->sense, len);			r->rlen = len;		}		return sdsetsense(r, SDok, 0, 0, 0);	case 0x12:	/* inquiry */		if(cmd[4] < sizeof unit->inquiry)			len = cmd[4];		else			len = sizeof unit->inquiry;		if(r->data && r->dlen >= len){			memmove(r->data, unit->inquiry, len);			r->rlen = len;		}		return sdsetsense(r, SDok, 0, 0, 0);	case 0x1B:	/* start/stop unit */		/*		 * nop for now, can use power management later.		 */		return sdsetsense(r, SDok, 0, 0, 0);	case 0x25:	/* read capacity */		if((cmd[1] & 0x01) || cmd[2] || cmd[3])			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);		if(r->data == nil || r->dlen < 8)			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);		/*		 * Read capacity returns the LBA of the last sector.		 */		len = unit->sectors - 1;		p = r->data;		*p++ = len>>24;		*p++ = len>>16;		*p++ = len>>8;		*p++ = len;		len = 512;		*p++ = len>>24;		*p++ = len>>16;		*p++ = len>>8;		*p++ = len;		r->rlen = p - (uchar*)r->data;		return sdsetsense(r, SDok, 0, 0, 0);	case 0x9E:	/* long read capacity */		if((cmd[1] & 0x01) || cmd[2] || cmd[3])			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);		if(r->data == nil || r->dlen < 8)			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);		/*		 * Read capcity returns the LBA of the last sector.		 */		len = unit->sectors - 1;		p = r->data;		*p++ = len>>56;		*p++ = len>>48;		*p++ = len>>40;		*p++ = len>>32;		*p++ = len>>24;		*p++ = len>>16;		*p++ = len>>8;		*p++ = len;		len = 512;		*p++ = len>>24;		*p++ = len>>16;		*p++ = len>>8;		*p++ = len;		r->rlen = p - (uchar*)r->data;		return sdsetsense(r, SDok, 0, 0, 0);	case 0x5A:	/* mode sense */		return sdmodesense(r, cmd, info, ilen);	case 0x28:	/* read */	case 0x2A:	/* write */	case 0x88:	/* read16 */	case 0x8a:	/* write16 */		return SDnostatus;	}}static longsdread(Chan *c, void *a, long n, vlong off){	char *p, *e, *buf;	SDpart *pp;	SDunit *unit;	SDev *sdev;	ulong offset;	int i, l, m, status;	offset = off;	switch(TYPE(c->qid)){	default:		error(Eperm);	case Qtopctl:		m = 64*1024;	/* room for register dumps */		p = buf = malloc(m);		assert(p);		e = p + m;		qlock(&devslock);		for(i = 0; i < nelem(devs); i++){			sdev = devs[i];			if(sdev && sdev->ifc->rtopctl)				p = sdev->ifc->rtopctl(sdev, p, e);		}		qunlock(&devslock);		n = readstr(off, a, n, buf);		free(buf);

⌨️ 快捷键说明

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