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