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