9fsys.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838
  1. #include "stdinc.h"
  2. #include "dat.h"
  3. #include "fns.h"
  4. #include "9.h"
  5. typedef struct Fsys Fsys;
  6. struct Fsys {
  7. VtLock* lock;
  8. char* name; /* copy here & Fs to ease error reporting */
  9. char* dev;
  10. char* venti;
  11. Fs* fs;
  12. VtSession* session;
  13. int ref;
  14. int noauth;
  15. int noperm;
  16. int wstatallow;
  17. Fsys* next;
  18. };
  19. static struct {
  20. VtLock* lock;
  21. Fsys* head;
  22. Fsys* tail;
  23. char* curfsys;
  24. } sbox;
  25. static char *_argv0;
  26. #define argv0 _argv0
  27. static char FsysAll[] = "all";
  28. static char EFsysBusy[] = "fsys: '%s' busy";
  29. static char EFsysExists[] = "fsys: '%s' already exists";
  30. static char EFsysNoCurrent[] = "fsys: no current fsys";
  31. static char EFsysNotFound[] = "fsys: '%s' not found";
  32. static char EFsysNotOpen[] = "fsys: '%s' not open";
  33. static char *
  34. ventihost(char *host)
  35. {
  36. if(host != nil)
  37. return strdup(host);
  38. host = getenv("venti");
  39. if(host == nil)
  40. host = strdup("$venti");
  41. return host;
  42. }
  43. static void
  44. prventihost(char *host)
  45. {
  46. char *vh;
  47. vh = ventihost(host);
  48. fprint(2, "%s: dialing venti at %s\n",
  49. argv0, netmkaddr(vh, 0, "venti"));
  50. free(vh);
  51. }
  52. static VtSession *
  53. myDial(char *host, int canfail)
  54. {
  55. prventihost(host);
  56. return vtDial(host, canfail);
  57. }
  58. static int
  59. myRedial(VtSession *z, char *host)
  60. {
  61. prventihost(host);
  62. return vtRedial(z, host);
  63. }
  64. static Fsys*
  65. _fsysGet(char* name)
  66. {
  67. Fsys *fsys;
  68. if(name == nil || name[0] == '\0')
  69. name = "main";
  70. vtRLock(sbox.lock);
  71. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  72. if(strcmp(name, fsys->name) == 0){
  73. fsys->ref++;
  74. break;
  75. }
  76. }
  77. vtRUnlock(sbox.lock);
  78. if(fsys == nil)
  79. vtSetError(EFsysNotFound, name);
  80. return fsys;
  81. }
  82. static int
  83. cmdPrintConfig(int argc, char* argv[])
  84. {
  85. Fsys *fsys;
  86. char *usage = "usage: printconfig";
  87. ARGBEGIN{
  88. default:
  89. return cliError(usage);
  90. }ARGEND
  91. if(argc)
  92. return cliError(usage);
  93. vtRLock(sbox.lock);
  94. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  95. consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev);
  96. if(fsys->venti && fsys->venti[0])
  97. consPrint("\tfsys %s venti %q\n", fsys->name,
  98. fsys->venti);
  99. }
  100. vtRUnlock(sbox.lock);
  101. return 1;
  102. }
  103. Fsys*
  104. fsysGet(char* name)
  105. {
  106. Fsys *fsys;
  107. if((fsys = _fsysGet(name)) == nil)
  108. return nil;
  109. vtLock(fsys->lock);
  110. if(fsys->fs == nil){
  111. vtSetError(EFsysNotOpen, fsys->name);
  112. vtUnlock(fsys->lock);
  113. fsysPut(fsys);
  114. return nil;
  115. }
  116. vtUnlock(fsys->lock);
  117. return fsys;
  118. }
  119. char*
  120. fsysGetName(Fsys* fsys)
  121. {
  122. return fsys->name;
  123. }
  124. Fsys*
  125. fsysIncRef(Fsys* fsys)
  126. {
  127. vtLock(sbox.lock);
  128. fsys->ref++;
  129. vtUnlock(sbox.lock);
  130. return fsys;
  131. }
  132. void
  133. fsysPut(Fsys* fsys)
  134. {
  135. vtLock(sbox.lock);
  136. assert(fsys->ref > 0);
  137. fsys->ref--;
  138. vtUnlock(sbox.lock);
  139. }
  140. Fs*
  141. fsysGetFs(Fsys* fsys)
  142. {
  143. assert(fsys != nil && fsys->fs != nil);
  144. return fsys->fs;
  145. }
  146. void
  147. fsysFsRlock(Fsys* fsys)
  148. {
  149. vtRLock(fsys->fs->elk);
  150. }
  151. void
  152. fsysFsRUnlock(Fsys* fsys)
  153. {
  154. vtRUnlock(fsys->fs->elk);
  155. }
  156. int
  157. fsysNoAuthCheck(Fsys* fsys)
  158. {
  159. return fsys->noauth;
  160. }
  161. int
  162. fsysNoPermCheck(Fsys* fsys)
  163. {
  164. return fsys->noperm;
  165. }
  166. int
  167. fsysWstatAllow(Fsys* fsys)
  168. {
  169. return fsys->wstatallow;
  170. }
  171. static char modechars[] = "YUGalLdHSATs";
  172. static ulong modebits[] = {
  173. ModeSticky,
  174. ModeSetUid,
  175. ModeSetGid,
  176. ModeAppend,
  177. ModeExclusive,
  178. ModeLink,
  179. ModeDir,
  180. ModeHidden,
  181. ModeSystem,
  182. ModeArchive,
  183. ModeTemporary,
  184. ModeSnapshot,
  185. 0
  186. };
  187. char*
  188. fsysModeString(ulong mode, char *buf)
  189. {
  190. int i;
  191. char *p;
  192. p = buf;
  193. for(i=0; modebits[i]; i++)
  194. if(mode & modebits[i])
  195. *p++ = modechars[i];
  196. sprint(p, "%luo", mode&0777);
  197. return buf;
  198. }
  199. int
  200. fsysParseMode(char* s, ulong* mode)
  201. {
  202. ulong x, y;
  203. char *p;
  204. x = 0;
  205. for(; *s < '0' || *s > '9'; s++){
  206. if(*s == 0)
  207. return 0;
  208. p = strchr(modechars, *s);
  209. if(p == nil)
  210. return 0;
  211. x |= modebits[p-modechars];
  212. }
  213. y = strtoul(s, &p, 8);
  214. if(*p != '\0' || y > 0777)
  215. return 0;
  216. *mode = x|y;
  217. return 1;
  218. }
  219. File*
  220. fsysGetRoot(Fsys* fsys, char* name)
  221. {
  222. File *root, *sub;
  223. assert(fsys != nil && fsys->fs != nil);
  224. root = fsGetRoot(fsys->fs);
  225. if(name == nil || strcmp(name, "") == 0)
  226. return root;
  227. sub = fileWalk(root, name);
  228. fileDecRef(root);
  229. return sub;
  230. }
  231. static Fsys*
  232. fsysAlloc(char* name, char* dev)
  233. {
  234. Fsys *fsys;
  235. vtLock(sbox.lock);
  236. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  237. if(strcmp(fsys->name, name) != 0)
  238. continue;
  239. vtSetError(EFsysExists, name);
  240. vtUnlock(sbox.lock);
  241. return nil;
  242. }
  243. fsys = vtMemAllocZ(sizeof(Fsys));
  244. fsys->lock = vtLockAlloc();
  245. fsys->name = vtStrDup(name);
  246. fsys->dev = vtStrDup(dev);
  247. fsys->ref = 1;
  248. if(sbox.tail != nil)
  249. sbox.tail->next = fsys;
  250. else
  251. sbox.head = fsys;
  252. sbox.tail = fsys;
  253. vtUnlock(sbox.lock);
  254. return fsys;
  255. }
  256. static int
  257. fsysClose(Fsys* fsys, int argc, char* argv[])
  258. {
  259. char *usage = "usage: [fsys name] close";
  260. ARGBEGIN{
  261. default:
  262. return cliError(usage);
  263. }ARGEND
  264. if(argc)
  265. return cliError(usage);
  266. return cliError("close isn't working yet; halt %s and then kill fossil",
  267. fsys->name);
  268. /*
  269. * Oooh. This could be hard. What if fsys->ref != 1?
  270. * Also, fsClose() either does the job or panics, can we
  271. * gracefully detect it's still busy?
  272. *
  273. * More thought and care needed here.
  274. fsClose(fsys->fs);
  275. fsys->fs = nil;
  276. vtClose(fsys->session);
  277. fsys->session = nil;
  278. if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){
  279. sbox.curfsys = nil;
  280. consPrompt(nil);
  281. }
  282. return 1;
  283. */
  284. }
  285. static int
  286. fsysVac(Fsys* fsys, int argc, char* argv[])
  287. {
  288. uchar score[VtScoreSize];
  289. char *usage = "usage: [fsys name] vac path";
  290. ARGBEGIN{
  291. default:
  292. return cliError(usage);
  293. }ARGEND
  294. if(argc != 1)
  295. return cliError(usage);
  296. if(!fsVac(fsys->fs, argv[0], score))
  297. return 0;
  298. consPrint("vac:%V\n", score);
  299. return 1;
  300. }
  301. static int
  302. fsysSnap(Fsys* fsys, int argc, char* argv[])
  303. {
  304. int doarchive;
  305. char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]";
  306. char *src, *dst;
  307. src = nil;
  308. dst = nil;
  309. doarchive = 0;
  310. ARGBEGIN{
  311. default:
  312. return cliError(usage);
  313. case 'a':
  314. doarchive = 1;
  315. break;
  316. case 'd':
  317. if((dst = ARGF()) == nil)
  318. return cliError(usage);
  319. break;
  320. case 's':
  321. if((src = ARGF()) == nil)
  322. return cliError(usage);
  323. break;
  324. }ARGEND
  325. if(argc)
  326. return cliError(usage);
  327. if(!fsSnapshot(fsys->fs, src, dst, doarchive))
  328. return 0;
  329. return 1;
  330. }
  331. static int
  332. fsysSnapClean(Fsys *fsys, int argc, char* argv[])
  333. {
  334. u32int arch, snap, life;
  335. char *usage = "usage: [fsys name] snapclean [maxminutes]\n";
  336. ARGBEGIN{
  337. default:
  338. return cliError(usage);
  339. }ARGEND
  340. if(argc > 1)
  341. return cliError(usage);
  342. if(argc == 1)
  343. life = atoi(argv[0]);
  344. else
  345. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  346. fsSnapshotCleanup(fsys->fs, life);
  347. return 1;
  348. }
  349. static int
  350. fsysSnapTime(Fsys* fsys, int argc, char* argv[])
  351. {
  352. char buf[128], *x;
  353. int hh, mm, changed;
  354. u32int arch, snap, life;
  355. char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]";
  356. changed = 0;
  357. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  358. ARGBEGIN{
  359. case 'a':
  360. changed = 1;
  361. x = ARGF();
  362. if(x == nil)
  363. return cliError(usage);
  364. if(strcmp(x, "none") == 0){
  365. arch = ~(u32int)0;
  366. break;
  367. }
  368. if(strlen(x) != 4 || strspn(x, "0123456789") != 4)
  369. return cliError(usage);
  370. hh = (x[0]-'0')*10 + x[1]-'0';
  371. mm = (x[2]-'0')*10 + x[3]-'0';
  372. if(hh >= 24 || mm >= 60)
  373. return cliError(usage);
  374. arch = hh*60+mm;
  375. break;
  376. case 's':
  377. changed = 1;
  378. x = ARGF();
  379. if(x == nil)
  380. return cliError(usage);
  381. if(strcmp(x, "none") == 0){
  382. snap = ~(u32int)0;
  383. break;
  384. }
  385. snap = atoi(x);
  386. break;
  387. case 't':
  388. changed = 1;
  389. x = ARGF();
  390. if(x == nil)
  391. return cliError(usage);
  392. if(strcmp(x, "none") == 0){
  393. life = ~(u32int)0;
  394. break;
  395. }
  396. life = atoi(x);
  397. break;
  398. default:
  399. return cliError(usage);
  400. }ARGEND
  401. if(argc > 0)
  402. return cliError(usage);
  403. if(changed){
  404. snapSetTimes(fsys->fs->snap, arch, snap, life);
  405. return 1;
  406. }
  407. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  408. if(arch != ~(u32int)0)
  409. sprint(buf, "-a %02d%02d", arch/60, arch%60);
  410. else
  411. sprint(buf, "-a none");
  412. if(snap != ~(u32int)0)
  413. sprint(buf+strlen(buf), " -s %d", snap);
  414. else
  415. sprint(buf+strlen(buf), " -s none");
  416. if(life != ~(u32int)0)
  417. sprint(buf+strlen(buf), " -t %ud", life);
  418. else
  419. sprint(buf+strlen(buf), " -t none");
  420. consPrint("\tsnaptime %s\n", buf);
  421. return 1;
  422. }
  423. static int
  424. fsysSync(Fsys* fsys, int argc, char* argv[])
  425. {
  426. char *usage = "usage: [fsys name] sync";
  427. int n;
  428. ARGBEGIN{
  429. default:
  430. return cliError(usage);
  431. }ARGEND
  432. if(argc > 0)
  433. return cliError(usage);
  434. n = cacheDirty(fsys->fs->cache);
  435. fsSync(fsys->fs);
  436. consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n);
  437. return 1;
  438. }
  439. static int
  440. fsysHalt(Fsys *fsys, int argc, char* argv[])
  441. {
  442. char *usage = "usage: [fsys name] halt";
  443. ARGBEGIN{
  444. default:
  445. return cliError(usage);
  446. }ARGEND
  447. if(argc > 0)
  448. return cliError(usage);
  449. fsHalt(fsys->fs);
  450. return 1;
  451. }
  452. static int
  453. fsysUnhalt(Fsys *fsys, int argc, char* argv[])
  454. {
  455. char *usage = "usage: [fsys name] unhalt";
  456. ARGBEGIN{
  457. default:
  458. return cliError(usage);
  459. }ARGEND
  460. if(argc > 0)
  461. return cliError(usage);
  462. if(!fsys->fs->halted)
  463. return cliError("file system %s not halted", fsys->name);
  464. fsUnhalt(fsys->fs);
  465. return 1;
  466. }
  467. static int
  468. fsysRemove(Fsys* fsys, int argc, char* argv[])
  469. {
  470. File *file;
  471. char *usage = "usage: [fsys name] remove path ...";
  472. ARGBEGIN{
  473. default:
  474. return cliError(usage);
  475. }ARGEND
  476. if(argc == 0)
  477. return cliError(usage);
  478. vtRLock(fsys->fs->elk);
  479. while(argc > 0){
  480. if((file = fileOpen(fsys->fs, argv[0])) == nil)
  481. consPrint("%s: %R\n", argv[0]);
  482. else{
  483. if(!fileRemove(file, uidadm))
  484. consPrint("%s: %R\n", argv[0]);
  485. fileDecRef(file);
  486. }
  487. argc--;
  488. argv++;
  489. }
  490. vtRUnlock(fsys->fs->elk);
  491. return 1;
  492. }
  493. static int
  494. fsysClri(Fsys* fsys, int argc, char* argv[])
  495. {
  496. char *usage = "usage: [fsys name] clri path ...";
  497. ARGBEGIN{
  498. default:
  499. return cliError(usage);
  500. }ARGEND
  501. if(argc == 0)
  502. return cliError(usage);
  503. vtRLock(fsys->fs->elk);
  504. while(argc > 0){
  505. if(!fileClriPath(fsys->fs, argv[0], uidadm))
  506. consPrint("clri %s: %R\n", argv[0]);
  507. argc--;
  508. argv++;
  509. }
  510. vtRUnlock(fsys->fs->elk);
  511. return 1;
  512. }
  513. /*
  514. * Inspect and edit the labels for blocks on disk.
  515. */
  516. static int
  517. fsysLabel(Fsys* fsys, int argc, char* argv[])
  518. {
  519. Fs *fs;
  520. Label l;
  521. int n, r;
  522. u32int addr;
  523. Block *b, *bb;
  524. char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]";
  525. ARGBEGIN{
  526. default:
  527. return cliError(usage);
  528. }ARGEND
  529. if(argc != 1 && argc != 6)
  530. return cliError(usage);
  531. r = 0;
  532. vtRLock(fsys->fs->elk);
  533. fs = fsys->fs;
  534. addr = strtoul(argv[0], 0, 0);
  535. b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
  536. if(b == nil)
  537. goto Out0;
  538. l = b->l;
  539. consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n",
  540. argc==6 ? "old: " : "", addr, l.type, l.state,
  541. l.epoch, l.epochClose, l.tag);
  542. if(argc == 6){
  543. if(strcmp(argv[1], "-") != 0)
  544. l.type = atoi(argv[1]);
  545. if(strcmp(argv[2], "-") != 0)
  546. l.state = atoi(argv[2]);
  547. if(strcmp(argv[3], "-") != 0)
  548. l.epoch = strtoul(argv[3], 0, 0);
  549. if(strcmp(argv[4], "-") != 0)
  550. l.epochClose = strtoul(argv[4], 0, 0);
  551. if(strcmp(argv[5], "-") != 0)
  552. l.tag = strtoul(argv[5], 0, 0);
  553. consPrint("new: label %#ux %ud %ud %ud %ud %#x\n",
  554. addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
  555. bb = _blockSetLabel(b, &l);
  556. if(bb == nil)
  557. goto Out1;
  558. n = 0;
  559. for(;;){
  560. if(blockWrite(bb)){
  561. while(bb->iostate != BioClean){
  562. assert(bb->iostate == BioWriting);
  563. vtSleep(bb->ioready);
  564. }
  565. break;
  566. }
  567. consPrint("blockWrite: %R\n");
  568. if(n++ >= 5){
  569. consPrint("giving up\n");
  570. break;
  571. }
  572. sleep(5*1000);
  573. }
  574. blockPut(bb);
  575. }
  576. r = 1;
  577. Out1:
  578. blockPut(b);
  579. Out0:
  580. vtRUnlock(fs->elk);
  581. return r;
  582. }
  583. /*
  584. * Inspect and edit the blocks on disk.
  585. */
  586. static int
  587. fsysBlock(Fsys* fsys, int argc, char* argv[])
  588. {
  589. Fs *fs;
  590. char *s;
  591. Block *b;
  592. uchar *buf;
  593. u32int addr;
  594. int c, count, i, offset;
  595. char *usage = "usage: [fsys name] block addr offset [count [data]]";
  596. ARGBEGIN{
  597. default:
  598. return cliError(usage);
  599. }ARGEND
  600. if(argc < 2 || argc > 4)
  601. return cliError(usage);
  602. fs = fsys->fs;
  603. addr = strtoul(argv[0], 0, 0);
  604. offset = strtoul(argv[1], 0, 0);
  605. if(offset < 0 || offset >= fs->blockSize){
  606. vtSetError("bad offset");
  607. return 0;
  608. }
  609. if(argc > 2)
  610. count = strtoul(argv[2], 0, 0);
  611. else
  612. count = 100000000;
  613. if(offset+count > fs->blockSize)
  614. count = fs->blockSize - count;
  615. vtRLock(fs->elk);
  616. b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
  617. if(b == nil){
  618. vtSetError("cacheLocal %#ux: %R", addr);
  619. vtRUnlock(fs->elk);
  620. return 0;
  621. }
  622. consPrint("\t%sblock %#ux %ud %ud %.*H\n",
  623. argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset);
  624. if(argc == 4){
  625. s = argv[3];
  626. if(strlen(s) != 2*count){
  627. vtSetError("bad data count");
  628. goto Out;
  629. }
  630. buf = vtMemAllocZ(count);
  631. for(i = 0; i < count*2; i++){
  632. if(s[i] >= '0' && s[i] <= '9')
  633. c = s[i] - '0';
  634. else if(s[i] >= 'a' && s[i] <= 'f')
  635. c = s[i] - 'a' + 10;
  636. else if(s[i] >= 'A' && s[i] <= 'F')
  637. c = s[i] - 'A' + 10;
  638. else{
  639. vtSetError("bad hex");
  640. vtMemFree(buf);
  641. goto Out;
  642. }
  643. if((i & 1) == 0)
  644. c <<= 4;
  645. buf[i>>1] |= c;
  646. }
  647. memmove(b->data+offset, buf, count);
  648. consPrint("\tnew: block %#ux %ud %ud %.*H\n",
  649. addr, offset, count, count, b->data+offset);
  650. blockDirty(b);
  651. }
  652. Out:
  653. blockPut(b);
  654. vtRUnlock(fs->elk);
  655. return 1;
  656. }
  657. /*
  658. * Free a disk block.
  659. */
  660. static int
  661. fsysBfree(Fsys* fsys, int argc, char* argv[])
  662. {
  663. Fs *fs;
  664. Label l;
  665. char *p;
  666. Block *b;
  667. u32int addr;
  668. char *usage = "usage: [fsys name] bfree addr ...";
  669. ARGBEGIN{
  670. default:
  671. return cliError(usage);
  672. }ARGEND
  673. if(argc == 0)
  674. return cliError(usage);
  675. fs = fsys->fs;
  676. vtRLock(fs->elk);
  677. while(argc > 0){
  678. addr = strtoul(argv[0], &p, 0);
  679. if(*p != '\0'){
  680. consPrint("bad address - '%ud'\n", addr);
  681. /* syntax error; let's stop */
  682. vtRUnlock(fs->elk);
  683. return 0;
  684. }
  685. b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
  686. if(b == nil){
  687. consPrint("loading %#ux: %R\n", addr);
  688. continue;
  689. }
  690. l = b->l;
  691. if(l.state == BsFree)
  692. consPrint("%#ux is already free\n", addr);
  693. else{
  694. consPrint("label %#ux %ud %ud %ud %ud %#x\n",
  695. addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
  696. l.state = BsFree;
  697. l.type = BtMax;
  698. l.tag = 0;
  699. l.epoch = 0;
  700. l.epochClose = 0;
  701. if(!blockSetLabel(b, &l, 0))
  702. consPrint("freeing %#ux: %R\n", addr);
  703. }
  704. blockPut(b);
  705. argc--;
  706. argv++;
  707. }
  708. vtRUnlock(fs->elk);
  709. return 1;
  710. }
  711. static int
  712. fsysDf(Fsys *fsys, int argc, char* argv[])
  713. {
  714. char *usage = "usage: [fsys name] df";
  715. u32int used, tot, bsize;
  716. Fs *fs;
  717. ARGBEGIN{
  718. default:
  719. return cliError(usage);
  720. }ARGEND
  721. if(argc != 0)
  722. return cliError(usage);
  723. fs = fsys->fs;
  724. cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize);
  725. consPrint("\t%s: %,llud used + %,llud free = %,llud (%llud%% used)\n",
  726. fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize,
  727. tot*(vlong)bsize, used*100LL/tot);
  728. return 1;
  729. }
  730. /*
  731. * Zero an entry or a pointer.
  732. */
  733. static int
  734. fsysClrep(Fsys* fsys, int argc, char* argv[], int ch)
  735. {
  736. Fs *fs;
  737. Entry e;
  738. Block *b;
  739. u32int addr;
  740. int i, max, offset, sz;
  741. uchar zero[VtEntrySize];
  742. char *usage = "usage: [fsys name] clr%c addr offset ...";
  743. ARGBEGIN{
  744. default:
  745. return cliError(usage, ch);
  746. }ARGEND
  747. if(argc < 2)
  748. return cliError(usage, ch);
  749. fs = fsys->fs;
  750. vtRLock(fsys->fs->elk);
  751. addr = strtoul(argv[0], 0, 0);
  752. b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
  753. if(b == nil){
  754. vtSetError("cacheLocal %#ux: %R", addr);
  755. Err:
  756. vtRUnlock(fsys->fs->elk);
  757. return 0;
  758. }
  759. switch(ch){
  760. default:
  761. vtSetError("clrep");
  762. goto Err;
  763. case 'e':
  764. if(b->l.type != BtDir){
  765. vtSetError("wrong block type");
  766. goto Err;
  767. }
  768. sz = VtEntrySize;
  769. memset(&e, 0, sizeof e);
  770. entryPack(&e, zero, 0);
  771. break;
  772. case 'p':
  773. if(b->l.type == BtDir || b->l.type == BtData){
  774. vtSetError("wrong block type");
  775. goto Err;
  776. }
  777. sz = VtScoreSize;
  778. memmove(zero, vtZeroScore, VtScoreSize);
  779. break;
  780. }
  781. max = fs->blockSize/sz;
  782. for(i = 1; i < argc; i++){
  783. offset = atoi(argv[i]);
  784. if(offset >= max){
  785. consPrint("\toffset %d too large (>= %d)\n", i, max);
  786. continue;
  787. }
  788. consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz);
  789. memmove(b->data+offset*sz, zero, sz);
  790. }
  791. blockDirty(b);
  792. blockPut(b);
  793. vtRUnlock(fsys->fs->elk);
  794. return 1;
  795. }
  796. static int
  797. fsysClre(Fsys* fsys, int argc, char* argv[])
  798. {
  799. return fsysClrep(fsys, argc, argv, 'e');
  800. }
  801. static int
  802. fsysClrp(Fsys* fsys, int argc, char* argv[])
  803. {
  804. return fsysClrep(fsys, argc, argv, 'p');
  805. }
  806. static int
  807. fsysEsearch1(File* f, char* s, u32int elo)
  808. {
  809. int n, r;
  810. DirEntry de;
  811. DirEntryEnum *dee;
  812. File *ff;
  813. Entry e, ee;
  814. char *t;
  815. dee = deeOpen(f);
  816. if(dee == nil)
  817. return 0;
  818. n = 0;
  819. for(;;){
  820. r = deeRead(dee, &de);
  821. if(r < 0){
  822. consPrint("\tdeeRead %s/%s: %R\n", s, de.elem);
  823. break;
  824. }
  825. if(r == 0)
  826. break;
  827. if(de.mode & ModeSnapshot){
  828. if((ff = fileWalk(f, de.elem)) == nil)
  829. consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
  830. else{
  831. if(!fileGetSources(ff, &e, &ee))
  832. consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem);
  833. else if(e.snap != 0 && e.snap < elo){
  834. consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem);
  835. n++;
  836. }
  837. fileDecRef(ff);
  838. }
  839. }
  840. else if(de.mode & ModeDir){
  841. if((ff = fileWalk(f, de.elem)) == nil)
  842. consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
  843. else{
  844. t = smprint("%s/%s", s, de.elem);
  845. n += fsysEsearch1(ff, t, elo);
  846. vtMemFree(t);
  847. fileDecRef(ff);
  848. }
  849. }
  850. deCleanup(&de);
  851. if(r < 0)
  852. break;
  853. }
  854. deeClose(dee);
  855. return n;
  856. }
  857. static int
  858. fsysEsearch(Fs* fs, char* path, u32int elo)
  859. {
  860. int n;
  861. File *f;
  862. DirEntry de;
  863. f = fileOpen(fs, path);
  864. if(f == nil)
  865. return 0;
  866. if(!fileGetDir(f, &de)){
  867. consPrint("\tfileGetDir %s failed: %R\n", path);
  868. fileDecRef(f);
  869. return 0;
  870. }
  871. if((de.mode & ModeDir) == 0){
  872. fileDecRef(f);
  873. deCleanup(&de);
  874. return 0;
  875. }
  876. deCleanup(&de);
  877. n = fsysEsearch1(f, path, elo);
  878. fileDecRef(f);
  879. return n;
  880. }
  881. static int
  882. fsysEpoch(Fsys* fsys, int argc, char* argv[])
  883. {
  884. Fs *fs;
  885. int force, n, remove;
  886. u32int low, old;
  887. char *usage = "usage: [fsys name] epoch [[-ry] low]";
  888. force = 0;
  889. remove = 0;
  890. ARGBEGIN{
  891. case 'y':
  892. force = 1;
  893. break;
  894. case 'r':
  895. remove = 1;
  896. break;
  897. default:
  898. return cliError(usage);
  899. }ARGEND
  900. if(argc > 1)
  901. return cliError(usage);
  902. if(argc > 0)
  903. low = strtoul(argv[0], 0, 0);
  904. else
  905. low = ~(u32int)0;
  906. if(low == 0)
  907. return cliError("low epoch cannot be zero");
  908. fs = fsys->fs;
  909. vtRLock(fs->elk);
  910. consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi);
  911. if(low == ~(u32int)0){
  912. vtRUnlock(fs->elk);
  913. return 1;
  914. }
  915. n = fsysEsearch(fsys->fs, "/archive", low);
  916. n += fsysEsearch(fsys->fs, "/snapshot", low);
  917. consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low);
  918. vtRUnlock(fs->elk);
  919. /*
  920. * There's a small race here -- a new snapshot with epoch < low might
  921. * get introduced now that we unlocked fs->elk. Low has to
  922. * be <= fs->ehi. Of course, in order for this to happen low has
  923. * to be equal to the current fs->ehi _and_ a snapshot has to
  924. * run right now. This is a small enough window that I don't care.
  925. */
  926. if(n != 0 && !force){
  927. consPrint("\tnot setting low epoch\n");
  928. return 1;
  929. }
  930. old = fs->elo;
  931. if(!fsEpochLow(fs, low))
  932. consPrint("\tfsEpochLow: %R\n");
  933. else{
  934. consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old);
  935. consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo);
  936. if(fs->elo < low)
  937. consPrint("\twarning: new low epoch < old low epoch\n");
  938. if(force && remove)
  939. fsSnapshotRemove(fs);
  940. }
  941. return 1;
  942. }
  943. static int
  944. fsysCreate(Fsys* fsys, int argc, char* argv[])
  945. {
  946. int r;
  947. ulong mode;
  948. char *elem, *p, *path;
  949. char *usage = "usage: [fsys name] create path uid gid perm";
  950. DirEntry de;
  951. File *file, *parent;
  952. ARGBEGIN{
  953. default:
  954. return cliError(usage);
  955. }ARGEND
  956. if(argc != 4)
  957. return cliError(usage);
  958. if(!fsysParseMode(argv[3], &mode))
  959. return cliError(usage);
  960. if(mode&ModeSnapshot)
  961. return cliError("create - cannot create with snapshot bit set");
  962. if(strcmp(argv[1], uidnoworld) == 0)
  963. return cliError("permission denied");
  964. vtRLock(fsys->fs->elk);
  965. path = vtStrDup(argv[0]);
  966. if((p = strrchr(path, '/')) != nil){
  967. *p++ = '\0';
  968. elem = p;
  969. p = path;
  970. if(*p == '\0')
  971. p = "/";
  972. }
  973. else{
  974. p = "/";
  975. elem = path;
  976. }
  977. r = 0;
  978. if((parent = fileOpen(fsys->fs, p)) == nil)
  979. goto out;
  980. file = fileCreate(parent, elem, mode, argv[1]);
  981. fileDecRef(parent);
  982. if(file == nil){
  983. vtSetError("create %s/%s: %R", p, elem);
  984. goto out;
  985. }
  986. if(!fileGetDir(file, &de)){
  987. vtSetError("stat failed after create: %R");
  988. goto out1;
  989. }
  990. if(strcmp(de.gid, argv[2]) != 0){
  991. vtMemFree(de.gid);
  992. de.gid = vtStrDup(argv[2]);
  993. if(!fileSetDir(file, &de, argv[1])){
  994. vtSetError("wstat failed after create: %R");
  995. goto out2;
  996. }
  997. }
  998. r = 1;
  999. out2:
  1000. deCleanup(&de);
  1001. out1:
  1002. fileDecRef(file);
  1003. out:
  1004. vtMemFree(path);
  1005. vtRUnlock(fsys->fs->elk);
  1006. return r;
  1007. }
  1008. static void
  1009. fsysPrintStat(char *prefix, char *file, DirEntry *de)
  1010. {
  1011. char buf[64];
  1012. if(prefix == nil)
  1013. prefix = "";
  1014. consPrint("%sstat %q %q %q %q %s %llud\n", prefix,
  1015. file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);
  1016. }
  1017. static int
  1018. fsysStat(Fsys* fsys, int argc, char* argv[])
  1019. {
  1020. int i;
  1021. File *f;
  1022. DirEntry de;
  1023. char *usage = "usage: [fsys name] stat files...";
  1024. ARGBEGIN{
  1025. default:
  1026. return cliError(usage);
  1027. }ARGEND
  1028. if(argc == 0)
  1029. return cliError(usage);
  1030. vtRLock(fsys->fs->elk);
  1031. for(i=0; i<argc; i++){
  1032. if((f = fileOpen(fsys->fs, argv[i])) == nil){
  1033. consPrint("%s: %R\n", argv[i]);
  1034. continue;
  1035. }
  1036. if(!fileGetDir(f, &de)){
  1037. consPrint("%s: %R\n", argv[i]);
  1038. fileDecRef(f);
  1039. continue;
  1040. }
  1041. fsysPrintStat("\t", argv[i], &de);
  1042. deCleanup(&de);
  1043. fileDecRef(f);
  1044. }
  1045. vtRUnlock(fsys->fs->elk);
  1046. return 1;
  1047. }
  1048. static int
  1049. fsysWstat(Fsys *fsys, int argc, char* argv[])
  1050. {
  1051. File *f;
  1052. char *p;
  1053. DirEntry de;
  1054. char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n"
  1055. "\tuse - for any field to mean don't change";
  1056. ARGBEGIN{
  1057. default:
  1058. return cliError(usage);
  1059. }ARGEND
  1060. if(argc != 6)
  1061. return cliError(usage);
  1062. vtRLock(fsys->fs->elk);
  1063. if((f = fileOpen(fsys->fs, argv[0])) == nil){
  1064. vtSetError("console wstat - walk - %R");
  1065. vtRUnlock(fsys->fs->elk);
  1066. return 0;
  1067. }
  1068. if(!fileGetDir(f, &de)){
  1069. vtSetError("console wstat - stat - %R");
  1070. fileDecRef(f);
  1071. vtRUnlock(fsys->fs->elk);
  1072. return 0;
  1073. }
  1074. fsysPrintStat("\told: w", argv[0], &de);
  1075. if(strcmp(argv[1], "-") != 0){
  1076. if(!validFileName(argv[1])){
  1077. vtSetError("console wstat - bad elem");
  1078. goto error;
  1079. }
  1080. vtMemFree(de.elem);
  1081. de.elem = vtStrDup(argv[1]);
  1082. }
  1083. if(strcmp(argv[2], "-") != 0){
  1084. if(!validUserName(argv[2])){
  1085. vtSetError("console wstat - bad uid");
  1086. goto error;
  1087. }
  1088. vtMemFree(de.uid);
  1089. de.uid = vtStrDup(argv[2]);
  1090. }
  1091. if(strcmp(argv[3], "-") != 0){
  1092. if(!validUserName(argv[3])){
  1093. vtSetError("console wstat - bad gid");
  1094. goto error;
  1095. }
  1096. vtMemFree(de.gid);
  1097. de.gid = vtStrDup(argv[3]);
  1098. }
  1099. if(strcmp(argv[4], "-") != 0){
  1100. if(!fsysParseMode(argv[4], &de.mode)){
  1101. vtSetError("console wstat - bad mode");
  1102. goto error;
  1103. }
  1104. }
  1105. if(strcmp(argv[5], "-") != 0){
  1106. de.size = strtoull(argv[5], &p, 0);
  1107. if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){
  1108. vtSetError("console wstat - bad length");
  1109. goto error;
  1110. }
  1111. }
  1112. if(!fileSetDir(f, &de, uidadm)){
  1113. vtSetError("console wstat - %R");
  1114. goto error;
  1115. }
  1116. deCleanup(&de);
  1117. if(!fileGetDir(f, &de)){
  1118. vtSetError("console wstat - stat2 - %R");
  1119. goto error;
  1120. }
  1121. fsysPrintStat("\tnew: w", argv[0], &de);
  1122. deCleanup(&de);
  1123. fileDecRef(f);
  1124. vtRUnlock(fsys->fs->elk);
  1125. return 1;
  1126. error:
  1127. deCleanup(&de); /* okay to do this twice */
  1128. fileDecRef(f);
  1129. vtRUnlock(fsys->fs->elk);
  1130. return 0;
  1131. }
  1132. static void
  1133. fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b)
  1134. {
  1135. USED(name);
  1136. if((fsck->flags&DoClri) == 0)
  1137. return;
  1138. mbDelete(mb, i);
  1139. mbPack(mb);
  1140. blockDirty(b);
  1141. }
  1142. static void
  1143. fsckClose(Fsck *fsck, Block *b, u32int epoch)
  1144. {
  1145. Label l;
  1146. if((fsck->flags&DoClose) == 0)
  1147. return;
  1148. l = b->l;
  1149. if(l.state == BsFree || (l.state&BsClosed)){
  1150. consPrint("%#ux is already closed\n", b->addr);
  1151. return;
  1152. }
  1153. if(epoch){
  1154. l.state |= BsClosed;
  1155. l.epochClose = epoch;
  1156. }else
  1157. l.state = BsFree;
  1158. if(!blockSetLabel(b, &l, 0))
  1159. consPrint("%#ux setlabel: %R\n", b->addr);
  1160. }
  1161. static void
  1162. fsckClre(Fsck *fsck, Block *b, int offset)
  1163. {
  1164. Entry e;
  1165. if((fsck->flags&DoClre) == 0)
  1166. return;
  1167. if(offset<0 || offset*VtEntrySize >= fsck->bsize){
  1168. consPrint("bad clre\n");
  1169. return;
  1170. }
  1171. memset(&e, 0, sizeof e);
  1172. entryPack(&e, b->data, offset);
  1173. blockDirty(b);
  1174. }
  1175. static void
  1176. fsckClrp(Fsck *fsck, Block *b, int offset)
  1177. {
  1178. if((fsck->flags&DoClrp) == 0)
  1179. return;
  1180. if(offset<0 || offset*VtScoreSize >= fsck->bsize){
  1181. consPrint("bad clre\n");
  1182. return;
  1183. }
  1184. memmove(b->data+offset*VtScoreSize, vtZeroScore, VtScoreSize);
  1185. blockDirty(b);
  1186. }
  1187. static int
  1188. fsysCheck(Fsys *fsys, int argc, char *argv[])
  1189. {
  1190. int i, halting;
  1191. char *usage = "usage: [fsys name] check [-v] [options]";
  1192. Fsck fsck;
  1193. Block *b;
  1194. Super super;
  1195. memset(&fsck, 0, sizeof fsck);
  1196. fsck.fs = fsys->fs;
  1197. fsck.clri = fsckClri;
  1198. fsck.clre = fsckClre;
  1199. fsck.clrp = fsckClrp;
  1200. fsck.close = fsckClose;
  1201. fsck.print = consPrint;
  1202. ARGBEGIN{
  1203. default:
  1204. return cliError(usage);
  1205. }ARGEND
  1206. for(i=0; i<argc; i++){
  1207. if(strcmp(argv[i], "pblock") == 0)
  1208. fsck.printblocks = 1;
  1209. else if(strcmp(argv[i], "pdir") == 0)
  1210. fsck.printdirs = 1;
  1211. else if(strcmp(argv[i], "pfile") == 0)
  1212. fsck.printfiles = 1;
  1213. else if(strcmp(argv[i], "bclose") == 0)
  1214. fsck.flags |= DoClose;
  1215. else if(strcmp(argv[i], "clri") == 0)
  1216. fsck.flags |= DoClri;
  1217. else if(strcmp(argv[i], "clre") == 0)
  1218. fsck.flags |= DoClre;
  1219. else if(strcmp(argv[i], "clrp") == 0)
  1220. fsck.flags |= DoClrp;
  1221. else if(strcmp(argv[i], "fix") == 0)
  1222. fsck.flags |= DoClose|DoClri|DoClre|DoClrp;
  1223. else if(strcmp(argv[i], "venti") == 0)
  1224. fsck.useventi = 1;
  1225. else if(strcmp(argv[i], "snapshot") == 0)
  1226. fsck.walksnapshots = 1;
  1227. else{
  1228. consPrint("unknown option '%s'\n", argv[i]);
  1229. return cliError(usage);
  1230. }
  1231. }
  1232. halting = fsys->fs->halted==0;
  1233. if(halting)
  1234. fsHalt(fsys->fs);
  1235. if(fsys->fs->arch){
  1236. b = superGet(fsys->fs->cache, &super);
  1237. if(b == nil){
  1238. consPrint("could not load super block\n");
  1239. goto Out;
  1240. }
  1241. blockPut(b);
  1242. if(super.current != NilBlock){
  1243. consPrint("cannot check fs while archiver is running; "
  1244. "wait for it to finish\n");
  1245. goto Out;
  1246. }
  1247. }
  1248. fsCheck(&fsck);
  1249. consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n",
  1250. fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose);
  1251. Out:
  1252. if(halting)
  1253. fsUnhalt(fsys->fs);
  1254. return 1;
  1255. }
  1256. static int
  1257. fsysVenti(char* name, int argc, char* argv[])
  1258. {
  1259. int r;
  1260. char *host;
  1261. char *usage = "usage: [fsys name] venti [address]";
  1262. Fsys *fsys;
  1263. ARGBEGIN{
  1264. default:
  1265. return cliError(usage);
  1266. }ARGEND
  1267. if(argc == 0)
  1268. host = nil;
  1269. else if(argc == 1)
  1270. host = argv[0];
  1271. else
  1272. return cliError(usage);
  1273. if((fsys = _fsysGet(name)) == nil)
  1274. return 0;
  1275. vtLock(fsys->lock);
  1276. if(host == nil)
  1277. host = fsys->venti;
  1278. else{
  1279. vtMemFree(fsys->venti);
  1280. if(host[0])
  1281. fsys->venti = vtStrDup(host);
  1282. else{
  1283. host = nil;
  1284. fsys->venti = nil;
  1285. }
  1286. }
  1287. /* already open: do a redial */
  1288. if(fsys->fs != nil){
  1289. if(fsys->session == nil){
  1290. vtSetError("file system was opened with -V");
  1291. r = 0;
  1292. goto out;
  1293. }
  1294. r = 1;
  1295. if(!myRedial(fsys->session, host)
  1296. || !vtConnect(fsys->session, 0))
  1297. r = 0;
  1298. goto out;
  1299. }
  1300. /* not yet open: try to dial */
  1301. if(fsys->session)
  1302. vtClose(fsys->session);
  1303. r = 1;
  1304. if((fsys->session = myDial(host, 0)) == nil
  1305. || !vtConnect(fsys->session, 0))
  1306. r = 0;
  1307. out:
  1308. vtUnlock(fsys->lock);
  1309. fsysPut(fsys);
  1310. return r;
  1311. }
  1312. static int
  1313. fsysOpen(char* name, int argc, char* argv[])
  1314. {
  1315. char *p, *host;
  1316. Fsys *fsys;
  1317. long ncache;
  1318. int noauth, noventi, noperm, rflag, wstatallow;
  1319. char *usage = "usage: fsys name open [-APVWr] [-c ncache]";
  1320. ncache = 1000;
  1321. noauth = noperm = wstatallow = noventi = 0;
  1322. rflag = OReadWrite;
  1323. ARGBEGIN{
  1324. default:
  1325. return cliError(usage);
  1326. case 'A':
  1327. noauth = 1;
  1328. break;
  1329. case 'P':
  1330. noperm = 1;
  1331. break;
  1332. case 'V':
  1333. noventi = 1;
  1334. break;
  1335. case 'W':
  1336. wstatallow = 1;
  1337. break;
  1338. case 'c':
  1339. p = ARGF();
  1340. if(p == nil)
  1341. return cliError(usage);
  1342. ncache = strtol(argv[0], &p, 0);
  1343. if(ncache <= 0 || p == argv[0] || *p != '\0')
  1344. return cliError(usage);
  1345. break;
  1346. case 'r':
  1347. rflag = OReadOnly;
  1348. break;
  1349. }ARGEND
  1350. if(argc)
  1351. return cliError(usage);
  1352. if((fsys = _fsysGet(name)) == nil)
  1353. return 0;
  1354. vtLock(fsys->lock);
  1355. if(fsys->fs != nil){
  1356. vtSetError(EFsysBusy, fsys->name);
  1357. vtUnlock(fsys->lock);
  1358. fsysPut(fsys);
  1359. return 0;
  1360. }
  1361. if(noventi){
  1362. if(fsys->session){
  1363. vtClose(fsys->session);
  1364. fsys->session = nil;
  1365. }
  1366. }
  1367. else if(fsys->session == nil){
  1368. if(fsys->venti && fsys->venti[0])
  1369. host = fsys->venti;
  1370. else
  1371. host = nil;
  1372. fsys->session = myDial(host, 1);
  1373. if(!vtConnect(fsys->session, nil) && !noventi)
  1374. fprint(2, "warning: connecting to venti: %R\n");
  1375. }
  1376. if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){
  1377. vtSetError("fsOpen: %R");
  1378. vtUnlock(fsys->lock);
  1379. fsysPut(fsys);
  1380. return 0;
  1381. }
  1382. fsys->fs->name = fsys->name; /* for better error messages */
  1383. fsys->noauth = noauth;
  1384. fsys->noperm = noperm;
  1385. fsys->wstatallow = wstatallow;
  1386. vtUnlock(fsys->lock);
  1387. fsysPut(fsys);
  1388. if(strcmp(name, "main") == 0)
  1389. usersFileRead(nil);
  1390. return 1;
  1391. }
  1392. static int
  1393. fsysUnconfig(char* name, int argc, char* argv[])
  1394. {
  1395. Fsys *fsys, **fp;
  1396. char *usage = "usage: fsys name unconfig";
  1397. ARGBEGIN{
  1398. default:
  1399. return cliError(usage);
  1400. }ARGEND
  1401. if(argc)
  1402. return cliError(usage);
  1403. vtLock(sbox.lock);
  1404. fp = &sbox.head;
  1405. for(fsys = *fp; fsys != nil; fsys = fsys->next){
  1406. if(strcmp(fsys->name, name) == 0)
  1407. break;
  1408. fp = &fsys->next;
  1409. }
  1410. if(fsys == nil){
  1411. vtSetError(EFsysNotFound, name);
  1412. vtUnlock(sbox.lock);
  1413. return 0;
  1414. }
  1415. if(fsys->ref != 0 || fsys->fs != nil){
  1416. vtSetError(EFsysBusy, fsys->name);
  1417. vtUnlock(sbox.lock);
  1418. return 0;
  1419. }
  1420. *fp = fsys->next;
  1421. vtUnlock(sbox.lock);
  1422. if(fsys->session != nil){
  1423. vtClose(fsys->session);
  1424. vtFree(fsys->session);
  1425. }
  1426. if(fsys->venti != nil)
  1427. vtMemFree(fsys->venti);
  1428. if(fsys->dev != nil)
  1429. vtMemFree(fsys->dev);
  1430. if(fsys->name != nil)
  1431. vtMemFree(fsys->name);
  1432. vtMemFree(fsys);
  1433. return 1;
  1434. }
  1435. static int
  1436. fsysConfig(char* name, int argc, char* argv[])
  1437. {
  1438. Fsys *fsys;
  1439. char *usage = "usage: fsys name config dev";
  1440. ARGBEGIN{
  1441. default:
  1442. return cliError(usage);
  1443. }ARGEND
  1444. if(argc != 1)
  1445. return cliError(usage);
  1446. if((fsys = _fsysGet(argv[0])) != nil){
  1447. vtLock(fsys->lock);
  1448. if(fsys->fs != nil){
  1449. vtSetError(EFsysBusy, fsys->name);
  1450. vtUnlock(fsys->lock);
  1451. fsysPut(fsys);
  1452. return 0;
  1453. }
  1454. vtMemFree(fsys->dev);
  1455. fsys->dev = vtStrDup(argv[0]);
  1456. vtUnlock(fsys->lock);
  1457. }
  1458. else if((fsys = fsysAlloc(name, argv[0])) == nil)
  1459. return 0;
  1460. fsysPut(fsys);
  1461. return 1;
  1462. }
  1463. static struct {
  1464. char* cmd;
  1465. int (*f)(Fsys*, int, char**);
  1466. int (*f1)(char*, int, char**);
  1467. } fsyscmd[] = {
  1468. { "close", fsysClose, },
  1469. { "config", nil, fsysConfig, },
  1470. { "open", nil, fsysOpen, },
  1471. { "unconfig", nil, fsysUnconfig, },
  1472. { "venti", nil, fsysVenti, },
  1473. { "bfree", fsysBfree, },
  1474. { "block", fsysBlock, },
  1475. { "check", fsysCheck, },
  1476. { "clre", fsysClre, },
  1477. { "clri", fsysClri, },
  1478. { "clrp", fsysClrp, },
  1479. { "create", fsysCreate, },
  1480. { "df", fsysDf, },
  1481. { "epoch", fsysEpoch, },
  1482. { "halt", fsysHalt, },
  1483. { "label", fsysLabel, },
  1484. { "remove", fsysRemove, },
  1485. { "snap", fsysSnap, },
  1486. { "snaptime", fsysSnapTime, },
  1487. { "snapclean", fsysSnapClean, },
  1488. { "stat", fsysStat, },
  1489. { "sync", fsysSync, },
  1490. { "unhalt", fsysUnhalt, },
  1491. { "wstat", fsysWstat, },
  1492. { "vac", fsysVac, },
  1493. { nil, nil, },
  1494. };
  1495. static int
  1496. fsysXXX1(Fsys *fsys, int i, int argc, char* argv[])
  1497. {
  1498. int r;
  1499. vtLock(fsys->lock);
  1500. if(fsys->fs == nil){
  1501. vtUnlock(fsys->lock);
  1502. vtSetError(EFsysNotOpen, fsys->name);
  1503. return 0;
  1504. }
  1505. if(fsys->fs->halted
  1506. && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){
  1507. vtSetError("file system %s is halted", fsys->name);
  1508. vtUnlock(fsys->lock);
  1509. return 0;
  1510. }
  1511. r = (*fsyscmd[i].f)(fsys, argc, argv);
  1512. vtUnlock(fsys->lock);
  1513. return r;
  1514. }
  1515. static int
  1516. fsysXXX(char* name, int argc, char* argv[])
  1517. {
  1518. int i, r;
  1519. Fsys *fsys;
  1520. for(i = 0; fsyscmd[i].cmd != nil; i++){
  1521. if(strcmp(fsyscmd[i].cmd, argv[0]) == 0)
  1522. break;
  1523. }
  1524. if(fsyscmd[i].cmd == nil){
  1525. vtSetError("unknown command - '%s'", argv[0]);
  1526. return 0;
  1527. }
  1528. /* some commands want the name... */
  1529. if(fsyscmd[i].f1 != nil){
  1530. if(strcmp(name, FsysAll) == 0){
  1531. vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]);
  1532. return 0;
  1533. }
  1534. return (*fsyscmd[i].f1)(name, argc, argv);
  1535. }
  1536. /* ... but most commands want the Fsys */
  1537. if(strcmp(name, FsysAll) == 0){
  1538. r = 1;
  1539. vtRLock(sbox.lock);
  1540. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  1541. fsys->ref++;
  1542. r = fsysXXX1(fsys, i, argc, argv) && r;
  1543. fsys->ref--;
  1544. }
  1545. vtRUnlock(sbox.lock);
  1546. }else{
  1547. if((fsys = _fsysGet(name)) == nil)
  1548. return 0;
  1549. r = fsysXXX1(fsys, i, argc, argv);
  1550. fsysPut(fsys);
  1551. }
  1552. return r;
  1553. }
  1554. static int
  1555. cmdFsysXXX(int argc, char* argv[])
  1556. {
  1557. char *name;
  1558. if((name = sbox.curfsys) == nil){
  1559. vtSetError(EFsysNoCurrent, argv[0]);
  1560. return 0;
  1561. }
  1562. return fsysXXX(name, argc, argv);
  1563. }
  1564. static int
  1565. cmdFsys(int argc, char* argv[])
  1566. {
  1567. Fsys *fsys;
  1568. char *usage = "usage: fsys [name ...]";
  1569. ARGBEGIN{
  1570. default:
  1571. return cliError(usage);
  1572. }ARGEND
  1573. if(argc == 0){
  1574. vtRLock(sbox.lock);
  1575. for(fsys = sbox.head; fsys != nil; fsys = fsys->next)
  1576. consPrint("\t%s\n", fsys->name);
  1577. vtRUnlock(sbox.lock);
  1578. return 1;
  1579. }
  1580. if(argc == 1){
  1581. fsys = nil;
  1582. if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil)
  1583. return 0;
  1584. sbox.curfsys = vtStrDup(argv[0]);
  1585. consPrompt(sbox.curfsys);
  1586. if(fsys)
  1587. fsysPut(fsys);
  1588. return 1;
  1589. }
  1590. return fsysXXX(argv[0], argc-1, argv+1);
  1591. }
  1592. int
  1593. fsysInit(void)
  1594. {
  1595. int i;
  1596. fmtinstall('H', encodefmt);
  1597. fmtinstall('V', scoreFmt);
  1598. fmtinstall('R', vtErrFmt);
  1599. fmtinstall('L', labelFmt);
  1600. sbox.lock = vtLockAlloc();
  1601. cliAddCmd("fsys", cmdFsys);
  1602. for(i = 0; fsyscmd[i].cmd != nil; i++){
  1603. if(fsyscmd[i].f != nil)
  1604. cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX);
  1605. }
  1606. /* the venti cmd is special: the fs can be either open or closed */
  1607. cliAddCmd("venti", cmdFsysXXX);
  1608. cliAddCmd("printconfig", cmdPrintConfig);
  1609. return 1;
  1610. }