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

📄 ramfs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	name = thdr.name;	if(strcmp(name, ".")==0 || strcmp(name, "..")==0)		return Ename;	for(r=ram; r<&ram[nram]; r++)		if(r->busy && parent==r->parent)		if(strcmp((char*)name, r->name)==0)			return Einuse;	for(r=ram; r->busy; r++)		if(r == &ram[Nram-1])			return "no free ram resources";	r->busy = 1;	r->qid.path = ++path;	r->qid.vers = 0;	if(prm & DMDIR)		r->qid.type |= QTDIR;	r->parent = parent;	free(r->name);	r->name = estrdup(name);	r->user = f->user;	r->group = f->ram->group;	r->muid = f->ram->muid;	if(prm & DMDIR)		prm = (prm&~0777) | (f->ram->perm&prm&0777);	else		prm = (prm&(~0777|0111)) | (f->ram->perm&prm&0666);	r->perm = prm;	r->ndata = 0;	if(r-ram >= nram)		nram = r - ram + 1;	r->atime = time(0);	r->mtime = r->atime;	f->ram->mtime = r->atime;	f->ram = r;	rhdr.qid = r->qid;	rhdr.iounit = messagesize-IOHDRSZ;	f->open = 1;	if(thdr.mode & ORCLOSE)		f->rclose = 1;	r->open++;	return 0;}char*rread(Fid *f){	Ram *r;	uchar *buf;	long off;	int n, m, cnt;	if(f->ram->busy == 0)		return Enotexist;	n = 0;	rhdr.count = 0;	off = thdr.offset;	buf = rdata;	cnt = thdr.count;	if(cnt > messagesize)	/* shouldn't happen, anyway */		cnt = messagesize;	if(f->ram->qid.type & QTDIR){		for(r=ram+1; off > 0; r++){			if(r->busy && r->parent==f->ram-ram)				off -= ramstat(r, statbuf, sizeof statbuf);			if(r == &ram[nram-1])				return 0;		}		for(; r<&ram[nram] && n < cnt; r++){			if(!r->busy || r->parent!=f->ram-ram)				continue;			m = ramstat(r, buf+n, cnt-n);			if(m == 0)				break;			n += m;		}		rhdr.data = (char*)rdata;		rhdr.count = n;		return 0;	}	r = f->ram;	if(off >= r->ndata)		return 0;	r->atime = time(0);	n = cnt;	if(off+n > r->ndata)		n = r->ndata - off;	rhdr.data = r->data+off;	rhdr.count = n;	return 0;}char*rwrite(Fid *f){	Ram *r;	ulong off;	int cnt;	r = f->ram;	if(r->busy == 0)		return Enotexist;	off = thdr.offset;	if(r->perm & DMAPPEND)		off = r->ndata;	cnt = thdr.count;	if(r->qid.type & QTDIR)		return Eisdir;	if(off+cnt >= Maxsize)		/* sanity check */		return "write too big";	if(off+cnt > r->ndata)		r->data = erealloc(r->data, off+cnt);	if(off > r->ndata)		memset(r->data+r->ndata, 0, off-r->ndata);	if(off+cnt > r->ndata)		r->ndata = off+cnt;	memmove(r->data+off, thdr.data, cnt);	r->qid.vers++;	r->mtime = time(0);	rhdr.count = cnt;	return 0;}static intemptydir(Ram *dr){	long didx = dr - ram;	Ram *r;	for(r=ram; r<&ram[nram]; r++)		if(r->busy && didx==r->parent)			return 0;	return 1;}char *realremove(Ram *r){	if(r->qid.type & QTDIR && !emptydir(r))		return Enotempty;	r->ndata = 0;	if(r->data)		free(r->data);	r->data = 0;	r->parent = 0;	memset(&r->qid, 0, sizeof r->qid);	free(r->name);	r->name = nil;	r->busy = 0;	return nil;}char *rclunk(Fid *f){	char *e = nil;	if(f->open)		f->ram->open--;	if(f->rclose)		e = realremove(f->ram);	f->busy = 0;	f->open = 0;	f->ram = 0;	return e;}char *rremove(Fid *f){	Ram *r;	if(f->open)		f->ram->open--;	f->busy = 0;	f->open = 0;	r = f->ram;	f->ram = 0;	if(r->qid.path == 0 || !perm(f, &ram[r->parent], Pwrite))		return Eperm;	ram[r->parent].mtime = time(0);	return realremove(r);}char *rstat(Fid *f){	if(f->ram->busy == 0)		return Enotexist;	rhdr.nstat = ramstat(f->ram, statbuf, sizeof statbuf);	rhdr.stat = statbuf;	return 0;}char *rwstat(Fid *f){	Ram *r, *s;	Dir dir;	if(f->ram->busy == 0)		return Enotexist;	convM2D(thdr.stat, thdr.nstat, &dir, (char*)statbuf);	r = f->ram;	/*	 * To change length, must have write permission on file.	 */	if(dir.length!=~0 && dir.length!=r->ndata){	 	if(!perm(f, r, Pwrite))			return Eperm;	}	/*	 * To change name, must have write permission in parent	 * and name must be unique.	 */	if(dir.name[0]!='\0' && strcmp(dir.name, r->name)!=0){	 	if(!perm(f, &ram[r->parent], Pwrite))			return Eperm;		for(s=ram; s<&ram[nram]; s++)			if(s->busy && s->parent==r->parent)			if(strcmp(dir.name, s->name)==0)				return Eexist;	}	/*	 * To change mode, must be owner or group leader.	 * Because of lack of users file, leader=>group itself.	 */	if(dir.mode!=~0 && r->perm!=dir.mode){		if(strcmp(f->user, r->user) != 0)		if(strcmp(f->user, r->group) != 0)			return Enotowner;	}	/*	 * To change group, must be owner and member of new group,	 * or leader of current group and leader of new group.	 * Second case cannot happen, but we check anyway.	 */	if(dir.gid[0]!='\0' && strcmp(r->group, dir.gid)!=0){		if(strcmp(f->user, r->user) == 0)	//	if(strcmp(f->user, dir.gid) == 0)			goto ok;		if(strcmp(f->user, r->group) == 0)		if(strcmp(f->user, dir.gid) == 0)			goto ok;		return Enotowner;		ok:;	}	/* all ok; do it */	if(dir.mode != ~0){		dir.mode &= ~DMDIR;	/* cannot change dir bit */		dir.mode |= r->perm&DMDIR;		r->perm = dir.mode;	}	if(dir.name[0] != '\0'){		free(r->name);		r->name = estrdup(dir.name);	}	if(dir.gid[0] != '\0')		r->group = estrdup(dir.gid);	if(dir.length!=~0 && dir.length!=r->ndata){		r->data = erealloc(r->data, dir.length);		if(r->ndata < dir.length)			memset(r->data+r->ndata, 0, dir.length-r->ndata);		r->ndata = dir.length;	}	ram[r->parent].mtime = time(0);	return 0;}uintramstat(Ram *r, uchar *buf, uint nbuf){	int n;	Dir dir;	dir.name = r->name;	dir.qid = r->qid;	dir.mode = r->perm;	dir.length = r->ndata;	dir.uid = r->user;	dir.gid = r->group;	dir.muid = r->muid;	dir.atime = r->atime;	dir.mtime = r->mtime;	n = convD2M(&dir, buf, nbuf);	if(n > 2)		return n;	return 0;}Fid *newfid(int fid){	Fid *f, *ff;	ff = 0;	for(f = fids; f; f = f->next)		if(f->fid == fid)			return f;		else if(!ff && !f->busy)			ff = f;	if(ff){		ff->fid = fid;		return ff;	}	f = emalloc(sizeof *f);	f->ram = nil;	f->fid = fid;	f->next = fids;	fids = f;	return f;}voidio(void){	char *err, buf[40];	int n, pid, ctl;	Fid *fid;	pid = getpid();	if(private){		snprint(buf, sizeof buf, "/proc/%d/ctl", pid);		ctl = open(buf, OWRITE);		if(ctl < 0){			fprint(2, "can't protect ramfs\n");		}else{			fprint(ctl, "noswap\n");			fprint(ctl, "private\n");			close(ctl);		}	}	for(;;){		/*		 * reading from a pipe or a network device		 * will give an error after a few eof reads.		 * however, we cannot tell the difference		 * between a zero-length read and an interrupt		 * on the processes writing to us,		 * so we wait for the error.		 */		n = read9pmsg(mfd[0], mdata, messagesize);		if(n < 0){			rerrstr(buf, sizeof buf);			if(buf[0]=='\0' || strstr(buf, "hungup"))				exits("");			error("mount read");		}		if(n == 0)			continue;		if(convM2S(mdata, n, &thdr) == 0)			continue;		if(debug)			fprint(2, "ramfs %d:<-%F\n", pid, &thdr);		if(thdr.type<0 || thdr.type>=nelem(fcalls) || !fcalls[thdr.type])			err = "bad fcall type";		else if(((fid=newfid(thdr.fid))==nil || !fid->ram) && needfid[thdr.type])			err = "fid not in use";		else			err = (*fcalls[thdr.type])(fid);		if(err){			rhdr.type = Rerror;			rhdr.ename = err;		}else{			rhdr.type = thdr.type + 1;			rhdr.fid = thdr.fid;		}		rhdr.tag = thdr.tag;		if(debug)			fprint(2, "ramfs %d:->%F\n", pid, &rhdr);/**/		n = convS2M(&rhdr, mdata, messagesize);		if(n == 0)			error("convS2M error on write");		if(write(mfd[1], mdata, n) != n)			error("mount write");	}}intperm(Fid *f, Ram *r, int p){	if((p*Pother) & r->perm)		return 1;	if(strcmp(f->user, r->group)==0 && ((p*Pgroup) & r->perm))		return 1;	if(strcmp(f->user, r->user)==0 && ((p*Powner) & r->perm))		return 1;	return 0;}voiderror(char *s){	fprint(2, "%s: %s: %r\n", argv0, s);	exits(s);}void *emalloc(ulong n){	void *p;	p = malloc(n);	if(!p)		error("out of memory");	memset(p, 0, n);	return p;}void *erealloc(void *p, ulong n){	p = realloc(p, n);	if(!p)		error("out of memory");	return p;}char *estrdup(char *q){	char *p;	int n;	n = strlen(q)+1;	p = malloc(n);	if(!p)		error("out of memory");	memmove(p, q, n);	return p;}voidusage(void){	fprint(2, "usage: %s [-Dips] [-m mountpoint] [-S srvname]\n", argv0);	exits("usage");}

⌨️ 快捷键说明

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