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

📄 depend.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <auth.h>#include <fcall.h>#include <thread.h>#include <bio.h>typedef struct Args Args;struct Args {	int	argc;	char	**argv;};typedef struct Dfile Dfile;typedef struct Fid Fid;typedef struct File File;typedef struct Fs Fs;typedef struct Request Request;typedef struct Symbol Symbol;typedef struct Tardir Tardir;extern int threadrforkflag = RFNAMEG;enum{	Nstat = 1024,	/* plenty for this application */	MAXSIZE = 8192+IOHDRSZ,};int messagesize = MAXSIZE;voidfatal(char *fmt, ...){	va_list arg;	char buf[1024];	write(2, "depend: ", 8);	va_start(arg, fmt);	vseprint(buf, buf+1024, fmt, arg);	va_end(arg);	write(2, buf, strlen(buf));	write(2, "\n", 1);	threadexitsall(fmt);}enum{	Nfidhash=	64,	Ndfhash=	128,};struct Symbol{	Symbol	*next;		/* hash list chaining */	char	*sym;	int	fno;		/* file symbol is defined in */};/* source file */struct File{	QLock;	char	*name;	Symbol	*ref;	uchar	*refvec;	/* files resolving the references */	uint	len;		/* length of file */	uint	tarlen;		/* length of tar file */	uint	mode;	uint	mtime;	int	use;	int	fd;};/* .depend file */struct Dfile{	Lock;	int	use;		/* use count */	int	old;		/* true if this is an superceded dfile */	File	*file;		/* files */	int	nfile;		/* number of files */	int	flen;		/* length of file table */	Symbol	**dhash;	/* hash table of symbols */	int	hlen;		/* length of hash table */	Dfile	*next;		/* hash chain */	char	*path;		/* path name of dependency file */	Qid	qid;		/* qid of the dependency file */};struct Fid{	Fid	*next;	int	fid;	int	ref;	int	attached;	int	open;	Qid	qid;	char	*path;	Dfile	*df;	Symbol	*dp;	int	fd;	Dir	*dir;	int	ndir;	int	dirindex;};struct Request{	Request	*next;	Fid	*fid;	Fcall	f;	uchar	buf[1];};enum{	Tblocksize=	512,	/* tar block size */	Tnamesize=	100,	/* tar name size */};struct Tardir{	char	name[Tnamesize];	char	mode[8];	char	uid[8];	char	gid[8];	char	size[12];	char	mtime[12];	char	chksum[8];	char	linkflag;	char	linkname[Tnamesize];};struct Fs{	Lock;	int	fd;		/* to kernel mount point */	Fid	*hash[Nfidhash];	char	*root;	Qid	rootqid;};struct Fsarg{	Fs	*fs;	int	fd;	char *root;};extern	void	fsrun(void*);extern	Fid*	fsgetfid(Fs*, int);extern	void	fsputfid(Fs*, Fid*);extern	void	fsreply(Fs*, Request*, char*);extern	void	fsversion(Fs*, Request*, Fid*);extern	void	fsauth(Fs*, Request*, Fid*);extern	void	fsflush(Fs*, Request*, Fid*);extern	void	fsattach(Fs*, Request*, Fid*);extern	void	fswalk(Fs*, Request*, Fid*);extern	void	fsopen(Fs*, Request*, Fid*);extern	void	fscreate(Fs*, Request*, Fid*);extern	void	fsread(Fs*, Request*, Fid*);extern	void	fswrite(Fs*, Request*, Fid*);extern	void	fsclunk(Fs*, Request*, Fid*);extern	void	fsremove(Fs*, Request*, Fid*);extern	void	fsstat(Fs*, Request*, Fid*);extern	void	fswstat(Fs*, Request*, Fid*);void 	(*fcall[])(Fs*, Request*, Fid*) ={	[Tflush]	fsflush,	[Tversion]	fsversion,	[Tauth]	fsauth,	[Tattach]	fsattach,	[Twalk]		fswalk,	[Topen]		fsopen,	[Tcreate]	fscreate,	[Tread]		fsread,	[Twrite]	fswrite,	[Tclunk]	fsclunk,	[Tremove]	fsremove,	[Tstat]		fsstat,	[Twstat]	fswstat};char Eperm[]   = "permission denied";char Eexist[]  = "file does not exist";char Enotdir[] = "not a directory";char Eisopen[] = "file already open";char Enofid[] = "no such fid";char mallocerr[]	= "malloc: %r";char Etoolong[]	= "name too long";char *dependlog = "depend";int debug;Dfile *dfhash[Ndfhash];		/* dependency file hash */QLock dfhlock[Ndfhash];QLock iolock;Request*	allocreq(int);Dfile*	getdf(char*);void	releasedf(Dfile*);Symbol*	dfsearch(Dfile*, char*);void	dfresolve(Dfile*, int);char*	mkpath(char*, char*);int	mktar(Dfile*, Symbol*, uchar*, uint, int);void	closetar(Dfile*, Symbol*);void*emalloc(uint n){	void *p;	p = malloc(n);	if(p == nil)		fatal(mallocerr);	memset(p, 0, n);	return p;}void *erealloc(void *ReallocP, int ReallocN){	if(ReallocN == 0)		ReallocN = 1;	if(!ReallocP)		ReallocP = emalloc(ReallocN);	else if(!(ReallocP = realloc(ReallocP, ReallocN)))		fatal("unable to allocate %d bytes",ReallocN);	return(ReallocP);}char*estrdup(char *s){	char *d, *d0;	if(!s)		return 0;	d = d0 = emalloc(strlen(s)+1);	while(*d++ = *s++)		;	return d0;}/* *  mount the user interface and start one request processor *  per CPU */voidrealmain(void *a){	Fs *fs;	int pfd[2];	int srv;	char service[128];	struct Fsarg fsarg;	Args *args;	int argc;	char **argv;	args = a;	argc = args->argc;	argv = args->argv;	fmtinstall('F', fcallfmt);	ARGBEGIN{		case 'd':			debug++;			break;	}ARGEND	if(argc != 2){		fprint(2, "usage: %s [-d] svc-name directory\n", argv0);		exits("usage");	}	snprint(service, sizeof service, "#s/%s", argv[0]);	if(argv[1][0] != '/')		fatal("directory must be rooted");	if(pipe(pfd) < 0)		fatal("opening pipe: %r");	/* Typically mounted before /srv exists */	srv = create(service, OWRITE, 0666);	if(srv < 0)		fatal("post: %r");	fprint(srv, "%d", pfd[1]);	close(srv);	close(pfd[1]);	time(nil);	/* open fd for time before losing / */	if(bind(argv[1], "/", MREPL) == 0)		fatal("can't bind %s to /", argv[1]);	fs = emalloc(sizeof(Fs));	fsarg.fs = fs;	fsarg.fd = pfd[0];	fsarg.root = argv[1];	proccreate(fsrun, &fsarg, 16*1024);	proccreate(fsrun, &fsarg, 16*1024);	fsrun(&fsarg);	exits(nil);}voidthreadmain(int argc, char *argv[]){	static Args args;	args.argc = argc;	args.argv = argv;	rfork(RFNAMEG);	proccreate(realmain, &args, 16*1024);}char*mkpath(char *dir, char *file){	int len;	char *path;	len = strlen(dir) + 1;	if(file != nil)		len += strlen(file) + 1;	path = emalloc(len);	if(file != nil)		sprint(path, "%s/%s", dir, file);	else		sprint(path, "%s", dir);	return path;}voidfsrun(void *a){	struct Fsarg *fsarg;	Fs* fs;	char *root;	int n, t;	Request *r;	Fid *f;	Dir *d;	fsarg = a;	fs = fsarg->fs;	fs->fd = fsarg->fd;	root = fsarg->root;	d = dirstat("/");	if(d == nil)		fatal("root %s inaccessible: %r", root);	fs->rootqid = d->qid;	free(d);	for(;;){		r = allocreq(messagesize);		qlock(&iolock);		n = read9pmsg(fs->fd, r->buf, messagesize);		qunlock(&iolock);		if(n <= 0)			fatal("read9pmsg error: %r");		if(convM2S(r->buf, n, &r->f) == 0){			fprint(2, "can't convert %ux %ux %ux\n", r->buf[0],				r->buf[1], r->buf[2]);			free(r);			continue;		}		f = fsgetfid(fs, r->f.fid);		r->fid = f;		if(debug)			fprint(2, "%F path %llux\n", &r->f, f->qid.path);		t = r->f.type;		r->f.type++;		(*fcall[t])(fs, r, f);		fsputfid(fs, f);	}}/* *  any request that can get queued for a delayed reply */Request*allocreq(int bufsize){	Request *r;	r = emalloc(sizeof(Request)+bufsize);	r->next = nil;	return r;}Fid*fsgetfid(Fs *fs, int fid){	Fid *f, *nf;	lock(fs);	for(f = fs->hash[fid%Nfidhash]; f; f = f->next){		if(f->fid == fid){			f->ref++;			unlock(fs);			return f;		}	}	nf = emalloc(sizeof(Fid));	nf->next = fs->hash[fid%Nfidhash];	fs->hash[fid%Nfidhash] = nf;	nf->fid = fid;	nf->ref = 1;	nf->fd = -1;	unlock(fs);	return nf;}voidfsputfid(Fs *fs, Fid *f){	Fid **l, *nf;	lock(fs);	if(--f->ref > 0){		unlock(fs);		return;	}	for(l = &fs->hash[f->fid%Nfidhash]; nf = *l; l = &nf->next)		if(nf == f){			*l = f->next;			break;		}	unlock(fs);	free(f);}voidfsreply(Fs *fs, Request *r, char *err){	int n;	uchar buf[MAXSIZE];	if(err){		r->f.type = Rerror;		r->f.ename = err;	}	if(debug)		fprint(2, "%F path %llux\n", &r->f, r->fid->qid.path);	n = convS2M(&r->f, buf, messagesize);	if(n == 0)		fatal("bad convS2M");	if(write(fs->fd, buf, n) != n)		fatal("unmounted");	free(r);}voidfsversion(Fs *fs, Request *r, Fid*){	if(r->f.msize < 256){		fsreply(fs, r, "version: bad message size");		return;	}	if(messagesize > r->f.msize)		messagesize = r->f.msize;	r->f.msize = messagesize;	r->f.version = "9P2000";	fsreply(fs, r, nil);}voidfsauth(Fs *fs, Request *r, Fid*){	fsreply(fs, r, "depend: authentication not required");}voidfsflush(Fs*, Request*, Fid*){}voidfsattach(Fs *fs, Request *r, Fid *f){	f->qid = fs->rootqid;	f->path = strdup("/");	f->df = getdf(mkpath(f->path, ".depend"));	/* hold down the fid till the clunk */	f->attached = 1;	lock(fs);	f->ref++;	unlock(fs);	r->f.qid = f->qid;	fsreply(fs, r, nil);}voidfswalk(Fs *fs, Request *r, Fid *f){	Fid *nf;	char *name, *tmp;	int i, nqid, nwname;	char errbuf[ERRMAX], *err;	Qid qid[MAXWELEM];	Dfile *lastdf;	char *path, *npath;	Dir *d;	Symbol *dp;	if(f->attached == 0){		fsreply(fs, r, Eexist);		return;	}	if(f->fd >= 0 || f->open)		fatal("walk of an open file");	nf = nil;	if(r->f.newfid != r->f.fid){		nf = fsgetfid(fs, r->f.newfid);		nf->attached = 1;		nf->open = f->open;		nf->path = strdup(f->path);		nf->qid = f->qid;		nf->dp = f->dp;		nf->fd = f->fd;		nf->df = f->df;		if(nf->df){			lock(nf->df);			nf->df->use++;			unlock(nf->df);		}		if(r->f.nwname == 0){			r->f.nwqid = 0;			fsreply(fs, r, nil);			return;		}		f = nf;	}	err = nil;	path = strdup(f->path);	if(path == nil)		fatal(mallocerr);	nqid = 0;	nwname = r->f.nwname;	lastdf = f->df;	if(nwname > 0){		for(; nqid<nwname; nqid++){			name = r->f.wname[nqid];			if(strcmp(name, ".") == 0){	Noop:				if(nqid == 0)					qid[nqid] = f->qid;				else					qid[nqid] = qid[nqid-1];				continue;			}			if(strcmp(name, "..") == 0){				name = strrchr(path, '/');				if(name){					if(name == path)	/* at root */						goto Noop;					*name = '\0';				}				d = dirstat(path);				if(d == nil){					*name = '/';					errstr(errbuf, sizeof errbuf);					err = errbuf;					break;				}	Directory:				qid[nqid] = d->qid;				free(d);				releasedf(lastdf);				lastdf = getdf(mkpath(path, ".depend"));				continue;			}			npath = mkpath(path, name);			free(path);			path = npath;			d = dirstat(path);			if(d !=nil && (d->qid.type & QTDIR))				goto Directory;			free(d);			qid[nqid].type = QTFILE;			qid[nqid].path = 0;			qid[nqid].vers = 0;			dp = dfsearch(lastdf, name);			if(dp == nil){				tmp = strdup(name);				if(tmp == nil)					fatal("mallocerr");				i = strlen(tmp);				if(i > 4 && strcmp(&tmp[i-4], ".tar") == 0){					tmp[i-4] = 0;					dp = dfsearch(lastdf, tmp);				}				free(tmp);			}			if(dp == nil){				err = Eexist;				break;			}			qid[nqid].path = (uvlong)dp;			qid[nqid].vers = 0;		}		if(nqid == 0 && err == nil)			err = "file does not exist";	}	/* for error or partial success, put the cloned fid back*/	if(nf!=nil && (err != nil || nqid < nwname)){		releasedf(nf->df);		nf->df = nil;		fsputfid(fs, nf);	}	if(err == nil){		/* return (possibly short) list of qids */		for(i=0; i<nqid; i++)			r->f.wqid[i] = qid[i];		r->f.nwqid = nqid;		/* for full success, advance f */		if(nqid > 0 && nqid == nwname){			free(f->path);			f->path = path;			path = nil;			f->qid = qid[nqid-1];			f->dp = (Symbol*)f->qid.path;			if(f->df != lastdf){				releasedf(f->df);				f->df = lastdf;				lastdf = nil;			}		}	}	releasedf(lastdf);	free(path);	fsreply(fs, r, err);}#ifdef adfvoidfsclone(Fs *fs, Request *r, Fid *f){	Fid *nf;	if(f->attached == 0){		fsreply(fs, r, Eexist);		return;	}	nf = fsgetfid(fs, r->f.newfid);	nf->attached = 1;	nf->open = f->open;	nf->path = strdup(f->path);	nf->qid = f->qid;	nf->dp = f->dp;	nf->fd = f->fd;	nf->df = f->df;	if(nf->df){		lock(nf->df);		nf->df->use++;		unlock(nf->df);	}	fsreply(fs, r, nil);}voidfswalk(Fs *fs, Request *r, Fid *f){	char *name;	int i;	Dir d;	char errbuf[ERRLEN];	char *path;	Symbol *dp;	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if(f->fd >= 0 || f->open)		fatal("walk of an open file");	name = r->f.name;	if(strcmp(name, ".") == 0){		fsreply(fs, r, nil);		return;	}	if(strcmp(name, "..") == 0){		name = strrchr(f->path, '/');		if(name){			if(name == f->path){				fsreply(fs, r, nil);				return;			}			*name = 0;		}		if(dirstat(f->path, &d) < 0){			*name = '/';			errstr(errbuf);			fsreply(fs, r, errbuf);			return;		}		r->f.qid = f->qid = d.qid;		releasedf(f->df);		f->df = getdf(mkpath(f->path, ".depend"));		fsreply(fs, r, nil);		return;	}	path = mkpath(f->path, name);	if(dirstat(path, &d) < 0 || (d.qid.path & CHDIR) == 0){		dp = dfsearch(f->df, name);		if(dp == nil){			i = strlen(name);			if(i > 4 && strcmp(&name[i-4], ".tar") == 0){				name[i-4] = 0;				dp = dfsearch(f->df, name);			}		}		if(dp == nil){			fsreply(fs, r, Eexist);			free(path);			return;		}		f->dp = dp;		d.qid.path = (uint)dp;

⌨️ 快捷键说明

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