main.c 9.6 KB

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