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

📄 9fsys.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "stdinc.h"#include "dat.h"#include "fns.h"#include "9.h"typedef struct Fsys Fsys;struct Fsys {	VtLock* lock;	char*	name;	char*	dev;	char*	venti;	Fs*	fs;	VtSession* session;	int	ref;	int	noauth;	int	noperm;	int	wstatallow;	Fsys*	next;};static struct {	VtLock*	lock;	Fsys*	head;	Fsys*	tail;	char*	curfsys;} sbox;static char *_argv0;#define argv0 _argv0static char FsysAll[] = "all";static char EFsysBusy[] = "fsys: '%s' busy";static char EFsysExists[] = "fsys: '%s' already exists";static char EFsysNoCurrent[] = "fsys: no current fsys";static char EFsysNotFound[] = "fsys: '%s' not found";static char EFsysNotOpen[] = "fsys: '%s' not open";static Fsys*_fsysGet(char* name){	Fsys *fsys;	if(name == nil || name[0] == '\0')		name = "main";	vtRLock(sbox.lock);	for(fsys = sbox.head; fsys != nil; fsys = fsys->next){		if(strcmp(name, fsys->name) == 0){			fsys->ref++;			break;		}	}	vtRUnlock(sbox.lock);	if(fsys == nil)		vtSetError(EFsysNotFound, name);	return fsys;}static intcmdPrintConfig(int argc, char* argv[]){	Fsys *fsys;	char *usage = "usage: printconfig";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc)		return cliError(usage);	vtRLock(sbox.lock);	for(fsys = sbox.head; fsys != nil; fsys = fsys->next){		consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev);		if(fsys->venti && fsys->venti[0])			consPrint("\tfsys %s venti %q\n", fsys->name, fsys->venti);	}	vtRUnlock(sbox.lock);	return 1;}Fsys*fsysGet(char* name){	Fsys *fsys;	if((fsys = _fsysGet(name)) == nil)		return nil;	vtLock(fsys->lock);	if(fsys->fs == nil){		vtSetError(EFsysNotOpen, fsys->name);		vtUnlock(fsys->lock);		fsysPut(fsys);		return nil;	}	vtUnlock(fsys->lock);	return fsys;}char*fsysGetName(Fsys* fsys){	return fsys->name;}Fsys*fsysIncRef(Fsys* fsys){	vtLock(sbox.lock);	fsys->ref++;	vtUnlock(sbox.lock);	return fsys;}voidfsysPut(Fsys* fsys){	vtLock(sbox.lock);	assert(fsys->ref > 0);	fsys->ref--;	vtUnlock(sbox.lock);}Fs*fsysGetFs(Fsys* fsys){	assert(fsys != nil && fsys->fs != nil);	return fsys->fs;}voidfsysFsRlock(Fsys* fsys){	vtRLock(fsys->fs->elk);}voidfsysFsRUnlock(Fsys* fsys){	vtRUnlock(fsys->fs->elk);}intfsysNoAuthCheck(Fsys* fsys){	return fsys->noauth;}intfsysNoPermCheck(Fsys* fsys){	return fsys->noperm;}intfsysWstatAllow(Fsys* fsys){	return fsys->wstatallow;}static char modechars[] = "YUGalLdHSATs";static ulong modebits[] = {	ModeSticky,	ModeSetUid,	ModeSetGid,	ModeAppend,	ModeExclusive,	ModeLink,	ModeDir,	ModeHidden,	ModeSystem,	ModeArchive,	ModeTemporary,	ModeSnapshot,	0};char*fsysModeString(ulong mode, char *buf){	int i;	char *p;	p = buf;	for(i=0; modebits[i]; i++)		if(mode & modebits[i])			*p++ = modechars[i];	sprint(p, "%luo", mode&0777);	return buf;}intfsysParseMode(char* s, ulong* mode){	ulong x, y;	char *p;	x = 0;	for(; *s < '0' || *s > '9'; s++){		if(*s == 0)			return 0;		p = strchr(modechars, *s);		if(p == nil)			return 0;		x |= modebits[p-modechars];	}	y = strtoul(s, &p, 8);	if(*p != '\0' || y > 0777)		return 0;	*mode = x|y;	return 1;}File*fsysGetRoot(Fsys* fsys, char* name){	File *root, *sub;	assert(fsys != nil && fsys->fs != nil);	root = fsGetRoot(fsys->fs);	if(name == nil || strcmp(name, "") == 0)		return root;	sub = fileWalk(root, name);	fileDecRef(root);	return sub;}static Fsys*fsysAlloc(char* name, char* dev){	Fsys *fsys;	vtLock(sbox.lock);	for(fsys = sbox.head; fsys != nil; fsys = fsys->next){		if(strcmp(fsys->name, name) != 0)			continue;		vtSetError(EFsysExists, name);		vtUnlock(sbox.lock);		return nil;	}	fsys = vtMemAllocZ(sizeof(Fsys));	fsys->lock = vtLockAlloc();	fsys->name = vtStrDup(name);	fsys->dev = vtStrDup(dev);	fsys->ref = 1;	if(sbox.tail != nil)		sbox.tail->next = fsys;	else		sbox.head = fsys;	sbox.tail = fsys;	vtUnlock(sbox.lock);	return fsys;}static intfsysClose(Fsys* fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] close";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc)		return cliError(usage);	return cliError("close isn't working yet; halt %s and then kill fossil",		fsys->name);	/*	 * Oooh. This could be hard. What if fsys->ref != 1?	 * Also, fsClose() either does the job or panics, can we	 * gracefully detect it's still busy?	 *	 * More thought and care needed here.	fsClose(fsys->fs);	fsys->fs = nil;	vtClose(fsys->session);	fsys->session = nil;	if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){		sbox.curfsys = nil;		consPrompt(nil);	}	return 1;	 */}static intfsysVac(Fsys* fsys, int argc, char* argv[]){	uchar score[VtScoreSize];	char *usage = "usage: [fsys name] vac path";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc != 1)		return cliError(usage);	if(!fsVac(fsys->fs, argv[0], score))		return 0;	consPrint("vac:%V\n", score);	return 1;}static intfsysSnap(Fsys* fsys, int argc, char* argv[]){	int doarchive;	char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]";	char *src, *dst;	src = nil;	dst = nil;	doarchive = 0;	ARGBEGIN{	default:		return cliError(usage);	case 'a':		doarchive = 1;		break;	case 'd':		if((dst = ARGF()) == nil)			return cliError(usage);		break;	case 's':		if((src = ARGF()) == nil)			return cliError(usage);		break;	}ARGEND	if(argc)		return cliError(usage);	if(!fsSnapshot(fsys->fs, src, dst, doarchive))		return 0;	return 1;}static intfsysSnapClean(Fsys *fsys, int argc, char* argv[]){	u32int arch, snap, life;	char *usage = "usage: [fsys name] snapclean [maxminutes]\n";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc > 1)		return cliError(usage);	if(argc == 1)		life = atoi(argv[0]);	else		snapGetTimes(fsys->fs->snap, &arch, &snap, &life);	fsSnapshotCleanup(fsys->fs, life);	return 1;}static intfsysSnapTime(Fsys* fsys, int argc, char* argv[]){	char buf[128], *x;	int hh, mm, changed;	u32int arch, snap, life;	char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]";	changed = 0;	snapGetTimes(fsys->fs->snap, &arch, &snap, &life);	ARGBEGIN{	case 'a':		changed = 1;		x = ARGF();		if(x == nil)			return cliError(usage);		if(strcmp(x, "none") == 0){			arch = ~(u32int)0;			break;		}		if(strlen(x) != 4 || strspn(x, "0123456789") != 4)			return cliError(usage);		hh = (x[0]-'0')*10 + x[1]-'0';		mm = (x[2]-'0')*10 + x[3]-'0';		if(hh >= 24 || mm >= 60)			return cliError(usage);		arch = hh*60+mm;		break;	case 's':		changed = 1;		x = ARGF();		if(x == nil)			return cliError(usage);		if(strcmp(x, "none") == 0){			snap = ~(u32int)0;			break;		}		snap = atoi(x);		break;	case 't':		changed = 1;		x = ARGF();		if(x == nil)			return cliError(usage);		if(strcmp(x, "none") == 0){			life = ~(u32int)0;			break;		}		life = atoi(x);		break;	default:		return cliError(usage);	}ARGEND	if(argc > 0)		return cliError(usage);	if(changed){		snapSetTimes(fsys->fs->snap, arch, snap, life);		return 1;	}	snapGetTimes(fsys->fs->snap, &arch, &snap, &life);	if(arch != ~(u32int)0)		sprint(buf, "-a %02d%02d", arch/60, arch%60);	else		sprint(buf, "-a none");	if(snap != ~(u32int)0)		sprint(buf+strlen(buf), " -s %d", snap);	else		sprint(buf+strlen(buf), " -s none");	if(life != ~(u32int)0)		sprint(buf+strlen(buf), " -t %ud", life);	else		sprint(buf+strlen(buf), " -t none");	consPrint("\tsnaptime %s\n", buf);	return 1;}static intfsysSync(Fsys* fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] sync";	int n;		ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc > 0)		return cliError(usage);	n = cacheDirty(fsys->fs->cache);	fsSync(fsys->fs);	consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n);	return 1;}static intfsysHalt(Fsys *fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] halt";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc > 0)		return cliError(usage);	fsHalt(fsys->fs);	return 1;}static intfsysUnhalt(Fsys *fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] unhalt";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc > 0)		return cliError(usage);	if(!fsys->fs->halted)		return cliError("file system %s not halted", fsys->name);	fsUnhalt(fsys->fs);	return 1;}static intfsysRemove(Fsys* fsys, int argc, char* argv[]){	File *file;	char *usage = "usage: [fsys name] remove path ...";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc == 0)		return cliError(usage);	vtRLock(fsys->fs->elk);	while(argc > 0){		if((file = fileOpen(fsys->fs, argv[0])) == nil)			consPrint("%s: %R\n", argv[0]);		else{			if(!fileRemove(file, uidadm))				consPrint("%s: %R\n", argv[0]);			fileDecRef(file);		}		argc--;		argv++;	}	vtRUnlock(fsys->fs->elk);	return 1;}static intfsysClri(Fsys* fsys, int argc, char* argv[]){	char *usage = "usage: [fsys name] clri path ...";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc == 0)		return cliError(usage);	vtRLock(fsys->fs->elk);	while(argc > 0){		if(!fileClriPath(fsys->fs, argv[0], uidadm))			consPrint("clri %s: %R\n", argv[0]);		argc--;		argv++;	}	vtRUnlock(fsys->fs->elk);	return 1;}/* * Inspect and edit the labels for blocks on disk. */static intfsysLabel(Fsys* fsys, int argc, char* argv[]){	Fs *fs;	Label l;	int n, r;	u32int addr;	Block *b, *bb;	char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]";	ARGBEGIN{	default:		return cliError(usage);	}ARGEND	if(argc != 1 && argc != 6)		return cliError(usage);	r = 0;	vtRLock(fsys->fs->elk);	fs = fsys->fs;	addr = strtoul(argv[0], 0, 0);	b = cacheLocal(fs->cache, PartData, addr, OReadOnly);	if(b == nil)		goto Out0;

⌨️ 快捷键说明

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