fsys.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <thread.h>
  12. #include <keyboard.h>
  13. #include <fcall.h>
  14. #include "dat.h"
  15. #include "fns.h"
  16. char Eperm[] = "permission denied";
  17. char Eexist[] = "file does not exist";
  18. char Enotdir[] = "not a directory";
  19. char Ebadfcall[] = "bad fcall type";
  20. char Eoffset[] = "illegal offset";
  21. int messagesize = 8192+IOHDRSZ; /* good start */
  22. enum{
  23. DEBUG = 1
  24. };
  25. Dirtab dirtab[]=
  26. {
  27. { ".", QTDIR, Qdir, 0500|DMDIR },
  28. { "cons", QTFILE, Qcons, 0600 },
  29. { "cursor", QTFILE, Qcursor, 0600 },
  30. { "consctl", QTFILE, Qconsctl, 0200 },
  31. { "winid", QTFILE, Qwinid, 0400 },
  32. { "winname", QTFILE, Qwinname, 0400 },
  33. { "kbdin", QTFILE, Qkbdin, 0200 },
  34. { "label", QTFILE, Qlabel, 0600 },
  35. { "mouse", QTFILE, Qmouse, 0600 },
  36. { "screen", QTFILE, Qscreen, 0400 },
  37. { "snarf", QTFILE, Qsnarf, 0600 },
  38. { "text", QTFILE, Qtext, 0400 },
  39. { "wdir", QTFILE, Qwdir, 0600 },
  40. { "wctl", QTFILE, Qwctl, 0600 },
  41. { "window", QTFILE, Qwindow, 0400 },
  42. { "wsys", QTDIR, Qwsys, 0500|DMDIR },
  43. { nil, }
  44. };
  45. static uint getclock(void);
  46. static void filsysproc(void*);
  47. static Fid* newfid(Filsys*, int);
  48. static int dostat(Filsys*, int, Dirtab*, uint8_t*, int, uint);
  49. int clockfd;
  50. int firstmessage = 1;
  51. static Xfid* filsysflush(Filsys*, Xfid*, Fid*);
  52. static Xfid* filsysversion(Filsys*, Xfid*, Fid*);
  53. static Xfid* filsysauth(Filsys*, Xfid*, Fid*);
  54. static Xfid* filsysattach(Filsys*, Xfid*, Fid*);
  55. static Xfid* filsyswalk(Filsys*, Xfid*, Fid*);
  56. static Xfid* filsysopen(Filsys*, Xfid*, Fid*);
  57. static Xfid* filsyscreate(Filsys*, Xfid*, Fid*);
  58. static Xfid* filsysread(Filsys*, Xfid*, Fid*);
  59. static Xfid* filsyswrite(Filsys*, Xfid*, Fid*);
  60. static Xfid* filsysclunk(Filsys*, Xfid*, Fid*);
  61. static Xfid* filsysremove(Filsys*, Xfid*, Fid*);
  62. static Xfid* filsysstat(Filsys*, Xfid*, Fid*);
  63. static Xfid* filsyswstat(Filsys*, Xfid*, Fid*);
  64. Xfid* (*fcall[Tmax])(Filsys*, Xfid*, Fid*) =
  65. {
  66. [Tflush] = filsysflush,
  67. [Tversion] = filsysversion,
  68. [Tauth] = filsysauth,
  69. [Tattach] = filsysattach,
  70. [Twalk] = filsyswalk,
  71. [Topen] = filsysopen,
  72. [Tcreate] = filsyscreate,
  73. [Tread] = filsysread,
  74. [Twrite] = filsyswrite,
  75. [Tclunk] = filsysclunk,
  76. [Tremove]= filsysremove,
  77. [Tstat] = filsysstat,
  78. [Twstat] = filsyswstat,
  79. };
  80. void
  81. post(char *name, char *envname, int srvfd)
  82. {
  83. print_func_entry();
  84. int fd;
  85. char buf[32];
  86. fd = create(name, OWRITE|ORCLOSE|OCEXEC, 0600);
  87. if(fd < 0)
  88. error(name);
  89. sprint(buf, "%d",srvfd);
  90. if(write(fd, buf, strlen(buf)) != strlen(buf))
  91. error("srv write");
  92. putenv(envname, name);
  93. print_func_exit();
  94. }
  95. /*
  96. * Build pipe with OCEXEC set on second fd.
  97. * Can't put it on both because we want to post one in /srv.
  98. */
  99. int
  100. cexecpipe(int *p0, int *p1)
  101. {
  102. print_func_entry();
  103. /* pipe the hard way to get close on exec */
  104. if(bind("#|", "/mnt/temp", MREPL) < 0) {
  105. print_func_exit();
  106. return -1;
  107. }
  108. *p0 = open("/mnt/temp/data", ORDWR);
  109. *p1 = open("/mnt/temp/data1", ORDWR|OCEXEC);
  110. unmount(nil, "/mnt/temp");
  111. if(*p0<0 || *p1<0) {
  112. print_func_exit();
  113. return -1;
  114. }
  115. print_func_exit();
  116. return 0;
  117. }
  118. Filsys*
  119. filsysinit(Channel *cxfidalloc)
  120. {
  121. print_func_entry();
  122. int n, fd, pid, p0;
  123. Filsys *fs;
  124. Channel *c;
  125. char buf[128];
  126. fs = emalloc(sizeof(Filsys));
  127. if(cexecpipe(&fs->cfd, &fs->sfd) < 0)
  128. goto Rescue;
  129. fmtinstall('F', fcallfmt);
  130. clockfd = open("/dev/time", OREAD|OCEXEC);
  131. fd = open("/dev/user", OREAD);
  132. strcpy(buf, "Jean-Paul_Belmondo");
  133. if(fd >= 0){
  134. n = read(fd, buf, sizeof buf-1);
  135. if(n > 0)
  136. buf[n] = 0;
  137. close(fd);
  138. }
  139. fs->user = estrdup(buf);
  140. fs->cxfidalloc = cxfidalloc;
  141. pid = getpid();
  142. /*
  143. * Create and post wctl pipe
  144. */
  145. if(cexecpipe(&p0, &wctlfd) < 0)
  146. goto Rescue;
  147. sprint(srvwctl, "/srv/riowctl.%s.%d", fs->user, pid);
  148. post(srvwctl, "wctl", p0);
  149. close(p0);
  150. /*
  151. * Start server processes
  152. */
  153. c = chancreate(sizeof(char*), 0);
  154. if(c == nil)
  155. error("wctl channel");
  156. proccreate(wctlproc, c, 4096);
  157. threadcreate(wctlthread, c, 4096);
  158. proccreate(filsysproc, fs, 10000);
  159. /*
  160. * Post srv pipe
  161. */
  162. sprint(srvpipe, "/srv/rio.%s.%d", fs->user, pid);
  163. post(srvpipe, "wsys", fs->cfd);
  164. print_func_exit();
  165. return fs;
  166. Rescue:
  167. free(fs);
  168. print_func_exit();
  169. return nil;
  170. }
  171. static
  172. void
  173. filsysproc(void *arg)
  174. {
  175. print_func_entry();
  176. int n;
  177. Xfid *x;
  178. Fid *f;
  179. Fcall t;
  180. uint8_t *buf;
  181. Filsys *fs;
  182. threadsetname("FILSYSPROC");
  183. fs = arg;
  184. fs->pid = getpid();
  185. x = nil;
  186. for(;;){
  187. buf = emalloc(messagesize+UTFmax); /* UTFmax for appending partial rune in xfidwrite */
  188. n = read9pmsg(fs->sfd, buf, messagesize);
  189. if(n <= 0){
  190. yield(); /* if threadexitsall'ing, will not return */
  191. fprint(2, "rio: %d: read9pmsg: %d %r\n", getpid(), n);
  192. errorshouldabort = 0;
  193. error("eof or i/o error on server channel");
  194. }
  195. if(x == nil){
  196. send(fs->cxfidalloc, nil);
  197. recv(fs->cxfidalloc, &x);
  198. x->fs = fs;
  199. }
  200. x->buf = buf;
  201. if(convM2S(buf, n, x) != n)
  202. error("convert error in convM2S");
  203. if(DEBUG)
  204. fprint(2, "rio:<-%F\n", &x->Fcall);
  205. if(fcall[x->type] == nil)
  206. x = filsysrespond(fs, x, &t, Ebadfcall);
  207. else{
  208. if(x->type==Tversion || x->type==Tauth)
  209. f = nil;
  210. else
  211. f = newfid(fs, x->fid);
  212. x->f = f;
  213. x = (*fcall[x->type])(fs, x, f);
  214. }
  215. firstmessage = 0;
  216. }
  217. print_func_exit();
  218. }
  219. /*
  220. * Called only from a different FD group
  221. */
  222. int
  223. filsysmount(Filsys *fs, int id)
  224. {
  225. print_func_entry();
  226. char buf[32];
  227. close(fs->sfd); /* close server end so mount won't hang if exiting */
  228. sprint(buf, "%d", id);
  229. if(mount(fs->cfd, -1, "/mnt/wsys", MREPL, buf, 'M') < 0){
  230. fprint(2, "mount failed: %r\n");
  231. print_func_exit();
  232. return -1;
  233. }
  234. if(bind("/mnt/wsys", "/dev", MBEFORE) < 0){
  235. fprint(2, "bind failed: %r\n");
  236. print_func_exit();
  237. return -1;
  238. }
  239. print_func_exit();
  240. return 0;
  241. }
  242. Xfid*
  243. filsysrespond(Filsys *fs, Xfid *x, Fcall *t, char *err)
  244. {
  245. print_func_entry();
  246. int n;
  247. if(err){
  248. t->type = Rerror;
  249. t->ename = err;
  250. }else
  251. t->type = x->type+1;
  252. t->fid = x->fid;
  253. t->tag = x->tag;
  254. if(x->buf == nil)
  255. x->buf = malloc(messagesize);
  256. n = convS2M(t, x->buf, messagesize);
  257. if(n <= 0)
  258. error("convert error in convS2M");
  259. if(write(fs->sfd, x->buf, n) != n)
  260. error("write error in respond");
  261. if(DEBUG)
  262. fprint(2, "rio:->%F\n", t);
  263. free(x->buf);
  264. x->buf = nil;
  265. print_func_exit();
  266. return x;
  267. }
  268. void
  269. filsyscancel(Xfid *x)
  270. {
  271. print_func_entry();
  272. if(x->buf){
  273. free(x->buf);
  274. x->buf = nil;
  275. }
  276. print_func_exit();
  277. }
  278. static
  279. Xfid*
  280. filsysversion(Filsys *fs, Xfid *x, Fid* f)
  281. {
  282. print_func_entry();
  283. Fcall t;
  284. if(!firstmessage) {
  285. print_func_exit();
  286. return filsysrespond(x->fs, x, &t, "version request not first message");
  287. }
  288. if(x->msize < 256) {
  289. print_func_exit();
  290. return filsysrespond(x->fs, x, &t, "version: message size too small");
  291. }
  292. messagesize = x->msize;
  293. t.msize = messagesize;
  294. if(strncmp(x->version, "9P2000", 6) != 0) {
  295. print_func_exit();
  296. return filsysrespond(x->fs, x, &t, "unrecognized 9P version");
  297. }
  298. t.version = "9P2000";
  299. print_func_exit();
  300. return filsysrespond(fs, x, &t, nil);
  301. }
  302. static
  303. Xfid*
  304. filsysauth(Filsys *fs, Xfid *x, Fid* f)
  305. {
  306. print_func_entry();
  307. Fcall t;
  308. print_func_exit();
  309. return filsysrespond(fs, x, &t, "rio: authentication not required");
  310. }
  311. static
  312. Xfid*
  313. filsysflush(Filsys* fs, Xfid *x, Fid* f)
  314. {
  315. print_func_entry();
  316. sendp(x->c, xfidflush);
  317. print_func_exit();
  318. return nil;
  319. }
  320. static
  321. Xfid*
  322. filsysattach(Filsys * fs, Xfid *x, Fid *f)
  323. {
  324. print_func_entry();
  325. Fcall t;
  326. if(strcmp(x->uname, x->fs->user) != 0) {
  327. print_func_exit();
  328. return filsysrespond(x->fs, x, &t, Eperm);
  329. }
  330. f->busy = TRUE;
  331. f->open = FALSE;
  332. f->qid.path = Qdir;
  333. f->qid.type = QTDIR;
  334. f->qid.vers = 0;
  335. f->dir = dirtab;
  336. f->nrpart = 0;
  337. sendp(x->c, xfidattach);
  338. print_func_exit();
  339. return nil;
  340. }
  341. static
  342. int
  343. numeric(char *s)
  344. {
  345. print_func_entry();
  346. for(; *s!='\0'; s++)
  347. if(*s<'0' || '9'<*s) {
  348. print_func_exit();
  349. return 0;
  350. }
  351. print_func_exit();
  352. return 1;
  353. }
  354. static
  355. Xfid*
  356. filsyswalk(Filsys *fs, Xfid *x, Fid *f)
  357. {
  358. print_func_entry();
  359. Fcall t;
  360. Fid *nf;
  361. int i, id;
  362. uint8_t type;
  363. uint32_t path;
  364. Dirtab *d, *dir;
  365. Window *w;
  366. char *err;
  367. Qid qid;
  368. if (DEBUG)
  369. fprint(2, "f %p\n", f);
  370. if (! f) {
  371. print_func_exit();
  372. return filsysrespond(fs, x, &t, "NO FID!");
  373. }
  374. if (DEBUG)
  375. fprint(2, "FID %f\n", f);
  376. if(f->open) {
  377. print_func_exit();
  378. return filsysrespond(fs, x, &t, "walk of open file");
  379. }
  380. nf = nil;
  381. if(x->fid != x->newfid){
  382. /* BUG: check exists */
  383. nf = newfid(fs, x->newfid);
  384. if(nf->busy) {
  385. print_func_exit();
  386. return filsysrespond(fs, x, &t, "clone to busy fid");
  387. }
  388. nf->busy = TRUE;
  389. nf->open = FALSE;
  390. nf->dir = f->dir;
  391. nf->qid = f->qid;
  392. nf->w = f->w;
  393. incref(f->w);
  394. nf->nrpart = 0; /* not open, so must be zero */
  395. f = nf; /* walk f */
  396. }
  397. t.nwqid = 0;
  398. err = nil;
  399. /* update f->qid, f->dir only if walk completes */
  400. qid = f->qid;
  401. dir = f->dir;
  402. if(x->nwname > 0){
  403. for(i=0; i<x->nwname; i++){
  404. if((qid.type & QTDIR) == 0){
  405. err = Enotdir;
  406. break;
  407. }
  408. if(strcmp(x->wname[i], "..") == 0){
  409. type = QTDIR;
  410. path = Qdir;
  411. dir = dirtab;
  412. if(FILE(qid) == Qwsysdir)
  413. path = Qwsys;
  414. id = 0;
  415. Accept:
  416. if(i == MAXWELEM){
  417. err = "name too long";
  418. break;
  419. }
  420. qid.type = type;
  421. qid.vers = 0;
  422. qid.path = QID(id, path);
  423. t.wqid[t.nwqid++] = qid;
  424. continue;
  425. }
  426. if(qid.path == Qwsys){
  427. /* is it a numeric name? */
  428. if(!numeric(x->wname[i]))
  429. break;
  430. /* yes: it's a directory */
  431. id = atoi(x->wname[i]);
  432. qlock(&all);
  433. w = wlookid(id);
  434. if(w == nil){
  435. qunlock(&all);
  436. break;
  437. }
  438. path = Qwsysdir;
  439. type = QTDIR;
  440. qunlock(&all);
  441. incref(w);
  442. sendp(winclosechan, f->w);
  443. f->w = w;
  444. dir = dirtab;
  445. goto Accept;
  446. }
  447. if(snarffd>=0 && strcmp(x->wname[i], "snarf")==0)
  448. break; /* don't serve /dev/snarf if it's provided in the environment */
  449. id = WIN(f->qid);
  450. d = dirtab;
  451. d++; /* skip '.' */
  452. for(; d->name; d++)
  453. if(strcmp(x->wname[i], d->name) == 0){
  454. path = d->qid;
  455. type = d->type;
  456. dir = d;
  457. goto Accept;
  458. }
  459. break; /* file not found */
  460. }
  461. if(i==0 && err==nil)
  462. err = Eexist;
  463. }
  464. if(err!=nil || t.nwqid<x->nwname){
  465. if(nf){
  466. if(nf->w)
  467. sendp(winclosechan, nf->w);
  468. nf->open = FALSE;
  469. nf->busy = FALSE;
  470. }
  471. }else if(t.nwqid == x->nwname){
  472. f->dir = dir;
  473. f->qid = qid;
  474. }
  475. print_func_exit();
  476. return filsysrespond(fs, x, &t, err);
  477. }
  478. static
  479. Xfid*
  480. filsysopen(Filsys *fs, Xfid *x, Fid *f)
  481. {
  482. print_func_entry();
  483. Fcall t;
  484. int m;
  485. /* can't truncate anything, so just disregard */
  486. x->mode &= ~(OTRUNC|OCEXEC);
  487. /* can't execute or remove anything */
  488. if(x->mode==OEXEC || (x->mode&ORCLOSE))
  489. goto Deny;
  490. switch(x->mode){
  491. default:
  492. goto Deny;
  493. case OREAD:
  494. m = 0400;
  495. break;
  496. case OWRITE:
  497. m = 0200;
  498. break;
  499. case ORDWR:
  500. m = 0600;
  501. break;
  502. }
  503. if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
  504. goto Deny;
  505. sendp(x->c, xfidopen);
  506. print_func_exit();
  507. return nil;
  508. Deny:
  509. print_func_exit();
  510. return filsysrespond(fs, x, &t, Eperm);
  511. }
  512. static
  513. Xfid*
  514. filsyscreate(Filsys *fs, Xfid *x, Fid*f)
  515. {
  516. print_func_entry();
  517. Fcall t;
  518. print_func_exit();
  519. return filsysrespond(fs, x, &t, Eperm);
  520. }
  521. static
  522. int
  523. idcmp(const void *a, const void *b)
  524. {
  525. print_func_entry();
  526. print_func_exit();
  527. return *(int*)a - *(int*)b;
  528. }
  529. static
  530. Xfid*
  531. filsysread(Filsys *fs, Xfid *x, Fid *f)
  532. {
  533. print_func_entry();
  534. Fcall t;
  535. uint8_t *b;
  536. int i, n, o, e, len, j, k, *ids;
  537. Dirtab *d, dt;
  538. uint clock;
  539. char buf[16];
  540. if((f->qid.type & QTDIR) == 0){
  541. sendp(x->c, xfidread);
  542. print_func_exit();
  543. return nil;
  544. }
  545. o = x->offset;
  546. e = x->offset+x->count;
  547. clock = getclock();
  548. b = malloc(messagesize-IOHDRSZ); /* avoid memset of emalloc */
  549. if(b == nil) {
  550. print_func_exit();
  551. return filsysrespond(fs, x, &t, "out of memory");
  552. }
  553. n = 0;
  554. switch(FILE(f->qid)){
  555. case Qdir:
  556. case Qwsysdir:
  557. d = dirtab;
  558. d++; /* first entry is '.' */
  559. for(i=0; d->name!=nil && i<e; i+=len){
  560. len = dostat(fs, WIN(x->f->qid), d, b+n, x->count-n, clock);
  561. if(len <= BIT16SZ)
  562. break;
  563. if(i >= o)
  564. n += len;
  565. d++;
  566. }
  567. break;
  568. case Qwsys:
  569. qlock(&all);
  570. ids = emalloc(nwindow*sizeof(int));
  571. for(j=0; j<nwindow; j++)
  572. ids[j] = window[j]->id;
  573. qunlock(&all);
  574. qsort(ids, nwindow, sizeof ids[0], idcmp);
  575. dt.name = buf;
  576. for(i=0, j=0; j<nwindow && i<e; i+=len){
  577. k = ids[j];
  578. sprint(dt.name, "%d", k);
  579. dt.qid = QID(k, Qdir);
  580. dt.type = QTDIR;
  581. dt.perm = DMDIR|0700;
  582. len = dostat(fs, k, &dt, b+n, x->count-n, clock);
  583. if(len == 0)
  584. break;
  585. if(i >= o)
  586. n += len;
  587. j++;
  588. }
  589. free(ids);
  590. break;
  591. }
  592. t.data = (char*)b;
  593. t.count = n;
  594. filsysrespond(fs, x, &t, nil);
  595. free(b);
  596. print_func_exit();
  597. return x;
  598. }
  599. static
  600. Xfid*
  601. filsyswrite(Filsys* fs, Xfid *x, Fid*f)
  602. {
  603. print_func_entry();
  604. sendp(x->c, xfidwrite);
  605. print_func_exit();
  606. return nil;
  607. }
  608. static
  609. Xfid*
  610. filsysclunk(Filsys *fs, Xfid *x, Fid *f)
  611. {
  612. print_func_entry();
  613. Fcall t;
  614. if(f->open){
  615. f->busy = FALSE;
  616. f->open = FALSE;
  617. sendp(x->c, xfidclose);
  618. print_func_exit();
  619. return nil;
  620. }
  621. if(f->w)
  622. sendp(winclosechan, f->w);
  623. f->busy = FALSE;
  624. f->open = FALSE;
  625. print_func_exit();
  626. return filsysrespond(fs, x, &t, nil);
  627. }
  628. static
  629. Xfid*
  630. filsysremove(Filsys *fs, Xfid *x, Fid*f)
  631. {
  632. print_func_entry();
  633. Fcall t;
  634. print_func_exit();
  635. return filsysrespond(fs, x, &t, Eperm);
  636. }
  637. static
  638. Xfid*
  639. filsysstat(Filsys *fs, Xfid *x, Fid *f)
  640. {
  641. print_func_entry();
  642. Fcall t;
  643. t.stat = emalloc(messagesize-IOHDRSZ);
  644. t.nstat = dostat(fs, WIN(x->f->qid), f->dir, t.stat, messagesize-IOHDRSZ, getclock());
  645. x = filsysrespond(fs, x, &t, nil);
  646. free(t.stat);
  647. print_func_exit();
  648. return x;
  649. }
  650. static
  651. Xfid*
  652. filsyswstat(Filsys *fs, Xfid *x, Fid*f)
  653. {
  654. print_func_entry();
  655. Fcall t;
  656. print_func_exit();
  657. return filsysrespond(fs, x, &t, Eperm);
  658. }
  659. static
  660. Fid*
  661. newfid(Filsys *fs, int fid)
  662. {
  663. print_func_entry();
  664. Fid *f, *ff, **fh;
  665. ff = nil;
  666. fh = &fs->fids[fid&(Nhash-1)];
  667. for(f=*fh; f; f=f->next)
  668. if(f->fid == fid) {
  669. print_func_exit();
  670. return f;
  671. }
  672. else if(ff==nil && f->busy==FALSE)
  673. ff = f;
  674. if(ff){
  675. ff->fid = fid;
  676. print_func_exit();
  677. return ff;
  678. }
  679. f = emalloc(sizeof *f);
  680. f->fid = fid;
  681. f->next = *fh;
  682. *fh = f;
  683. print_func_exit();
  684. return f;
  685. }
  686. static
  687. uint
  688. getclock(void)
  689. {
  690. print_func_entry();
  691. char buf[32];
  692. seek(clockfd, 0, 0);
  693. read(clockfd, buf, sizeof buf);
  694. print_func_exit();
  695. return atoi(buf);
  696. }
  697. static
  698. int
  699. dostat(Filsys *fs, int id, Dirtab *dir, uint8_t *buf, int nbuf, uint clock)
  700. {
  701. print_func_entry();
  702. Dir d;
  703. d.qid.path = QID(id, dir->qid);
  704. if(dir->qid == Qsnarf)
  705. d.qid.vers = snarfversion;
  706. else
  707. d.qid.vers = 0;
  708. d.qid.type = dir->type;
  709. d.mode = dir->perm;
  710. d.length = 0; /* would be nice to do better */
  711. d.name = dir->name;
  712. d.uid = fs->user;
  713. d.gid = fs->user;
  714. d.muid = fs->user;
  715. d.atime = clock;
  716. d.mtime = clock;
  717. print_func_exit();
  718. return convD2M(&d, buf, nbuf);
  719. }
  720. int
  721. fidfmt(Fmt *f)
  722. {
  723. Fid *fid;
  724. fid = va_arg(f->args, Fid*);
  725. if (! fid)
  726. return fmtprint(f, "<NULL>");
  727. return fmtprint(f, "fid %d, %s%s, %W\n",
  728. fid->fid, fid->busy ? "busy," : "",
  729. fid->open ? "open, " : "",
  730. fid->w);
  731. }