fsys.b 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. implement Fsys;
  2. include "common.m";
  3. sys : Sys;
  4. styx : Styx;
  5. styxaux : Styxaux;
  6. acme : Acme;
  7. dat : Dat;
  8. utils : Utils;
  9. look : Look;
  10. windowm : Windowm;
  11. xfidm : Xfidm;
  12. QTDIR, QTFILE, QTAPPEND : import Sys;
  13. DMDIR, DMAPPEND, Qid, ORCLOSE, OTRUNC, OREAD, OWRITE, ORDWR, Dir : import Sys;
  14. sprint : import sys;
  15. MAXWELEM, Rerror : import Styx;
  16. Qdir,Qacme,Qcons,Qconsctl,Qdraw,Qeditout,Qindex,Qlabel,Qnew,QWaddr,QWbody,QWconsctl,QWctl,QWdata,QWeditout,QWevent,QWrdsel,QWwrsel,QWtag,QMAX : import Dat;
  17. TRUE, FALSE : import Dat;
  18. cxfidalloc, cerr : import dat;
  19. Mntdir, Fid, Dirtab, Lock, Ref, Smsg0 : import dat;
  20. Tmsg, Rmsg : import styx;
  21. msize, version, fid, uname, aname, newfid, name, mode, offset, count, setmode : import styxaux;
  22. Xfid : import xfidm;
  23. row : import dat;
  24. Column : import Columnm;
  25. Window : import windowm;
  26. lookid : import look;
  27. warning, error : import utils;
  28. init(mods : ref Dat->Mods)
  29. {
  30. messagesize = Styx->MAXRPC;
  31. sys = mods.sys;
  32. styx = mods.styx;
  33. styxaux = mods.styxaux;
  34. acme = mods.acme;
  35. dat = mods.dat;
  36. utils = mods.utils;
  37. look = mods.look;
  38. windowm = mods.windowm;
  39. xfidm = mods.xfidm;
  40. }
  41. sfd, cfd : ref Sys->FD;
  42. Nhash : con 16;
  43. DEBUG : con 0;
  44. fids := array[Nhash] of ref Fid;
  45. Eperm := "permission denied";
  46. Eexist := "file does not exist";
  47. Enotdir := "not a directory";
  48. dirtab := array[10] of {
  49. Dirtab ( ".", QTDIR, Qdir, 8r500|DMDIR ),
  50. Dirtab ( "acme", QTDIR, Qacme, 8r500|DMDIR ),
  51. Dirtab ( "cons", QTFILE, Qcons, 8r600 ),
  52. Dirtab ( "consctl", QTFILE, Qconsctl, 8r000 ),
  53. Dirtab ( "draw", QTDIR, Qdraw, 8r000|DMDIR ),
  54. Dirtab ( "editout", QTFILE, Qeditout, 8r200 ),
  55. Dirtab ( "index", QTFILE, Qindex, 8r400 ),
  56. Dirtab ( "label", QTFILE, Qlabel, 8r600 ),
  57. Dirtab ( "new", QTDIR, Qnew, 8r500|DMDIR ),
  58. Dirtab ( nil, 0, 0, 0 ),
  59. };
  60. dirtabw := array[12] of {
  61. Dirtab ( ".", QTDIR, Qdir, 8r500|DMDIR ),
  62. Dirtab ( "addr", QTFILE, QWaddr, 8r600 ),
  63. Dirtab ( "body", QTAPPEND, QWbody, 8r600|DMAPPEND ),
  64. Dirtab ( "ctl", QTFILE, QWctl, 8r600 ),
  65. Dirtab ( "consctl", QTFILE, QWconsctl, 8r200 ),
  66. Dirtab ( "data", QTFILE, QWdata, 8r600 ),
  67. Dirtab ( "editout", QTFILE, QWeditout, 8r200 ),
  68. Dirtab ( "event", QTFILE, QWevent, 8r600 ),
  69. Dirtab ( "rdsel", QTFILE, QWrdsel, 8r400 ),
  70. Dirtab ( "wrsel", QTFILE, QWwrsel, 8r200 ),
  71. Dirtab ( "tag", QTAPPEND, QWtag, 8r600|DMAPPEND ),
  72. Dirtab ( nil, 0, 0, 0 ),
  73. };
  74. Mnt : adt {
  75. qlock : ref Lock;
  76. id : int;
  77. md : ref Mntdir;
  78. };
  79. mnt : Mnt;
  80. user : string;
  81. clockfd : ref Sys->FD;
  82. closing := 0;
  83. fsysinit()
  84. {
  85. p : array of ref Sys->FD;
  86. p = array[2] of ref Sys->FD;
  87. if(sys->pipe(p) < 0)
  88. error("can't create pipe");
  89. cfd = p[0];
  90. sfd = p[1];
  91. clockfd = sys->open("/dev/time", Sys->OREAD);
  92. user = utils->getuser();
  93. if (user == nil)
  94. user = "Wile. E. Coyote";
  95. mnt.qlock = Lock.init();
  96. mnt.id = 0;
  97. spawn fsysproc();
  98. }
  99. fsyscfd() : int
  100. {
  101. return cfd.fd;
  102. }
  103. QID(w, q : int) : int
  104. {
  105. return (w<<8)|q;
  106. }
  107. FILE(q : Qid) : int
  108. {
  109. return int q.path & 16rFF;
  110. }
  111. WIN(q : Qid) : int
  112. {
  113. return (int q.path>>8) & 16rFFFFFF;
  114. }
  115. # nullsmsg : Smsg;
  116. nullsmsg0 : Smsg0;
  117. fsysproc()
  118. {
  119. n, ok : int;
  120. x : ref Xfid;
  121. f : ref Fid;
  122. t : Smsg0;
  123. acme->fsyspid = sys->pctl(0, nil);
  124. x = nil;
  125. for(;;){
  126. if(x == nil){
  127. cxfidalloc <-= nil;
  128. x = <-cxfidalloc;
  129. }
  130. n = sys->read(sfd, x.buf, messagesize);
  131. if(n <= 0) {
  132. if (closing)
  133. break;
  134. error("i/o error on server channel");
  135. }
  136. (ok, x.fcall) = Tmsg.unpack(x.buf[0:n]);
  137. if(ok < 0)
  138. error("convert error in convM2S");
  139. if(DEBUG)
  140. utils->debug(sprint("%d:%s\n", x.tid, x.fcall.text()));
  141. pick fc := x.fcall {
  142. Version =>
  143. f = nil;
  144. Auth =>
  145. f = nil;
  146. * =>
  147. f = allocfid(fid(x.fcall));
  148. }
  149. x.f = f;
  150. pick fc := x.fcall {
  151. Readerror => x = fsyserror();
  152. Flush => x = fsysflush(x);
  153. Version => x = fsysversion(x);
  154. Auth => x = fsysauth(x);
  155. Attach => x = fsysattach(x, f);
  156. Walk => x = fsyswalk(x, f);
  157. Open => x = fsysopen(x, f);
  158. Create => x = fsyscreate(x);
  159. Read => x = fsysread(x, f);
  160. Write => x = fsyswrite(x);
  161. Clunk => x = fsysclunk(x, f);
  162. Remove => x = fsysremove(x);
  163. Stat => x = fsysstat(x, f);
  164. Wstat => x = fsyswstat(x);
  165. # Clone => x = fsysclone(x, f);
  166. * =>
  167. x = respond(x, t, "bad fcall type");
  168. }
  169. }
  170. }
  171. fsysaddid(dir : string, ndir : int, incl : array of string, nincl : int) : ref Mntdir
  172. {
  173. m : ref Mntdir;
  174. id : int;
  175. mnt.qlock.lock();
  176. id = ++mnt.id;
  177. m = ref Mntdir;
  178. m.id = id;
  179. m.dir = dir;
  180. m.refs = 1; # one for Command, one will be incremented in attach
  181. m.ndir = ndir;
  182. m.next = mnt.md;
  183. m.incl = incl;
  184. m.nincl = nincl;
  185. mnt.md = m;
  186. mnt.qlock.unlock();
  187. return m;
  188. }
  189. fsysdelid(idm : ref Mntdir)
  190. {
  191. m, prev : ref Mntdir;
  192. i : int;
  193. if(idm == nil)
  194. return;
  195. mnt.qlock.lock();
  196. if(--idm.refs > 0){
  197. mnt.qlock.unlock();
  198. return;
  199. }
  200. prev = nil;
  201. for(m=mnt.md; m != nil; m=m.next){
  202. if(m == idm){
  203. if(prev != nil)
  204. prev.next = m.next;
  205. else
  206. mnt.md = m.next;
  207. for(i=0; i<m.nincl; i++)
  208. m.incl[i] = nil;
  209. m.incl = nil;
  210. m.dir = nil;
  211. m = nil;
  212. mnt.qlock.unlock();
  213. return;
  214. }
  215. prev = m;
  216. }
  217. mnt.qlock.unlock();
  218. buf := sys->sprint("fsysdelid: can't find id %d\n", idm.id);
  219. cerr <-= buf;
  220. }
  221. #
  222. # Called only in exec.l:run(), from a different FD group
  223. #
  224. fsysmount(dir : string, ndir : int, incl : array of string, nincl : int) : ref Mntdir
  225. {
  226. m : ref Mntdir;
  227. # close server side so don't hang if acme is half-exited
  228. # sfd = nil;
  229. m = fsysaddid(dir, ndir, incl, nincl);
  230. buf := sys->sprint("%d", m.id);
  231. if(sys->mount(cfd, nil, "/mnt/acme", Sys->MREPL, buf) < 0){
  232. fsysdelid(m);
  233. return nil;
  234. }
  235. # cfd = nil;
  236. sys->bind("/mnt/acme", "/chan", Sys->MBEFORE); # was MREPL
  237. if(sys->bind("/mnt/acme", "/dev", Sys->MBEFORE) < 0){
  238. fsysdelid(m);
  239. return nil;
  240. }
  241. return m;
  242. }
  243. fsysclose()
  244. {
  245. closing = 1;
  246. # sfd = cfd = nil;
  247. }
  248. respond(x : ref Xfid, t0 : Smsg0, err : string) : ref Xfid
  249. {
  250. t : ref Rmsg;
  251. # t = nullsmsg;
  252. tag := x.fcall.tag;
  253. # fid := fid(x.fcall);
  254. qid := t0.qid;
  255. if(err != nil)
  256. t = ref Rmsg.Error(tag, err);
  257. else
  258. pick fc := x.fcall {
  259. Readerror => t = ref Rmsg.Error(tag, err);
  260. Flush => t = ref Rmsg.Flush(tag);
  261. Version => t = ref Rmsg.Version(tag, t0.msize, t0.version);
  262. Auth => t = ref Rmsg.Auth(tag, qid);
  263. # Clone => t = ref Rmsg.Clone(tag, fid);
  264. Attach => t = ref Rmsg.Attach(tag, qid);
  265. Walk => t = ref Rmsg.Walk(tag, t0.qids);
  266. Open => t = ref Rmsg.Open(tag, qid, t0.iounit);
  267. Create => t = ref Rmsg.Create(tag, qid, 0);
  268. Read => if(t0.count == len t0.data)
  269. t = ref Rmsg.Read(tag, t0.data);
  270. else
  271. t = ref Rmsg.Read(tag, t0.data[0: t0.count]);
  272. Write => t = ref Rmsg.Write(tag, t0.count);
  273. Clunk => t = ref Rmsg.Clunk(tag);
  274. Remove => t = ref Rmsg.Remove(tag);
  275. Stat => t = ref Rmsg.Stat(tag, t0.stat);
  276. Wstat => t = ref Rmsg.Wstat(tag);
  277. }
  278. # t.qid = t0.qid;
  279. # t.count = t0.count;
  280. # t.data = t0.data;
  281. # t.stat = t0.stat;
  282. # t.fid = x.fcall.fid;
  283. # t.tag = x.fcall.tag;
  284. buf := t.pack();
  285. if(buf == nil)
  286. error("convert error in convS2M");
  287. if(sys->write(sfd, buf, len buf) != len buf)
  288. error("write error in respond");
  289. buf = nil;
  290. if(DEBUG)
  291. utils->debug(sprint("%d:r: %s\n", x.tid, t.text()));
  292. return x;
  293. }
  294. # fsysnop(x : ref Xfid) : ref Xfid
  295. # {
  296. # t : Smsg0;
  297. #
  298. # return respond(x, t, nil);
  299. # }
  300. fsyserror() : ref Xfid
  301. {
  302. error("sys error : Terror");
  303. return nil;
  304. }
  305. fsyssession(x : ref Xfid) : ref Xfid
  306. {
  307. t : Smsg0;
  308. # BUG: should shut everybody down ??
  309. t = nullsmsg0;
  310. return respond(x, t, nil);
  311. }
  312. fsysversion(x : ref Xfid) : ref Xfid
  313. {
  314. t : Smsg0;
  315. pick m := x.fcall {
  316. Version =>
  317. (t.msize, t.version) = styx->compatible(m, messagesize, nil);
  318. messagesize = t.msize;
  319. return respond(x, t, nil);
  320. }
  321. return respond(x, t, "acme: bad version");
  322. # ms := msize(x.fcall);
  323. # if(ms < 256)
  324. # return respond(x, t, "version: message size too small");
  325. # t.msize = messagesize = ms;
  326. # v := version(x.fcall);
  327. # if(len v < 6 || v[0: 6] != "9P2000")
  328. # return respond(x, t, "unrecognized 9P version");
  329. # t.version = "9P2000";
  330. # return respond(x, t, nil);
  331. }
  332. fsysauth(x : ref Xfid) : ref Xfid
  333. {
  334. t : Smsg0;
  335. return respond(x, t, "acme: authentication not required");
  336. }
  337. fsysflush(x : ref Xfid) : ref Xfid
  338. {
  339. x.c <-= Xfidm->Xflush;
  340. return nil;
  341. }
  342. fsysattach(x : ref Xfid, f : ref Fid) : ref Xfid
  343. {
  344. t : Smsg0;
  345. id : int;
  346. m : ref Mntdir;
  347. if (uname(x.fcall) != user)
  348. return respond(x, t, Eperm);
  349. f.busy = TRUE;
  350. f.open = FALSE;
  351. f.qid = (Qid)(big Qdir, 0, QTDIR);
  352. f.dir = dirtab;
  353. f.nrpart = 0;
  354. f.w = nil;
  355. t.qid = f.qid;
  356. f.mntdir = nil;
  357. id = int aname(x.fcall);
  358. mnt.qlock.lock();
  359. for(m=mnt.md; m != nil; m=m.next)
  360. if(m.id == id){
  361. f.mntdir = m;
  362. m.refs++;
  363. break;
  364. }
  365. if(m == nil)
  366. cerr <-= "unknown id in attach";
  367. mnt.qlock.unlock();
  368. return respond(x, t, nil);
  369. }
  370. fsyswalk(x : ref Xfid, f : ref Fid) : ref Xfid
  371. {
  372. t : Smsg0;
  373. c, i, j, id : int;
  374. path, qtype : int;
  375. d, dir : array of Dirtab;
  376. w : ref Window;
  377. nf : ref Fid;
  378. if(f.open)
  379. return respond(x, t, "walk of open file");
  380. if(fid(x.fcall) != newfid(x.fcall)){
  381. nf = allocfid(newfid(x.fcall));
  382. if(nf.busy)
  383. return respond(x, t, "newfid already in use");
  384. nf.busy = TRUE;
  385. nf.open = FALSE;
  386. nf.mntdir = f.mntdir;
  387. if(f.mntdir != nil)
  388. f.mntdir.refs++;
  389. nf.dir = f.dir;
  390. nf.qid = f.qid;
  391. nf.w = f.w;
  392. nf.nrpart = 0; # not open, so must be zero
  393. if(nf.w != nil)
  394. nf.w.refx.inc();
  395. f = nf; # walk f
  396. }
  397. qtype = QTFILE;
  398. wqids: list of Qid;
  399. err := string nil;
  400. id = WIN(f.qid);
  401. q := f.qid;
  402. names := styxaux->names(x.fcall);
  403. nwname := len names;
  404. if(nwname > 0){
  405. for(i = 0; i < nwname; i++){
  406. if((q.qtype & QTDIR) == 0){
  407. err = Enotdir;
  408. break;
  409. }
  410. name := names[i];
  411. if(name == ".."){
  412. path = Qdir;
  413. qtype = QTDIR;
  414. id = 0;
  415. if(w != nil){
  416. w.close();
  417. w = nil;
  418. }
  419. if(i == MAXWELEM){
  420. err = "name too long";
  421. break;
  422. }
  423. q.qtype = qtype;
  424. q.vers = 0;
  425. q.path = big QID(id, path);
  426. wqids = q :: wqids;
  427. continue;
  428. }
  429. # is it a numeric name?
  430. regular := 0;
  431. for(j=0; j < len name; j++) {
  432. c = name[j];
  433. if(c<'0' || '9'<c) {
  434. regular = 1;
  435. break;
  436. }
  437. }
  438. if (!regular) {
  439. # yes: it's a directory
  440. if(w != nil) # name has form 27/23; get out before losing w
  441. break;
  442. id = int name;
  443. row.qlock.lock();
  444. w = lookid(id, FALSE);
  445. if(w == nil){
  446. row.qlock.unlock();
  447. break;
  448. }
  449. w.refx.inc();
  450. path = Qdir;
  451. qtype = QTDIR;
  452. row.qlock.unlock();
  453. dir = dirtabw;
  454. if(i == MAXWELEM){
  455. err = "name too long";
  456. break;
  457. }
  458. q.qtype = qtype;
  459. q.vers = 0;
  460. q.path = big QID(id, path);
  461. wqids = q :: wqids;
  462. continue;
  463. }
  464. else {
  465. # if(FILE(f.qid) == Qacme) # empty directory
  466. # break;
  467. if(name == "new"){
  468. if(w != nil)
  469. error("w set in walk to new");
  470. cw := chan of ref Window;
  471. spawn x.walk(cw);
  472. w = <- cw;
  473. w.refx.inc();
  474. path = QID(w.id, Qdir);
  475. qtype = QTDIR;
  476. id = w.id;
  477. dir = dirtabw;
  478. # x.c <-= Xfidm->Xwalk;
  479. if(i == MAXWELEM){
  480. err = "name too long";
  481. break;
  482. }
  483. q.qtype = qtype;
  484. q.vers = 0;
  485. q.path = big QID(id, path);
  486. wqids = q :: wqids;
  487. continue;
  488. }
  489. if(id == 0)
  490. d = dirtab;
  491. else
  492. d = dirtabw;
  493. k := 1; # skip '.'
  494. found := 0;
  495. for( ; d[k].name != nil; k++){
  496. if(name == d[k].name){
  497. path = d[k].qid;
  498. qtype = d[k].qtype;
  499. dir = d[k:];
  500. if(i == MAXWELEM){
  501. err = "name too long";
  502. break;
  503. }
  504. q.qtype = qtype;
  505. q.vers = 0;
  506. q.path = big QID(id, path);
  507. wqids = q :: wqids;
  508. found = 1;
  509. break;
  510. }
  511. }
  512. if(found)
  513. continue;
  514. break; # file not found
  515. }
  516. }
  517. if(i == 0 && err == nil)
  518. err = Eexist;
  519. }
  520. nwqid := len wqids;
  521. if(nwqid > 0){
  522. t.qids = array[nwqid] of Qid;
  523. for(i = nwqid-1; i >= 0; i--){
  524. t.qids[i] = hd wqids;
  525. wqids = tl wqids;
  526. }
  527. }
  528. if(err != nil || nwqid < nwname){
  529. if(nf != nil){
  530. nf.busy = FALSE;
  531. fsysdelid(nf.mntdir);
  532. }
  533. }
  534. else if(nwqid == nwname){
  535. if(w != nil){
  536. f.w = w;
  537. w = nil;
  538. }
  539. if(dir != nil)
  540. f.dir = dir;
  541. f.qid = q;
  542. }
  543. if(w != nil)
  544. w.close();
  545. return respond(x, t, err);
  546. }
  547. fsysopen(x : ref Xfid, f : ref Fid) : ref Xfid
  548. {
  549. t : Smsg0;
  550. m : int;
  551. # can't truncate anything, so just disregard
  552. setmode(x.fcall, mode(x.fcall)&~OTRUNC);
  553. # can't execute or remove anything
  554. if(mode(x.fcall)&ORCLOSE)
  555. return respond(x, t, Eperm);
  556. case(mode(x.fcall)){
  557. OREAD =>
  558. m = 8r400;
  559. OWRITE =>
  560. m = 8r200;
  561. ORDWR =>
  562. m = 8r600;
  563. * =>
  564. return respond(x, t, Eperm);
  565. }
  566. if(((f.dir[0].perm&~(DMDIR|DMAPPEND))&m) != m)
  567. return respond(x, t, Eperm);
  568. x.c <-= Xfidm->Xopen;
  569. return nil;
  570. }
  571. fsyscreate(x : ref Xfid) : ref Xfid
  572. {
  573. t : Smsg0;
  574. return respond(x, t, Eperm);
  575. }
  576. idcmp(a, b : int) : int
  577. {
  578. return a-b;
  579. }
  580. qsort(a : array of int, n : int)
  581. {
  582. i, j : int;
  583. t : int;
  584. while(n > 1) {
  585. i = n>>1;
  586. t = a[0]; a[0] = a[i]; a[i] = t;
  587. i = 0;
  588. j = n;
  589. for(;;) {
  590. do
  591. i++;
  592. while(i < n && idcmp(a[i], a[0]) < 0);
  593. do
  594. j--;
  595. while(j > 0 && idcmp(a[j], a[0]) > 0);
  596. if(j < i)
  597. break;
  598. t = a[i]; a[i] = a[j]; a[j] = t;
  599. }
  600. t = a[0]; a[0] = a[j]; a[j] = t;
  601. n = n-j-1;
  602. if(j >= n) {
  603. qsort(a, j);
  604. a = a[j+1:];
  605. } else {
  606. qsort(a[j+1:], n);
  607. n = j;
  608. }
  609. }
  610. }
  611. fsysread(x : ref Xfid, f : ref Fid) : ref Xfid
  612. {
  613. t : Smsg0;
  614. b : array of byte;
  615. i, id, n, o, e, j, k, nids : int;
  616. ids : array of int;
  617. d : array of Dirtab;
  618. dt : Dirtab;
  619. c : ref Column;
  620. clock : int;
  621. b = nil;
  622. if(f.qid.qtype & QTDIR){
  623. # if(int offset(x.fcall) % DIRLEN)
  624. # return respond(x, t, "illegal offset in directory");
  625. if(FILE(f.qid) == Qacme){ # empty dir
  626. t.data = nil;
  627. t.count = 0;
  628. respond(x, t, nil);
  629. return x;
  630. }
  631. o = int offset(x.fcall);
  632. e = int offset(x.fcall)+count(x.fcall);
  633. clock = getclock();
  634. b = array[messagesize] of byte;
  635. id = WIN(f.qid);
  636. n = 0;
  637. if(id > 0)
  638. d = dirtabw;
  639. else
  640. d = dirtab;
  641. k = 1; # first entry is '.'
  642. leng := 0;
  643. for(i=0; d[k].name!=nil && i<e; i+=leng){
  644. bb := styx->packdir(dostat(WIN(x.f.qid), d[k], clock));
  645. leng = len bb;
  646. for (kk := 0; kk < leng; kk++)
  647. b[kk+n] = bb[kk];
  648. bb = nil;
  649. if(leng <= Styx->BIT16SZ)
  650. break;
  651. if(i >= o)
  652. n += leng;
  653. k++;
  654. }
  655. if(id == 0){
  656. row.qlock.lock();
  657. nids = 0;
  658. ids = nil;
  659. for(j=0; j<row.ncol; j++){
  660. c = row.col[j];
  661. for(k=0; k<c.nw; k++){
  662. oids := ids;
  663. ids = array[nids+1] of int;
  664. ids[0:] = oids[0:nids];
  665. oids = nil;
  666. ids[nids++] = c.w[k].id;
  667. }
  668. }
  669. row.qlock.unlock();
  670. qsort(ids, nids);
  671. j = 0;
  672. for(; j<nids && i<e; i+=leng){
  673. k = ids[j];
  674. dt.name = sys->sprint("%d", k);
  675. dt.qid = QID(k, 0);
  676. dt.qtype = QTDIR;
  677. dt.perm = DMDIR|8r700;
  678. bb := styx->packdir(dostat(k, dt, clock));
  679. leng = len bb;
  680. for (kk := 0; kk < leng; kk++)
  681. b[kk+n] = bb[kk];
  682. bb = nil;
  683. if(leng == 0)
  684. break;
  685. if(i >= o)
  686. n += leng;
  687. j++;
  688. }
  689. ids = nil;
  690. }
  691. t.data = b;
  692. t.count = n;
  693. respond(x, t, nil);
  694. b = nil;
  695. return x;
  696. }
  697. x.c <-= Xfidm->Xread;
  698. return nil;
  699. }
  700. fsyswrite(x : ref Xfid) : ref Xfid
  701. {
  702. x.c <-= Xfidm->Xwrite;
  703. return nil;
  704. }
  705. fsysclunk(x : ref Xfid, f : ref Fid) : ref Xfid
  706. {
  707. t : Smsg0;
  708. fsysdelid(f.mntdir);
  709. if(f.open){
  710. f.busy = FALSE;
  711. f.open = FALSE;
  712. x.c <-= Xfidm->Xclose;
  713. return nil;
  714. }
  715. if(f.w != nil)
  716. f.w.close();
  717. f.busy = FALSE;
  718. f.open = FALSE;
  719. return respond(x, t, nil);
  720. }
  721. fsysremove(x : ref Xfid) : ref Xfid
  722. {
  723. t : Smsg0;
  724. return respond(x, t, Eperm);
  725. }
  726. fsysstat(x : ref Xfid, f : ref Fid) : ref Xfid
  727. {
  728. t : Smsg0;
  729. t.stat = dostat(WIN(x.f.qid), f.dir[0], getclock());
  730. return respond(x, t, nil);
  731. }
  732. fsyswstat(x : ref Xfid) : ref Xfid
  733. {
  734. t : Smsg0;
  735. return respond(x, t, Eperm);
  736. }
  737. allocfid(fid : int) : ref Fid
  738. {
  739. f, ff : ref Fid;
  740. fh : int;
  741. ff = nil;
  742. fh = fid&(Nhash-1);
  743. for(f=fids[fh]; f != nil; f=f.next)
  744. if(f.fid == fid)
  745. return f;
  746. else if(ff==nil && f.busy==FALSE)
  747. ff = f;
  748. if(ff != nil){
  749. ff.fid = fid;
  750. return ff;
  751. }
  752. f = ref Fid;
  753. f.busy = FALSE;
  754. f.rpart = array[Sys->UTFmax] of byte;
  755. f.nrpart = 0;
  756. f.fid = fid;
  757. f.next = fids[fh];
  758. fids[fh] = f;
  759. return f;
  760. }
  761. cbuf := array[32] of byte;
  762. getclock() : int
  763. {
  764. sys->seek(clockfd, big 0, 0);
  765. n := sys->read(clockfd, cbuf, len cbuf);
  766. return int string cbuf[0:n];
  767. }
  768. dostat(id : int, dir : Dirtab, clock : int) : Sys->Dir
  769. {
  770. d : Dir;
  771. d.qid.path = big QID(id, dir.qid);
  772. d.qid.vers = 0;
  773. d.qid.qtype = dir.qtype;
  774. d.mode = dir.perm;
  775. d.length = big 0; # would be nice to do better
  776. d.name = dir.name;
  777. d.uid = user;
  778. d.gid = user;
  779. d.atime = clock;
  780. d.mtime = clock;
  781. d.dtype = d.dev = 0;
  782. return d;
  783. # buf := styx->convD2M(d);
  784. # d = nil;
  785. # return buf;
  786. }