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

📄 u9fs.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
/* already in plan9.h #include <sys/types.h> *//* for struct passwd, struct group, struct stat ... *//* plan9.h is first to get the large file support definitions as early as possible */#include <plan9.h>#include <sys/stat.h>	/* for stat, umask */#include <stdlib.h>	/* for malloc */#include <string.h>	/* for strcpy, memmove */#include <pwd.h>	/* for getpwnam, getpwuid */#include <grp.h>	/* for getgrnam, getgrgid */#include <unistd.h>	/* for gethostname, pread, pwrite, read, write */#include <utime.h>	/* for utime */#include <dirent.h>	/* for readdir */#include <errno.h>	/* for errno */#include <stdio.h>	/* for remove [sic] */#include <fcntl.h>	/* for O_RDONLY, etc. */#include <sys/socket.h>	/* various networking crud */#include <netinet/in.h>#include <netdb.h>#include <fcall.h>#include <oldfcall.h>#include <u9fs.h>/* #ifndef because can be given in makefile */#ifndef DEFAULTLOG#define DEFAULTLOG "/tmp/u9fs.log"#endifchar *logfile = DEFAULTLOG;#define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m))enum {	Tdot = 1,	Tdotdot};enum {	P9P1,	P9P2000};typedef struct User User;struct User {	int id;	gid_t defaultgid;	char *name;	char **mem;	/* group members */	int nmem;	User *next;};struct Fid {	int fid;	char *path;	struct stat st;	User *u;	int omode;	DIR *dir;	int diroffset;	int fd;	struct dirent *dirent;	Fid *next;	Fid *prev;	int auth;	void *authmagic;};void*	emalloc(size_t);void*	erealloc(void*, size_t);char*	estrdup(char*);char*	estrpath(char*, char*);void	sysfatal(char*, ...);int	okuser(char*);void	rversion(Fcall*, Fcall*);void	rauth(Fcall*, Fcall*);void	rattach(Fcall*, Fcall*);void	rflush(Fcall*, Fcall*);void	rclone(Fcall*, Fcall*);void	rwalk(Fcall*, Fcall*);void	ropen(Fcall*, Fcall*);void	rcreate(Fcall*, Fcall*);void	rread(Fcall*, Fcall*);void	rwrite(Fcall*, Fcall*);void	rclunk(Fcall*, Fcall*);void	rstat(Fcall*, Fcall*);void	rwstat(Fcall*, Fcall*);void	rclwalk(Fcall*, Fcall*);void	rremove(Fcall*, Fcall*);User*	uname2user(char*);User*	gname2user(char*);User*	uid2user(int);User*	gid2user(int);Fid*	newfid(int, char**);Fid*	oldfidex(int, int, char**);Fid*	oldfid(int, char**);int	fidstat(Fid*, char**);void	freefid(Fid*);int	userchange(User*, char**);int	userwalk(User*, char**, char*, Qid*, char**);int	useropen(Fid*, int, char**);int	usercreate(Fid*, char*, int, long, char**);int	userremove(Fid*, char**);int	userperm(User*, char*, int, int);int	useringroup(User*, User*);Qid	stat2qid(struct stat*);void	getfcallold(int, Fcall*, int);void	putfcallold(int, Fcall*);char	Eauth[] =	"authentication failed";char	Ebadfid[] =	"fid unknown or out of range";char	Ebadoffset[] =	"bad offset in directory read";char	Ebadusefid[] =	"bad use of fid";char	Edirchange[] =	"wstat can't convert between files and directories";char	Eexist[] =	"file or directory already exists";char	Efidactive[] =	"fid already in use";char	Enotdir[] =	"not a directory";char	Enotingroup[] =	"not a member of proposed group";char	Enotowner[] = 	"only owner can change group in wstat";char	Eperm[] =	"permission denied";char	Especial0[] =	"already attached without access to special files";char	Especial1[] =	"already attached with access to special files";char	Especial[] =	"no access to special file";char	Etoolarge[] =	"i/o count too large";char	Eunknowngroup[] = "unknown group";char	Eunknownuser[] = "unknown user";char	Ewstatbuffer[] = "bogus wstat buffer";ulong	msize = IOHDRSZ+8192;uchar*	rxbuf;uchar*	txbuf;void*	databuf;int	connected;int	devallowed;char*	autharg;char*	defaultuser;char	hostname[256];char	remotehostname[256];int	chatty9p = 0;int	network = 1;int	old9p = -1;int	authed;User*	none;Auth *authmethods[] = {	/* first is default */	&authrhosts,	&authp9any,	&authnone,};Auth *auth;voidgetfcallnew(int fd, Fcall *fc, int have){	int len;	if(have > BIT32SZ)		sysfatal("cannot happen");	if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have)		sysfatal("couldn't read message");	len = GBIT32(rxbuf);	if(len <= BIT32SZ)		sysfatal("bogus message");	len -= BIT32SZ;	if(readn(fd, rxbuf+BIT32SZ, len) != len)		sysfatal("short message");	if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ)		sysfatal("badly sized message type %d", rxbuf[0]);}voidgetfcallold(int fd, Fcall *fc, int have){	int len, n;	if(have > 3)		sysfatal("cannot happen");	if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have)		sysfatal("couldn't read message");	len = oldhdrsize(rxbuf[0]);	if(len < 3)		sysfatal("bad message %d", rxbuf[0]);	if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3)		sysfatal("couldn't read message");	n = iosize(rxbuf);	if(readn(fd, rxbuf+len, n) != n)		sysfatal("couldn't read message");	len += n;	if(convM2Sold(rxbuf, len, fc) != len)		sysfatal("badly sized message type %d", rxbuf[0]);}voidputfcallnew(int wfd, Fcall *tx){	uint n;	if((n = convS2M(tx, txbuf, msize)) == 0)		sysfatal("couldn't format message type %d", tx->type);	if(write(wfd, txbuf, n) != n)		sysfatal("couldn't send message");}voidputfcallold(int wfd, Fcall *tx){	uint n;	if((n = convS2Mold(tx, txbuf, msize)) == 0)		sysfatal("couldn't format message type %d", tx->type);	if(write(wfd, txbuf, n) != n)		sysfatal("couldn't send message");}voidgetfcall(int fd, Fcall *fc){	if(old9p == 1){		getfcallold(fd, fc, 0);		return;	}	if(old9p == 0){		getfcallnew(fd, fc, 0);		return;	}	/* auto-detect */	if(readn(fd, rxbuf, 3) != 3)		sysfatal("couldn't read message");	/* is it an old (9P1) message? */	if(50 <= rxbuf[0] && rxbuf[0] <= 87 && (rxbuf[0]&1)==0 && GBIT16(rxbuf+1) == 0xFFFF){		old9p = 1;		getfcallold(fd, fc, 3);		return;	}	getfcallnew(fd, fc, 3);	old9p = 0;}voidseterror(Fcall *f, char *error){	f->type = Rerror;	f->ename = error ? error : "programmer error";}intisowner(User *u, Fid *f){	return u->id == f->st.st_uid;}voidserve(int rfd, int wfd){	Fcall rx, tx;	for(;;){		getfcall(rfd, &rx);		if(chatty9p)			fprint(2, "<- %F\n", &rx);		memset(&tx, 0, sizeof tx);		tx.type = rx.type+1;		tx.tag = rx.tag;		switch(rx.type){		case Tflush:			break;		case Tversion:			rversion(&rx, &tx);			break;		case Tauth:			rauth(&rx, &tx);			break;		case Tattach:			rattach(&rx, &tx);			break;		case Twalk:			rwalk(&rx, &tx);			break;		case Tstat:			tx.stat = databuf;			rstat(&rx, &tx);			break;		case Twstat:			rwstat(&rx, &tx);			break;		case Topen:			ropen(&rx, &tx);			break;		case Tcreate:			rcreate(&rx, &tx);			break;		case Tread:			tx.data = databuf;			rread(&rx, &tx);			break;		case Twrite:			rwrite(&rx, &tx);			break;		case Tclunk:			rclunk(&rx, &tx);			break;		case Tremove:			rremove(&rx, &tx);			break;		default:			fprint(2, "unknown message %F\n", &rx);			seterror(&tx, "bad message");			break;		}		if(chatty9p)			fprint(2, "-> %F\n", &tx);		(old9p ? putfcallold : putfcallnew)(wfd, &tx);	}}voidrversion(Fcall *rx, Fcall *tx){	if(msize > rx->msize)		msize = rx->msize;	tx->msize = msize;	if(strncmp(rx->version, "9P", 2) != 0)		tx->version = "unknown";	else		tx->version = "9P2000";}voidrauth(Fcall *rx, Fcall *tx){	char *e;	if((e = auth->auth(rx, tx)) != nil)		seterror(tx, e);}voidrattach(Fcall *rx, Fcall *tx){	char *e;	Fid *fid;	User *u;	if(rx->aname == nil)		rx->aname = "";	if(strcmp(rx->aname, "device") == 0){		if(connected && !devallowed){			seterror(tx, Especial0);			return;		}		devallowed = 1;	}else{		if(connected && devallowed){			seterror(tx, Especial1);			return;		}	}	if(strcmp(rx->uname, "none") == 0){		if(authed == 0){			seterror(tx, Eauth);			return;		}	} else {		if((e = auth->attach(rx, tx)) != nil){			seterror(tx, e);			return;		}		authed++;	}	if((fid = newfid(rx->fid, &e)) == nil){		seterror(tx, e);		return;	}	fid->path = estrdup("/");	if(fidstat(fid, &e) < 0){		seterror(tx, e);		freefid(fid);		return;	}	if(defaultuser)		rx->uname = defaultuser;	if((u = uname2user(rx->uname)) == nil	|| (!defaultuser && u->id == 0)){		/* we don't know anyone named root... */		seterror(tx, Eunknownuser);		freefid(fid);		return;	}	fid->u = u;	tx->qid = stat2qid(&fid->st);	return;}voidrwalk(Fcall *rx, Fcall *tx){	int i;	char *path, *e;	Fid *fid, *nfid;	e = nil;	if((fid = oldfid(rx->fid, &e)) == nil){		seterror(tx, e);		return;	}	if(fid->omode != -1){		seterror(tx, Ebadusefid);		return;	}	if(fidstat(fid, &e) < 0){		seterror(tx, e);		return;	}	if(!S_ISDIR(fid->st.st_mode) && rx->nwname){		seterror(tx, Enotdir);		return;	}	nfid = nil;	if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){		seterror(tx, e);		return;	}	path = estrdup(fid->path);	e = nil;	for(i=0; i<rx->nwname; i++)		if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0)			break;	if(i == rx->nwname){		/* successful clone or walk */		tx->nwqid = i;		if(nfid){			nfid->path = path;			nfid->u = fid->u;		}else{			free(fid->path);			fid->path = path;		}	}else{		if(i > 0)		/* partial walk? */			tx->nwqid = i;		else			seterror(tx, e);		if(nfid)		/* clone implicit new fid */			freefid(nfid);		free(path);	}	return;}voidropen(Fcall *rx, Fcall *tx){	char *e;	Fid *fid;	if((fid = oldfid(rx->fid, &e)) == nil){		seterror(tx, e);		return;	}	if(fid->omode != -1){		seterror(tx, Ebadusefid);		return;	}	if(fidstat(fid, &e) < 0){		seterror(tx, e);		return;	}	if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){		seterror(tx, Especial);		return;	}	if(useropen(fid, rx->mode, &e) < 0){		seterror(tx, e);		return;	}	tx->iounit = 0;	tx->qid = stat2qid(&fid->st);}voidrcreate(Fcall *rx, Fcall *tx){	char *e;	Fid *fid;	if((fid = oldfid(rx->fid, &e)) == nil){		seterror(tx, e);		return;	}	if(fid->omode != -1){		seterror(tx, Ebadusefid);		return;	}	if(fidstat(fid, &e) < 0){		seterror(tx, e);		return;	}	if(!S_ISDIR(fid->st.st_mode)){		seterror(tx, Enotdir);		return;	}	if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){		seterror(tx, e);		return;	}	if(fidstat(fid, &e) < 0){		seterror(tx, e);		return;	}	tx->iounit = 0;	tx->qid = stat2qid(&fid->st);}ucharmodebyte(struct stat *st){	uchar b;	b = 0;	if(S_ISDIR(st->st_mode))

⌨️ 快捷键说明

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