📄 9fsys.c
字号:
#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 + -