1 /* already in plan9.h #include <sys/types.h> *//* for struct passwd, struct group, struct stat ... */ 2 /* plan9.h is first to get the large file support definitions as early as possible */ 3 #include <plan9.h> 4 #include <sys/stat.h> /* for stat, umask */ 5 #include <stdlib.h> /* for malloc */ 6 #include <string.h> /* for strcpy, memmove */ 7 #include <pwd.h> /* for getpwnam, getpwuid */ 8 #include <grp.h> /* for getgrnam, getgrgid */ 9 #include <unistd.h> /* for gethostname, pread, pwrite, read, write */ 10 #include <utime.h> /* for utime */ 11 #include <dirent.h> /* for readdir */ 12 #include <errno.h> /* for errno */ 13 #include <stdio.h> /* for remove [sic] */ 14 #include <fcntl.h> /* for O_RDONLY, etc. */ 15 16 #include <sys/socket.h> /* various networking crud */ 17 #include <netinet/in.h> 18 #include <netdb.h> 19 20 #include <fcall.h> 21 #include <oldfcall.h> 22 #include <u9fs.h> 23 24 /* #ifndef because can be given in makefile */ 25 #ifndef DEFAULTLOG 26 #define DEFAULTLOG "/tmp/u9fs.log" 27 #endif 28 29 char *logfile = DEFAULTLOG; 30 31 #define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m)) 32 33 enum { 34 Tdot = 1, 35 Tdotdot 36 }; 37 38 enum { 39 P9P1, 40 P9P2000 41 }; 42 43 typedef struct User User; 44 struct User { 45 int id; 46 gid_t defaultgid; 47 char *name; 48 char **mem; /* group members */ 49 int nmem; 50 User *next; 51 }; 52 53 struct Fid { 54 int fid; 55 char *path; 56 struct stat st; 57 User *u; 58 int omode; 59 DIR *dir; 60 int diroffset; 61 int fd; 62 struct dirent *dirent; 63 int direof; 64 Fid *next; 65 Fid *prev; 66 int auth; 67 void *authmagic; 68 }; 69 70 void* emalloc(size_t); 71 void* erealloc(void*, size_t); 72 char* estrdup(char*); 73 char* estrpath(char*, char*, int); 74 void sysfatal(char*, ...); 75 int okuser(char*); 76 77 void rversion(Fcall*, Fcall*); 78 void rauth(Fcall*, Fcall*); 79 void rattach(Fcall*, Fcall*); 80 void rflush(Fcall*, Fcall*); 81 void rclone(Fcall*, Fcall*); 82 void rwalk(Fcall*, Fcall*); 83 void ropen(Fcall*, Fcall*); 84 void rcreate(Fcall*, Fcall*); 85 void rread(Fcall*, Fcall*); 86 void rwrite(Fcall*, Fcall*); 87 void rclunk(Fcall*, Fcall*); 88 void rstat(Fcall*, Fcall*); 89 void rwstat(Fcall*, Fcall*); 90 void rclwalk(Fcall*, Fcall*); 91 void rremove(Fcall*, Fcall*); 92 93 User* uname2user(char*); 94 User* gname2user(char*); 95 User* uid2user(int); 96 User* gid2user(int); 97 98 Fid* newfid(int, char**); 99 Fid* oldfidex(int, int, char**); 100 Fid* oldfid(int, char**); 101 int fidstat(Fid*, char**); 102 void freefid(Fid*); 103 104 int userchange(User*, char**); 105 int userwalk(User*, char**, char*, Qid*, char**); 106 int useropen(Fid*, int, char**); 107 int usercreate(Fid*, char*, int, long, char**); 108 int userremove(Fid*, char**); 109 int userperm(User*, char*, int, int); 110 int useringroup(User*, User*); 111 112 Qid stat2qid(struct stat*); 113 114 void getfcallold(int, Fcall*, int); 115 void putfcallold(int, Fcall*); 116 117 char Eauth[] = "authentication failed"; 118 char Ebadfid[] = "fid unknown or out of range"; 119 char Ebadoffset[] = "bad offset in directory read"; 120 char Ebadusefid[] = "bad use of fid"; 121 char Edirchange[] = "wstat can't convert between files and directories"; 122 char Eexist[] = "file or directory already exists"; 123 char Efidactive[] = "fid already in use"; 124 char Enotdir[] = "not a directory"; 125 char Enotingroup[] = "not a member of proposed group"; 126 char Enotowner[] = "only owner can change group in wstat"; 127 char Eperm[] = "permission denied"; 128 char Especial0[] = "already attached without access to special files"; 129 char Especial1[] = "already attached with access to special files"; 130 char Especial[] = "no access to special file"; 131 char Etoolarge[] = "i/o count too large"; 132 char Eunknowngroup[] = "unknown group"; 133 char Eunknownuser[] = "unknown user"; 134 char Ewstatbuffer[] = "bogus wstat buffer"; 135 136 ulong msize = IOHDRSZ+8192; 137 uchar* rxbuf; 138 uchar* txbuf; 139 void* databuf; 140 int connected; 141 int devallowed; 142 char* autharg; 143 char* defaultuser; 144 char hostname[256]; 145 char remotehostname[256]; 146 int chatty9p = 0; 147 int network = 1; 148 int old9p = -1; 149 int authed; 150 User* none; 151 152 Auth *authmethods[] = { /* first is default */ 153 &authrhosts, 154 &authp9any, 155 &authnone, 156 }; 157 158 Auth *auth; 159 160 /* 161 * frogs: characters not valid in plan9 162 * filenames, keep this list in sync with 163 * /sys/src/9/port/chan.c:1656 164 */ 165 char isfrog[256]={ 166 /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, 167 /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, 168 /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, 169 /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, 170 ['/'] 1, 171 [0x7f] 1, 172 }; 173 174 void 175 getfcallnew(int fd, Fcall *fc, int have) 176 { 177 int len; 178 179 if(have > BIT32SZ) 180 sysfatal("cannot happen"); 181 182 if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have) 183 sysfatal("couldn't read message"); 184 185 len = GBIT32(rxbuf); 186 if(len <= BIT32SZ) 187 sysfatal("bogus message"); 188 189 len -= BIT32SZ; 190 if(readn(fd, rxbuf+BIT32SZ, len) != len) 191 sysfatal("short message"); 192 193 if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ) 194 sysfatal("badly sized message type %d", rxbuf[0]); 195 } 196 197 void 198 getfcallold(int fd, Fcall *fc, int have) 199 { 200 int len, n; 201 202 if(have > 3) 203 sysfatal("cannot happen"); 204 205 if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have) 206 sysfatal("couldn't read message"); 207 208 len = oldhdrsize(rxbuf[0]); 209 if(len < 3) 210 sysfatal("bad message %d", rxbuf[0]); 211 if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3) 212 sysfatal("couldn't read message"); 213 214 n = iosize(rxbuf); 215 if(readn(fd, rxbuf+len, n) != n) 216 sysfatal("couldn't read message"); 217 len += n; 218 219 if(convM2Sold(rxbuf, len, fc) != len) 220 sysfatal("badly sized message type %d", rxbuf[0]); 221 } 222 223 void 224 putfcallnew(int wfd, Fcall *tx) 225 { 226 uint n; 227 228 if((n = convS2M(tx, txbuf, msize)) == 0) 229 sysfatal("couldn't format message type %d", tx->type); 230 if(write(wfd, txbuf, n) != n) 231 sysfatal("couldn't send message"); 232 } 233 234 void 235 putfcallold(int wfd, Fcall *tx) 236 { 237 uint n; 238 239 if((n = convS2Mold(tx, txbuf, msize)) == 0) 240 sysfatal("couldn't format message type %d", tx->type); 241 if(write(wfd, txbuf, n) != n) 242 sysfatal("couldn't send message"); 243 } 244 245 void 246 getfcall(int fd, Fcall *fc) 247 { 248 if(old9p == 1){ 249 getfcallold(fd, fc, 0); 250 return; 251 } 252 if(old9p == 0){ 253 getfcallnew(fd, fc, 0); 254 return; 255 } 256 257 /* auto-detect */ 258 if(readn(fd, rxbuf, 3) != 3) 259 sysfatal("couldn't read message"); 260 261 /* is it an old (9P1) message? */ 262 if(50 <= rxbuf[0] && rxbuf[0] <= 87 && (rxbuf[0]&1)==0 && GBIT16(rxbuf+1) == 0xFFFF){ 263 old9p = 1; 264 getfcallold(fd, fc, 3); 265 return; 266 } 267 268 getfcallnew(fd, fc, 3); 269 old9p = 0; 270 } 271 272 void 273 seterror(Fcall *f, char *error) 274 { 275 f->type = Rerror; 276 f->ename = error ? error : "programmer error"; 277 } 278 279 int 280 isowner(User *u, Fid *f) 281 { 282 return u->id == f->st.st_uid; 283 } 284 285 286 287 void 288 serve(int rfd, int wfd) 289 { 290 Fcall rx, tx; 291 292 for(;;){ 293 getfcall(rfd, &rx); 294 295 if(chatty9p) 296 fprint(2, "<- %F\n", &rx); 297 298 memset(&tx, 0, sizeof tx); 299 tx.type = rx.type+1; 300 tx.tag = rx.tag; 301 switch(rx.type){ 302 case Tflush: 303 break; 304 case Tversion: 305 rversion(&rx, &tx); 306 break; 307 case Tauth: 308 rauth(&rx, &tx); 309 break; 310 case Tattach: 311 rattach(&rx, &tx); 312 break; 313 case Twalk: 314 rwalk(&rx, &tx); 315 break; 316 case Tstat: 317 tx.stat = databuf; 318 rstat(&rx, &tx); 319 break; 320 case Twstat: 321 rwstat(&rx, &tx); 322 break; 323 case Topen: 324 ropen(&rx, &tx); 325 break; 326 case Tcreate: 327 rcreate(&rx, &tx); 328 break; 329 case Tread: 330 tx.data = databuf; 331 rread(&rx, &tx); 332 break; 333 case Twrite: 334 rwrite(&rx, &tx); 335 break; 336 case Tclunk: 337 rclunk(&rx, &tx); 338 break; 339 case Tremove: 340 rremove(&rx, &tx); 341 break; 342 default: 343 fprint(2, "unknown message %F\n", &rx); 344 seterror(&tx, "bad message"); 345 break; 346 } 347 348 if(chatty9p) 349 fprint(2, "-> %F\n", &tx); 350 351 (old9p ? putfcallold : putfcallnew)(wfd, &tx); 352 } 353 } 354 355 void 356 rversion(Fcall *rx, Fcall *tx) 357 { 358 if(msize > rx->msize) 359 msize = rx->msize; 360 tx->msize = msize; 361 if(strncmp(rx->version, "9P", 2) != 0) 362 tx->version = "unknown"; 363 else 364 tx->version = "9P2000"; 365 } 366 367 void 368 rauth(Fcall *rx, Fcall *tx) 369 { 370 char *e; 371 372 if((e = auth->auth(rx, tx)) != nil) 373 seterror(tx, e); 374 } 375 376 void 377 rattach(Fcall *rx, Fcall *tx) 378 { 379 char *e; 380 Fid *fid; 381 User *u; 382 383 if(rx->aname == nil) 384 rx->aname = ""; 385 386 if(strcmp(rx->aname, "device") == 0){ 387 if(connected && !devallowed){ 388 seterror(tx, Especial0); 389 return; 390 } 391 devallowed = 1; 392 }else{ 393 if(connected && devallowed){ 394 seterror(tx, Especial1); 395 return; 396 } 397 } 398 399 if(strcmp(rx->uname, "none") == 0){ 400 if(authed == 0){ 401 seterror(tx, Eauth); 402 return; 403 } 404 if (none != nil) 405 rx->uname = none->name; 406 } else { 407 if((e = auth->attach(rx, tx)) != nil){ 408 seterror(tx, e); 409 return; 410 } 411 authed++; 412 } 413 414 if((fid = newfid(rx->fid, &e)) == nil){ 415 seterror(tx, e); 416 return; 417 } 418 fid->path = estrdup("/"); 419 if(fidstat(fid, &e) < 0){ 420 seterror(tx, e); 421 freefid(fid); 422 return; 423 } 424 425 if(defaultuser) 426 rx->uname = defaultuser; 427 428 if((u = uname2user(rx->uname)) == nil 429 || (!defaultuser && u->id == 0)){ 430 /* we don't know anyone named root... */ 431 seterror(tx, Eunknownuser); 432 freefid(fid); 433 return; 434 } 435 436 fid->u = u; 437 tx->qid = stat2qid(&fid->st); 438 return; 439 } 440 441 void 442 rwalk(Fcall *rx, Fcall *tx) 443 { 444 int i; 445 char *path, *e; 446 Fid *fid, *nfid; 447 448 e = nil; 449 if((fid = oldfid(rx->fid, &e)) == nil){ 450 seterror(tx, e); 451 return; 452 } 453 454 if(fid->omode != -1){ 455 seterror(tx, Ebadusefid); 456 return; 457 } 458 459 if(fidstat(fid, &e) < 0){ 460 seterror(tx, e); 461 return; 462 } 463 464 if(!S_ISDIR(fid->st.st_mode) && rx->nwname){ 465 seterror(tx, Enotdir); 466 return; 467 } 468 469 nfid = nil; 470 if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){ 471 seterror(tx, e); 472 return; 473 } 474 475 path = estrdup(fid->path); 476 e = nil; 477 for(i=0; i<rx->nwname; i++) 478 if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0) 479 break; 480 481 if(i == rx->nwname){ /* successful clone or walk */ 482 tx->nwqid = i; 483 if(nfid){ 484 nfid->path = path; 485 nfid->u = fid->u; 486 }else{ 487 free(fid->path); 488 fid->path = path; 489 } 490 }else{ 491 if(i > 0) /* partial walk? */ 492 tx->nwqid = i; 493 else 494 seterror(tx, e); 495 496 if(nfid) /* clone implicit new fid */ 497 freefid(nfid); 498 free(path); 499 } 500 return; 501 } 502 503 void 504 ropen(Fcall *rx, Fcall *tx) 505 { 506 char *e; 507 Fid *fid; 508 509 if((fid = oldfid(rx->fid, &e)) == nil){ 510 seterror(tx, e); 511 return; 512 } 513 514 if(fid->omode != -1){ 515 seterror(tx, Ebadusefid); 516 return; 517 } 518 519 if(fidstat(fid, &e) < 0){ 520 seterror(tx, e); 521 return; 522 } 523 524 if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){ 525 seterror(tx, Especial); 526 return; 527 } 528 529 if(useropen(fid, rx->mode, &e) < 0){ 530 seterror(tx, e); 531 return; 532 } 533 534 tx->iounit = 0; 535 tx->qid = stat2qid(&fid->st); 536 } 537 538 void 539 rcreate(Fcall *rx, Fcall *tx) 540 { 541 char *e; 542 Fid *fid; 543 544 if((fid = oldfid(rx->fid, &e)) == nil){ 545 seterror(tx, e); 546 return; 547 } 548 549 if(fid->omode != -1){ 550 seterror(tx, Ebadusefid); 551 return; 552 } 553 554 if(fidstat(fid, &e) < 0){ 555 seterror(tx, e); 556 return; 557 } 558 559 if(!S_ISDIR(fid->st.st_mode)){ 560 seterror(tx, Enotdir); 561 return; 562 } 563 564 if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){ 565 seterror(tx, e); 566 return; 567 } 568 569 if(fidstat(fid, &e) < 0){ 570 seterror(tx, e); 571 return; 572 } 573 574 tx->iounit = 0; 575 tx->qid = stat2qid(&fid->st); 576 } 577 578 uchar 579 modebyte(struct stat *st) 580 { 581 uchar b; 582 583 b = 0; 584 585 if(S_ISDIR(st->st_mode)) 586 b |= QTDIR; 587 588 /* no way to test append-only */ 589 /* no real way to test exclusive use, but mark devices as such */ 590 if(S_ISSPECIAL(st->st_mode)) 591 b |= QTEXCL; 592 593 return b; 594 } 595 596 ulong 597 plan9mode(struct stat *st) 598 { 599 return ((ulong)modebyte(st)<<24) | (st->st_mode & 0777); 600 } 601 602 /* 603 * this is for chmod, so don't worry about S_IFDIR 604 */ 605 mode_t 606 unixmode(Dir *d) 607 { 608 return (mode_t)(d->mode&0777); 609 } 610 611 Qid 612 stat2qid(struct stat *st) 613 { 614 uchar *p, *ep, *q; 615 Qid qid; 616 617 /* 618 * For now, ignore the device number. 619 */ 620 qid.path = 0; 621 p = (uchar*)&qid.path; 622 ep = p+sizeof(qid.path); 623 q = p+sizeof(ino_t); 624 if(q > ep){ 625 fprint(2, "warning: inode number too big\n"); 626 q = ep; 627 } 628 memmove(p, &st->st_ino, q-p); 629 q = q+sizeof(dev_t); 630 if(q > ep){ 631 /* 632 * fprint(2, "warning: inode number + device number too big %d+%d\n", 633 * sizeof(ino_t), sizeof(dev_t)); 634 */ 635 q = ep - sizeof(dev_t); 636 if(q < p) 637 fprint(2, "warning: device number too big by itself\n"); 638 else 639 *(dev_t*)q ^= st->st_dev; 640 } 641 642 qid.vers = st->st_mtime ^ (st->st_size << 8); 643 qid.type = modebyte(st); 644 return qid; 645 } 646 647 char * 648 enfrog(char *src) 649 { 650 char *d, *dst; 651 uchar *s; 652 653 d = dst = emalloc(strlen(src)*3 + 1); 654 for (s = (uchar *)src; *s; s++) 655 if(isfrog[*s] || *s == '\\') 656 d += sprintf(d, "\\%02x", *s); 657 else 658 *d++ = *s; 659 *d = 0; 660 return dst; 661 } 662 663 char * 664 defrog(char *s) 665 { 666 char *d, *dst, buf[3]; 667 668 d = dst = emalloc(strlen(s) + 1); 669 for(; *s; s++) 670 if(*s == '\\' && strlen(s) >= 3){ 671 buf[0] = *++s; /* skip \ */ 672 buf[1] = *++s; 673 buf[2] = 0; 674 *d++ = strtoul(buf, NULL, 16); 675 } else 676 *d++ = *s; 677 *d = 0; 678 return dst; 679 } 680 681 void 682 stat2dir(char *path, struct stat *st, Dir *d) 683 { 684 User *u; 685 char *q, *p, *npath; 686 687 memset(d, 0, sizeof(*d)); 688 d->qid = stat2qid(st); 689 d->mode = plan9mode(st); 690 d->atime = st->st_atime; 691 d->mtime = st->st_mtime; 692 d->length = st->st_size; 693 694 d->uid = (u = uid2user(st->st_uid)) ? u->name : "???"; 695 d->gid = (u = gid2user(st->st_gid)) ? u->name : "???"; 696 d->muid = ""; 697 698 if((q = strrchr(path, '/')) != nil) 699 d->name = enfrog(q+1); 700 else 701 d->name = enfrog(path); 702 } 703 704 void 705 rread(Fcall *rx, Fcall *tx) 706 { 707 char *e, *path; 708 uchar *p, *ep; 709 int n; 710 Fid *fid; 711 Dir d; 712 struct stat st; 713 714 if(rx->count > msize-IOHDRSZ){ 715 seterror(tx, Etoolarge); 716 return; 717 } 718 719 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 720 seterror(tx, e); 721 return; 722 } 723 724 if (fid->auth) { 725 char *e; 726 e = auth->read(rx, tx); 727 if (e) 728 seterror(tx, e); 729 return; 730 } 731 732 if(fid->omode == -1 || (fid->omode&3) == OWRITE){ 733 seterror(tx, Ebadusefid); 734 return; 735 } 736 737 if(fid->dir){ 738 if(rx->offset != fid->diroffset){ 739 if(rx->offset != 0){ 740 seterror(tx, Ebadoffset); 741 return; 742 } 743 rewinddir(fid->dir); 744 fid->diroffset = 0; 745 fid->direof = 0; 746 } 747 if(fid->direof){ 748 tx->count = 0; 749 return; 750 } 751 752 p = (uchar*)tx->data; 753 ep = (uchar*)tx->data+rx->count; 754 for(;;){ 755 if(p+BIT16SZ >= ep) 756 break; 757 if(fid->dirent == nil) /* one entry cache for when convD2M fails */ 758 if((fid->dirent = readdir(fid->dir)) == nil){ 759 fid->direof = 1; 760 break; 761 } 762 if(strcmp(fid->dirent->d_name, ".") == 0 763 || strcmp(fid->dirent->d_name, "..") == 0){ 764 fid->dirent = nil; 765 continue; 766 } 767 path = estrpath(fid->path, fid->dirent->d_name, 0); 768 memset(&st, 0, sizeof st); 769 if(stat(path, &st) < 0){ 770 fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno)); 771 fid->dirent = nil; 772 free(path); 773 continue; 774 } 775 free(path); 776 stat2dir(fid->dirent->d_name, &st, &d); 777 if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ) 778 break; 779 p += n; 780 fid->dirent = nil; 781 } 782 tx->count = p - (uchar*)tx->data; 783 fid->diroffset += tx->count; 784 }else{ 785 if((n = pread(fid->fd, tx->data, rx->count, rx->offset)) < 0){ 786 seterror(tx, strerror(errno)); 787 return; 788 } 789 tx->count = n; 790 } 791 } 792 793 void 794 rwrite(Fcall *rx, Fcall *tx) 795 { 796 char *e; 797 Fid *fid; 798 int n; 799 800 if(rx->count > msize-IOHDRSZ){ 801 seterror(tx, Etoolarge); 802 return; 803 } 804 805 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 806 seterror(tx, e); 807 return; 808 } 809 810 if (fid->auth) { 811 char *e; 812 e = auth->write(rx, tx); 813 if (e) 814 seterror(tx, e); 815 return; 816 } 817 818 if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){ 819 seterror(tx, Ebadusefid); 820 return; 821 } 822 823 if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){ 824 seterror(tx, strerror(errno)); 825 return; 826 } 827 tx->count = n; 828 } 829 830 void 831 rclunk(Fcall *rx, Fcall *tx) 832 { 833 char *e; 834 Fid *fid; 835 836 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 837 seterror(tx, e); 838 return; 839 } 840 if (fid->auth) { 841 if (auth->clunk) { 842 e = (*auth->clunk)(rx, tx); 843 if (e) { 844 seterror(tx, e); 845 return; 846 } 847 } 848 } 849 else if(fid->omode != -1 && fid->omode&ORCLOSE) 850 remove(fid->path); 851 freefid(fid); 852 } 853 854 void 855 rremove(Fcall *rx, Fcall *tx) 856 { 857 char *e; 858 Fid *fid; 859 860 if((fid = oldfid(rx->fid, &e)) == nil){ 861 seterror(tx, e); 862 return; 863 } 864 if(userremove(fid, &e) < 0) 865 seterror(tx, e); 866 freefid(fid); 867 } 868 869 void 870 rstat(Fcall *rx, Fcall *tx) 871 { 872 char *e; 873 Fid *fid; 874 Dir d; 875 876 if((fid = oldfid(rx->fid, &e)) == nil){ 877 seterror(tx, e); 878 return; 879 } 880 881 if(fidstat(fid, &e) < 0){ 882 seterror(tx, e); 883 return; 884 } 885 886 stat2dir(fid->path, &fid->st, &d); 887 if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ) 888 seterror(tx, "convD2M fails"); 889 } 890 891 void 892 rwstat(Fcall *rx, Fcall *tx) 893 { 894 char *e; 895 char *p, *old, *new, *dir; 896 gid_t gid; 897 Dir d; 898 Fid *fid; 899 900 if((fid = oldfid(rx->fid, &e)) == nil){ 901 seterror(tx, e); 902 return; 903 } 904 905 /* 906 * wstat is supposed to be atomic. 907 * we check all the things we can before trying anything. 908 * still, if we are told to truncate a file and rename it and only 909 * one works, we're screwed. in such cases we leave things 910 * half broken and return an error. it's hardly perfect. 911 */ 912 if((old9p ? convM2Dold : convM2D)(rx->stat, rx->nstat, &d, (char*)rx->stat) <= BIT16SZ){ 913 seterror(tx, Ewstatbuffer); 914 return; 915 } 916 917 if(fidstat(fid, &e) < 0){ 918 seterror(tx, e); 919 return; 920 } 921 922 /* 923 * The casting is necessary because d.mode is ulong and might, 924 * on some systems, be 64 bits. We only want to compare the 925 * bottom 32 bits, since that's all that gets sent in the protocol. 926 * 927 * Same situation for d.mtime and d.length (although that last check 928 * is admittedly superfluous, given the current lack of 128-bit machines). 929 */ 930 gid = (gid_t)-1; 931 if(d.gid[0] != '\0'){ 932 User *g; 933 934 g = gname2user(d.gid); 935 if(g == nil){ 936 seterror(tx, Eunknowngroup); 937 return; 938 } 939 gid = (gid_t)g->id; 940 941 if(groupchange(fid->u, gid2user(gid), &e) < 0){ 942 seterror(tx, e); 943 return; 944 } 945 } 946 947 if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){ 948 seterror(tx, Edirchange); 949 return; 950 } 951 952 if(strcmp(fid->path, "/") == 0){ 953 seterror(tx, "no wstat of root"); 954 return; 955 } 956 957 /* 958 * try things in increasing order of harm to the file. 959 * mtime should come after truncate so that if you 960 * do both the mtime actually takes effect, but i'd rather 961 * leave truncate until last. 962 * (see above comment about atomicity). 963 */ 964 if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){ 965 if(chatty9p) 966 fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d)); 967 seterror(tx, strerror(errno)); 968 return; 969 } 970 971 if((u32int)d.mtime != (u32int)~0){ 972 struct utimbuf t; 973 974 t.actime = 0; 975 t.modtime = d.mtime; 976 if(utime(fid->path, &t) < 0){ 977 if(chatty9p) 978 fprint(2, "utime(%s) failed\n", fid->path); 979 seterror(tx, strerror(errno)); 980 return; 981 } 982 } 983 984 if(gid != (gid_t)-1 && gid != fid->st.st_gid){ 985 if(chown(fid->path, (uid_t)-1, gid) < 0){ 986 if(chatty9p) 987 fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid); 988 seterror(tx, strerror(errno)); 989 return; 990 } 991 } 992 993 if(d.name[0]){ 994 old = fid->path; 995 dir = estrdup(fid->path); 996 if((p = strrchr(dir, '/')) > dir) 997 *p = '\0'; 998 else{ 999 seterror(tx, "whoops: can't happen in u9fs"); 1000 return; 1001 } 1002 new = estrpath(dir, d.name, 1); 1003 if(strcmp(old, new) != 0 && rename(old, new) < 0){ 1004 if(chatty9p) 1005 fprint(2, "rename(%s, %s) failed\n", old, new); 1006 seterror(tx, strerror(errno)); 1007 free(new); 1008 free(dir); 1009 return; 1010 } 1011 fid->path = new; 1012 free(old); 1013 free(dir); 1014 } 1015 1016 if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){ 1017 fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length); 1018 seterror(tx, strerror(errno)); 1019 return; 1020 } 1021 } 1022 1023 /* 1024 * we keep a table by numeric id. by name lookups happen infrequently 1025 * while by-number lookups happen once for every directory entry read 1026 * and every stat request. 1027 */ 1028 User *utab[64]; 1029 User *gtab[64]; 1030 1031 User* 1032 adduser(struct passwd *p) 1033 { 1034 User *u; 1035 1036 u = emalloc(sizeof(*u)); 1037 u->id = p->pw_uid; 1038 u->name = estrdup(p->pw_name); 1039 u->next = utab[p->pw_uid%nelem(utab)]; 1040 u->defaultgid = p->pw_gid; 1041 utab[p->pw_uid%nelem(utab)] = u; 1042 return u; 1043 } 1044 1045 int 1046 useringroup(User *u, User *g) 1047 { 1048 int i; 1049 1050 for(i=0; i<g->nmem; i++) 1051 if(strcmp(g->mem[i], u->name) == 0) 1052 return 1; 1053 1054 /* 1055 * Hack around common Unix problem that everyone has 1056 * default group "user" but /etc/group lists no members. 1057 */ 1058 if(u->defaultgid == g->id) 1059 return 1; 1060 return 0; 1061 } 1062 1063 User* 1064 addgroup(struct group *g) 1065 { 1066 User *u; 1067 char **p; 1068 int n; 1069 1070 u = emalloc(sizeof(*u)); 1071 n = 0; 1072 for(p=g->gr_mem; *p; p++) 1073 n++; 1074 u->mem = emalloc(sizeof(u->mem[0])*n); 1075 n = 0; 1076 for(p=g->gr_mem; *p; p++) 1077 u->mem[n++] = estrdup(*p); 1078 u->nmem = n; 1079 u->id = g->gr_gid; 1080 u->name = estrdup(g->gr_name); 1081 u->next = gtab[g->gr_gid%nelem(gtab)]; 1082 gtab[g->gr_gid%nelem(gtab)] = u; 1083 return u; 1084 } 1085 1086 User* 1087 uname2user(char *name) 1088 { 1089 int i; 1090 User *u; 1091 struct passwd *p; 1092 1093 for(i=0; i<nelem(utab); i++) 1094 for(u=utab[i]; u; u=u->next) 1095 if(strcmp(u->name, name) == 0) 1096 return u; 1097 1098 if((p = getpwnam(name)) == nil) 1099 return nil; 1100 return adduser(p); 1101 } 1102 1103 User* 1104 uid2user(int id) 1105 { 1106 User *u; 1107 struct passwd *p; 1108 1109 for(u=utab[id%nelem(utab)]; u; u=u->next) 1110 if(u->id == id) 1111 return u; 1112 1113 if((p = getpwuid(id)) == nil) 1114 return nil; 1115 return adduser(p); 1116 } 1117 1118 User* 1119 gname2user(char *name) 1120 { 1121 int i; 1122 User *u; 1123 struct group *g; 1124 1125 for(i=0; i<nelem(gtab); i++) 1126 for(u=gtab[i]; u; u=u->next) 1127 if(strcmp(u->name, name) == 0) 1128 return u; 1129 1130 if((g = getgrnam(name)) == nil) 1131 return nil; 1132 return addgroup(g); 1133 } 1134 1135 User* 1136 gid2user(int id) 1137 { 1138 User *u; 1139 struct group *g; 1140 1141 for(u=gtab[id%nelem(gtab)]; u; u=u->next) 1142 if(u->id == id) 1143 return u; 1144 1145 if((g = getgrgid(id)) == nil) 1146 return nil; 1147 return addgroup(g); 1148 } 1149 1150 void 1151 sysfatal(char *fmt, ...) 1152 { 1153 char buf[1024]; 1154 va_list va, temp; 1155 1156 va_start(va, fmt); 1157 va_copy(temp, va); 1158 doprint(buf, buf+sizeof buf, fmt, &temp); 1159 va_end(temp); 1160 va_end(va); 1161 fprint(2, "u9fs: %s\n", buf); 1162 fprint(2, "last unix error: %s\n", strerror(errno)); 1163 exit(1); 1164 } 1165 1166 void* 1167 emalloc(size_t n) 1168 { 1169 void *p; 1170 1171 if(n == 0) 1172 n = 1; 1173 p = malloc(n); 1174 if(p == 0) 1175 sysfatal("malloc(%ld) fails", (long)n); 1176 memset(p, 0, n); 1177 return p; 1178 } 1179 1180 void* 1181 erealloc(void *p, size_t n) 1182 { 1183 if(p == 0) 1184 p = malloc(n); 1185 else 1186 p = realloc(p, n); 1187 if(p == 0) 1188 sysfatal("realloc(..., %ld) fails", (long)n); 1189 return p; 1190 } 1191 1192 char* 1193 estrdup(char *p) 1194 { 1195 p = strdup(p); 1196 if(p == 0) 1197 sysfatal("strdup(%.20s) fails", p); 1198 return p; 1199 } 1200 1201 char* 1202 estrpath(char *p, char *q, int frog) 1203 { 1204 char *r, *s; 1205 1206 if(strcmp(q, "..") == 0){ 1207 r = estrdup(p); 1208 if((s = strrchr(r, '/')) && s > r) 1209 *s = '\0'; 1210 else if(s == r) 1211 s[1] = '\0'; 1212 return r; 1213 } 1214 1215 if(frog) 1216 q = defrog(q); 1217 else 1218 q = strdup(q); 1219 r = emalloc(strlen(p)+1+strlen(q)+1); 1220 strcpy(r, p); 1221 if(r[0]=='\0' || r[strlen(r)-1] != '/') 1222 strcat(r, "/"); 1223 strcat(r, q); 1224 free(q); 1225 return r; 1226 } 1227 1228 Fid *fidtab[1]; 1229 1230 Fid* 1231 lookupfid(int fid) 1232 { 1233 Fid *f; 1234 1235 for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next) 1236 if(f->fid == fid) 1237 return f; 1238 return nil; 1239 } 1240 1241 Fid* 1242 newfid(int fid, char **ep) 1243 { 1244 Fid *f; 1245 1246 if(lookupfid(fid) != nil){ 1247 *ep = Efidactive; 1248 return nil; 1249 } 1250 1251 f = emalloc(sizeof(*f)); 1252 f->next = fidtab[fid%nelem(fidtab)]; 1253 if(f->next) 1254 f->next->prev = f; 1255 fidtab[fid%nelem(fidtab)] = f; 1256 f->fid = fid; 1257 f->fd = -1; 1258 f->omode = -1; 1259 return f; 1260 } 1261 1262 Fid* 1263 newauthfid(int fid, void *magic, char **ep) 1264 { 1265 Fid *af; 1266 af = newfid(fid, ep); 1267 if (af == nil) 1268 return nil; 1269 af->auth = 1; 1270 af->authmagic = magic; 1271 return af; 1272 } 1273 1274 Fid* 1275 oldfidex(int fid, int auth, char **ep) 1276 { 1277 Fid *f; 1278 1279 if((f = lookupfid(fid)) == nil){ 1280 *ep = Ebadfid; 1281 return nil; 1282 } 1283 1284 if (auth != -1 && f->auth != auth) { 1285 *ep = Ebadfid; 1286 return nil; 1287 } 1288 1289 if (!f->auth) { 1290 if(userchange(f->u, ep) < 0) 1291 return nil; 1292 } 1293 1294 return f; 1295 } 1296 1297 Fid* 1298 oldfid(int fid, char **ep) 1299 { 1300 return oldfidex(fid, 0, ep); 1301 } 1302 1303 Fid* 1304 oldauthfid(int fid, void **magic, char **ep) 1305 { 1306 Fid *af; 1307 af = oldfidex(fid, 1, ep); 1308 if (af == nil) 1309 return nil; 1310 *magic = af->authmagic; 1311 return af; 1312 } 1313 1314 void 1315 freefid(Fid *f) 1316 { 1317 if(f->prev) 1318 f->prev->next = f->next; 1319 else 1320 fidtab[f->fid%nelem(fidtab)] = f->next; 1321 if(f->next) 1322 f->next->prev = f->prev; 1323 if(f->dir) 1324 closedir(f->dir); 1325 if(f->fd) 1326 close(f->fd); 1327 free(f->path); 1328 free(f); 1329 } 1330 1331 int 1332 fidstat(Fid *fid, char **ep) 1333 { 1334 if(stat(fid->path, &fid->st) < 0){ 1335 fprint(2, "fidstat(%s) failed\n", fid->path); 1336 if(ep) 1337 *ep = strerror(errno); 1338 return -1; 1339 } 1340 if(S_ISDIR(fid->st.st_mode)) 1341 fid->st.st_size = 0; 1342 return 0; 1343 } 1344 1345 int 1346 userchange(User *u, char **ep) 1347 { 1348 if(defaultuser) 1349 return 0; 1350 1351 if(setreuid(0, 0) < 0){ 1352 fprint(2, "setreuid(0, 0) failed\n"); 1353 *ep = "cannot setuid back to root"; 1354 return -1; 1355 } 1356 1357 /* 1358 * Initgroups does not appear to be SUSV standard. 1359 * But it exists on SGI and on Linux, which makes me 1360 * think it's standard enough. We have to do something 1361 * like this, and the closest other function I can find is 1362 * setgroups (which initgroups eventually calls). 1363 * Setgroups is the same as far as standardization though, 1364 * so we're stuck using a non-SUSV call. Sigh. 1365 */ 1366 if(initgroups(u->name, u->defaultgid) < 0) 1367 fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno)); 1368 1369 if(setreuid(-1, u->id) < 0){ 1370 fprint(2, "setreuid(-1, %s) failed\n", u->name); 1371 *ep = strerror(errno); 1372 return -1; 1373 } 1374 1375 return 0; 1376 } 1377 1378 /* 1379 * We do our own checking here, then switch to root temporarily 1380 * to set our gid. In a perfect world, you'd be allowed to set your 1381 * egid to any of the supplemental groups of your euid, but this 1382 * is not the case on Linux 2.2.14 (and perhaps others). 1383 * 1384 * This is a race, of course, but it's a race against processes 1385 * that can edit the group lists. If you can do that, you can 1386 * change your own group without our help. 1387 */ 1388 int 1389 groupchange(User *u, User *g, char **ep) 1390 { 1391 if(g == nil) 1392 return -1; 1393 if(!useringroup(u, g)){ 1394 if(chatty9p) 1395 fprint(2, "%s not in group %s\n", u->name, g->name); 1396 *ep = Enotingroup; 1397 return -1; 1398 } 1399 1400 setreuid(0,0); 1401 if(setregid(-1, g->id) < 0){ 1402 fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id); 1403 *ep = strerror(errno); 1404 return -1; 1405 } 1406 if(userchange(u, ep) < 0) 1407 return -1; 1408 1409 return 0; 1410 } 1411 1412 1413 /* 1414 * An attempt to enforce permissions by looking at the 1415 * file system. Separation of checking permission and 1416 * actually performing the action is a terrible idea, of 1417 * course, so we use setreuid for most of the permission 1418 * enforcement. This is here only so we can give errors 1419 * on open(ORCLOSE) in some cases. 1420 */ 1421 int 1422 userperm(User *u, char *path, int type, int need) 1423 { 1424 char *p, *q; 1425 int i, have; 1426 struct stat st; 1427 User *g; 1428 1429 switch(type){ 1430 default: 1431 fprint(2, "bad type %d in userperm\n", type); 1432 return -1; 1433 case Tdot: 1434 if(stat(path, &st) < 0){ 1435 fprint(2, "userperm: stat(%s) failed\n", path); 1436 return -1; 1437 } 1438 break; 1439 case Tdotdot: 1440 p = estrdup(path); 1441 if((q = strrchr(p, '/'))==nil){ 1442 fprint(2, "userperm(%s, ..): bad path\n", p); 1443 free(p); 1444 return -1; 1445 } 1446 if(q > p) 1447 *q = '\0'; 1448 else 1449 *(q+1) = '\0'; 1450 if(stat(p, &st) < 0){ 1451 fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", 1452 p, path); 1453 free(p); 1454 return -1; 1455 } 1456 free(p); 1457 break; 1458 } 1459 1460 if(u == none){ 1461 fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode); 1462 have = st.st_mode&7; 1463 if((have&need)==need) 1464 return 0; 1465 return -1; 1466 } 1467 have = st.st_mode&7; 1468 if((uid_t)u->id == st.st_uid) 1469 have |= (st.st_mode>>6)&7; 1470 if((have&need)==need) 1471 return 0; 1472 if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */ 1473 return -1; 1474 g = gid2user(st.st_gid); 1475 for(i=0; i<g->nmem; i++){ 1476 if(strcmp(g->mem[i], u->name) == 0){ 1477 have |= (st.st_mode>>3)&7; 1478 break; 1479 } 1480 } 1481 if((have&need)==need) 1482 return 0; 1483 return -1; 1484 } 1485 1486 int 1487 userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) 1488 { 1489 char *npath; 1490 struct stat st; 1491 1492 npath = estrpath(*path, elem, 1); 1493 if(stat(npath, &st) < 0){ 1494 free(npath); 1495 *ep = strerror(errno); 1496 return -1; 1497 } 1498 *qid = stat2qid(&st); 1499 free(*path); 1500 *path = npath; 1501 return 0; 1502 } 1503 1504 int 1505 useropen(Fid *fid, int omode, char **ep) 1506 { 1507 int a, o; 1508 1509 /* 1510 * Check this anyway, to try to head off problems later. 1511 */ 1512 if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){ 1513 *ep = Eperm; 1514 return -1; 1515 } 1516 1517 switch(omode&3){ 1518 default: 1519 *ep = "programmer error"; 1520 return -1; 1521 case OREAD: 1522 a = R_OK; 1523 o = O_RDONLY; 1524 break; 1525 case ORDWR: 1526 a = R_OK|W_OK; 1527 o = O_RDWR; 1528 break; 1529 case OWRITE: 1530 a = W_OK; 1531 o = O_WRONLY; 1532 break; 1533 case OEXEC: 1534 a = X_OK; 1535 o = O_RDONLY; 1536 break; 1537 } 1538 if(omode & OTRUNC){ 1539 a |= W_OK; 1540 o |= O_TRUNC; 1541 } 1542 1543 if(S_ISDIR(fid->st.st_mode)){ 1544 if(a != R_OK){ 1545 fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode); 1546 *ep = Eperm; 1547 return -1; 1548 } 1549 if((fid->dir = opendir(fid->path)) == nil){ 1550 *ep = strerror(errno); 1551 return -1; 1552 } 1553 }else{ 1554 /* 1555 * This is wrong because access used the real uid 1556 * and not the effective uid. Let the open sort it out. 1557 * 1558 if(access(fid->path, a) < 0){ 1559 *ep = strerror(errno); 1560 return -1; 1561 } 1562 * 1563 */ 1564 if((fid->fd = open(fid->path, o)) < 0){ 1565 *ep = strerror(errno); 1566 return -1; 1567 } 1568 } 1569 fid->omode = omode; 1570 return 0; 1571 } 1572 1573 int 1574 usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) 1575 { 1576 int o, m; 1577 char *opath, *npath; 1578 struct stat st, parent; 1579 1580 if(stat(fid->path, &parent) < 0){ 1581 *ep = strerror(errno); 1582 return -1; 1583 } 1584 1585 /* 1586 * Change group so that created file has expected group 1587 * by Plan 9 semantics. If that fails, might as well go 1588 * with the user's default group. 1589 */ 1590 if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0 1591 && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0) 1592 return -1; 1593 1594 m = (perm & DMDIR) ? 0777 : 0666; 1595 perm = perm & (~m | (fid->st.st_mode & m)); 1596 1597 npath = estrpath(fid->path, elem, 1); 1598 if(perm & DMDIR){ 1599 if((omode&~ORCLOSE) != OREAD){ 1600 *ep = Eperm; 1601 free(npath); 1602 return -1; 1603 } 1604 if(stat(npath, &st) >= 0 || errno != ENOENT){ 1605 *ep = Eexist; 1606 free(npath); 1607 return -1; 1608 } 1609 /* race */ 1610 if(mkdir(npath, (perm|0400)&0777) < 0){ 1611 *ep = strerror(errno); 1612 free(npath); 1613 return -1; 1614 } 1615 if((fid->dir = opendir(npath)) == nil){ 1616 *ep = strerror(errno); 1617 remove(npath); /* race */ 1618 free(npath); 1619 return -1; 1620 } 1621 }else{ 1622 o = O_CREAT|O_EXCL; 1623 switch(omode&3){ 1624 default: 1625 *ep = "programmer error"; 1626 return -1; 1627 case OREAD: 1628 case OEXEC: 1629 o |= O_RDONLY; 1630 break; 1631 case ORDWR: 1632 o |= O_RDWR; 1633 break; 1634 case OWRITE: 1635 o |= O_WRONLY; 1636 break; 1637 } 1638 if(omode & OTRUNC) 1639 o |= O_TRUNC; 1640 if((fid->fd = open(npath, o, perm&0777)) < 0){ 1641 if(chatty9p) 1642 fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777); 1643 *ep = strerror(errno); 1644 free(npath); 1645 return -1; 1646 } 1647 } 1648 1649 opath = fid->path; 1650 fid->path = npath; 1651 if(fidstat(fid, ep) < 0){ 1652 fprint(2, "stat after create on %s failed\n", npath); 1653 remove(npath); /* race */ 1654 free(npath); 1655 fid->path = opath; 1656 if(fid->fd >= 0){ 1657 close(fid->fd); 1658 fid->fd = -1; 1659 }else{ 1660 closedir(fid->dir); 1661 fid->dir = nil; 1662 } 1663 return -1; 1664 } 1665 fid->omode = omode; 1666 free(opath); 1667 return 0; 1668 } 1669 1670 int 1671 userremove(Fid *fid, char **ep) 1672 { 1673 if(remove(fid->path) < 0){ 1674 *ep = strerror(errno); 1675 return -1; 1676 } 1677 return 0; 1678 } 1679 1680 void 1681 usage(void) 1682 { 1683 fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n"); 1684 exit(1); 1685 } 1686 1687 int 1688 main(int argc, char **argv) 1689 { 1690 char *authtype; 1691 int i; 1692 int fd; 1693 int logflag; 1694 1695 auth = authmethods[0]; 1696 logflag = O_WRONLY|O_APPEND|O_CREAT; 1697 ARGBEGIN{ 1698 case 'D': 1699 chatty9p = 1; 1700 break; 1701 case 'a': 1702 authtype = EARGF(usage()); 1703 auth = nil; 1704 for(i=0; i<nelem(authmethods); i++) 1705 if(strcmp(authmethods[i]->name, authtype)==0) 1706 auth = authmethods[i]; 1707 if(auth == nil) 1708 sysfatal("unknown auth type '%s'", authtype); 1709 break; 1710 case 'A': 1711 autharg = EARGF(usage()); 1712 break; 1713 case 'l': 1714 logfile = EARGF(usage()); 1715 break; 1716 case 'm': 1717 msize = strtol(EARGF(usage()), 0, 0); 1718 break; 1719 case 'n': 1720 network = 0; 1721 break; 1722 case 'u': 1723 defaultuser = EARGF(usage()); 1724 break; 1725 case 'z': 1726 logflag |= O_TRUNC; 1727 }ARGEND 1728 1729 if(argc > 1) 1730 usage(); 1731 1732 fd = open(logfile, logflag, 0666); 1733 if(fd < 0) 1734 sysfatal("cannot open log '%s'", logfile); 1735 1736 if(dup2(fd, 2) < 0) 1737 sysfatal("cannot dup fd onto stderr"); 1738 fprint(2, "u9fs\nkill %d\n", (int)getpid()); 1739 1740 fmtinstall('F', fcallconv); 1741 fmtinstall('D', dirconv); 1742 fmtinstall('M', dirmodeconv); 1743 1744 rxbuf = emalloc(msize); 1745 txbuf = emalloc(msize); 1746 databuf = emalloc(msize); 1747 1748 if(auth->init) 1749 auth->init(); 1750 1751 if(network) 1752 getremotehostname(remotehostname, sizeof remotehostname); 1753 1754 if(gethostname(hostname, sizeof hostname) < 0) 1755 strcpy(hostname, "gnot"); 1756 1757 umask(0); 1758 1759 if(argc == 1) 1760 if(chroot(argv[0]) < 0) 1761 sysfatal("chroot '%s' failed", argv[0]); 1762 1763 none = uname2user("none"); 1764 if(none == nil) 1765 none = uname2user("nobody"); 1766 1767 serve(0, 1); 1768 return 0; 1769 } 1770