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