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

📄 9fsys.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	l = b->l;	consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n",		argc==6 ? "old: " : "", addr, l.type, l.state,		l.epoch, l.epochClose, l.tag);	if(argc == 6){		if(strcmp(argv[1], "-") != 0)			l.type = atoi(argv[1]);		if(strcmp(argv[2], "-") != 0)			l.state = atoi(argv[2]);		if(strcmp(argv[3], "-") != 0)			l.epoch = strtoul(argv[3], 0, 0);		if(strcmp(argv[4], "-") != 0)			l.epochClose = strtoul(argv[4], 0, 0);		if(strcmp(argv[5], "-") != 0)			l.tag = strtoul(argv[5], 0, 0);		consPrint("new: label %#ux %ud %ud %ud %ud %#x\n",			addr, l.type, l.state, l.epoch, l.epochClose, l.tag);		bb = _blockSetLabel(b, &l);		if(bb == nil)			goto Out1;		n = 0;		for(;;){			if(blockWrite(bb)){				while(bb->iostate != BioClean){					assert(bb->iostate == BioWriting);					vtSleep(bb->ioready);				}				break;			}			consPrint("blockWrite: %R\n");			if(n++ >= 5){				consPrint("giving up\n");				break;			}			sleep(5*1000);		}		blockPut(bb);	}	r = 1;Out1:	blockPut(b);Out0:	vtRUnlock(fs->elk);	return r;}/* * Inspect and edit the blocks on disk. */static intfsysBlock(Fsys* fsys, int argc, char* argv[]){	Fs *fs;	char *s;	Block *b;	uchar *buf;	u32int addr;	int c, count, i, offset;	char *usage = "usage: [fsys name] block addr offset [count [data]]";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc < 2 || argc > 4)		return cliError(usage);	fs = fsys->fs;	addr = strtoul(argv[0], 0, 0);	offset = strtoul(argv[1], 0, 0);	if(offset < 0 || offset >= fs->blockSize){		vtSetError("bad offset");		return 0;	}	if(argc > 2)		count = strtoul(argv[2], 0, 0);	else		count = 100000000;	if(offset+count > fs->blockSize)		count = fs->blockSize - count;	vtRLock(fs->elk);	b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);	if(b == nil){		vtSetError("cacheLocal %#ux: %R", addr);		vtRUnlock(fs->elk);		return 0;	}	consPrint("\t%sblock %#ux %ud %ud %.*H\n",		argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset);	if(argc == 4){		s = argv[3];		if(strlen(s) != 2*count){			vtSetError("bad data count");			goto Out;		}		buf = vtMemAllocZ(count);		for(i = 0; i < count*2; i++){			if(s[i] >= '0' && s[i] <= '9')				c = s[i] - '0';			else if(s[i] >= 'a' && s[i] <= 'f')				c = s[i] - 'a' + 10;			else if(s[i] >= 'A' && s[i] <= 'F')				c = s[i] - 'A' + 10;			else{				vtSetError("bad hex");				vtMemFree(buf);				goto Out;			}			if((i & 1) == 0)				c <<= 4;			buf[i>>1] |= c;		}		memmove(b->data+offset, buf, count);		consPrint("\tnew: block %#ux %ud %ud %.*H\n",			addr, offset, count, count, b->data+offset);		blockDirty(b);	}Out:	blockPut(b);	vtRUnlock(fs->elk);	return 1;}/* * Free a disk block. */static intfsysBfree(Fsys* fsys, int argc, char* argv[]){	Fs *fs;	Label l;	char *p;	Block *b;	u32int addr;	char *usage = "usage: [fsys name] bfree addr ...";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc == 0)		return cliError(usage);	fs = fsys->fs;	vtRLock(fs->elk);	while(argc > 0){		addr = strtoul(argv[0], &p, 0);		if(*p != '\0'){			consPrint("bad address - '%s'\n", addr);			/* syntax error; let's stop */			vtRUnlock(fs->elk);			return 0;		}		b = cacheLocal(fs->cache, PartData, addr, OReadOnly);		if(b == nil){			consPrint("loading %#ux: %R\n", addr);			continue;		}		l = b->l;		if(l.state == BsFree)			consPrint("%#ux is already free\n", addr);		else{			consPrint("label %#ux %ud %ud %ud %ud %#x\n",				addr, l.type, l.state, l.epoch, l.epochClose, l.tag);			l.state = BsFree;			l.type = BtMax;			l.tag = 0;			l.epoch = 0;			l.epochClose = 0;			if(!blockSetLabel(b, &l, 0))				consPrint("freeing %#ux: %R\n", addr);		}		blockPut(b);		argc--;		argv++;	}	vtRUnlock(fs->elk);	return 1;}static intfsysDf(Fsys *fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] df";	u32int used, tot, bsize;	Fs *fs;	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc != 0)		return cliError(usage);	fs = fsys->fs;	cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize);	consPrint("\t%s: %,llud used + %,llud free = %,llud (%ud%% used)\n",		fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize,		tot*(vlong)bsize, used*100/tot);	return 1;}/* * Zero an entry or a pointer. */static intfsysClrep(Fsys* fsys, int argc, char* argv[], int ch){	Fs *fs;	Entry e;	Block *b;	u32int addr;	int i, max, offset, sz;	uchar zero[VtEntrySize];	char *usage = "usage: [fsys name] clr%c addr offset ...";	ARGBEGIN{	default:		return cliError(usage, ch);	}ARGEND	if(argc < 2)		return cliError(usage, ch);	fs = fsys->fs;	vtRLock(fsys->fs->elk);	addr = strtoul(argv[0], 0, 0);	b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);	if(b == nil){		vtSetError("cacheLocal %#ux: %R", addr);	Err:		vtRUnlock(fsys->fs->elk);		return 0;	}	switch(ch){	default:		vtSetError("clrep");		goto Err;	case 'e':		if(b->l.type != BtDir){			vtSetError("wrong block type");			goto Err;		}		sz = VtEntrySize;		memset(&e, 0, sizeof e);		entryPack(&e, zero, 0);		break;	case 'p':		if(b->l.type == BtDir || b->l.type == BtData){			vtSetError("wrong block type");			goto Err;		}		sz = VtScoreSize;		memmove(zero, vtZeroScore, VtScoreSize);		break;	}	max = fs->blockSize/sz;	for(i = 1; i < argc; i++){		offset = atoi(argv[i]);		if(offset >= max){			consPrint("\toffset %d too large (>= %d)\n", i, max);			continue;		}		consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz);		memmove(b->data+offset*sz, zero, sz);	}	blockDirty(b);	blockPut(b);	vtRUnlock(fsys->fs->elk);	return 1;}static intfsysClre(Fsys* fsys, int argc, char* argv[]){	return fsysClrep(fsys, argc, argv, 'e');}static intfsysClrp(Fsys* fsys, int argc, char* argv[]){	return fsysClrep(fsys, argc, argv, 'p');}static intfsysEsearch1(File* f, char* s, u32int elo){	int n, r;	DirEntry de;	DirEntryEnum *dee;	File *ff;	Entry e, ee;	char *t;	dee = deeOpen(f);	if(dee == nil)		return 0;	n = 0;	for(;;){		r = deeRead(dee, &de);		if(r < 0){			consPrint("\tdeeRead %s/%s: %R\n", s, de.elem);			break;		}		if(r == 0)			break;		if(de.mode & ModeSnapshot){			if((ff = fileWalk(f, de.elem)) == nil)				consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);			else{				if(!fileGetSources(ff, &e, &ee))					consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem);				else if(e.snap != 0 && e.snap < elo){					consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem);					n++;				}				fileDecRef(ff);			}		}		else if(de.mode & ModeDir){			if((ff = fileWalk(f, de.elem)) == nil)				consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);			else{				t = smprint("%s/%s", s, de.elem);				n += fsysEsearch1(ff, t, elo);				vtMemFree(t);				fileDecRef(ff);			}		}		deCleanup(&de);		if(r < 0)			break;	}	deeClose(dee);	return n;}static intfsysEsearch(Fs* fs, char* path, u32int elo){	int n;	File *f;	DirEntry de;	f = fileOpen(fs, path);	if(f == nil)		return 0;	if(!fileGetDir(f, &de)){		consPrint("\tfileGetDir %s failed: %R\n", path);		fileDecRef(f);		return 0;	}	if((de.mode & ModeDir) == 0){		fileDecRef(f);		deCleanup(&de);		return 0;	}	deCleanup(&de);	n = fsysEsearch1(f, path, elo);	fileDecRef(f);	return n;}static intfsysEpoch(Fsys* fsys, int argc, char* argv[]){	Fs *fs;	int force, n, remove;	u32int low, old;	char *usage = "usage: [fsys name] epoch [[-ry] low]";	force = 0;	remove = 0;	ARGBEGIN{	case 'y':		force = 1;		break;	case 'r':		remove = 1;		break;	default:		return cliError(usage);	}ARGEND	if(argc > 1)		return cliError(usage);	if(argc > 0)		low = strtoul(argv[0], 0, 0);	else		low = ~(u32int)0;	if(low == 0)		return cliError("low epoch cannot be zero");	fs = fsys->fs;	vtRLock(fs->elk);	consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi);	n = fsysEsearch(fsys->fs, "/archive", low);	n += fsysEsearch(fsys->fs, "/snapshot", low);	consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low);	vtRUnlock(fs->elk);	/*	 * There's a small race here -- a new snapshot with epoch < low might	 * get introduced now that we unlocked fs->elk.  Low has to	 * be <= fs->ehi.  Of course, in order for this to happen low has	 * to be equal to the current fs->ehi _and_ a snapshot has to	 * run right now.  This is a small enough window that I don't care.	 */	if(n != 0 && !force){		consPrint("\tnot setting low epoch\n");		return 1;	}	old = fs->elo;	if(!fsEpochLow(fs, low))		consPrint("\tfsEpochLow: %R\n");	else{		consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old);		consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo);		if(fs->elo < low)			consPrint("\twarning: new low epoch < old low epoch\n");		if(force && remove)			fsSnapshotRemove(fs);	}	return 1;}static intfsysCreate(Fsys* fsys, int argc, char* argv[]){	int r;	ulong mode;	char *elem, *p, *path;	char *usage = "usage: [fsys name] create path uid gid perm";	DirEntry de;	File *file, *parent;	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc != 4)		return cliError(usage);	if(!fsysParseMode(argv[3], &mode))		return cliError(usage);	if(mode&ModeSnapshot)		return cliError("create - cannot create with snapshot bit set");	if(strcmp(argv[1], uidnoworld) == 0)		return cliError("permission denied");	vtRLock(fsys->fs->elk);	path = vtStrDup(argv[0]);	if((p = strrchr(path, '/')) != nil){		*p++ = '\0';		elem = p;		p = path;		if(*p == '\0')			p = "/";	}	else{		p = "/";		elem = path;	}	r = 0;	if((parent = fileOpen(fsys->fs, p)) == nil)		goto out;	file = fileCreate(parent, elem, mode, argv[1]);	fileDecRef(parent);	if(file == nil){		vtSetError("create %s/%s: %R", p, elem);		goto out;	}	if(!fileGetDir(file, &de)){		vtSetError("stat failed after create: %R");		goto out1;	}	if(strcmp(de.gid, argv[2]) != 0){		vtMemFree(de.gid);		de.gid = vtStrDup(argv[2]);		if(!fileSetDir(file, &de, argv[1])){			vtSetError("wstat failed after create: %R");			goto out2;		}	}	r = 1;out2:	deCleanup(&de);out1:	fileDecRef(file);out:	vtMemFree(path);	vtRUnlock(fsys->fs->elk);	return r;}static voidfsysPrintStat(char *prefix, char *file, DirEntry *de){	char buf[64];	if(prefix == nil)		prefix = "";	consPrint("%sstat %q %q %q %q %s %llud\n", prefix,		file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);}static intfsysStat(Fsys* fsys, int argc, char* argv[]){	int i;	File *f;	DirEntry de;	char *usage = "usage: [fsys name] stat files...";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc == 0)		return cliError(usage);	vtRLock(fsys->fs->elk);	for(i=0; i<argc; i++){		if((f = fileOpen(fsys->fs, argv[i])) == nil){			consPrint("%s: %R\n");			continue;		}		if(!fileGetDir(f, &de)){			consPrint("%s: %R\n");			fileDecRef(f);			continue;		}		fsysPrintStat("\t", argv[i], &de);		deCleanup(&de);		fileDecRef(f);	}	vtRUnlock(fsys->fs->elk);	return 1;}static intfsysWstat(Fsys *fsys, int argc, char* argv[]){	File *f;	char *p;	DirEntry de;	char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n"		"\tuse - for any field to mean don't change";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc != 6)		return cliError(usage);	vtRLock(fsys->fs->elk);	if((f = fileOpen(fsys->fs, argv[0])) == nil){		vtSetError("console wstat - walk - %R");		vtRUnlock(fsys->fs->elk);		return 0;	}	if(!fileGetDir(f, &de)){		vtSetError("console wstat - stat - %R");		fileDecRef(f);		vtRUnlock(fsys->fs->elk);		return 0;	}	fsysPrintStat("\told: w", argv[0], &de);	if(strcmp(argv[1], "-") != 0){		if(!validFileName(argv[1])){			vtSetError("console wstat - bad elem");

⌨️ 快捷键说明

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