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