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

📄 dev.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	<u.h>#include	<libc.h>#include	<fcall.h>#include	"compat.h"#include	"error.h"extern ulong	kerndate;voidmkqid(Qid *q, vlong path, ulong vers, int type){	q->type = type;	q->vers = vers;	q->path = path;}intdevno(int c, int user){	int i;	for(i = 0; devtab[i] != nil; i++){		if(devtab[i]->dc == c)			return i;	}	if(user == 0)		panic("devno %C 0x%ux", c, c);	return -1;}voiddevdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db){	db->name = n;	db->qid = qid;	db->type = devtab[c->type]->dc;	db->dev = c->dev;	db->mode = (qid.type << 24) | perm;	db->atime = seconds();	db->mtime = kerndate;	db->length = length;	db->uid = user;	db->gid = eve;	db->muid = user;}/* * the zeroth element of the table MUST be the directory itself for ..*/intdevgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp){	if(tab == 0)		return -1;	if(i != DEVDOTDOT){		i++; /* skip first element for . itself */		if(i >= ntab)			return -1;		tab += i;	}	devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);	return 1;}voiddevreset(void){}voiddevinit(void){}Chan*devattach(int tc, char *spec){	Chan *c;	char *buf;	c = newchan();	mkqid(&c->qid, 0, 0, QTDIR);	c->type = devno(tc, 0);	if(spec == nil)		spec = "";	buf = smalloc(4+strlen(spec)+1);	sprint(buf, "#%C%s", tc, spec);	c->name = newcname(buf);	free(buf);	return c;}Chan*devclone(Chan *c){	Chan *nc;	if(c->flag & COPEN)		panic("clone of open file type %C\n", devtab[c->type]->dc);	nc = newchan();	nc->type = c->type;	nc->dev = c->dev;	nc->mode = c->mode;	nc->qid = c->qid;	nc->offset = c->offset;	nc->aux = c->aux;	return nc;}Walkqid*devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen){	int i, j, alloc;	Walkqid *wq;	char *n;	Dir dir;	isdir(c);	alloc = 0;	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));	if(waserror()){		if(alloc && wq->clone!=nil)			cclose(wq->clone);		free(wq);		return nil;	}	if(nc == nil){		nc = devclone(c);		nc->type = 0;	/* device doesn't know about this channel yet */		alloc = 1;	}	wq->clone = nc;	for(j=0; j<nname; j++){		isdir(nc);		n = name[j];		if(strcmp(n, ".") == 0){    Accept:			wq->qid[wq->nqid++] = nc->qid;			continue;		}		if(strcmp(n, "..") == 0){			(*gen)(nc, tab, ntab, DEVDOTDOT, &dir);			nc->qid = dir.qid;			goto Accept;		}		for(i=0;; i++){			switch((*gen)(nc, tab, ntab, i, &dir)){			case -1:				if(j == 0)					error(Enonexist);				strncpy(up->error, Enonexist, ERRMAX);				goto Done;			case 0:				continue;			case 1:				if(strcmp(n, dir.name) == 0){					nc->qid = dir.qid;					goto Accept;				}				continue;			}		}	}	/*	 * We processed at least one name, so will return some data.	 * If we didn't process all nname entries succesfully, we drop	 * the cloned channel and return just the Qids of the walks.	 */Done:	poperror();	if(wq->nqid < nname){		if(alloc)			cclose(wq->clone);		wq->clone = nil;	}else if(wq->clone){		/* attach cloned channel to same device */		wq->clone->type = c->type;	}	return wq;}intdevstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen){	int i;	Dir dir;	char *p, *elem;	for(i=0;; i++)		switch((*gen)(c, tab, ntab, i, &dir)){		case -1:			if(c->qid.type & QTDIR){				if(c->name == nil)					elem = "???";				else if(strcmp(c->name->s, "/") == 0)					elem = "/";				else					for(elem=p=c->name->s; *p; p++)						if(*p == '/')							elem = p+1;				devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);				return convD2M(&dir, db, n);			}			error(Enonexist);		case 0:			break;		case 1:			if(c->qid.path == dir.qid.path){				return convD2M(&dir, db, n);			}			break;		}}longdevdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen){	long k, m, dsz;	struct{		Dir;		char slop[100];	}dir;	k = c->offset;	for(m=0; m<n; k++){		switch((*gen)(c, tab, ntab, k, &dir)){		case -1:			return m;		case 0:			c->offset++;	/* BUG??? (was DIRLEN: skip entry) */			break;		case 1:			dsz = convD2M(&dir, (uchar*)d, n-m);			if(dsz <= BIT16SZ){	/* <= not < because this isn't stat; read is stuck */				if(m == 0)					return -1;				return m;			}			m += dsz;			d += dsz;			break;		}	}	return m;}/* * error(Eperm) if open permission not granted for up->user. */voiddevpermcheck(char *fileuid, ulong perm, int omode){	ulong t;	static int access[] = { 0400, 0200, 0600, 0100 };	if(strcmp(up->user, fileuid) == 0)		perm <<= 0;	else	if(strcmp(up->user, eve) == 0)		perm <<= 3;	else		perm <<= 6;	t = access[omode&3];	if((t&perm) != t)		error(Eperm);}Chan*devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen){	int i;	Dir dir;	for(i=0;; i++){		switch((*gen)(c, tab, ntab, i, &dir)){		case -1:			goto Return;		case 0:			break;		case 1:			if(c->qid.path == dir.qid.path){				devpermcheck(dir.uid, dir.mode, omode);				goto Return;			}			break;		}	}Return:	c->offset = 0;	if((c->qid.type&QTDIR) && omode!=OREAD)		error(Eperm);	c->mode = openmode(omode);	c->flag |= COPEN;	return c;}voiddevcreate(Chan*, char*, int, ulong){	error(Eperm);}Block*devbread(Chan *, long, ulong){	panic("no block read");	return nil;}longdevbwrite(Chan *, Block *, ulong){	panic("no block write");	return 0;}voiddevremove(Chan*){	error(Eperm);}intdevwstat(Chan*, uchar*, int){	error(Eperm);	return 0;}

⌨️ 快捷键说明

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