15e96a66cSDavid du Colombier #include "stdinc.h" 25e96a66cSDavid du Colombier #include "dat.h" 35e96a66cSDavid du Colombier #include "fns.h" 45e96a66cSDavid du Colombier #include "9.h" 55e96a66cSDavid du Colombier 65e96a66cSDavid du Colombier typedef struct Fsys Fsys; 75e96a66cSDavid du Colombier 87abd426fSDavid du Colombier struct Fsys { 95e96a66cSDavid du Colombier VtLock* lock; 105e96a66cSDavid du Colombier 11*0c6300e7SDavid du Colombier char* name; /* copy here & Fs to ease error reporting */ 125e96a66cSDavid du Colombier char* dev; 135e96a66cSDavid du Colombier char* venti; 145e96a66cSDavid du Colombier 155e96a66cSDavid du Colombier Fs* fs; 165e96a66cSDavid du Colombier VtSession* session; 175e96a66cSDavid du Colombier int ref; 185e96a66cSDavid du Colombier 195e96a66cSDavid du Colombier int noauth; 205e96a66cSDavid du Colombier int noperm; 215e96a66cSDavid du Colombier int wstatallow; 225e96a66cSDavid du Colombier 235e96a66cSDavid du Colombier Fsys* next; 247abd426fSDavid du Colombier }; 255e96a66cSDavid du Colombier 265e96a66cSDavid du Colombier static struct { 275e96a66cSDavid du Colombier VtLock* lock; 285e96a66cSDavid du Colombier Fsys* head; 295e96a66cSDavid du Colombier Fsys* tail; 305e96a66cSDavid du Colombier 315e96a66cSDavid du Colombier char* curfsys; 325e96a66cSDavid du Colombier } sbox; 335e96a66cSDavid du Colombier 345e96a66cSDavid du Colombier static char *_argv0; 355e96a66cSDavid du Colombier #define argv0 _argv0 365e96a66cSDavid du Colombier 3781cf8742SDavid du Colombier static char FsysAll[] = "all"; 3881cf8742SDavid du Colombier 395e96a66cSDavid du Colombier static char EFsysBusy[] = "fsys: '%s' busy"; 405e96a66cSDavid du Colombier static char EFsysExists[] = "fsys: '%s' already exists"; 415e96a66cSDavid du Colombier static char EFsysNoCurrent[] = "fsys: no current fsys"; 425e96a66cSDavid du Colombier static char EFsysNotFound[] = "fsys: '%s' not found"; 435e96a66cSDavid du Colombier static char EFsysNotOpen[] = "fsys: '%s' not open"; 445e96a66cSDavid du Colombier 455e96a66cSDavid du Colombier static Fsys* 465e96a66cSDavid du Colombier _fsysGet(char* name) 475e96a66cSDavid du Colombier { 485e96a66cSDavid du Colombier Fsys *fsys; 495e96a66cSDavid du Colombier 505e96a66cSDavid du Colombier if(name == nil || name[0] == '\0') 515e96a66cSDavid du Colombier name = "main"; 525e96a66cSDavid du Colombier 535e96a66cSDavid du Colombier vtRLock(sbox.lock); 545e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 555e96a66cSDavid du Colombier if(strcmp(name, fsys->name) == 0){ 565e96a66cSDavid du Colombier fsys->ref++; 575e96a66cSDavid du Colombier break; 585e96a66cSDavid du Colombier } 595e96a66cSDavid du Colombier } 60dc5a79c1SDavid du Colombier vtRUnlock(sbox.lock); 615e96a66cSDavid du Colombier if(fsys == nil) 625e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 635e96a66cSDavid du Colombier return fsys; 645e96a66cSDavid du Colombier } 655e96a66cSDavid du Colombier 665e96a66cSDavid du Colombier static int 675e96a66cSDavid du Colombier cmdPrintConfig(int argc, char* argv[]) 685e96a66cSDavid du Colombier { 695e96a66cSDavid du Colombier Fsys *fsys; 705e96a66cSDavid du Colombier char *usage = "usage: printconfig"; 715e96a66cSDavid du Colombier 725e96a66cSDavid du Colombier ARGBEGIN{ 735e96a66cSDavid du Colombier default: 745e96a66cSDavid du Colombier return cliError(usage); 755e96a66cSDavid du Colombier }ARGEND 765e96a66cSDavid du Colombier 775e96a66cSDavid du Colombier if(argc) 785e96a66cSDavid du Colombier return cliError(usage); 795e96a66cSDavid du Colombier 805e96a66cSDavid du Colombier vtRLock(sbox.lock); 815e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 825e96a66cSDavid du Colombier consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev); 835e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 84*0c6300e7SDavid du Colombier consPrint("\tfsys %s venti %q\n", fsys->name, 85*0c6300e7SDavid du Colombier fsys->venti); 865e96a66cSDavid du Colombier } 875e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 885e96a66cSDavid du Colombier return 1; 895e96a66cSDavid du Colombier } 905e96a66cSDavid du Colombier 915e96a66cSDavid du Colombier Fsys* 925e96a66cSDavid du Colombier fsysGet(char* name) 935e96a66cSDavid du Colombier { 945e96a66cSDavid du Colombier Fsys *fsys; 955e96a66cSDavid du Colombier 965e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 975e96a66cSDavid du Colombier return nil; 985e96a66cSDavid du Colombier 995e96a66cSDavid du Colombier vtLock(fsys->lock); 1005e96a66cSDavid du Colombier if(fsys->fs == nil){ 1015e96a66cSDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 1025e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1035e96a66cSDavid du Colombier fsysPut(fsys); 1045e96a66cSDavid du Colombier return nil; 1055e96a66cSDavid du Colombier } 1065e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1075e96a66cSDavid du Colombier 1085e96a66cSDavid du Colombier return fsys; 1095e96a66cSDavid du Colombier } 1105e96a66cSDavid du Colombier 11161201b97SDavid du Colombier char* 11261201b97SDavid du Colombier fsysGetName(Fsys* fsys) 11361201b97SDavid du Colombier { 11461201b97SDavid du Colombier return fsys->name; 11561201b97SDavid du Colombier } 11661201b97SDavid du Colombier 1175e96a66cSDavid du Colombier Fsys* 1185e96a66cSDavid du Colombier fsysIncRef(Fsys* fsys) 1195e96a66cSDavid du Colombier { 1205e96a66cSDavid du Colombier vtLock(sbox.lock); 1215e96a66cSDavid du Colombier fsys->ref++; 1225e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1235e96a66cSDavid du Colombier 1245e96a66cSDavid du Colombier return fsys; 1255e96a66cSDavid du Colombier } 1265e96a66cSDavid du Colombier 1275e96a66cSDavid du Colombier void 1285e96a66cSDavid du Colombier fsysPut(Fsys* fsys) 1295e96a66cSDavid du Colombier { 1305e96a66cSDavid du Colombier vtLock(sbox.lock); 1315e96a66cSDavid du Colombier assert(fsys->ref > 0); 1325e96a66cSDavid du Colombier fsys->ref--; 1335e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1345e96a66cSDavid du Colombier } 1355e96a66cSDavid du Colombier 1365e96a66cSDavid du Colombier Fs* 1375e96a66cSDavid du Colombier fsysGetFs(Fsys* fsys) 1385e96a66cSDavid du Colombier { 1395e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 1405e96a66cSDavid du Colombier 1415e96a66cSDavid du Colombier return fsys->fs; 1425e96a66cSDavid du Colombier } 1435e96a66cSDavid du Colombier 1445e96a66cSDavid du Colombier void 1455e96a66cSDavid du Colombier fsysFsRlock(Fsys* fsys) 1465e96a66cSDavid du Colombier { 1475e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 1485e96a66cSDavid du Colombier } 1495e96a66cSDavid du Colombier 1505e96a66cSDavid du Colombier void 1515e96a66cSDavid du Colombier fsysFsRUnlock(Fsys* fsys) 1525e96a66cSDavid du Colombier { 1535e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 1545e96a66cSDavid du Colombier } 1555e96a66cSDavid du Colombier 1565e96a66cSDavid du Colombier int 1575e96a66cSDavid du Colombier fsysNoAuthCheck(Fsys* fsys) 1585e96a66cSDavid du Colombier { 1595e96a66cSDavid du Colombier return fsys->noauth; 1605e96a66cSDavid du Colombier } 1615e96a66cSDavid du Colombier 1625e96a66cSDavid du Colombier int 1635e96a66cSDavid du Colombier fsysNoPermCheck(Fsys* fsys) 1645e96a66cSDavid du Colombier { 1655e96a66cSDavid du Colombier return fsys->noperm; 1665e96a66cSDavid du Colombier } 1675e96a66cSDavid du Colombier 1685e96a66cSDavid du Colombier int 1695e96a66cSDavid du Colombier fsysWstatAllow(Fsys* fsys) 1705e96a66cSDavid du Colombier { 1715e96a66cSDavid du Colombier return fsys->wstatallow; 1725e96a66cSDavid du Colombier } 1735e96a66cSDavid du Colombier 1745e96a66cSDavid du Colombier static char modechars[] = "YUGalLdHSATs"; 1755e96a66cSDavid du Colombier static ulong modebits[] = { 1765e96a66cSDavid du Colombier ModeSticky, 1775e96a66cSDavid du Colombier ModeSetUid, 1785e96a66cSDavid du Colombier ModeSetGid, 1795e96a66cSDavid du Colombier ModeAppend, 1805e96a66cSDavid du Colombier ModeExclusive, 1815e96a66cSDavid du Colombier ModeLink, 1825e96a66cSDavid du Colombier ModeDir, 1835e96a66cSDavid du Colombier ModeHidden, 1845e96a66cSDavid du Colombier ModeSystem, 1855e96a66cSDavid du Colombier ModeArchive, 1865e96a66cSDavid du Colombier ModeTemporary, 1875e96a66cSDavid du Colombier ModeSnapshot, 1885e96a66cSDavid du Colombier 0 1895e96a66cSDavid du Colombier }; 1905e96a66cSDavid du Colombier 1915e96a66cSDavid du Colombier char* 1925e96a66cSDavid du Colombier fsysModeString(ulong mode, char *buf) 1935e96a66cSDavid du Colombier { 1945e96a66cSDavid du Colombier int i; 1955e96a66cSDavid du Colombier char *p; 1965e96a66cSDavid du Colombier 1975e96a66cSDavid du Colombier p = buf; 1985e96a66cSDavid du Colombier for(i=0; modebits[i]; i++) 1995e96a66cSDavid du Colombier if(mode & modebits[i]) 2005e96a66cSDavid du Colombier *p++ = modechars[i]; 2015e96a66cSDavid du Colombier sprint(p, "%luo", mode&0777); 2025e96a66cSDavid du Colombier return buf; 2035e96a66cSDavid du Colombier } 2045e96a66cSDavid du Colombier 2055e96a66cSDavid du Colombier int 2065e96a66cSDavid du Colombier fsysParseMode(char* s, ulong* mode) 2075e96a66cSDavid du Colombier { 2085e96a66cSDavid du Colombier ulong x, y; 2095e96a66cSDavid du Colombier char *p; 2105e96a66cSDavid du Colombier 2115e96a66cSDavid du Colombier x = 0; 2125e96a66cSDavid du Colombier for(; *s < '0' || *s > '9'; s++){ 2135e96a66cSDavid du Colombier if(*s == 0) 2145e96a66cSDavid du Colombier return 0; 2155e96a66cSDavid du Colombier p = strchr(modechars, *s); 2165e96a66cSDavid du Colombier if(p == nil) 2175e96a66cSDavid du Colombier return 0; 2185e96a66cSDavid du Colombier x |= modebits[p-modechars]; 2195e96a66cSDavid du Colombier } 2205e96a66cSDavid du Colombier y = strtoul(s, &p, 8); 2215e96a66cSDavid du Colombier if(*p != '\0' || y > 0777) 2225e96a66cSDavid du Colombier return 0; 2235e96a66cSDavid du Colombier *mode = x|y; 2245e96a66cSDavid du Colombier return 1; 2255e96a66cSDavid du Colombier } 2265e96a66cSDavid du Colombier 2275e96a66cSDavid du Colombier File* 2285e96a66cSDavid du Colombier fsysGetRoot(Fsys* fsys, char* name) 2295e96a66cSDavid du Colombier { 2305e96a66cSDavid du Colombier File *root, *sub; 2315e96a66cSDavid du Colombier 2325e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 2335e96a66cSDavid du Colombier 2345e96a66cSDavid du Colombier root = fsGetRoot(fsys->fs); 2355e96a66cSDavid du Colombier if(name == nil || strcmp(name, "") == 0) 2365e96a66cSDavid du Colombier return root; 2375e96a66cSDavid du Colombier 2385e96a66cSDavid du Colombier sub = fileWalk(root, name); 2395e96a66cSDavid du Colombier fileDecRef(root); 2405e96a66cSDavid du Colombier 2415e96a66cSDavid du Colombier return sub; 2425e96a66cSDavid du Colombier } 2435e96a66cSDavid du Colombier 2445e96a66cSDavid du Colombier static Fsys* 2455e96a66cSDavid du Colombier fsysAlloc(char* name, char* dev) 2465e96a66cSDavid du Colombier { 2475e96a66cSDavid du Colombier Fsys *fsys; 2485e96a66cSDavid du Colombier 2495e96a66cSDavid du Colombier vtLock(sbox.lock); 2505e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 2515e96a66cSDavid du Colombier if(strcmp(fsys->name, name) != 0) 2525e96a66cSDavid du Colombier continue; 2535e96a66cSDavid du Colombier vtSetError(EFsysExists, name); 2545e96a66cSDavid du Colombier vtUnlock(sbox.lock); 2555e96a66cSDavid du Colombier return nil; 2565e96a66cSDavid du Colombier } 2575e96a66cSDavid du Colombier 2585e96a66cSDavid du Colombier fsys = vtMemAllocZ(sizeof(Fsys)); 2595e96a66cSDavid du Colombier fsys->lock = vtLockAlloc(); 2605e96a66cSDavid du Colombier fsys->name = vtStrDup(name); 2615e96a66cSDavid du Colombier fsys->dev = vtStrDup(dev); 2625e96a66cSDavid du Colombier 2635e96a66cSDavid du Colombier fsys->ref = 1; 2645e96a66cSDavid du Colombier 2655e96a66cSDavid du Colombier if(sbox.tail != nil) 2665e96a66cSDavid du Colombier sbox.tail->next = fsys; 2675e96a66cSDavid du Colombier else 2685e96a66cSDavid du Colombier sbox.head = fsys; 2695e96a66cSDavid du Colombier sbox.tail = fsys; 2705e96a66cSDavid du Colombier vtUnlock(sbox.lock); 2715e96a66cSDavid du Colombier 2725e96a66cSDavid du Colombier return fsys; 2735e96a66cSDavid du Colombier } 2745e96a66cSDavid du Colombier 2755e96a66cSDavid du Colombier static int 2765e96a66cSDavid du Colombier fsysClose(Fsys* fsys, int argc, char* argv[]) 2775e96a66cSDavid du Colombier { 2785e96a66cSDavid du Colombier char *usage = "usage: [fsys name] close"; 2795e96a66cSDavid du Colombier 2805e96a66cSDavid du Colombier ARGBEGIN{ 2815e96a66cSDavid du Colombier default: 2825e96a66cSDavid du Colombier return cliError(usage); 2835e96a66cSDavid du Colombier }ARGEND 2845e96a66cSDavid du Colombier if(argc) 2855e96a66cSDavid du Colombier return cliError(usage); 2865e96a66cSDavid du Colombier 28768412abfSDavid du Colombier return cliError("close isn't working yet; halt %s and then kill fossil", 28868412abfSDavid du Colombier fsys->name); 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 fsClose(fsys->fs); 2975e96a66cSDavid du Colombier fsys->fs = nil; 2985e96a66cSDavid du Colombier vtClose(fsys->session); 2995e96a66cSDavid du Colombier fsys->session = nil; 3005e96a66cSDavid du Colombier 3015e96a66cSDavid du Colombier if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){ 3025e96a66cSDavid du Colombier sbox.curfsys = nil; 3035e96a66cSDavid du Colombier consPrompt(nil); 3045e96a66cSDavid du Colombier } 3055e96a66cSDavid du Colombier 3065e96a66cSDavid du Colombier return 1; 30768412abfSDavid du Colombier */ 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; 334c3c4501eSDavid du Colombier char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]"; 335c3c4501eSDavid du Colombier char *src, *dst; 3365e96a66cSDavid du Colombier 337c3c4501eSDavid du Colombier src = nil; 338c3c4501eSDavid du Colombier dst = nil; 3395e96a66cSDavid du Colombier doarchive = 0; 3405e96a66cSDavid du Colombier ARGBEGIN{ 3415e96a66cSDavid du Colombier default: 3425e96a66cSDavid du Colombier return cliError(usage); 3435e96a66cSDavid du Colombier case 'a': 3445e96a66cSDavid du Colombier doarchive = 1; 3455e96a66cSDavid du Colombier break; 346c3c4501eSDavid du Colombier case 'd': 347c3c4501eSDavid du Colombier if((dst = ARGF()) == nil) 348c3c4501eSDavid du Colombier return cliError(usage); 349c3c4501eSDavid du Colombier break; 350c3c4501eSDavid du Colombier case 's': 351c3c4501eSDavid du Colombier if((src = ARGF()) == nil) 352c3c4501eSDavid du Colombier return cliError(usage); 353c3c4501eSDavid du Colombier break; 3545e96a66cSDavid du Colombier }ARGEND 3555e96a66cSDavid du Colombier if(argc) 3565e96a66cSDavid du Colombier return cliError(usage); 3575e96a66cSDavid du Colombier 358c3c4501eSDavid du Colombier if(!fsSnapshot(fsys->fs, src, dst, doarchive)) 3595e96a66cSDavid du Colombier return 0; 3605e96a66cSDavid du Colombier 3615e96a66cSDavid du Colombier return 1; 3625e96a66cSDavid du Colombier } 3635e96a66cSDavid du Colombier 3645e96a66cSDavid du Colombier static int 365dc5a79c1SDavid du Colombier fsysSnapClean(Fsys *fsys, int argc, char* argv[]) 366dc5a79c1SDavid du Colombier { 367dc5a79c1SDavid du Colombier u32int arch, snap, life; 368dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snapclean [maxminutes]\n"; 369dc5a79c1SDavid du Colombier 370dc5a79c1SDavid du Colombier ARGBEGIN{ 371dc5a79c1SDavid du Colombier default: 372dc5a79c1SDavid du Colombier return cliError(usage); 373dc5a79c1SDavid du Colombier }ARGEND 374dc5a79c1SDavid du Colombier 375dc5a79c1SDavid du Colombier if(argc > 1) 376dc5a79c1SDavid du Colombier return cliError(usage); 377dc5a79c1SDavid du Colombier if(argc == 1) 378f83f9c78SDavid du Colombier life = atoi(argv[0]); 379dc5a79c1SDavid du Colombier else 380dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 381dc5a79c1SDavid du Colombier 382dc5a79c1SDavid du Colombier fsSnapshotCleanup(fsys->fs, life); 383dc5a79c1SDavid du Colombier return 1; 384dc5a79c1SDavid du Colombier } 385dc5a79c1SDavid du Colombier 386dc5a79c1SDavid du Colombier static int 3875e96a66cSDavid du Colombier fsysSnapTime(Fsys* fsys, int argc, char* argv[]) 3885e96a66cSDavid du Colombier { 389dc5a79c1SDavid du Colombier char buf[128], *x; 390dc5a79c1SDavid du Colombier int hh, mm, changed; 391dc5a79c1SDavid du Colombier u32int arch, snap, life; 392dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]"; 3935e96a66cSDavid du Colombier 394dc5a79c1SDavid du Colombier changed = 0; 395dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 3965e96a66cSDavid du Colombier ARGBEGIN{ 3975e96a66cSDavid du Colombier case 'a': 398dc5a79c1SDavid du Colombier changed = 1; 3995e96a66cSDavid du Colombier x = ARGF(); 4005e96a66cSDavid du Colombier if(x == nil) 4015e96a66cSDavid du Colombier return cliError(usage); 4025e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 4035e96a66cSDavid du Colombier arch = ~(u32int)0; 4045e96a66cSDavid du Colombier break; 4055e96a66cSDavid du Colombier } 4065e96a66cSDavid du Colombier if(strlen(x) != 4 || strspn(x, "0123456789") != 4) 4075e96a66cSDavid du Colombier return cliError(usage); 4085e96a66cSDavid du Colombier hh = (x[0]-'0')*10 + x[1]-'0'; 4095e96a66cSDavid du Colombier mm = (x[2]-'0')*10 + x[3]-'0'; 4105e96a66cSDavid du Colombier if(hh >= 24 || mm >= 60) 4115e96a66cSDavid du Colombier return cliError(usage); 4125e96a66cSDavid du Colombier arch = hh*60+mm; 4135e96a66cSDavid du Colombier break; 4145e96a66cSDavid du Colombier case 's': 415dc5a79c1SDavid du Colombier changed = 1; 4165e96a66cSDavid du Colombier x = ARGF(); 4175e96a66cSDavid du Colombier if(x == nil) 4185e96a66cSDavid du Colombier return cliError(usage); 4195e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 4205e96a66cSDavid du Colombier snap = ~(u32int)0; 4215e96a66cSDavid du Colombier break; 4225e96a66cSDavid du Colombier } 4235e96a66cSDavid du Colombier snap = atoi(x); 4245e96a66cSDavid du Colombier break; 425dc5a79c1SDavid du Colombier case 't': 426dc5a79c1SDavid du Colombier changed = 1; 427dc5a79c1SDavid du Colombier x = ARGF(); 428dc5a79c1SDavid du Colombier if(x == nil) 429dc5a79c1SDavid du Colombier return cliError(usage); 430dc5a79c1SDavid du Colombier if(strcmp(x, "none") == 0){ 431dc5a79c1SDavid du Colombier life = ~(u32int)0; 432dc5a79c1SDavid du Colombier break; 433dc5a79c1SDavid du Colombier } 434dc5a79c1SDavid du Colombier life = atoi(x); 435dc5a79c1SDavid du Colombier break; 4365e96a66cSDavid du Colombier default: 4375e96a66cSDavid du Colombier return cliError(usage); 4385e96a66cSDavid du Colombier }ARGEND 4395e96a66cSDavid du Colombier if(argc > 0) 4405e96a66cSDavid du Colombier return cliError(usage); 4415e96a66cSDavid du Colombier 442dc5a79c1SDavid du Colombier if(changed){ 443dc5a79c1SDavid du Colombier snapSetTimes(fsys->fs->snap, arch, snap, life); 444dc5a79c1SDavid du Colombier return 1; 445dc5a79c1SDavid du Colombier } 446dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 4475e96a66cSDavid du Colombier if(arch != ~(u32int)0) 4485e96a66cSDavid du Colombier sprint(buf, "-a %02d%02d", arch/60, arch%60); 4495e96a66cSDavid du Colombier else 4505e96a66cSDavid du Colombier sprint(buf, "-a none"); 4515e96a66cSDavid du Colombier if(snap != ~(u32int)0) 4525e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s %d", snap); 4535e96a66cSDavid du Colombier else 4545e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s none"); 455dc5a79c1SDavid du Colombier if(life != ~(u32int)0) 456dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t %ud", life); 457dc5a79c1SDavid du Colombier else 458dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t none"); 4595e96a66cSDavid du Colombier consPrint("\tsnaptime %s\n", buf); 4605e96a66cSDavid du Colombier return 1; 4615e96a66cSDavid du Colombier } 4625e96a66cSDavid du Colombier 4635e96a66cSDavid du Colombier static int 4645e96a66cSDavid du Colombier fsysSync(Fsys* fsys, int argc, char* argv[]) 4655e96a66cSDavid du Colombier { 4665e96a66cSDavid du Colombier char *usage = "usage: [fsys name] sync"; 4670b9a5132SDavid du Colombier int n; 4685e96a66cSDavid du Colombier 4695e96a66cSDavid du Colombier ARGBEGIN{ 4705e96a66cSDavid du Colombier default: 4715e96a66cSDavid du Colombier return cliError(usage); 4725e96a66cSDavid du Colombier }ARGEND 4735e96a66cSDavid du Colombier if(argc > 0) 4745e96a66cSDavid du Colombier return cliError(usage); 4755e96a66cSDavid du Colombier 4760b9a5132SDavid du Colombier n = cacheDirty(fsys->fs->cache); 4775e96a66cSDavid du Colombier fsSync(fsys->fs); 4780b9a5132SDavid du Colombier consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n); 47981cf8742SDavid du Colombier return 1; 48081cf8742SDavid du Colombier } 4815e96a66cSDavid du Colombier 48281cf8742SDavid du Colombier static int 48381cf8742SDavid du Colombier fsysHalt(Fsys *fsys, int argc, char* argv[]) 48481cf8742SDavid du Colombier { 48581cf8742SDavid du Colombier char *usage = "usage: [fsys name] halt"; 48681cf8742SDavid du Colombier 48781cf8742SDavid du Colombier ARGBEGIN{ 48881cf8742SDavid du Colombier default: 48981cf8742SDavid du Colombier return cliError(usage); 49081cf8742SDavid du Colombier }ARGEND 49181cf8742SDavid du Colombier if(argc > 0) 49281cf8742SDavid du Colombier return cliError(usage); 49381cf8742SDavid du Colombier 49481cf8742SDavid du Colombier fsHalt(fsys->fs); 49581cf8742SDavid du Colombier return 1; 49681cf8742SDavid du Colombier } 49781cf8742SDavid du Colombier 49881cf8742SDavid du Colombier static int 49981cf8742SDavid du Colombier fsysUnhalt(Fsys *fsys, int argc, char* argv[]) 50081cf8742SDavid du Colombier { 50181cf8742SDavid du Colombier char *usage = "usage: [fsys name] unhalt"; 50281cf8742SDavid du Colombier 50381cf8742SDavid du Colombier ARGBEGIN{ 50481cf8742SDavid du Colombier default: 50581cf8742SDavid du Colombier return cliError(usage); 50681cf8742SDavid du Colombier }ARGEND 50781cf8742SDavid du Colombier if(argc > 0) 50881cf8742SDavid du Colombier return cliError(usage); 50981cf8742SDavid du Colombier 51081cf8742SDavid du Colombier if(!fsys->fs->halted) 51181cf8742SDavid du Colombier return cliError("file system %s not halted", fsys->name); 51281cf8742SDavid du Colombier 51381cf8742SDavid du Colombier fsUnhalt(fsys->fs); 5145e96a66cSDavid du Colombier return 1; 5155e96a66cSDavid du Colombier } 5165e96a66cSDavid du Colombier 5175e96a66cSDavid du Colombier static int 5185e96a66cSDavid du Colombier fsysRemove(Fsys* fsys, int argc, char* argv[]) 5195e96a66cSDavid du Colombier { 5205e96a66cSDavid du Colombier File *file; 5215e96a66cSDavid du Colombier char *usage = "usage: [fsys name] remove path ..."; 5225e96a66cSDavid du Colombier 5235e96a66cSDavid du Colombier ARGBEGIN{ 5245e96a66cSDavid du Colombier default: 5255e96a66cSDavid du Colombier return cliError(usage); 5265e96a66cSDavid du Colombier }ARGEND 5275e96a66cSDavid du Colombier if(argc == 0) 5285e96a66cSDavid du Colombier return cliError(usage); 5295e96a66cSDavid du Colombier 5305e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5315e96a66cSDavid du Colombier while(argc > 0){ 5325e96a66cSDavid du Colombier if((file = fileOpen(fsys->fs, argv[0])) == nil) 5335e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 5345e96a66cSDavid du Colombier else{ 5355e96a66cSDavid du Colombier if(!fileRemove(file, uidadm)) 5365e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 5375e96a66cSDavid du Colombier fileDecRef(file); 5385e96a66cSDavid du Colombier } 5395e96a66cSDavid du Colombier argc--; 5405e96a66cSDavid du Colombier argv++; 5415e96a66cSDavid du Colombier } 5425e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 5435e96a66cSDavid du Colombier 5445e96a66cSDavid du Colombier return 1; 5455e96a66cSDavid du Colombier } 5465e96a66cSDavid du Colombier 5475e96a66cSDavid du Colombier static int 5485e96a66cSDavid du Colombier fsysClri(Fsys* fsys, int argc, char* argv[]) 5495e96a66cSDavid du Colombier { 5505e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clri path ..."; 5515e96a66cSDavid du Colombier 5525e96a66cSDavid du Colombier ARGBEGIN{ 5535e96a66cSDavid du Colombier default: 5545e96a66cSDavid du Colombier return cliError(usage); 5555e96a66cSDavid du Colombier }ARGEND 5565e96a66cSDavid du Colombier if(argc == 0) 5575e96a66cSDavid du Colombier return cliError(usage); 5585e96a66cSDavid du Colombier 5595e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5605e96a66cSDavid du Colombier while(argc > 0){ 561dc5a79c1SDavid du Colombier if(!fileClriPath(fsys->fs, argv[0], uidadm)) 5625e96a66cSDavid du Colombier consPrint("clri %s: %R\n", argv[0]); 5635e96a66cSDavid du Colombier argc--; 5645e96a66cSDavid du Colombier argv++; 5655e96a66cSDavid du Colombier } 5665e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 5675e96a66cSDavid du Colombier 5685e96a66cSDavid du Colombier return 1; 5695e96a66cSDavid du Colombier } 5705e96a66cSDavid du Colombier 5715e96a66cSDavid du Colombier /* 5725e96a66cSDavid du Colombier * Inspect and edit the labels for blocks on disk. 5735e96a66cSDavid du Colombier */ 5745e96a66cSDavid du Colombier static int 5755e96a66cSDavid du Colombier fsysLabel(Fsys* fsys, int argc, char* argv[]) 5765e96a66cSDavid du Colombier { 5775e96a66cSDavid du Colombier Fs *fs; 5785e96a66cSDavid du Colombier Label l; 5795e96a66cSDavid du Colombier int n, r; 5805e96a66cSDavid du Colombier u32int addr; 5815e96a66cSDavid du Colombier Block *b, *bb; 5825e96a66cSDavid du Colombier char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]"; 5835e96a66cSDavid du Colombier 5845e96a66cSDavid du Colombier ARGBEGIN{ 5855e96a66cSDavid du Colombier default: 5865e96a66cSDavid du Colombier return cliError(usage); 5875e96a66cSDavid du Colombier }ARGEND 5885e96a66cSDavid du Colombier if(argc != 1 && argc != 6) 5895e96a66cSDavid du Colombier return cliError(usage); 5905e96a66cSDavid du Colombier 5915e96a66cSDavid du Colombier r = 0; 5925e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5935e96a66cSDavid du Colombier 5945e96a66cSDavid du Colombier fs = fsys->fs; 5955e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 5965e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 5975e96a66cSDavid du Colombier if(b == nil) 5985e96a66cSDavid du Colombier goto Out0; 5995e96a66cSDavid du Colombier 6005e96a66cSDavid du Colombier l = b->l; 6015e96a66cSDavid du Colombier consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n", 6025e96a66cSDavid du Colombier argc==6 ? "old: " : "", addr, l.type, l.state, 6035e96a66cSDavid du Colombier l.epoch, l.epochClose, l.tag); 6045e96a66cSDavid du Colombier 6055e96a66cSDavid du Colombier if(argc == 6){ 6065e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0) 6075e96a66cSDavid du Colombier l.type = atoi(argv[1]); 6085e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0) 6095e96a66cSDavid du Colombier l.state = atoi(argv[2]); 6105e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0) 6115e96a66cSDavid du Colombier l.epoch = strtoul(argv[3], 0, 0); 6125e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0) 6135e96a66cSDavid du Colombier l.epochClose = strtoul(argv[4], 0, 0); 6145e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0) 6155e96a66cSDavid du Colombier l.tag = strtoul(argv[5], 0, 0); 6165e96a66cSDavid du Colombier 6175e96a66cSDavid du Colombier consPrint("new: label %#ux %ud %ud %ud %ud %#x\n", 6185e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 6195e96a66cSDavid du Colombier bb = _blockSetLabel(b, &l); 6205e96a66cSDavid du Colombier if(bb == nil) 6215e96a66cSDavid du Colombier goto Out1; 6225e96a66cSDavid du Colombier n = 0; 6235e96a66cSDavid du Colombier for(;;){ 6245e96a66cSDavid du Colombier if(blockWrite(bb)){ 6255e96a66cSDavid du Colombier while(bb->iostate != BioClean){ 6265e96a66cSDavid du Colombier assert(bb->iostate == BioWriting); 6275e96a66cSDavid du Colombier vtSleep(bb->ioready); 6285e96a66cSDavid du Colombier } 6295e96a66cSDavid du Colombier break; 6305e96a66cSDavid du Colombier } 6315e96a66cSDavid du Colombier consPrint("blockWrite: %R\n"); 6325e96a66cSDavid du Colombier if(n++ >= 5){ 6335e96a66cSDavid du Colombier consPrint("giving up\n"); 6345e96a66cSDavid du Colombier break; 6355e96a66cSDavid du Colombier } 6365e96a66cSDavid du Colombier sleep(5*1000); 6375e96a66cSDavid du Colombier } 6385e96a66cSDavid du Colombier blockPut(bb); 6395e96a66cSDavid du Colombier } 6405e96a66cSDavid du Colombier r = 1; 6415e96a66cSDavid du Colombier Out1: 6425e96a66cSDavid du Colombier blockPut(b); 6435e96a66cSDavid du Colombier Out0: 6445e96a66cSDavid du Colombier vtRUnlock(fs->elk); 6455e96a66cSDavid du Colombier 6465e96a66cSDavid du Colombier return r; 6475e96a66cSDavid du Colombier } 6485e96a66cSDavid du Colombier 6495e96a66cSDavid du Colombier /* 6505e96a66cSDavid du Colombier * Inspect and edit the blocks on disk. 6515e96a66cSDavid du Colombier */ 6525e96a66cSDavid du Colombier static int 6535e96a66cSDavid du Colombier fsysBlock(Fsys* fsys, int argc, char* argv[]) 6545e96a66cSDavid du Colombier { 6555e96a66cSDavid du Colombier Fs *fs; 6565e96a66cSDavid du Colombier char *s; 6575e96a66cSDavid du Colombier Block *b; 6585e96a66cSDavid du Colombier uchar *buf; 6595e96a66cSDavid du Colombier u32int addr; 6605e96a66cSDavid du Colombier int c, count, i, offset; 6615e96a66cSDavid du Colombier char *usage = "usage: [fsys name] block addr offset [count [data]]"; 6625e96a66cSDavid du Colombier 6635e96a66cSDavid du Colombier ARGBEGIN{ 6645e96a66cSDavid du Colombier default: 6655e96a66cSDavid du Colombier return cliError(usage); 6665e96a66cSDavid du Colombier }ARGEND 6675e96a66cSDavid du Colombier if(argc < 2 || argc > 4) 6685e96a66cSDavid du Colombier return cliError(usage); 6695e96a66cSDavid du Colombier 6705e96a66cSDavid du Colombier fs = fsys->fs; 6715e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 6725e96a66cSDavid du Colombier offset = strtoul(argv[1], 0, 0); 6735e96a66cSDavid du Colombier if(offset < 0 || offset >= fs->blockSize){ 6745e96a66cSDavid du Colombier vtSetError("bad offset"); 6755e96a66cSDavid du Colombier return 0; 6765e96a66cSDavid du Colombier } 6775e96a66cSDavid du Colombier if(argc > 2) 6785e96a66cSDavid du Colombier count = strtoul(argv[2], 0, 0); 6795e96a66cSDavid du Colombier else 6805e96a66cSDavid du Colombier count = 100000000; 6815e96a66cSDavid du Colombier if(offset+count > fs->blockSize) 6825e96a66cSDavid du Colombier count = fs->blockSize - count; 6835e96a66cSDavid du Colombier 6845e96a66cSDavid du Colombier vtRLock(fs->elk); 6855e96a66cSDavid du Colombier 6865e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 6875e96a66cSDavid du Colombier if(b == nil){ 6885e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 6895e96a66cSDavid du Colombier vtRUnlock(fs->elk); 6905e96a66cSDavid du Colombier return 0; 6915e96a66cSDavid du Colombier } 6925e96a66cSDavid du Colombier 6935e96a66cSDavid du Colombier consPrint("\t%sblock %#ux %ud %ud %.*H\n", 6945e96a66cSDavid du Colombier argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset); 6955e96a66cSDavid du Colombier 6965e96a66cSDavid du Colombier if(argc == 4){ 6975e96a66cSDavid du Colombier s = argv[3]; 6985e96a66cSDavid du Colombier if(strlen(s) != 2*count){ 6995e96a66cSDavid du Colombier vtSetError("bad data count"); 7005e96a66cSDavid du Colombier goto Out; 7015e96a66cSDavid du Colombier } 7025e96a66cSDavid du Colombier buf = vtMemAllocZ(count); 7035e96a66cSDavid du Colombier for(i = 0; i < count*2; i++){ 7045e96a66cSDavid du Colombier if(s[i] >= '0' && s[i] <= '9') 7055e96a66cSDavid du Colombier c = s[i] - '0'; 7065e96a66cSDavid du Colombier else if(s[i] >= 'a' && s[i] <= 'f') 7075e96a66cSDavid du Colombier c = s[i] - 'a' + 10; 7085e96a66cSDavid du Colombier else if(s[i] >= 'A' && s[i] <= 'F') 7095e96a66cSDavid du Colombier c = s[i] - 'A' + 10; 7105e96a66cSDavid du Colombier else{ 7115e96a66cSDavid du Colombier vtSetError("bad hex"); 7125e96a66cSDavid du Colombier vtMemFree(buf); 7135e96a66cSDavid du Colombier goto Out; 7145e96a66cSDavid du Colombier } 7155e96a66cSDavid du Colombier if((i & 1) == 0) 7165e96a66cSDavid du Colombier c <<= 4; 7175e96a66cSDavid du Colombier buf[i>>1] |= c; 7185e96a66cSDavid du Colombier } 7195e96a66cSDavid du Colombier memmove(b->data+offset, buf, count); 7205e96a66cSDavid du Colombier consPrint("\tnew: block %#ux %ud %ud %.*H\n", 7215e96a66cSDavid du Colombier addr, offset, count, count, b->data+offset); 7225e96a66cSDavid du Colombier blockDirty(b); 7235e96a66cSDavid du Colombier } 7245e96a66cSDavid du Colombier 7255e96a66cSDavid du Colombier Out: 7265e96a66cSDavid du Colombier blockPut(b); 7275e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7285e96a66cSDavid du Colombier 7295e96a66cSDavid du Colombier return 1; 7305e96a66cSDavid du Colombier } 7315e96a66cSDavid du Colombier 7325e96a66cSDavid du Colombier /* 7335e96a66cSDavid du Colombier * Free a disk block. 7345e96a66cSDavid du Colombier */ 7355e96a66cSDavid du Colombier static int 7365e96a66cSDavid du Colombier fsysBfree(Fsys* fsys, int argc, char* argv[]) 7375e96a66cSDavid du Colombier { 7385e96a66cSDavid du Colombier Fs *fs; 7395e96a66cSDavid du Colombier Label l; 7405e96a66cSDavid du Colombier char *p; 7415e96a66cSDavid du Colombier Block *b; 7425e96a66cSDavid du Colombier u32int addr; 7435e96a66cSDavid du Colombier char *usage = "usage: [fsys name] bfree addr ..."; 7445e96a66cSDavid du Colombier 7455e96a66cSDavid du Colombier ARGBEGIN{ 7465e96a66cSDavid du Colombier default: 7475e96a66cSDavid du Colombier return cliError(usage); 7485e96a66cSDavid du Colombier }ARGEND 7495e96a66cSDavid du Colombier if(argc == 0) 7505e96a66cSDavid du Colombier return cliError(usage); 7515e96a66cSDavid du Colombier 7525e96a66cSDavid du Colombier fs = fsys->fs; 7535e96a66cSDavid du Colombier vtRLock(fs->elk); 7545e96a66cSDavid du Colombier while(argc > 0){ 7555e96a66cSDavid du Colombier addr = strtoul(argv[0], &p, 0); 7565e96a66cSDavid du Colombier if(*p != '\0'){ 757*0c6300e7SDavid du Colombier consPrint("bad address - '%ud'\n", addr); 7585e96a66cSDavid du Colombier /* syntax error; let's stop */ 7595e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7605e96a66cSDavid du Colombier return 0; 7615e96a66cSDavid du Colombier } 7625e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 7635e96a66cSDavid du Colombier if(b == nil){ 7645e96a66cSDavid du Colombier consPrint("loading %#ux: %R\n", addr); 7655e96a66cSDavid du Colombier continue; 7665e96a66cSDavid du Colombier } 7675e96a66cSDavid du Colombier l = b->l; 768e569ccb5SDavid du Colombier if(l.state == BsFree) 769e569ccb5SDavid du Colombier consPrint("%#ux is already free\n", addr); 770e569ccb5SDavid du Colombier else{ 7715e96a66cSDavid du Colombier consPrint("label %#ux %ud %ud %ud %ud %#x\n", 7725e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 7735e96a66cSDavid du Colombier l.state = BsFree; 7745e96a66cSDavid du Colombier l.type = BtMax; 7755e96a66cSDavid du Colombier l.tag = 0; 7765e96a66cSDavid du Colombier l.epoch = 0; 7775e96a66cSDavid du Colombier l.epochClose = 0; 778e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0)) 7795e96a66cSDavid du Colombier consPrint("freeing %#ux: %R\n", addr); 780e569ccb5SDavid du Colombier } 7815e96a66cSDavid du Colombier blockPut(b); 7825e96a66cSDavid du Colombier argc--; 7835e96a66cSDavid du Colombier argv++; 7845e96a66cSDavid du Colombier } 7855e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7865e96a66cSDavid du Colombier 7875e96a66cSDavid du Colombier return 1; 7885e96a66cSDavid du Colombier } 7895e96a66cSDavid du Colombier 7907abd426fSDavid du Colombier static int 7917abd426fSDavid du Colombier fsysDf(Fsys *fsys, int argc, char* argv[]) 7927abd426fSDavid du Colombier { 7937abd426fSDavid du Colombier char *usage = "usage: [fsys name] df"; 7947abd426fSDavid du Colombier u32int used, tot, bsize; 7957abd426fSDavid du Colombier Fs *fs; 7967abd426fSDavid du Colombier 7977abd426fSDavid du Colombier ARGBEGIN{ 7987abd426fSDavid du Colombier default: 7997abd426fSDavid du Colombier return cliError(usage); 8007abd426fSDavid du Colombier }ARGEND 8017abd426fSDavid du Colombier if(argc != 0) 8027abd426fSDavid du Colombier return cliError(usage); 8037abd426fSDavid du Colombier 8047abd426fSDavid du Colombier fs = fsys->fs; 8057abd426fSDavid du Colombier cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize); 806*0c6300e7SDavid du Colombier consPrint("\t%s: %,llud used + %,llud free = %,llud (%llud%% used)\n", 807dc5a79c1SDavid du Colombier fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize, 808208510e1SDavid du Colombier tot*(vlong)bsize, used*100LL/tot); 8097abd426fSDavid du Colombier return 1; 8107abd426fSDavid du Colombier } 8117abd426fSDavid du Colombier 8125e96a66cSDavid du Colombier /* 8135e96a66cSDavid du Colombier * Zero an entry or a pointer. 8145e96a66cSDavid du Colombier */ 8155e96a66cSDavid du Colombier static int 8165e96a66cSDavid du Colombier fsysClrep(Fsys* fsys, int argc, char* argv[], int ch) 8175e96a66cSDavid du Colombier { 8185e96a66cSDavid du Colombier Fs *fs; 8195e96a66cSDavid du Colombier Entry e; 8205e96a66cSDavid du Colombier Block *b; 8215e96a66cSDavid du Colombier u32int addr; 8225e96a66cSDavid du Colombier int i, max, offset, sz; 8235e96a66cSDavid du Colombier uchar zero[VtEntrySize]; 8245e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clr%c addr offset ..."; 8255e96a66cSDavid du Colombier 8265e96a66cSDavid du Colombier ARGBEGIN{ 8275e96a66cSDavid du Colombier default: 8285e96a66cSDavid du Colombier return cliError(usage, ch); 8295e96a66cSDavid du Colombier }ARGEND 8305e96a66cSDavid du Colombier if(argc < 2) 8315e96a66cSDavid du Colombier return cliError(usage, ch); 8325e96a66cSDavid du Colombier 8335e96a66cSDavid du Colombier fs = fsys->fs; 8345e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 8355e96a66cSDavid du Colombier 8365e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 8375e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 8385e96a66cSDavid du Colombier if(b == nil){ 8395e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 8405e96a66cSDavid du Colombier Err: 8415e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 8425e96a66cSDavid du Colombier return 0; 8435e96a66cSDavid du Colombier } 8445e96a66cSDavid du Colombier 8455e96a66cSDavid du Colombier switch(ch){ 8465e96a66cSDavid du Colombier default: 8475e96a66cSDavid du Colombier vtSetError("clrep"); 8485e96a66cSDavid du Colombier goto Err; 8495e96a66cSDavid du Colombier case 'e': 8505e96a66cSDavid du Colombier if(b->l.type != BtDir){ 8515e96a66cSDavid du Colombier vtSetError("wrong block type"); 8525e96a66cSDavid du Colombier goto Err; 8535e96a66cSDavid du Colombier } 8545e96a66cSDavid du Colombier sz = VtEntrySize; 8555e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 8565e96a66cSDavid du Colombier entryPack(&e, zero, 0); 8575e96a66cSDavid du Colombier break; 8585e96a66cSDavid du Colombier case 'p': 8595e96a66cSDavid du Colombier if(b->l.type == BtDir || b->l.type == BtData){ 8605e96a66cSDavid du Colombier vtSetError("wrong block type"); 8615e96a66cSDavid du Colombier goto Err; 8625e96a66cSDavid du Colombier } 8635e96a66cSDavid du Colombier sz = VtScoreSize; 8645e96a66cSDavid du Colombier memmove(zero, vtZeroScore, VtScoreSize); 8655e96a66cSDavid du Colombier break; 8665e96a66cSDavid du Colombier } 8675e96a66cSDavid du Colombier max = fs->blockSize/sz; 8685e96a66cSDavid du Colombier 8695e96a66cSDavid du Colombier for(i = 1; i < argc; i++){ 8705e96a66cSDavid du Colombier offset = atoi(argv[i]); 8715e96a66cSDavid du Colombier if(offset >= max){ 8725e96a66cSDavid du Colombier consPrint("\toffset %d too large (>= %d)\n", i, max); 8735e96a66cSDavid du Colombier continue; 8745e96a66cSDavid du Colombier } 8755e96a66cSDavid du Colombier consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz); 8765e96a66cSDavid du Colombier memmove(b->data+offset*sz, zero, sz); 8775e96a66cSDavid du Colombier } 8785e96a66cSDavid du Colombier blockDirty(b); 8795e96a66cSDavid du Colombier blockPut(b); 8805e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 8815e96a66cSDavid du Colombier 8825e96a66cSDavid du Colombier return 1; 8835e96a66cSDavid du Colombier } 8845e96a66cSDavid du Colombier 8855e96a66cSDavid du Colombier static int 8865e96a66cSDavid du Colombier fsysClre(Fsys* fsys, int argc, char* argv[]) 8875e96a66cSDavid du Colombier { 8885e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'e'); 8895e96a66cSDavid du Colombier } 8905e96a66cSDavid du Colombier 8915e96a66cSDavid du Colombier static int 8925e96a66cSDavid du Colombier fsysClrp(Fsys* fsys, int argc, char* argv[]) 8935e96a66cSDavid du Colombier { 8945e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'p'); 8955e96a66cSDavid du Colombier } 8965e96a66cSDavid du Colombier 8975e96a66cSDavid du Colombier static int 8985e96a66cSDavid du Colombier fsysEsearch1(File* f, char* s, u32int elo) 8995e96a66cSDavid du Colombier { 9005e96a66cSDavid du Colombier int n, r; 9015e96a66cSDavid du Colombier DirEntry de; 9025e96a66cSDavid du Colombier DirEntryEnum *dee; 9035e96a66cSDavid du Colombier File *ff; 9045e96a66cSDavid du Colombier Entry e, ee; 9055e96a66cSDavid du Colombier char *t; 9065e96a66cSDavid du Colombier 9075e96a66cSDavid du Colombier dee = deeOpen(f); 9085e96a66cSDavid du Colombier if(dee == nil) 9095e96a66cSDavid du Colombier return 0; 9105e96a66cSDavid du Colombier 9115e96a66cSDavid du Colombier n = 0; 9125e96a66cSDavid du Colombier for(;;){ 9135e96a66cSDavid du Colombier r = deeRead(dee, &de); 9145e96a66cSDavid du Colombier if(r < 0){ 9155e96a66cSDavid du Colombier consPrint("\tdeeRead %s/%s: %R\n", s, de.elem); 9165e96a66cSDavid du Colombier break; 9175e96a66cSDavid du Colombier } 9185e96a66cSDavid du Colombier if(r == 0) 9195e96a66cSDavid du Colombier break; 9205e96a66cSDavid du Colombier if(de.mode & ModeSnapshot){ 9215e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 9225e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 9235e96a66cSDavid du Colombier else{ 924e569ccb5SDavid du Colombier if(!fileGetSources(ff, &e, &ee)) 9255e96a66cSDavid du Colombier consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem); 9265e96a66cSDavid du Colombier else if(e.snap != 0 && e.snap < elo){ 9275e96a66cSDavid du Colombier consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem); 9285e96a66cSDavid du Colombier n++; 9295e96a66cSDavid du Colombier } 9305e96a66cSDavid du Colombier fileDecRef(ff); 9315e96a66cSDavid du Colombier } 9325e96a66cSDavid du Colombier } 9335e96a66cSDavid du Colombier else if(de.mode & ModeDir){ 9345e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 9355e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 9365e96a66cSDavid du Colombier else{ 937f8e525acSDavid du Colombier t = smprint("%s/%s", s, de.elem); 9385e96a66cSDavid du Colombier n += fsysEsearch1(ff, t, elo); 9395e96a66cSDavid du Colombier vtMemFree(t); 9405e96a66cSDavid du Colombier fileDecRef(ff); 9415e96a66cSDavid du Colombier } 9425e96a66cSDavid du Colombier } 9435e96a66cSDavid du Colombier deCleanup(&de); 9445e96a66cSDavid du Colombier if(r < 0) 9455e96a66cSDavid du Colombier break; 9465e96a66cSDavid du Colombier } 9475e96a66cSDavid du Colombier deeClose(dee); 9485e96a66cSDavid du Colombier 9495e96a66cSDavid du Colombier return n; 9505e96a66cSDavid du Colombier } 9515e96a66cSDavid du Colombier 9525e96a66cSDavid du Colombier static int 9535e96a66cSDavid du Colombier fsysEsearch(Fs* fs, char* path, u32int elo) 9545e96a66cSDavid du Colombier { 9555e96a66cSDavid du Colombier int n; 9565e96a66cSDavid du Colombier File *f; 9575e96a66cSDavid du Colombier DirEntry de; 9585e96a66cSDavid du Colombier 9595e96a66cSDavid du Colombier f = fileOpen(fs, path); 9605e96a66cSDavid du Colombier if(f == nil) 9615e96a66cSDavid du Colombier return 0; 9625e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 9635e96a66cSDavid du Colombier consPrint("\tfileGetDir %s failed: %R\n", path); 9645e96a66cSDavid du Colombier fileDecRef(f); 9655e96a66cSDavid du Colombier return 0; 9665e96a66cSDavid du Colombier } 9675e96a66cSDavid du Colombier if((de.mode & ModeDir) == 0){ 9685e96a66cSDavid du Colombier fileDecRef(f); 9695e96a66cSDavid du Colombier deCleanup(&de); 9705e96a66cSDavid du Colombier return 0; 9715e96a66cSDavid du Colombier } 9725e96a66cSDavid du Colombier deCleanup(&de); 9735e96a66cSDavid du Colombier n = fsysEsearch1(f, path, elo); 9745e96a66cSDavid du Colombier fileDecRef(f); 9755e96a66cSDavid du Colombier return n; 9765e96a66cSDavid du Colombier } 9775e96a66cSDavid du Colombier 9785e96a66cSDavid du Colombier static int 9795e96a66cSDavid du Colombier fsysEpoch(Fsys* fsys, int argc, char* argv[]) 9805e96a66cSDavid du Colombier { 9815e96a66cSDavid du Colombier Fs *fs; 982dc5a79c1SDavid du Colombier int force, n, remove; 9835e96a66cSDavid du Colombier u32int low, old; 984dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] epoch [[-ry] low]"; 9855e96a66cSDavid du Colombier 9865e96a66cSDavid du Colombier force = 0; 987dc5a79c1SDavid du Colombier remove = 0; 9885e96a66cSDavid du Colombier ARGBEGIN{ 9895e96a66cSDavid du Colombier case 'y': 9905e96a66cSDavid du Colombier force = 1; 9915e96a66cSDavid du Colombier break; 992dc5a79c1SDavid du Colombier case 'r': 993dc5a79c1SDavid du Colombier remove = 1; 994dc5a79c1SDavid du Colombier break; 9955e96a66cSDavid du Colombier default: 9965e96a66cSDavid du Colombier return cliError(usage); 9975e96a66cSDavid du Colombier }ARGEND 9985e96a66cSDavid du Colombier if(argc > 1) 9995e96a66cSDavid du Colombier return cliError(usage); 10005e96a66cSDavid du Colombier if(argc > 0) 10015e96a66cSDavid du Colombier low = strtoul(argv[0], 0, 0); 10025e96a66cSDavid du Colombier else 10035e96a66cSDavid du Colombier low = ~(u32int)0; 10045e96a66cSDavid du Colombier 10058a2c5ad0SDavid du Colombier if(low == 0) 10068a2c5ad0SDavid du Colombier return cliError("low epoch cannot be zero"); 10078a2c5ad0SDavid du Colombier 10085e96a66cSDavid du Colombier fs = fsys->fs; 10095e96a66cSDavid du Colombier 10105e96a66cSDavid du Colombier vtRLock(fs->elk); 10115e96a66cSDavid du Colombier consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi); 101257195852SDavid du Colombier if(low == ~(u32int)0){ 101357195852SDavid du Colombier vtRUnlock(fs->elk); 101457195852SDavid du Colombier return 1; 101557195852SDavid du Colombier } 10165e96a66cSDavid du Colombier n = fsysEsearch(fsys->fs, "/archive", low); 10175e96a66cSDavid du Colombier n += fsysEsearch(fsys->fs, "/snapshot", low); 10185e96a66cSDavid du Colombier consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low); 10195e96a66cSDavid du Colombier vtRUnlock(fs->elk); 10205e96a66cSDavid du Colombier 10215e96a66cSDavid du Colombier /* 10225e96a66cSDavid du Colombier * There's a small race here -- a new snapshot with epoch < low might 10235e96a66cSDavid du Colombier * get introduced now that we unlocked fs->elk. Low has to 10245e96a66cSDavid du Colombier * be <= fs->ehi. Of course, in order for this to happen low has 10255e96a66cSDavid du Colombier * to be equal to the current fs->ehi _and_ a snapshot has to 10265e96a66cSDavid du Colombier * run right now. This is a small enough window that I don't care. 10275e96a66cSDavid du Colombier */ 10285e96a66cSDavid du Colombier if(n != 0 && !force){ 10295e96a66cSDavid du Colombier consPrint("\tnot setting low epoch\n"); 10305e96a66cSDavid du Colombier return 1; 10315e96a66cSDavid du Colombier } 10325e96a66cSDavid du Colombier old = fs->elo; 10335e96a66cSDavid du Colombier if(!fsEpochLow(fs, low)) 10345e96a66cSDavid du Colombier consPrint("\tfsEpochLow: %R\n"); 10355e96a66cSDavid du Colombier else{ 10365e96a66cSDavid du Colombier consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old); 10375e96a66cSDavid du Colombier consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo); 10385e96a66cSDavid du Colombier if(fs->elo < low) 10395e96a66cSDavid du Colombier consPrint("\twarning: new low epoch < old low epoch\n"); 1040dc5a79c1SDavid du Colombier if(force && remove) 1041dc5a79c1SDavid du Colombier fsSnapshotRemove(fs); 10425e96a66cSDavid du Colombier } 10435e96a66cSDavid du Colombier 10445e96a66cSDavid du Colombier return 1; 10455e96a66cSDavid du Colombier } 10465e96a66cSDavid du Colombier 10475e96a66cSDavid du Colombier static int 10485e96a66cSDavid du Colombier fsysCreate(Fsys* fsys, int argc, char* argv[]) 10495e96a66cSDavid du Colombier { 10505e96a66cSDavid du Colombier int r; 10515e96a66cSDavid du Colombier ulong mode; 10525e96a66cSDavid du Colombier char *elem, *p, *path; 10535e96a66cSDavid du Colombier char *usage = "usage: [fsys name] create path uid gid perm"; 10545e96a66cSDavid du Colombier DirEntry de; 10555e96a66cSDavid du Colombier File *file, *parent; 10565e96a66cSDavid du Colombier 10575e96a66cSDavid du Colombier ARGBEGIN{ 10585e96a66cSDavid du Colombier default: 10595e96a66cSDavid du Colombier return cliError(usage); 10605e96a66cSDavid du Colombier }ARGEND 10615e96a66cSDavid du Colombier if(argc != 4) 10625e96a66cSDavid du Colombier return cliError(usage); 10635e96a66cSDavid du Colombier 10645e96a66cSDavid du Colombier if(!fsysParseMode(argv[3], &mode)) 10655e96a66cSDavid du Colombier return cliError(usage); 10665e96a66cSDavid du Colombier if(mode&ModeSnapshot) 10675e96a66cSDavid du Colombier return cliError("create - cannot create with snapshot bit set"); 10685e96a66cSDavid du Colombier 10695e96a66cSDavid du Colombier if(strcmp(argv[1], uidnoworld) == 0) 10705e96a66cSDavid du Colombier return cliError("permission denied"); 10715e96a66cSDavid du Colombier 10725e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 10735e96a66cSDavid du Colombier path = vtStrDup(argv[0]); 10745e96a66cSDavid du Colombier if((p = strrchr(path, '/')) != nil){ 10755e96a66cSDavid du Colombier *p++ = '\0'; 10765e96a66cSDavid du Colombier elem = p; 10775e96a66cSDavid du Colombier p = path; 10785e96a66cSDavid du Colombier if(*p == '\0') 10795e96a66cSDavid du Colombier p = "/"; 10805e96a66cSDavid du Colombier } 10815e96a66cSDavid du Colombier else{ 10825e96a66cSDavid du Colombier p = "/"; 10835e96a66cSDavid du Colombier elem = path; 10845e96a66cSDavid du Colombier } 1085f8e525acSDavid du Colombier 10865e96a66cSDavid du Colombier r = 0; 1087f8e525acSDavid du Colombier if((parent = fileOpen(fsys->fs, p)) == nil) 1088f8e525acSDavid du Colombier goto out; 1089f8e525acSDavid du Colombier 10905e96a66cSDavid du Colombier file = fileCreate(parent, elem, mode, argv[1]); 10915e96a66cSDavid du Colombier fileDecRef(parent); 1092f8e525acSDavid du Colombier if(file == nil){ 1093f8e525acSDavid du Colombier vtSetError("create %s/%s: %R", p, elem); 1094f8e525acSDavid du Colombier goto out; 1095f8e525acSDavid du Colombier } 1096f8e525acSDavid du Colombier 1097f8e525acSDavid du Colombier if(!fileGetDir(file, &de)){ 1098f8e525acSDavid du Colombier vtSetError("stat failed after create: %R"); 1099f8e525acSDavid du Colombier goto out1; 1100f8e525acSDavid du Colombier } 1101f8e525acSDavid du Colombier 11025e96a66cSDavid du Colombier if(strcmp(de.gid, argv[2]) != 0){ 11035e96a66cSDavid du Colombier vtMemFree(de.gid); 11045e96a66cSDavid du Colombier de.gid = vtStrDup(argv[2]); 1105f8e525acSDavid du Colombier if(!fileSetDir(file, &de, argv[1])){ 1106f8e525acSDavid du Colombier vtSetError("wstat failed after create: %R"); 1107f8e525acSDavid du Colombier goto out2; 11085e96a66cSDavid du Colombier } 1109f8e525acSDavid du Colombier } 1110f8e525acSDavid du Colombier r = 1; 1111f8e525acSDavid du Colombier 1112f8e525acSDavid du Colombier out2: 11135e96a66cSDavid du Colombier deCleanup(&de); 1114f8e525acSDavid du Colombier out1: 11155e96a66cSDavid du Colombier fileDecRef(file); 1116f8e525acSDavid du Colombier out: 11175e96a66cSDavid du Colombier vtMemFree(path); 11185e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11195e96a66cSDavid du Colombier 11205e96a66cSDavid du Colombier return r; 11215e96a66cSDavid du Colombier } 11225e96a66cSDavid du Colombier 11235e96a66cSDavid du Colombier static void 11245e96a66cSDavid du Colombier fsysPrintStat(char *prefix, char *file, DirEntry *de) 11255e96a66cSDavid du Colombier { 11265e96a66cSDavid du Colombier char buf[64]; 11275e96a66cSDavid du Colombier 11285e96a66cSDavid du Colombier if(prefix == nil) 11295e96a66cSDavid du Colombier prefix = ""; 11305e96a66cSDavid du Colombier consPrint("%sstat %q %q %q %q %s %llud\n", prefix, 11315e96a66cSDavid du Colombier file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size); 11325e96a66cSDavid du Colombier } 11335e96a66cSDavid du Colombier 11345e96a66cSDavid du Colombier static int 11355e96a66cSDavid du Colombier fsysStat(Fsys* fsys, int argc, char* argv[]) 11365e96a66cSDavid du Colombier { 11375e96a66cSDavid du Colombier int i; 11385e96a66cSDavid du Colombier File *f; 11395e96a66cSDavid du Colombier DirEntry de; 11405e96a66cSDavid du Colombier char *usage = "usage: [fsys name] stat files..."; 11415e96a66cSDavid du Colombier 11425e96a66cSDavid du Colombier ARGBEGIN{ 11435e96a66cSDavid du Colombier default: 11445e96a66cSDavid du Colombier return cliError(usage); 11455e96a66cSDavid du Colombier }ARGEND 11465e96a66cSDavid du Colombier 11475e96a66cSDavid du Colombier if(argc == 0) 11485e96a66cSDavid du Colombier return cliError(usage); 11495e96a66cSDavid du Colombier 11505e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 11515e96a66cSDavid du Colombier for(i=0; i<argc; i++){ 11525e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[i])) == nil){ 1153*0c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]); 11545e96a66cSDavid du Colombier continue; 11555e96a66cSDavid du Colombier } 11565e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 1157*0c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]); 11585e96a66cSDavid du Colombier fileDecRef(f); 11595e96a66cSDavid du Colombier continue; 11605e96a66cSDavid du Colombier } 11615e96a66cSDavid du Colombier fsysPrintStat("\t", argv[i], &de); 11625e96a66cSDavid du Colombier deCleanup(&de); 11635e96a66cSDavid du Colombier fileDecRef(f); 11645e96a66cSDavid du Colombier } 11655e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11665e96a66cSDavid du Colombier return 1; 11675e96a66cSDavid du Colombier } 11685e96a66cSDavid du Colombier 11695e96a66cSDavid du Colombier static int 11705e96a66cSDavid du Colombier fsysWstat(Fsys *fsys, int argc, char* argv[]) 11715e96a66cSDavid du Colombier { 11725e96a66cSDavid du Colombier File *f; 11735e96a66cSDavid du Colombier char *p; 11745e96a66cSDavid du Colombier DirEntry de; 11755e96a66cSDavid du Colombier char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n" 11765e96a66cSDavid du Colombier "\tuse - for any field to mean don't change"; 11775e96a66cSDavid du Colombier 11785e96a66cSDavid du Colombier ARGBEGIN{ 11795e96a66cSDavid du Colombier default: 11805e96a66cSDavid du Colombier return cliError(usage); 11815e96a66cSDavid du Colombier }ARGEND 11825e96a66cSDavid du Colombier 11835e96a66cSDavid du Colombier if(argc != 6) 11845e96a66cSDavid du Colombier return cliError(usage); 11855e96a66cSDavid du Colombier 11865e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 11875e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[0])) == nil){ 11885e96a66cSDavid du Colombier vtSetError("console wstat - walk - %R"); 11895e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11905e96a66cSDavid du Colombier return 0; 11915e96a66cSDavid du Colombier } 11925e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 11935e96a66cSDavid du Colombier vtSetError("console wstat - stat - %R"); 11945e96a66cSDavid du Colombier fileDecRef(f); 11955e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11965e96a66cSDavid du Colombier return 0; 11975e96a66cSDavid du Colombier } 11985e96a66cSDavid du Colombier fsysPrintStat("\told: w", argv[0], &de); 11995e96a66cSDavid du Colombier 12005e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0){ 12015e96a66cSDavid du Colombier if(!validFileName(argv[1])){ 12025e96a66cSDavid du Colombier vtSetError("console wstat - bad elem"); 12035e96a66cSDavid du Colombier goto error; 12045e96a66cSDavid du Colombier } 12055e96a66cSDavid du Colombier vtMemFree(de.elem); 12065e96a66cSDavid du Colombier de.elem = vtStrDup(argv[1]); 12075e96a66cSDavid du Colombier } 12085e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0){ 12095e96a66cSDavid du Colombier if(!validUserName(argv[2])){ 12105e96a66cSDavid du Colombier vtSetError("console wstat - bad uid"); 12115e96a66cSDavid du Colombier goto error; 12125e96a66cSDavid du Colombier } 12135e96a66cSDavid du Colombier vtMemFree(de.uid); 12145e96a66cSDavid du Colombier de.uid = vtStrDup(argv[2]); 12155e96a66cSDavid du Colombier } 12165e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0){ 12175e96a66cSDavid du Colombier if(!validUserName(argv[3])){ 12185e96a66cSDavid du Colombier vtSetError("console wstat - bad gid"); 12195e96a66cSDavid du Colombier goto error; 12205e96a66cSDavid du Colombier } 12215e96a66cSDavid du Colombier vtMemFree(de.gid); 12225e96a66cSDavid du Colombier de.gid = vtStrDup(argv[3]); 12235e96a66cSDavid du Colombier } 12245e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0){ 12255e96a66cSDavid du Colombier if(!fsysParseMode(argv[4], &de.mode)){ 12265e96a66cSDavid du Colombier vtSetError("console wstat - bad mode"); 12275e96a66cSDavid du Colombier goto error; 12285e96a66cSDavid du Colombier } 12295e96a66cSDavid du Colombier } 12305e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0){ 12315e96a66cSDavid du Colombier de.size = strtoull(argv[5], &p, 0); 123222a127bbSDavid du Colombier if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){ 12335e96a66cSDavid du Colombier vtSetError("console wstat - bad length"); 12345e96a66cSDavid du Colombier goto error; 12355e96a66cSDavid du Colombier } 12365e96a66cSDavid du Colombier } 12375e96a66cSDavid du Colombier 12385e96a66cSDavid du Colombier if(!fileSetDir(f, &de, uidadm)){ 12395e96a66cSDavid du Colombier vtSetError("console wstat - %R"); 12405e96a66cSDavid du Colombier goto error; 12415e96a66cSDavid du Colombier } 12425e96a66cSDavid du Colombier deCleanup(&de); 12435e96a66cSDavid du Colombier 12445e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 12455e96a66cSDavid du Colombier vtSetError("console wstat - stat2 - %R"); 12465e96a66cSDavid du Colombier goto error; 12475e96a66cSDavid du Colombier } 12485e96a66cSDavid du Colombier fsysPrintStat("\tnew: w", argv[0], &de); 12495e96a66cSDavid du Colombier deCleanup(&de); 12505e96a66cSDavid du Colombier fileDecRef(f); 12515e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12525e96a66cSDavid du Colombier 12535e96a66cSDavid du Colombier return 1; 12545e96a66cSDavid du Colombier 12555e96a66cSDavid du Colombier error: 12565e96a66cSDavid du Colombier deCleanup(&de); /* okay to do this twice */ 12575e96a66cSDavid du Colombier fileDecRef(f); 12585e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12595e96a66cSDavid du Colombier return 0; 12605e96a66cSDavid du Colombier } 12615e96a66cSDavid du Colombier 1262e569ccb5SDavid du Colombier static void 1263e569ccb5SDavid du Colombier fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b) 1264e569ccb5SDavid du Colombier { 1265e569ccb5SDavid du Colombier USED(name); 1266e569ccb5SDavid du Colombier 1267e569ccb5SDavid du Colombier if((fsck->flags&DoClri) == 0) 1268e569ccb5SDavid du Colombier return; 1269e569ccb5SDavid du Colombier 1270e569ccb5SDavid du Colombier mbDelete(mb, i); 1271e569ccb5SDavid du Colombier mbPack(mb); 1272e569ccb5SDavid du Colombier blockDirty(b); 1273e569ccb5SDavid du Colombier } 1274e569ccb5SDavid du Colombier 1275e569ccb5SDavid du Colombier static void 1276e569ccb5SDavid du Colombier fsckClose(Fsck *fsck, Block *b, u32int epoch) 1277e569ccb5SDavid du Colombier { 1278e569ccb5SDavid du Colombier Label l; 1279e569ccb5SDavid du Colombier 1280e569ccb5SDavid du Colombier if((fsck->flags&DoClose) == 0) 1281e569ccb5SDavid du Colombier return; 1282e569ccb5SDavid du Colombier l = b->l; 1283e569ccb5SDavid du Colombier if(l.state == BsFree || (l.state&BsClosed)){ 1284e569ccb5SDavid du Colombier consPrint("%#ux is already closed\n", b->addr); 1285e569ccb5SDavid du Colombier return; 1286e569ccb5SDavid du Colombier } 1287e569ccb5SDavid du Colombier if(epoch){ 1288e569ccb5SDavid du Colombier l.state |= BsClosed; 1289e569ccb5SDavid du Colombier l.epochClose = epoch; 1290e569ccb5SDavid du Colombier }else 1291e569ccb5SDavid du Colombier l.state = BsFree; 1292e569ccb5SDavid du Colombier 1293e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0)) 1294e569ccb5SDavid du Colombier consPrint("%#ux setlabel: %R\n", b->addr); 1295e569ccb5SDavid du Colombier } 1296e569ccb5SDavid du Colombier 1297e569ccb5SDavid du Colombier static void 1298e569ccb5SDavid du Colombier fsckClre(Fsck *fsck, Block *b, int offset) 1299e569ccb5SDavid du Colombier { 1300e569ccb5SDavid du Colombier Entry e; 1301e569ccb5SDavid du Colombier 1302e569ccb5SDavid du Colombier if((fsck->flags&DoClre) == 0) 1303e569ccb5SDavid du Colombier return; 1304e569ccb5SDavid du Colombier if(offset<0 || offset*VtEntrySize >= fsck->bsize){ 1305e569ccb5SDavid du Colombier consPrint("bad clre\n"); 1306e569ccb5SDavid du Colombier return; 1307e569ccb5SDavid du Colombier } 1308e569ccb5SDavid du Colombier memset(&e, 0, sizeof e); 1309e569ccb5SDavid du Colombier entryPack(&e, b->data, offset); 1310e569ccb5SDavid du Colombier blockDirty(b); 1311e569ccb5SDavid du Colombier } 1312e569ccb5SDavid du Colombier 1313e569ccb5SDavid du Colombier static void 1314e569ccb5SDavid du Colombier fsckClrp(Fsck *fsck, Block *b, int offset) 1315e569ccb5SDavid du Colombier { 1316e569ccb5SDavid du Colombier if((fsck->flags&DoClrp) == 0) 1317e569ccb5SDavid du Colombier return; 1318e569ccb5SDavid du Colombier if(offset<0 || offset*VtScoreSize >= fsck->bsize){ 1319e569ccb5SDavid du Colombier consPrint("bad clre\n"); 1320e569ccb5SDavid du Colombier return; 1321e569ccb5SDavid du Colombier } 1322e569ccb5SDavid du Colombier memmove(b->data+offset*VtScoreSize, vtZeroScore, VtScoreSize); 1323e569ccb5SDavid du Colombier blockDirty(b); 1324e569ccb5SDavid du Colombier } 1325e569ccb5SDavid du Colombier 1326e569ccb5SDavid du Colombier static int 1327e569ccb5SDavid du Colombier fsysCheck(Fsys *fsys, int argc, char *argv[]) 1328e569ccb5SDavid du Colombier { 1329e569ccb5SDavid du Colombier int i, halting; 1330e569ccb5SDavid du Colombier char *usage = "usage: [fsys name] check [-v] [options]"; 1331e569ccb5SDavid du Colombier Fsck fsck; 1332e569ccb5SDavid du Colombier Block *b; 1333e569ccb5SDavid du Colombier Super super; 1334e569ccb5SDavid du Colombier 1335e569ccb5SDavid du Colombier memset(&fsck, 0, sizeof fsck); 1336e569ccb5SDavid du Colombier fsck.fs = fsys->fs; 1337e569ccb5SDavid du Colombier fsck.clri = fsckClri; 1338e569ccb5SDavid du Colombier fsck.clre = fsckClre; 1339e569ccb5SDavid du Colombier fsck.clrp = fsckClrp; 1340e569ccb5SDavid du Colombier fsck.close = fsckClose; 1341e569ccb5SDavid du Colombier fsck.print = consPrint; 1342e569ccb5SDavid du Colombier 1343e569ccb5SDavid du Colombier ARGBEGIN{ 1344e569ccb5SDavid du Colombier default: 1345e569ccb5SDavid du Colombier return cliError(usage); 1346e569ccb5SDavid du Colombier }ARGEND 1347e569ccb5SDavid du Colombier 1348e569ccb5SDavid du Colombier for(i=0; i<argc; i++){ 1349e569ccb5SDavid du Colombier if(strcmp(argv[i], "pblock") == 0) 1350e569ccb5SDavid du Colombier fsck.printblocks = 1; 1351e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pdir") == 0) 1352e569ccb5SDavid du Colombier fsck.printdirs = 1; 1353e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pfile") == 0) 1354e569ccb5SDavid du Colombier fsck.printfiles = 1; 1355e569ccb5SDavid du Colombier else if(strcmp(argv[i], "bclose") == 0) 1356e569ccb5SDavid du Colombier fsck.flags |= DoClose; 1357e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clri") == 0) 1358e569ccb5SDavid du Colombier fsck.flags |= DoClri; 1359e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clre") == 0) 1360e569ccb5SDavid du Colombier fsck.flags |= DoClre; 1361e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clrp") == 0) 1362e569ccb5SDavid du Colombier fsck.flags |= DoClrp; 1363e569ccb5SDavid du Colombier else if(strcmp(argv[i], "fix") == 0) 1364e569ccb5SDavid du Colombier fsck.flags |= DoClose|DoClri|DoClre|DoClrp; 1365e569ccb5SDavid du Colombier else if(strcmp(argv[i], "venti") == 0) 1366e569ccb5SDavid du Colombier fsck.useventi = 1; 1367e569ccb5SDavid du Colombier else if(strcmp(argv[i], "snapshot") == 0) 1368e569ccb5SDavid du Colombier fsck.walksnapshots = 1; 1369e569ccb5SDavid du Colombier else{ 1370e569ccb5SDavid du Colombier consPrint("unknown option '%s'\n", argv[i]); 1371e569ccb5SDavid du Colombier return cliError(usage); 1372e569ccb5SDavid du Colombier } 1373e569ccb5SDavid du Colombier } 1374e569ccb5SDavid du Colombier 1375e569ccb5SDavid du Colombier halting = fsys->fs->halted==0; 1376e569ccb5SDavid du Colombier if(halting) 1377e569ccb5SDavid du Colombier fsHalt(fsys->fs); 1378e569ccb5SDavid du Colombier if(fsys->fs->arch){ 1379e569ccb5SDavid du Colombier b = superGet(fsys->fs->cache, &super); 1380e569ccb5SDavid du Colombier if(b == nil){ 1381e569ccb5SDavid du Colombier consPrint("could not load super block\n"); 1382e569ccb5SDavid du Colombier goto Out; 1383e569ccb5SDavid du Colombier } 1384e569ccb5SDavid du Colombier blockPut(b); 1385e569ccb5SDavid du Colombier if(super.current != NilBlock){ 1386e569ccb5SDavid du Colombier consPrint("cannot check fs while archiver is running; wait for it to finish\n"); 1387e569ccb5SDavid du Colombier goto Out; 1388e569ccb5SDavid du Colombier } 1389e569ccb5SDavid du Colombier } 1390e569ccb5SDavid du Colombier fsCheck(&fsck); 1391e569ccb5SDavid du Colombier consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n", 1392e569ccb5SDavid du Colombier fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose); 1393e569ccb5SDavid du Colombier Out: 1394e569ccb5SDavid du Colombier if(halting) 1395e569ccb5SDavid du Colombier fsUnhalt(fsys->fs); 1396e569ccb5SDavid du Colombier return 1; 1397e569ccb5SDavid du Colombier } 1398e569ccb5SDavid du Colombier 13995e96a66cSDavid du Colombier static int 14005e96a66cSDavid du Colombier fsysVenti(char* name, int argc, char* argv[]) 14015e96a66cSDavid du Colombier { 14025e96a66cSDavid du Colombier int r; 14035e96a66cSDavid du Colombier char *host; 14045e96a66cSDavid du Colombier char *usage = "usage: [fsys name] venti [address]"; 14055e96a66cSDavid du Colombier Fsys *fsys; 14065e96a66cSDavid du Colombier 14075e96a66cSDavid du Colombier ARGBEGIN{ 14085e96a66cSDavid du Colombier default: 14095e96a66cSDavid du Colombier return cliError(usage); 14105e96a66cSDavid du Colombier }ARGEND 14115e96a66cSDavid du Colombier 14125e96a66cSDavid du Colombier if(argc == 0) 14135e96a66cSDavid du Colombier host = nil; 14145e96a66cSDavid du Colombier else if(argc == 1) 14155e96a66cSDavid du Colombier host = argv[0]; 14165e96a66cSDavid du Colombier else 14175e96a66cSDavid du Colombier return cliError(usage); 14185e96a66cSDavid du Colombier 14195e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 14205e96a66cSDavid du Colombier return 0; 14215e96a66cSDavid du Colombier 14225e96a66cSDavid du Colombier vtLock(fsys->lock); 14235e96a66cSDavid du Colombier if(host == nil) 14245e96a66cSDavid du Colombier host = fsys->venti; 14255e96a66cSDavid du Colombier else{ 14265e96a66cSDavid du Colombier vtMemFree(fsys->venti); 14275e96a66cSDavid du Colombier if(host[0]) 14285e96a66cSDavid du Colombier fsys->venti = vtStrDup(host); 14295e96a66cSDavid du Colombier else{ 14305e96a66cSDavid du Colombier host = nil; 14315e96a66cSDavid du Colombier fsys->venti = nil; 14325e96a66cSDavid du Colombier } 14335e96a66cSDavid du Colombier } 14345e96a66cSDavid du Colombier 14355e96a66cSDavid du Colombier /* already open: do a redial */ 14365e96a66cSDavid du Colombier if(fsys->fs != nil){ 14376042bf6dSDavid du Colombier if(fsys->session == nil){ 14386042bf6dSDavid du Colombier vtSetError("file system was opened with -V"); 14396042bf6dSDavid du Colombier r = 0; 14406042bf6dSDavid du Colombier goto out; 14416042bf6dSDavid du Colombier } 14425e96a66cSDavid du Colombier r = 1; 14435e96a66cSDavid du Colombier if(!vtRedial(fsys->session, host) 14445e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 14455e96a66cSDavid du Colombier r = 0; 14466042bf6dSDavid du Colombier goto out; 14475e96a66cSDavid du Colombier } 14485e96a66cSDavid du Colombier 14495e96a66cSDavid du Colombier /* not yet open: try to dial */ 14505e96a66cSDavid du Colombier if(fsys->session) 14515e96a66cSDavid du Colombier vtClose(fsys->session); 14525e96a66cSDavid du Colombier r = 1; 14535e96a66cSDavid du Colombier if((fsys->session = vtDial(host, 0)) == nil 14545e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 14555e96a66cSDavid du Colombier r = 0; 14566042bf6dSDavid du Colombier out: 14575e96a66cSDavid du Colombier vtUnlock(fsys->lock); 14585e96a66cSDavid du Colombier fsysPut(fsys); 14595e96a66cSDavid du Colombier return r; 14605e96a66cSDavid du Colombier } 14615e96a66cSDavid du Colombier 14625e96a66cSDavid du Colombier static int 14635e96a66cSDavid du Colombier fsysOpen(char* name, int argc, char* argv[]) 14645e96a66cSDavid du Colombier { 14655e96a66cSDavid du Colombier char *p, *host; 14665e96a66cSDavid du Colombier Fsys *fsys; 14675e96a66cSDavid du Colombier long ncache; 14686042bf6dSDavid du Colombier int noauth, noventi, noperm, rflag, wstatallow; 14696042bf6dSDavid du Colombier char *usage = "usage: fsys name open [-APVWr] [-c ncache]"; 14705e96a66cSDavid du Colombier 14715e96a66cSDavid du Colombier ncache = 1000; 14726042bf6dSDavid du Colombier noauth = noperm = wstatallow = noventi = 0; 14735e96a66cSDavid du Colombier rflag = OReadWrite; 14745e96a66cSDavid du Colombier 14755e96a66cSDavid du Colombier ARGBEGIN{ 14765e96a66cSDavid du Colombier default: 14775e96a66cSDavid du Colombier return cliError(usage); 14785e96a66cSDavid du Colombier case 'A': 14795e96a66cSDavid du Colombier noauth = 1; 14805e96a66cSDavid du Colombier break; 14815e96a66cSDavid du Colombier case 'P': 14825e96a66cSDavid du Colombier noperm = 1; 14835e96a66cSDavid du Colombier break; 14846042bf6dSDavid du Colombier case 'V': 14856042bf6dSDavid du Colombier noventi = 1; 14866042bf6dSDavid du Colombier break; 14875e96a66cSDavid du Colombier case 'W': 14885e96a66cSDavid du Colombier wstatallow = 1; 14895e96a66cSDavid du Colombier break; 14905e96a66cSDavid du Colombier case 'c': 14915e96a66cSDavid du Colombier p = ARGF(); 14925e96a66cSDavid du Colombier if(p == nil) 14935e96a66cSDavid du Colombier return cliError(usage); 14945e96a66cSDavid du Colombier ncache = strtol(argv[0], &p, 0); 14955e96a66cSDavid du Colombier if(ncache <= 0 || p == argv[0] || *p != '\0') 14965e96a66cSDavid du Colombier return cliError(usage); 14975e96a66cSDavid du Colombier break; 14985e96a66cSDavid du Colombier case 'r': 14995e96a66cSDavid du Colombier rflag = OReadOnly; 15005e96a66cSDavid du Colombier break; 15015e96a66cSDavid du Colombier }ARGEND 15025e96a66cSDavid du Colombier if(argc) 15035e96a66cSDavid du Colombier return cliError(usage); 15045e96a66cSDavid du Colombier 15055e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 15065e96a66cSDavid du Colombier return 0; 15075e96a66cSDavid du Colombier 15085e96a66cSDavid du Colombier vtLock(fsys->lock); 15095e96a66cSDavid du Colombier if(fsys->fs != nil){ 15105e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 15115e96a66cSDavid du Colombier vtUnlock(fsys->lock); 15125e96a66cSDavid du Colombier fsysPut(fsys); 15135e96a66cSDavid du Colombier return 0; 15145e96a66cSDavid du Colombier } 15155e96a66cSDavid du Colombier 15167611b47fSDavid du Colombier if(noventi){ 15177611b47fSDavid du Colombier if(fsys->session){ 15187611b47fSDavid du Colombier vtClose(fsys->session); 15197611b47fSDavid du Colombier fsys->session = nil; 15207611b47fSDavid du Colombier } 15217611b47fSDavid du Colombier } 15227611b47fSDavid du Colombier else if(fsys->session == nil){ 15235e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 15245e96a66cSDavid du Colombier host = fsys->venti; 15255e96a66cSDavid du Colombier else 15265e96a66cSDavid du Colombier host = nil; 15275e96a66cSDavid du Colombier fsys->session = vtDial(host, 1); 15286042bf6dSDavid du Colombier if(!vtConnect(fsys->session, nil) && !noventi) 152961201b97SDavid du Colombier fprint(2, "warning: connecting to venti: %R\n"); 15305e96a66cSDavid du Colombier } 15315e96a66cSDavid du Colombier if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){ 1532dc5a79c1SDavid du Colombier vtSetError("fsOpen: %R"); 15335e96a66cSDavid du Colombier vtUnlock(fsys->lock); 15345e96a66cSDavid du Colombier fsysPut(fsys); 15355e96a66cSDavid du Colombier return 0; 15365e96a66cSDavid du Colombier } 1537*0c6300e7SDavid du Colombier fsys->fs->name = fsys->name; /* for better error messages */ 15385e96a66cSDavid du Colombier fsys->noauth = noauth; 15395e96a66cSDavid du Colombier fsys->noperm = noperm; 15405e96a66cSDavid du Colombier fsys->wstatallow = wstatallow; 15415e96a66cSDavid du Colombier vtUnlock(fsys->lock); 15425e96a66cSDavid du Colombier fsysPut(fsys); 15435e96a66cSDavid du Colombier 154481cf8742SDavid du Colombier if(strcmp(name, "main") == 0) 154581cf8742SDavid du Colombier usersFileRead(nil); 154681cf8742SDavid du Colombier 15475e96a66cSDavid du Colombier return 1; 15485e96a66cSDavid du Colombier } 15495e96a66cSDavid du Colombier 15505e96a66cSDavid du Colombier static int 15515e96a66cSDavid du Colombier fsysUnconfig(char* name, int argc, char* argv[]) 15525e96a66cSDavid du Colombier { 15535e96a66cSDavid du Colombier Fsys *fsys, **fp; 15545e96a66cSDavid du Colombier char *usage = "usage: fsys name unconfig"; 15555e96a66cSDavid du Colombier 15565e96a66cSDavid du Colombier ARGBEGIN{ 15575e96a66cSDavid du Colombier default: 15585e96a66cSDavid du Colombier return cliError(usage); 15595e96a66cSDavid du Colombier }ARGEND 15605e96a66cSDavid du Colombier if(argc) 15615e96a66cSDavid du Colombier return cliError(usage); 15625e96a66cSDavid du Colombier 15635e96a66cSDavid du Colombier vtLock(sbox.lock); 15645e96a66cSDavid du Colombier fp = &sbox.head; 15655e96a66cSDavid du Colombier for(fsys = *fp; fsys != nil; fsys = fsys->next){ 15665e96a66cSDavid du Colombier if(strcmp(fsys->name, name) == 0) 15675e96a66cSDavid du Colombier break; 15685e96a66cSDavid du Colombier fp = &fsys->next; 15695e96a66cSDavid du Colombier } 15705e96a66cSDavid du Colombier if(fsys == nil){ 15715e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 15725e96a66cSDavid du Colombier vtUnlock(sbox.lock); 15735e96a66cSDavid du Colombier return 0; 15745e96a66cSDavid du Colombier } 15755e96a66cSDavid du Colombier if(fsys->ref != 0 || fsys->fs != nil){ 15765e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 15775e96a66cSDavid du Colombier vtUnlock(sbox.lock); 15785e96a66cSDavid du Colombier return 0; 15795e96a66cSDavid du Colombier } 15805e96a66cSDavid du Colombier *fp = fsys->next; 15815e96a66cSDavid du Colombier vtUnlock(sbox.lock); 15825e96a66cSDavid du Colombier 15835e96a66cSDavid du Colombier if(fsys->session != nil){ 15845e96a66cSDavid du Colombier vtClose(fsys->session); 15855e96a66cSDavid du Colombier vtFree(fsys->session); 15865e96a66cSDavid du Colombier } 15875e96a66cSDavid du Colombier if(fsys->venti != nil) 15885e96a66cSDavid du Colombier vtMemFree(fsys->venti); 15895e96a66cSDavid du Colombier if(fsys->dev != nil) 15905e96a66cSDavid du Colombier vtMemFree(fsys->dev); 15915e96a66cSDavid du Colombier if(fsys->name != nil) 15925e96a66cSDavid du Colombier vtMemFree(fsys->name); 15935e96a66cSDavid du Colombier vtMemFree(fsys); 15945e96a66cSDavid du Colombier 15955e96a66cSDavid du Colombier return 1; 15965e96a66cSDavid du Colombier } 15975e96a66cSDavid du Colombier 15985e96a66cSDavid du Colombier static int 15995e96a66cSDavid du Colombier fsysConfig(char* name, int argc, char* argv[]) 16005e96a66cSDavid du Colombier { 16015e96a66cSDavid du Colombier Fsys *fsys; 16025e96a66cSDavid du Colombier char *usage = "usage: fsys name config dev"; 16035e96a66cSDavid du Colombier 16045e96a66cSDavid du Colombier ARGBEGIN{ 16055e96a66cSDavid du Colombier default: 16065e96a66cSDavid du Colombier return cliError(usage); 16075e96a66cSDavid du Colombier }ARGEND 16085e96a66cSDavid du Colombier if(argc != 1) 16095e96a66cSDavid du Colombier return cliError(usage); 16105e96a66cSDavid du Colombier 16115e96a66cSDavid du Colombier if((fsys = _fsysGet(argv[0])) != nil){ 16125e96a66cSDavid du Colombier vtLock(fsys->lock); 16135e96a66cSDavid du Colombier if(fsys->fs != nil){ 16145e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 16155e96a66cSDavid du Colombier vtUnlock(fsys->lock); 16165e96a66cSDavid du Colombier fsysPut(fsys); 16175e96a66cSDavid du Colombier return 0; 16185e96a66cSDavid du Colombier } 16195e96a66cSDavid du Colombier vtMemFree(fsys->dev); 16205e96a66cSDavid du Colombier fsys->dev = vtStrDup(argv[0]); 16215e96a66cSDavid du Colombier vtUnlock(fsys->lock); 16225e96a66cSDavid du Colombier } 16235e96a66cSDavid du Colombier else if((fsys = fsysAlloc(name, argv[0])) == nil) 16245e96a66cSDavid du Colombier return 0; 16255e96a66cSDavid du Colombier 16265e96a66cSDavid du Colombier fsysPut(fsys); 16275e96a66cSDavid du Colombier 16285e96a66cSDavid du Colombier return 1; 16295e96a66cSDavid du Colombier } 16305e96a66cSDavid du Colombier 16315e96a66cSDavid du Colombier static struct { 16325e96a66cSDavid du Colombier char* cmd; 16335e96a66cSDavid du Colombier int (*f)(Fsys*, int, char**); 16345e96a66cSDavid du Colombier int (*f1)(char*, int, char**); 16355e96a66cSDavid du Colombier } fsyscmd[] = { 16365e96a66cSDavid du Colombier { "close", fsysClose, }, 16375e96a66cSDavid du Colombier { "config", nil, fsysConfig, }, 16385e96a66cSDavid du Colombier { "open", nil, fsysOpen, }, 16395e96a66cSDavid du Colombier { "unconfig", nil, fsysUnconfig, }, 16405e96a66cSDavid du Colombier { "venti", nil, fsysVenti, }, 16415e96a66cSDavid du Colombier 16425e96a66cSDavid du Colombier { "bfree", fsysBfree, }, 16435e96a66cSDavid du Colombier { "block", fsysBlock, }, 1644e569ccb5SDavid du Colombier { "check", fsysCheck, }, 16455e96a66cSDavid du Colombier { "clre", fsysClre, }, 16465e96a66cSDavid du Colombier { "clri", fsysClri, }, 16475e96a66cSDavid du Colombier { "clrp", fsysClrp, }, 16485e96a66cSDavid du Colombier { "create", fsysCreate, }, 16497abd426fSDavid du Colombier { "df", fsysDf, }, 16505e96a66cSDavid du Colombier { "epoch", fsysEpoch, }, 165181cf8742SDavid du Colombier { "halt", fsysHalt, }, 16525e96a66cSDavid du Colombier { "label", fsysLabel, }, 16535e96a66cSDavid du Colombier { "remove", fsysRemove, }, 16545e96a66cSDavid du Colombier { "snap", fsysSnap, }, 16555e96a66cSDavid du Colombier { "snaptime", fsysSnapTime, }, 1656dc5a79c1SDavid du Colombier { "snapclean", fsysSnapClean, }, 16575e96a66cSDavid du Colombier { "stat", fsysStat, }, 16585e96a66cSDavid du Colombier { "sync", fsysSync, }, 165981cf8742SDavid du Colombier { "unhalt", fsysUnhalt, }, 16605e96a66cSDavid du Colombier { "wstat", fsysWstat, }, 16615e96a66cSDavid du Colombier { "vac", fsysVac, }, 16625e96a66cSDavid du Colombier 16635e96a66cSDavid du Colombier { nil, nil, }, 16645e96a66cSDavid du Colombier }; 16655e96a66cSDavid du Colombier 16665e96a66cSDavid du Colombier static int 166781cf8742SDavid du Colombier fsysXXX1(Fsys *fsys, int i, int argc, char* argv[]) 166881cf8742SDavid du Colombier { 166981cf8742SDavid du Colombier int r; 167081cf8742SDavid du Colombier 167181cf8742SDavid du Colombier vtLock(fsys->lock); 167281cf8742SDavid du Colombier if(fsys->fs == nil){ 167381cf8742SDavid du Colombier vtUnlock(fsys->lock); 167481cf8742SDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 167581cf8742SDavid du Colombier return 0; 167681cf8742SDavid du Colombier } 167781cf8742SDavid du Colombier 1678e569ccb5SDavid du Colombier if(fsys->fs->halted 1679e569ccb5SDavid du Colombier && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){ 168081cf8742SDavid du Colombier vtSetError("file system %s is halted", fsys->name); 168181cf8742SDavid du Colombier vtUnlock(fsys->lock); 168281cf8742SDavid du Colombier return 0; 168381cf8742SDavid du Colombier } 168481cf8742SDavid du Colombier 168581cf8742SDavid du Colombier r = (*fsyscmd[i].f)(fsys, argc, argv); 168681cf8742SDavid du Colombier vtUnlock(fsys->lock); 168781cf8742SDavid du Colombier return r; 168881cf8742SDavid du Colombier } 168981cf8742SDavid du Colombier 169081cf8742SDavid du Colombier static int 16915e96a66cSDavid du Colombier fsysXXX(char* name, int argc, char* argv[]) 16925e96a66cSDavid du Colombier { 16935e96a66cSDavid du Colombier int i, r; 16945e96a66cSDavid du Colombier Fsys *fsys; 16955e96a66cSDavid du Colombier 16965e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 16975e96a66cSDavid du Colombier if(strcmp(fsyscmd[i].cmd, argv[0]) == 0) 16985e96a66cSDavid du Colombier break; 16995e96a66cSDavid du Colombier } 17005e96a66cSDavid du Colombier 17015e96a66cSDavid du Colombier if(fsyscmd[i].cmd == nil){ 17025e96a66cSDavid du Colombier vtSetError("unknown command - '%s'", argv[0]); 17035e96a66cSDavid du Colombier return 0; 17045e96a66cSDavid du Colombier } 17055e96a66cSDavid du Colombier 17065e96a66cSDavid du Colombier /* some commands want the name... */ 170781cf8742SDavid du Colombier if(fsyscmd[i].f1 != nil){ 170881cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 170981cf8742SDavid du Colombier vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]); 17105e96a66cSDavid du Colombier return 0; 17115e96a66cSDavid du Colombier } 171281cf8742SDavid du Colombier return (*fsyscmd[i].f1)(name, argc, argv); 171381cf8742SDavid du Colombier } 17145e96a66cSDavid du Colombier 171581cf8742SDavid du Colombier /* ... but most commands want the Fsys */ 171681cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 171781cf8742SDavid du Colombier r = 1; 171881cf8742SDavid du Colombier vtRLock(sbox.lock); 171981cf8742SDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 172081cf8742SDavid du Colombier fsys->ref++; 172181cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv) && r; 172281cf8742SDavid du Colombier fsys->ref--; 172381cf8742SDavid du Colombier } 172481cf8742SDavid du Colombier vtRUnlock(sbox.lock); 172581cf8742SDavid du Colombier }else{ 172681cf8742SDavid du Colombier if((fsys = _fsysGet(name)) == nil) 172781cf8742SDavid du Colombier return 0; 172881cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv); 17295e96a66cSDavid du Colombier fsysPut(fsys); 173081cf8742SDavid du Colombier } 17315e96a66cSDavid du Colombier return r; 17325e96a66cSDavid du Colombier } 17335e96a66cSDavid du Colombier 17345e96a66cSDavid du Colombier static int 17355e96a66cSDavid du Colombier cmdFsysXXX(int argc, char* argv[]) 17365e96a66cSDavid du Colombier { 17375e96a66cSDavid du Colombier char *name; 17385e96a66cSDavid du Colombier 17395e96a66cSDavid du Colombier if((name = sbox.curfsys) == nil){ 17405e96a66cSDavid du Colombier vtSetError(EFsysNoCurrent, argv[0]); 17415e96a66cSDavid du Colombier return 0; 17425e96a66cSDavid du Colombier } 17435e96a66cSDavid du Colombier 17445e96a66cSDavid du Colombier return fsysXXX(name, argc, argv); 17455e96a66cSDavid du Colombier } 17465e96a66cSDavid du Colombier 17475e96a66cSDavid du Colombier static int 17485e96a66cSDavid du Colombier cmdFsys(int argc, char* argv[]) 17495e96a66cSDavid du Colombier { 17505e96a66cSDavid du Colombier Fsys *fsys; 17515e96a66cSDavid du Colombier char *usage = "usage: fsys [name ...]"; 17525e96a66cSDavid du Colombier 17535e96a66cSDavid du Colombier ARGBEGIN{ 17545e96a66cSDavid du Colombier default: 17555e96a66cSDavid du Colombier return cliError(usage); 17565e96a66cSDavid du Colombier }ARGEND 17575e96a66cSDavid du Colombier 17585e96a66cSDavid du Colombier if(argc == 0){ 17595e96a66cSDavid du Colombier vtRLock(sbox.lock); 17605e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next) 17615e96a66cSDavid du Colombier consPrint("\t%s\n", fsys->name); 17625e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 17635e96a66cSDavid du Colombier return 1; 17645e96a66cSDavid du Colombier } 17655e96a66cSDavid du Colombier if(argc == 1){ 176681cf8742SDavid du Colombier fsys = nil; 176781cf8742SDavid du Colombier if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil) 17685e96a66cSDavid du Colombier return 0; 176981cf8742SDavid du Colombier sbox.curfsys = vtStrDup(argv[0]); 17705e96a66cSDavid du Colombier consPrompt(sbox.curfsys); 177181cf8742SDavid du Colombier if(fsys) 17725e96a66cSDavid du Colombier fsysPut(fsys); 17735e96a66cSDavid du Colombier return 1; 17745e96a66cSDavid du Colombier } 17755e96a66cSDavid du Colombier 17765e96a66cSDavid du Colombier return fsysXXX(argv[0], argc-1, argv+1); 17775e96a66cSDavid du Colombier } 17785e96a66cSDavid du Colombier 17795e96a66cSDavid du Colombier int 17805e96a66cSDavid du Colombier fsysInit(void) 17815e96a66cSDavid du Colombier { 17825e96a66cSDavid du Colombier int i; 17835e96a66cSDavid du Colombier 17845e96a66cSDavid du Colombier fmtinstall('H', encodefmt); 17855e96a66cSDavid du Colombier fmtinstall('V', scoreFmt); 17865e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt); 17875e96a66cSDavid du Colombier fmtinstall('L', labelFmt); 17885e96a66cSDavid du Colombier 17895e96a66cSDavid du Colombier sbox.lock = vtLockAlloc(); 17905e96a66cSDavid du Colombier 17915e96a66cSDavid du Colombier cliAddCmd("fsys", cmdFsys); 17925e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 17935e96a66cSDavid du Colombier if(fsyscmd[i].f != nil) 17945e96a66cSDavid du Colombier cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX); 17955e96a66cSDavid du Colombier } 17965e96a66cSDavid du Colombier /* the venti cmd is special: the fs can be either open or closed */ 17975e96a66cSDavid du Colombier cliAddCmd("venti", cmdFsysXXX); 17985e96a66cSDavid du Colombier cliAddCmd("printconfig", cmdPrintConfig); 17995e96a66cSDavid du Colombier 18005e96a66cSDavid du Colombier return 1; 18015e96a66cSDavid du Colombier } 1802