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

📄 vtdump.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "stdinc.h"#include <bio.h>typedef struct Source Source;struct Source{	ulong gen;	int psize;	int dsize;	int dir;	int active;	int depth;	uvlong size;	uchar score[VtScoreSize];	int reserved;};int bsize;Biobuf *bout;VtRoot root;int ver;int cmp;int all;int find;uchar fscore[VtScoreSize];VtSession *z;int vtGetUint16(uchar *p);ulong vtGetUint32(uchar *p);uvlong vtGetUint48(uchar *p);void usage(void);int parseScore(uchar *score, char *buf, int n);void readRoot(VtRoot*, uchar *score, char *file);int dumpDir(Source*, int indent);voidmain(int argc, char *argv[]){	char *host = nil;	uchar score[VtScoreSize];	Source source;	uchar buf[VtMaxLumpSize];	char *p;	int n;	ARGBEGIN{	case 'h':		host = ARGF();		break;	case 'c':		cmp++;		break;	case 'f':		find++;		p = EARGF(usage());		if(!parseScore(fscore, p, strlen(p)))			usage();		break;	case 'a':		all = 1;		break;	default:		usage();	}ARGEND	vtAttach();	bout = vtMemAllocZ(sizeof(Biobuf));	Binit(bout, 1, OWRITE);	if(argc > 1)		usage();	vtAttach();	fmtinstall('V', vtScoreFmt);	fmtinstall('R', vtErrFmt);	z = vtDial(host, 0);	if(z == nil)		vtFatal("could not connect to server: %s", vtGetError());	if(!vtConnect(z, 0))		sysfatal("vtConnect: %r");	readRoot(&root, score, argv[0]);	ver = root.version;	bsize = root.blockSize;	if(!find) {		Bprint(bout, "score: %V\n", score);		Bprint(bout, "version: %d\n", ver);		Bprint(bout, "name: %s\n", root.name);		Bprint(bout, "type: %s\n", root.type);		Bprint(bout, "bsize: %d\n", bsize);		Bprint(bout, "prev: %V\n", root.prev);	}	if (bsize == 0)		sysfatal("zero bsize");	switch(ver) {	default:		sysfatal("unknown version");	case VtRootVersion:		break;	}	n = vtRead(z, root.score, VtDirType, buf, bsize);	if(n < 0)		sysfatal("could not read root dir");	/* fake up top level source */	memset(&source, 0, sizeof(source));	memmove(source.score, root.score, VtScoreSize);	source.psize = bsize;	source.dsize = bsize;	source.dir = 1;	source.active = 1;	source.depth = 0;	source.size = n;	dumpDir(&source, 0);	Bterm(bout);	vtClose(z);	vtDetach();	exits(0);}voidsourcePrint(Source *s, int indent, int entry){	int i;	uvlong size, dsize;	int ne;	for(i=0; i<indent; i++)		Bprint(bout, " ");	Bprint(bout, "%4d", entry);	if(s->active) {		/* dir size in directory entries */		if(s->dir) {			dsize = s->dsize;			if (dsize <= 0) {				fprint(2, "%s: non-positive dsize %d in dir %V\n",					argv0, s->dsize, s->score);				dsize = 1;	/* don't divide by zero */			}			ne = s->dsize/VtEntrySize;			size = ne*(s->size/dsize) +				(s->size%dsize)/VtEntrySize;		} else 			size = s->size;		if(cmp) {			Bprint(bout, ": gen: %lud size: %llud",				s->gen, size);			if(!s->dir)				Bprint(bout, ": %V", s->score);		} else {			Bprint(bout, ": gen: %lud psize: %d dsize: %d",				s->gen, s->psize, s->dsize);			Bprint(bout, " depth: %d size: %llud: %V",				s->depth, size, s->score);		}				if(s->reserved)			Bprint(bout, ": reserved not emtpy");	}	Bprint(bout, "\n");}intparse(Source *s, uchar *p){	VtEntry dir;	memset(s, 0, sizeof(*s));	if(!vtEntryUnpack(&dir, p, 0))		return 0;	if(!(dir.flags & VtEntryActive))		return 1;	s->active = 1;	s->gen = dir.gen;	s->psize = dir.psize;	s->dsize = dir.dsize;	s->size = dir.size;	memmove(s->score, dir.score, VtScoreSize);	if(dir.flags & VtEntryDir)		s->dir = 1;	s->depth = dir.depth;	return 1;}intsourceRead(Source *s, ulong block, uchar *p, int n){	uchar buf[VtMaxLumpSize];	uchar score[VtScoreSize];	int i, nn, np, type;	int elem[VtPointerDepth];	memmove(score, s->score, VtScoreSize);	np = s->psize/VtScoreSize;	assert(np > 0);	for(i=0; i<s->depth; i++) {		elem[i] = block % np;		block /= np;	}	assert(block == 0);	for(i=s->depth-1; i>=0; i--) {		nn = vtRead(z, score, VtPointerType0+i, buf, s->psize);		if(nn < 0)			return -1;		if(!vtSha1Check(score, buf, nn)) {			vtSetError("vtSha1Check failed on root block");			return -1;		}		if((elem[i]+1)*VtScoreSize > nn)			return 0;		memmove(score, buf + elem[i]*VtScoreSize, VtScoreSize);	}	if(s->dir)		type = VtDirType;	else		type = VtDataType;	nn = vtRead(z, score, type, p, n);	if(nn < 0)		return -1;	if(!vtSha1Check(score, p, nn)) {		vtSetError("vtSha1Check failed on root block");		return -1;	}		return nn;}voiddumpFileContents(Source *s){	int nb, lb, i, n;	uchar buf[VtMaxLumpSize];	nb = (s->size + s->dsize - 1)/s->dsize;	lb = s->size%s->dsize;	for(i=0; i<nb; i++) {		if (s->dsize > sizeof buf) {			fprint(2, "%s: implausibly large s->dsize %d for %V\n",				argv0, s->dsize, s->score);			continue;		}		memset(buf, 0, s->dsize);		n = sourceRead(s, i, buf, s->dsize);		if(n < 0) {				fprint(2, "could not read block: %d: %s\n", i, vtGetError());			continue;		}		if(i < nb-1)			Bwrite(bout, buf, s->dsize);		else			Bwrite(bout, buf, lb);	}}voiddumpFile(Source *s, int indent){	int nb, i, j, n;	uchar buf[VtMaxLumpSize];	uchar score[VtScoreSize];	nb = (s->size + s->dsize - 1)/s->dsize;	for(i=0; i<nb; i++) {		if (s->dsize > sizeof buf) {			fprint(2, "%s: implausibly large s->dsize %d for %V\n",				argv0, s->dsize, s->score);			continue;		}		memset(buf, 0, s->dsize);		n = sourceRead(s, i, buf, s->dsize);		if(n < 0) {				fprint(2, "could not read block: %d: %s\n", i, vtGetError());			continue;		}		for(j=0; j<indent; j++)			Bprint(bout, " ");		vtSha1(score, buf, n);				Bprint(bout, "%4d: size: %ud: %V\n", i, n, score);	}}intdumpDir(Source *s, int indent){	int pb, ne, nb, i, j, n, entry;	uchar buf[VtMaxLumpSize];	Source ss;	if (s->dsize <= 0) {		fprint(2, "%s: dumpDir %V: non-positive s->dsize %d\n",			argv0, s->score, s->dsize);		return 1;	}	pb = s->dsize/VtEntrySize;	ne = pb*(s->size/s->dsize) + (s->size%s->dsize)/VtEntrySize;	nb = (s->size + s->dsize - 1)/s->dsize;	for(i=0; i<nb; i++) {		if (s->dsize > sizeof buf) {			fprint(2, "%s: implausibly large s->dsize %d for %V\n",				argv0, s->dsize, s->score);			continue;		}		memset(buf, 0, s->dsize);		n = sourceRead(s, i, buf, s->dsize);		if(n < 0) {				fprint(2, "could not read block: %d: %s\n", i, vtGetError());			continue;		}		for(j=0; j<pb; j++) {			entry = i*pb + j;			if(entry >= ne)				break;			parse(&ss, buf + j * VtEntrySize);			if(!find)				sourcePrint(&ss, indent, entry);			else if(memcmp(ss.score, fscore, VtScoreSize) == 0) {				dumpFileContents(&ss);				return 0;			}			if(ss.dir) {				if(!dumpDir(&ss, indent+1))					return 0;			} else if(all)				dumpFile(&ss, indent+1);		}	}	return 1;}voidusage(void){	fprint(2, "usage: %s [-ac] [-f findscore] [-h host] [file]\n", argv0);	exits("usage");}intparseScore(uchar *score, char *buf, int n){	int i, c;	memset(score, 0, VtScoreSize);	if(n < VtScoreSize*2)		return 0;	for(i=0; i<VtScoreSize*2; i++) {		if(buf[i] >= '0' && buf[i] <= '9')			c = buf[i] - '0';		else if(buf[i] >= 'a' && buf[i] <= 'f')			c = buf[i] - 'a' + 10;		else if(buf[i] >= 'A' && buf[i] <= 'F')			c = buf[i] - 'A' + 10;		else {			return 0;		}		if((i & 1) == 0)			c <<= 4;			score[i>>1] |= c;	}	return 1;}voidreadRoot(VtRoot *root, uchar *score, char *file){	int fd;	uchar buf[VtRootSize];	int i, n, nn;	if(file == nil)		fd = 0;	else {		fd = open(file, OREAD);		if(fd < 0)			sysfatal("could not open file: %s: %r", file);	}	n = readn(fd, buf, sizeof(buf)-1);	if(n < 0)		sysfatal("read failed: %r");	buf[n] = 0;	close(fd);	for(i=0; i<n; i++) {		if(!parseScore(score, (char*)(buf+i), n-i))			continue;		nn = vtRead(z, score, VtRootType, buf, VtRootSize);		if(nn >= 0) {			if(nn != VtRootSize)				sysfatal("vtRead on root too short");			if(!vtSha1Check(score, buf, VtRootSize))				sysfatal("vtSha1Check failed on root block");			if(!vtRootUnpack(root, buf))				sysfatal("could not parse root: %r");			return;		}	}	sysfatal("could not find root");}

⌨️ 快捷键说明

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