main.c 9.5 KB

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