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 {
85e96a66cSDavid du Colombier VtLock* 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;
155e96a66cSDavid du Colombier VtSession* 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 {
305e96a66cSDavid du Colombier VtLock* 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)
521bdadbfaSDavid du Colombier return vtStrDup(host);
53ea58ad6fSDavid du Colombier host = getenv("venti");
54ea58ad6fSDavid du Colombier if(host == nil)
551bdadbfaSDavid 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
70ea58ad6fSDavid du Colombier static VtSession *
myDial(char * host,int canfail)71ea58ad6fSDavid du Colombier myDial(char *host, int canfail)
72ea58ad6fSDavid du Colombier {
73ea58ad6fSDavid du Colombier prventihost(host);
74ea58ad6fSDavid du Colombier return vtDial(host, canfail);
75ea58ad6fSDavid du Colombier }
76ea58ad6fSDavid du Colombier
77ea58ad6fSDavid du Colombier static int
myRedial(VtSession * z,char * host)78ea58ad6fSDavid du Colombier myRedial(VtSession *z, char *host)
79ea58ad6fSDavid du Colombier {
80ea58ad6fSDavid du Colombier prventihost(host);
81ea58ad6fSDavid 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
925e96a66cSDavid du Colombier vtRLock(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 }
99dc5a79c1SDavid du Colombier vtRUnlock(sbox.lock);
1005e96a66cSDavid du Colombier if(fsys == nil)
1015e96a66cSDavid du Colombier vtSetError(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
1195e96a66cSDavid du Colombier vtRLock(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 }
1265e96a66cSDavid du Colombier vtRUnlock(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
1385e96a66cSDavid du Colombier vtLock(fsys->lock);
1395e96a66cSDavid du Colombier if(fsys->fs == nil){
1405e96a66cSDavid du Colombier vtSetError(EFsysNotOpen, fsys->name);
1415e96a66cSDavid du Colombier vtUnlock(fsys->lock);
1425e96a66cSDavid du Colombier fsysPut(fsys);
1435e96a66cSDavid du Colombier return nil;
1445e96a66cSDavid du Colombier }
1455e96a66cSDavid du Colombier vtUnlock(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 {
1595e96a66cSDavid du Colombier vtLock(sbox.lock);
1605e96a66cSDavid du Colombier fsys->ref++;
1615e96a66cSDavid du Colombier vtUnlock(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 {
1695e96a66cSDavid du Colombier vtLock(sbox.lock);
1705e96a66cSDavid du Colombier assert(fsys->ref > 0);
1715e96a66cSDavid du Colombier fsys->ref--;
1725e96a66cSDavid du Colombier vtUnlock(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 {
1865e96a66cSDavid du Colombier vtRLock(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 {
1925e96a66cSDavid du Colombier vtRUnlock(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
2885e96a66cSDavid du Colombier vtLock(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;
2925e96a66cSDavid du Colombier vtSetError(EFsysExists, name);
2935e96a66cSDavid du Colombier vtUnlock(sbox.lock);
2945e96a66cSDavid du Colombier return nil;
2955e96a66cSDavid du Colombier }
2965e96a66cSDavid du Colombier
2975e96a66cSDavid du Colombier fsys = vtMemAllocZ(sizeof(Fsys));
2985e96a66cSDavid du Colombier fsys->lock = vtLockAlloc();
2995e96a66cSDavid du Colombier fsys->name = vtStrDup(name);
3005e96a66cSDavid du Colombier fsys->dev = vtStrDup(dev);
3015e96a66cSDavid du Colombier
3025e96a66cSDavid du Colombier fsys->ref = 1;
3035e96a66cSDavid du Colombier
3045e96a66cSDavid du Colombier if(sbox.tail != nil)
3055e96a66cSDavid du Colombier sbox.tail->next = fsys;
3065e96a66cSDavid du Colombier else
3075e96a66cSDavid du Colombier sbox.head = fsys;
3085e96a66cSDavid du Colombier sbox.tail = fsys;
3095e96a66cSDavid du Colombier vtUnlock(sbox.lock);
3105e96a66cSDavid du Colombier
3115e96a66cSDavid du Colombier return fsys;
3125e96a66cSDavid du Colombier }
3135e96a66cSDavid du Colombier
3145e96a66cSDavid du Colombier static int
fsysClose(Fsys * fsys,int argc,char * argv[])3155e96a66cSDavid du Colombier fsysClose(Fsys* fsys, int argc, char* argv[])
3165e96a66cSDavid du Colombier {
3175e96a66cSDavid du Colombier char *usage = "usage: [fsys name] close";
3185e96a66cSDavid du Colombier
3195e96a66cSDavid du Colombier ARGBEGIN{
3205e96a66cSDavid du Colombier default:
3215e96a66cSDavid du Colombier return cliError(usage);
3225e96a66cSDavid du Colombier }ARGEND
3235e96a66cSDavid du Colombier if(argc)
3245e96a66cSDavid du Colombier return cliError(usage);
3255e96a66cSDavid du Colombier
32668412abfSDavid du Colombier return cliError("close isn't working yet; halt %s and then kill fossil",
32768412abfSDavid du Colombier fsys->name);
3285e96a66cSDavid du Colombier
3295e96a66cSDavid du Colombier /*
3305e96a66cSDavid du Colombier * Oooh. This could be hard. What if fsys->ref != 1?
3315e96a66cSDavid du Colombier * Also, fsClose() either does the job or panics, can we
3325e96a66cSDavid du Colombier * gracefully detect it's still busy?
3335e96a66cSDavid du Colombier *
3345e96a66cSDavid du Colombier * More thought and care needed here.
3355e96a66cSDavid du Colombier fsClose(fsys->fs);
3365e96a66cSDavid du Colombier fsys->fs = nil;
3375e96a66cSDavid du Colombier vtClose(fsys->session);
3385e96a66cSDavid du Colombier fsys->session = nil;
3395e96a66cSDavid du Colombier
3405e96a66cSDavid du Colombier if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){
3415e96a66cSDavid du Colombier sbox.curfsys = nil;
3425e96a66cSDavid du Colombier consPrompt(nil);
3435e96a66cSDavid du Colombier }
3445e96a66cSDavid du Colombier
3455e96a66cSDavid du Colombier return 1;
34668412abfSDavid du Colombier */
3475e96a66cSDavid du Colombier }
3485e96a66cSDavid du Colombier
3495e96a66cSDavid du Colombier static int
fsysVac(Fsys * fsys,int argc,char * argv[])3505e96a66cSDavid du Colombier fsysVac(Fsys* fsys, int argc, char* argv[])
3515e96a66cSDavid du Colombier {
3525e96a66cSDavid du Colombier uchar score[VtScoreSize];
3535e96a66cSDavid du Colombier char *usage = "usage: [fsys name] vac path";
3545e96a66cSDavid du Colombier
3555e96a66cSDavid du Colombier ARGBEGIN{
3565e96a66cSDavid du Colombier default:
3575e96a66cSDavid du Colombier return cliError(usage);
3585e96a66cSDavid du Colombier }ARGEND
3595e96a66cSDavid du Colombier if(argc != 1)
3605e96a66cSDavid du Colombier return cliError(usage);
3615e96a66cSDavid du Colombier
3625e96a66cSDavid du Colombier if(!fsVac(fsys->fs, argv[0], score))
3635e96a66cSDavid du Colombier return 0;
3645e96a66cSDavid du Colombier
3655e96a66cSDavid du Colombier consPrint("vac:%V\n", score);
3665e96a66cSDavid du Colombier return 1;
3675e96a66cSDavid du Colombier }
3685e96a66cSDavid du Colombier
3695e96a66cSDavid du Colombier static int
fsysSnap(Fsys * fsys,int argc,char * argv[])3705e96a66cSDavid du Colombier fsysSnap(Fsys* fsys, int argc, char* argv[])
3715e96a66cSDavid du Colombier {
3725e96a66cSDavid du Colombier int doarchive;
373c3c4501eSDavid du Colombier char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]";
374c3c4501eSDavid du Colombier char *src, *dst;
3755e96a66cSDavid du Colombier
376c3c4501eSDavid du Colombier src = nil;
377c3c4501eSDavid du Colombier dst = nil;
3785e96a66cSDavid du Colombier doarchive = 0;
3795e96a66cSDavid du Colombier ARGBEGIN{
3805e96a66cSDavid du Colombier default:
3815e96a66cSDavid du Colombier return cliError(usage);
3825e96a66cSDavid du Colombier case 'a':
3835e96a66cSDavid du Colombier doarchive = 1;
3845e96a66cSDavid du Colombier break;
385c3c4501eSDavid du Colombier case 'd':
386c3c4501eSDavid du Colombier if((dst = ARGF()) == nil)
387c3c4501eSDavid du Colombier return cliError(usage);
388c3c4501eSDavid du Colombier break;
389c3c4501eSDavid du Colombier case 's':
390c3c4501eSDavid du Colombier if((src = ARGF()) == nil)
391c3c4501eSDavid du Colombier return cliError(usage);
392c3c4501eSDavid du Colombier break;
3935e96a66cSDavid du Colombier }ARGEND
3945e96a66cSDavid du Colombier if(argc)
3955e96a66cSDavid du Colombier return cliError(usage);
3965e96a66cSDavid du Colombier
397c3c4501eSDavid du Colombier if(!fsSnapshot(fsys->fs, src, dst, doarchive))
3985e96a66cSDavid du Colombier return 0;
3995e96a66cSDavid du Colombier
4005e96a66cSDavid du Colombier return 1;
4015e96a66cSDavid du Colombier }
4025e96a66cSDavid du Colombier
4035e96a66cSDavid du Colombier static int
fsysSnapClean(Fsys * fsys,int argc,char * argv[])404dc5a79c1SDavid du Colombier fsysSnapClean(Fsys *fsys, int argc, char* argv[])
405dc5a79c1SDavid du Colombier {
406dc5a79c1SDavid du Colombier u32int arch, snap, life;
407dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snapclean [maxminutes]\n";
408dc5a79c1SDavid du Colombier
409dc5a79c1SDavid du Colombier ARGBEGIN{
410dc5a79c1SDavid du Colombier default:
411dc5a79c1SDavid du Colombier return cliError(usage);
412dc5a79c1SDavid du Colombier }ARGEND
413dc5a79c1SDavid du Colombier
414dc5a79c1SDavid du Colombier if(argc > 1)
415dc5a79c1SDavid du Colombier return cliError(usage);
416dc5a79c1SDavid du Colombier if(argc == 1)
417f83f9c78SDavid du Colombier life = atoi(argv[0]);
418dc5a79c1SDavid du Colombier else
419dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
420dc5a79c1SDavid du Colombier
421dc5a79c1SDavid du Colombier fsSnapshotCleanup(fsys->fs, life);
422dc5a79c1SDavid du Colombier return 1;
423dc5a79c1SDavid du Colombier }
424dc5a79c1SDavid du Colombier
425dc5a79c1SDavid du Colombier static int
fsysSnapTime(Fsys * fsys,int argc,char * argv[])4265e96a66cSDavid du Colombier fsysSnapTime(Fsys* fsys, int argc, char* argv[])
4275e96a66cSDavid du Colombier {
428dc5a79c1SDavid du Colombier char buf[128], *x;
429dc5a79c1SDavid du Colombier int hh, mm, changed;
430dc5a79c1SDavid du Colombier u32int arch, snap, life;
431dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]";
4325e96a66cSDavid du Colombier
433dc5a79c1SDavid du Colombier changed = 0;
434dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
4355e96a66cSDavid du Colombier ARGBEGIN{
4365e96a66cSDavid du Colombier case 'a':
437dc5a79c1SDavid du Colombier changed = 1;
4385e96a66cSDavid du Colombier x = ARGF();
4395e96a66cSDavid du Colombier if(x == nil)
4405e96a66cSDavid du Colombier return cliError(usage);
4415e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){
4425e96a66cSDavid du Colombier arch = ~(u32int)0;
4435e96a66cSDavid du Colombier break;
4445e96a66cSDavid du Colombier }
4455e96a66cSDavid du Colombier if(strlen(x) != 4 || strspn(x, "0123456789") != 4)
4465e96a66cSDavid du Colombier return cliError(usage);
4475e96a66cSDavid du Colombier hh = (x[0]-'0')*10 + x[1]-'0';
4485e96a66cSDavid du Colombier mm = (x[2]-'0')*10 + x[3]-'0';
4495e96a66cSDavid du Colombier if(hh >= 24 || mm >= 60)
4505e96a66cSDavid du Colombier return cliError(usage);
4515e96a66cSDavid du Colombier arch = hh*60+mm;
4525e96a66cSDavid du Colombier break;
4535e96a66cSDavid du Colombier case 's':
454dc5a79c1SDavid du Colombier changed = 1;
4555e96a66cSDavid du Colombier x = ARGF();
4565e96a66cSDavid du Colombier if(x == nil)
4575e96a66cSDavid du Colombier return cliError(usage);
4585e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){
4595e96a66cSDavid du Colombier snap = ~(u32int)0;
4605e96a66cSDavid du Colombier break;
4615e96a66cSDavid du Colombier }
4625e96a66cSDavid du Colombier snap = atoi(x);
4635e96a66cSDavid du Colombier break;
464dc5a79c1SDavid du Colombier case 't':
465dc5a79c1SDavid du Colombier changed = 1;
466dc5a79c1SDavid du Colombier x = ARGF();
467dc5a79c1SDavid du Colombier if(x == nil)
468dc5a79c1SDavid du Colombier return cliError(usage);
469dc5a79c1SDavid du Colombier if(strcmp(x, "none") == 0){
470dc5a79c1SDavid du Colombier life = ~(u32int)0;
471dc5a79c1SDavid du Colombier break;
472dc5a79c1SDavid du Colombier }
473dc5a79c1SDavid du Colombier life = atoi(x);
474dc5a79c1SDavid du Colombier break;
4755e96a66cSDavid du Colombier default:
4765e96a66cSDavid du Colombier return cliError(usage);
4775e96a66cSDavid du Colombier }ARGEND
4785e96a66cSDavid du Colombier if(argc > 0)
4795e96a66cSDavid du Colombier return cliError(usage);
4805e96a66cSDavid du Colombier
481dc5a79c1SDavid du Colombier if(changed){
482dc5a79c1SDavid du Colombier snapSetTimes(fsys->fs->snap, arch, snap, life);
483dc5a79c1SDavid du Colombier return 1;
484dc5a79c1SDavid du Colombier }
485dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
4865e96a66cSDavid du Colombier if(arch != ~(u32int)0)
4875e96a66cSDavid du Colombier sprint(buf, "-a %02d%02d", arch/60, arch%60);
4885e96a66cSDavid du Colombier else
4895e96a66cSDavid du Colombier sprint(buf, "-a none");
4905e96a66cSDavid du Colombier if(snap != ~(u32int)0)
4915e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s %d", snap);
4925e96a66cSDavid du Colombier else
4935e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s none");
494dc5a79c1SDavid du Colombier if(life != ~(u32int)0)
495dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t %ud", life);
496dc5a79c1SDavid du Colombier else
497dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t none");
4985e96a66cSDavid du Colombier consPrint("\tsnaptime %s\n", buf);
4995e96a66cSDavid du Colombier return 1;
5005e96a66cSDavid du Colombier }
5015e96a66cSDavid du Colombier
5025e96a66cSDavid du Colombier static int
fsysSync(Fsys * fsys,int argc,char * argv[])5035e96a66cSDavid du Colombier fsysSync(Fsys* fsys, int argc, char* argv[])
5045e96a66cSDavid du Colombier {
5055e96a66cSDavid du Colombier char *usage = "usage: [fsys name] sync";
5060b9a5132SDavid du Colombier int n;
5075e96a66cSDavid du Colombier
5085e96a66cSDavid du Colombier ARGBEGIN{
5095e96a66cSDavid du Colombier default:
5105e96a66cSDavid du Colombier return cliError(usage);
5115e96a66cSDavid du Colombier }ARGEND
5125e96a66cSDavid du Colombier if(argc > 0)
5135e96a66cSDavid du Colombier return cliError(usage);
5145e96a66cSDavid du Colombier
5150b9a5132SDavid du Colombier n = cacheDirty(fsys->fs->cache);
5165e96a66cSDavid du Colombier fsSync(fsys->fs);
5170b9a5132SDavid du Colombier consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n);
51881cf8742SDavid du Colombier return 1;
51981cf8742SDavid du Colombier }
5205e96a66cSDavid du Colombier
52181cf8742SDavid du Colombier static int
fsysHalt(Fsys * fsys,int argc,char * argv[])52281cf8742SDavid du Colombier fsysHalt(Fsys *fsys, int argc, char* argv[])
52381cf8742SDavid du Colombier {
52481cf8742SDavid du Colombier char *usage = "usage: [fsys name] halt";
52581cf8742SDavid du Colombier
52681cf8742SDavid du Colombier ARGBEGIN{
52781cf8742SDavid du Colombier default:
52881cf8742SDavid du Colombier return cliError(usage);
52981cf8742SDavid du Colombier }ARGEND
53081cf8742SDavid du Colombier if(argc > 0)
53181cf8742SDavid du Colombier return cliError(usage);
53281cf8742SDavid du Colombier
53381cf8742SDavid du Colombier fsHalt(fsys->fs);
53481cf8742SDavid du Colombier return 1;
53581cf8742SDavid du Colombier }
53681cf8742SDavid du Colombier
53781cf8742SDavid du Colombier static int
fsysUnhalt(Fsys * fsys,int argc,char * argv[])53881cf8742SDavid du Colombier fsysUnhalt(Fsys *fsys, int argc, char* argv[])
53981cf8742SDavid du Colombier {
54081cf8742SDavid du Colombier char *usage = "usage: [fsys name] unhalt";
54181cf8742SDavid du Colombier
54281cf8742SDavid du Colombier ARGBEGIN{
54381cf8742SDavid du Colombier default:
54481cf8742SDavid du Colombier return cliError(usage);
54581cf8742SDavid du Colombier }ARGEND
54681cf8742SDavid du Colombier if(argc > 0)
54781cf8742SDavid du Colombier return cliError(usage);
54881cf8742SDavid du Colombier
54981cf8742SDavid du Colombier if(!fsys->fs->halted)
55081cf8742SDavid du Colombier return cliError("file system %s not halted", fsys->name);
55181cf8742SDavid du Colombier
55281cf8742SDavid du Colombier fsUnhalt(fsys->fs);
5535e96a66cSDavid du Colombier return 1;
5545e96a66cSDavid du Colombier }
5555e96a66cSDavid du Colombier
5565e96a66cSDavid du Colombier static int
fsysRemove(Fsys * fsys,int argc,char * argv[])5575e96a66cSDavid du Colombier fsysRemove(Fsys* fsys, int argc, char* argv[])
5585e96a66cSDavid du Colombier {
5595e96a66cSDavid du Colombier File *file;
5605e96a66cSDavid du Colombier char *usage = "usage: [fsys name] remove path ...";
5615e96a66cSDavid du Colombier
5625e96a66cSDavid du Colombier ARGBEGIN{
5635e96a66cSDavid du Colombier default:
5645e96a66cSDavid du Colombier return cliError(usage);
5655e96a66cSDavid du Colombier }ARGEND
5665e96a66cSDavid du Colombier if(argc == 0)
5675e96a66cSDavid du Colombier return cliError(usage);
5685e96a66cSDavid du Colombier
5695e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
5705e96a66cSDavid du Colombier while(argc > 0){
5715e96a66cSDavid du Colombier if((file = fileOpen(fsys->fs, argv[0])) == nil)
5725e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]);
5735e96a66cSDavid du Colombier else{
5745e96a66cSDavid du Colombier if(!fileRemove(file, uidadm))
5755e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]);
5765e96a66cSDavid du Colombier fileDecRef(file);
5775e96a66cSDavid du Colombier }
5785e96a66cSDavid du Colombier argc--;
5795e96a66cSDavid du Colombier argv++;
5805e96a66cSDavid du Colombier }
5815e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
5825e96a66cSDavid du Colombier
5835e96a66cSDavid du Colombier return 1;
5845e96a66cSDavid du Colombier }
5855e96a66cSDavid du Colombier
5865e96a66cSDavid du Colombier static int
fsysClri(Fsys * fsys,int argc,char * argv[])5875e96a66cSDavid du Colombier fsysClri(Fsys* fsys, int argc, char* argv[])
5885e96a66cSDavid du Colombier {
5895e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clri path ...";
5905e96a66cSDavid du Colombier
5915e96a66cSDavid du Colombier ARGBEGIN{
5925e96a66cSDavid du Colombier default:
5935e96a66cSDavid du Colombier return cliError(usage);
5945e96a66cSDavid du Colombier }ARGEND
5955e96a66cSDavid du Colombier if(argc == 0)
5965e96a66cSDavid du Colombier return cliError(usage);
5975e96a66cSDavid du Colombier
5985e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
5995e96a66cSDavid du Colombier while(argc > 0){
600dc5a79c1SDavid du Colombier if(!fileClriPath(fsys->fs, argv[0], uidadm))
6015e96a66cSDavid du Colombier consPrint("clri %s: %R\n", argv[0]);
6025e96a66cSDavid du Colombier argc--;
6035e96a66cSDavid du Colombier argv++;
6045e96a66cSDavid du Colombier }
6055e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
6065e96a66cSDavid du Colombier
6075e96a66cSDavid du Colombier return 1;
6085e96a66cSDavid du Colombier }
6095e96a66cSDavid du Colombier
6105e96a66cSDavid du Colombier /*
6115e96a66cSDavid du Colombier * Inspect and edit the labels for blocks on disk.
6125e96a66cSDavid du Colombier */
6135e96a66cSDavid du Colombier static int
fsysLabel(Fsys * fsys,int argc,char * argv[])6145e96a66cSDavid du Colombier fsysLabel(Fsys* fsys, int argc, char* argv[])
6155e96a66cSDavid du Colombier {
6165e96a66cSDavid du Colombier Fs *fs;
6175e96a66cSDavid du Colombier Label l;
6185e96a66cSDavid du Colombier int n, r;
6195e96a66cSDavid du Colombier u32int addr;
6205e96a66cSDavid du Colombier Block *b, *bb;
6215e96a66cSDavid du Colombier char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]";
6225e96a66cSDavid du Colombier
6235e96a66cSDavid du Colombier ARGBEGIN{
6245e96a66cSDavid du Colombier default:
6255e96a66cSDavid du Colombier return cliError(usage);
6265e96a66cSDavid du Colombier }ARGEND
6275e96a66cSDavid du Colombier if(argc != 1 && argc != 6)
6285e96a66cSDavid du Colombier return cliError(usage);
6295e96a66cSDavid du Colombier
6305e96a66cSDavid du Colombier r = 0;
6315e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
6325e96a66cSDavid du Colombier
6335e96a66cSDavid du Colombier fs = fsys->fs;
6345e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
6355e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
6365e96a66cSDavid du Colombier if(b == nil)
6375e96a66cSDavid du Colombier goto Out0;
6385e96a66cSDavid du Colombier
6395e96a66cSDavid du Colombier l = b->l;
6405e96a66cSDavid du Colombier consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n",
6415e96a66cSDavid du Colombier argc==6 ? "old: " : "", addr, l.type, l.state,
6425e96a66cSDavid du Colombier l.epoch, l.epochClose, l.tag);
6435e96a66cSDavid du Colombier
6445e96a66cSDavid du Colombier if(argc == 6){
6455e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0)
6465e96a66cSDavid du Colombier l.type = atoi(argv[1]);
6475e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0)
6485e96a66cSDavid du Colombier l.state = atoi(argv[2]);
6495e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0)
6505e96a66cSDavid du Colombier l.epoch = strtoul(argv[3], 0, 0);
6515e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0)
6525e96a66cSDavid du Colombier l.epochClose = strtoul(argv[4], 0, 0);
6535e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0)
6545e96a66cSDavid du Colombier l.tag = strtoul(argv[5], 0, 0);
6555e96a66cSDavid du Colombier
6565e96a66cSDavid du Colombier consPrint("new: label %#ux %ud %ud %ud %ud %#x\n",
6575e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
6585e96a66cSDavid du Colombier bb = _blockSetLabel(b, &l);
6595e96a66cSDavid du Colombier if(bb == nil)
6605e96a66cSDavid du Colombier goto Out1;
6615e96a66cSDavid du Colombier n = 0;
6625e96a66cSDavid du Colombier for(;;){
663*e12a9870SDavid du Colombier if(blockWrite(bb, Waitlock)){
6645e96a66cSDavid du Colombier while(bb->iostate != BioClean){
6655e96a66cSDavid du Colombier assert(bb->iostate == BioWriting);
6665e96a66cSDavid du Colombier vtSleep(bb->ioready);
6675e96a66cSDavid du Colombier }
6685e96a66cSDavid du Colombier break;
6695e96a66cSDavid du Colombier }
6705e96a66cSDavid du Colombier consPrint("blockWrite: %R\n");
6715e96a66cSDavid du Colombier if(n++ >= 5){
6725e96a66cSDavid du Colombier consPrint("giving up\n");
6735e96a66cSDavid du Colombier break;
6745e96a66cSDavid du Colombier }
6755e96a66cSDavid du Colombier sleep(5*1000);
6765e96a66cSDavid du Colombier }
6775e96a66cSDavid du Colombier blockPut(bb);
6785e96a66cSDavid du Colombier }
6795e96a66cSDavid du Colombier r = 1;
6805e96a66cSDavid du Colombier Out1:
6815e96a66cSDavid du Colombier blockPut(b);
6825e96a66cSDavid du Colombier Out0:
6835e96a66cSDavid du Colombier vtRUnlock(fs->elk);
6845e96a66cSDavid du Colombier
6855e96a66cSDavid du Colombier return r;
6865e96a66cSDavid du Colombier }
6875e96a66cSDavid du Colombier
6885e96a66cSDavid du Colombier /*
6895e96a66cSDavid du Colombier * Inspect and edit the blocks on disk.
6905e96a66cSDavid du Colombier */
6915e96a66cSDavid du Colombier static int
fsysBlock(Fsys * fsys,int argc,char * argv[])6925e96a66cSDavid du Colombier fsysBlock(Fsys* fsys, int argc, char* argv[])
6935e96a66cSDavid du Colombier {
6945e96a66cSDavid du Colombier Fs *fs;
6955e96a66cSDavid du Colombier char *s;
6965e96a66cSDavid du Colombier Block *b;
6975e96a66cSDavid du Colombier uchar *buf;
6985e96a66cSDavid du Colombier u32int addr;
6995e96a66cSDavid du Colombier int c, count, i, offset;
7005e96a66cSDavid du Colombier char *usage = "usage: [fsys name] block addr offset [count [data]]";
7015e96a66cSDavid du Colombier
7025e96a66cSDavid du Colombier ARGBEGIN{
7035e96a66cSDavid du Colombier default:
7045e96a66cSDavid du Colombier return cliError(usage);
7055e96a66cSDavid du Colombier }ARGEND
7065e96a66cSDavid du Colombier if(argc < 2 || argc > 4)
7075e96a66cSDavid du Colombier return cliError(usage);
7085e96a66cSDavid du Colombier
7095e96a66cSDavid du Colombier fs = fsys->fs;
7105e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
7115e96a66cSDavid du Colombier offset = strtoul(argv[1], 0, 0);
7125e96a66cSDavid du Colombier if(offset < 0 || offset >= fs->blockSize){
7135e96a66cSDavid du Colombier vtSetError("bad offset");
7145e96a66cSDavid du Colombier return 0;
7155e96a66cSDavid du Colombier }
7165e96a66cSDavid du Colombier if(argc > 2)
7175e96a66cSDavid du Colombier count = strtoul(argv[2], 0, 0);
7185e96a66cSDavid du Colombier else
7195e96a66cSDavid du Colombier count = 100000000;
7205e96a66cSDavid du Colombier if(offset+count > fs->blockSize)
7215e96a66cSDavid du Colombier count = fs->blockSize - count;
7225e96a66cSDavid du Colombier
7235e96a66cSDavid du Colombier vtRLock(fs->elk);
7245e96a66cSDavid du Colombier
7255e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
7265e96a66cSDavid du Colombier if(b == nil){
7275e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr);
7285e96a66cSDavid du Colombier vtRUnlock(fs->elk);
7295e96a66cSDavid du Colombier return 0;
7305e96a66cSDavid du Colombier }
7315e96a66cSDavid du Colombier
7325e96a66cSDavid du Colombier consPrint("\t%sblock %#ux %ud %ud %.*H\n",
7335e96a66cSDavid du Colombier argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset);
7345e96a66cSDavid du Colombier
7355e96a66cSDavid du Colombier if(argc == 4){
7365e96a66cSDavid du Colombier s = argv[3];
7375e96a66cSDavid du Colombier if(strlen(s) != 2*count){
7385e96a66cSDavid du Colombier vtSetError("bad data count");
7395e96a66cSDavid du Colombier goto Out;
7405e96a66cSDavid du Colombier }
7415e96a66cSDavid du Colombier buf = vtMemAllocZ(count);
7425e96a66cSDavid du Colombier for(i = 0; i < count*2; i++){
7435e96a66cSDavid du Colombier if(s[i] >= '0' && s[i] <= '9')
7445e96a66cSDavid du Colombier c = s[i] - '0';
7455e96a66cSDavid du Colombier else if(s[i] >= 'a' && s[i] <= 'f')
7465e96a66cSDavid du Colombier c = s[i] - 'a' + 10;
7475e96a66cSDavid du Colombier else if(s[i] >= 'A' && s[i] <= 'F')
7485e96a66cSDavid du Colombier c = s[i] - 'A' + 10;
7495e96a66cSDavid du Colombier else{
7505e96a66cSDavid du Colombier vtSetError("bad hex");
7515e96a66cSDavid du Colombier vtMemFree(buf);
7525e96a66cSDavid du Colombier goto Out;
7535e96a66cSDavid du Colombier }
7545e96a66cSDavid du Colombier if((i & 1) == 0)
7555e96a66cSDavid du Colombier c <<= 4;
7565e96a66cSDavid du Colombier buf[i>>1] |= c;
7575e96a66cSDavid du Colombier }
7585e96a66cSDavid du Colombier memmove(b->data+offset, buf, count);
7595e96a66cSDavid du Colombier consPrint("\tnew: block %#ux %ud %ud %.*H\n",
7605e96a66cSDavid du Colombier addr, offset, count, count, b->data+offset);
7615e96a66cSDavid du Colombier blockDirty(b);
7625e96a66cSDavid du Colombier }
7635e96a66cSDavid du Colombier
7645e96a66cSDavid du Colombier Out:
7655e96a66cSDavid du Colombier blockPut(b);
7665e96a66cSDavid du Colombier vtRUnlock(fs->elk);
7675e96a66cSDavid du Colombier
7685e96a66cSDavid du Colombier return 1;
7695e96a66cSDavid du Colombier }
7705e96a66cSDavid du Colombier
7715e96a66cSDavid du Colombier /*
7725e96a66cSDavid du Colombier * Free a disk block.
7735e96a66cSDavid du Colombier */
7745e96a66cSDavid du Colombier static int
fsysBfree(Fsys * fsys,int argc,char * argv[])7755e96a66cSDavid du Colombier fsysBfree(Fsys* fsys, int argc, char* argv[])
7765e96a66cSDavid du Colombier {
7775e96a66cSDavid du Colombier Fs *fs;
7785e96a66cSDavid du Colombier Label l;
7795e96a66cSDavid du Colombier char *p;
7805e96a66cSDavid du Colombier Block *b;
7815e96a66cSDavid du Colombier u32int addr;
7825e96a66cSDavid du Colombier char *usage = "usage: [fsys name] bfree addr ...";
7835e96a66cSDavid du Colombier
7845e96a66cSDavid du Colombier ARGBEGIN{
7855e96a66cSDavid du Colombier default:
7865e96a66cSDavid du Colombier return cliError(usage);
7875e96a66cSDavid du Colombier }ARGEND
7885e96a66cSDavid du Colombier if(argc == 0)
7895e96a66cSDavid du Colombier return cliError(usage);
7905e96a66cSDavid du Colombier
7915e96a66cSDavid du Colombier fs = fsys->fs;
7925e96a66cSDavid du Colombier vtRLock(fs->elk);
7935e96a66cSDavid du Colombier while(argc > 0){
7945e96a66cSDavid du Colombier addr = strtoul(argv[0], &p, 0);
7955e96a66cSDavid du Colombier if(*p != '\0'){
7960c6300e7SDavid du Colombier consPrint("bad address - '%ud'\n", addr);
7975e96a66cSDavid du Colombier /* syntax error; let's stop */
7985e96a66cSDavid du Colombier vtRUnlock(fs->elk);
7995e96a66cSDavid du Colombier return 0;
8005e96a66cSDavid du Colombier }
8015e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
8025e96a66cSDavid du Colombier if(b == nil){
8035e96a66cSDavid du Colombier consPrint("loading %#ux: %R\n", addr);
8045e96a66cSDavid du Colombier continue;
8055e96a66cSDavid du Colombier }
8065e96a66cSDavid du Colombier l = b->l;
807e569ccb5SDavid du Colombier if(l.state == BsFree)
808e569ccb5SDavid du Colombier consPrint("%#ux is already free\n", addr);
809e569ccb5SDavid du Colombier else{
8105e96a66cSDavid du Colombier consPrint("label %#ux %ud %ud %ud %ud %#x\n",
8115e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
8125e96a66cSDavid du Colombier l.state = BsFree;
8135e96a66cSDavid du Colombier l.type = BtMax;
8145e96a66cSDavid du Colombier l.tag = 0;
8155e96a66cSDavid du Colombier l.epoch = 0;
8165e96a66cSDavid du Colombier l.epochClose = 0;
817e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0))
8185e96a66cSDavid du Colombier consPrint("freeing %#ux: %R\n", addr);
819e569ccb5SDavid du Colombier }
8205e96a66cSDavid du Colombier blockPut(b);
8215e96a66cSDavid du Colombier argc--;
8225e96a66cSDavid du Colombier argv++;
8235e96a66cSDavid du Colombier }
8245e96a66cSDavid du Colombier vtRUnlock(fs->elk);
8255e96a66cSDavid du Colombier
8265e96a66cSDavid du Colombier return 1;
8275e96a66cSDavid du Colombier }
8285e96a66cSDavid du Colombier
8297abd426fSDavid du Colombier static int
fsysDf(Fsys * fsys,int argc,char * argv[])8307abd426fSDavid du Colombier fsysDf(Fsys *fsys, int argc, char* argv[])
8317abd426fSDavid du Colombier {
8327abd426fSDavid du Colombier char *usage = "usage: [fsys name] df";
8337abd426fSDavid du Colombier u32int used, tot, bsize;
8347abd426fSDavid du Colombier Fs *fs;
8357abd426fSDavid du Colombier
8367abd426fSDavid du Colombier ARGBEGIN{
8377abd426fSDavid du Colombier default:
8387abd426fSDavid du Colombier return cliError(usage);
8397abd426fSDavid du Colombier }ARGEND
8407abd426fSDavid du Colombier if(argc != 0)
8417abd426fSDavid du Colombier return cliError(usage);
8427abd426fSDavid du Colombier
8437abd426fSDavid du Colombier fs = fsys->fs;
8447abd426fSDavid du Colombier cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize);
845*e12a9870SDavid du Colombier consPrint("\t%s: %,llud used + %,llud free = %,llud (%.1f%% used)\n",
846dc5a79c1SDavid du Colombier fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize,
847*e12a9870SDavid du Colombier tot*(vlong)bsize, used*100.0/tot);
8487abd426fSDavid du Colombier return 1;
8497abd426fSDavid du Colombier }
8507abd426fSDavid du Colombier
8515e96a66cSDavid du Colombier /*
8525e96a66cSDavid du Colombier * Zero an entry or a pointer.
8535e96a66cSDavid du Colombier */
8545e96a66cSDavid du Colombier static int
fsysClrep(Fsys * fsys,int argc,char * argv[],int ch)8555e96a66cSDavid du Colombier fsysClrep(Fsys* fsys, int argc, char* argv[], int ch)
8565e96a66cSDavid du Colombier {
8575e96a66cSDavid du Colombier Fs *fs;
8585e96a66cSDavid du Colombier Entry e;
8595e96a66cSDavid du Colombier Block *b;
8605e96a66cSDavid du Colombier u32int addr;
8615e96a66cSDavid du Colombier int i, max, offset, sz;
8625e96a66cSDavid du Colombier uchar zero[VtEntrySize];
8635e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clr%c addr offset ...";
8645e96a66cSDavid du Colombier
8655e96a66cSDavid du Colombier ARGBEGIN{
8665e96a66cSDavid du Colombier default:
8675e96a66cSDavid du Colombier return cliError(usage, ch);
8685e96a66cSDavid du Colombier }ARGEND
8695e96a66cSDavid du Colombier if(argc < 2)
8705e96a66cSDavid du Colombier return cliError(usage, ch);
8715e96a66cSDavid du Colombier
8725e96a66cSDavid du Colombier fs = fsys->fs;
8735e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
8745e96a66cSDavid du Colombier
8755e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0);
8765e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
8775e96a66cSDavid du Colombier if(b == nil){
8785e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr);
8795e96a66cSDavid du Colombier Err:
8805e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
8815e96a66cSDavid du Colombier return 0;
8825e96a66cSDavid du Colombier }
8835e96a66cSDavid du Colombier
8845e96a66cSDavid du Colombier switch(ch){
8855e96a66cSDavid du Colombier default:
8865e96a66cSDavid du Colombier vtSetError("clrep");
8875e96a66cSDavid du Colombier goto Err;
8885e96a66cSDavid du Colombier case 'e':
8895e96a66cSDavid du Colombier if(b->l.type != BtDir){
8905e96a66cSDavid du Colombier vtSetError("wrong block type");
8915e96a66cSDavid du Colombier goto Err;
8925e96a66cSDavid du Colombier }
8935e96a66cSDavid du Colombier sz = VtEntrySize;
8945e96a66cSDavid du Colombier memset(&e, 0, sizeof e);
8955e96a66cSDavid du Colombier entryPack(&e, zero, 0);
8965e96a66cSDavid du Colombier break;
8975e96a66cSDavid du Colombier case 'p':
8985e96a66cSDavid du Colombier if(b->l.type == BtDir || b->l.type == BtData){
8995e96a66cSDavid du Colombier vtSetError("wrong block type");
9005e96a66cSDavid du Colombier goto Err;
9015e96a66cSDavid du Colombier }
9025e96a66cSDavid du Colombier sz = VtScoreSize;
9035e96a66cSDavid du Colombier memmove(zero, vtZeroScore, VtScoreSize);
9045e96a66cSDavid du Colombier break;
9055e96a66cSDavid du Colombier }
9065e96a66cSDavid du Colombier max = fs->blockSize/sz;
9075e96a66cSDavid du Colombier
9085e96a66cSDavid du Colombier for(i = 1; i < argc; i++){
9095e96a66cSDavid du Colombier offset = atoi(argv[i]);
9105e96a66cSDavid du Colombier if(offset >= max){
9115e96a66cSDavid du Colombier consPrint("\toffset %d too large (>= %d)\n", i, max);
9125e96a66cSDavid du Colombier continue;
9135e96a66cSDavid du Colombier }
9145e96a66cSDavid du Colombier consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz);
9155e96a66cSDavid du Colombier memmove(b->data+offset*sz, zero, sz);
9165e96a66cSDavid du Colombier }
9175e96a66cSDavid du Colombier blockDirty(b);
9185e96a66cSDavid du Colombier blockPut(b);
9195e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
9205e96a66cSDavid du Colombier
9215e96a66cSDavid du Colombier return 1;
9225e96a66cSDavid du Colombier }
9235e96a66cSDavid du Colombier
9245e96a66cSDavid du Colombier static int
fsysClre(Fsys * fsys,int argc,char * argv[])9255e96a66cSDavid du Colombier fsysClre(Fsys* fsys, int argc, char* argv[])
9265e96a66cSDavid du Colombier {
9275e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'e');
9285e96a66cSDavid du Colombier }
9295e96a66cSDavid du Colombier
9305e96a66cSDavid du Colombier static int
fsysClrp(Fsys * fsys,int argc,char * argv[])9315e96a66cSDavid du Colombier fsysClrp(Fsys* fsys, int argc, char* argv[])
9325e96a66cSDavid du Colombier {
9335e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'p');
9345e96a66cSDavid du Colombier }
9355e96a66cSDavid du Colombier
9365e96a66cSDavid du Colombier static int
fsysEsearch1(File * f,char * s,u32int elo)9375e96a66cSDavid du Colombier fsysEsearch1(File* f, char* s, u32int elo)
9385e96a66cSDavid du Colombier {
9395e96a66cSDavid du Colombier int n, r;
9405e96a66cSDavid du Colombier DirEntry de;
9415e96a66cSDavid du Colombier DirEntryEnum *dee;
9425e96a66cSDavid du Colombier File *ff;
9435e96a66cSDavid du Colombier Entry e, ee;
9445e96a66cSDavid du Colombier char *t;
9455e96a66cSDavid du Colombier
9465e96a66cSDavid du Colombier dee = deeOpen(f);
9475e96a66cSDavid du Colombier if(dee == nil)
9485e96a66cSDavid du Colombier return 0;
9495e96a66cSDavid du Colombier
9505e96a66cSDavid du Colombier n = 0;
9515e96a66cSDavid du Colombier for(;;){
9525e96a66cSDavid du Colombier r = deeRead(dee, &de);
9535e96a66cSDavid du Colombier if(r < 0){
9545e96a66cSDavid du Colombier consPrint("\tdeeRead %s/%s: %R\n", s, de.elem);
9555e96a66cSDavid du Colombier break;
9565e96a66cSDavid du Colombier }
9575e96a66cSDavid du Colombier if(r == 0)
9585e96a66cSDavid du Colombier break;
9595e96a66cSDavid du Colombier if(de.mode & ModeSnapshot){
9605e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil)
9615e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
9625e96a66cSDavid du Colombier else{
963e569ccb5SDavid du Colombier if(!fileGetSources(ff, &e, &ee))
9645e96a66cSDavid du Colombier consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem);
9655e96a66cSDavid du Colombier else if(e.snap != 0 && e.snap < elo){
9665e96a66cSDavid du Colombier consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem);
9675e96a66cSDavid du Colombier n++;
9685e96a66cSDavid du Colombier }
9695e96a66cSDavid du Colombier fileDecRef(ff);
9705e96a66cSDavid du Colombier }
9715e96a66cSDavid du Colombier }
9725e96a66cSDavid du Colombier else if(de.mode & ModeDir){
9735e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil)
9745e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
9755e96a66cSDavid du Colombier else{
976f8e525acSDavid du Colombier t = smprint("%s/%s", s, de.elem);
9775e96a66cSDavid du Colombier n += fsysEsearch1(ff, t, elo);
9785e96a66cSDavid du Colombier vtMemFree(t);
9795e96a66cSDavid du Colombier fileDecRef(ff);
9805e96a66cSDavid du Colombier }
9815e96a66cSDavid du Colombier }
9825e96a66cSDavid du Colombier deCleanup(&de);
9835e96a66cSDavid du Colombier if(r < 0)
9845e96a66cSDavid du Colombier break;
9855e96a66cSDavid du Colombier }
9865e96a66cSDavid du Colombier deeClose(dee);
9875e96a66cSDavid du Colombier
9885e96a66cSDavid du Colombier return n;
9895e96a66cSDavid du Colombier }
9905e96a66cSDavid du Colombier
9915e96a66cSDavid du Colombier static int
fsysEsearch(Fs * fs,char * path,u32int elo)9925e96a66cSDavid du Colombier fsysEsearch(Fs* fs, char* path, u32int elo)
9935e96a66cSDavid du Colombier {
9945e96a66cSDavid du Colombier int n;
9955e96a66cSDavid du Colombier File *f;
9965e96a66cSDavid du Colombier DirEntry de;
9975e96a66cSDavid du Colombier
9985e96a66cSDavid du Colombier f = fileOpen(fs, path);
9995e96a66cSDavid du Colombier if(f == nil)
10005e96a66cSDavid du Colombier return 0;
10015e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
10025e96a66cSDavid du Colombier consPrint("\tfileGetDir %s failed: %R\n", path);
10035e96a66cSDavid du Colombier fileDecRef(f);
10045e96a66cSDavid du Colombier return 0;
10055e96a66cSDavid du Colombier }
10065e96a66cSDavid du Colombier if((de.mode & ModeDir) == 0){
10075e96a66cSDavid du Colombier fileDecRef(f);
10085e96a66cSDavid du Colombier deCleanup(&de);
10095e96a66cSDavid du Colombier return 0;
10105e96a66cSDavid du Colombier }
10115e96a66cSDavid du Colombier deCleanup(&de);
10125e96a66cSDavid du Colombier n = fsysEsearch1(f, path, elo);
10135e96a66cSDavid du Colombier fileDecRef(f);
10145e96a66cSDavid du Colombier return n;
10155e96a66cSDavid du Colombier }
10165e96a66cSDavid du Colombier
10175e96a66cSDavid du Colombier static int
fsysEpoch(Fsys * fsys,int argc,char * argv[])10185e96a66cSDavid du Colombier fsysEpoch(Fsys* fsys, int argc, char* argv[])
10195e96a66cSDavid du Colombier {
10205e96a66cSDavid du Colombier Fs *fs;
1021dc5a79c1SDavid du Colombier int force, n, remove;
10225e96a66cSDavid du Colombier u32int low, old;
1023dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] epoch [[-ry] low]";
10245e96a66cSDavid du Colombier
10255e96a66cSDavid du Colombier force = 0;
1026dc5a79c1SDavid du Colombier remove = 0;
10275e96a66cSDavid du Colombier ARGBEGIN{
10285e96a66cSDavid du Colombier case 'y':
10295e96a66cSDavid du Colombier force = 1;
10305e96a66cSDavid du Colombier break;
1031dc5a79c1SDavid du Colombier case 'r':
1032dc5a79c1SDavid du Colombier remove = 1;
1033dc5a79c1SDavid du Colombier break;
10345e96a66cSDavid du Colombier default:
10355e96a66cSDavid du Colombier return cliError(usage);
10365e96a66cSDavid du Colombier }ARGEND
10375e96a66cSDavid du Colombier if(argc > 1)
10385e96a66cSDavid du Colombier return cliError(usage);
10395e96a66cSDavid du Colombier if(argc > 0)
10405e96a66cSDavid du Colombier low = strtoul(argv[0], 0, 0);
10415e96a66cSDavid du Colombier else
10425e96a66cSDavid du Colombier low = ~(u32int)0;
10435e96a66cSDavid du Colombier
10448a2c5ad0SDavid du Colombier if(low == 0)
10458a2c5ad0SDavid du Colombier return cliError("low epoch cannot be zero");
10468a2c5ad0SDavid du Colombier
10475e96a66cSDavid du Colombier fs = fsys->fs;
10485e96a66cSDavid du Colombier
10495e96a66cSDavid du Colombier vtRLock(fs->elk);
10505e96a66cSDavid du Colombier consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi);
105157195852SDavid du Colombier if(low == ~(u32int)0){
105257195852SDavid du Colombier vtRUnlock(fs->elk);
105357195852SDavid du Colombier return 1;
105457195852SDavid du Colombier }
10555e96a66cSDavid du Colombier n = fsysEsearch(fsys->fs, "/archive", low);
10565e96a66cSDavid du Colombier n += fsysEsearch(fsys->fs, "/snapshot", low);
10575e96a66cSDavid du Colombier consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low);
10585e96a66cSDavid du Colombier vtRUnlock(fs->elk);
10595e96a66cSDavid du Colombier
10605e96a66cSDavid du Colombier /*
10615e96a66cSDavid du Colombier * There's a small race here -- a new snapshot with epoch < low might
10625e96a66cSDavid du Colombier * get introduced now that we unlocked fs->elk. Low has to
10635e96a66cSDavid du Colombier * be <= fs->ehi. Of course, in order for this to happen low has
10645e96a66cSDavid du Colombier * to be equal to the current fs->ehi _and_ a snapshot has to
10655e96a66cSDavid du Colombier * run right now. This is a small enough window that I don't care.
10665e96a66cSDavid du Colombier */
10675e96a66cSDavid du Colombier if(n != 0 && !force){
10685e96a66cSDavid du Colombier consPrint("\tnot setting low epoch\n");
10695e96a66cSDavid du Colombier return 1;
10705e96a66cSDavid du Colombier }
10715e96a66cSDavid du Colombier old = fs->elo;
10725e96a66cSDavid du Colombier if(!fsEpochLow(fs, low))
10735e96a66cSDavid du Colombier consPrint("\tfsEpochLow: %R\n");
10745e96a66cSDavid du Colombier else{
10755e96a66cSDavid du Colombier consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old);
10765e96a66cSDavid du Colombier consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo);
10775e96a66cSDavid du Colombier if(fs->elo < low)
10785e96a66cSDavid du Colombier consPrint("\twarning: new low epoch < old low epoch\n");
1079dc5a79c1SDavid du Colombier if(force && remove)
1080dc5a79c1SDavid du Colombier fsSnapshotRemove(fs);
10815e96a66cSDavid du Colombier }
10825e96a66cSDavid du Colombier
10835e96a66cSDavid du Colombier return 1;
10845e96a66cSDavid du Colombier }
10855e96a66cSDavid du Colombier
10865e96a66cSDavid du Colombier static int
fsysCreate(Fsys * fsys,int argc,char * argv[])10875e96a66cSDavid du Colombier fsysCreate(Fsys* fsys, int argc, char* argv[])
10885e96a66cSDavid du Colombier {
10895e96a66cSDavid du Colombier int r;
10905e96a66cSDavid du Colombier ulong mode;
10915e96a66cSDavid du Colombier char *elem, *p, *path;
10925e96a66cSDavid du Colombier char *usage = "usage: [fsys name] create path uid gid perm";
10935e96a66cSDavid du Colombier DirEntry de;
10945e96a66cSDavid du Colombier File *file, *parent;
10955e96a66cSDavid du Colombier
10965e96a66cSDavid du Colombier ARGBEGIN{
10975e96a66cSDavid du Colombier default:
10985e96a66cSDavid du Colombier return cliError(usage);
10995e96a66cSDavid du Colombier }ARGEND
11005e96a66cSDavid du Colombier if(argc != 4)
11015e96a66cSDavid du Colombier return cliError(usage);
11025e96a66cSDavid du Colombier
11035e96a66cSDavid du Colombier if(!fsysParseMode(argv[3], &mode))
11045e96a66cSDavid du Colombier return cliError(usage);
11055e96a66cSDavid du Colombier if(mode&ModeSnapshot)
11065e96a66cSDavid du Colombier return cliError("create - cannot create with snapshot bit set");
11075e96a66cSDavid du Colombier
11085e96a66cSDavid du Colombier if(strcmp(argv[1], uidnoworld) == 0)
11095e96a66cSDavid du Colombier return cliError("permission denied");
11105e96a66cSDavid du Colombier
11115e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
11125e96a66cSDavid du Colombier path = vtStrDup(argv[0]);
11135e96a66cSDavid du Colombier if((p = strrchr(path, '/')) != nil){
11145e96a66cSDavid du Colombier *p++ = '\0';
11155e96a66cSDavid du Colombier elem = p;
11165e96a66cSDavid du Colombier p = path;
11175e96a66cSDavid du Colombier if(*p == '\0')
11185e96a66cSDavid du Colombier p = "/";
11195e96a66cSDavid du Colombier }
11205e96a66cSDavid du Colombier else{
11215e96a66cSDavid du Colombier p = "/";
11225e96a66cSDavid du Colombier elem = path;
11235e96a66cSDavid du Colombier }
1124f8e525acSDavid du Colombier
11255e96a66cSDavid du Colombier r = 0;
1126f8e525acSDavid du Colombier if((parent = fileOpen(fsys->fs, p)) == nil)
1127f8e525acSDavid du Colombier goto out;
1128f8e525acSDavid du Colombier
11295e96a66cSDavid du Colombier file = fileCreate(parent, elem, mode, argv[1]);
11305e96a66cSDavid du Colombier fileDecRef(parent);
1131f8e525acSDavid du Colombier if(file == nil){
1132f8e525acSDavid du Colombier vtSetError("create %s/%s: %R", p, elem);
1133f8e525acSDavid du Colombier goto out;
1134f8e525acSDavid du Colombier }
1135f8e525acSDavid du Colombier
1136f8e525acSDavid du Colombier if(!fileGetDir(file, &de)){
1137f8e525acSDavid du Colombier vtSetError("stat failed after create: %R");
1138f8e525acSDavid du Colombier goto out1;
1139f8e525acSDavid du Colombier }
1140f8e525acSDavid du Colombier
11415e96a66cSDavid du Colombier if(strcmp(de.gid, argv[2]) != 0){
11425e96a66cSDavid du Colombier vtMemFree(de.gid);
11435e96a66cSDavid du Colombier de.gid = vtStrDup(argv[2]);
1144f8e525acSDavid du Colombier if(!fileSetDir(file, &de, argv[1])){
1145f8e525acSDavid du Colombier vtSetError("wstat failed after create: %R");
1146f8e525acSDavid du Colombier goto out2;
11475e96a66cSDavid du Colombier }
1148f8e525acSDavid du Colombier }
1149f8e525acSDavid du Colombier r = 1;
1150f8e525acSDavid du Colombier
1151f8e525acSDavid du Colombier out2:
11525e96a66cSDavid du Colombier deCleanup(&de);
1153f8e525acSDavid du Colombier out1:
11545e96a66cSDavid du Colombier fileDecRef(file);
1155f8e525acSDavid du Colombier out:
11565e96a66cSDavid du Colombier vtMemFree(path);
11575e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
11585e96a66cSDavid du Colombier
11595e96a66cSDavid du Colombier return r;
11605e96a66cSDavid du Colombier }
11615e96a66cSDavid du Colombier
11625e96a66cSDavid du Colombier static void
fsysPrintStat(char * prefix,char * file,DirEntry * de)11635e96a66cSDavid du Colombier fsysPrintStat(char *prefix, char *file, DirEntry *de)
11645e96a66cSDavid du Colombier {
11655e96a66cSDavid du Colombier char buf[64];
11665e96a66cSDavid du Colombier
11675e96a66cSDavid du Colombier if(prefix == nil)
11685e96a66cSDavid du Colombier prefix = "";
11695e96a66cSDavid du Colombier consPrint("%sstat %q %q %q %q %s %llud\n", prefix,
11705e96a66cSDavid du Colombier file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);
11715e96a66cSDavid du Colombier }
11725e96a66cSDavid du Colombier
11735e96a66cSDavid du Colombier static int
fsysStat(Fsys * fsys,int argc,char * argv[])11745e96a66cSDavid du Colombier fsysStat(Fsys* fsys, int argc, char* argv[])
11755e96a66cSDavid du Colombier {
11765e96a66cSDavid du Colombier int i;
11775e96a66cSDavid du Colombier File *f;
11785e96a66cSDavid du Colombier DirEntry de;
11795e96a66cSDavid du Colombier char *usage = "usage: [fsys name] stat files...";
11805e96a66cSDavid du Colombier
11815e96a66cSDavid du Colombier ARGBEGIN{
11825e96a66cSDavid du Colombier default:
11835e96a66cSDavid du Colombier return cliError(usage);
11845e96a66cSDavid du Colombier }ARGEND
11855e96a66cSDavid du Colombier
11865e96a66cSDavid du Colombier if(argc == 0)
11875e96a66cSDavid du Colombier return cliError(usage);
11885e96a66cSDavid du Colombier
11895e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
11905e96a66cSDavid du Colombier for(i=0; i<argc; i++){
11915e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[i])) == nil){
11920c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]);
11935e96a66cSDavid du Colombier continue;
11945e96a66cSDavid du Colombier }
11955e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
11960c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]);
11975e96a66cSDavid du Colombier fileDecRef(f);
11985e96a66cSDavid du Colombier continue;
11995e96a66cSDavid du Colombier }
12005e96a66cSDavid du Colombier fsysPrintStat("\t", argv[i], &de);
12015e96a66cSDavid du Colombier deCleanup(&de);
12025e96a66cSDavid du Colombier fileDecRef(f);
12035e96a66cSDavid du Colombier }
12045e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
12055e96a66cSDavid du Colombier return 1;
12065e96a66cSDavid du Colombier }
12075e96a66cSDavid du Colombier
12085e96a66cSDavid du Colombier static int
fsysWstat(Fsys * fsys,int argc,char * argv[])12095e96a66cSDavid du Colombier fsysWstat(Fsys *fsys, int argc, char* argv[])
12105e96a66cSDavid du Colombier {
12115e96a66cSDavid du Colombier File *f;
12125e96a66cSDavid du Colombier char *p;
12135e96a66cSDavid du Colombier DirEntry de;
12145e96a66cSDavid du Colombier char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n"
12155e96a66cSDavid du Colombier "\tuse - for any field to mean don't change";
12165e96a66cSDavid du Colombier
12175e96a66cSDavid du Colombier ARGBEGIN{
12185e96a66cSDavid du Colombier default:
12195e96a66cSDavid du Colombier return cliError(usage);
12205e96a66cSDavid du Colombier }ARGEND
12215e96a66cSDavid du Colombier
12225e96a66cSDavid du Colombier if(argc != 6)
12235e96a66cSDavid du Colombier return cliError(usage);
12245e96a66cSDavid du Colombier
12255e96a66cSDavid du Colombier vtRLock(fsys->fs->elk);
12265e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[0])) == nil){
12275e96a66cSDavid du Colombier vtSetError("console wstat - walk - %R");
12285e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
12295e96a66cSDavid du Colombier return 0;
12305e96a66cSDavid du Colombier }
12315e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
12325e96a66cSDavid du Colombier vtSetError("console wstat - stat - %R");
12335e96a66cSDavid du Colombier fileDecRef(f);
12345e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
12355e96a66cSDavid du Colombier return 0;
12365e96a66cSDavid du Colombier }
12375e96a66cSDavid du Colombier fsysPrintStat("\told: w", argv[0], &de);
12385e96a66cSDavid du Colombier
12395e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0){
12405e96a66cSDavid du Colombier if(!validFileName(argv[1])){
12415e96a66cSDavid du Colombier vtSetError("console wstat - bad elem");
12425e96a66cSDavid du Colombier goto error;
12435e96a66cSDavid du Colombier }
12445e96a66cSDavid du Colombier vtMemFree(de.elem);
12455e96a66cSDavid du Colombier de.elem = vtStrDup(argv[1]);
12465e96a66cSDavid du Colombier }
12475e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0){
12485e96a66cSDavid du Colombier if(!validUserName(argv[2])){
12495e96a66cSDavid du Colombier vtSetError("console wstat - bad uid");
12505e96a66cSDavid du Colombier goto error;
12515e96a66cSDavid du Colombier }
12525e96a66cSDavid du Colombier vtMemFree(de.uid);
12535e96a66cSDavid du Colombier de.uid = vtStrDup(argv[2]);
12545e96a66cSDavid du Colombier }
12555e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0){
12565e96a66cSDavid du Colombier if(!validUserName(argv[3])){
12575e96a66cSDavid du Colombier vtSetError("console wstat - bad gid");
12585e96a66cSDavid du Colombier goto error;
12595e96a66cSDavid du Colombier }
12605e96a66cSDavid du Colombier vtMemFree(de.gid);
12615e96a66cSDavid du Colombier de.gid = vtStrDup(argv[3]);
12625e96a66cSDavid du Colombier }
12635e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0){
12645e96a66cSDavid du Colombier if(!fsysParseMode(argv[4], &de.mode)){
12655e96a66cSDavid du Colombier vtSetError("console wstat - bad mode");
12665e96a66cSDavid du Colombier goto error;
12675e96a66cSDavid du Colombier }
12685e96a66cSDavid du Colombier }
12695e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0){
12705e96a66cSDavid du Colombier de.size = strtoull(argv[5], &p, 0);
127122a127bbSDavid du Colombier if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){
12725e96a66cSDavid du Colombier vtSetError("console wstat - bad length");
12735e96a66cSDavid du Colombier goto error;
12745e96a66cSDavid du Colombier }
12755e96a66cSDavid du Colombier }
12765e96a66cSDavid du Colombier
12775e96a66cSDavid du Colombier if(!fileSetDir(f, &de, uidadm)){
12785e96a66cSDavid du Colombier vtSetError("console wstat - %R");
12795e96a66cSDavid du Colombier goto error;
12805e96a66cSDavid du Colombier }
12815e96a66cSDavid du Colombier deCleanup(&de);
12825e96a66cSDavid du Colombier
12835e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){
12845e96a66cSDavid du Colombier vtSetError("console wstat - stat2 - %R");
12855e96a66cSDavid du Colombier goto error;
12865e96a66cSDavid du Colombier }
12875e96a66cSDavid du Colombier fsysPrintStat("\tnew: w", argv[0], &de);
12885e96a66cSDavid du Colombier deCleanup(&de);
12895e96a66cSDavid du Colombier fileDecRef(f);
12905e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
12915e96a66cSDavid du Colombier
12925e96a66cSDavid du Colombier return 1;
12935e96a66cSDavid du Colombier
12945e96a66cSDavid du Colombier error:
12955e96a66cSDavid du Colombier deCleanup(&de); /* okay to do this twice */
12965e96a66cSDavid du Colombier fileDecRef(f);
12975e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk);
12985e96a66cSDavid du Colombier return 0;
12995e96a66cSDavid du Colombier }
13005e96a66cSDavid du Colombier
1301e569ccb5SDavid du Colombier static void
fsckClri(Fsck * fsck,char * name,MetaBlock * mb,int i,Block * b)1302e569ccb5SDavid du Colombier fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b)
1303e569ccb5SDavid du Colombier {
1304e569ccb5SDavid du Colombier USED(name);
1305e569ccb5SDavid du Colombier
1306e569ccb5SDavid du Colombier if((fsck->flags&DoClri) == 0)
1307e569ccb5SDavid du Colombier return;
1308e569ccb5SDavid du Colombier
1309e569ccb5SDavid du Colombier mbDelete(mb, i);
1310e569ccb5SDavid du Colombier mbPack(mb);
1311e569ccb5SDavid du Colombier blockDirty(b);
1312e569ccb5SDavid du Colombier }
1313e569ccb5SDavid du Colombier
1314e569ccb5SDavid du Colombier static void
fsckClose(Fsck * fsck,Block * b,u32int epoch)1315e569ccb5SDavid du Colombier fsckClose(Fsck *fsck, Block *b, u32int epoch)
1316e569ccb5SDavid du Colombier {
1317e569ccb5SDavid du Colombier Label l;
1318e569ccb5SDavid du Colombier
1319e569ccb5SDavid du Colombier if((fsck->flags&DoClose) == 0)
1320e569ccb5SDavid du Colombier return;
1321e569ccb5SDavid du Colombier l = b->l;
1322e569ccb5SDavid du Colombier if(l.state == BsFree || (l.state&BsClosed)){
1323e569ccb5SDavid du Colombier consPrint("%#ux is already closed\n", b->addr);
1324e569ccb5SDavid du Colombier return;
1325e569ccb5SDavid du Colombier }
1326e569ccb5SDavid du Colombier if(epoch){
1327e569ccb5SDavid du Colombier l.state |= BsClosed;
1328e569ccb5SDavid du Colombier l.epochClose = epoch;
1329e569ccb5SDavid du Colombier }else
1330e569ccb5SDavid du Colombier l.state = BsFree;
1331e569ccb5SDavid du Colombier
1332e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0))
1333e569ccb5SDavid du Colombier consPrint("%#ux setlabel: %R\n", b->addr);
1334e569ccb5SDavid du Colombier }
1335e569ccb5SDavid du Colombier
1336e569ccb5SDavid du Colombier static void
fsckClre(Fsck * fsck,Block * b,int offset)1337e569ccb5SDavid du Colombier fsckClre(Fsck *fsck, Block *b, int offset)
1338e569ccb5SDavid du Colombier {
1339e569ccb5SDavid du Colombier Entry e;
1340e569ccb5SDavid du Colombier
1341e569ccb5SDavid du Colombier if((fsck->flags&DoClre) == 0)
1342e569ccb5SDavid du Colombier return;
1343e569ccb5SDavid du Colombier if(offset<0 || offset*VtEntrySize >= fsck->bsize){
1344e569ccb5SDavid du Colombier consPrint("bad clre\n");
1345e569ccb5SDavid du Colombier return;
1346e569ccb5SDavid du Colombier }
1347e569ccb5SDavid du Colombier memset(&e, 0, sizeof e);
1348e569ccb5SDavid du Colombier entryPack(&e, b->data, offset);
1349e569ccb5SDavid du Colombier blockDirty(b);
1350e569ccb5SDavid du Colombier }
1351e569ccb5SDavid du Colombier
1352e569ccb5SDavid du Colombier static void
fsckClrp(Fsck * fsck,Block * b,int offset)1353e569ccb5SDavid du Colombier fsckClrp(Fsck *fsck, Block *b, int offset)
1354e569ccb5SDavid du Colombier {
1355e569ccb5SDavid du Colombier if((fsck->flags&DoClrp) == 0)
1356e569ccb5SDavid du Colombier return;
1357e569ccb5SDavid du Colombier if(offset<0 || offset*VtScoreSize >= fsck->bsize){
1358e569ccb5SDavid du Colombier consPrint("bad clre\n");
1359e569ccb5SDavid du Colombier return;
1360e569ccb5SDavid du Colombier }
1361e569ccb5SDavid du Colombier memmove(b->data+offset*VtScoreSize, vtZeroScore, VtScoreSize);
1362e569ccb5SDavid du Colombier blockDirty(b);
1363e569ccb5SDavid du Colombier }
1364e569ccb5SDavid du Colombier
1365e569ccb5SDavid du Colombier static int
fsysCheck(Fsys * fsys,int argc,char * argv[])1366e569ccb5SDavid du Colombier fsysCheck(Fsys *fsys, int argc, char *argv[])
1367e569ccb5SDavid du Colombier {
1368e569ccb5SDavid du Colombier int i, halting;
1369e569ccb5SDavid du Colombier char *usage = "usage: [fsys name] check [-v] [options]";
1370e569ccb5SDavid du Colombier Fsck fsck;
1371e569ccb5SDavid du Colombier Block *b;
1372e569ccb5SDavid du Colombier Super super;
1373e569ccb5SDavid du Colombier
1374e569ccb5SDavid du Colombier memset(&fsck, 0, sizeof fsck);
1375e569ccb5SDavid du Colombier fsck.fs = fsys->fs;
1376e569ccb5SDavid du Colombier fsck.clri = fsckClri;
1377e569ccb5SDavid du Colombier fsck.clre = fsckClre;
1378e569ccb5SDavid du Colombier fsck.clrp = fsckClrp;
1379e569ccb5SDavid du Colombier fsck.close = fsckClose;
1380e569ccb5SDavid du Colombier fsck.print = consPrint;
1381e569ccb5SDavid du Colombier
1382e569ccb5SDavid du Colombier ARGBEGIN{
1383e569ccb5SDavid du Colombier default:
1384e569ccb5SDavid du Colombier return cliError(usage);
1385e569ccb5SDavid du Colombier }ARGEND
1386e569ccb5SDavid du Colombier
1387e569ccb5SDavid du Colombier for(i=0; i<argc; i++){
1388e569ccb5SDavid du Colombier if(strcmp(argv[i], "pblock") == 0)
1389e569ccb5SDavid du Colombier fsck.printblocks = 1;
1390e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pdir") == 0)
1391e569ccb5SDavid du Colombier fsck.printdirs = 1;
1392e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pfile") == 0)
1393e569ccb5SDavid du Colombier fsck.printfiles = 1;
1394e569ccb5SDavid du Colombier else if(strcmp(argv[i], "bclose") == 0)
1395e569ccb5SDavid du Colombier fsck.flags |= DoClose;
1396e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clri") == 0)
1397e569ccb5SDavid du Colombier fsck.flags |= DoClri;
1398e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clre") == 0)
1399e569ccb5SDavid du Colombier fsck.flags |= DoClre;
1400e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clrp") == 0)
1401e569ccb5SDavid du Colombier fsck.flags |= DoClrp;
1402e569ccb5SDavid du Colombier else if(strcmp(argv[i], "fix") == 0)
1403e569ccb5SDavid du Colombier fsck.flags |= DoClose|DoClri|DoClre|DoClrp;
1404e569ccb5SDavid du Colombier else if(strcmp(argv[i], "venti") == 0)
1405e569ccb5SDavid du Colombier fsck.useventi = 1;
1406e569ccb5SDavid du Colombier else if(strcmp(argv[i], "snapshot") == 0)
1407e569ccb5SDavid du Colombier fsck.walksnapshots = 1;
1408e569ccb5SDavid du Colombier else{
1409e569ccb5SDavid du Colombier consPrint("unknown option '%s'\n", argv[i]);
1410e569ccb5SDavid du Colombier return cliError(usage);
1411e569ccb5SDavid du Colombier }
1412e569ccb5SDavid du Colombier }
1413e569ccb5SDavid du Colombier
1414e569ccb5SDavid du Colombier halting = fsys->fs->halted==0;
1415e569ccb5SDavid du Colombier if(halting)
1416e569ccb5SDavid du Colombier fsHalt(fsys->fs);
1417e569ccb5SDavid du Colombier if(fsys->fs->arch){
1418e569ccb5SDavid du Colombier b = superGet(fsys->fs->cache, &super);
1419e569ccb5SDavid du Colombier if(b == nil){
1420e569ccb5SDavid du Colombier consPrint("could not load super block\n");
1421e569ccb5SDavid du Colombier goto Out;
1422e569ccb5SDavid du Colombier }
1423e569ccb5SDavid du Colombier blockPut(b);
1424e569ccb5SDavid du Colombier if(super.current != NilBlock){
1425225077b0SDavid du Colombier consPrint("cannot check fs while archiver is running; "
1426225077b0SDavid du Colombier "wait for it to finish\n");
1427e569ccb5SDavid du Colombier goto Out;
1428e569ccb5SDavid du Colombier }
1429e569ccb5SDavid du Colombier }
1430e569ccb5SDavid du Colombier fsCheck(&fsck);
1431e569ccb5SDavid du Colombier consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n",
1432e569ccb5SDavid du Colombier fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose);
1433e569ccb5SDavid du Colombier Out:
1434e569ccb5SDavid du Colombier if(halting)
1435e569ccb5SDavid du Colombier fsUnhalt(fsys->fs);
1436e569ccb5SDavid du Colombier return 1;
1437e569ccb5SDavid du Colombier }
1438e569ccb5SDavid du Colombier
14395e96a66cSDavid du Colombier static int
fsysVenti(char * name,int argc,char * argv[])14405e96a66cSDavid du Colombier fsysVenti(char* name, int argc, char* argv[])
14415e96a66cSDavid du Colombier {
14425e96a66cSDavid du Colombier int r;
14435e96a66cSDavid du Colombier char *host;
14445e96a66cSDavid du Colombier char *usage = "usage: [fsys name] venti [address]";
14455e96a66cSDavid du Colombier Fsys *fsys;
14465e96a66cSDavid du Colombier
14475e96a66cSDavid du Colombier ARGBEGIN{
14485e96a66cSDavid du Colombier default:
14495e96a66cSDavid du Colombier return cliError(usage);
14505e96a66cSDavid du Colombier }ARGEND
14515e96a66cSDavid du Colombier
14525e96a66cSDavid du Colombier if(argc == 0)
14535e96a66cSDavid du Colombier host = nil;
14545e96a66cSDavid du Colombier else if(argc == 1)
14555e96a66cSDavid du Colombier host = argv[0];
14565e96a66cSDavid du Colombier else
14575e96a66cSDavid du Colombier return cliError(usage);
14585e96a66cSDavid du Colombier
14595e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil)
14605e96a66cSDavid du Colombier return 0;
14615e96a66cSDavid du Colombier
14625e96a66cSDavid du Colombier vtLock(fsys->lock);
14635e96a66cSDavid du Colombier if(host == nil)
14645e96a66cSDavid du Colombier host = fsys->venti;
14655e96a66cSDavid du Colombier else{
14665e96a66cSDavid du Colombier vtMemFree(fsys->venti);
14675e96a66cSDavid du Colombier if(host[0])
14685e96a66cSDavid du Colombier fsys->venti = vtStrDup(host);
14695e96a66cSDavid du Colombier else{
14705e96a66cSDavid du Colombier host = nil;
14715e96a66cSDavid du Colombier fsys->venti = nil;
14725e96a66cSDavid du Colombier }
14735e96a66cSDavid du Colombier }
14745e96a66cSDavid du Colombier
14755e96a66cSDavid du Colombier /* already open: do a redial */
14765e96a66cSDavid du Colombier if(fsys->fs != nil){
14776042bf6dSDavid du Colombier if(fsys->session == nil){
14786042bf6dSDavid du Colombier vtSetError("file system was opened with -V");
14796042bf6dSDavid du Colombier r = 0;
14806042bf6dSDavid du Colombier goto out;
14816042bf6dSDavid du Colombier }
14825e96a66cSDavid du Colombier r = 1;
1483ea58ad6fSDavid du Colombier if(!myRedial(fsys->session, host)
14845e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0))
14855e96a66cSDavid du Colombier r = 0;
14866042bf6dSDavid du Colombier goto out;
14875e96a66cSDavid du Colombier }
14885e96a66cSDavid du Colombier
14895e96a66cSDavid du Colombier /* not yet open: try to dial */
14905e96a66cSDavid du Colombier if(fsys->session)
14915e96a66cSDavid du Colombier vtClose(fsys->session);
14925e96a66cSDavid du Colombier r = 1;
1493ea58ad6fSDavid du Colombier if((fsys->session = myDial(host, 0)) == nil
14945e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0))
14955e96a66cSDavid du Colombier r = 0;
14966042bf6dSDavid du Colombier out:
14975e96a66cSDavid du Colombier vtUnlock(fsys->lock);
14985e96a66cSDavid du Colombier fsysPut(fsys);
14995e96a66cSDavid du Colombier return r;
15005e96a66cSDavid du Colombier }
15015e96a66cSDavid du Colombier
1502b8a11165SDavid du Colombier static ulong
freemem(void)1503b8a11165SDavid du Colombier freemem(void)
1504b8a11165SDavid du Colombier {
1505b8a11165SDavid du Colombier int nf, pgsize = 0;
1506b8a11165SDavid du Colombier uvlong size, userpgs = 0, userused = 0;
1507b8a11165SDavid du Colombier char *ln, *sl;
1508b8a11165SDavid du Colombier char *fields[2];
1509b8a11165SDavid du Colombier Biobuf *bp;
1510b8a11165SDavid du Colombier
1511b8a11165SDavid du Colombier size = 64*1024*1024;
1512b8a11165SDavid du Colombier bp = Bopen("#c/swap", OREAD);
1513b8a11165SDavid du Colombier if (bp != nil) {
1514b8a11165SDavid du Colombier while ((ln = Brdline(bp, '\n')) != nil) {
1515b8a11165SDavid du Colombier ln[Blinelen(bp)-1] = '\0';
1516b8a11165SDavid du Colombier nf = tokenize(ln, fields, nelem(fields));
1517b8a11165SDavid du Colombier if (nf != 2)
1518b8a11165SDavid du Colombier continue;
1519b8a11165SDavid du Colombier if (strcmp(fields[1], "pagesize") == 0)
1520b8a11165SDavid du Colombier pgsize = atoi(fields[0]);
1521b8a11165SDavid du Colombier else if (strcmp(fields[1], "user") == 0) {
1522b8a11165SDavid du Colombier sl = strchr(fields[0], '/');
1523b8a11165SDavid du Colombier if (sl == nil)
1524b8a11165SDavid du Colombier continue;
1525b8a11165SDavid du Colombier userpgs = atoll(sl+1);
1526b8a11165SDavid du Colombier userused = atoll(fields[0]);
1527b8a11165SDavid du Colombier }
1528b8a11165SDavid du Colombier }
1529b8a11165SDavid du Colombier Bterm(bp);
1530b8a11165SDavid du Colombier if (pgsize > 0 && userpgs > 0)
1531b8a11165SDavid du Colombier size = (userpgs - userused) * pgsize;
1532b8a11165SDavid du Colombier }
1533b8a11165SDavid du Colombier /* cap it to keep the size within 32 bits */
1534b8a11165SDavid du Colombier if (size >= 3840UL * 1024 * 1024)
1535b8a11165SDavid du Colombier size = 3840UL * 1024 * 1024;
1536b8a11165SDavid du Colombier return size;
1537b8a11165SDavid du Colombier }
1538b8a11165SDavid du Colombier
15395e96a66cSDavid du Colombier static int
fsysOpen(char * name,int argc,char * argv[])15405e96a66cSDavid du Colombier fsysOpen(char* name, int argc, char* argv[])
15415e96a66cSDavid du Colombier {
15425e96a66cSDavid du Colombier char *p, *host;
15435e96a66cSDavid du Colombier Fsys *fsys;
1544f4051287SDavid du Colombier int noauth, noventi, noperm, rflag, wstatallow, noatimeupd;
1545b8a11165SDavid du Colombier long ncache;
15466042bf6dSDavid du Colombier char *usage = "usage: fsys name open [-APVWr] [-c ncache]";
15475e96a66cSDavid du Colombier
15485e96a66cSDavid du Colombier ncache = 1000;
1549f4051287SDavid du Colombier noauth = noperm = wstatallow = noventi = noatimeupd = 0;
15505e96a66cSDavid du Colombier rflag = OReadWrite;
15515e96a66cSDavid du Colombier
15525e96a66cSDavid du Colombier ARGBEGIN{
15535e96a66cSDavid du Colombier default:
15545e96a66cSDavid du Colombier return cliError(usage);
15555e96a66cSDavid du Colombier case 'A':
15565e96a66cSDavid du Colombier noauth = 1;
15575e96a66cSDavid du Colombier break;
15585e96a66cSDavid du Colombier case 'P':
15595e96a66cSDavid du Colombier noperm = 1;
15605e96a66cSDavid du Colombier break;
15616042bf6dSDavid du Colombier case 'V':
15626042bf6dSDavid du Colombier noventi = 1;
15636042bf6dSDavid du Colombier break;
15645e96a66cSDavid du Colombier case 'W':
15655e96a66cSDavid du Colombier wstatallow = 1;
15665e96a66cSDavid du Colombier break;
1567f4051287SDavid du Colombier case 'a':
1568f4051287SDavid du Colombier noatimeupd = 1;
1569f4051287SDavid du Colombier break;
15705e96a66cSDavid du Colombier case 'c':
15715e96a66cSDavid du Colombier p = ARGF();
15725e96a66cSDavid du Colombier if(p == nil)
15735e96a66cSDavid du Colombier return cliError(usage);
15745e96a66cSDavid du Colombier ncache = strtol(argv[0], &p, 0);
15755e96a66cSDavid du Colombier if(ncache <= 0 || p == argv[0] || *p != '\0')
15765e96a66cSDavid du Colombier return cliError(usage);
15775e96a66cSDavid du Colombier break;
15785e96a66cSDavid du Colombier case 'r':
15795e96a66cSDavid du Colombier rflag = OReadOnly;
15805e96a66cSDavid du Colombier break;
15815e96a66cSDavid du Colombier }ARGEND
15825e96a66cSDavid du Colombier if(argc)
15835e96a66cSDavid du Colombier return cliError(usage);
15845e96a66cSDavid du Colombier
15855e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil)
15865e96a66cSDavid du Colombier return 0;
15875e96a66cSDavid du Colombier
1588b8a11165SDavid du Colombier /* automatic memory sizing? */
1589b8a11165SDavid du Colombier if(mempcnt > 0) {
1590b8a11165SDavid du Colombier /* TODO: 8K is a hack; use the actual block size */
1591b8a11165SDavid du Colombier ncache = (((vlong)freemem() * mempcnt) / 100) / (8*1024);
1592b8a11165SDavid du Colombier if (ncache < 100)
1593b8a11165SDavid du Colombier ncache = 100;
1594b8a11165SDavid du Colombier }
1595b8a11165SDavid du Colombier
15965e96a66cSDavid du Colombier vtLock(fsys->lock);
15975e96a66cSDavid du Colombier if(fsys->fs != nil){
15985e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name);
15995e96a66cSDavid du Colombier vtUnlock(fsys->lock);
16005e96a66cSDavid du Colombier fsysPut(fsys);
16015e96a66cSDavid du Colombier return 0;
16025e96a66cSDavid du Colombier }
16035e96a66cSDavid du Colombier
16047611b47fSDavid du Colombier if(noventi){
16057611b47fSDavid du Colombier if(fsys->session){
16067611b47fSDavid du Colombier vtClose(fsys->session);
16077611b47fSDavid du Colombier fsys->session = nil;
16087611b47fSDavid du Colombier }
16097611b47fSDavid du Colombier }
16107611b47fSDavid du Colombier else if(fsys->session == nil){
16115e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0])
16125e96a66cSDavid du Colombier host = fsys->venti;
16135e96a66cSDavid du Colombier else
16145e96a66cSDavid du Colombier host = nil;
1615ea58ad6fSDavid du Colombier fsys->session = myDial(host, 1);
16166042bf6dSDavid du Colombier if(!vtConnect(fsys->session, nil) && !noventi)
161761201b97SDavid 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){
1620dc5a79c1SDavid du Colombier vtSetError("fsOpen: %R");
16215e96a66cSDavid du Colombier vtUnlock(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;
16305e96a66cSDavid du Colombier vtUnlock(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
16525e96a66cSDavid du Colombier vtLock(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){
16605e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name);
16615e96a66cSDavid du Colombier vtUnlock(sbox.lock);
16625e96a66cSDavid du Colombier return 0;
16635e96a66cSDavid du Colombier }
16645e96a66cSDavid du Colombier if(fsys->ref != 0 || fsys->fs != nil){
16655e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name);
16665e96a66cSDavid du Colombier vtUnlock(sbox.lock);
16675e96a66cSDavid du Colombier return 0;
16685e96a66cSDavid du Colombier }
16695e96a66cSDavid du Colombier *fp = fsys->next;
16705e96a66cSDavid du Colombier vtUnlock(sbox.lock);
16715e96a66cSDavid du Colombier
16725e96a66cSDavid du Colombier if(fsys->session != nil){
16735e96a66cSDavid du Colombier vtClose(fsys->session);
16745e96a66cSDavid du Colombier vtFree(fsys->session);
16755e96a66cSDavid du Colombier }
16765e96a66cSDavid du Colombier if(fsys->venti != nil)
16775e96a66cSDavid du Colombier vtMemFree(fsys->venti);
16785e96a66cSDavid du Colombier if(fsys->dev != nil)
16795e96a66cSDavid du Colombier vtMemFree(fsys->dev);
16805e96a66cSDavid du Colombier if(fsys->name != nil)
16815e96a66cSDavid du Colombier vtMemFree(fsys->name);
16825e96a66cSDavid du Colombier vtMemFree(fsys);
16835e96a66cSDavid du Colombier
16845e96a66cSDavid du Colombier return 1;
16855e96a66cSDavid du Colombier }
16865e96a66cSDavid du Colombier
16875e96a66cSDavid du Colombier static int
fsysConfig(char * name,int argc,char * argv[])16885e96a66cSDavid du Colombier fsysConfig(char* name, int argc, char* argv[])
16895e96a66cSDavid du Colombier {
16905e96a66cSDavid du Colombier Fsys *fsys;
16911bdadbfaSDavid du Colombier char *part;
16921bdadbfaSDavid du Colombier char *usage = "usage: fsys name config [dev]";
16935e96a66cSDavid du Colombier
16945e96a66cSDavid du Colombier ARGBEGIN{
16955e96a66cSDavid du Colombier default:
16965e96a66cSDavid du Colombier return cliError(usage);
16975e96a66cSDavid du Colombier }ARGEND
16981bdadbfaSDavid du Colombier if(argc > 1)
16995e96a66cSDavid du Colombier return cliError(usage);
17005e96a66cSDavid du Colombier
17011bdadbfaSDavid du Colombier if(argc == 0)
17021bdadbfaSDavid du Colombier part = foptname;
17031bdadbfaSDavid du Colombier else
17041bdadbfaSDavid du Colombier part = argv[0];
17051bdadbfaSDavid du Colombier
17061bdadbfaSDavid du Colombier if((fsys = _fsysGet(part)) != nil){
17075e96a66cSDavid du Colombier vtLock(fsys->lock);
17085e96a66cSDavid du Colombier if(fsys->fs != nil){
17095e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name);
17105e96a66cSDavid du Colombier vtUnlock(fsys->lock);
17115e96a66cSDavid du Colombier fsysPut(fsys);
17125e96a66cSDavid du Colombier return 0;
17135e96a66cSDavid du Colombier }
17145e96a66cSDavid du Colombier vtMemFree(fsys->dev);
17151bdadbfaSDavid du Colombier fsys->dev = vtStrDup(part);
17165e96a66cSDavid du Colombier vtUnlock(fsys->lock);
17175e96a66cSDavid du Colombier }
17181bdadbfaSDavid du Colombier else if((fsys = fsysAlloc(name, part)) == nil)
17195e96a66cSDavid du Colombier return 0;
17205e96a66cSDavid du Colombier
17215e96a66cSDavid du Colombier fsysPut(fsys);
17225e96a66cSDavid du Colombier return 1;
17235e96a66cSDavid du Colombier }
17245e96a66cSDavid du Colombier
17255e96a66cSDavid du Colombier static struct {
17265e96a66cSDavid du Colombier char* cmd;
17275e96a66cSDavid du Colombier int (*f)(Fsys*, int, char**);
17285e96a66cSDavid du Colombier int (*f1)(char*, int, char**);
17295e96a66cSDavid du Colombier } fsyscmd[] = {
17305e96a66cSDavid du Colombier { "close", fsysClose, },
17315e96a66cSDavid du Colombier { "config", nil, fsysConfig, },
17325e96a66cSDavid du Colombier { "open", nil, fsysOpen, },
17335e96a66cSDavid du Colombier { "unconfig", nil, fsysUnconfig, },
17345e96a66cSDavid du Colombier { "venti", nil, fsysVenti, },
17355e96a66cSDavid du Colombier
17365e96a66cSDavid du Colombier { "bfree", fsysBfree, },
17375e96a66cSDavid du Colombier { "block", fsysBlock, },
1738e569ccb5SDavid du Colombier { "check", fsysCheck, },
17395e96a66cSDavid du Colombier { "clre", fsysClre, },
17405e96a66cSDavid du Colombier { "clri", fsysClri, },
17415e96a66cSDavid du Colombier { "clrp", fsysClrp, },
17425e96a66cSDavid du Colombier { "create", fsysCreate, },
17437abd426fSDavid du Colombier { "df", fsysDf, },
17445e96a66cSDavid du Colombier { "epoch", fsysEpoch, },
174581cf8742SDavid du Colombier { "halt", fsysHalt, },
17465e96a66cSDavid du Colombier { "label", fsysLabel, },
17475e96a66cSDavid du Colombier { "remove", fsysRemove, },
17485e96a66cSDavid du Colombier { "snap", fsysSnap, },
17495e96a66cSDavid du Colombier { "snaptime", fsysSnapTime, },
1750dc5a79c1SDavid du Colombier { "snapclean", fsysSnapClean, },
17515e96a66cSDavid du Colombier { "stat", fsysStat, },
17525e96a66cSDavid du Colombier { "sync", fsysSync, },
175381cf8742SDavid du Colombier { "unhalt", fsysUnhalt, },
17545e96a66cSDavid du Colombier { "wstat", fsysWstat, },
17555e96a66cSDavid du Colombier { "vac", fsysVac, },
17565e96a66cSDavid du Colombier
17575e96a66cSDavid du Colombier { nil, nil, },
17585e96a66cSDavid du Colombier };
17595e96a66cSDavid du Colombier
17605e96a66cSDavid du Colombier static int
fsysXXX1(Fsys * fsys,int i,int argc,char * argv[])176181cf8742SDavid du Colombier fsysXXX1(Fsys *fsys, int i, int argc, char* argv[])
176281cf8742SDavid du Colombier {
176381cf8742SDavid du Colombier int r;
176481cf8742SDavid du Colombier
176581cf8742SDavid du Colombier vtLock(fsys->lock);
176681cf8742SDavid du Colombier if(fsys->fs == nil){
176781cf8742SDavid du Colombier vtUnlock(fsys->lock);
176881cf8742SDavid du Colombier vtSetError(EFsysNotOpen, fsys->name);
176981cf8742SDavid du Colombier return 0;
177081cf8742SDavid du Colombier }
177181cf8742SDavid du Colombier
1772e569ccb5SDavid du Colombier if(fsys->fs->halted
1773e569ccb5SDavid du Colombier && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){
177481cf8742SDavid du Colombier vtSetError("file system %s is halted", fsys->name);
177581cf8742SDavid du Colombier vtUnlock(fsys->lock);
177681cf8742SDavid du Colombier return 0;
177781cf8742SDavid du Colombier }
177881cf8742SDavid du Colombier
177981cf8742SDavid du Colombier r = (*fsyscmd[i].f)(fsys, argc, argv);
178081cf8742SDavid du Colombier vtUnlock(fsys->lock);
178181cf8742SDavid du Colombier return r;
178281cf8742SDavid du Colombier }
178381cf8742SDavid du Colombier
178481cf8742SDavid du Colombier static int
fsysXXX(char * name,int argc,char * argv[])17855e96a66cSDavid du Colombier fsysXXX(char* name, int argc, char* argv[])
17865e96a66cSDavid du Colombier {
17875e96a66cSDavid du Colombier int i, r;
17885e96a66cSDavid du Colombier Fsys *fsys;
17895e96a66cSDavid du Colombier
17905e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){
17915e96a66cSDavid du Colombier if(strcmp(fsyscmd[i].cmd, argv[0]) == 0)
17925e96a66cSDavid du Colombier break;
17935e96a66cSDavid du Colombier }
17945e96a66cSDavid du Colombier
17955e96a66cSDavid du Colombier if(fsyscmd[i].cmd == nil){
17965e96a66cSDavid du Colombier vtSetError("unknown command - '%s'", argv[0]);
17975e96a66cSDavid du Colombier return 0;
17985e96a66cSDavid du Colombier }
17995e96a66cSDavid du Colombier
18005e96a66cSDavid du Colombier /* some commands want the name... */
180181cf8742SDavid du Colombier if(fsyscmd[i].f1 != nil){
180281cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){
180381cf8742SDavid du Colombier vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]);
18045e96a66cSDavid du Colombier return 0;
18055e96a66cSDavid du Colombier }
180681cf8742SDavid du Colombier return (*fsyscmd[i].f1)(name, argc, argv);
180781cf8742SDavid du Colombier }
18085e96a66cSDavid du Colombier
180981cf8742SDavid du Colombier /* ... but most commands want the Fsys */
181081cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){
181181cf8742SDavid du Colombier r = 1;
181281cf8742SDavid du Colombier vtRLock(sbox.lock);
181381cf8742SDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
181481cf8742SDavid du Colombier fsys->ref++;
181581cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv) && r;
181681cf8742SDavid du Colombier fsys->ref--;
181781cf8742SDavid du Colombier }
181881cf8742SDavid du Colombier vtRUnlock(sbox.lock);
181981cf8742SDavid du Colombier }else{
182081cf8742SDavid du Colombier if((fsys = _fsysGet(name)) == nil)
182181cf8742SDavid du Colombier return 0;
182281cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv);
18235e96a66cSDavid du Colombier fsysPut(fsys);
182481cf8742SDavid du Colombier }
18255e96a66cSDavid du Colombier return r;
18265e96a66cSDavid du Colombier }
18275e96a66cSDavid du Colombier
18285e96a66cSDavid du Colombier static int
cmdFsysXXX(int argc,char * argv[])18295e96a66cSDavid du Colombier cmdFsysXXX(int argc, char* argv[])
18305e96a66cSDavid du Colombier {
18315e96a66cSDavid du Colombier char *name;
18325e96a66cSDavid du Colombier
18335e96a66cSDavid du Colombier if((name = sbox.curfsys) == nil){
18345e96a66cSDavid du Colombier vtSetError(EFsysNoCurrent, argv[0]);
18355e96a66cSDavid du Colombier return 0;
18365e96a66cSDavid du Colombier }
18375e96a66cSDavid du Colombier
18385e96a66cSDavid du Colombier return fsysXXX(name, argc, argv);
18395e96a66cSDavid du Colombier }
18405e96a66cSDavid du Colombier
18415e96a66cSDavid du Colombier static int
cmdFsys(int argc,char * argv[])18425e96a66cSDavid du Colombier cmdFsys(int argc, char* argv[])
18435e96a66cSDavid du Colombier {
18445e96a66cSDavid du Colombier Fsys *fsys;
18455e96a66cSDavid du Colombier char *usage = "usage: fsys [name ...]";
18465e96a66cSDavid du Colombier
18475e96a66cSDavid du Colombier ARGBEGIN{
18485e96a66cSDavid du Colombier default:
18495e96a66cSDavid du Colombier return cliError(usage);
18505e96a66cSDavid du Colombier }ARGEND
18515e96a66cSDavid du Colombier
18525e96a66cSDavid du Colombier if(argc == 0){
18535e96a66cSDavid du Colombier vtRLock(sbox.lock);
1854b8a11165SDavid du Colombier currfsysname = sbox.head->name;
18555e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next)
18565e96a66cSDavid du Colombier consPrint("\t%s\n", fsys->name);
18575e96a66cSDavid du Colombier vtRUnlock(sbox.lock);
18585e96a66cSDavid du Colombier return 1;
18595e96a66cSDavid du Colombier }
18605e96a66cSDavid du Colombier if(argc == 1){
186181cf8742SDavid du Colombier fsys = nil;
186281cf8742SDavid du Colombier if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil)
18635e96a66cSDavid du Colombier return 0;
186481cf8742SDavid du Colombier sbox.curfsys = vtStrDup(argv[0]);
18655e96a66cSDavid du Colombier consPrompt(sbox.curfsys);
186681cf8742SDavid du Colombier if(fsys)
18675e96a66cSDavid du Colombier fsysPut(fsys);
18685e96a66cSDavid du Colombier return 1;
18695e96a66cSDavid du Colombier }
18705e96a66cSDavid du Colombier
18715e96a66cSDavid du Colombier return fsysXXX(argv[0], argc-1, argv+1);
18725e96a66cSDavid du Colombier }
18735e96a66cSDavid du Colombier
18745e96a66cSDavid du Colombier int
fsysInit(void)18755e96a66cSDavid du Colombier fsysInit(void)
18765e96a66cSDavid du Colombier {
18775e96a66cSDavid du Colombier int i;
18785e96a66cSDavid du Colombier
18795e96a66cSDavid du Colombier fmtinstall('H', encodefmt);
18805e96a66cSDavid du Colombier fmtinstall('V', scoreFmt);
18815e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt);
18825e96a66cSDavid du Colombier fmtinstall('L', labelFmt);
18835e96a66cSDavid du Colombier
18845e96a66cSDavid du Colombier sbox.lock = vtLockAlloc();
18855e96a66cSDavid du Colombier
18865e96a66cSDavid du Colombier cliAddCmd("fsys", cmdFsys);
18875e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){
18885e96a66cSDavid du Colombier if(fsyscmd[i].f != nil)
18895e96a66cSDavid du Colombier cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX);
18905e96a66cSDavid du Colombier }
18915e96a66cSDavid du Colombier /* the venti cmd is special: the fs can be either open or closed */
18925e96a66cSDavid du Colombier cliAddCmd("venti", cmdFsysXXX);
18935e96a66cSDavid du Colombier cliAddCmd("printconfig", cmdPrintConfig);
18945e96a66cSDavid du Colombier
18955e96a66cSDavid du Colombier return 1;
18965e96a66cSDavid du Colombier }
1897