main.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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 <auth.h>
  12. #include <fcall.h>
  13. #include "dat.h"
  14. #include "fns.h"
  15. enum
  16. {
  17. Maxfdata = 8192,
  18. Maxiosize = IOHDRSZ+Maxfdata,
  19. };
  20. void io(int);
  21. void rversion(void);
  22. void rattach(void);
  23. void rauth(void);
  24. void rclunk(void);
  25. void rcreate(void);
  26. void rflush(void);
  27. void ropen(void);
  28. void rread(void);
  29. void rremove(void);
  30. void rsession(void);
  31. void rstat(void);
  32. void rwalk(void);
  33. void rwrite(void);
  34. void rwstat(void);
  35. static int openflags(int);
  36. //static void rmservice(void);
  37. static void usage(void);
  38. #define Reqsize (sizeof(Fcall)+Maxfdata)
  39. Fcall *req;
  40. Fcall *rep;
  41. uint8_t mdata[Maxiosize];
  42. char fdata[Maxfdata];
  43. uint8_t statbuf[STATMAX];
  44. int errno;
  45. static char srvfile[64];
  46. extern Xfsub *xsublist[];
  47. extern int nclust;
  48. jmp_buf err_lab[16];
  49. int nerr_lab;
  50. char err_msg[ERRMAX];
  51. int chatty;
  52. int nojoliet;
  53. int noplan9;
  54. int norock;
  55. void (*fcalls[])(void) = {
  56. [Tversion] = rversion,
  57. [Tflush] = rflush,
  58. [Tauth] = rauth,
  59. [Tattach] = rattach,
  60. [Twalk] = rwalk,
  61. [Topen] = ropen,
  62. [Tcreate] = rcreate,
  63. [Tread] = rread,
  64. [Twrite] = rwrite,
  65. [Tclunk] = rclunk,
  66. [Tremove] = rremove,
  67. [Tstat] = rstat,
  68. [Twstat] = rwstat,
  69. };
  70. void
  71. main(int argc, char **argv)
  72. {
  73. int srvfd, pipefd[2], stdio;
  74. Xfsub **xs;
  75. stdio = 0;
  76. ARGBEGIN {
  77. case '9':
  78. noplan9 = 1;
  79. break;
  80. case 'c':
  81. nclust = atoi(EARGF(usage()));
  82. if (nclust <= 0)
  83. sysfatal("nclust %d non-positive", nclust);
  84. break;
  85. case 'f':
  86. deffile = EARGF(usage());
  87. break;
  88. case 'r':
  89. norock = 1;
  90. break;
  91. case 's':
  92. stdio = 1;
  93. break;
  94. case 'v':
  95. chatty = 1;
  96. break;
  97. case 'J':
  98. nojoliet = 1;
  99. break;
  100. default:
  101. usage();
  102. } ARGEND
  103. switch(argc) {
  104. case 0:
  105. break;
  106. case 1:
  107. srvname = argv[0];
  108. break;
  109. default:
  110. usage();
  111. }
  112. iobuf_init();
  113. for(xs=xsublist; *xs; xs++)
  114. (*(*xs)->reset)();
  115. if(stdio) {
  116. pipefd[0] = 0;
  117. pipefd[1] = 1;
  118. } else {
  119. close(0);
  120. close(1);
  121. open("/dev/null", OREAD);
  122. open("/dev/null", OWRITE);
  123. if(pipe(pipefd) < 0)
  124. panic(1, "pipe");
  125. sprint(srvfile, "/srv/%s", srvname);
  126. srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
  127. if(srvfd < 0)
  128. panic(1, srvfile);
  129. fprint(srvfd, "%d", pipefd[0]);
  130. close(pipefd[0]);
  131. fprint(2, "%s %d: serving %s\n", argv0, getpid(), srvfile);
  132. }
  133. srvfd = pipefd[1];
  134. switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC)){
  135. case -1:
  136. panic(1, "fork");
  137. default:
  138. _exits(0);
  139. case 0:
  140. break;
  141. }
  142. io(srvfd);
  143. exits(0);
  144. }
  145. void
  146. io(int srvfd)
  147. {
  148. int n, pid;
  149. Fcall xreq, xrep;
  150. req = &xreq;
  151. rep = &xrep;
  152. pid = getpid();
  153. fmtinstall('F', fcallfmt);
  154. for(;;){
  155. /*
  156. * reading from a pipe or a network device
  157. * will give an error after a few eof reads.
  158. * however, we cannot tell the difference
  159. * between a zero-length read and an interrupt
  160. * on the processes writing to us,
  161. * so we wait for the error.
  162. */
  163. n = read9pmsg(srvfd, mdata, sizeof mdata);
  164. if(n < 0)
  165. break;
  166. if(n == 0)
  167. continue;
  168. if(convM2S(mdata, n, req) == 0)
  169. continue;
  170. if(chatty)
  171. fprint(2, "9660srv %d:<-%F\n", pid, req);
  172. errno = 0;
  173. if(!waserror()){
  174. err_msg[0] = 0;
  175. if(req->type >= nelem(fcalls) || !fcalls[req->type])
  176. error("bad fcall type");
  177. (*fcalls[req->type])();
  178. poperror();
  179. }
  180. if(err_msg[0]){
  181. rep->type = Rerror;
  182. rep->ename = err_msg;
  183. }else{
  184. rep->type = req->type + 1;
  185. rep->fid = req->fid;
  186. }
  187. rep->tag = req->tag;
  188. if(chatty)
  189. fprint(2, "9660srv %d:->%F\n", pid, rep);
  190. n = convS2M(rep, mdata, sizeof mdata);
  191. if(n == 0)
  192. panic(1, "convS2M error on write");
  193. if(write(srvfd, mdata, n) != n)
  194. panic(1, "mount write");
  195. if(nerr_lab != 0)
  196. panic(0, "err stack %d: %lx %lx %lx %lx %lx %lx", nerr_lab,
  197. err_lab[0][JMPBUFPC], err_lab[1][JMPBUFPC],
  198. err_lab[2][JMPBUFPC], err_lab[3][JMPBUFPC],
  199. err_lab[4][JMPBUFPC], err_lab[5][JMPBUFPC]);
  200. }
  201. chat("server shut down");
  202. }
  203. static void
  204. usage(void)
  205. {
  206. fprint(2, "usage: %s [-v] [-9Jr] [-s] [-f devicefile] [srvname]\n", argv0);
  207. exits("usage");
  208. }
  209. void
  210. error(char *p)
  211. {
  212. strecpy(err_msg, err_msg+sizeof err_msg, p);
  213. nexterror();
  214. }
  215. void
  216. nexterror(void)
  217. {
  218. longjmp(err_lab[--nerr_lab], 1);
  219. }
  220. void*
  221. ealloc(int32_t n)
  222. {
  223. void *p;
  224. p = malloc(n);
  225. if(p == 0)
  226. error("no memory");
  227. return p;
  228. }
  229. void
  230. setnames(Dir *d, char *n)
  231. {
  232. d->name = n;
  233. d->uid = n+Maxname;
  234. d->gid = n+Maxname*2;
  235. d->muid = n+Maxname*3;
  236. d->name[0] = '\0';
  237. d->uid[0] = '\0';
  238. d->gid[0] = '\0';
  239. d->muid[0] = '\0';
  240. }
  241. void
  242. rversion(void)
  243. {
  244. if(req->msize > Maxiosize)
  245. rep->msize = Maxiosize;
  246. else
  247. rep->msize = req->msize;
  248. rep->version = "9P2000";
  249. }
  250. void
  251. rauth(void)
  252. {
  253. error("9660srv: authentication not required");
  254. }
  255. void
  256. rflush(void)
  257. {
  258. }
  259. void
  260. rattach(void)
  261. {
  262. Xfs *xf;
  263. Xfile *root;
  264. Xfsub **xs;
  265. chat("attach(fid=%d,uname=\"%s\",aname=\"%s\")...",
  266. req->fid, req->uname, req->aname);
  267. if(waserror()){
  268. xfile(req->fid, Clunk);
  269. nexterror();
  270. }
  271. root = xfile(req->fid, Clean);
  272. root->qid = (Qid){0, 0, QTDIR};
  273. root->xf = xf = ealloc(sizeof(Xfs));
  274. memset(xf, 0, sizeof(Xfs));
  275. xf->ref = 1;
  276. xf->d = getxdata(req->aname);
  277. for(xs=xsublist; *xs; xs++)
  278. if((*(*xs)->attach)(root) >= 0){
  279. poperror();
  280. xf->s = *xs;
  281. xf->rootqid = root->qid;
  282. rep->qid = root->qid;
  283. return;
  284. }
  285. error("unknown format");
  286. }
  287. Xfile*
  288. doclone(Xfile *of, int newfid)
  289. {
  290. Xfile *nf, *next;
  291. nf = xfile(newfid, Clean);
  292. if(waserror()){
  293. xfile(newfid, Clunk);
  294. nexterror();
  295. }
  296. next = nf->next;
  297. *nf = *of;
  298. nf->next = next;
  299. nf->fid = newfid;
  300. refxfs(nf->xf, 1);
  301. if(nf->len){
  302. nf->ptr = ealloc(nf->len);
  303. memmove(nf->ptr, of->ptr, nf->len);
  304. }else
  305. nf->ptr = of->ptr;
  306. (*of->xf->s->clone)(of, nf);
  307. poperror();
  308. return nf;
  309. }
  310. void
  311. rwalk(void)
  312. {
  313. Xfile *f, *nf;
  314. Isofile *oldptr;
  315. int oldlen;
  316. Qid oldqid;
  317. rep->nwqid = 0;
  318. nf = nil;
  319. f = xfile(req->fid, Asis);
  320. if(req->fid != req->newfid)
  321. f = nf = doclone(f, req->newfid);
  322. /* save old state in case of error */
  323. oldqid = f->qid;
  324. oldlen = f->len;
  325. oldptr = f->ptr;
  326. if(oldlen){
  327. oldptr = ealloc(oldlen);
  328. memmove(oldptr, f->ptr, oldlen);
  329. }
  330. if(waserror()){
  331. /*
  332. * if nf != nil, nf == f, which is derived from req->newfid,
  333. * so we can't clunk req->newfid with xfile, which would put
  334. * f back on the free list, until we're done with f below.
  335. */
  336. if(rep->nwqid == req->nwname){
  337. if(oldlen)
  338. free(oldptr);
  339. }else{
  340. /* restore previous state */
  341. f->qid = oldqid;
  342. if(f->len)
  343. free(f->ptr);
  344. f->ptr = oldptr;
  345. f->len = oldlen;
  346. }
  347. if(nf != nil)
  348. xfile(req->newfid, Clunk);
  349. if(rep->nwqid==req->nwname || rep->nwqid > 0){
  350. err_msg[0] = '\0';
  351. return;
  352. }
  353. nexterror();
  354. }
  355. for(rep->nwqid=0; rep->nwqid < req->nwname && rep->nwqid < MAXWELEM; rep->nwqid++){
  356. chat("\twalking %s\n", req->wname[rep->nwqid]);
  357. if(!(f->qid.type & QTDIR)){
  358. chat("\tnot dir: type=%#x\n", f->qid.type);
  359. error("walk in non-directory");
  360. }
  361. if(strcmp(req->wname[rep->nwqid], "..")==0){
  362. if(f->qid.path != f->xf->rootqid.path)
  363. (*f->xf->s->walkup)(f);
  364. }else
  365. (*f->xf->s->walk)(f, req->wname[rep->nwqid]);
  366. rep->wqid[rep->nwqid] = f->qid;
  367. }
  368. poperror();
  369. if(oldlen)
  370. free(oldptr);
  371. }
  372. void
  373. ropen(void)
  374. {
  375. Xfile *f;
  376. f = xfile(req->fid, Asis);
  377. if(f->flags&Omodes)
  378. error("open on open file");
  379. if(req->mode&ORCLOSE)
  380. error("no removes");
  381. (*f->xf->s->open)(f, req->mode);
  382. f->flags = openflags(req->mode);
  383. rep->qid = f->qid;
  384. rep->iounit = 0;
  385. }
  386. void
  387. rcreate(void)
  388. {
  389. error("no creates");
  390. /*
  391. Xfile *f;
  392. if(strcmp(req->name, ".") == 0 || strcmp(req->name, "..") == 0)
  393. error("create . or ..");
  394. f = xfile(req->fid, Asis);
  395. if(f->flags&Omodes)
  396. error("create on open file");
  397. if(!(f->qid.path&CHDIR))
  398. error("create in non-directory");
  399. (*f->xf->s->create)(f, req->name, req->perm, req->mode);
  400. chat("f->qid=0x%8.8lux...", f->qid.path);
  401. f->flags = openflags(req->mode);
  402. rep->qid = f->qid;
  403. */
  404. }
  405. void
  406. rread(void)
  407. {
  408. Xfile *f;
  409. f=xfile(req->fid, Asis);
  410. if (!(f->flags&Oread))
  411. error("file not opened for reading");
  412. if(f->qid.type & QTDIR)
  413. rep->count = (*f->xf->s->readdir)(f, (uint8_t*)fdata,
  414. req->offset, req->count);
  415. else
  416. rep->count = (*f->xf->s->read)(f, fdata, req->offset, req->count);
  417. rep->data = fdata;
  418. }
  419. void
  420. rwrite(void)
  421. {
  422. Xfile *f;
  423. f=xfile(req->fid, Asis);
  424. if(!(f->flags&Owrite))
  425. error("file not opened for writing");
  426. rep->count = (*f->xf->s->write)(f, req->data, req->offset, req->count);
  427. }
  428. void
  429. rclunk(void)
  430. {
  431. Xfile *f;
  432. if(!waserror()){
  433. f = xfile(req->fid, Asis);
  434. (*f->xf->s->clunk)(f);
  435. poperror();
  436. }
  437. xfile(req->fid, Clunk);
  438. }
  439. void
  440. rremove(void)
  441. {
  442. error("no removes");
  443. }
  444. void
  445. rstat(void)
  446. {
  447. Xfile *f;
  448. Dir dir;
  449. chat("stat(fid=%d)...", req->fid);
  450. f=xfile(req->fid, Asis);
  451. setnames(&dir, fdata);
  452. (*f->xf->s->stat)(f, &dir);
  453. if(chatty)
  454. showdir(2, &dir);
  455. rep->nstat = convD2M(&dir, statbuf, sizeof statbuf);
  456. rep->stat = statbuf;
  457. }
  458. void
  459. rwstat(void)
  460. {
  461. error("no wstat");
  462. }
  463. static int
  464. openflags(int mode)
  465. {
  466. int flags = 0;
  467. switch(mode & ~(OTRUNC|OCEXEC|ORCLOSE)){
  468. case OREAD:
  469. case OEXEC:
  470. flags = Oread; break;
  471. case OWRITE:
  472. flags = Owrite; break;
  473. case ORDWR:
  474. flags = Oread|Owrite; break;
  475. }
  476. if(mode & ORCLOSE)
  477. flags |= Orclose;
  478. return flags;
  479. }
  480. void
  481. showdir(int fd, Dir *s)
  482. {
  483. char a_time[32], m_time[32];
  484. char *p;
  485. strcpy(a_time, ctime(s->atime));
  486. if(p=strchr(a_time, '\n')) /* assign = */
  487. *p = 0;
  488. strcpy(m_time, ctime(s->mtime));
  489. if(p=strchr(m_time, '\n')) /* assign = */
  490. *p = 0;
  491. fprint(fd, "name=\"%s\" qid=(0x%llux,%lu) type=%d dev=%d \
  492. mode=0x%8.8lux=0%luo atime=%s mtime=%s length=%lld uid=\"%s\" gid=\"%s\"...",
  493. s->name, s->qid.path, s->qid.vers, s->type, s->dev,
  494. s->mode, s->mode,
  495. a_time, m_time, s->length, s->uid, s->gid);
  496. }
  497. #define SIZE 1024
  498. void
  499. chat(char *fmt, ...)
  500. {
  501. va_list arg;
  502. if(chatty){
  503. va_start(arg, fmt);
  504. vfprint(2, fmt, arg);
  505. va_end(arg);
  506. }
  507. }
  508. void
  509. panic(int rflag, char *fmt, ...)
  510. {
  511. va_list arg;
  512. char buf[SIZE]; int n;
  513. n = sprint(buf, "%s %d: ", argv0, getpid());
  514. va_start(arg, fmt);
  515. vseprint(buf+n, buf+SIZE, fmt, arg);
  516. va_end(arg);
  517. fprint(2, (rflag ? "%s: %r\n" : "%s\n"), buf);
  518. if(chatty){
  519. fprint(2, "abort\n");
  520. abort();
  521. }
  522. exits("panic");
  523. }