15e96a66cSDavid du Colombier #include "stdinc.h" 25e96a66cSDavid du Colombier #include "dat.h" 35e96a66cSDavid du Colombier #include "fns.h" 45e96a66cSDavid du Colombier 55e96a66cSDavid du Colombier #include "9.h" 65e96a66cSDavid du Colombier 75e96a66cSDavid du Colombier typedef struct Fsys Fsys; 85e96a66cSDavid du Colombier 97abd426fSDavid du Colombier struct Fsys { 105e96a66cSDavid du Colombier VtLock* lock; 115e96a66cSDavid du Colombier 125e96a66cSDavid du Colombier char* name; 135e96a66cSDavid du Colombier char* dev; 145e96a66cSDavid du Colombier char* venti; 155e96a66cSDavid du Colombier 165e96a66cSDavid du Colombier Fs* fs; 175e96a66cSDavid du Colombier VtSession* session; 185e96a66cSDavid du Colombier int ref; 195e96a66cSDavid du Colombier 205e96a66cSDavid du Colombier int noauth; 215e96a66cSDavid du Colombier int noperm; 225e96a66cSDavid du Colombier int wstatallow; 235e96a66cSDavid du Colombier 245e96a66cSDavid du Colombier Fsys* next; 257abd426fSDavid du Colombier }; 265e96a66cSDavid du Colombier 275e96a66cSDavid du Colombier static struct { 285e96a66cSDavid du Colombier VtLock* lock; 295e96a66cSDavid du Colombier Fsys* head; 305e96a66cSDavid du Colombier Fsys* tail; 315e96a66cSDavid du Colombier 325e96a66cSDavid du Colombier char* curfsys; 335e96a66cSDavid du Colombier } sbox; 345e96a66cSDavid du Colombier 355e96a66cSDavid du Colombier static char *_argv0; 365e96a66cSDavid du Colombier #define argv0 _argv0 375e96a66cSDavid du Colombier 38*81cf8742SDavid du Colombier static char FsysAll[] = "all"; 39*81cf8742SDavid du Colombier 405e96a66cSDavid du Colombier static char EFsysBusy[] = "fsys: '%s' busy"; 415e96a66cSDavid du Colombier static char EFsysExists[] = "fsys: '%s' already exists"; 425e96a66cSDavid du Colombier static char EFsysNoCurrent[] = "fsys: no current fsys"; 435e96a66cSDavid du Colombier static char EFsysNotFound[] = "fsys: '%s' not found"; 445e96a66cSDavid du Colombier static char EFsysNotOpen[] = "fsys: '%s' not open"; 455e96a66cSDavid du Colombier 465e96a66cSDavid du Colombier static Fsys* 475e96a66cSDavid du Colombier _fsysGet(char* name) 485e96a66cSDavid du Colombier { 495e96a66cSDavid du Colombier Fsys *fsys; 505e96a66cSDavid du Colombier 515e96a66cSDavid du Colombier if(name == nil || name[0] == '\0') 525e96a66cSDavid du Colombier name = "main"; 535e96a66cSDavid du Colombier 545e96a66cSDavid du Colombier vtRLock(sbox.lock); 555e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 565e96a66cSDavid du Colombier if(strcmp(name, fsys->name) == 0){ 575e96a66cSDavid du Colombier fsys->ref++; 585e96a66cSDavid du Colombier break; 595e96a66cSDavid du Colombier } 605e96a66cSDavid du Colombier } 615e96a66cSDavid du Colombier if(fsys == nil) 625e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 635e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 645e96a66cSDavid du Colombier 655e96a66cSDavid du Colombier return fsys; 665e96a66cSDavid du Colombier } 675e96a66cSDavid du Colombier 685e96a66cSDavid du Colombier static int 695e96a66cSDavid du Colombier cmdPrintConfig(int argc, char* argv[]) 705e96a66cSDavid du Colombier { 715e96a66cSDavid du Colombier Fsys *fsys; 725e96a66cSDavid du Colombier char *usage = "usage: printconfig"; 735e96a66cSDavid du Colombier 745e96a66cSDavid du Colombier ARGBEGIN{ 755e96a66cSDavid du Colombier default: 765e96a66cSDavid du Colombier return cliError(usage); 775e96a66cSDavid du Colombier }ARGEND 785e96a66cSDavid du Colombier 795e96a66cSDavid du Colombier if(argc) 805e96a66cSDavid du Colombier return cliError(usage); 815e96a66cSDavid du Colombier 825e96a66cSDavid du Colombier vtRLock(sbox.lock); 835e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 845e96a66cSDavid du Colombier consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev); 855e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 865e96a66cSDavid du Colombier consPrint("\tfsys %s venti %q\n", fsys->name, fsys->venti); 875e96a66cSDavid du Colombier } 885e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 895e96a66cSDavid du Colombier return 1; 905e96a66cSDavid du Colombier } 915e96a66cSDavid du Colombier 925e96a66cSDavid du Colombier Fsys* 935e96a66cSDavid du Colombier fsysGet(char* name) 945e96a66cSDavid du Colombier { 955e96a66cSDavid du Colombier Fsys *fsys; 965e96a66cSDavid du Colombier 975e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 985e96a66cSDavid du Colombier return nil; 995e96a66cSDavid du Colombier 1005e96a66cSDavid du Colombier vtLock(fsys->lock); 1015e96a66cSDavid du Colombier if(fsys->fs == nil){ 1025e96a66cSDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 1035e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1045e96a66cSDavid du Colombier fsysPut(fsys); 1055e96a66cSDavid du Colombier return nil; 1065e96a66cSDavid du Colombier } 1075e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1085e96a66cSDavid du Colombier 1095e96a66cSDavid du Colombier return fsys; 1105e96a66cSDavid du Colombier } 1115e96a66cSDavid du Colombier 11261201b97SDavid du Colombier char* 11361201b97SDavid du Colombier fsysGetName(Fsys* fsys) 11461201b97SDavid du Colombier { 11561201b97SDavid du Colombier return fsys->name; 11661201b97SDavid du Colombier } 11761201b97SDavid du Colombier 1185e96a66cSDavid du Colombier Fsys* 1195e96a66cSDavid du Colombier fsysIncRef(Fsys* fsys) 1205e96a66cSDavid du Colombier { 1215e96a66cSDavid du Colombier vtLock(sbox.lock); 1225e96a66cSDavid du Colombier fsys->ref++; 1235e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1245e96a66cSDavid du Colombier 1255e96a66cSDavid du Colombier return fsys; 1265e96a66cSDavid du Colombier } 1275e96a66cSDavid du Colombier 1285e96a66cSDavid du Colombier void 1295e96a66cSDavid du Colombier fsysPut(Fsys* fsys) 1305e96a66cSDavid du Colombier { 1315e96a66cSDavid du Colombier vtLock(sbox.lock); 1325e96a66cSDavid du Colombier assert(fsys->ref > 0); 1335e96a66cSDavid du Colombier fsys->ref--; 1345e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1355e96a66cSDavid du Colombier } 1365e96a66cSDavid du Colombier 1375e96a66cSDavid du Colombier Fs* 1385e96a66cSDavid du Colombier fsysGetFs(Fsys* fsys) 1395e96a66cSDavid du Colombier { 1405e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 1415e96a66cSDavid du Colombier 1425e96a66cSDavid du Colombier return fsys->fs; 1435e96a66cSDavid du Colombier } 1445e96a66cSDavid du Colombier 1455e96a66cSDavid du Colombier void 1465e96a66cSDavid du Colombier fsysFsRlock(Fsys* fsys) 1475e96a66cSDavid du Colombier { 1485e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 1495e96a66cSDavid du Colombier } 1505e96a66cSDavid du Colombier 1515e96a66cSDavid du Colombier void 1525e96a66cSDavid du Colombier fsysFsRUnlock(Fsys* fsys) 1535e96a66cSDavid du Colombier { 1545e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 1555e96a66cSDavid du Colombier } 1565e96a66cSDavid du Colombier 1575e96a66cSDavid du Colombier int 1585e96a66cSDavid du Colombier fsysNoAuthCheck(Fsys* fsys) 1595e96a66cSDavid du Colombier { 1605e96a66cSDavid du Colombier return fsys->noauth; 1615e96a66cSDavid du Colombier } 1625e96a66cSDavid du Colombier 1635e96a66cSDavid du Colombier int 1645e96a66cSDavid du Colombier fsysNoPermCheck(Fsys* fsys) 1655e96a66cSDavid du Colombier { 1665e96a66cSDavid du Colombier return fsys->noperm; 1675e96a66cSDavid du Colombier } 1685e96a66cSDavid du Colombier 1695e96a66cSDavid du Colombier int 1705e96a66cSDavid du Colombier fsysWstatAllow(Fsys* fsys) 1715e96a66cSDavid du Colombier { 1725e96a66cSDavid du Colombier return fsys->wstatallow; 1735e96a66cSDavid du Colombier } 1745e96a66cSDavid du Colombier 1755e96a66cSDavid du Colombier static char modechars[] = "YUGalLdHSATs"; 1765e96a66cSDavid du Colombier static ulong modebits[] = { 1775e96a66cSDavid du Colombier ModeSticky, 1785e96a66cSDavid du Colombier ModeSetUid, 1795e96a66cSDavid du Colombier ModeSetGid, 1805e96a66cSDavid du Colombier ModeAppend, 1815e96a66cSDavid du Colombier ModeExclusive, 1825e96a66cSDavid du Colombier ModeLink, 1835e96a66cSDavid du Colombier ModeDir, 1845e96a66cSDavid du Colombier ModeHidden, 1855e96a66cSDavid du Colombier ModeSystem, 1865e96a66cSDavid du Colombier ModeArchive, 1875e96a66cSDavid du Colombier ModeTemporary, 1885e96a66cSDavid du Colombier ModeSnapshot, 1895e96a66cSDavid du Colombier 0 1905e96a66cSDavid du Colombier }; 1915e96a66cSDavid du Colombier 1925e96a66cSDavid du Colombier char* 1935e96a66cSDavid du Colombier fsysModeString(ulong mode, char *buf) 1945e96a66cSDavid du Colombier { 1955e96a66cSDavid du Colombier int i; 1965e96a66cSDavid du Colombier char *p; 1975e96a66cSDavid du Colombier 1985e96a66cSDavid du Colombier p = buf; 1995e96a66cSDavid du Colombier for(i=0; modebits[i]; i++) 2005e96a66cSDavid du Colombier if(mode & modebits[i]) 2015e96a66cSDavid du Colombier *p++ = modechars[i]; 2025e96a66cSDavid du Colombier sprint(p, "%luo", mode&0777); 2035e96a66cSDavid du Colombier return buf; 2045e96a66cSDavid du Colombier } 2055e96a66cSDavid du Colombier 2065e96a66cSDavid du Colombier int 2075e96a66cSDavid du Colombier fsysParseMode(char* s, ulong* mode) 2085e96a66cSDavid du Colombier { 2095e96a66cSDavid du Colombier ulong x, y; 2105e96a66cSDavid du Colombier char *p; 2115e96a66cSDavid du Colombier 2125e96a66cSDavid du Colombier x = 0; 2135e96a66cSDavid du Colombier for(; *s < '0' || *s > '9'; s++){ 2145e96a66cSDavid du Colombier if(*s == 0) 2155e96a66cSDavid du Colombier return 0; 2165e96a66cSDavid du Colombier p = strchr(modechars, *s); 2175e96a66cSDavid du Colombier if(p == nil) 2185e96a66cSDavid du Colombier return 0; 2195e96a66cSDavid du Colombier x |= modebits[p-modechars]; 2205e96a66cSDavid du Colombier } 2215e96a66cSDavid du Colombier y = strtoul(s, &p, 8); 2225e96a66cSDavid du Colombier if(*p != '\0' || y > 0777) 2235e96a66cSDavid du Colombier return 0; 2245e96a66cSDavid du Colombier *mode = x|y; 2255e96a66cSDavid du Colombier return 1; 2265e96a66cSDavid du Colombier } 2275e96a66cSDavid du Colombier 2285e96a66cSDavid du Colombier File* 2295e96a66cSDavid du Colombier fsysGetRoot(Fsys* fsys, char* name) 2305e96a66cSDavid du Colombier { 2315e96a66cSDavid du Colombier File *root, *sub; 2325e96a66cSDavid du Colombier 2335e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 2345e96a66cSDavid du Colombier 2355e96a66cSDavid du Colombier root = fsGetRoot(fsys->fs); 2365e96a66cSDavid du Colombier if(name == nil || strcmp(name, "") == 0) 2375e96a66cSDavid du Colombier return root; 2385e96a66cSDavid du Colombier 2395e96a66cSDavid du Colombier sub = fileWalk(root, name); 2405e96a66cSDavid du Colombier fileDecRef(root); 2415e96a66cSDavid du Colombier 2425e96a66cSDavid du Colombier return sub; 2435e96a66cSDavid du Colombier } 2445e96a66cSDavid du Colombier 2455e96a66cSDavid du Colombier static Fsys* 2465e96a66cSDavid du Colombier fsysAlloc(char* name, char* dev) 2475e96a66cSDavid du Colombier { 2485e96a66cSDavid du Colombier Fsys *fsys; 2495e96a66cSDavid du Colombier 2505e96a66cSDavid du Colombier vtLock(sbox.lock); 2515e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 2525e96a66cSDavid du Colombier if(strcmp(fsys->name, name) != 0) 2535e96a66cSDavid du Colombier continue; 2545e96a66cSDavid du Colombier vtSetError(EFsysExists, name); 2555e96a66cSDavid du Colombier vtUnlock(sbox.lock); 2565e96a66cSDavid du Colombier return nil; 2575e96a66cSDavid du Colombier } 2585e96a66cSDavid du Colombier 2595e96a66cSDavid du Colombier fsys = vtMemAllocZ(sizeof(Fsys)); 2605e96a66cSDavid du Colombier fsys->lock = vtLockAlloc(); 2615e96a66cSDavid du Colombier fsys->name = vtStrDup(name); 2625e96a66cSDavid du Colombier fsys->dev = vtStrDup(dev); 2635e96a66cSDavid du Colombier 2645e96a66cSDavid du Colombier fsys->ref = 1; 2655e96a66cSDavid du Colombier 2665e96a66cSDavid du Colombier if(sbox.tail != nil) 2675e96a66cSDavid du Colombier sbox.tail->next = fsys; 2685e96a66cSDavid du Colombier else 2695e96a66cSDavid du Colombier sbox.head = fsys; 2705e96a66cSDavid du Colombier sbox.tail = fsys; 2715e96a66cSDavid du Colombier vtUnlock(sbox.lock); 2725e96a66cSDavid du Colombier 2735e96a66cSDavid du Colombier return fsys; 2745e96a66cSDavid du Colombier } 2755e96a66cSDavid du Colombier 2765e96a66cSDavid du Colombier static int 2775e96a66cSDavid du Colombier fsysClose(Fsys* fsys, int argc, char* argv[]) 2785e96a66cSDavid du Colombier { 2795e96a66cSDavid du Colombier char *usage = "usage: [fsys name] close"; 2805e96a66cSDavid du Colombier 2815e96a66cSDavid du Colombier ARGBEGIN{ 2825e96a66cSDavid du Colombier default: 2835e96a66cSDavid du Colombier return cliError(usage); 2845e96a66cSDavid du Colombier }ARGEND 2855e96a66cSDavid du Colombier if(argc) 2865e96a66cSDavid du Colombier return cliError(usage); 2875e96a66cSDavid du Colombier 2885e96a66cSDavid du Colombier return cliError("close isn't working yet; sync and then kill fossil"); 2895e96a66cSDavid du Colombier 2905e96a66cSDavid du Colombier /* 2915e96a66cSDavid du Colombier * Oooh. This could be hard. What if fsys->ref != 1? 2925e96a66cSDavid du Colombier * Also, fsClose() either does the job or panics, can we 2935e96a66cSDavid du Colombier * gracefully detect it's still busy? 2945e96a66cSDavid du Colombier * 2955e96a66cSDavid du Colombier * More thought and care needed here. 2965e96a66cSDavid du Colombier */ 2975e96a66cSDavid du Colombier fsClose(fsys->fs); 2985e96a66cSDavid du Colombier fsys->fs = nil; 2995e96a66cSDavid du Colombier vtClose(fsys->session); 3005e96a66cSDavid du Colombier fsys->session = nil; 3015e96a66cSDavid du Colombier 3025e96a66cSDavid du Colombier if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){ 3035e96a66cSDavid du Colombier sbox.curfsys = nil; 3045e96a66cSDavid du Colombier consPrompt(nil); 3055e96a66cSDavid du Colombier } 3065e96a66cSDavid du Colombier 3075e96a66cSDavid du Colombier return 1; 3085e96a66cSDavid du Colombier } 3095e96a66cSDavid du Colombier 3105e96a66cSDavid du Colombier static int 3115e96a66cSDavid du Colombier fsysVac(Fsys* fsys, int argc, char* argv[]) 3125e96a66cSDavid du Colombier { 3135e96a66cSDavid du Colombier uchar score[VtScoreSize]; 3145e96a66cSDavid du Colombier char *usage = "usage: [fsys name] vac path"; 3155e96a66cSDavid du Colombier 3165e96a66cSDavid du Colombier ARGBEGIN{ 3175e96a66cSDavid du Colombier default: 3185e96a66cSDavid du Colombier return cliError(usage); 3195e96a66cSDavid du Colombier }ARGEND 3205e96a66cSDavid du Colombier if(argc != 1) 3215e96a66cSDavid du Colombier return cliError(usage); 3225e96a66cSDavid du Colombier 3235e96a66cSDavid du Colombier if(!fsVac(fsys->fs, argv[0], score)) 3245e96a66cSDavid du Colombier return 0; 3255e96a66cSDavid du Colombier 3265e96a66cSDavid du Colombier consPrint("vac:%V\n", score); 3275e96a66cSDavid du Colombier return 1; 3285e96a66cSDavid du Colombier } 3295e96a66cSDavid du Colombier 3305e96a66cSDavid du Colombier static int 3315e96a66cSDavid du Colombier fsysSnap(Fsys* fsys, int argc, char* argv[]) 3325e96a66cSDavid du Colombier { 3335e96a66cSDavid du Colombier int doarchive; 3345e96a66cSDavid du Colombier char *usage = "usage: [fsys name] snap [-a]"; 3355e96a66cSDavid du Colombier 3365e96a66cSDavid du Colombier doarchive = 0; 3375e96a66cSDavid du Colombier ARGBEGIN{ 3385e96a66cSDavid du Colombier default: 3395e96a66cSDavid du Colombier return cliError(usage); 3405e96a66cSDavid du Colombier case 'a': 3415e96a66cSDavid du Colombier doarchive = 1; 3425e96a66cSDavid du Colombier break; 3435e96a66cSDavid du Colombier }ARGEND 3445e96a66cSDavid du Colombier if(argc) 3455e96a66cSDavid du Colombier return cliError(usage); 3465e96a66cSDavid du Colombier 3475e96a66cSDavid du Colombier if(!fsSnapshot(fsys->fs, doarchive)) 3485e96a66cSDavid du Colombier return 0; 3495e96a66cSDavid du Colombier 3505e96a66cSDavid du Colombier return 1; 3515e96a66cSDavid du Colombier } 3525e96a66cSDavid du Colombier 3535e96a66cSDavid du Colombier static int 3545e96a66cSDavid du Colombier fsysSnapTime(Fsys* fsys, int argc, char* argv[]) 3555e96a66cSDavid du Colombier { 3565e96a66cSDavid du Colombier char buf[40], *x; 3575e96a66cSDavid du Colombier int hh, mm; 3585e96a66cSDavid du Colombier u32int arch, snap; 3595e96a66cSDavid du Colombier char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s minutes]"; 3605e96a66cSDavid du Colombier 3615e96a66cSDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap); 3625e96a66cSDavid du Colombier ARGBEGIN{ 3635e96a66cSDavid du Colombier case 'a': 3645e96a66cSDavid du Colombier x = ARGF(); 3655e96a66cSDavid du Colombier if(x == nil) 3665e96a66cSDavid du Colombier return cliError(usage); 3675e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 3685e96a66cSDavid du Colombier arch = ~(u32int)0; 3695e96a66cSDavid du Colombier break; 3705e96a66cSDavid du Colombier } 3715e96a66cSDavid du Colombier if(strlen(x) != 4 || strspn(x, "0123456789") != 4) 3725e96a66cSDavid du Colombier return cliError(usage); 3735e96a66cSDavid du Colombier hh = (x[0]-'0')*10 + x[1]-'0'; 3745e96a66cSDavid du Colombier mm = (x[2]-'0')*10 + x[3]-'0'; 3755e96a66cSDavid du Colombier if(hh >= 24 || mm >= 60) 3765e96a66cSDavid du Colombier return cliError(usage); 3775e96a66cSDavid du Colombier arch = hh*60+mm; 3785e96a66cSDavid du Colombier break; 3795e96a66cSDavid du Colombier case 's': 3805e96a66cSDavid du Colombier x = ARGF(); 3815e96a66cSDavid du Colombier if(x == nil) 3825e96a66cSDavid du Colombier return cliError(usage); 3835e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 3845e96a66cSDavid du Colombier snap = ~(u32int)0; 3855e96a66cSDavid du Colombier break; 3865e96a66cSDavid du Colombier } 3875e96a66cSDavid du Colombier snap = atoi(x); 3885e96a66cSDavid du Colombier break; 3895e96a66cSDavid du Colombier default: 3905e96a66cSDavid du Colombier return cliError(usage); 3915e96a66cSDavid du Colombier }ARGEND 3925e96a66cSDavid du Colombier if(argc > 0) 3935e96a66cSDavid du Colombier return cliError(usage); 3945e96a66cSDavid du Colombier 3955e96a66cSDavid du Colombier snapSetTimes(fsys->fs->snap, arch, snap); 3965e96a66cSDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap); 3975e96a66cSDavid du Colombier if(arch != ~(u32int)0) 3985e96a66cSDavid du Colombier sprint(buf, "-a %02d%02d", arch/60, arch%60); 3995e96a66cSDavid du Colombier else 4005e96a66cSDavid du Colombier sprint(buf, "-a none"); 4015e96a66cSDavid du Colombier if(snap != ~(u32int)0) 4025e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s %d", snap); 4035e96a66cSDavid du Colombier else 4045e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s none"); 4055e96a66cSDavid du Colombier consPrint("\tsnaptime %s\n", buf); 4065e96a66cSDavid du Colombier return 1; 4075e96a66cSDavid du Colombier } 4085e96a66cSDavid du Colombier 4095e96a66cSDavid du Colombier static int 4105e96a66cSDavid du Colombier fsysSync(Fsys* fsys, int argc, char* argv[]) 4115e96a66cSDavid du Colombier { 4125e96a66cSDavid du Colombier char *usage = "usage: [fsys name] sync"; 4135e96a66cSDavid du Colombier 4145e96a66cSDavid du Colombier ARGBEGIN{ 4155e96a66cSDavid du Colombier default: 4165e96a66cSDavid du Colombier return cliError(usage); 4175e96a66cSDavid du Colombier }ARGEND 4185e96a66cSDavid du Colombier if(argc > 0) 4195e96a66cSDavid du Colombier return cliError(usage); 4205e96a66cSDavid du Colombier 4215e96a66cSDavid du Colombier fsSync(fsys->fs); 422*81cf8742SDavid du Colombier return 1; 423*81cf8742SDavid du Colombier } 4245e96a66cSDavid du Colombier 425*81cf8742SDavid du Colombier static int 426*81cf8742SDavid du Colombier fsysHalt(Fsys *fsys, int argc, char* argv[]) 427*81cf8742SDavid du Colombier { 428*81cf8742SDavid du Colombier char *usage = "usage: [fsys name] halt"; 429*81cf8742SDavid du Colombier 430*81cf8742SDavid du Colombier ARGBEGIN{ 431*81cf8742SDavid du Colombier default: 432*81cf8742SDavid du Colombier return cliError(usage); 433*81cf8742SDavid du Colombier }ARGEND 434*81cf8742SDavid du Colombier if(argc > 0) 435*81cf8742SDavid du Colombier return cliError(usage); 436*81cf8742SDavid du Colombier 437*81cf8742SDavid du Colombier fsHalt(fsys->fs); 438*81cf8742SDavid du Colombier return 1; 439*81cf8742SDavid du Colombier } 440*81cf8742SDavid du Colombier 441*81cf8742SDavid du Colombier static int 442*81cf8742SDavid du Colombier fsysUnhalt(Fsys *fsys, int argc, char* argv[]) 443*81cf8742SDavid du Colombier { 444*81cf8742SDavid du Colombier char *usage = "usage: [fsys name] unhalt"; 445*81cf8742SDavid du Colombier 446*81cf8742SDavid du Colombier ARGBEGIN{ 447*81cf8742SDavid du Colombier default: 448*81cf8742SDavid du Colombier return cliError(usage); 449*81cf8742SDavid du Colombier }ARGEND 450*81cf8742SDavid du Colombier if(argc > 0) 451*81cf8742SDavid du Colombier return cliError(usage); 452*81cf8742SDavid du Colombier 453*81cf8742SDavid du Colombier if(!fsys->fs->halted) 454*81cf8742SDavid du Colombier return cliError("file system %s not halted", fsys->name); 455*81cf8742SDavid du Colombier 456*81cf8742SDavid du Colombier fsUnhalt(fsys->fs); 4575e96a66cSDavid du Colombier return 1; 4585e96a66cSDavid du Colombier } 4595e96a66cSDavid du Colombier 4605e96a66cSDavid du Colombier static int 4615e96a66cSDavid du Colombier fsysRemove(Fsys* fsys, int argc, char* argv[]) 4625e96a66cSDavid du Colombier { 4635e96a66cSDavid du Colombier File *file; 4645e96a66cSDavid du Colombier char *usage = "usage: [fsys name] remove path ..."; 4655e96a66cSDavid du Colombier 4665e96a66cSDavid du Colombier ARGBEGIN{ 4675e96a66cSDavid du Colombier default: 4685e96a66cSDavid du Colombier return cliError(usage); 4695e96a66cSDavid du Colombier }ARGEND 4705e96a66cSDavid du Colombier if(argc == 0) 4715e96a66cSDavid du Colombier return cliError(usage); 4725e96a66cSDavid du Colombier 4735e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 4745e96a66cSDavid du Colombier while(argc > 0){ 4755e96a66cSDavid du Colombier if((file = fileOpen(fsys->fs, argv[0])) == nil) 4765e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 4775e96a66cSDavid du Colombier else{ 4785e96a66cSDavid du Colombier if(!fileRemove(file, uidadm)) 4795e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 4805e96a66cSDavid du Colombier fileDecRef(file); 4815e96a66cSDavid du Colombier } 4825e96a66cSDavid du Colombier argc--; 4835e96a66cSDavid du Colombier argv++; 4845e96a66cSDavid du Colombier } 4855e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 4865e96a66cSDavid du Colombier 4875e96a66cSDavid du Colombier return 1; 4885e96a66cSDavid du Colombier } 4895e96a66cSDavid du Colombier 4905e96a66cSDavid du Colombier static int 4915e96a66cSDavid du Colombier fsysClri(Fsys* fsys, int argc, char* argv[]) 4925e96a66cSDavid du Colombier { 4935e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clri path ..."; 4945e96a66cSDavid du Colombier 4955e96a66cSDavid du Colombier ARGBEGIN{ 4965e96a66cSDavid du Colombier default: 4975e96a66cSDavid du Colombier return cliError(usage); 4985e96a66cSDavid du Colombier }ARGEND 4995e96a66cSDavid du Colombier if(argc == 0) 5005e96a66cSDavid du Colombier return cliError(usage); 5015e96a66cSDavid du Colombier 5025e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5035e96a66cSDavid du Colombier while(argc > 0){ 5045e96a66cSDavid du Colombier if(!fileClri(fsys->fs, argv[0], uidadm)) 5055e96a66cSDavid du Colombier consPrint("clri %s: %R\n", argv[0]); 5065e96a66cSDavid du Colombier argc--; 5075e96a66cSDavid du Colombier argv++; 5085e96a66cSDavid du Colombier } 5095e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 5105e96a66cSDavid du Colombier 5115e96a66cSDavid du Colombier return 1; 5125e96a66cSDavid du Colombier } 5135e96a66cSDavid du Colombier 5145e96a66cSDavid du Colombier /* 5155e96a66cSDavid du Colombier * Inspect and edit the labels for blocks on disk. 5165e96a66cSDavid du Colombier */ 5175e96a66cSDavid du Colombier static int 5185e96a66cSDavid du Colombier fsysLabel(Fsys* fsys, int argc, char* argv[]) 5195e96a66cSDavid du Colombier { 5205e96a66cSDavid du Colombier Fs *fs; 5215e96a66cSDavid du Colombier Label l; 5225e96a66cSDavid du Colombier int n, r; 5235e96a66cSDavid du Colombier u32int addr; 5245e96a66cSDavid du Colombier Block *b, *bb; 5255e96a66cSDavid du Colombier char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]"; 5265e96a66cSDavid du Colombier 5275e96a66cSDavid du Colombier ARGBEGIN{ 5285e96a66cSDavid du Colombier default: 5295e96a66cSDavid du Colombier return cliError(usage); 5305e96a66cSDavid du Colombier }ARGEND 5315e96a66cSDavid du Colombier if(argc != 1 && argc != 6) 5325e96a66cSDavid du Colombier return cliError(usage); 5335e96a66cSDavid du Colombier 5345e96a66cSDavid du Colombier r = 0; 5355e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5365e96a66cSDavid du Colombier 5375e96a66cSDavid du Colombier fs = fsys->fs; 5385e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 5395e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 5405e96a66cSDavid du Colombier if(b == nil) 5415e96a66cSDavid du Colombier goto Out0; 5425e96a66cSDavid du Colombier 5435e96a66cSDavid du Colombier l = b->l; 5445e96a66cSDavid du Colombier consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n", 5455e96a66cSDavid du Colombier argc==6 ? "old: " : "", addr, l.type, l.state, 5465e96a66cSDavid du Colombier l.epoch, l.epochClose, l.tag); 5475e96a66cSDavid du Colombier 5485e96a66cSDavid du Colombier if(argc == 6){ 5495e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0) 5505e96a66cSDavid du Colombier l.type = atoi(argv[1]); 5515e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0) 5525e96a66cSDavid du Colombier l.state = atoi(argv[2]); 5535e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0) 5545e96a66cSDavid du Colombier l.epoch = strtoul(argv[3], 0, 0); 5555e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0) 5565e96a66cSDavid du Colombier l.epochClose = strtoul(argv[4], 0, 0); 5575e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0) 5585e96a66cSDavid du Colombier l.tag = strtoul(argv[5], 0, 0); 5595e96a66cSDavid du Colombier 5605e96a66cSDavid du Colombier consPrint("new: label %#ux %ud %ud %ud %ud %#x\n", 5615e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 5625e96a66cSDavid du Colombier bb = _blockSetLabel(b, &l); 5635e96a66cSDavid du Colombier if(bb == nil) 5645e96a66cSDavid du Colombier goto Out1; 5655e96a66cSDavid du Colombier n = 0; 5665e96a66cSDavid du Colombier for(;;){ 5675e96a66cSDavid du Colombier if(blockWrite(bb)){ 5685e96a66cSDavid du Colombier while(bb->iostate != BioClean){ 5695e96a66cSDavid du Colombier assert(bb->iostate == BioWriting); 5705e96a66cSDavid du Colombier vtSleep(bb->ioready); 5715e96a66cSDavid du Colombier } 5725e96a66cSDavid du Colombier break; 5735e96a66cSDavid du Colombier } 5745e96a66cSDavid du Colombier consPrint("blockWrite: %R\n"); 5755e96a66cSDavid du Colombier if(n++ >= 5){ 5765e96a66cSDavid du Colombier consPrint("giving up\n"); 5775e96a66cSDavid du Colombier break; 5785e96a66cSDavid du Colombier } 5795e96a66cSDavid du Colombier sleep(5*1000); 5805e96a66cSDavid du Colombier } 5815e96a66cSDavid du Colombier blockPut(bb); 5825e96a66cSDavid du Colombier } 5835e96a66cSDavid du Colombier r = 1; 5845e96a66cSDavid du Colombier Out1: 5855e96a66cSDavid du Colombier blockPut(b); 5865e96a66cSDavid du Colombier Out0: 5875e96a66cSDavid du Colombier vtRUnlock(fs->elk); 5885e96a66cSDavid du Colombier 5895e96a66cSDavid du Colombier return r; 5905e96a66cSDavid du Colombier } 5915e96a66cSDavid du Colombier 5925e96a66cSDavid du Colombier /* 5935e96a66cSDavid du Colombier * Inspect and edit the blocks on disk. 5945e96a66cSDavid du Colombier */ 5955e96a66cSDavid du Colombier static int 5965e96a66cSDavid du Colombier fsysBlock(Fsys* fsys, int argc, char* argv[]) 5975e96a66cSDavid du Colombier { 5985e96a66cSDavid du Colombier Fs *fs; 5995e96a66cSDavid du Colombier char *s; 6005e96a66cSDavid du Colombier Block *b; 6015e96a66cSDavid du Colombier uchar *buf; 6025e96a66cSDavid du Colombier u32int addr; 6035e96a66cSDavid du Colombier int c, count, i, offset; 6045e96a66cSDavid du Colombier char *usage = "usage: [fsys name] block addr offset [count [data]]"; 6055e96a66cSDavid du Colombier 6065e96a66cSDavid du Colombier ARGBEGIN{ 6075e96a66cSDavid du Colombier default: 6085e96a66cSDavid du Colombier return cliError(usage); 6095e96a66cSDavid du Colombier }ARGEND 6105e96a66cSDavid du Colombier if(argc < 2 || argc > 4) 6115e96a66cSDavid du Colombier return cliError(usage); 6125e96a66cSDavid du Colombier 6135e96a66cSDavid du Colombier fs = fsys->fs; 6145e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 6155e96a66cSDavid du Colombier offset = strtoul(argv[1], 0, 0); 6165e96a66cSDavid du Colombier if(offset < 0 || offset >= fs->blockSize){ 6175e96a66cSDavid du Colombier vtSetError("bad offset"); 6185e96a66cSDavid du Colombier return 0; 6195e96a66cSDavid du Colombier } 6205e96a66cSDavid du Colombier if(argc > 2) 6215e96a66cSDavid du Colombier count = strtoul(argv[2], 0, 0); 6225e96a66cSDavid du Colombier else 6235e96a66cSDavid du Colombier count = 100000000; 6245e96a66cSDavid du Colombier if(offset+count > fs->blockSize) 6255e96a66cSDavid du Colombier count = fs->blockSize - count; 6265e96a66cSDavid du Colombier 6275e96a66cSDavid du Colombier vtRLock(fs->elk); 6285e96a66cSDavid du Colombier 6295e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 6305e96a66cSDavid du Colombier if(b == nil){ 6315e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 6325e96a66cSDavid du Colombier vtRUnlock(fs->elk); 6335e96a66cSDavid du Colombier return 0; 6345e96a66cSDavid du Colombier } 6355e96a66cSDavid du Colombier 6365e96a66cSDavid du Colombier consPrint("\t%sblock %#ux %ud %ud %.*H\n", 6375e96a66cSDavid du Colombier argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset); 6385e96a66cSDavid du Colombier 6395e96a66cSDavid du Colombier if(argc == 4){ 6405e96a66cSDavid du Colombier s = argv[3]; 6415e96a66cSDavid du Colombier if(strlen(s) != 2*count){ 6425e96a66cSDavid du Colombier vtSetError("bad data count"); 6435e96a66cSDavid du Colombier goto Out; 6445e96a66cSDavid du Colombier } 6455e96a66cSDavid du Colombier buf = vtMemAllocZ(count); 6465e96a66cSDavid du Colombier for(i = 0; i < count*2; i++){ 6475e96a66cSDavid du Colombier if(s[i] >= '0' && s[i] <= '9') 6485e96a66cSDavid du Colombier c = s[i] - '0'; 6495e96a66cSDavid du Colombier else if(s[i] >= 'a' && s[i] <= 'f') 6505e96a66cSDavid du Colombier c = s[i] - 'a' + 10; 6515e96a66cSDavid du Colombier else if(s[i] >= 'A' && s[i] <= 'F') 6525e96a66cSDavid du Colombier c = s[i] - 'A' + 10; 6535e96a66cSDavid du Colombier else{ 6545e96a66cSDavid du Colombier vtSetError("bad hex"); 6555e96a66cSDavid du Colombier vtMemFree(buf); 6565e96a66cSDavid du Colombier goto Out; 6575e96a66cSDavid du Colombier } 6585e96a66cSDavid du Colombier if((i & 1) == 0) 6595e96a66cSDavid du Colombier c <<= 4; 6605e96a66cSDavid du Colombier buf[i>>1] |= c; 6615e96a66cSDavid du Colombier } 6625e96a66cSDavid du Colombier memmove(b->data+offset, buf, count); 6635e96a66cSDavid du Colombier consPrint("\tnew: block %#ux %ud %ud %.*H\n", 6645e96a66cSDavid du Colombier addr, offset, count, count, b->data+offset); 6655e96a66cSDavid du Colombier blockDirty(b); 6665e96a66cSDavid du Colombier } 6675e96a66cSDavid du Colombier 6685e96a66cSDavid du Colombier Out: 6695e96a66cSDavid du Colombier blockPut(b); 6705e96a66cSDavid du Colombier vtRUnlock(fs->elk); 6715e96a66cSDavid du Colombier 6725e96a66cSDavid du Colombier return 1; 6735e96a66cSDavid du Colombier } 6745e96a66cSDavid du Colombier 6755e96a66cSDavid du Colombier /* 6765e96a66cSDavid du Colombier * Free a disk block. 6775e96a66cSDavid du Colombier */ 6785e96a66cSDavid du Colombier static int 6795e96a66cSDavid du Colombier fsysBfree(Fsys* fsys, int argc, char* argv[]) 6805e96a66cSDavid du Colombier { 6815e96a66cSDavid du Colombier Fs *fs; 6825e96a66cSDavid du Colombier Label l; 6835e96a66cSDavid du Colombier char *p; 6845e96a66cSDavid du Colombier Block *b; 6855e96a66cSDavid du Colombier u32int addr; 6865e96a66cSDavid du Colombier char *usage = "usage: [fsys name] bfree addr ..."; 6875e96a66cSDavid du Colombier 6885e96a66cSDavid du Colombier ARGBEGIN{ 6895e96a66cSDavid du Colombier default: 6905e96a66cSDavid du Colombier return cliError(usage); 6915e96a66cSDavid du Colombier }ARGEND 6925e96a66cSDavid du Colombier if(argc == 0) 6935e96a66cSDavid du Colombier return cliError(usage); 6945e96a66cSDavid du Colombier 6955e96a66cSDavid du Colombier fs = fsys->fs; 6965e96a66cSDavid du Colombier vtRLock(fs->elk); 6975e96a66cSDavid du Colombier while(argc > 0){ 6985e96a66cSDavid du Colombier addr = strtoul(argv[0], &p, 0); 6995e96a66cSDavid du Colombier if(*p != '\0'){ 7005e96a66cSDavid du Colombier consPrint("bad address - '%s'\n", addr); 7015e96a66cSDavid du Colombier /* syntax error; let's stop */ 7025e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7035e96a66cSDavid du Colombier return 0; 7045e96a66cSDavid du Colombier } 7055e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 7065e96a66cSDavid du Colombier if(b == nil){ 7075e96a66cSDavid du Colombier consPrint("loading %#ux: %R\n", addr); 7085e96a66cSDavid du Colombier continue; 7095e96a66cSDavid du Colombier } 7105e96a66cSDavid du Colombier l = b->l; 7115e96a66cSDavid du Colombier consPrint("label %#ux %ud %ud %ud %ud %#x\n", 7125e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 7135e96a66cSDavid du Colombier l.state = BsFree; 7145e96a66cSDavid du Colombier l.type = BtMax; 7155e96a66cSDavid du Colombier l.tag = 0; 7165e96a66cSDavid du Colombier l.epoch = 0; 7175e96a66cSDavid du Colombier l.epochClose = 0; 7185e96a66cSDavid du Colombier if(!blockSetLabel(b, &l)) 7195e96a66cSDavid du Colombier consPrint("freeing %#ux: %R\n", addr); 7205e96a66cSDavid du Colombier blockPut(b); 7215e96a66cSDavid du Colombier argc--; 7225e96a66cSDavid du Colombier argv++; 7235e96a66cSDavid du Colombier } 7245e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7255e96a66cSDavid du Colombier 7265e96a66cSDavid du Colombier return 1; 7275e96a66cSDavid du Colombier } 7285e96a66cSDavid du Colombier 7297abd426fSDavid du Colombier static int 7307abd426fSDavid du Colombier fsysDf(Fsys *fsys, int argc, char* argv[]) 7317abd426fSDavid du Colombier { 7327abd426fSDavid du Colombier char *usage = "usage: [fsys name] df"; 7337abd426fSDavid du Colombier u32int used, tot, bsize; 7347abd426fSDavid du Colombier Fs *fs; 7357abd426fSDavid du Colombier 7367abd426fSDavid du Colombier ARGBEGIN{ 7377abd426fSDavid du Colombier default: 7387abd426fSDavid du Colombier return cliError(usage); 7397abd426fSDavid du Colombier }ARGEND 7407abd426fSDavid du Colombier if(argc != 0) 7417abd426fSDavid du Colombier return cliError(usage); 7427abd426fSDavid du Colombier 7437abd426fSDavid du Colombier fs = fsys->fs; 7447abd426fSDavid du Colombier cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize); 7457abd426fSDavid du Colombier consPrint("%lud/%lud blocks used (%,llud/%,llud bytes)\n", 7467abd426fSDavid du Colombier used, tot, used*(vlong)bsize, tot*(vlong)bsize); 7477abd426fSDavid du Colombier return 1; 7487abd426fSDavid du Colombier } 7497abd426fSDavid du Colombier 7505e96a66cSDavid du Colombier /* 7515e96a66cSDavid du Colombier * Zero an entry or a pointer. 7525e96a66cSDavid du Colombier */ 7535e96a66cSDavid du Colombier static int 7545e96a66cSDavid du Colombier fsysClrep(Fsys* fsys, int argc, char* argv[], int ch) 7555e96a66cSDavid du Colombier { 7565e96a66cSDavid du Colombier Fs *fs; 7575e96a66cSDavid du Colombier Entry e; 7585e96a66cSDavid du Colombier Block *b; 7595e96a66cSDavid du Colombier u32int addr; 7605e96a66cSDavid du Colombier int i, max, offset, sz; 7615e96a66cSDavid du Colombier uchar zero[VtEntrySize]; 7625e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clr%c addr offset ..."; 7635e96a66cSDavid du Colombier 7645e96a66cSDavid du Colombier ARGBEGIN{ 7655e96a66cSDavid du Colombier default: 7665e96a66cSDavid du Colombier return cliError(usage, ch); 7675e96a66cSDavid du Colombier }ARGEND 7685e96a66cSDavid du Colombier if(argc < 2) 7695e96a66cSDavid du Colombier return cliError(usage, ch); 7705e96a66cSDavid du Colombier 7715e96a66cSDavid du Colombier fs = fsys->fs; 7725e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 7735e96a66cSDavid du Colombier 7745e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 7755e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 7765e96a66cSDavid du Colombier if(b == nil){ 7775e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 7785e96a66cSDavid du Colombier Err: 7795e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 7805e96a66cSDavid du Colombier return 0; 7815e96a66cSDavid du Colombier } 7825e96a66cSDavid du Colombier 7835e96a66cSDavid du Colombier switch(ch){ 7845e96a66cSDavid du Colombier default: 7855e96a66cSDavid du Colombier vtSetError("clrep"); 7865e96a66cSDavid du Colombier goto Err; 7875e96a66cSDavid du Colombier case 'e': 7885e96a66cSDavid du Colombier if(b->l.type != BtDir){ 7895e96a66cSDavid du Colombier vtSetError("wrong block type"); 7905e96a66cSDavid du Colombier goto Err; 7915e96a66cSDavid du Colombier } 7925e96a66cSDavid du Colombier sz = VtEntrySize; 7935e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 7945e96a66cSDavid du Colombier entryPack(&e, zero, 0); 7955e96a66cSDavid du Colombier break; 7965e96a66cSDavid du Colombier case 'p': 7975e96a66cSDavid du Colombier if(b->l.type == BtDir || b->l.type == BtData){ 7985e96a66cSDavid du Colombier vtSetError("wrong block type"); 7995e96a66cSDavid du Colombier goto Err; 8005e96a66cSDavid du Colombier } 8015e96a66cSDavid du Colombier sz = VtScoreSize; 8025e96a66cSDavid du Colombier memmove(zero, vtZeroScore, VtScoreSize); 8035e96a66cSDavid du Colombier break; 8045e96a66cSDavid du Colombier } 8055e96a66cSDavid du Colombier max = fs->blockSize/sz; 8065e96a66cSDavid du Colombier 8075e96a66cSDavid du Colombier for(i = 1; i < argc; i++){ 8085e96a66cSDavid du Colombier offset = atoi(argv[i]); 8095e96a66cSDavid du Colombier if(offset >= max){ 8105e96a66cSDavid du Colombier consPrint("\toffset %d too large (>= %d)\n", i, max); 8115e96a66cSDavid du Colombier continue; 8125e96a66cSDavid du Colombier } 8135e96a66cSDavid du Colombier consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz); 8145e96a66cSDavid du Colombier memmove(b->data+offset*sz, zero, sz); 8155e96a66cSDavid du Colombier } 8165e96a66cSDavid du Colombier blockDirty(b); 8175e96a66cSDavid du Colombier blockPut(b); 8185e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 8195e96a66cSDavid du Colombier 8205e96a66cSDavid du Colombier return 1; 8215e96a66cSDavid du Colombier } 8225e96a66cSDavid du Colombier 8235e96a66cSDavid du Colombier static int 8245e96a66cSDavid du Colombier fsysClre(Fsys* fsys, int argc, char* argv[]) 8255e96a66cSDavid du Colombier { 8265e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'e'); 8275e96a66cSDavid du Colombier } 8285e96a66cSDavid du Colombier 8295e96a66cSDavid du Colombier static int 8305e96a66cSDavid du Colombier fsysClrp(Fsys* fsys, int argc, char* argv[]) 8315e96a66cSDavid du Colombier { 8325e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'p'); 8335e96a66cSDavid du Colombier } 8345e96a66cSDavid du Colombier 8355e96a66cSDavid du Colombier static int 8365e96a66cSDavid du Colombier fsysEsearch1(File* f, char* s, u32int elo) 8375e96a66cSDavid du Colombier { 8385e96a66cSDavid du Colombier int n, r; 8395e96a66cSDavid du Colombier DirEntry de; 8405e96a66cSDavid du Colombier DirEntryEnum *dee; 8415e96a66cSDavid du Colombier File *ff; 8425e96a66cSDavid du Colombier Entry e, ee; 8435e96a66cSDavid du Colombier char *t; 8445e96a66cSDavid du Colombier 8455e96a66cSDavid du Colombier dee = deeOpen(f); 8465e96a66cSDavid du Colombier if(dee == nil) 8475e96a66cSDavid du Colombier return 0; 8485e96a66cSDavid du Colombier 8495e96a66cSDavid du Colombier n = 0; 8505e96a66cSDavid du Colombier for(;;){ 8515e96a66cSDavid du Colombier r = deeRead(dee, &de); 8525e96a66cSDavid du Colombier if(r < 0){ 8535e96a66cSDavid du Colombier consPrint("\tdeeRead %s/%s: %R\n", s, de.elem); 8545e96a66cSDavid du Colombier break; 8555e96a66cSDavid du Colombier } 8565e96a66cSDavid du Colombier if(r == 0) 8575e96a66cSDavid du Colombier break; 8585e96a66cSDavid du Colombier if(de.mode & ModeSnapshot){ 8595e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 8605e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 8615e96a66cSDavid du Colombier else{ 8625e96a66cSDavid du Colombier if(!fileGetSources(ff, &e, &ee, 0)) 8635e96a66cSDavid du Colombier consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem); 8645e96a66cSDavid du Colombier else if(e.snap != 0 && e.snap < elo){ 8655e96a66cSDavid du Colombier consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem); 8665e96a66cSDavid du Colombier n++; 8675e96a66cSDavid du Colombier } 8685e96a66cSDavid du Colombier fileDecRef(ff); 8695e96a66cSDavid du Colombier } 8705e96a66cSDavid du Colombier } 8715e96a66cSDavid du Colombier else if(de.mode & ModeDir){ 8725e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 8735e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 8745e96a66cSDavid du Colombier else{ 875f8e525acSDavid du Colombier t = smprint("%s/%s", s, de.elem); 8765e96a66cSDavid du Colombier n += fsysEsearch1(ff, t, elo); 8775e96a66cSDavid du Colombier vtMemFree(t); 8785e96a66cSDavid du Colombier fileDecRef(ff); 8795e96a66cSDavid du Colombier } 8805e96a66cSDavid du Colombier } 8815e96a66cSDavid du Colombier deCleanup(&de); 8825e96a66cSDavid du Colombier if(r < 0) 8835e96a66cSDavid du Colombier break; 8845e96a66cSDavid du Colombier } 8855e96a66cSDavid du Colombier deeClose(dee); 8865e96a66cSDavid du Colombier 8875e96a66cSDavid du Colombier return n; 8885e96a66cSDavid du Colombier } 8895e96a66cSDavid du Colombier 8905e96a66cSDavid du Colombier static int 8915e96a66cSDavid du Colombier fsysEsearch(Fs* fs, char* path, u32int elo) 8925e96a66cSDavid du Colombier { 8935e96a66cSDavid du Colombier int n; 8945e96a66cSDavid du Colombier File *f; 8955e96a66cSDavid du Colombier DirEntry de; 8965e96a66cSDavid du Colombier 8975e96a66cSDavid du Colombier f = fileOpen(fs, path); 8985e96a66cSDavid du Colombier if(f == nil) 8995e96a66cSDavid du Colombier return 0; 9005e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 9015e96a66cSDavid du Colombier consPrint("\tfileGetDir %s failed: %R\n", path); 9025e96a66cSDavid du Colombier fileDecRef(f); 9035e96a66cSDavid du Colombier return 0; 9045e96a66cSDavid du Colombier } 9055e96a66cSDavid du Colombier if((de.mode & ModeDir) == 0){ 9065e96a66cSDavid du Colombier fileDecRef(f); 9075e96a66cSDavid du Colombier deCleanup(&de); 9085e96a66cSDavid du Colombier return 0; 9095e96a66cSDavid du Colombier } 9105e96a66cSDavid du Colombier deCleanup(&de); 9115e96a66cSDavid du Colombier n = fsysEsearch1(f, path, elo); 9125e96a66cSDavid du Colombier fileDecRef(f); 9135e96a66cSDavid du Colombier return n; 9145e96a66cSDavid du Colombier } 9155e96a66cSDavid du Colombier 9165e96a66cSDavid du Colombier static int 9175e96a66cSDavid du Colombier fsysEpoch(Fsys* fsys, int argc, char* argv[]) 9185e96a66cSDavid du Colombier { 9195e96a66cSDavid du Colombier Fs *fs; 9205e96a66cSDavid du Colombier int force, n; 9215e96a66cSDavid du Colombier u32int low, old; 9225e96a66cSDavid du Colombier char *usage = "usage: [fsys name] epoch [[-y] low]"; 9235e96a66cSDavid du Colombier 9245e96a66cSDavid du Colombier force = 0; 9255e96a66cSDavid du Colombier ARGBEGIN{ 9265e96a66cSDavid du Colombier case 'y': 9275e96a66cSDavid du Colombier force = 1; 9285e96a66cSDavid du Colombier break; 9295e96a66cSDavid du Colombier default: 9305e96a66cSDavid du Colombier return cliError(usage); 9315e96a66cSDavid du Colombier }ARGEND 9325e96a66cSDavid du Colombier if(argc > 1) 9335e96a66cSDavid du Colombier return cliError(usage); 9345e96a66cSDavid du Colombier if(argc > 0) 9355e96a66cSDavid du Colombier low = strtoul(argv[0], 0, 0); 9365e96a66cSDavid du Colombier else 9375e96a66cSDavid du Colombier low = ~(u32int)0; 9385e96a66cSDavid du Colombier 9395e96a66cSDavid du Colombier fs = fsys->fs; 9405e96a66cSDavid du Colombier 9415e96a66cSDavid du Colombier vtRLock(fs->elk); 9425e96a66cSDavid du Colombier consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi); 9435e96a66cSDavid du Colombier n = fsysEsearch(fsys->fs, "/archive", low); 9445e96a66cSDavid du Colombier n += fsysEsearch(fsys->fs, "/snapshot", low); 9455e96a66cSDavid du Colombier consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low); 9465e96a66cSDavid du Colombier vtRUnlock(fs->elk); 9475e96a66cSDavid du Colombier 9485e96a66cSDavid du Colombier /* 9495e96a66cSDavid du Colombier * There's a small race here -- a new snapshot with epoch < low might 9505e96a66cSDavid du Colombier * get introduced now that we unlocked fs->elk. Low has to 9515e96a66cSDavid du Colombier * be <= fs->ehi. Of course, in order for this to happen low has 9525e96a66cSDavid du Colombier * to be equal to the current fs->ehi _and_ a snapshot has to 9535e96a66cSDavid du Colombier * run right now. This is a small enough window that I don't care. 9545e96a66cSDavid du Colombier */ 9555e96a66cSDavid du Colombier if(n != 0 && !force){ 9565e96a66cSDavid du Colombier consPrint("\tnot setting low epoch\n"); 9575e96a66cSDavid du Colombier return 1; 9585e96a66cSDavid du Colombier } 9595e96a66cSDavid du Colombier old = fs->elo; 9605e96a66cSDavid du Colombier if(!fsEpochLow(fs, low)) 9615e96a66cSDavid du Colombier consPrint("\tfsEpochLow: %R\n"); 9625e96a66cSDavid du Colombier else{ 9635e96a66cSDavid du Colombier consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old); 9645e96a66cSDavid du Colombier consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo); 9655e96a66cSDavid du Colombier if(fs->elo < low) 9665e96a66cSDavid du Colombier consPrint("\twarning: new low epoch < old low epoch\n"); 9675e96a66cSDavid du Colombier } 9685e96a66cSDavid du Colombier 9695e96a66cSDavid du Colombier return 1; 9705e96a66cSDavid du Colombier } 9715e96a66cSDavid du Colombier 9725e96a66cSDavid du Colombier static int 9735e96a66cSDavid du Colombier fsysCreate(Fsys* fsys, int argc, char* argv[]) 9745e96a66cSDavid du Colombier { 9755e96a66cSDavid du Colombier int r; 9765e96a66cSDavid du Colombier ulong mode; 9775e96a66cSDavid du Colombier char *elem, *p, *path; 9785e96a66cSDavid du Colombier char *usage = "usage: [fsys name] create path uid gid perm"; 9795e96a66cSDavid du Colombier DirEntry de; 9805e96a66cSDavid du Colombier File *file, *parent; 9815e96a66cSDavid du Colombier 9825e96a66cSDavid du Colombier ARGBEGIN{ 9835e96a66cSDavid du Colombier default: 9845e96a66cSDavid du Colombier return cliError(usage); 9855e96a66cSDavid du Colombier }ARGEND 9865e96a66cSDavid du Colombier if(argc != 4) 9875e96a66cSDavid du Colombier return cliError(usage); 9885e96a66cSDavid du Colombier 9895e96a66cSDavid du Colombier if(!fsysParseMode(argv[3], &mode)) 9905e96a66cSDavid du Colombier return cliError(usage); 9915e96a66cSDavid du Colombier if(mode&ModeSnapshot) 9925e96a66cSDavid du Colombier return cliError("create - cannot create with snapshot bit set"); 9935e96a66cSDavid du Colombier 9945e96a66cSDavid du Colombier if(strcmp(argv[1], uidnoworld) == 0) 9955e96a66cSDavid du Colombier return cliError("permission denied"); 9965e96a66cSDavid du Colombier 9975e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 9985e96a66cSDavid du Colombier path = vtStrDup(argv[0]); 9995e96a66cSDavid du Colombier if((p = strrchr(path, '/')) != nil){ 10005e96a66cSDavid du Colombier *p++ = '\0'; 10015e96a66cSDavid du Colombier elem = p; 10025e96a66cSDavid du Colombier p = path; 10035e96a66cSDavid du Colombier if(*p == '\0') 10045e96a66cSDavid du Colombier p = "/"; 10055e96a66cSDavid du Colombier } 10065e96a66cSDavid du Colombier else{ 10075e96a66cSDavid du Colombier p = "/"; 10085e96a66cSDavid du Colombier elem = path; 10095e96a66cSDavid du Colombier } 1010f8e525acSDavid du Colombier 10115e96a66cSDavid du Colombier r = 0; 1012f8e525acSDavid du Colombier if((parent = fileOpen(fsys->fs, p)) == nil) 1013f8e525acSDavid du Colombier goto out; 1014f8e525acSDavid du Colombier 10155e96a66cSDavid du Colombier file = fileCreate(parent, elem, mode, argv[1]); 10165e96a66cSDavid du Colombier fileDecRef(parent); 1017f8e525acSDavid du Colombier if(file == nil){ 1018f8e525acSDavid du Colombier vtSetError("create %s/%s: %R", p, elem); 1019f8e525acSDavid du Colombier goto out; 1020f8e525acSDavid du Colombier } 1021f8e525acSDavid du Colombier 1022f8e525acSDavid du Colombier if(!fileGetDir(file, &de)){ 1023f8e525acSDavid du Colombier vtSetError("stat failed after create: %R"); 1024f8e525acSDavid du Colombier goto out1; 1025f8e525acSDavid du Colombier } 1026f8e525acSDavid du Colombier 10275e96a66cSDavid du Colombier if(strcmp(de.gid, argv[2]) != 0){ 10285e96a66cSDavid du Colombier vtMemFree(de.gid); 10295e96a66cSDavid du Colombier de.gid = vtStrDup(argv[2]); 1030f8e525acSDavid du Colombier if(!fileSetDir(file, &de, argv[1])){ 1031f8e525acSDavid du Colombier vtSetError("wstat failed after create: %R"); 1032f8e525acSDavid du Colombier goto out2; 10335e96a66cSDavid du Colombier } 1034f8e525acSDavid du Colombier } 1035f8e525acSDavid du Colombier r = 1; 1036f8e525acSDavid du Colombier 1037f8e525acSDavid du Colombier out2: 10385e96a66cSDavid du Colombier deCleanup(&de); 1039f8e525acSDavid du Colombier out1: 10405e96a66cSDavid du Colombier fileDecRef(file); 1041f8e525acSDavid du Colombier out: 10425e96a66cSDavid du Colombier vtMemFree(path); 10435e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 10445e96a66cSDavid du Colombier 10455e96a66cSDavid du Colombier return r; 10465e96a66cSDavid du Colombier } 10475e96a66cSDavid du Colombier 10485e96a66cSDavid du Colombier static void 10495e96a66cSDavid du Colombier fsysPrintStat(char *prefix, char *file, DirEntry *de) 10505e96a66cSDavid du Colombier { 10515e96a66cSDavid du Colombier char buf[64]; 10525e96a66cSDavid du Colombier 10535e96a66cSDavid du Colombier if(prefix == nil) 10545e96a66cSDavid du Colombier prefix = ""; 10555e96a66cSDavid du Colombier consPrint("%sstat %q %q %q %q %s %llud\n", prefix, 10565e96a66cSDavid du Colombier file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size); 10575e96a66cSDavid du Colombier } 10585e96a66cSDavid du Colombier 10595e96a66cSDavid du Colombier static int 10605e96a66cSDavid du Colombier fsysStat(Fsys* fsys, int argc, char* argv[]) 10615e96a66cSDavid du Colombier { 10625e96a66cSDavid du Colombier int i; 10635e96a66cSDavid du Colombier File *f; 10645e96a66cSDavid du Colombier DirEntry de; 10655e96a66cSDavid du Colombier char *usage = "usage: [fsys name] stat files..."; 10665e96a66cSDavid du Colombier 10675e96a66cSDavid du Colombier ARGBEGIN{ 10685e96a66cSDavid du Colombier default: 10695e96a66cSDavid du Colombier return cliError(usage); 10705e96a66cSDavid du Colombier }ARGEND 10715e96a66cSDavid du Colombier 10725e96a66cSDavid du Colombier if(argc == 0) 10735e96a66cSDavid du Colombier return cliError(usage); 10745e96a66cSDavid du Colombier 10755e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 10765e96a66cSDavid du Colombier for(i=0; i<argc; i++){ 10775e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[i])) == nil){ 10785e96a66cSDavid du Colombier consPrint("%s: %R\n"); 10795e96a66cSDavid du Colombier continue; 10805e96a66cSDavid du Colombier } 10815e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 10825e96a66cSDavid du Colombier consPrint("%s: %R\n"); 10835e96a66cSDavid du Colombier fileDecRef(f); 10845e96a66cSDavid du Colombier continue; 10855e96a66cSDavid du Colombier } 10865e96a66cSDavid du Colombier fsysPrintStat("\t", argv[i], &de); 10875e96a66cSDavid du Colombier deCleanup(&de); 10885e96a66cSDavid du Colombier fileDecRef(f); 10895e96a66cSDavid du Colombier } 10905e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 10915e96a66cSDavid du Colombier return 1; 10925e96a66cSDavid du Colombier } 10935e96a66cSDavid du Colombier 10945e96a66cSDavid du Colombier static int 10955e96a66cSDavid du Colombier fsysWstat(Fsys *fsys, int argc, char* argv[]) 10965e96a66cSDavid du Colombier { 10975e96a66cSDavid du Colombier File *f; 10985e96a66cSDavid du Colombier char *p; 10995e96a66cSDavid du Colombier DirEntry de; 11005e96a66cSDavid du Colombier char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n" 11015e96a66cSDavid du Colombier "\tuse - for any field to mean don't change"; 11025e96a66cSDavid du Colombier 11035e96a66cSDavid du Colombier ARGBEGIN{ 11045e96a66cSDavid du Colombier default: 11055e96a66cSDavid du Colombier return cliError(usage); 11065e96a66cSDavid du Colombier }ARGEND 11075e96a66cSDavid du Colombier 11085e96a66cSDavid du Colombier if(argc != 6) 11095e96a66cSDavid du Colombier return cliError(usage); 11105e96a66cSDavid du Colombier 11115e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 11125e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[0])) == nil){ 11135e96a66cSDavid du Colombier vtSetError("console wstat - walk - %R"); 11145e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11155e96a66cSDavid du Colombier return 0; 11165e96a66cSDavid du Colombier } 11175e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 11185e96a66cSDavid du Colombier vtSetError("console wstat - stat - %R"); 11195e96a66cSDavid du Colombier fileDecRef(f); 11205e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11215e96a66cSDavid du Colombier return 0; 11225e96a66cSDavid du Colombier } 11235e96a66cSDavid du Colombier fsysPrintStat("\told: w", argv[0], &de); 11245e96a66cSDavid du Colombier 11255e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0){ 11265e96a66cSDavid du Colombier if(!validFileName(argv[1])){ 11275e96a66cSDavid du Colombier vtSetError("console wstat - bad elem"); 11285e96a66cSDavid du Colombier goto error; 11295e96a66cSDavid du Colombier } 11305e96a66cSDavid du Colombier vtMemFree(de.elem); 11315e96a66cSDavid du Colombier de.elem = vtStrDup(argv[1]); 11325e96a66cSDavid du Colombier } 11335e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0){ 11345e96a66cSDavid du Colombier if(!validUserName(argv[2])){ 11355e96a66cSDavid du Colombier vtSetError("console wstat - bad uid"); 11365e96a66cSDavid du Colombier goto error; 11375e96a66cSDavid du Colombier } 11385e96a66cSDavid du Colombier vtMemFree(de.uid); 11395e96a66cSDavid du Colombier de.uid = vtStrDup(argv[2]); 11405e96a66cSDavid du Colombier } 11415e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0){ 11425e96a66cSDavid du Colombier if(!validUserName(argv[3])){ 11435e96a66cSDavid du Colombier vtSetError("console wstat - bad gid"); 11445e96a66cSDavid du Colombier goto error; 11455e96a66cSDavid du Colombier } 11465e96a66cSDavid du Colombier vtMemFree(de.gid); 11475e96a66cSDavid du Colombier de.gid = vtStrDup(argv[3]); 11485e96a66cSDavid du Colombier } 11495e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0){ 11505e96a66cSDavid du Colombier if(!fsysParseMode(argv[4], &de.mode)){ 11515e96a66cSDavid du Colombier vtSetError("console wstat - bad mode"); 11525e96a66cSDavid du Colombier goto error; 11535e96a66cSDavid du Colombier } 11545e96a66cSDavid du Colombier } 11555e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0){ 11565e96a66cSDavid du Colombier de.size = strtoull(argv[5], &p, 0); 11575e96a66cSDavid du Colombier if(argv[5][0] == '\0' || *p != '\0' || de.size < 0){ 11585e96a66cSDavid du Colombier vtSetError("console wstat - bad length"); 11595e96a66cSDavid du Colombier goto error; 11605e96a66cSDavid du Colombier } 11615e96a66cSDavid du Colombier } 11625e96a66cSDavid du Colombier 11635e96a66cSDavid du Colombier if(!fileSetDir(f, &de, uidadm)){ 11645e96a66cSDavid du Colombier vtSetError("console wstat - %R"); 11655e96a66cSDavid du Colombier goto error; 11665e96a66cSDavid du Colombier } 11675e96a66cSDavid du Colombier deCleanup(&de); 11685e96a66cSDavid du Colombier 11695e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 11705e96a66cSDavid du Colombier vtSetError("console wstat - stat2 - %R"); 11715e96a66cSDavid du Colombier goto error; 11725e96a66cSDavid du Colombier } 11735e96a66cSDavid du Colombier fsysPrintStat("\tnew: w", argv[0], &de); 11745e96a66cSDavid du Colombier deCleanup(&de); 11755e96a66cSDavid du Colombier fileDecRef(f); 11765e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11775e96a66cSDavid du Colombier 11785e96a66cSDavid du Colombier return 1; 11795e96a66cSDavid du Colombier 11805e96a66cSDavid du Colombier error: 11815e96a66cSDavid du Colombier deCleanup(&de); /* okay to do this twice */ 11825e96a66cSDavid du Colombier fileDecRef(f); 11835e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11845e96a66cSDavid du Colombier return 0; 11855e96a66cSDavid du Colombier } 11865e96a66cSDavid du Colombier 11875e96a66cSDavid du Colombier static int 11885e96a66cSDavid du Colombier fsysVenti(char* name, int argc, char* argv[]) 11895e96a66cSDavid du Colombier { 11905e96a66cSDavid du Colombier int r; 11915e96a66cSDavid du Colombier char *host; 11925e96a66cSDavid du Colombier char *usage = "usage: [fsys name] venti [address]"; 11935e96a66cSDavid du Colombier Fsys *fsys; 11945e96a66cSDavid du Colombier 11955e96a66cSDavid du Colombier ARGBEGIN{ 11965e96a66cSDavid du Colombier default: 11975e96a66cSDavid du Colombier return cliError(usage); 11985e96a66cSDavid du Colombier }ARGEND 11995e96a66cSDavid du Colombier 12005e96a66cSDavid du Colombier if(argc == 0) 12015e96a66cSDavid du Colombier host = nil; 12025e96a66cSDavid du Colombier else if(argc == 1) 12035e96a66cSDavid du Colombier host = argv[0]; 12045e96a66cSDavid du Colombier else 12055e96a66cSDavid du Colombier return cliError(usage); 12065e96a66cSDavid du Colombier 12075e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 12085e96a66cSDavid du Colombier return 0; 12095e96a66cSDavid du Colombier 12105e96a66cSDavid du Colombier vtLock(fsys->lock); 12115e96a66cSDavid du Colombier if(host == nil) 12125e96a66cSDavid du Colombier host = fsys->venti; 12135e96a66cSDavid du Colombier else{ 12145e96a66cSDavid du Colombier vtMemFree(fsys->venti); 12155e96a66cSDavid du Colombier if(host[0]) 12165e96a66cSDavid du Colombier fsys->venti = vtStrDup(host); 12175e96a66cSDavid du Colombier else{ 12185e96a66cSDavid du Colombier host = nil; 12195e96a66cSDavid du Colombier fsys->venti = nil; 12205e96a66cSDavid du Colombier } 12215e96a66cSDavid du Colombier } 12225e96a66cSDavid du Colombier 12235e96a66cSDavid du Colombier /* already open: do a redial */ 12245e96a66cSDavid du Colombier if(fsys->fs != nil){ 12255e96a66cSDavid du Colombier r = 1; 12265e96a66cSDavid du Colombier if(!vtRedial(fsys->session, host) 12275e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 12285e96a66cSDavid du Colombier r = 0; 12295e96a66cSDavid du Colombier vtUnlock(fsys->lock); 12305e96a66cSDavid du Colombier fsysPut(fsys); 12315e96a66cSDavid du Colombier return r; 12325e96a66cSDavid du Colombier } 12335e96a66cSDavid du Colombier 12345e96a66cSDavid du Colombier /* not yet open: try to dial */ 12355e96a66cSDavid du Colombier if(fsys->session) 12365e96a66cSDavid du Colombier vtClose(fsys->session); 12375e96a66cSDavid du Colombier r = 1; 12385e96a66cSDavid du Colombier if((fsys->session = vtDial(host, 0)) == nil 12395e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 12405e96a66cSDavid du Colombier r = 0; 12415e96a66cSDavid du Colombier vtUnlock(fsys->lock); 12425e96a66cSDavid du Colombier fsysPut(fsys); 12435e96a66cSDavid du Colombier return r; 12445e96a66cSDavid du Colombier } 12455e96a66cSDavid du Colombier 12465e96a66cSDavid du Colombier static int 12475e96a66cSDavid du Colombier fsysOpen(char* name, int argc, char* argv[]) 12485e96a66cSDavid du Colombier { 12495e96a66cSDavid du Colombier char *p, *host; 12505e96a66cSDavid du Colombier Fsys *fsys; 12515e96a66cSDavid du Colombier long ncache; 12525e96a66cSDavid du Colombier int noauth, noperm, rflag, wstatallow; 12535e96a66cSDavid du Colombier char *usage = "usage: fsys name open [-APWr] [-c ncache]"; 12545e96a66cSDavid du Colombier 12555e96a66cSDavid du Colombier ncache = 1000; 12565e96a66cSDavid du Colombier noauth = noperm = wstatallow = 0; 12575e96a66cSDavid du Colombier rflag = OReadWrite; 12585e96a66cSDavid du Colombier 12595e96a66cSDavid du Colombier ARGBEGIN{ 12605e96a66cSDavid du Colombier default: 12615e96a66cSDavid du Colombier return cliError(usage); 12625e96a66cSDavid du Colombier case 'A': 12635e96a66cSDavid du Colombier noauth = 1; 12645e96a66cSDavid du Colombier break; 12655e96a66cSDavid du Colombier case 'P': 12665e96a66cSDavid du Colombier noperm = 1; 12675e96a66cSDavid du Colombier break; 12685e96a66cSDavid du Colombier case 'W': 12695e96a66cSDavid du Colombier wstatallow = 1; 12705e96a66cSDavid du Colombier break; 12715e96a66cSDavid du Colombier case 'c': 12725e96a66cSDavid du Colombier p = ARGF(); 12735e96a66cSDavid du Colombier if(p == nil) 12745e96a66cSDavid du Colombier return cliError(usage); 12755e96a66cSDavid du Colombier ncache = strtol(argv[0], &p, 0); 12765e96a66cSDavid du Colombier if(ncache <= 0 || p == argv[0] || *p != '\0') 12775e96a66cSDavid du Colombier return cliError(usage); 12785e96a66cSDavid du Colombier break; 12795e96a66cSDavid du Colombier case 'r': 12805e96a66cSDavid du Colombier rflag = OReadOnly; 12815e96a66cSDavid du Colombier break; 12825e96a66cSDavid du Colombier }ARGEND 12835e96a66cSDavid du Colombier if(argc) 12845e96a66cSDavid du Colombier return cliError(usage); 12855e96a66cSDavid du Colombier 12865e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 12875e96a66cSDavid du Colombier return 0; 12885e96a66cSDavid du Colombier 12895e96a66cSDavid du Colombier vtLock(fsys->lock); 12905e96a66cSDavid du Colombier if(fsys->fs != nil){ 12915e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 12925e96a66cSDavid du Colombier vtUnlock(fsys->lock); 12935e96a66cSDavid du Colombier fsysPut(fsys); 12945e96a66cSDavid du Colombier return 0; 12955e96a66cSDavid du Colombier } 12965e96a66cSDavid du Colombier 12975e96a66cSDavid du Colombier if(fsys->session == nil){ 12985e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 12995e96a66cSDavid du Colombier host = fsys->venti; 13005e96a66cSDavid du Colombier else 13015e96a66cSDavid du Colombier host = nil; 13025e96a66cSDavid du Colombier fsys->session = vtDial(host, 1); 13035e96a66cSDavid du Colombier if(!vtConnect(fsys->session, nil)) 130461201b97SDavid du Colombier fprint(2, "warning: connecting to venti: %R\n"); 13055e96a66cSDavid du Colombier } 13065e96a66cSDavid du Colombier if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){ 13075e96a66cSDavid du Colombier vtUnlock(fsys->lock); 13085e96a66cSDavid du Colombier fsysPut(fsys); 13095e96a66cSDavid du Colombier return 0; 13105e96a66cSDavid du Colombier } 13115e96a66cSDavid du Colombier fsys->noauth = noauth; 13125e96a66cSDavid du Colombier fsys->noperm = noperm; 13135e96a66cSDavid du Colombier fsys->wstatallow = wstatallow; 13145e96a66cSDavid du Colombier vtUnlock(fsys->lock); 13155e96a66cSDavid du Colombier fsysPut(fsys); 13165e96a66cSDavid du Colombier 1317*81cf8742SDavid du Colombier if(strcmp(name, "main") == 0) 1318*81cf8742SDavid du Colombier usersFileRead(nil); 1319*81cf8742SDavid du Colombier 13205e96a66cSDavid du Colombier return 1; 13215e96a66cSDavid du Colombier } 13225e96a66cSDavid du Colombier 13235e96a66cSDavid du Colombier static int 13245e96a66cSDavid du Colombier fsysUnconfig(char* name, int argc, char* argv[]) 13255e96a66cSDavid du Colombier { 13265e96a66cSDavid du Colombier Fsys *fsys, **fp; 13275e96a66cSDavid du Colombier char *usage = "usage: fsys name unconfig"; 13285e96a66cSDavid du Colombier 13295e96a66cSDavid du Colombier ARGBEGIN{ 13305e96a66cSDavid du Colombier default: 13315e96a66cSDavid du Colombier return cliError(usage); 13325e96a66cSDavid du Colombier }ARGEND 13335e96a66cSDavid du Colombier if(argc) 13345e96a66cSDavid du Colombier return cliError(usage); 13355e96a66cSDavid du Colombier 13365e96a66cSDavid du Colombier vtLock(sbox.lock); 13375e96a66cSDavid du Colombier fp = &sbox.head; 13385e96a66cSDavid du Colombier for(fsys = *fp; fsys != nil; fsys = fsys->next){ 13395e96a66cSDavid du Colombier if(strcmp(fsys->name, name) == 0) 13405e96a66cSDavid du Colombier break; 13415e96a66cSDavid du Colombier fp = &fsys->next; 13425e96a66cSDavid du Colombier } 13435e96a66cSDavid du Colombier if(fsys == nil){ 13445e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 13455e96a66cSDavid du Colombier vtUnlock(sbox.lock); 13465e96a66cSDavid du Colombier return 0; 13475e96a66cSDavid du Colombier } 13485e96a66cSDavid du Colombier if(fsys->ref != 0 || fsys->fs != nil){ 13495e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 13505e96a66cSDavid du Colombier vtUnlock(sbox.lock); 13515e96a66cSDavid du Colombier return 0; 13525e96a66cSDavid du Colombier } 13535e96a66cSDavid du Colombier *fp = fsys->next; 13545e96a66cSDavid du Colombier vtUnlock(sbox.lock); 13555e96a66cSDavid du Colombier 13565e96a66cSDavid du Colombier if(fsys->session != nil){ 13575e96a66cSDavid du Colombier vtClose(fsys->session); 13585e96a66cSDavid du Colombier vtFree(fsys->session); 13595e96a66cSDavid du Colombier } 13605e96a66cSDavid du Colombier if(fsys->venti != nil) 13615e96a66cSDavid du Colombier vtMemFree(fsys->venti); 13625e96a66cSDavid du Colombier if(fsys->dev != nil) 13635e96a66cSDavid du Colombier vtMemFree(fsys->dev); 13645e96a66cSDavid du Colombier if(fsys->name != nil) 13655e96a66cSDavid du Colombier vtMemFree(fsys->name); 13665e96a66cSDavid du Colombier vtMemFree(fsys); 13675e96a66cSDavid du Colombier 13685e96a66cSDavid du Colombier return 1; 13695e96a66cSDavid du Colombier } 13705e96a66cSDavid du Colombier 13715e96a66cSDavid du Colombier static int 13725e96a66cSDavid du Colombier fsysConfig(char* name, int argc, char* argv[]) 13735e96a66cSDavid du Colombier { 13745e96a66cSDavid du Colombier Fsys *fsys; 13755e96a66cSDavid du Colombier char *usage = "usage: fsys name config dev"; 13765e96a66cSDavid du Colombier 13775e96a66cSDavid du Colombier ARGBEGIN{ 13785e96a66cSDavid du Colombier default: 13795e96a66cSDavid du Colombier return cliError(usage); 13805e96a66cSDavid du Colombier }ARGEND 13815e96a66cSDavid du Colombier if(argc != 1) 13825e96a66cSDavid du Colombier return cliError(usage); 13835e96a66cSDavid du Colombier 13845e96a66cSDavid du Colombier if((fsys = _fsysGet(argv[0])) != nil){ 13855e96a66cSDavid du Colombier vtLock(fsys->lock); 13865e96a66cSDavid du Colombier if(fsys->fs != nil){ 13875e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 13885e96a66cSDavid du Colombier vtUnlock(fsys->lock); 13895e96a66cSDavid du Colombier fsysPut(fsys); 13905e96a66cSDavid du Colombier return 0; 13915e96a66cSDavid du Colombier } 13925e96a66cSDavid du Colombier vtMemFree(fsys->dev); 13935e96a66cSDavid du Colombier fsys->dev = vtStrDup(argv[0]); 13945e96a66cSDavid du Colombier vtUnlock(fsys->lock); 13955e96a66cSDavid du Colombier } 13965e96a66cSDavid du Colombier else if((fsys = fsysAlloc(name, argv[0])) == nil) 13975e96a66cSDavid du Colombier return 0; 13985e96a66cSDavid du Colombier 13995e96a66cSDavid du Colombier fsysPut(fsys); 14005e96a66cSDavid du Colombier 14015e96a66cSDavid du Colombier return 1; 14025e96a66cSDavid du Colombier } 14035e96a66cSDavid du Colombier 14045e96a66cSDavid du Colombier static struct { 14055e96a66cSDavid du Colombier char* cmd; 14065e96a66cSDavid du Colombier int (*f)(Fsys*, int, char**); 14075e96a66cSDavid du Colombier int (*f1)(char*, int, char**); 14085e96a66cSDavid du Colombier } fsyscmd[] = { 14095e96a66cSDavid du Colombier { "close", fsysClose, }, 14105e96a66cSDavid du Colombier { "config", nil, fsysConfig, }, 14115e96a66cSDavid du Colombier { "open", nil, fsysOpen, }, 14125e96a66cSDavid du Colombier { "unconfig", nil, fsysUnconfig, }, 14135e96a66cSDavid du Colombier { "venti", nil, fsysVenti, }, 14145e96a66cSDavid du Colombier 14155e96a66cSDavid du Colombier { "bfree", fsysBfree, }, 14165e96a66cSDavid du Colombier { "block", fsysBlock, }, 14175e96a66cSDavid du Colombier { "clre", fsysClre, }, 14185e96a66cSDavid du Colombier { "clri", fsysClri, }, 14195e96a66cSDavid du Colombier { "clrp", fsysClrp, }, 14205e96a66cSDavid du Colombier { "create", fsysCreate, }, 14217abd426fSDavid du Colombier { "df", fsysDf, }, 14225e96a66cSDavid du Colombier { "epoch", fsysEpoch, }, 1423*81cf8742SDavid du Colombier { "halt", fsysHalt, }, 14245e96a66cSDavid du Colombier { "label", fsysLabel, }, 14255e96a66cSDavid du Colombier { "remove", fsysRemove, }, 14265e96a66cSDavid du Colombier { "snap", fsysSnap, }, 14275e96a66cSDavid du Colombier { "snaptime", fsysSnapTime, }, 14285e96a66cSDavid du Colombier { "stat", fsysStat, }, 14295e96a66cSDavid du Colombier { "sync", fsysSync, }, 1430*81cf8742SDavid du Colombier { "unhalt", fsysUnhalt, }, 14315e96a66cSDavid du Colombier { "wstat", fsysWstat, }, 14325e96a66cSDavid du Colombier { "vac", fsysVac, }, 14335e96a66cSDavid du Colombier 14345e96a66cSDavid du Colombier { nil, nil, }, 14355e96a66cSDavid du Colombier }; 14365e96a66cSDavid du Colombier 14375e96a66cSDavid du Colombier static int 1438*81cf8742SDavid du Colombier fsysXXX1(Fsys *fsys, int i, int argc, char* argv[]) 1439*81cf8742SDavid du Colombier { 1440*81cf8742SDavid du Colombier int r; 1441*81cf8742SDavid du Colombier 1442*81cf8742SDavid du Colombier vtLock(fsys->lock); 1443*81cf8742SDavid du Colombier if(fsys->fs == nil){ 1444*81cf8742SDavid du Colombier vtUnlock(fsys->lock); 1445*81cf8742SDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 1446*81cf8742SDavid du Colombier return 0; 1447*81cf8742SDavid du Colombier } 1448*81cf8742SDavid du Colombier 1449*81cf8742SDavid du Colombier if(fsys->fs->halted && fsyscmd[i].f != fsysUnhalt){ 1450*81cf8742SDavid du Colombier vtSetError("file system %s is halted", fsys->name); 1451*81cf8742SDavid du Colombier vtUnlock(fsys->lock); 1452*81cf8742SDavid du Colombier return 0; 1453*81cf8742SDavid du Colombier } 1454*81cf8742SDavid du Colombier 1455*81cf8742SDavid du Colombier r = (*fsyscmd[i].f)(fsys, argc, argv); 1456*81cf8742SDavid du Colombier vtUnlock(fsys->lock); 1457*81cf8742SDavid du Colombier return r; 1458*81cf8742SDavid du Colombier } 1459*81cf8742SDavid du Colombier 1460*81cf8742SDavid du Colombier static int 14615e96a66cSDavid du Colombier fsysXXX(char* name, int argc, char* argv[]) 14625e96a66cSDavid du Colombier { 14635e96a66cSDavid du Colombier int i, r; 14645e96a66cSDavid du Colombier Fsys *fsys; 14655e96a66cSDavid du Colombier 14665e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 14675e96a66cSDavid du Colombier if(strcmp(fsyscmd[i].cmd, argv[0]) == 0) 14685e96a66cSDavid du Colombier break; 14695e96a66cSDavid du Colombier } 14705e96a66cSDavid du Colombier 14715e96a66cSDavid du Colombier if(fsyscmd[i].cmd == nil){ 14725e96a66cSDavid du Colombier vtSetError("unknown command - '%s'", argv[0]); 14735e96a66cSDavid du Colombier return 0; 14745e96a66cSDavid du Colombier } 14755e96a66cSDavid du Colombier 14765e96a66cSDavid du Colombier /* some commands want the name... */ 1477*81cf8742SDavid du Colombier if(fsyscmd[i].f1 != nil){ 1478*81cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 1479*81cf8742SDavid du Colombier vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]); 14805e96a66cSDavid du Colombier return 0; 14815e96a66cSDavid du Colombier } 1482*81cf8742SDavid du Colombier return (*fsyscmd[i].f1)(name, argc, argv); 1483*81cf8742SDavid du Colombier } 14845e96a66cSDavid du Colombier 1485*81cf8742SDavid du Colombier /* ... but most commands want the Fsys */ 1486*81cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 1487*81cf8742SDavid du Colombier r = 1; 1488*81cf8742SDavid du Colombier vtRLock(sbox.lock); 1489*81cf8742SDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 1490*81cf8742SDavid du Colombier fsys->ref++; 1491*81cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv) && r; 1492*81cf8742SDavid du Colombier fsys->ref--; 1493*81cf8742SDavid du Colombier } 1494*81cf8742SDavid du Colombier vtRUnlock(sbox.lock); 1495*81cf8742SDavid du Colombier }else{ 1496*81cf8742SDavid du Colombier if((fsys = _fsysGet(name)) == nil) 1497*81cf8742SDavid du Colombier return 0; 1498*81cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv); 14995e96a66cSDavid du Colombier fsysPut(fsys); 1500*81cf8742SDavid du Colombier } 15015e96a66cSDavid du Colombier return r; 15025e96a66cSDavid du Colombier } 15035e96a66cSDavid du Colombier 15045e96a66cSDavid du Colombier static int 15055e96a66cSDavid du Colombier cmdFsysXXX(int argc, char* argv[]) 15065e96a66cSDavid du Colombier { 15075e96a66cSDavid du Colombier char *name; 15085e96a66cSDavid du Colombier 15095e96a66cSDavid du Colombier if((name = sbox.curfsys) == nil){ 15105e96a66cSDavid du Colombier vtSetError(EFsysNoCurrent, argv[0]); 15115e96a66cSDavid du Colombier return 0; 15125e96a66cSDavid du Colombier } 15135e96a66cSDavid du Colombier 15145e96a66cSDavid du Colombier return fsysXXX(name, argc, argv); 15155e96a66cSDavid du Colombier } 15165e96a66cSDavid du Colombier 15175e96a66cSDavid du Colombier static int 15185e96a66cSDavid du Colombier cmdFsys(int argc, char* argv[]) 15195e96a66cSDavid du Colombier { 15205e96a66cSDavid du Colombier Fsys *fsys; 15215e96a66cSDavid du Colombier char *usage = "usage: fsys [name ...]"; 15225e96a66cSDavid du Colombier 15235e96a66cSDavid du Colombier ARGBEGIN{ 15245e96a66cSDavid du Colombier default: 15255e96a66cSDavid du Colombier return cliError(usage); 15265e96a66cSDavid du Colombier }ARGEND 15275e96a66cSDavid du Colombier 15285e96a66cSDavid du Colombier if(argc == 0){ 15295e96a66cSDavid du Colombier vtRLock(sbox.lock); 15305e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next) 15315e96a66cSDavid du Colombier consPrint("\t%s\n", fsys->name); 15325e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 15335e96a66cSDavid du Colombier return 1; 15345e96a66cSDavid du Colombier } 15355e96a66cSDavid du Colombier if(argc == 1){ 1536*81cf8742SDavid du Colombier fsys = nil; 1537*81cf8742SDavid du Colombier if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil) 15385e96a66cSDavid du Colombier return 0; 1539*81cf8742SDavid du Colombier sbox.curfsys = vtStrDup(argv[0]); 15405e96a66cSDavid du Colombier consPrompt(sbox.curfsys); 1541*81cf8742SDavid du Colombier if(fsys) 15425e96a66cSDavid du Colombier fsysPut(fsys); 15435e96a66cSDavid du Colombier return 1; 15445e96a66cSDavid du Colombier } 15455e96a66cSDavid du Colombier 15465e96a66cSDavid du Colombier return fsysXXX(argv[0], argc-1, argv+1); 15475e96a66cSDavid du Colombier } 15485e96a66cSDavid du Colombier 15495e96a66cSDavid du Colombier int 15505e96a66cSDavid du Colombier fsysInit(void) 15515e96a66cSDavid du Colombier { 15525e96a66cSDavid du Colombier int i; 15535e96a66cSDavid du Colombier 15545e96a66cSDavid du Colombier fmtinstall('H', encodefmt); 15555e96a66cSDavid du Colombier fmtinstall('V', scoreFmt); 15565e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt); 15575e96a66cSDavid du Colombier fmtinstall('L', labelFmt); 15585e96a66cSDavid du Colombier 15595e96a66cSDavid du Colombier sbox.lock = vtLockAlloc(); 15605e96a66cSDavid du Colombier 15615e96a66cSDavid du Colombier cliAddCmd("fsys", cmdFsys); 15625e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 15635e96a66cSDavid du Colombier if(fsyscmd[i].f != nil) 15645e96a66cSDavid du Colombier cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX); 15655e96a66cSDavid du Colombier } 15665e96a66cSDavid du Colombier /* the venti cmd is special: the fs can be either open or closed */ 15675e96a66cSDavid du Colombier cliAddCmd("venti", cmdFsysXXX); 15685e96a66cSDavid du Colombier cliAddCmd("printconfig", cmdPrintConfig); 15695e96a66cSDavid du Colombier 15705e96a66cSDavid du Colombier return 1; 15715e96a66cSDavid du Colombier } 1572