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

📄 depend.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		d.qid.vers = 0;	}	free(f->path);	f->path = path;	if(d.qid.path & CHDIR){		releasedf(f->df);		f->df = getdf(mkpath(f->path, ".depend"));	}	r->f.qid = f->qid = d.qid;	fsreply(fs, r, nil);}#endifvoidfsopen(Fs *fs, Request *r, Fid *f){	int mode;	char errbuf[ERRMAX];		if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if(f->open){		fsreply(fs, r, Eisopen);		return;	}	mode = r->f.mode & 3;	if(mode != OREAD){		fsreply(fs, r, Eperm);		return;	}	if(f->qid.type & QTDIR){		f->fd = open(f->path, OREAD);		if(f->fd < 0){			errstr(errbuf, sizeof errbuf);			fsreply(fs, r, errbuf);			return;		}	}	f->open = 1;	r->f.qid = f->qid;	fsreply(fs, r, nil);}voidfscreate(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsread(Fs *fs, Request *r, Fid *f){	int i, n, len,skip;	Dir d;	Symbol *dp;	char buf[512];	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if((int)r->f.count < 0){		fsreply(fs, r, "bad read count");		return;	}	if(f->qid.type & QTDIR){		n = 0;		if(f->dir == nil){			f->ndir = dirreadall(f->fd, &f->dir);			f->dirindex = 0;		}		if(f->dir == nil)			goto Return;		if(r->f.offset == 0)	/* seeking to zero is permitted */			f->dirindex = 0;		for(; f->dirindex < f->ndir; f->dirindex++){			if((f->dir[f->dirindex].qid.type & QTDIR) == 0)				continue;			len = convD2M(&f->dir[f->dirindex], r->buf+n, r->f.count-n);			if(len <= BIT16SZ)				goto Return;			n += len;		}		skip = f->dirindex - f->ndir;	/* # depend records already read */		if(f->df){			for(i = 0; i < f->df->hlen; i++)				for(dp = f->df->dhash[i]; dp; dp = dp->next){					if(skip-- > 0)						continue;					snprint(buf, sizeof buf, "%s.tar", dp->sym);					d.name = buf;					d.uid = "none";					d.gid = "none";					d.muid = "none";					d.qid.type = QTFILE;					d.qid.path = (uvlong)dp;					d.qid.vers = 0;					d.length = f->df->file[dp->fno].tarlen;					d.mode = 0444;					d.mtime = time(nil);					d.atime = time(nil);					len = convD2M(&d, r->buf + n, r->f.count - n);					if(len <= BIT16SZ)						goto Return;					n += len;					f->dirindex++;				}		}	} else		n = mktar(f->df, f->dp, r->buf, r->f.offset, r->f.count);    Return:	r->f.data = (char*)r->buf;	r->f.count = n;	fsreply(fs, r, nil);}voidfswrite(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsclunk(Fs *fs, Request *r, Fid *f){	if(f->attached == 0){		fsreply(fs, r, Enofid);		return;	}	if(f->fd >= 0){		close(f->fd);		f->fd = -1;	}	if((f->qid.type & QTDIR) == 0)		closetar(f->df, f->dp);	releasedf(f->df);	f->df = nil;	free(f->dir);	f->dir = nil;	fsreply(fs, r, nil);	fsputfid(fs, f);}voidfsremove(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}voidfsstat(Fs *fs, Request *r, Fid *f){	char err[ERRMAX];	Dir d;	Symbol *dp;	int n;	uchar statbuf[Nstat];	if(f->qid.type & QTDIR)		n = stat(f->path, statbuf, sizeof statbuf);	else {		dp = f->dp;		d.name = dp->sym;		d.uid = "none";		d.gid = "none";		d.muid = "none";		d.qid.type = QTFILE;		d.qid.path = (uvlong)dp;		d.qid.vers = 0;		d.length = f->df->file[dp->fno].tarlen;		d.mode = 0444;		d.mtime = time(nil);		d.atime = time(nil);		n = convD2M(&d, statbuf, sizeof statbuf);	}	if(n <= BIT16SZ){		errstr(err, sizeof err);		fsreply(fs, r, err);	} else {		r->f.stat = statbuf;		r->f.nstat = n;		fsreply(fs, r, nil);	}}voidfswstat(Fs *fs, Request *r, Fid*){	fsreply(fs, r, Eperm);}/* *  string hash */uintshash(char *str, int len){	uint	hash;	char	*val; 	hash = 0;	for(val = str; *val; val++)		hash = (hash*13) + *val-'a';	return hash % len;}/* *  free info about a dependency file */voidfreedf(Dfile *df){	int i;	Symbol *dp, *next;	lock(df);	df->old = 1;	if(df->use){		unlock(df);		return;	}	unlock(df);	/* we're no longer referenced */	for(i = 0; i < df->nfile; i++)		free(df->file[i].name);	free(df->file[i].refvec);	free(df->file);	df->file = nil;	for(i = 0; i < df->hlen; i++)		for(dp = df->dhash[i]; dp != nil; dp = next){			next = dp->next;			free(dp);		}	free(df->path);	free(df);	free(df->dhash);	df->dhash = nil;}/* *  crack a dependency file */voidnewsym(char *name, int fno, Symbol **l){	Symbol *dp;	dp = emalloc(sizeof(Symbol));	dp->sym = strdup(name);	if(dp->sym == nil)		fatal("mallocerr");	dp->next = *l;	dp->fno = fno;	*l = dp;}intawk(Biobuf *b, char **field, int n){	char *line;	int i;	while(line = Brdline(b, '\n')){		line[Blinelen(b)-1] = 0;		while(*line == ' ' || *line == '\t')			*line++ = 0;		for(i = 0; i < n; i++){			if(*line == 0 || *line == '#')				break;			field[i] = line;			while(*line && *line != ' ' && *line != '\t')				line++;			while(*line == ' ' || *line == '\t')				*line++ = 0;		}		if(i)			return i;	}	return 0;}voidcrackdf(Dfile *df, Biobuf *b, uint len, char *dpath){	char *name;	char *field[3];	char path[512];	int n, inc, ok, npath;	Symbol **l, *dp, *next;	File *f, *ef;	Dir *d;	inc = 32;	df->flen = inc;	df->file = emalloc(df->flen*sizeof(File));	df->nfile = 0;	df->hlen = 1 + len/8;	df->dhash = emalloc(df->hlen*sizeof(Symbol*));	l = nil;	while((n = awk(b, field, 3)) > 0){		if(n != 2)			continue;		name = field[1];		switch(*field[0]){		case 'F':			if(df->flen == df->nfile){				df->flen += inc;				df->file = realloc(df->file, df->flen*sizeof(File));				if(df->file == nil)					fatal(mallocerr);				memset(&df->file[df->nfile], 0, inc*sizeof(File));			}			f = &df->file[df->nfile++];			f->name = strdup(name);			l = &f->ref;			/* fall through and define as a symbol */		case 'D':			if(l == nil)				continue;			newsym(name, df->nfile-1, &(df->dhash[shash(name, df->hlen)]));			break;		case 'R':			if(l == nil)				continue;			newsym(name, 0, l);			break;		}	}	ef = &df->file[df->nfile];	/* stat the files to get sizes */	npath = strlen(dpath);	if(npath+1+1 >= sizeof path)		fatal(Etoolong);	memmove(path, dpath, npath+1);	/* include NUL */	name = strrchr(path, '/') + 1;	for(f = df->file; f < ef; f++){		n = strlen(f->name);		if(npath+1+n+3+1 > sizeof path)			fatal(Etoolong);		memmove(name, f->name, n+1);	/* include NUL */		ok = access(path, AEXIST);		if(ok < 0){			strcpy(name+n, ".Z");			ok = access(path, AEXIST);			if(ok < 0){				strcpy(name+n, ".gz");				ok = access(path, AEXIST);			}		}		if(ok >= 0){			free(f->name);			f->name = strdup(name);			if(f->name == nil)				fatal(mallocerr);		}		d = dirstat(path);		if(d){			f->len = d->length;			f->mode = d->mode;			f->mtime = d->mtime;			free(d);		}else{			f->len = 0;			f->mode = 0;			f->mtime = 0;		}		f->fd = -1;	}	/* resolve all file references */	for(f = df->file; f < ef; f++)		dfresolve(df, f-df->file);	/* free the referenced symbols, don't need them anymore */	for(f = df->file; f < ef; f++){		f->tarlen += 2*Tblocksize;	/* tars trailing 0 blocks */		for(dp = f->ref; dp != nil; dp = next){			next = dp->next;			free(dp);		}		f->ref = nil;	}}/* *  get a cracked dependency file */Dfile*getdf(char *path){	Dfile *df, **l;	QLock *lk;	Dir *d;	int i, fd;	Biobuf *b;	i = shash(path, Ndfhash);	l = &dfhash[i];	lk = &dfhlock[i];	qlock(lk);	for(df = *l; df; df = *l){		if(strcmp(path, df->path) == 0)			break;		l = &df->next;	}	d = dirstat(path);	if(df){		if(d!=nil && d->qid.type == df->qid.type && d->qid.vers == df->qid.vers && d->qid.vers == df->qid.vers){			free(path);			lock(df);			df->use++;			unlock(df);			goto Return;		}		*l = df->next;		freedf(df);	}	fd = open(path, OREAD);	if(d == nil || fd < 0){		close(fd);		goto Return;	}	df = emalloc(sizeof(*df));	b = emalloc(sizeof(Biobuf));	Binit(b, fd, OREAD);	df->qid = d->qid;	df->path = path;	crackdf(df, b, d->length, path);	Bterm(b);	free(b);	df->next = *l;	*l = df;	df->use = 1;    Return:	qunlock(lk);	free(d);	return df;}/* *  stop using a dependency file.  Free it if it is no longer linked in. */voidreleasedf(Dfile *df){	Dfile **l, *d;	QLock *lk;	int i;	if(df == nil)		return;	/* remove from hash chain */	i = shash(df->path, Ndfhash);	l = &dfhash[i];	lk = &dfhlock[i];	qlock(lk);	lock(df);	df->use--;	if(df->old == 0 || df->use > 0){		unlock(df);		qunlock(lk);		return;	}	for(d = *l; d; d = *l){		if(d == df){			*l = d->next;			break;		}		l = &d->next;	}	unlock(df);	qunlock(lk);	/* now we know it is unreferenced, remove it */	freedf(df);}/* *  search a dependency file for a symbol */Symbol*dfsearch(Dfile *df, char *name){	Symbol *dp;	if(df == nil)		return nil;	for(dp = df->dhash[shash(name, df->hlen)]; dp; dp = dp->next)		if(strcmp(dp->sym, name) == 0)			return dp;	return nil;}/* *  resolve a single file into a vector of referenced files and the sum of their *  lengths *//* set a bit in the referenced file vector */intset(uchar *vec, int fno){	if(vec[fno/8] & (1<<(fno&7)))		return 1;	vec[fno/8] |= 1<<(fno&7);	return 0;}/* merge two referenced file vectors */voidmerge(uchar *vec, uchar *ovec, int nfile){	nfile = (nfile+7)/8;	while(nfile-- > 0)		*vec++ |= *ovec++;}uintres(Dfile *df, uchar *vec, int fno){	File *f;	Symbol *rp, *dp;	int len;	f = &df->file[fno];	if(set(vec, fno))		return 0;				/* already set */	if(f->refvec != nil){		merge(vec, f->refvec, df->nfile);	/* we've descended here before */		return f->tarlen;	}	len = 0;	for(rp = f->ref; rp; rp = rp->next){		dp = dfsearch(df, rp->sym);		if(dp == nil)			continue;		len += res(df, vec, dp->fno);	}	return len + Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;}voiddfresolve(Dfile *df, int fno){	uchar *vec;	File *f;	f = &df->file[fno];	vec = emalloc((df->nfile+7)/8);	f->tarlen = res(df, vec, fno);	f->refvec = vec;}/* *  make the tar directory block for a file */uchar*mktardir(File *f){	uchar *ep;	Tardir *tp;	uint sum;	uchar *p, *cp;	p = emalloc(Tblocksize);	tp = (Tardir*)p;	strcpy(tp->name, f->name);	sprint(tp->mode, "%6o ", f->mode & 0777);	sprint(tp->uid, "%6o ", 0);	sprint(tp->gid, "%6o ", 0);	sprint(tp->size, "%11o ", f->len);	sprint(tp->mtime, "%11o ", f->mtime);	/* calculate checksum */	memset(tp->chksum, ' ', sizeof(tp->chksum));	sum = 0;	ep = p + Tblocksize;	for (cp = p; cp < ep; cp++)		sum += *cp;	sprint(tp->chksum, "%6o", sum);	return p;}/* *  manage open files */intgetfile(Dfile *df, File *f){	int n;	char path[512], *name;	qlock(f);	f->use++;	if(f->fd < 0){		name = strrchr(df->path, '/') + 1;		n = snprint(path, sizeof path, "%.*s/%s", (int)(name-df->path), df->path, f->name);		if(n >= sizeof path - UTFmax){			syslog(0, dependlog, "path name too long: %.20s.../%.20s...", df->path, f->name);			return -1;		}		f->fd = open(path, OREAD);		if(f->fd < 0)			syslog(0, dependlog, "can't open %s: %r", path);	}	return f->fd;}voidreleasefile(File *f){	--f->use;	qunlock(f);}voidclosefile(File *f){	qlock(f);	if(f->use == 0){		close(f->fd);		f->fd = -1;	}	qunlock(f);}/* *  return a block of a tar file */intmktar(Dfile *df, Symbol *dp, uchar *area, uint offset, int len){	int fd, i, j, n, off;	uchar *p, *buf;	uchar *vec;	File *f;	f = &df->file[dp->fno];	vec = f->refvec;	p = area;	/* find file */	for(i = 0; i < df->nfile && len > 0; i++){		if((vec[i/8] & (1<<(i&7))) == 0)			continue;		f = &df->file[i];		n = Tblocksize + ((f->len + Tblocksize - 1)/Tblocksize)*Tblocksize;		if(offset >= n){			offset -= n;			continue;		}		if(offset < Tblocksize){			buf = mktardir(f);			if(offset + len > Tblocksize)				j = Tblocksize - offset;			else				j = len;//if(debug)fprint(2, "reading %d bytes dir of %s\n", j, f->name);			memmove(p, buf+offset, j);			p += j;			len -= j;			offset += j;			free(buf);		}		if(len <= 0)			break;		off = offset - Tblocksize;		if(off >= 0 && off < f->len){			if(off + len > f->len)				j = f->len - off;			else				j = len;			fd = getfile(df, f);			if(fd >= 0){//if(debug)fprint(2, "reading %d bytes from offset %d of %s\n", j, off, f->name);				if(pread(fd, p, j, off) != j)					syslog(0, dependlog, "%r reading %d bytes from offset %d of %s", j, off, f->name);			}			releasefile(f);			p += j;			len -= j;			offset += j;		}		if(len <= 0)			break;		if(offset < n){			if(offset + len > n)				j = n - offset;			else				j = len;//if(debug)fprint(2, "filling %d bytes after %s\n", j, f->name);			memset(p, 0, j);			p += j;			len -= j;		}		offset = 0;	}	/* null blocks at end of tar file */	if(offset < 2*Tblocksize && len > 0){		if(offset + len > 2*Tblocksize)			j = 2*Tblocksize - offset;		else			j = len;//if(debug)fprint(2, "filling %d bytes at end\n", j);		memset(p, 0, j);		p += j;	}	return p - area;}/* *  close the files making up  a tar file */voidclosetar(Dfile *df, Symbol *dp){	int i;	uchar *vec;	File *f;	f = &df->file[dp->fno];	vec = f->refvec;	/* find file */	for(i = 0; i < df->nfile; i++){		if((vec[i/8] & (1<<(i&7))) == 0)			continue;		closefile(&df->file[i]);	}}

⌨️ 快捷键说明

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