15e96a66cSDavid du Colombier #include "stdinc.h"
2b8a11165SDavid du Colombier #include <bio.h>
35e96a66cSDavid du Colombier #include "dat.h"
45e96a66cSDavid du Colombier #include "fns.h"
55e96a66cSDavid du Colombier #include "9.h"
65e96a66cSDavid du Colombier
77abd426fSDavid du Colombier struct Fsys {
8*d7aba6c3SDavid du Colombier QLock lock;
95e96a66cSDavid du Colombier
100c6300e7SDavid du Colombier char* name; /* copy here & Fs to ease error reporting */
115e96a66cSDavid du Colombier char* dev;
125e96a66cSDavid du Colombier char* venti;
135e96a66cSDavid du Colombier
145e96a66cSDavid du Colombier Fs* fs;
15*d7aba6c3SDavid du Colombier VtConn* session;
165e96a66cSDavid du Colombier int ref;
175e96a66cSDavid du Colombier
185e96a66cSDavid du Colombier int noauth;
195e96a66cSDavid du Colombier int noperm;
205e96a66cSDavid du Colombier int wstatallow;
215e96a66cSDavid du Colombier
225e96a66cSDavid du Colombier Fsys* next;
237abd426fSDavid du Colombier };
245e96a66cSDavid du Colombier
25b8a11165SDavid du Colombier int mempcnt; /* from fossil.c */
26b8a11165SDavid du Colombier
27b8a11165SDavid du Colombier int fsGetBlockSize(Fs *fs);
28b8a11165SDavid du Colombier
295e96a66cSDavid du Colombier static struct {
30*d7aba6c3SDavid du Colombier RWLock lock;
315e96a66cSDavid du Colombier Fsys* head;
325e96a66cSDavid du Colombier Fsys* tail;
335e96a66cSDavid du Colombier
345e96a66cSDavid du Colombier char* curfsys;
355e96a66cSDavid du Colombier } sbox;
365e96a66cSDavid du Colombier
375e96a66cSDavid du Colombier static char *_argv0;
385e96a66cSDavid du Colombier #define argv0 _argv0
395e96a66cSDavid du Colombier
4081cf8742SDavid du Colombier static char FsysAll[] = "all";
4181cf8742SDavid du Colombier
425e96a66cSDavid du Colombier static char EFsysBusy[] = "fsys: '%s' busy";
435e96a66cSDavid du Colombier static char EFsysExists[] = "fsys: '%s' already exists";
445e96a66cSDavid du Colombier static char EFsysNoCurrent[] = "fsys: no current fsys";
455e96a66cSDavid du Colombier static char EFsysNotFound[] = "fsys: '%s' not found";
465e96a66cSDavid du Colombier static char EFsysNotOpen[] = "fsys: '%s' not open";
475e96a66cSDavid du Colombier
48ea58ad6fSDavid du Colombier static char *
ventihost(char * host)49ea58ad6fSDavid du Colombier ventihost(char *host)
50ea58ad6fSDavid du Colombier {
51ea58ad6fSDavid du Colombier if(host != nil)
52*d7aba6c3SDavid du Colombier return vtstrdup(host);
53ea58ad6fSDavid du Colombier host = getenv("venti");
54ea58ad6fSDavid du Colombier if(host == nil)
55*d7aba6c3SDavid du Colombier host = vtstrdup("$venti");
56ea58ad6fSDavid du Colombier return host;
57ea58ad6fSDavid du Colombier }
58ea58ad6fSDavid du Colombier
59ea58ad6fSDavid du Colombier static void
prventihost(char * host)60ea58ad6fSDavid du Colombier prventihost(char *host)
61ea58ad6fSDavid du Colombier {
62ea58ad6fSDavid du Colombier char *vh;
63ea58ad6fSDavid du Colombier
64ea58ad6fSDavid du Colombier vh = ventihost(host);
65ea58ad6fSDavid du Colombier fprint(2, "%s: dialing venti at %s\n",
66ea58ad6fSDavid du Colombier argv0, netmkaddr(vh, 0, "venti"));
67ea58ad6fSDavid du Colombier free(vh);
68ea58ad6fSDavid du Colombier }
69ea58ad6fSDavid du Colombier
70*d7aba6c3SDavid du Colombier static VtConn *
myDial(char * host)71*d7aba6c3SDavid du Colombier myDial(char *host)
72ea58ad6fSDavid du Colombier {
73ea58ad6fSDavid du Colombier prventihost(host);
74*d7aba6c3SDavid du Colombier return vtdial(host);
75ea58ad6fSDavid du Colombier }
76ea58ad6fSDavid du Colombier
77ea58ad6fSDavid du Colombier static int
myRedial(VtConn * z,char * host)78*d7aba6c3SDavid du Colombier myRedial(VtConn *z, char *host)
79ea58ad6fSDavid du Colombier {
80ea58ad6fSDavid du Colombier prventihost(host);
81*d7aba6c3SDavid du Colombier return vtredial(z, host);
82ea58ad6fSDavid du Colombier }
83ea58ad6fSDavid du Colombier
845e96a66cSDavid du Colombier static Fsys*
_fsysGet(char * name)855e96a66cSDavid du Colombier _fsysGet(char* name)
865e96a66cSDavid du Colombier {
875e96a66cSDavid du Colombier Fsys *fsys;
885e96a66cSDavid du Colombier
895e96a66cSDavid du Colombier if(name == nil || name[0] == '\0')
905e96a66cSDavid du Colombier name = "main";
915e96a66cSDavid du Colombier
92*d7aba6c3SDavid du Colombier rlock(&sbox.lock);
935e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
945e96a66cSDavid du Colombier if(strcmp(name, fsys->name) == 0){
955e96a66cSDavid du Colombier fsys->ref++;
965e96a66cSDavid du Colombier break;
975e96a66cSDavid du Colombier }
985e96a66cSDavid du Colombier }
99*d7aba6c3SDavid du Colombier runlock(&sbox.lock);
1005e96a66cSDavid du Colombier if(fsys == nil)
101*d7aba6c3SDavid du Colombier werrstr(EFsysNotFound, name);
1025e96a66cSDavid du Colombier return fsys;
1035e96a66cSDavid du Colombier }
1045e96a66cSDavid du Colombier
1055e96a66cSDavid du Colombier static int
cmdPrintConfig(int argc,char * argv[])1065e96a66cSDavid du Colombier cmdPrintConfig(int argc, char* argv[])
1075e96a66cSDavid du Colombier {
1085e96a66cSDavid du Colombier Fsys *fsys;
1095e96a66cSDavid du Colombier char *usage = "usage: printconfig";
1105e96a66cSDavid du Colombier
1115e96a66cSDavid du Colombier ARGBEGIN{
1125e96a66cSDavid du Colombier default:
1135e96a66cSDavid du Colombier return cliError(usage);
1145e96a66cSDavid du Colombier }ARGEND
1155e96a66cSDavid du Colombier
1165e96a66cSDavid du Colombier if(argc)
1175e96a66cSDavid du Colombier return cliError(usage);
1185e96a66cSDavid du Colombier
119*d7aba6c3SDavid du Colombier rlock(&sbox.lock);
1205e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
1215e96a66cSDavid du Colombier consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev);
1225e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0])
1230c6300e7SDavid du Colombier consPrint("\tfsys %s venti %q\n", fsys->name,
1240c6300e7SDavid du Colombier fsys->venti);
1255e96a66cSDavid du Colombier }
126*d7aba6c3SDavid du Colombier runlock(&sbox.lock);
1275e96a66cSDavid du Colombier return 1;
1285e96a66cSDavid du Colombier }
1295e96a66cSDavid du Colombier
1305e96a66cSDavid du Colombier Fsys*
fsysGet(char * name)1315e96a66cSDavid du Colombier fsysGet(char* name)
1325e96a66cSDavid du Colombier {
1335e96a66cSDavid du Colombier Fsys *fsys;
1345e96a66cSDavid du Colombier
1355e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil)
1365e96a66cSDavid du Colombier return nil;
1375e96a66cSDavid du Colombier
138*d7aba6c3SDavid du Colombier qlock(&fsys->lock);
1395e96a66cSDavid du Colombier if(fsys->fs == nil){
140*d7aba6c3SDavid du Colombier werrstr(EFsysNotOpen, fsys->name);
141*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
1425e96a66cSDavid du Colombier fsysPut(fsys);
1435e96a66cSDavid du Colombier return nil;
1445e96a66cSDavid du Colombier }
145*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
1465e96a66cSDavid du Colombier
1475e96a66cSDavid du Colombier return fsys;
1485e96a66cSDavid du Colombier }
1495e96a66cSDavid du Colombier
15061201b97SDavid du Colombier char*
fsysGetName(Fsys * fsys)15161201b97SDavid du Colombier fsysGetName(Fsys* fsys)
15261201b97SDavid du Colombier {
15361201b97SDavid du Colombier return fsys->name;
15461201b97SDavid du Colombier }
15561201b97SDavid du Colombier
1565e96a66cSDavid du Colombier Fsys*
fsysIncRef(Fsys * fsys)1575e96a66cSDavid du Colombier fsysIncRef(Fsys* fsys)
1585e96a66cSDavid du Colombier {
159*d7aba6c3SDavid du Colombier wlock(&sbox.lock);
1605e96a66cSDavid du Colombier fsys->ref++;
161*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
1625e96a66cSDavid du Colombier
1635e96a66cSDavid du Colombier return fsys;
1645e96a66cSDavid du Colombier }
1655e96a66cSDavid du Colombier
1665e96a66cSDavid du Colombier void
fsysPut(Fsys * fsys)1675e96a66cSDavid du Colombier fsysPut(Fsys* fsys)
1685e96a66cSDavid du Colombier {
169*d7aba6c3SDavid du Colombier wlock(&sbox.lock);
1705e96a66cSDavid du Colombier assert(fsys->ref > 0);
1715e96a66cSDavid du Colombier fsys->ref--;
172*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
1735e96a66cSDavid du Colombier }
1745e96a66cSDavid du Colombier
1755e96a66cSDavid du Colombier Fs*
fsysGetFs(Fsys * fsys)1765e96a66cSDavid du Colombier fsysGetFs(Fsys* fsys)
1775e96a66cSDavid du Colombier {
1785e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil);
1795e96a66cSDavid du Colombier
1805e96a66cSDavid du Colombier return fsys->fs;
1815e96a66cSDavid du Colombier }
1825e96a66cSDavid du Colombier
1835e96a66cSDavid du Colombier void
fsysFsRlock(Fsys * fsys)1845e96a66cSDavid du Colombier fsysFsRlock(Fsys* fsys)
1855e96a66cSDavid du Colombier {
186*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
1875e96a66cSDavid du Colombier }
1885e96a66cSDavid du Colombier
1895e96a66cSDavid du Colombier void
fsysFsRUnlock(Fsys * fsys)1905e96a66cSDavid du Colombier fsysFsRUnlock(Fsys* fsys)
1915e96a66cSDavid du Colombier {
192*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
1935e96a66cSDavid du Colombier }
1945e96a66cSDavid du Colombier
1955e96a66cSDavid du Colombier int
fsysNoAuthCheck(Fsys * fsys)1965e96a66cSDavid du Colombier fsysNoAuthCheck(Fsys* fsys)
1975e96a66cSDavid du Colombier {
1985e96a66cSDavid du Colombier return fsys->noauth;
1995e96a66cSDavid du Colombier }
2005e96a66cSDavid du Colombier
2015e96a66cSDavid du Colombier int
fsysNoPermCheck(Fsys * fsys)2025e96a66cSDavid du Colombier fsysNoPermCheck(Fsys* fsys)
2035e96a66cSDavid du Colombier {
2045e96a66cSDavid du Colombier return fsys->noperm;
2055e96a66cSDavid du Colombier }
2065e96a66cSDavid du Colombier
2075e96a66cSDavid du Colombier int
fsysWstatAllow(Fsys * fsys)2085e96a66cSDavid du Colombier fsysWstatAllow(Fsys* fsys)
2095e96a66cSDavid du Colombier {
2105e96a66cSDavid du Colombier return fsys->wstatallow;
2115e96a66cSDavid du Colombier }
2125e96a66cSDavid du Colombier
2135e96a66cSDavid du Colombier static char modechars[] = "YUGalLdHSATs";
2145e96a66cSDavid du Colombier static ulong modebits[] = {
2155e96a66cSDavid du Colombier ModeSticky,
2165e96a66cSDavid du Colombier ModeSetUid,
2175e96a66cSDavid du Colombier ModeSetGid,
2185e96a66cSDavid du Colombier ModeAppend,
2195e96a66cSDavid du Colombier ModeExclusive,
2205e96a66cSDavid du Colombier ModeLink,
2215e96a66cSDavid du Colombier ModeDir,
2225e96a66cSDavid du Colombier ModeHidden,
2235e96a66cSDavid du Colombier ModeSystem,
2245e96a66cSDavid du Colombier ModeArchive,
2255e96a66cSDavid du Colombier ModeTemporary,
2265e96a66cSDavid du Colombier ModeSnapshot,
2275e96a66cSDavid du Colombier 0
2285e96a66cSDavid du Colombier };
2295e96a66cSDavid du Colombier
2305e96a66cSDavid du Colombier char*
fsysModeString(ulong mode,char * buf)2315e96a66cSDavid du Colombier fsysModeString(ulong mode, char *buf)
2325e96a66cSDavid du Colombier {
2335e96a66cSDavid du Colombier int i;
2345e96a66cSDavid du Colombier char *p;
2355e96a66cSDavid du Colombier
2365e96a66cSDavid du Colombier p = buf;
2375e96a66cSDavid du Colombier for(i=0; modebits[i]; i++)
2385e96a66cSDavid du Colombier if(mode & modebits[i])
2395e96a66cSDavid du Colombier *p++ = modechars[i];
2405e96a66cSDavid du Colombier sprint(p, "%luo", mode&0777);
2415e96a66cSDavid du Colombier return buf;
2425e96a66cSDavid du Colombier }
2435e96a66cSDavid du Colombier
2445e96a66cSDavid du Colombier int
fsysParseMode(char * s,ulong * mode)2455e96a66cSDavid du Colombier fsysParseMode(char* s, ulong* mode)
2465e96a66cSDavid du Colombier {
2475e96a66cSDavid du Colombier ulong x, y;
2485e96a66cSDavid du Colombier char *p;
2495e96a66cSDavid du Colombier
2505e96a66cSDavid du Colombier x = 0;
2515e96a66cSDavid du Colombier for(; *s < '0' || *s > '9'; s++){
2525e96a66cSDavid du Colombier if(*s == 0)
2535e96a66cSDavid du Colombier return 0;
2545e96a66cSDavid du Colombier p = strchr(modechars, *s);
2555e96a66cSDavid du Colombier if(p == nil)
2565e96a66cSDavid du Colombier return 0;
2575e96a66cSDavid du Colombier x |= modebits[p-modechars];
2585e96a66cSDavid du Colombier }
2595e96a66cSDavid du Colombier y = strtoul(s, &p, 8);
2605e96a66cSDavid du Colombier if(*p != '\0' || y > 0777)
2615e96a66cSDavid du Colombier return 0;
2625e96a66cSDavid du Colombier *mode = x|y;
2635e96a66cSDavid du Colombier return 1;
2645e96a66cSDavid du Colombier }
2655e96a66cSDavid du Colombier
2665e96a66cSDavid du Colombier File*
fsysGetRoot(Fsys * fsys,char * name)2675e96a66cSDavid du Colombier fsysGetRoot(Fsys* fsys, char* name)
2685e96a66cSDavid du Colombier {
2695e96a66cSDavid du Colombier File *root, *sub;
2705e96a66cSDavid du Colombier
2715e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil);
2725e96a66cSDavid du Colombier
2735e96a66cSDavid du Colombier root = fsGetRoot(fsys->fs);
2745e96a66cSDavid du Colombier if(name == nil || strcmp(name, "") == 0)
2755e96a66cSDavid du Colombier return root;
2765e96a66cSDavid du Colombier
2775e96a66cSDavid du Colombier sub = fileWalk(root, name);
2785e96a66cSDavid du Colombier fileDecRef(root);
2795e96a66cSDavid du Colombier
2805e96a66cSDavid du Colombier return sub;
2815e96a66cSDavid du Colombier }
2825e96a66cSDavid du Colombier
2835e96a66cSDavid du Colombier static Fsys*
fsysAlloc(char * name,char * dev)2845e96a66cSDavid du Colombier fsysAlloc(char* name, char* dev)
2855e96a66cSDavid du Colombier {
2865e96a66cSDavid du Colombier Fsys *fsys;
2875e96a66cSDavid du Colombier
288*d7aba6c3SDavid du Colombier wlock(&sbox.lock);
2895e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
2905e96a66cSDavid du Colombier if(strcmp(fsys->name, name) != 0)
2915e96a66cSDavid du Colombier continue;
292*d7aba6c3SDavid du Colombier werrstr(EFsysExists, name);
293*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
2945e96a66cSDavid du Colombier return nil;
2955e96a66cSDavid du Colombier }
2965e96a66cSDavid du Colombier
297*d7aba6c3SDavid du Colombier fsys = vtmallocz(sizeof(Fsys));
298*d7aba6c3SDavid du Colombier fsys->name = vtstrdup(name);
299*d7aba6c3SDavid du Colombier fsys->dev = vtstrdup(dev);
3005e96a66cSDavid du Colombier
3015e96a66cSDavid du Colombier fsys->ref = 1;
3025e96a66cSDavid du Colombier
3035e96a66cSDavid du Colombier if(sbox.tail != nil)
3045e96a66cSDavid du Colombier sbox.tail->next = fsys;
3055e96a66cSDavid du Colombier else
3065e96a66cSDavid du Colombier sbox.head = fsys;
3075e96a66cSDavid du Colombier sbox.tail = fsys;
308*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
3095e96a66cSDavid du Colombier
3105e96a66cSDavid du Colombier return fsys;
3115e96a66cSDavid du Colombier }
3125e96a66cSDavid du Colombier
3135e96a66cSDavid du Colombier static int
fsysClose(Fsys * fsys,int argc,char * argv[])3145e96a66cSDavid du Colombier fsysClose(Fsys* fsys, int argc, char* argv[])
3155e96a66cSDavid du Colombier {
3165e96a66cSDavid du Colombier char *usage = "usage: [fsys name] close";
3175e96a66cSDavid du Colombier
3185e96a66cSDavid du Colombier ARGBEGIN{
3195e96a66cSDavid du Colombier default:
3205e96a66cSDavid du Colombier return cliError(usage);
3215e96a66cSDavid du Colombier }ARGEND
3225e96a66cSDavid du Colombier if(argc)
3235e96a66cSDavid du Colombier return cliError(usage);
3245e96a66cSDavid du Colombier
32568412abfSDavid du Colombier return cliError("close isn't working yet; halt %s and then kill fossil",
32668412abfSDavid du Colombier fsys->name);
3275e96a66cSDavid du Colombier
3285e96a66cSDavid du Colombier /*
3295e96a66cSDavid du Colombier * Oooh. This could be hard. What if fsys->ref != 1?
3305e96a66cSDavid du Colombier * Also, fsClose() either does the job or panics, can we
3315e96a66cSDavid du Colombier * gracefully detect it's still busy?
3325e96a66cSDavid du Colombier *
3335e96a66cSDavid du Colombier * More thought and care needed here.
3345e96a66cSDavid du Colombier fsClose(fsys->fs);
3355e96a66cSDavid du Colombier fsys->fs = nil;
336*d7aba6c3SDavid du Colombier vtfreeconn(fsys->session);
3375e96a66cSDavid du Colombier fsys->session = nil;
3385e96a66cSDavid du Colombier
3395e96a66cSDavid du Colombier if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){
3405e96a66cSDavid du Colombier sbox.curfsys = nil;
3415e96a66cSDavid du Colombier consPrompt(nil);
3425e96a66cSDavid du Colombier }
3435e96a66cSDavid du Colombier
3445e96a66cSDavid du Colombier return 1;
34568412abfSDavid du Colombier */
3465e96a66cSDavid du Colombier }
3475e96a66cSDavid du Colombier
3485e96a66cSDavid du Colombier static int
fsysVac(Fsys * fsys,int argc,char * argv[])3495e96a66cSDavid du Colombier fsysVac(Fsys* fsys, int argc, char* argv[])
3505e96a66cSDavid du Colombier {
3515e96a66cSDavid du Colombier uchar score[VtScoreSize];
3525e96a66cSDavid du Colombier char *usage = "usage: [fsys name] vac path";
3535e96a66cSDavid du Colombier
3545e96a66cSDavid du Colombier ARGBEGIN{
3555e96a66cSDavid du Colombier default:
3565e96a66cSDavid du Colombier return cliError(usage);
3575e96a66cSDavid du Colombier }ARGEND
3585e96a66cSDavid du Colombier if(argc != 1)
3595e96a66cSDavid du Colombier return cliError(usage);
3605e96a66cSDavid du Colombier
3615e96a66cSDavid du Colombier if(!fsVac(fsys->fs, argv[0], score))
3625e96a66cSDavid du Colombier return 0;
3635e96a66cSDavid du Colombier
3645e96a66cSDavid du Colombier consPrint("vac:%V\n", score);
3655e96a66cSDavid du Colombier return 1;
3665e96a66cSDavid du Colombier }
3675e96a66cSDavid du Colombier
3685e96a66cSDavid du Colombier static int
fsysSnap(Fsys * fsys,int argc,char * argv[])3695e96a66cSDavid du Colombier fsysSnap(Fsys* fsys, int argc, char* argv[])
3705e96a66cSDavid du Colombier {
3715e96a66cSDavid du Colombier int doarchive;
372c3c4501eSDavid du Colombier char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]";
373c3c4501eSDavid du Colombier char *src, *dst;
3745e96a66cSDavid du Colombier
375c3c4501eSDavid du Colombier src = nil;
376c3c4501eSDavid du Colombier dst = nil;
3775e96a66cSDavid du Colombier doarchive = 0;
3785e96a66cSDavid du Colombier ARGBEGIN{
3795e96a66cSDavid du Colombier default:
3805e96a66cSDavid du Colombier return cliError(usage);
3815e96a66cSDavid du Colombier case 'a':
3825e96a66cSDavid du Colombier doarchive = 1;
3835e96a66cSDavid du Colombier break;
384c3c4501eSDavid du Colombier case 'd':
385c3c4501eSDavid du Colombier if((dst = ARGF()) == nil)
386c3c4501eSDavid du Colombier return cliError(usage);
387c3c4501eSDavid du Colombier break;
388c3c4501eSDavid du Colombier case 's':
389c3c4501eSDavid du Colombier if((src = ARGF()) == nil)
390c3c4501eSDavid du Colombier return cliError(usage);
391c3c4501eSDavid du Colombier break;
3925e96a66cSDavid du Colombier }ARGEND
3935e96a66cSDavid du Colombier if(argc)
3945e96a66cSDavid du Colombier return cliError(usage);
3955e96a66cSDavid du Colombier
396c3c4501eSDavid du Colombier if(!fsSnapshot(fsys->fs, src, dst, doarchive))
3975e96a66cSDavid du Colombier return 0;
3985e96a66cSDavid du Colombier
3995e96a66cSDavid du Colombier return 1;
4005e96a66cSDavid du Colombier }
4015e96a66cSDavid du Colombier
4025e96a66cSDavid du Colombier static int
fsysSnapClean(Fsys * fsys,int argc,char * argv[])403dc5a79c1SDavid du Colombier fsysSnapClean(Fsys *fsys, int argc, char* argv[])
404dc5a79c1SDavid du Colombier {
405dc5a79c1SDavid du Colombier u32int arch, snap, life;
406dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snapclean [maxminutes]\n";
407dc5a79c1SDavid du Colombier
408dc5a79c1SDavid du Colombier ARGBEGIN{
409dc5a79c1SDavid du Colombier default:
410dc5a79c1SDavid du Colombier return cliError(usage);
411dc5a79c1SDavid du Colombier }ARGEND
412dc5a79c1SDavid du Colombier
413dc5a79c1SDavid du Colombier if(argc > 1)
414dc5a79c1SDavid du Colombier return cliError(usage);
415dc5a79c1SDavid du Colombier if(argc == 1)
416f83f9c78SDavid du Colombier life = atoi(argv[0]);
417dc5a79c1SDavid du Colombier else
418dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
419dc5a79c1SDavid du Colombier
420dc5a79c1SDavid du Colombier fsSnapshotCleanup(fsys->fs, life);
421dc5a79c1SDavid du Colombier return 1;
422dc5a79c1SDavid du Colombier }
423dc5a79c1SDavid du Colombier
424dc5a79c1SDavid du Colombier static int
fsysSnapTime(Fsys * fsys,int argc,char * argv[])4255e96a66cSDavid du Colombier fsysSnapTime(Fsys* fsys, int argc, char* argv[])
4265e96a66cSDavid du Colombier {
427dc5a79c1SDavid du Colombier char buf[128], *x;
428dc5a79c1SDavid du Colombier int hh, mm, changed;
429dc5a79c1SDavid du Colombier u32int arch, snap, life;
430dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]";
4315e96a66cSDavid du Colombier
432dc5a79c1SDavid du Colombier changed = 0;
433dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
4345e96a66cSDavid du Colombier ARGBEGIN{
4355e96a66cSDavid du Colombier case 'a':
436dc5a79c1SDavid du Colombier changed = 1;
4375e96a66cSDavid du Colombier x = ARGF();
4385e96a66cSDavid du Colombier if(x == nil)
4395e96a66cSDavid du Colombier return cliError(usage);
4405e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){
4415e96a66cSDavid du Colombier arch = ~(u32int)0;
4425e96a66cSDavid du Colombier break;
4435e96a66cSDavid du Colombier }
4445e96a66cSDavid du Colombier if(strlen(x) != 4 || strspn(x, "0123456789") != 4)
4455e96a66cSDavid du Colombier return cliError(usage);
4465e96a66cSDavid du Colombier hh = (x[0]-'0')*10 + x[1]-'0';
4475e96a66cSDavid du Colombier mm = (x[2]-'0')*10 + x[3]-'0';
4485e96a66cSDavid du Colombier if(hh >= 24 || mm >= 60)
4495e96a66cSDavid du Colombier return cliError(usage);
4505e96a66cSDavid du Colombier arch = hh*60+mm;
4515e96a66cSDavid du Colombier break;
4525e96a66cSDavid du Colombier case 's':
453dc5a79c1SDavid du Colombier changed = 1;
4545e96a66cSDavid du Colombier x = ARGF();
4555e96a66cSDavid du Colombier if(x == nil)
4565e96a66cSDavid du Colombier return cliError(usage);
4575e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){
4585e96a66cSDavid du Colombier snap = ~(u32int)0;
4595e96a66cSDavid du Colombier break;
4605e96a66cSDavid du Colombier }
4615e96a66cSDavid du Colombier snap = atoi(x);
4625e96a66cSDavid du Colombier break;
463dc5a79c1SDavid du Colombier case 't':
464dc5a79c1SDavid du Colombier changed = 1;
465dc5a79c1SDavid du Colombier x = ARGF();
466dc5a79c1SDavid du Colombier if(x == nil)
467dc5a79c1SDavid du Colombier return cliError(usage);
468dc5a79c1SDavid du Colombier if(strcmp(x, "none") == 0){
469dc5a79c1SDavid du Colombier life = ~(u32int)0;
470dc5a79c1SDavid du Colombier break;
471dc5a79c1SDavid du Colombier }
472dc5a79c1SDavid du Colombier life = atoi(x);
473dc5a79c1SDavid du Colombier break;
4745e96a66cSDavid du Colombier default:
4755e96a66cSDavid du Colombier return cliError(usage);
4765e96a66cSDavid du Colombier }ARGEND
4775e96a66cSDavid du Colombier if(argc > 0)
4785e96a66cSDavid du Colombier return cliError(usage);
4795e96a66cSDavid du Colombier
480dc5a79c1SDavid du Colombier if(changed){
481dc5a79c1SDavid du Colombier snapSetTimes(fsys->fs->snap, arch, snap, life);
482dc5a79c1SDavid du Colombier return 1;
483dc5a79c1SDavid du Colombier }
484dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
4855e96a66cSDavid du Colombier if(arch != ~(u32int)0)
4865e96a66cSDavid du Colombier sprint(buf, "-a %02d%02d", arch/60, arch%60);
4875e96a66cSDavid du Colombier else
4885e96a66cSDavid du Colombier sprint(buf, "-a none");
4895e96a66cSDavid du Colombier if(snap != ~(u32int)0)
4905e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s %d", snap);
4915e96a66cSDavid du Colombier else
4925e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s none");
493dc5a79c1SDavid du Colombier if(life != ~(u32int)0)
494dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t %ud", life);
495dc5a79c1SDavid du Colombier else
496dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t none");
4975e96a66cSDavid du Colombier consPrint("\tsnaptime %s\n", buf);
4985e96a66cSDavid du Colombier return 1;
4995e96a66cSDavid du Colombier }
5005e96a66cSDavid du Colombier
5015e96a66cSDavid du Colombier static int
fsysSync(Fsys * fsys,int argc,char * argv[])5025e96a66cSDavid du Colombier fsysSync(Fsys* fsys, int argc, char* argv[])
5035e96a66cSDavid du Colombier {
5045e96a66cSDavid du Colombier char *usage = "usage: [fsys name] sync";
5050b9a5132SDavid du Colombier int n;
5065e96a66cSDavid du Colombier
5075e96a66cSDavid du Colombier ARGBEGIN{
5085e96a66cSDavid du Colombier default:
5095e96a66cSDavid du Colombier return cliError(usage);
5105e96a66cSDavid du Colombier }ARGEND
5115e96a66cSDavid du Colombier if(argc > 0)
5125e96a66cSDavid du Colombier return cliError(usage);
5135e96a66cSDavid du Colombier
5140b9a5132SDavid du Colombier n = cacheDirty(fsys->fs->cache);
5155e96a66cSDavid du Colombier fsSync(fsys->fs);
5160b9a5132SDavid du Colombier consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n);
51781cf8742SDavid du Colombier return 1;
51881cf8742SDavid du Colombier }
5195e96a66cSDavid du Colombier
52081cf8742SDavid du Colombier static int
fsysHalt(Fsys * fsys,int argc,char * argv[])52181cf8742SDavid du Colombier fsysHalt(Fsys *fsys, int argc, char* argv[])
52281cf8742SDavid du Colombier {
52381cf8742SDavid du Colombier char *usage = "usage: [fsys name] halt";
52481cf8742SDavid du Colombier
52581cf8742SDavid du Colombier ARGBEGIN{
52681cf8742SDavid du Colombier default:
52781cf8742SDavid du Colombier return cliError(usage);
52881cf8742SDavid du Colombier }ARGEND
52981cf8742SDavid du Colombier if(argc > 0)
53081cf8742SDavid du Colombier return cliError(usage);
53181cf8742SDavid du Colombier
53281cf8742SDavid du Colombier fsHalt(fsys->fs);
53381cf8742SDavid du Colombier return 1;
53481cf8742SDavid du Colombier }
53581cf8742SDavid du Colombier
53681cf8742SDavid du Colombier static int
fsysUnhalt(Fsys * fsys,int argc,char * argv[])53781cf8742SDavid du Colombier fsysUnhalt(Fsys *fsys, int argc, char* argv[])
53881cf8742SDavid du Colombier {
53981cf8742SDavid du Colombier char *usage = "usage: [fsys name] unhalt";
54081cf8742SDavid du Colombier
54181cf8742SDavid du Colombier ARGBEGIN{
54281cf8742SDavid du Colombier default:
54381cf8742SDavid du Colombier return cliError(usage);
54481cf8742SDavid du Colombier }ARGEND
54581cf8742SDavid du Colombier if(argc > 0)
54681cf8742SDavid du Colombier return cliError(usage);
54781cf8742SDavid du Colombier
54881cf8742SDavid du Colombier if(!fsys->fs->halted)
54981cf8742SDavid du Colombier return cliError("file system %s not halted", fsys->name);
55081cf8742SDavid du Colombier
55181cf8742SDavid du Colombier fsUnhalt(fsys->fs);
5525e96a66cSDavid du Colombier return 1;
5535e96a66cSDavid du Colombier }
5545e96a66cSDavid du Colombier
5555e96a66cSDavid du Colombier static int
fsysRemove(Fsys * fsys,int argc,char * argv[])5565e96a66cSDavid du Colombier fsysRemove(Fsys* fsys, int argc, char* argv[])
5575e96a66cSDavid du Colombier {
5585e96a66cSDavid du Colombier File *file;
5595e96a66cSDavid du Colombier char *usage = "usage: [fsys name] remove path ...";
5605e96a66cSDavid du Colombier
5615e96a66cSDavid du Colombier ARGBEGIN{
5625e96a66cSDavid du Colombier default:
5635e96a66cSDavid du Colombier return cliError(usage);
5645e96a66cSDavid du Colombier }ARGEND
5655e96a66cSDavid du Colombier if(argc == 0)
5665e96a66cSDavid du Colombier return cliError(usage);
5675e96a66cSDavid du Colombier
568*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
5695e96a66cSDavid du Colombier while(argc > 0){
5705e96a66cSDavid du Colombier if((file = fileOpen(fsys->fs, argv[0])) == nil)
571*d7aba6c3SDavid du Colombier consPrint("%s: %r\n", argv[0]);
5725e96a66cSDavid du Colombier else{
5735e96a66cSDavid du Colombier if(!fileRemove(file, uidadm))
574*d7aba6c3SDavid du Colombier consPrint("%s: %r\n", argv[0]);
5755e96a66cSDavid du Colombier fileDecRef(file);
5765e96a66cSDavid du Colombier }
5775e96a66cSDavid du Colombier argc--;
5785e96a66cSDavid du Colombier argv++;
5795e96a66cSDavid du Colombier }
580*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
5815e96a66cSDavid du Colombier
5825e96a66cSDavid du Colombier return 1;
5835e96a66cSDavid du Colombier }
5845e96a66cSDavid du Colombier
5855e96a66cSDavid du Colombier static int
fsysClri(Fsys * fsys,int argc,char * argv[])5865e96a66cSDavid du Colombier fsysClri(Fsys* fsys, int argc, char* argv[])
5875e96a66cSDavid du Colombier {
5885e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clri path ...";
5895e96a66cSDavid du Colombier
5905e96a66cSDavid du Colombier ARGBEGIN{
5915e96a66cSDavid du Colombier default:
5925e96a66cSDavid du Colombier return cliError(usage);
5935e96a66cSDavid du Colombier }ARGEND
5945e96a66cSDavid du Colombier if(argc == 0)
5955e96a66cSDavid du Colombier return cliError(usage);
5965e96a66cSDavid du Colombier
597*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
5985e96a66cSDavid du Colombier while(argc > 0){
599dc5a79c1SDavid du Colombier if(!fileClriPath(fsys->fs, argv[0], uidadm))
600*d7aba6c3SDavid du Colombier consPrint("clri %s: %r\n", argv[0]);
6015e96a66cSDavid du Colombier argc--;
6025e96a66cSDavid du Colombier argv++;
6035e96a66cSDavid du Colombier }
604*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
6055e96a66cSDavid du Colombier
6065e96a66cSDavid du Colombier return 1;
6075e96a66cSDavid du Colombier }
6085e96a66cSDavid du Colombier
6095e96a66cSDavid du Colombier /*
6105e96a66cSDavid du Colombier * Inspect and edit the labels for blocks on disk.
6115e96a66cSDavid du Colombier */
6125e96a66cSDavid du Colombier static int
fsysLabel(Fsys * fsys,int argc,char * argv[])6135e96a66cSDavid du Colombier fsysLabel(Fsys* fsys, int argc, char* argv[])
6145e96a66cSDavid du Colombier {
6155e96a66cSDavid du Colombier Fs *fs;
6165e96a66cSDavid du Colombier Label l;
6175e96a66cSDavid du Colombier int n, r;
6185e96a66cSDavid du Colombier u32int addr;
6195e96a66cSDavid du Colombier Block *b, *bb;
6205e96a66cSDavid du Colombier char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]";
6215e96a66cSDavid du Colombier
6225e96a66cSDavid du Colombier ARGBEGIN{
6235e96a66cSDavid du Colombier default:
6245e96a66cSDavid du Colombier return cliError(usage);
6255e96a66cSDavid du Colombier }ARGEND
6265e96a66cSDavid du Colombier if(argc != 1 && argc != 6)
6275e96a66cSDavid du Colombier return cliError(usage);
6285e96a66cSDavid du Colombier
6295e96a66cSDavid du Colombier r = 0;
630*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
6315e96a66cSDavid du Colombier
6325e96a66cSDavid du Colombier fs = fsys->fs;
6335e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
6345e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
6355e96a66cSDavid du Colombier if(b == nil)
6365e96a66cSDavid du Colombier goto Out0;
6375e96a66cSDavid du Colombier
6385e96a66cSDavid du Colombier l = b->l;
6395e96a66cSDavid du Colombier consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n",
6405e96a66cSDavid du Colombier argc==6 ? "old: " : "", addr, l.type, l.state,
6415e96a66cSDavid du Colombier l.epoch, l.epochClose, l.tag);
6425e96a66cSDavid du Colombier
6435e96a66cSDavid du Colombier if(argc == 6){
6445e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0)
6455e96a66cSDavid du Colombier l.type = atoi(argv[1]);
6465e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0)
6475e96a66cSDavid du Colombier l.state = atoi(argv[2]);
6485e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0)
6495e96a66cSDavid du Colombier l.epoch = strtoul(argv[3], 0, 0);
6505e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0)
6515e96a66cSDavid du Colombier l.epochClose = strtoul(argv[4], 0, 0);
6525e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0)
6535e96a66cSDavid du Colombier l.tag = strtoul(argv[5], 0, 0);
6545e96a66cSDavid du Colombier
6555e96a66cSDavid du Colombier consPrint("new: label %#ux %ud %ud %ud %ud %#x\n",
6565e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
6575e96a66cSDavid du Colombier bb = _blockSetLabel(b, &l);
6585e96a66cSDavid du Colombier if(bb == nil)
6595e96a66cSDavid du Colombier goto Out1;
6605e96a66cSDavid du Colombier n = 0;
6615e96a66cSDavid du Colombier for(;;){
662e12a9870SDavid du Colombier if(blockWrite(bb, Waitlock)){
6635e96a66cSDavid du Colombier while(bb->iostate != BioClean){
6645e96a66cSDavid du Colombier assert(bb->iostate == BioWriting);
665*d7aba6c3SDavid du Colombier rsleep(&bb->ioready);
6665e96a66cSDavid du Colombier }
6675e96a66cSDavid du Colombier break;
6685e96a66cSDavid du Colombier }
669*d7aba6c3SDavid du Colombier consPrint("blockWrite: %r\n");
6705e96a66cSDavid du Colombier if(n++ >= 5){
6715e96a66cSDavid du Colombier consPrint("giving up\n");
6725e96a66cSDavid du Colombier break;
6735e96a66cSDavid du Colombier }
6745e96a66cSDavid du Colombier sleep(5*1000);
6755e96a66cSDavid du Colombier }
6765e96a66cSDavid du Colombier blockPut(bb);
6775e96a66cSDavid du Colombier }
6785e96a66cSDavid du Colombier r = 1;
6795e96a66cSDavid du Colombier Out1:
6805e96a66cSDavid du Colombier blockPut(b);
6815e96a66cSDavid du Colombier Out0:
682*d7aba6c3SDavid du Colombier runlock(&fs->elk);
6835e96a66cSDavid du Colombier
6845e96a66cSDavid du Colombier return r;
6855e96a66cSDavid du Colombier }
6865e96a66cSDavid du Colombier
6875e96a66cSDavid du Colombier /*
6885e96a66cSDavid du Colombier * Inspect and edit the blocks on disk.
6895e96a66cSDavid du Colombier */
6905e96a66cSDavid du Colombier static int
fsysBlock(Fsys * fsys,int argc,char * argv[])6915e96a66cSDavid du Colombier fsysBlock(Fsys* fsys, int argc, char* argv[])
6925e96a66cSDavid du Colombier {
6935e96a66cSDavid du Colombier Fs *fs;
6945e96a66cSDavid du Colombier char *s;
6955e96a66cSDavid du Colombier Block *b;
6965e96a66cSDavid du Colombier uchar *buf;
6975e96a66cSDavid du Colombier u32int addr;
6985e96a66cSDavid du Colombier int c, count, i, offset;
6995e96a66cSDavid du Colombier char *usage = "usage: [fsys name] block addr offset [count [data]]";
7005e96a66cSDavid du Colombier
7015e96a66cSDavid du Colombier ARGBEGIN{
7025e96a66cSDavid du Colombier default:
7035e96a66cSDavid du Colombier return cliError(usage);
7045e96a66cSDavid du Colombier }ARGEND
7055e96a66cSDavid du Colombier if(argc < 2 || argc > 4)
7065e96a66cSDavid du Colombier return cliError(usage);
7075e96a66cSDavid du Colombier
7085e96a66cSDavid du Colombier fs = fsys->fs;
7095e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
7105e96a66cSDavid du Colombier offset = strtoul(argv[1], 0, 0);
7115e96a66cSDavid du Colombier if(offset < 0 || offset >= fs->blockSize){
712*d7aba6c3SDavid du Colombier werrstr("bad offset");
7135e96a66cSDavid du Colombier return 0;
7145e96a66cSDavid du Colombier }
7155e96a66cSDavid du Colombier if(argc > 2)
7165e96a66cSDavid du Colombier count = strtoul(argv[2], 0, 0);
7175e96a66cSDavid du Colombier else
7185e96a66cSDavid du Colombier count = 100000000;
7195e96a66cSDavid du Colombier if(offset+count > fs->blockSize)
7205e96a66cSDavid du Colombier count = fs->blockSize - count;
7215e96a66cSDavid du Colombier
722*d7aba6c3SDavid du Colombier rlock(&fs->elk);
7235e96a66cSDavid du Colombier
7245e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
7255e96a66cSDavid du Colombier if(b == nil){
726*d7aba6c3SDavid du Colombier werrstr("cacheLocal %#ux: %r", addr);
727*d7aba6c3SDavid du Colombier runlock(&fs->elk);
7285e96a66cSDavid du Colombier return 0;
7295e96a66cSDavid du Colombier }
7305e96a66cSDavid du Colombier
7315e96a66cSDavid du Colombier consPrint("\t%sblock %#ux %ud %ud %.*H\n",
7325e96a66cSDavid du Colombier argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset);
7335e96a66cSDavid du Colombier
7345e96a66cSDavid du Colombier if(argc == 4){
7355e96a66cSDavid du Colombier s = argv[3];
7365e96a66cSDavid du Colombier if(strlen(s) != 2*count){
737*d7aba6c3SDavid du Colombier werrstr("bad data count");
7385e96a66cSDavid du Colombier goto Out;
7395e96a66cSDavid du Colombier }
740*d7aba6c3SDavid du Colombier buf = vtmallocz(count);
7415e96a66cSDavid du Colombier for(i = 0; i < count*2; i++){
7425e96a66cSDavid du Colombier if(s[i] >= '0' && s[i] <= '9')
7435e96a66cSDavid du Colombier c = s[i] - '0';
7445e96a66cSDavid du Colombier else if(s[i] >= 'a' && s[i] <= 'f')
7455e96a66cSDavid du Colombier c = s[i] - 'a' + 10;
7465e96a66cSDavid du Colombier else if(s[i] >= 'A' && s[i] <= 'F')
7475e96a66cSDavid du Colombier c = s[i] - 'A' + 10;
7485e96a66cSDavid du Colombier else{
749*d7aba6c3SDavid du Colombier werrstr("bad hex");
750*d7aba6c3SDavid du Colombier vtfree(buf);
7515e96a66cSDavid du Colombier goto Out;
7525e96a66cSDavid du Colombier }
7535e96a66cSDavid du Colombier if((i & 1) == 0)
7545e96a66cSDavid du Colombier c <<= 4;
7555e96a66cSDavid du Colombier buf[i>>1] |= c;
7565e96a66cSDavid du Colombier }
7575e96a66cSDavid du Colombier memmove(b->data+offset, buf, count);
7585e96a66cSDavid du Colombier consPrint("\tnew: block %#ux %ud %ud %.*H\n",
7595e96a66cSDavid du Colombier addr, offset, count, count, b->data+offset);
7605e96a66cSDavid du Colombier blockDirty(b);
7615e96a66cSDavid du Colombier }
7625e96a66cSDavid du Colombier
7635e96a66cSDavid du Colombier Out:
7645e96a66cSDavid du Colombier blockPut(b);
765*d7aba6c3SDavid du Colombier runlock(&fs->elk);
7665e96a66cSDavid du Colombier
7675e96a66cSDavid du Colombier return 1;
7685e96a66cSDavid du Colombier }
7695e96a66cSDavid du Colombier
7705e96a66cSDavid du Colombier /*
7715e96a66cSDavid du Colombier * Free a disk block.
7725e96a66cSDavid du Colombier */
7735e96a66cSDavid du Colombier static int
fsysBfree(Fsys * fsys,int argc,char * argv[])7745e96a66cSDavid du Colombier fsysBfree(Fsys* fsys, int argc, char* argv[])
7755e96a66cSDavid du Colombier {
7765e96a66cSDavid du Colombier Fs *fs;
7775e96a66cSDavid du Colombier Label l;
7785e96a66cSDavid du Colombier char *p;
7795e96a66cSDavid du Colombier Block *b;
7805e96a66cSDavid du Colombier u32int addr;
7815e96a66cSDavid du Colombier char *usage = "usage: [fsys name] bfree addr ...";
7825e96a66cSDavid du Colombier
7835e96a66cSDavid du Colombier ARGBEGIN{
7845e96a66cSDavid du Colombier default:
7855e96a66cSDavid du Colombier return cliError(usage);
7865e96a66cSDavid du Colombier }ARGEND
7875e96a66cSDavid du Colombier if(argc == 0)
7885e96a66cSDavid du Colombier return cliError(usage);
7895e96a66cSDavid du Colombier
7905e96a66cSDavid du Colombier fs = fsys->fs;
791*d7aba6c3SDavid du Colombier rlock(&fs->elk);
7925e96a66cSDavid du Colombier while(argc > 0){
7935e96a66cSDavid du Colombier addr = strtoul(argv[0], &p, 0);
7945e96a66cSDavid du Colombier if(*p != '\0'){
7950c6300e7SDavid du Colombier consPrint("bad address - '%ud'\n", addr);
7965e96a66cSDavid du Colombier /* syntax error; let's stop */
797*d7aba6c3SDavid du Colombier runlock(&fs->elk);
7985e96a66cSDavid du Colombier return 0;
7995e96a66cSDavid du Colombier }
8005e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
8015e96a66cSDavid du Colombier if(b == nil){
802*d7aba6c3SDavid du Colombier consPrint("loading %#ux: %r\n", addr);
8035e96a66cSDavid du Colombier continue;
8045e96a66cSDavid du Colombier }
8055e96a66cSDavid du Colombier l = b->l;
806e569ccb5SDavid du Colombier if(l.state == BsFree)
807e569ccb5SDavid du Colombier consPrint("%#ux is already free\n", addr);
808e569ccb5SDavid du Colombier else{
8095e96a66cSDavid du Colombier consPrint("label %#ux %ud %ud %ud %ud %#x\n",
8105e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
8115e96a66cSDavid du Colombier l.state = BsFree;
8125e96a66cSDavid du Colombier l.type = BtMax;
8135e96a66cSDavid du Colombier l.tag = 0;
8145e96a66cSDavid du Colombier l.epoch = 0;
8155e96a66cSDavid du Colombier l.epochClose = 0;
816e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0))
817*d7aba6c3SDavid du Colombier consPrint("freeing %#ux: %r\n", addr);
818e569ccb5SDavid du Colombier }
8195e96a66cSDavid du Colombier blockPut(b);
8205e96a66cSDavid du Colombier argc--;
8215e96a66cSDavid du Colombier argv++;
8225e96a66cSDavid du Colombier }
823*d7aba6c3SDavid du Colombier runlock(&fs->elk);
8245e96a66cSDavid du Colombier
8255e96a66cSDavid du Colombier return 1;
8265e96a66cSDavid du Colombier }
8275e96a66cSDavid du Colombier
8287abd426fSDavid du Colombier static int
fsysDf(Fsys * fsys,int argc,char * argv[])8297abd426fSDavid du Colombier fsysDf(Fsys *fsys, int argc, char* argv[])
8307abd426fSDavid du Colombier {
8317abd426fSDavid du Colombier char *usage = "usage: [fsys name] df";
8327abd426fSDavid du Colombier u32int used, tot, bsize;
8337abd426fSDavid du Colombier Fs *fs;
8347abd426fSDavid du Colombier
8357abd426fSDavid du Colombier ARGBEGIN{
8367abd426fSDavid du Colombier default:
8377abd426fSDavid du Colombier return cliError(usage);
8387abd426fSDavid du Colombier }ARGEND
8397abd426fSDavid du Colombier if(argc != 0)
8407abd426fSDavid du Colombier return cliError(usage);
8417abd426fSDavid du Colombier
8427abd426fSDavid du Colombier fs = fsys->fs;
8437abd426fSDavid du Colombier cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize);
844e12a9870SDavid du Colombier consPrint("\t%s: %,llud used + %,llud free = %,llud (%.1f%% used)\n",
845dc5a79c1SDavid du Colombier fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize,
846e12a9870SDavid du Colombier tot*(vlong)bsize, used*100.0/tot);
8477abd426fSDavid du Colombier return 1;
8487abd426fSDavid du Colombier }
8497abd426fSDavid du Colombier
8505e96a66cSDavid du Colombier /*
8515e96a66cSDavid du Colombier * Zero an entry or a pointer.
8525e96a66cSDavid du Colombier */
8535e96a66cSDavid du Colombier static int
fsysClrep(Fsys * fsys,int argc,char * argv[],int ch)8545e96a66cSDavid du Colombier fsysClrep(Fsys* fsys, int argc, char* argv[], int ch)
8555e96a66cSDavid du Colombier {
8565e96a66cSDavid du Colombier Fs *fs;
8575e96a66cSDavid du Colombier Entry e;
8585e96a66cSDavid du Colombier Block *b;
8595e96a66cSDavid du Colombier u32int addr;
8605e96a66cSDavid du Colombier int i, max, offset, sz;
8615e96a66cSDavid du Colombier uchar zero[VtEntrySize];
8625e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clr%c addr offset ...";
8635e96a66cSDavid du Colombier
8645e96a66cSDavid du Colombier ARGBEGIN{
8655e96a66cSDavid du Colombier default:
8665e96a66cSDavid du Colombier return cliError(usage, ch);
8675e96a66cSDavid du Colombier }ARGEND
8685e96a66cSDavid du Colombier if(argc < 2)
8695e96a66cSDavid du Colombier return cliError(usage, ch);
8705e96a66cSDavid du Colombier
8715e96a66cSDavid du Colombier fs = fsys->fs;
872*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
8735e96a66cSDavid du Colombier
8745e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
8755e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
8765e96a66cSDavid du Colombier if(b == nil){
877*d7aba6c3SDavid du Colombier werrstr("cacheLocal %#ux: %r", addr);
8785e96a66cSDavid du Colombier Err:
879*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
8805e96a66cSDavid du Colombier return 0;
8815e96a66cSDavid du Colombier }
8825e96a66cSDavid du Colombier
8835e96a66cSDavid du Colombier switch(ch){
8845e96a66cSDavid du Colombier default:
885*d7aba6c3SDavid du Colombier werrstr("clrep");
8865e96a66cSDavid du Colombier goto Err;
8875e96a66cSDavid du Colombier case 'e':
8885e96a66cSDavid du Colombier if(b->l.type != BtDir){
889*d7aba6c3SDavid du Colombier werrstr("wrong block type");
8905e96a66cSDavid du Colombier goto Err;
8915e96a66cSDavid du Colombier }
8925e96a66cSDavid du Colombier sz = VtEntrySize;
8935e96a66cSDavid du Colombier memset(&e, 0, sizeof e);
8945e96a66cSDavid du Colombier entryPack(&e, zero, 0);
8955e96a66cSDavid du Colombier break;
8965e96a66cSDavid du Colombier case 'p':
8975e96a66cSDavid du Colombier if(b->l.type == BtDir || b->l.type == BtData){
898*d7aba6c3SDavid du Colombier werrstr("wrong block type");
8995e96a66cSDavid du Colombier goto Err;
9005e96a66cSDavid du Colombier }
9015e96a66cSDavid du Colombier sz = VtScoreSize;
902*d7aba6c3SDavid du Colombier memmove(zero, vtzeroscore, VtScoreSize);
9035e96a66cSDavid du Colombier break;
9045e96a66cSDavid du Colombier }
9055e96a66cSDavid du Colombier max = fs->blockSize/sz;
9065e96a66cSDavid du Colombier
9075e96a66cSDavid du Colombier for(i = 1; i < argc; i++){
9085e96a66cSDavid du Colombier offset = atoi(argv[i]);
9095e96a66cSDavid du Colombier if(offset >= max){
9105e96a66cSDavid du Colombier consPrint("\toffset %d too large (>= %d)\n", i, max);
9115e96a66cSDavid du Colombier continue;
9125e96a66cSDavid du Colombier }
9135e96a66cSDavid du Colombier consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz);
9145e96a66cSDavid du Colombier memmove(b->data+offset*sz, zero, sz);
9155e96a66cSDavid du Colombier }
9165e96a66cSDavid du Colombier blockDirty(b);
9175e96a66cSDavid du Colombier blockPut(b);
918*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
9195e96a66cSDavid du Colombier
9205e96a66cSDavid du Colombier return 1;
9215e96a66cSDavid du Colombier }
9225e96a66cSDavid du Colombier
9235e96a66cSDavid du Colombier static int
fsysClre(Fsys * fsys,int argc,char * argv[])9245e96a66cSDavid du Colombier fsysClre(Fsys* fsys, int argc, char* argv[])
9255e96a66cSDavid du Colombier {
9265e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'e');
9275e96a66cSDavid du Colombier }
9285e96a66cSDavid du Colombier
9295e96a66cSDavid du Colombier static int
fsysClrp(Fsys * fsys,int argc,char * argv[])9305e96a66cSDavid du Colombier fsysClrp(Fsys* fsys, int argc, char* argv[])
9315e96a66cSDavid du Colombier {
9325e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'p');
9335e96a66cSDavid du Colombier }
9345e96a66cSDavid du Colombier
9355e96a66cSDavid du Colombier static int
fsysEsearch1(File * f,char * s,u32int elo)9365e96a66cSDavid du Colombier fsysEsearch1(File* f, char* s, u32int elo)
9375e96a66cSDavid du Colombier {
9385e96a66cSDavid du Colombier int n, r;
9395e96a66cSDavid du Colombier DirEntry de;
9405e96a66cSDavid du Colombier DirEntryEnum *dee;
9415e96a66cSDavid du Colombier File *ff;
9425e96a66cSDavid du Colombier Entry e, ee;
9435e96a66cSDavid du Colombier char *t;
9445e96a66cSDavid du Colombier
9455e96a66cSDavid du Colombier dee = deeOpen(f);
9465e96a66cSDavid du Colombier if(dee == nil)
9475e96a66cSDavid du Colombier return 0;
9485e96a66cSDavid du Colombier
9495e96a66cSDavid du Colombier n = 0;
9505e96a66cSDavid du Colombier for(;;){
9515e96a66cSDavid du Colombier r = deeRead(dee, &de);
9525e96a66cSDavid du Colombier if(r < 0){
953*d7aba6c3SDavid du Colombier consPrint("\tdeeRead %s/%s: %r\n", s, de.elem);
9545e96a66cSDavid du Colombier break;
9555e96a66cSDavid du Colombier }
9565e96a66cSDavid du Colombier if(r == 0)
9575e96a66cSDavid du Colombier break;
9585e96a66cSDavid du Colombier if(de.mode & ModeSnapshot){
9595e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil)
960*d7aba6c3SDavid du Colombier consPrint("\tcannot walk %s/%s: %r\n", s, de.elem);
9615e96a66cSDavid du Colombier else{
962e569ccb5SDavid du Colombier if(!fileGetSources(ff, &e, &ee))
963*d7aba6c3SDavid du Colombier consPrint("\tcannot get sources for %s/%s: %r\n", s, de.elem);
9645e96a66cSDavid du Colombier else if(e.snap != 0 && e.snap < elo){
9655e96a66cSDavid du Colombier consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem);
9665e96a66cSDavid du Colombier n++;
9675e96a66cSDavid du Colombier }
9685e96a66cSDavid du Colombier fileDecRef(ff);
9695e96a66cSDavid du Colombier }
9705e96a66cSDavid du Colombier }
9715e96a66cSDavid du Colombier else if(de.mode & ModeDir){
9725e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil)
973*d7aba6c3SDavid du Colombier consPrint("\tcannot walk %s/%s: %r\n", s, de.elem);
9745e96a66cSDavid du Colombier else{
975f8e525acSDavid du Colombier t = smprint("%s/%s", s, de.elem);
9765e96a66cSDavid du Colombier n += fsysEsearch1(ff, t, elo);
977*d7aba6c3SDavid du Colombier vtfree(t);
9785e96a66cSDavid du Colombier fileDecRef(ff);
9795e96a66cSDavid du Colombier }
9805e96a66cSDavid du Colombier }
9815e96a66cSDavid du Colombier deCleanup(&de);
9825e96a66cSDavid du Colombier if(r < 0)
9835e96a66cSDavid du Colombier break;
9845e96a66cSDavid du Colombier }
9855e96a66cSDavid du Colombier deeClose(dee);
9865e96a66cSDavid du Colombier
9875e96a66cSDavid du Colombier return n;
9885e96a66cSDavid du Colombier }
9895e96a66cSDavid du Colombier
9905e96a66cSDavid du Colombier static int
fsysEsearch(Fs * fs,char * path,u32int elo)9915e96a66cSDavid du Colombier fsysEsearch(Fs* fs, char* path, u32int elo)
9925e96a66cSDavid du Colombier {
9935e96a66cSDavid du Colombier int n;
9945e96a66cSDavid du Colombier File *f;
9955e96a66cSDavid du Colombier DirEntry de;
9965e96a66cSDavid du Colombier
9975e96a66cSDavid du Colombier f = fileOpen(fs, path);
9985e96a66cSDavid du Colombier if(f == nil)
9995e96a66cSDavid du Colombier return 0;
10005e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
1001*d7aba6c3SDavid du Colombier consPrint("\tfileGetDir %s failed: %r\n", path);
10025e96a66cSDavid du Colombier fileDecRef(f);
10035e96a66cSDavid du Colombier return 0;
10045e96a66cSDavid du Colombier }
10055e96a66cSDavid du Colombier if((de.mode & ModeDir) == 0){
10065e96a66cSDavid du Colombier fileDecRef(f);
10075e96a66cSDavid du Colombier deCleanup(&de);
10085e96a66cSDavid du Colombier return 0;
10095e96a66cSDavid du Colombier }
10105e96a66cSDavid du Colombier deCleanup(&de);
10115e96a66cSDavid du Colombier n = fsysEsearch1(f, path, elo);
10125e96a66cSDavid du Colombier fileDecRef(f);
10135e96a66cSDavid du Colombier return n;
10145e96a66cSDavid du Colombier }
10155e96a66cSDavid du Colombier
10165e96a66cSDavid du Colombier static int
fsysEpoch(Fsys * fsys,int argc,char * argv[])10175e96a66cSDavid du Colombier fsysEpoch(Fsys* fsys, int argc, char* argv[])
10185e96a66cSDavid du Colombier {
10195e96a66cSDavid du Colombier Fs *fs;
1020dc5a79c1SDavid du Colombier int force, n, remove;
10215e96a66cSDavid du Colombier u32int low, old;
1022dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] epoch [[-ry] low]";
10235e96a66cSDavid du Colombier
10245e96a66cSDavid du Colombier force = 0;
1025dc5a79c1SDavid du Colombier remove = 0;
10265e96a66cSDavid du Colombier ARGBEGIN{
10275e96a66cSDavid du Colombier case 'y':
10285e96a66cSDavid du Colombier force = 1;
10295e96a66cSDavid du Colombier break;
1030dc5a79c1SDavid du Colombier case 'r':
1031dc5a79c1SDavid du Colombier remove = 1;
1032dc5a79c1SDavid du Colombier break;
10335e96a66cSDavid du Colombier default:
10345e96a66cSDavid du Colombier return cliError(usage);
10355e96a66cSDavid du Colombier }ARGEND
10365e96a66cSDavid du Colombier if(argc > 1)
10375e96a66cSDavid du Colombier return cliError(usage);
10385e96a66cSDavid du Colombier if(argc > 0)
10395e96a66cSDavid du Colombier low = strtoul(argv[0], 0, 0);
10405e96a66cSDavid du Colombier else
10415e96a66cSDavid du Colombier low = ~(u32int)0;
10425e96a66cSDavid du Colombier
10438a2c5ad0SDavid du Colombier if(low == 0)
10448a2c5ad0SDavid du Colombier return cliError("low epoch cannot be zero");
10458a2c5ad0SDavid du Colombier
10465e96a66cSDavid du Colombier fs = fsys->fs;
10475e96a66cSDavid du Colombier
1048*d7aba6c3SDavid du Colombier rlock(&fs->elk);
10495e96a66cSDavid du Colombier consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi);
105057195852SDavid du Colombier if(low == ~(u32int)0){
1051*d7aba6c3SDavid du Colombier runlock(&fs->elk);
105257195852SDavid du Colombier return 1;
105357195852SDavid du Colombier }
10545e96a66cSDavid du Colombier n = fsysEsearch(fsys->fs, "/archive", low);
10555e96a66cSDavid du Colombier n += fsysEsearch(fsys->fs, "/snapshot", low);
10565e96a66cSDavid du Colombier consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low);
1057*d7aba6c3SDavid du Colombier runlock(&fs->elk);
10585e96a66cSDavid du Colombier
10595e96a66cSDavid du Colombier /*
10605e96a66cSDavid du Colombier * There's a small race here -- a new snapshot with epoch < low might
10615e96a66cSDavid du Colombier * get introduced now that we unlocked fs->elk. Low has to
10625e96a66cSDavid du Colombier * be <= fs->ehi. Of course, in order for this to happen low has
10635e96a66cSDavid du Colombier * to be equal to the current fs->ehi _and_ a snapshot has to
10645e96a66cSDavid du Colombier * run right now. This is a small enough window that I don't care.
10655e96a66cSDavid du Colombier */
10665e96a66cSDavid du Colombier if(n != 0 && !force){
10675e96a66cSDavid du Colombier consPrint("\tnot setting low epoch\n");
10685e96a66cSDavid du Colombier return 1;
10695e96a66cSDavid du Colombier }
10705e96a66cSDavid du Colombier old = fs->elo;
10715e96a66cSDavid du Colombier if(!fsEpochLow(fs, low))
1072*d7aba6c3SDavid du Colombier consPrint("\tfsEpochLow: %r\n");
10735e96a66cSDavid du Colombier else{
10745e96a66cSDavid du Colombier consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old);
10755e96a66cSDavid du Colombier consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo);
10765e96a66cSDavid du Colombier if(fs->elo < low)
10775e96a66cSDavid du Colombier consPrint("\twarning: new low epoch < old low epoch\n");
1078dc5a79c1SDavid du Colombier if(force && remove)
1079dc5a79c1SDavid du Colombier fsSnapshotRemove(fs);
10805e96a66cSDavid du Colombier }
10815e96a66cSDavid du Colombier
10825e96a66cSDavid du Colombier return 1;
10835e96a66cSDavid du Colombier }
10845e96a66cSDavid du Colombier
10855e96a66cSDavid du Colombier static int
fsysCreate(Fsys * fsys,int argc,char * argv[])10865e96a66cSDavid du Colombier fsysCreate(Fsys* fsys, int argc, char* argv[])
10875e96a66cSDavid du Colombier {
10885e96a66cSDavid du Colombier int r;
10895e96a66cSDavid du Colombier ulong mode;
10905e96a66cSDavid du Colombier char *elem, *p, *path;
10915e96a66cSDavid du Colombier char *usage = "usage: [fsys name] create path uid gid perm";
10925e96a66cSDavid du Colombier DirEntry de;
10935e96a66cSDavid du Colombier File *file, *parent;
10945e96a66cSDavid du Colombier
10955e96a66cSDavid du Colombier ARGBEGIN{
10965e96a66cSDavid du Colombier default:
10975e96a66cSDavid du Colombier return cliError(usage);
10985e96a66cSDavid du Colombier }ARGEND
10995e96a66cSDavid du Colombier if(argc != 4)
11005e96a66cSDavid du Colombier return cliError(usage);
11015e96a66cSDavid du Colombier
11025e96a66cSDavid du Colombier if(!fsysParseMode(argv[3], &mode))
11035e96a66cSDavid du Colombier return cliError(usage);
11045e96a66cSDavid du Colombier if(mode&ModeSnapshot)
11055e96a66cSDavid du Colombier return cliError("create - cannot create with snapshot bit set");
11065e96a66cSDavid du Colombier
11075e96a66cSDavid du Colombier if(strcmp(argv[1], uidnoworld) == 0)
11085e96a66cSDavid du Colombier return cliError("permission denied");
11095e96a66cSDavid du Colombier
1110*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
1111*d7aba6c3SDavid du Colombier path = vtstrdup(argv[0]);
11125e96a66cSDavid du Colombier if((p = strrchr(path, '/')) != nil){
11135e96a66cSDavid du Colombier *p++ = '\0';
11145e96a66cSDavid du Colombier elem = p;
11155e96a66cSDavid du Colombier p = path;
11165e96a66cSDavid du Colombier if(*p == '\0')
11175e96a66cSDavid du Colombier p = "/";
11185e96a66cSDavid du Colombier }
11195e96a66cSDavid du Colombier else{
11205e96a66cSDavid du Colombier p = "/";
11215e96a66cSDavid du Colombier elem = path;
11225e96a66cSDavid du Colombier }
1123f8e525acSDavid du Colombier
11245e96a66cSDavid du Colombier r = 0;
1125f8e525acSDavid du Colombier if((parent = fileOpen(fsys->fs, p)) == nil)
1126f8e525acSDavid du Colombier goto out;
1127f8e525acSDavid du Colombier
11285e96a66cSDavid du Colombier file = fileCreate(parent, elem, mode, argv[1]);
11295e96a66cSDavid du Colombier fileDecRef(parent);
1130f8e525acSDavid du Colombier if(file == nil){
1131*d7aba6c3SDavid du Colombier werrstr("create %s/%s: %r", p, elem);
1132f8e525acSDavid du Colombier goto out;
1133f8e525acSDavid du Colombier }
1134f8e525acSDavid du Colombier
1135f8e525acSDavid du Colombier if(!fileGetDir(file, &de)){
1136*d7aba6c3SDavid du Colombier werrstr("stat failed after create: %r");
1137f8e525acSDavid du Colombier goto out1;
1138f8e525acSDavid du Colombier }
1139f8e525acSDavid du Colombier
11405e96a66cSDavid du Colombier if(strcmp(de.gid, argv[2]) != 0){
1141*d7aba6c3SDavid du Colombier vtfree(de.gid);
1142*d7aba6c3SDavid du Colombier de.gid = vtstrdup(argv[2]);
1143f8e525acSDavid du Colombier if(!fileSetDir(file, &de, argv[1])){
1144*d7aba6c3SDavid du Colombier werrstr("wstat failed after create: %r");
1145f8e525acSDavid du Colombier goto out2;
11465e96a66cSDavid du Colombier }
1147f8e525acSDavid du Colombier }
1148f8e525acSDavid du Colombier r = 1;
1149f8e525acSDavid du Colombier
1150f8e525acSDavid du Colombier out2:
11515e96a66cSDavid du Colombier deCleanup(&de);
1152f8e525acSDavid du Colombier out1:
11535e96a66cSDavid du Colombier fileDecRef(file);
1154f8e525acSDavid du Colombier out:
1155*d7aba6c3SDavid du Colombier vtfree(path);
1156*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
11575e96a66cSDavid du Colombier
11585e96a66cSDavid du Colombier return r;
11595e96a66cSDavid du Colombier }
11605e96a66cSDavid du Colombier
11615e96a66cSDavid du Colombier static void
fsysPrintStat(char * prefix,char * file,DirEntry * de)11625e96a66cSDavid du Colombier fsysPrintStat(char *prefix, char *file, DirEntry *de)
11635e96a66cSDavid du Colombier {
11645e96a66cSDavid du Colombier char buf[64];
11655e96a66cSDavid du Colombier
11665e96a66cSDavid du Colombier if(prefix == nil)
11675e96a66cSDavid du Colombier prefix = "";
11685e96a66cSDavid du Colombier consPrint("%sstat %q %q %q %q %s %llud\n", prefix,
11695e96a66cSDavid du Colombier file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);
11705e96a66cSDavid du Colombier }
11715e96a66cSDavid du Colombier
11725e96a66cSDavid du Colombier static int
fsysStat(Fsys * fsys,int argc,char * argv[])11735e96a66cSDavid du Colombier fsysStat(Fsys* fsys, int argc, char* argv[])
11745e96a66cSDavid du Colombier {
11755e96a66cSDavid du Colombier int i;
11765e96a66cSDavid du Colombier File *f;
11775e96a66cSDavid du Colombier DirEntry de;
11785e96a66cSDavid du Colombier char *usage = "usage: [fsys name] stat files...";
11795e96a66cSDavid du Colombier
11805e96a66cSDavid du Colombier ARGBEGIN{
11815e96a66cSDavid du Colombier default:
11825e96a66cSDavid du Colombier return cliError(usage);
11835e96a66cSDavid du Colombier }ARGEND
11845e96a66cSDavid du Colombier
11855e96a66cSDavid du Colombier if(argc == 0)
11865e96a66cSDavid du Colombier return cliError(usage);
11875e96a66cSDavid du Colombier
1188*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
11895e96a66cSDavid du Colombier for(i=0; i<argc; i++){
11905e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[i])) == nil){
1191*d7aba6c3SDavid du Colombier consPrint("%s: %r\n", argv[i]);
11925e96a66cSDavid du Colombier continue;
11935e96a66cSDavid du Colombier }
11945e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
1195*d7aba6c3SDavid du Colombier consPrint("%s: %r\n", argv[i]);
11965e96a66cSDavid du Colombier fileDecRef(f);
11975e96a66cSDavid du Colombier continue;
11985e96a66cSDavid du Colombier }
11995e96a66cSDavid du Colombier fsysPrintStat("\t", argv[i], &de);
12005e96a66cSDavid du Colombier deCleanup(&de);
12015e96a66cSDavid du Colombier fileDecRef(f);
12025e96a66cSDavid du Colombier }
1203*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
12045e96a66cSDavid du Colombier return 1;
12055e96a66cSDavid du Colombier }
12065e96a66cSDavid du Colombier
12075e96a66cSDavid du Colombier static int
fsysWstat(Fsys * fsys,int argc,char * argv[])12085e96a66cSDavid du Colombier fsysWstat(Fsys *fsys, int argc, char* argv[])
12095e96a66cSDavid du Colombier {
12105e96a66cSDavid du Colombier File *f;
12115e96a66cSDavid du Colombier char *p;
12125e96a66cSDavid du Colombier DirEntry de;
12135e96a66cSDavid du Colombier char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n"
12145e96a66cSDavid du Colombier "\tuse - for any field to mean don't change";
12155e96a66cSDavid du Colombier
12165e96a66cSDavid du Colombier ARGBEGIN{
12175e96a66cSDavid du Colombier default:
12185e96a66cSDavid du Colombier return cliError(usage);
12195e96a66cSDavid du Colombier }ARGEND
12205e96a66cSDavid du Colombier
12215e96a66cSDavid du Colombier if(argc != 6)
12225e96a66cSDavid du Colombier return cliError(usage);
12235e96a66cSDavid du Colombier
1224*d7aba6c3SDavid du Colombier rlock(&fsys->fs->elk);
12255e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[0])) == nil){
1226*d7aba6c3SDavid du Colombier werrstr("console wstat - walk - %r");
1227*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
12285e96a66cSDavid du Colombier return 0;
12295e96a66cSDavid du Colombier }
12305e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
1231*d7aba6c3SDavid du Colombier werrstr("console wstat - stat - %r");
12325e96a66cSDavid du Colombier fileDecRef(f);
1233*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
12345e96a66cSDavid du Colombier return 0;
12355e96a66cSDavid du Colombier }
12365e96a66cSDavid du Colombier fsysPrintStat("\told: w", argv[0], &de);
12375e96a66cSDavid du Colombier
12385e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0){
12395e96a66cSDavid du Colombier if(!validFileName(argv[1])){
1240*d7aba6c3SDavid du Colombier werrstr("console wstat - bad elem");
12415e96a66cSDavid du Colombier goto error;
12425e96a66cSDavid du Colombier }
1243*d7aba6c3SDavid du Colombier vtfree(de.elem);
1244*d7aba6c3SDavid du Colombier de.elem = vtstrdup(argv[1]);
12455e96a66cSDavid du Colombier }
12465e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0){
12475e96a66cSDavid du Colombier if(!validUserName(argv[2])){
1248*d7aba6c3SDavid du Colombier werrstr("console wstat - bad uid");
12495e96a66cSDavid du Colombier goto error;
12505e96a66cSDavid du Colombier }
1251*d7aba6c3SDavid du Colombier vtfree(de.uid);
1252*d7aba6c3SDavid du Colombier de.uid = vtstrdup(argv[2]);
12535e96a66cSDavid du Colombier }
12545e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0){
12555e96a66cSDavid du Colombier if(!validUserName(argv[3])){
1256*d7aba6c3SDavid du Colombier werrstr("console wstat - bad gid");
12575e96a66cSDavid du Colombier goto error;
12585e96a66cSDavid du Colombier }
1259*d7aba6c3SDavid du Colombier vtfree(de.gid);
1260*d7aba6c3SDavid du Colombier de.gid = vtstrdup(argv[3]);
12615e96a66cSDavid du Colombier }
12625e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0){
12635e96a66cSDavid du Colombier if(!fsysParseMode(argv[4], &de.mode)){
1264*d7aba6c3SDavid du Colombier werrstr("console wstat - bad mode");
12655e96a66cSDavid du Colombier goto error;
12665e96a66cSDavid du Colombier }
12675e96a66cSDavid du Colombier }
12685e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0){
12695e96a66cSDavid du Colombier de.size = strtoull(argv[5], &p, 0);
127022a127bbSDavid du Colombier if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){
1271*d7aba6c3SDavid du Colombier werrstr("console wstat - bad length");
12725e96a66cSDavid du Colombier goto error;
12735e96a66cSDavid du Colombier }
12745e96a66cSDavid du Colombier }
12755e96a66cSDavid du Colombier
12765e96a66cSDavid du Colombier if(!fileSetDir(f, &de, uidadm)){
1277*d7aba6c3SDavid du Colombier werrstr("console wstat - %r");
12785e96a66cSDavid du Colombier goto error;
12795e96a66cSDavid du Colombier }
12805e96a66cSDavid du Colombier deCleanup(&de);
12815e96a66cSDavid du Colombier
12825e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
1283*d7aba6c3SDavid du Colombier werrstr("console wstat - stat2 - %r");
12845e96a66cSDavid du Colombier goto error;
12855e96a66cSDavid du Colombier }
12865e96a66cSDavid du Colombier fsysPrintStat("\tnew: w", argv[0], &de);
12875e96a66cSDavid du Colombier deCleanup(&de);
12885e96a66cSDavid du Colombier fileDecRef(f);
1289*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
12905e96a66cSDavid du Colombier
12915e96a66cSDavid du Colombier return 1;
12925e96a66cSDavid du Colombier
12935e96a66cSDavid du Colombier error:
12945e96a66cSDavid du Colombier deCleanup(&de); /* okay to do this twice */
12955e96a66cSDavid du Colombier fileDecRef(f);
1296*d7aba6c3SDavid du Colombier runlock(&fsys->fs->elk);
12975e96a66cSDavid du Colombier return 0;
12985e96a66cSDavid du Colombier }
12995e96a66cSDavid du Colombier
1300e569ccb5SDavid du Colombier static void
fsckClri(Fsck * fsck,char * name,MetaBlock * mb,int i,Block * b)1301e569ccb5SDavid du Colombier fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b)
1302e569ccb5SDavid du Colombier {
1303e569ccb5SDavid du Colombier USED(name);
1304e569ccb5SDavid du Colombier
1305e569ccb5SDavid du Colombier if((fsck->flags&DoClri) == 0)
1306e569ccb5SDavid du Colombier return;
1307e569ccb5SDavid du Colombier
1308e569ccb5SDavid du Colombier mbDelete(mb, i);
1309e569ccb5SDavid du Colombier mbPack(mb);
1310e569ccb5SDavid du Colombier blockDirty(b);
1311e569ccb5SDavid du Colombier }
1312e569ccb5SDavid du Colombier
1313e569ccb5SDavid du Colombier static void
fsckClose(Fsck * fsck,Block * b,u32int epoch)1314e569ccb5SDavid du Colombier fsckClose(Fsck *fsck, Block *b, u32int epoch)
1315e569ccb5SDavid du Colombier {
1316e569ccb5SDavid du Colombier Label l;
1317e569ccb5SDavid du Colombier
1318e569ccb5SDavid du Colombier if((fsck->flags&DoClose) == 0)
1319e569ccb5SDavid du Colombier return;
1320e569ccb5SDavid du Colombier l = b->l;
1321e569ccb5SDavid du Colombier if(l.state == BsFree || (l.state&BsClosed)){
1322e569ccb5SDavid du Colombier consPrint("%#ux is already closed\n", b->addr);
1323e569ccb5SDavid du Colombier return;
1324e569ccb5SDavid du Colombier }
1325e569ccb5SDavid du Colombier if(epoch){
1326e569ccb5SDavid du Colombier l.state |= BsClosed;
1327e569ccb5SDavid du Colombier l.epochClose = epoch;
1328e569ccb5SDavid du Colombier }else
1329e569ccb5SDavid du Colombier l.state = BsFree;
1330e569ccb5SDavid du Colombier
1331e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0))
1332*d7aba6c3SDavid du Colombier consPrint("%#ux setlabel: %r\n", b->addr);
1333e569ccb5SDavid du Colombier }
1334e569ccb5SDavid du Colombier
1335e569ccb5SDavid du Colombier static void
fsckClre(Fsck * fsck,Block * b,int offset)1336e569ccb5SDavid du Colombier fsckClre(Fsck *fsck, Block *b, int offset)
1337e569ccb5SDavid du Colombier {
1338e569ccb5SDavid du Colombier Entry e;
1339e569ccb5SDavid du Colombier
1340e569ccb5SDavid du Colombier if((fsck->flags&DoClre) == 0)
1341e569ccb5SDavid du Colombier return;
1342e569ccb5SDavid du Colombier if(offset<0 || offset*VtEntrySize >= fsck->bsize){
1343e569ccb5SDavid du Colombier consPrint("bad clre\n");
1344e569ccb5SDavid du Colombier return;
1345e569ccb5SDavid du Colombier }
1346e569ccb5SDavid du Colombier memset(&e, 0, sizeof e);
1347e569ccb5SDavid du Colombier entryPack(&e, b->data, offset);
1348e569ccb5SDavid du Colombier blockDirty(b);
1349e569ccb5SDavid du Colombier }
1350e569ccb5SDavid du Colombier
1351e569ccb5SDavid du Colombier static void
fsckClrp(Fsck * fsck,Block * b,int offset)1352e569ccb5SDavid du Colombier fsckClrp(Fsck *fsck, Block *b, int offset)
1353e569ccb5SDavid du Colombier {
1354e569ccb5SDavid du Colombier if((fsck->flags&DoClrp) == 0)
1355e569ccb5SDavid du Colombier return;
1356e569ccb5SDavid du Colombier if(offset<0 || offset*VtScoreSize >= fsck->bsize){
1357e569ccb5SDavid du Colombier consPrint("bad clre\n");
1358e569ccb5SDavid du Colombier return;
1359e569ccb5SDavid du Colombier }
1360*d7aba6c3SDavid du Colombier memmove(b->data+offset*VtScoreSize, vtzeroscore, VtScoreSize);
1361e569ccb5SDavid du Colombier blockDirty(b);
1362e569ccb5SDavid du Colombier }
1363e569ccb5SDavid du Colombier
1364e569ccb5SDavid du Colombier static int
fsysCheck(Fsys * fsys,int argc,char * argv[])1365e569ccb5SDavid du Colombier fsysCheck(Fsys *fsys, int argc, char *argv[])
1366e569ccb5SDavid du Colombier {
1367e569ccb5SDavid du Colombier int i, halting;
1368e569ccb5SDavid du Colombier char *usage = "usage: [fsys name] check [-v] [options]";
1369e569ccb5SDavid du Colombier Fsck fsck;
1370e569ccb5SDavid du Colombier Block *b;
1371e569ccb5SDavid du Colombier Super super;
1372e569ccb5SDavid du Colombier
1373e569ccb5SDavid du Colombier memset(&fsck, 0, sizeof fsck);
1374e569ccb5SDavid du Colombier fsck.fs = fsys->fs;
1375e569ccb5SDavid du Colombier fsck.clri = fsckClri;
1376e569ccb5SDavid du Colombier fsck.clre = fsckClre;
1377e569ccb5SDavid du Colombier fsck.clrp = fsckClrp;
1378e569ccb5SDavid du Colombier fsck.close = fsckClose;
1379e569ccb5SDavid du Colombier fsck.print = consPrint;
1380e569ccb5SDavid du Colombier
1381e569ccb5SDavid du Colombier ARGBEGIN{
1382e569ccb5SDavid du Colombier default:
1383e569ccb5SDavid du Colombier return cliError(usage);
1384e569ccb5SDavid du Colombier }ARGEND
1385e569ccb5SDavid du Colombier
1386e569ccb5SDavid du Colombier for(i=0; i<argc; i++){
1387e569ccb5SDavid du Colombier if(strcmp(argv[i], "pblock") == 0)
1388e569ccb5SDavid du Colombier fsck.printblocks = 1;
1389e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pdir") == 0)
1390e569ccb5SDavid du Colombier fsck.printdirs = 1;
1391e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pfile") == 0)
1392e569ccb5SDavid du Colombier fsck.printfiles = 1;
1393e569ccb5SDavid du Colombier else if(strcmp(argv[i], "bclose") == 0)
1394e569ccb5SDavid du Colombier fsck.flags |= DoClose;
1395e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clri") == 0)
1396e569ccb5SDavid du Colombier fsck.flags |= DoClri;
1397e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clre") == 0)
1398e569ccb5SDavid du Colombier fsck.flags |= DoClre;
1399e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clrp") == 0)
1400e569ccb5SDavid du Colombier fsck.flags |= DoClrp;
1401e569ccb5SDavid du Colombier else if(strcmp(argv[i], "fix") == 0)
1402e569ccb5SDavid du Colombier fsck.flags |= DoClose|DoClri|DoClre|DoClrp;
1403e569ccb5SDavid du Colombier else if(strcmp(argv[i], "venti") == 0)
1404e569ccb5SDavid du Colombier fsck.useventi = 1;
1405e569ccb5SDavid du Colombier else if(strcmp(argv[i], "snapshot") == 0)
1406e569ccb5SDavid du Colombier fsck.walksnapshots = 1;
1407e569ccb5SDavid du Colombier else{
1408e569ccb5SDavid du Colombier consPrint("unknown option '%s'\n", argv[i]);
1409e569ccb5SDavid du Colombier return cliError(usage);
1410e569ccb5SDavid du Colombier }
1411e569ccb5SDavid du Colombier }
1412e569ccb5SDavid du Colombier
1413e569ccb5SDavid du Colombier halting = fsys->fs->halted==0;
1414e569ccb5SDavid du Colombier if(halting)
1415e569ccb5SDavid du Colombier fsHalt(fsys->fs);
1416e569ccb5SDavid du Colombier if(fsys->fs->arch){
1417e569ccb5SDavid du Colombier b = superGet(fsys->fs->cache, &super);
1418e569ccb5SDavid du Colombier if(b == nil){
1419e569ccb5SDavid du Colombier consPrint("could not load super block\n");
1420e569ccb5SDavid du Colombier goto Out;
1421e569ccb5SDavid du Colombier }
1422e569ccb5SDavid du Colombier blockPut(b);
1423e569ccb5SDavid du Colombier if(super.current != NilBlock){
1424225077b0SDavid du Colombier consPrint("cannot check fs while archiver is running; "
1425225077b0SDavid du Colombier "wait for it to finish\n");
1426e569ccb5SDavid du Colombier goto Out;
1427e569ccb5SDavid du Colombier }
1428e569ccb5SDavid du Colombier }
1429e569ccb5SDavid du Colombier fsCheck(&fsck);
1430e569ccb5SDavid du Colombier consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n",
1431e569ccb5SDavid du Colombier fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose);
1432e569ccb5SDavid du Colombier Out:
1433e569ccb5SDavid du Colombier if(halting)
1434e569ccb5SDavid du Colombier fsUnhalt(fsys->fs);
1435e569ccb5SDavid du Colombier return 1;
1436e569ccb5SDavid du Colombier }
1437e569ccb5SDavid du Colombier
14385e96a66cSDavid du Colombier static int
fsysVenti(char * name,int argc,char * argv[])14395e96a66cSDavid du Colombier fsysVenti(char* name, int argc, char* argv[])
14405e96a66cSDavid du Colombier {
14415e96a66cSDavid du Colombier int r;
14425e96a66cSDavid du Colombier char *host;
14435e96a66cSDavid du Colombier char *usage = "usage: [fsys name] venti [address]";
14445e96a66cSDavid du Colombier Fsys *fsys;
14455e96a66cSDavid du Colombier
14465e96a66cSDavid du Colombier ARGBEGIN{
14475e96a66cSDavid du Colombier default:
14485e96a66cSDavid du Colombier return cliError(usage);
14495e96a66cSDavid du Colombier }ARGEND
14505e96a66cSDavid du Colombier
14515e96a66cSDavid du Colombier if(argc == 0)
14525e96a66cSDavid du Colombier host = nil;
14535e96a66cSDavid du Colombier else if(argc == 1)
14545e96a66cSDavid du Colombier host = argv[0];
14555e96a66cSDavid du Colombier else
14565e96a66cSDavid du Colombier return cliError(usage);
14575e96a66cSDavid du Colombier
14585e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil)
14595e96a66cSDavid du Colombier return 0;
14605e96a66cSDavid du Colombier
1461*d7aba6c3SDavid du Colombier qlock(&fsys->lock);
14625e96a66cSDavid du Colombier if(host == nil)
14635e96a66cSDavid du Colombier host = fsys->venti;
14645e96a66cSDavid du Colombier else{
1465*d7aba6c3SDavid du Colombier vtfree(fsys->venti);
14665e96a66cSDavid du Colombier if(host[0])
1467*d7aba6c3SDavid du Colombier fsys->venti = vtstrdup(host);
14685e96a66cSDavid du Colombier else{
14695e96a66cSDavid du Colombier host = nil;
14705e96a66cSDavid du Colombier fsys->venti = nil;
14715e96a66cSDavid du Colombier }
14725e96a66cSDavid du Colombier }
14735e96a66cSDavid du Colombier
14745e96a66cSDavid du Colombier /* already open: do a redial */
14755e96a66cSDavid du Colombier if(fsys->fs != nil){
14766042bf6dSDavid du Colombier if(fsys->session == nil){
1477*d7aba6c3SDavid du Colombier werrstr("file system was opened with -V");
14786042bf6dSDavid du Colombier r = 0;
14796042bf6dSDavid du Colombier goto out;
14806042bf6dSDavid du Colombier }
14815e96a66cSDavid du Colombier r = 1;
1482*d7aba6c3SDavid du Colombier if(myRedial(fsys->session, host) < 0
1483*d7aba6c3SDavid du Colombier || vtconnect(fsys->session) < 0)
14845e96a66cSDavid du Colombier r = 0;
14856042bf6dSDavid du Colombier goto out;
14865e96a66cSDavid du Colombier }
14875e96a66cSDavid du Colombier
14885e96a66cSDavid du Colombier /* not yet open: try to dial */
14895e96a66cSDavid du Colombier if(fsys->session)
1490*d7aba6c3SDavid du Colombier vtfreeconn(fsys->session);
14915e96a66cSDavid du Colombier r = 1;
1492*d7aba6c3SDavid du Colombier if((fsys->session = myDial(host)) == nil
1493*d7aba6c3SDavid du Colombier || vtconnect(fsys->session) < 0)
14945e96a66cSDavid du Colombier r = 0;
14956042bf6dSDavid du Colombier out:
1496*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
14975e96a66cSDavid du Colombier fsysPut(fsys);
14985e96a66cSDavid du Colombier return r;
14995e96a66cSDavid du Colombier }
15005e96a66cSDavid du Colombier
1501b8a11165SDavid du Colombier static ulong
freemem(void)1502b8a11165SDavid du Colombier freemem(void)
1503b8a11165SDavid du Colombier {
1504b8a11165SDavid du Colombier int nf, pgsize = 0;
1505b8a11165SDavid du Colombier uvlong size, userpgs = 0, userused = 0;
1506b8a11165SDavid du Colombier char *ln, *sl;
1507b8a11165SDavid du Colombier char *fields[2];
1508b8a11165SDavid du Colombier Biobuf *bp;
1509b8a11165SDavid du Colombier
1510b8a11165SDavid du Colombier size = 64*1024*1024;
1511b8a11165SDavid du Colombier bp = Bopen("#c/swap", OREAD);
1512b8a11165SDavid du Colombier if (bp != nil) {
1513b8a11165SDavid du Colombier while ((ln = Brdline(bp, '\n')) != nil) {
1514b8a11165SDavid du Colombier ln[Blinelen(bp)-1] = '\0';
1515b8a11165SDavid du Colombier nf = tokenize(ln, fields, nelem(fields));
1516b8a11165SDavid du Colombier if (nf != 2)
1517b8a11165SDavid du Colombier continue;
1518b8a11165SDavid du Colombier if (strcmp(fields[1], "pagesize") == 0)
1519b8a11165SDavid du Colombier pgsize = atoi(fields[0]);
1520b8a11165SDavid du Colombier else if (strcmp(fields[1], "user") == 0) {
1521b8a11165SDavid du Colombier sl = strchr(fields[0], '/');
1522b8a11165SDavid du Colombier if (sl == nil)
1523b8a11165SDavid du Colombier continue;
1524b8a11165SDavid du Colombier userpgs = atoll(sl+1);
1525b8a11165SDavid du Colombier userused = atoll(fields[0]);
1526b8a11165SDavid du Colombier }
1527b8a11165SDavid du Colombier }
1528b8a11165SDavid du Colombier Bterm(bp);
1529b8a11165SDavid du Colombier if (pgsize > 0 && userpgs > 0)
1530b8a11165SDavid du Colombier size = (userpgs - userused) * pgsize;
1531b8a11165SDavid du Colombier }
1532b8a11165SDavid du Colombier /* cap it to keep the size within 32 bits */
1533b8a11165SDavid du Colombier if (size >= 3840UL * 1024 * 1024)
1534b8a11165SDavid du Colombier size = 3840UL * 1024 * 1024;
1535b8a11165SDavid du Colombier return size;
1536b8a11165SDavid du Colombier }
1537b8a11165SDavid du Colombier
15385e96a66cSDavid du Colombier static int
fsysOpen(char * name,int argc,char * argv[])15395e96a66cSDavid du Colombier fsysOpen(char* name, int argc, char* argv[])
15405e96a66cSDavid du Colombier {
15415e96a66cSDavid du Colombier char *p, *host;
15425e96a66cSDavid du Colombier Fsys *fsys;
1543f4051287SDavid du Colombier int noauth, noventi, noperm, rflag, wstatallow, noatimeupd;
1544b8a11165SDavid du Colombier long ncache;
15456042bf6dSDavid du Colombier char *usage = "usage: fsys name open [-APVWr] [-c ncache]";
15465e96a66cSDavid du Colombier
15475e96a66cSDavid du Colombier ncache = 1000;
1548f4051287SDavid du Colombier noauth = noperm = wstatallow = noventi = noatimeupd = 0;
15495e96a66cSDavid du Colombier rflag = OReadWrite;
15505e96a66cSDavid du Colombier
15515e96a66cSDavid du Colombier ARGBEGIN{
15525e96a66cSDavid du Colombier default:
15535e96a66cSDavid du Colombier return cliError(usage);
15545e96a66cSDavid du Colombier case 'A':
15555e96a66cSDavid du Colombier noauth = 1;
15565e96a66cSDavid du Colombier break;
15575e96a66cSDavid du Colombier case 'P':
15585e96a66cSDavid du Colombier noperm = 1;
15595e96a66cSDavid du Colombier break;
15606042bf6dSDavid du Colombier case 'V':
15616042bf6dSDavid du Colombier noventi = 1;
15626042bf6dSDavid du Colombier break;
15635e96a66cSDavid du Colombier case 'W':
15645e96a66cSDavid du Colombier wstatallow = 1;
15655e96a66cSDavid du Colombier break;
1566f4051287SDavid du Colombier case 'a':
1567f4051287SDavid du Colombier noatimeupd = 1;
1568f4051287SDavid du Colombier break;
15695e96a66cSDavid du Colombier case 'c':
15705e96a66cSDavid du Colombier p = ARGF();
15715e96a66cSDavid du Colombier if(p == nil)
15725e96a66cSDavid du Colombier return cliError(usage);
15735e96a66cSDavid du Colombier ncache = strtol(argv[0], &p, 0);
15745e96a66cSDavid du Colombier if(ncache <= 0 || p == argv[0] || *p != '\0')
15755e96a66cSDavid du Colombier return cliError(usage);
15765e96a66cSDavid du Colombier break;
15775e96a66cSDavid du Colombier case 'r':
15785e96a66cSDavid du Colombier rflag = OReadOnly;
15795e96a66cSDavid du Colombier break;
15805e96a66cSDavid du Colombier }ARGEND
15815e96a66cSDavid du Colombier if(argc)
15825e96a66cSDavid du Colombier return cliError(usage);
15835e96a66cSDavid du Colombier
15845e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil)
15855e96a66cSDavid du Colombier return 0;
15865e96a66cSDavid du Colombier
1587b8a11165SDavid du Colombier /* automatic memory sizing? */
1588b8a11165SDavid du Colombier if(mempcnt > 0) {
1589b8a11165SDavid du Colombier /* TODO: 8K is a hack; use the actual block size */
1590b8a11165SDavid du Colombier ncache = (((vlong)freemem() * mempcnt) / 100) / (8*1024);
1591b8a11165SDavid du Colombier if (ncache < 100)
1592b8a11165SDavid du Colombier ncache = 100;
1593b8a11165SDavid du Colombier }
1594b8a11165SDavid du Colombier
1595*d7aba6c3SDavid du Colombier qlock(&fsys->lock);
15965e96a66cSDavid du Colombier if(fsys->fs != nil){
1597*d7aba6c3SDavid du Colombier werrstr(EFsysBusy, fsys->name);
1598*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
15995e96a66cSDavid du Colombier fsysPut(fsys);
16005e96a66cSDavid du Colombier return 0;
16015e96a66cSDavid du Colombier }
16025e96a66cSDavid du Colombier
16037611b47fSDavid du Colombier if(noventi){
16047611b47fSDavid du Colombier if(fsys->session){
1605*d7aba6c3SDavid du Colombier vtfreeconn(fsys->session);
16067611b47fSDavid du Colombier fsys->session = nil;
16077611b47fSDavid du Colombier }
16087611b47fSDavid du Colombier }
16097611b47fSDavid du Colombier else if(fsys->session == nil){
16105e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0])
16115e96a66cSDavid du Colombier host = fsys->venti;
16125e96a66cSDavid du Colombier else
16135e96a66cSDavid du Colombier host = nil;
1614*d7aba6c3SDavid du Colombier
1615*d7aba6c3SDavid du Colombier if((fsys->session = myDial(host)) == nil
1616*d7aba6c3SDavid du Colombier || vtconnect(fsys->session) < 0 && !noventi)
1617*d7aba6c3SDavid du Colombier fprint(2, "warning: connecting to venti: %r\n");
16185e96a66cSDavid du Colombier }
16195e96a66cSDavid du Colombier if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){
1620*d7aba6c3SDavid du Colombier werrstr("fsOpen: %r");
1621*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
16225e96a66cSDavid du Colombier fsysPut(fsys);
16235e96a66cSDavid du Colombier return 0;
16245e96a66cSDavid du Colombier }
16250c6300e7SDavid du Colombier fsys->fs->name = fsys->name; /* for better error messages */
16265e96a66cSDavid du Colombier fsys->noauth = noauth;
16275e96a66cSDavid du Colombier fsys->noperm = noperm;
16285e96a66cSDavid du Colombier fsys->wstatallow = wstatallow;
1629f4051287SDavid du Colombier fsys->fs->noatimeupd = noatimeupd;
1630*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
16315e96a66cSDavid du Colombier fsysPut(fsys);
16325e96a66cSDavid du Colombier
163381cf8742SDavid du Colombier if(strcmp(name, "main") == 0)
163481cf8742SDavid du Colombier usersFileRead(nil);
163581cf8742SDavid du Colombier
16365e96a66cSDavid du Colombier return 1;
16375e96a66cSDavid du Colombier }
16385e96a66cSDavid du Colombier
16395e96a66cSDavid du Colombier static int
fsysUnconfig(char * name,int argc,char * argv[])16405e96a66cSDavid du Colombier fsysUnconfig(char* name, int argc, char* argv[])
16415e96a66cSDavid du Colombier {
16425e96a66cSDavid du Colombier Fsys *fsys, **fp;
16435e96a66cSDavid du Colombier char *usage = "usage: fsys name unconfig";
16445e96a66cSDavid du Colombier
16455e96a66cSDavid du Colombier ARGBEGIN{
16465e96a66cSDavid du Colombier default:
16475e96a66cSDavid du Colombier return cliError(usage);
16485e96a66cSDavid du Colombier }ARGEND
16495e96a66cSDavid du Colombier if(argc)
16505e96a66cSDavid du Colombier return cliError(usage);
16515e96a66cSDavid du Colombier
1652*d7aba6c3SDavid du Colombier wlock(&sbox.lock);
16535e96a66cSDavid du Colombier fp = &sbox.head;
16545e96a66cSDavid du Colombier for(fsys = *fp; fsys != nil; fsys = fsys->next){
16555e96a66cSDavid du Colombier if(strcmp(fsys->name, name) == 0)
16565e96a66cSDavid du Colombier break;
16575e96a66cSDavid du Colombier fp = &fsys->next;
16585e96a66cSDavid du Colombier }
16595e96a66cSDavid du Colombier if(fsys == nil){
1660*d7aba6c3SDavid du Colombier werrstr(EFsysNotFound, name);
1661*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
16625e96a66cSDavid du Colombier return 0;
16635e96a66cSDavid du Colombier }
16645e96a66cSDavid du Colombier if(fsys->ref != 0 || fsys->fs != nil){
1665*d7aba6c3SDavid du Colombier werrstr(EFsysBusy, fsys->name);
1666*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
16675e96a66cSDavid du Colombier return 0;
16685e96a66cSDavid du Colombier }
16695e96a66cSDavid du Colombier *fp = fsys->next;
1670*d7aba6c3SDavid du Colombier wunlock(&sbox.lock);
16715e96a66cSDavid du Colombier
1672*d7aba6c3SDavid du Colombier if(fsys->session != nil)
1673*d7aba6c3SDavid du Colombier vtfreeconn(fsys->session);
16745e96a66cSDavid du Colombier if(fsys->venti != nil)
1675*d7aba6c3SDavid du Colombier vtfree(fsys->venti);
16765e96a66cSDavid du Colombier if(fsys->dev != nil)
1677*d7aba6c3SDavid du Colombier vtfree(fsys->dev);
16785e96a66cSDavid du Colombier if(fsys->name != nil)
1679*d7aba6c3SDavid du Colombier vtfree(fsys->name);
1680*d7aba6c3SDavid du Colombier vtfree(fsys);
16815e96a66cSDavid du Colombier
16825e96a66cSDavid du Colombier return 1;
16835e96a66cSDavid du Colombier }
16845e96a66cSDavid du Colombier
16855e96a66cSDavid du Colombier static int
fsysConfig(char * name,int argc,char * argv[])16865e96a66cSDavid du Colombier fsysConfig(char* name, int argc, char* argv[])
16875e96a66cSDavid du Colombier {
16885e96a66cSDavid du Colombier Fsys *fsys;
16891bdadbfaSDavid du Colombier char *part;
16901bdadbfaSDavid du Colombier char *usage = "usage: fsys name config [dev]";
16915e96a66cSDavid du Colombier
16925e96a66cSDavid du Colombier ARGBEGIN{
16935e96a66cSDavid du Colombier default:
16945e96a66cSDavid du Colombier return cliError(usage);
16955e96a66cSDavid du Colombier }ARGEND
16961bdadbfaSDavid du Colombier if(argc > 1)
16975e96a66cSDavid du Colombier return cliError(usage);
16985e96a66cSDavid du Colombier
16991bdadbfaSDavid du Colombier if(argc == 0)
17001bdadbfaSDavid du Colombier part = foptname;
17011bdadbfaSDavid du Colombier else
17021bdadbfaSDavid du Colombier part = argv[0];
17031bdadbfaSDavid du Colombier
17041bdadbfaSDavid du Colombier if((fsys = _fsysGet(part)) != nil){
1705*d7aba6c3SDavid du Colombier qlock(&fsys->lock);
17065e96a66cSDavid du Colombier if(fsys->fs != nil){
1707*d7aba6c3SDavid du Colombier werrstr(EFsysBusy, fsys->name);
1708*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
17095e96a66cSDavid du Colombier fsysPut(fsys);
17105e96a66cSDavid du Colombier return 0;
17115e96a66cSDavid du Colombier }
1712*d7aba6c3SDavid du Colombier vtfree(fsys->dev);
1713*d7aba6c3SDavid du Colombier fsys->dev = vtstrdup(part);
1714*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
17155e96a66cSDavid du Colombier }
17161bdadbfaSDavid du Colombier else if((fsys = fsysAlloc(name, part)) == nil)
17175e96a66cSDavid du Colombier return 0;
17185e96a66cSDavid du Colombier
17195e96a66cSDavid du Colombier fsysPut(fsys);
17205e96a66cSDavid du Colombier return 1;
17215e96a66cSDavid du Colombier }
17225e96a66cSDavid du Colombier
17235e96a66cSDavid du Colombier static struct {
17245e96a66cSDavid du Colombier char* cmd;
17255e96a66cSDavid du Colombier int (*f)(Fsys*, int, char**);
17265e96a66cSDavid du Colombier int (*f1)(char*, int, char**);
17275e96a66cSDavid du Colombier } fsyscmd[] = {
17285e96a66cSDavid du Colombier { "close", fsysClose, },
17295e96a66cSDavid du Colombier { "config", nil, fsysConfig, },
17305e96a66cSDavid du Colombier { "open", nil, fsysOpen, },
17315e96a66cSDavid du Colombier { "unconfig", nil, fsysUnconfig, },
17325e96a66cSDavid du Colombier { "venti", nil, fsysVenti, },
17335e96a66cSDavid du Colombier
17345e96a66cSDavid du Colombier { "bfree", fsysBfree, },
17355e96a66cSDavid du Colombier { "block", fsysBlock, },
1736e569ccb5SDavid du Colombier { "check", fsysCheck, },
17375e96a66cSDavid du Colombier { "clre", fsysClre, },
17385e96a66cSDavid du Colombier { "clri", fsysClri, },
17395e96a66cSDavid du Colombier { "clrp", fsysClrp, },
17405e96a66cSDavid du Colombier { "create", fsysCreate, },
17417abd426fSDavid du Colombier { "df", fsysDf, },
17425e96a66cSDavid du Colombier { "epoch", fsysEpoch, },
174381cf8742SDavid du Colombier { "halt", fsysHalt, },
17445e96a66cSDavid du Colombier { "label", fsysLabel, },
17455e96a66cSDavid du Colombier { "remove", fsysRemove, },
17465e96a66cSDavid du Colombier { "snap", fsysSnap, },
17475e96a66cSDavid du Colombier { "snaptime", fsysSnapTime, },
1748dc5a79c1SDavid du Colombier { "snapclean", fsysSnapClean, },
17495e96a66cSDavid du Colombier { "stat", fsysStat, },
17505e96a66cSDavid du Colombier { "sync", fsysSync, },
175181cf8742SDavid du Colombier { "unhalt", fsysUnhalt, },
17525e96a66cSDavid du Colombier { "wstat", fsysWstat, },
17535e96a66cSDavid du Colombier { "vac", fsysVac, },
17545e96a66cSDavid du Colombier
17555e96a66cSDavid du Colombier { nil, nil, },
17565e96a66cSDavid du Colombier };
17575e96a66cSDavid du Colombier
17585e96a66cSDavid du Colombier static int
fsysXXX1(Fsys * fsys,int i,int argc,char * argv[])175981cf8742SDavid du Colombier fsysXXX1(Fsys *fsys, int i, int argc, char* argv[])
176081cf8742SDavid du Colombier {
176181cf8742SDavid du Colombier int r;
176281cf8742SDavid du Colombier
1763*d7aba6c3SDavid du Colombier qlock(&fsys->lock);
176481cf8742SDavid du Colombier if(fsys->fs == nil){
1765*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
1766*d7aba6c3SDavid du Colombier werrstr(EFsysNotOpen, fsys->name);
176781cf8742SDavid du Colombier return 0;
176881cf8742SDavid du Colombier }
176981cf8742SDavid du Colombier
1770e569ccb5SDavid du Colombier if(fsys->fs->halted
1771e569ccb5SDavid du Colombier && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){
1772*d7aba6c3SDavid du Colombier werrstr("file system %s is halted", fsys->name);
1773*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
177481cf8742SDavid du Colombier return 0;
177581cf8742SDavid du Colombier }
177681cf8742SDavid du Colombier
177781cf8742SDavid du Colombier r = (*fsyscmd[i].f)(fsys, argc, argv);
1778*d7aba6c3SDavid du Colombier qunlock(&fsys->lock);
177981cf8742SDavid du Colombier return r;
178081cf8742SDavid du Colombier }
178181cf8742SDavid du Colombier
178281cf8742SDavid du Colombier static int
fsysXXX(char * name,int argc,char * argv[])17835e96a66cSDavid du Colombier fsysXXX(char* name, int argc, char* argv[])
17845e96a66cSDavid du Colombier {
17855e96a66cSDavid du Colombier int i, r;
17865e96a66cSDavid du Colombier Fsys *fsys;
17875e96a66cSDavid du Colombier
17885e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){
17895e96a66cSDavid du Colombier if(strcmp(fsyscmd[i].cmd, argv[0]) == 0)
17905e96a66cSDavid du Colombier break;
17915e96a66cSDavid du Colombier }
17925e96a66cSDavid du Colombier
17935e96a66cSDavid du Colombier if(fsyscmd[i].cmd == nil){
1794*d7aba6c3SDavid du Colombier werrstr("unknown command - '%s'", argv[0]);
17955e96a66cSDavid du Colombier return 0;
17965e96a66cSDavid du Colombier }
17975e96a66cSDavid du Colombier
17985e96a66cSDavid du Colombier /* some commands want the name... */
179981cf8742SDavid du Colombier if(fsyscmd[i].f1 != nil){
180081cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){
1801*d7aba6c3SDavid du Colombier werrstr("cannot use fsys %#q with %#q command", FsysAll, argv[0]);
18025e96a66cSDavid du Colombier return 0;
18035e96a66cSDavid du Colombier }
180481cf8742SDavid du Colombier return (*fsyscmd[i].f1)(name, argc, argv);
180581cf8742SDavid du Colombier }
18065e96a66cSDavid du Colombier
180781cf8742SDavid du Colombier /* ... but most commands want the Fsys */
180881cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){
180981cf8742SDavid du Colombier r = 1;
1810*d7aba6c3SDavid du Colombier rlock(&sbox.lock);
181181cf8742SDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
181281cf8742SDavid du Colombier fsys->ref++;
181381cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv) && r;
181481cf8742SDavid du Colombier fsys->ref--;
181581cf8742SDavid du Colombier }
1816*d7aba6c3SDavid du Colombier runlock(&sbox.lock);
181781cf8742SDavid du Colombier }else{
181881cf8742SDavid du Colombier if((fsys = _fsysGet(name)) == nil)
181981cf8742SDavid du Colombier return 0;
182081cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv);
18215e96a66cSDavid du Colombier fsysPut(fsys);
182281cf8742SDavid du Colombier }
18235e96a66cSDavid du Colombier return r;
18245e96a66cSDavid du Colombier }
18255e96a66cSDavid du Colombier
18265e96a66cSDavid du Colombier static int
cmdFsysXXX(int argc,char * argv[])18275e96a66cSDavid du Colombier cmdFsysXXX(int argc, char* argv[])
18285e96a66cSDavid du Colombier {
18295e96a66cSDavid du Colombier char *name;
18305e96a66cSDavid du Colombier
18315e96a66cSDavid du Colombier if((name = sbox.curfsys) == nil){
1832*d7aba6c3SDavid du Colombier werrstr(EFsysNoCurrent, argv[0]);
18335e96a66cSDavid du Colombier return 0;
18345e96a66cSDavid du Colombier }
18355e96a66cSDavid du Colombier
18365e96a66cSDavid du Colombier return fsysXXX(name, argc, argv);
18375e96a66cSDavid du Colombier }
18385e96a66cSDavid du Colombier
18395e96a66cSDavid du Colombier static int
cmdFsys(int argc,char * argv[])18405e96a66cSDavid du Colombier cmdFsys(int argc, char* argv[])
18415e96a66cSDavid du Colombier {
18425e96a66cSDavid du Colombier Fsys *fsys;
18435e96a66cSDavid du Colombier char *usage = "usage: fsys [name ...]";
18445e96a66cSDavid du Colombier
18455e96a66cSDavid du Colombier ARGBEGIN{
18465e96a66cSDavid du Colombier default:
18475e96a66cSDavid du Colombier return cliError(usage);
18485e96a66cSDavid du Colombier }ARGEND
18495e96a66cSDavid du Colombier
18505e96a66cSDavid du Colombier if(argc == 0){
1851*d7aba6c3SDavid du Colombier rlock(&sbox.lock);
1852b8a11165SDavid du Colombier currfsysname = sbox.head->name;
18535e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next)
18545e96a66cSDavid du Colombier consPrint("\t%s\n", fsys->name);
1855*d7aba6c3SDavid du Colombier runlock(&sbox.lock);
18565e96a66cSDavid du Colombier return 1;
18575e96a66cSDavid du Colombier }
18585e96a66cSDavid du Colombier if(argc == 1){
185981cf8742SDavid du Colombier fsys = nil;
186081cf8742SDavid du Colombier if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil)
18615e96a66cSDavid du Colombier return 0;
1862*d7aba6c3SDavid du Colombier sbox.curfsys = vtstrdup(argv[0]);
18635e96a66cSDavid du Colombier consPrompt(sbox.curfsys);
186481cf8742SDavid du Colombier if(fsys)
18655e96a66cSDavid du Colombier fsysPut(fsys);
18665e96a66cSDavid du Colombier return 1;
18675e96a66cSDavid du Colombier }
18685e96a66cSDavid du Colombier
18695e96a66cSDavid du Colombier return fsysXXX(argv[0], argc-1, argv+1);
18705e96a66cSDavid du Colombier }
18715e96a66cSDavid du Colombier
18725e96a66cSDavid du Colombier int
fsysInit(void)18735e96a66cSDavid du Colombier fsysInit(void)
18745e96a66cSDavid du Colombier {
18755e96a66cSDavid du Colombier int i;
18765e96a66cSDavid du Colombier
18775e96a66cSDavid du Colombier fmtinstall('H', encodefmt);
18785e96a66cSDavid du Colombier fmtinstall('V', scoreFmt);
18795e96a66cSDavid du Colombier fmtinstall('L', labelFmt);
18805e96a66cSDavid du Colombier
18815e96a66cSDavid du Colombier cliAddCmd("fsys", cmdFsys);
18825e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){
18835e96a66cSDavid du Colombier if(fsyscmd[i].f != nil)
18845e96a66cSDavid du Colombier cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX);
18855e96a66cSDavid du Colombier }
18865e96a66cSDavid du Colombier /* the venti cmd is special: the fs can be either open or closed */
18875e96a66cSDavid du Colombier cliAddCmd("venti", cmdFsysXXX);
18885e96a66cSDavid du Colombier cliAddCmd("printconfig", cmdPrintConfig);
18895e96a66cSDavid du Colombier
18905e96a66cSDavid du Colombier return 1;
18915e96a66cSDavid du Colombier }
1892