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

📄 devsd.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Storage Device. */#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "ureg.h"#include "error.h"#include "sd.h"extern Dev sddevtab;extern SDifc* sdifc[];static char Echange[] = "media or partition has changed";static char devletters[] = "0123456789"	"abcdefghijklmnopqrstuvwxyz"	"ABCDEFGHIJKLMNOPQRSTUVWXYZ";static SDev *devs[sizeof devletters-1];static QLock devslock;enum {	Rawcmd,	Rawdata,	Rawstatus,};enum {	Qtopdir		= 1,		/* top level directory */	Qtopbase,	Qtopctl		 = Qtopbase,	Qunitdir,			/* directory per unit */	Qunitbase,	Qctl		= Qunitbase,	Qraw,	Qpart,	TypeLOG		= 4,	NType		= (1<<TypeLOG),	TypeMASK	= (NType-1),	TypeSHIFT	= 0,	PartLOG		= 8,	NPart		= (1<<PartLOG),	PartMASK	= (NPart-1),	PartSHIFT	= TypeLOG,	UnitLOG		= 8,	NUnit		= (1<<UnitLOG),	UnitMASK	= (NUnit-1),	UnitSHIFT	= (PartLOG+TypeLOG),	DevLOG		= 8,	NDev		= (1 << DevLOG),	DevMASK		= (NDev-1),	DevSHIFT	 = (UnitLOG+PartLOG+TypeLOG),	Ncmd = 20,};#define TYPE(q)		((((ulong)(q).path)>>TypeSHIFT) & TypeMASK)#define PART(q)		((((ulong)(q).path)>>PartSHIFT) & PartMASK)#define UNIT(q)		((((ulong)(q).path)>>UnitSHIFT) & UnitMASK)#define DEV(q)		((((ulong)(q).path)>>DevSHIFT) & DevMASK)#define QID(d,u, p, t)	(((d)<<DevSHIFT)|((u)<<UnitSHIFT)|\					 ((p)<<PartSHIFT)|((t)<<TypeSHIFT))static voidsdaddpart(SDunit* unit, char* name, uvlong start, uvlong end){	SDpart *pp;	int i, partno;	/*	 * Check name not already used	 * and look for a free slot.	 */	if(unit->part != nil){		partno = -1;		for(i = 0; i < unit->npart; i++){			pp = &unit->part[i];			if(!pp->valid){				if(partno == -1)					partno = i;				break;			}			if(strcmp(name, pp->perm.name) == 0){				if(pp->start == start && pp->end == end)					return;				error(Ebadctl);			}		}	}	else{		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil)			error(Enomem);		unit->npart = SDnpart;		partno = 0;	}	/*	 * If no free slot found then increase the	 * array size (can't get here with unit->part == nil).	 */	if(partno == -1){		if(unit->npart >= NPart)			error(Enomem);		if((pp = malloc(sizeof(SDpart)*(unit->npart+SDnpart))) == nil)			error(Enomem);		memmove(pp, unit->part, sizeof(SDpart)*unit->npart);		free(unit->part);		unit->part = pp;		partno = unit->npart;		unit->npart += SDnpart;	}	/*	 * Check size and extent are valid.	 */	if(start > end || end > unit->sectors)		error(Eio);	pp = &unit->part[partno];	pp->start = start;	pp->end = end;	kstrdup(&pp->perm.name, name);	kstrdup(&pp->perm.user, eve);	pp->perm.perm = 0640;	pp->valid = 1;}static voidsddelpart(SDunit* unit, char* name){	int i;	SDpart *pp;	/*	 * Look for the partition to delete.	 * Can't delete if someone still has it open.	 */	pp = unit->part;	for(i = 0; i < unit->npart; i++){		if(strcmp(name, pp->perm.name) == 0)			break;		pp++;	}	if(i >= unit->npart)		error(Ebadctl);	if(strcmp(up->user, pp->perm.user) && !iseve())		error(Eperm);	pp->valid = 0;	pp->vers++;}static voidsdincvers(SDunit *unit){	int i;	unit->vers++;	if(unit->part){		for(i = 0; i < unit->npart; i++){			unit->part[i].valid = 0;			unit->part[i].vers++;		}	}}static intsdinitpart(SDunit* unit){	if(unit->sectors > 0){		unit->sectors = unit->secsize = 0;		sdincvers(unit);	}	if(unit->inquiry[0] & 0xC0)		return 0;	switch(unit->inquiry[0] & 0x1F){	case 0x00:			/* DA */	case 0x04:			/* WORM */	case 0x05:			/* CD-ROM */	case 0x07:			/* MO */		break;	default:		return 0;	}	if(unit->dev->ifc->online)		unit->dev->ifc->online(unit);	if(unit->sectors){		sdincvers(unit);		sdaddpart(unit, "data", 0, unit->sectors);#if 0		/*		 * Use partitions passed from boot program,		 * e.g.		 *	sdC0part=dos 63 123123/plan9 123123 456456		 * This happens before /boot sets hostname so the		 * partitions will have the null-string for user.		 * The gen functions patch it up.		 */		snprint(buf, sizeof buf, "%spart", unit->perm.name);		for(p = getconf(buf); p != nil; p = q){			if(q = strchr(p, '/'))				*q++ = '\0';			nf = tokenize(p, f, nelem(f));			if(nf < 3)				continue;			start = strtoull(f[1], 0, 0);			end = strtoull(f[2], 0, 0);			if(!waserror()){				sdaddpart(unit, f[0], start, end);				poperror();			}		}#endif	}	return 1;}static intsdindex(int idno){	char *p;	p = strchr(devletters, idno);	if(p == nil)		return -1;	return p-devletters;}static SDev*sdgetdev(int idno){	SDev *sdev;	int i;	if((i = sdindex(idno)) < 0)		return nil;	qlock(&devslock);	if((sdev = devs[i]))		incref(&sdev->r);	qunlock(&devslock);	return sdev;}static SDunit*sdgetunit(SDev* sdev, int subno){	SDunit *unit;	char buf[32];	/*	 * Associate a unit with a given device and sub-unit	 * number on that device.	 * The device will be probed if it has not already been	 * successfully accessed.	 */	qlock(&sdev->unitlock);	if(subno > sdev->nunit){		qunlock(&sdev->unitlock);		return nil;	}	unit = sdev->unit[subno];	if(unit == nil){		/*		 * Probe the unit only once. This decision		 * may be a little severe and reviewed later.		 */		if(sdev->unitflg[subno]){			qunlock(&sdev->unitlock);			return nil;		}		if((unit = malloc(sizeof(SDunit))) == nil){			qunlock(&sdev->unitlock);			return nil;		}		sdev->unitflg[subno] = 1;		snprint(buf, sizeof(buf), "%s%d", sdev->name, subno);		kstrdup(&unit->perm.name, buf);		kstrdup(&unit->perm.user, eve);		unit->perm.perm = 0555;		unit->subno = subno;		unit->dev = sdev;		if(sdev->enabled == 0 && sdev->ifc->enable)			sdev->ifc->enable(sdev);		sdev->enabled = 1;		/*		 * No need to lock anything here as this is only		 * called before the unit is made available in the		 * sdunit[] array.		 */		if(unit->dev->ifc->verify(unit) == 0){			qunlock(&sdev->unitlock);			free(unit);			return nil;		}		sdev->unit[subno] = unit;	}	qunlock(&sdev->unitlock);	return unit;}static voidsdreset(void){	int i;	SDev *sdev;	/*	 * Probe all known controller types and register any devices found.	 */	for(i = 0; sdifc[i] != nil; i++){		if(sdifc[i]->pnp == nil || (sdev = sdifc[i]->pnp()) == nil)			continue;		sdadddevs(sdev);	}}voidsdadddevs(SDev *sdev){	int i, j, id;	SDev *next;	for(; sdev; sdev=next){		next = sdev->next;		sdev->unit = (SDunit**)malloc(sdev->nunit * sizeof(SDunit*));		sdev->unitflg = (int*)malloc(sdev->nunit * sizeof(int));		if(sdev->unit == nil || sdev->unitflg == nil){			print("sdadddevs: out of memory\n");		giveup:			free(sdev->unit);			free(sdev->unitflg);			if(sdev->ifc->clear)				sdev->ifc->clear(sdev);			free(sdev);			continue;		}		id = sdindex(sdev->idno);		if(id == -1){			print("sdadddevs: bad id number %d (%C)\n", id, id);			goto giveup;		}		qlock(&devslock);		for(i=0; i<nelem(devs); i++){			if(devs[j = (id+i)%nelem(devs)] == nil){				sdev->idno = devletters[j];				devs[j] = sdev;				snprint(sdev->name, sizeof sdev->name, "sd%c", devletters[j]);				break;			}		}		qunlock(&devslock);		if(i == nelem(devs)){			print("sdadddevs: out of device letters\n");			goto giveup;		}	}}// void// sdrmdevs(SDev *sdev)// {// 	char buf[2];//// 	snprint(buf, sizeof buf, "%c", sdev->idno);// 	unconfigure(buf);// }static intsd2gen(Chan* c, int i, Dir* dp){	Qid q;	uvlong l;	SDpart *pp;	SDperm *perm;	SDunit *unit;	SDev *sdev;	int rv;	sdev = sdgetdev(DEV(c->qid));	assert(sdev);	unit = sdev->unit[UNIT(c->qid)];	rv = -1;	switch(i){	case Qctl:		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qctl),			unit->vers, QTFILE);		perm = &unit->ctlperm;		if(emptystr(perm->user)){			kstrdup(&perm->user, eve);			perm->perm = 0640;		}		devdir(c, q, "ctl", 0, perm->user, perm->perm, dp);		rv = 1;		break;	case Qraw:		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), Qraw),			unit->vers, QTFILE);		perm = &unit->rawperm;		if(emptystr(perm->user)){			kstrdup(&perm->user, eve);			perm->perm = DMEXCL|0600;		}		devdir(c, q, "raw", 0, perm->user, perm->perm, dp);		rv = 1;		break;	case Qpart:		pp = &unit->part[PART(c->qid)];		l = (pp->end - pp->start) * unit->secsize;		mkqid(&q, QID(DEV(c->qid), UNIT(c->qid), PART(c->qid), 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);		rv = 1;		break;	}	decref(&sdev->r);	return rv;}static intsd1gen(Chan* c, int i, Dir* dp){	Qid q;	switch(i){	case Qtopctl:		mkqid(&q, QID(0, 0, 0, Qtopctl), 0, QTFILE);		devdir(c, q, "sdctl", 0, eve, 0640, dp);		return 1;	}	return -1;}static intsdgen(Chan* c, char *name, Dirtab *dt, int j, int s, Dir* dp){	Qid q;	uvlong l;	int i, r;	SDpart *pp;	SDunit *unit;	SDev *sdev;	switch(TYPE(c->qid)){	case Qtopdir:		if(s == DEVDOTDOT){			mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);			sprint(up->genbuf, "#%C", sddevtab.dc);			devdir(c, q, up->genbuf, 0, eve, 0555, dp);			return 1;		}		if(s+Qtopbase < Qunitdir)			return sd1gen(c, s+Qtopbase, dp);		s -= (Qunitdir-Qtopbase);		qlock(&devslock);		for(i=0; i<nelem(devs); i++){			if(devs[i]){				if(s < devs[i]->nunit)					break;				s -= devs[i]->nunit;			}		}		if(i == nelem(devs)){			/* Run off the end of the list */			qunlock(&devslock);			return -1;		}		if((sdev = devs[i]) == nil){			qunlock(&devslock);			return 0;		}		incref(&sdev->r);		qunlock(&devslock);		if((unit = sdev->unit[s]) == nil)			if((unit = sdgetunit(sdev, s)) == nil){				decref(&sdev->r);				return 0;			}		mkqid(&q, QID(sdev->idno, s, 0, Qunitdir), 0, QTDIR);		if(emptystr(unit->perm.user))			kstrdup(&unit->perm.user, eve);		devdir(c, q, unit->perm.name, 0, unit->perm.user, unit->perm.perm, dp);		decref(&sdev->r);		return 1;	case Qunitdir:		if(s == DEVDOTDOT){			mkqid(&q, QID(0, 0, 0, Qtopdir), 0, QTDIR);			sprint(up->genbuf, "#%C", sddevtab.dc);			devdir(c, q, up->genbuf, 0, eve, 0555, dp);			return 1;		}		if((sdev = sdgetdev(DEV(c->qid))) == nil){			devdir(c, c->qid, "unavailable", 0, eve, 0, dp);			return 1;		}		unit = sdev->unit[UNIT(c->qid)];		qlock(&unit->ctl);		/*		 * Check for media change.		 * If one has already been detected, sectors will be zero.		 * If there is one waiting to be detected, online		 * will return > 1.		 * Online is a bit of a large hammer but does the job.		 */		if(unit->sectors == 0		|| (unit->dev->ifc->online && unit->dev->ifc->online(unit) > 1))			sdinitpart(unit);		i = s+Qunitbase;		if(i < Qpart){			r = sd2gen(c, i, dp);			qunlock(&unit->ctl);			decref(&sdev->r);

⌨️ 快捷键说明

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