|
|
1.1 ! root 1: #include "u.h" ! 2: #include <sys/types.h> ! 3: #include <sys/stat.h> ! 4: #include "libc.h" ! 5: #include "9p.h" ! 6: #include "stdio.h" ! 7: #include "setjmp.h" ! 8: #include "pwd.h" ! 9: #include "grp.h" ! 10: ! 11: #define DBG(f) ! 12: ! 13: struct group *getgrent(void); ! 14: struct passwd *getpwent(void); ! 15: ! 16: #ifdef SYSV ! 17: # include <dirent.h> ! 18: # define DTYPE struct dirent ! 19: # define SOCKETS ! 20: #endif ! 21: #ifdef V10 ! 22: # include <ndir.h> ! 23: # define DTYPE struct direct ! 24: #endif ! 25: #ifdef BSD ! 26: # include <sys/dir.h> ! 27: # define DTYPE struct direct ! 28: # define SOCKETS ! 29: #endif ! 30: #ifdef SOCKETS ! 31: # define sendmsg __sendmsg ! 32: # include <sys/socket.h> ! 33: # include <netinet/in.h> ! 34: # include <netdb.h> ! 35: # undef sendmsg ! 36: char bsdhost[256]; ! 37: void remotehostname(void); ! 38: #endif ! 39: ! 40: typedef struct File File; ! 41: typedef struct Rfile Rfile; ! 42: typedef struct Fd Fd; ! 43: typedef struct Pass Pass; ! 44: ! 45: struct Fd{ ! 46: int ref; ! 47: Ulong offset; ! 48: int fd; ! 49: DIR *dir; ! 50: }; ! 51: ! 52: struct Rfile{ ! 53: int busy; ! 54: int uid; ! 55: int gid; ! 56: int rclose; ! 57: File *file; ! 58: Fd *fd; ! 59: }; ! 60: ! 61: struct File{ ! 62: int ref; ! 63: char *path; ! 64: char *name; ! 65: Qid qid; ! 66: struct stat stbuf; ! 67: }; ! 68: ! 69: struct Pass{ ! 70: int id; ! 71: int gid; ! 72: char *name; ! 73: Pass *next; ! 74: }; ! 75: ! 76: char data[2][MAXMSG+MAXFDATA]; ! 77: char tdata[MAXMSG+MAXFDATA]; ! 78: char rdata[MAXFDATA]; ! 79: Fcall rhdr; ! 80: Fcall thdr; ! 81: Rfile *rfile; ! 82: File *file0; ! 83: int nrfilealloc; ! 84: jmp_buf loopjmp; ! 85: Pass* uid[256]; ! 86: Pass* gid[256]; ! 87: int devallowed; ! 88: int connected; ! 89: ! 90: void io(void); ! 91: void error(char*); ! 92: char *mfmt(Fcall*); ! 93: void sendmsg(char*); ! 94: int okfid(int); ! 95: Rfile* rfilefid(void); ! 96: File* newfile(void); ! 97: void* erealloc(void*, unsigned); ! 98: char* estrdup(char*); ! 99: char* dostat(File*, char*); ! 100: char* bldpath(char*, char*, char*); ! 101: Ulong qid(struct stat*); ! 102: Ulong vers(struct stat*); ! 103: void errjmp(char*); ! 104: int omode(int); ! 105: char* id2name(Pass**, int); ! 106: Pass* name2pass(Pass**, char*); ! 107: void getpwdf(void); ! 108: void getgrpf(void); ! 109: void perm(Rfile*, int, struct stat*); ! 110: void parentwrperm(Rfile*); ! 111: ! 112: void rsession(void); ! 113: void rattach(void); ! 114: void rflush(void); ! 115: void rclone(void); ! 116: void rwalk(void); ! 117: void ropen(void); ! 118: void rcreate(void); ! 119: void rread(void); ! 120: void rwrite(void); ! 121: void rclunk(int); ! 122: void rstat(void); ! 123: void rwstat(void); ! 124: void rclwalk(void); ! 125: ! 126: char Eauth[] = "authentication failed"; ! 127: char Eperm[] = "permission denied"; ! 128: char Ebadfid[] = "fid unknown or out of range"; ! 129: char Efidactive[] = "fid already in use"; ! 130: char Eopen[] = "file is open"; ! 131: char Emode[] = "invalid open mode"; ! 132: char Especial[] = "no access to special file"; ! 133: char Especial0[] = "already attached without access to special files"; ! 134: char Especial1[] = "already attached with access to special files"; ! 135: char Enotopen[] = "file is not open"; ! 136: char Etoolarge[] = "i/o count too large"; ! 137: char Ebaddir[] = "i/o error on directory"; ! 138: char Eunknown[] = "unknown user or group"; ! 139: char Euid[] = "can't set uid"; ! 140: char Egid[] = "can't set gid"; ! 141: char Eowner[] = "not owner"; ! 142: ! 143: int ! 144: main(int argc, char *argv[]) ! 145: { ! 146: freopen(LOG, "a", stderr); ! 147: setbuf(stderr, (void*)0); ! 148: DBG(fprintf(stderr, "u9fs\nkill %d\n", getpid())); ! 149: if(argc > 1) ! 150: if(chroot(argv[1]) == -1) ! 151: error("chroot failed"); ! 152: ! 153: # ifdef SOCKETS ! 154: remotehostname(); ! 155: # endif ! 156: ! 157: io(); ! 158: return 0; ! 159: } ! 160: ! 161: void ! 162: io(void) ! 163: { ! 164: int m; ! 165: static int toggle, ndata; ! 166: char *datap; ! 167: ! 168: /* ! 169: * TCP does not preserve record boundaries; this dance works around ! 170: * the problem. ! 171: */ ! 172: setjmp(loopjmp); ! 173: ! 174: /* ! 175: * Invariant: data[toggle] has ndata bytes already ! 176: */ ! 177: loop: ! 178: datap = data[toggle]; ! 179: toggle ^= 1; ! 180: for(;;){ ! 181: if(ndata){ ! 182: m = convM2S(datap, &rhdr, ndata); ! 183: /* m is number of bytes more than a full message */ ! 184: if(m >= 0){ ! 185: memmove(data[toggle], datap+(ndata-m), m); ! 186: ndata = m; ! 187: break; ! 188: } ! 189: } ! 190: m = read(0, datap+ndata, (MAXMSG+MAXFDATA)-ndata); ! 191: if(m <= 0) ! 192: error("read"); ! 193: ndata += m; ! 194: } ! 195: ! 196: thdr.type = rhdr.type+1; ! 197: thdr.tag = rhdr.tag; ! 198: thdr.fid = rhdr.fid; ! 199: DBG(fprintf(stderr, ">> %s\n", mfmt(&rhdr))); ! 200: switch(rhdr.type){ ! 201: case Tnop: ! 202: case Tflush: /* this is a synchronous fs; easy */ ! 203: break; ! 204: case Tsession: ! 205: rsession(); ! 206: break; ! 207: case Tattach: ! 208: rattach(); ! 209: break; ! 210: case Tclone: ! 211: rclone(); ! 212: break; ! 213: case Twalk: ! 214: rwalk(); ! 215: break; ! 216: case Tstat: ! 217: rstat(); ! 218: break; ! 219: case Twstat: ! 220: rwstat(); ! 221: break; ! 222: case Topen: ! 223: ropen(); ! 224: break; ! 225: case Tcreate: ! 226: rcreate(); ! 227: break; ! 228: case Tread: ! 229: rread(); ! 230: break; ! 231: case Twrite: ! 232: rwrite(); ! 233: break; ! 234: case Tclunk: ! 235: rclunk(0); ! 236: break; ! 237: case Tremove: ! 238: rclunk(1); ! 239: break; ! 240: default: ! 241: fprintf(stderr, "unknown message %s\n", mfmt(&rhdr)); ! 242: error("bad message"); ! 243: } ! 244: sendmsg(0); ! 245: goto loop; ! 246: } ! 247: ! 248: void ! 249: rsession(void) ! 250: { ! 251: memset(thdr.authid, 0, sizeof(thdr.authid)); ! 252: memset(thdr.authdom, 0, sizeof(thdr.authdom)); ! 253: memset(thdr.chal, 0, sizeof(thdr.chal)); ! 254: } ! 255: ! 256: void ! 257: rattach(void) ! 258: { ! 259: Rfile *rf; ! 260: char *err; ! 261: Pass *p; ! 262: ! 263: err = 0; ! 264: if(file0 == 0){ ! 265: file0 = newfile(); ! 266: file0->ref++; /* one extra to hold it up */ ! 267: file0->path = estrdup("/"); ! 268: file0->name = estrdup("/"); ! 269: errjmp(dostat(file0, 0)); ! 270: } ! 271: if(!okfid(rhdr.fid)) ! 272: errjmp(Ebadfid); ! 273: if(strncmp(rhdr.aname, "device", 6) == 0){ ! 274: if(connected && !devallowed) ! 275: errjmp(Especial0); ! 276: devallowed = 1; ! 277: }else{ ! 278: if(connected && devallowed) ! 279: errjmp(Especial1); ! 280: } ! 281: getpwdf(); ! 282: getgrpf(); ! 283: rf = &rfile[rhdr.fid]; ! 284: if(rf->busy) ! 285: errjmp(Efidactive); ! 286: rf->busy = 1; ! 287: rf->rclose = 0; ! 288: rf->file = file0; ! 289: file0->ref++; ! 290: p = name2pass(uid, rhdr.uname); ! 291: if(p == 0) ! 292: errjmp(Eunknown); ! 293: if(p->id == 0) ! 294: errjmp(Eperm); ! 295: # ifdef SOCKETS ! 296: if(ruserok(bsdhost, 0, rhdr.uname, rhdr.uname) < 0) ! 297: errjmp(Eperm); ! 298: # endif ! 299: rf->uid = p->id; ! 300: rf->gid = p->gid; ! 301: thdr.qid = file0->qid; ! 302: connected = 1; ! 303: } ! 304: ! 305: void ! 306: rclone(void) ! 307: { ! 308: Rfile *rf, *nrf; ! 309: File *f; ! 310: ! 311: rfilefid(); ! 312: if(!okfid(rhdr.newfid)) ! 313: errjmp(Ebadfid); ! 314: rf = &rfile[rhdr.fid]; ! 315: nrf = &rfile[rhdr.newfid]; ! 316: f = rf->file; ! 317: if(nrf->busy) ! 318: errjmp(Efidactive); ! 319: nrf->busy = 1; ! 320: nrf->file = f; ! 321: f->ref++; ! 322: nrf->fd = rf->fd; ! 323: nrf->uid = rf->uid; ! 324: nrf->gid = rf->gid; ! 325: nrf->rclose = rf->rclose; ! 326: if(nrf->fd){ ! 327: if(nrf->fd->ref == 0) ! 328: error("clone fd count"); ! 329: nrf->fd->ref++; ! 330: } ! 331: } ! 332: ! 333: void ! 334: rwalk(void) ! 335: { ! 336: char *err; ! 337: Rfile *rf; ! 338: File *of, *f; ! 339: ! 340: rf = rfilefid(); ! 341: if(rf->fd) ! 342: errjmp(Eopen); ! 343: of = rf->file; ! 344: perm(rf, 1, 0); ! 345: f = newfile(); ! 346: f->path = estrdup(of->path); ! 347: err = dostat(f, rhdr.name); ! 348: if(err){ ! 349: f->ref = 0; ! 350: free(f->path); ! 351: errjmp(err); ! 352: } ! 353: if(of->ref <= 0) ! 354: error("walk ref count"); ! 355: if(--of->ref == 0){ ! 356: free(of->path); ! 357: free(of->name); ! 358: free(of); ! 359: } ! 360: rf->file = f; ! 361: thdr.qid = f->qid; ! 362: } ! 363: ! 364: void ! 365: ropen(void) ! 366: { ! 367: Rfile *rf; ! 368: File *f; ! 369: int fd; ! 370: DIR *dir; ! 371: int m, trunc; ! 372: ! 373: rf = rfilefid(); ! 374: f = rf->file; ! 375: if(rf->fd) ! 376: error("open already open"); ! 377: if(!devallowed && (f->stbuf.st_mode & S_IFCHR)) ! 378: errjmp(Especial); ! 379: m = rhdr.mode & (16|3); ! 380: trunc = m & 16; /* OTRUNC */ ! 381: switch(m){ ! 382: case 0: ! 383: perm(rf, 4, 0); ! 384: break; ! 385: case 1: ! 386: case 1|16: ! 387: perm(rf, 2, 0); ! 388: break; ! 389: case 2: ! 390: case 0|16: ! 391: case 2|16: ! 392: perm(rf, 4, 0); ! 393: perm(rf, 2, 0); ! 394: break; ! 395: case 3: ! 396: perm(rf, 1, 0); ! 397: break; ! 398: default: ! 399: errjmp(Emode); ! 400: } ! 401: ! 402: m = omode(m & 3); ! 403: errno = 0; ! 404: if(f->qid.path & CHDIR){ ! 405: if(rhdr.mode != 0) /* OREAD */ ! 406: errjmp(Eperm); ! 407: dir = opendir(f->path); ! 408: if(dir == 0) ! 409: errjmp(sys_errlist[errno]); ! 410: fd = 0; ! 411: }else{ ! 412: if(trunc){ ! 413: fd = creat(f->path, 0666); ! 414: if(fd >= 0) ! 415: if(m != 1){ ! 416: close(fd); ! 417: fd = open(f->path, m); ! 418: } ! 419: }else ! 420: fd = open(f->path, m); ! 421: if(fd < 0) ! 422: errjmp(sys_errlist[errno]); ! 423: dir = 0; ! 424: } ! 425: rf->rclose = rhdr.mode & 64; /* ORCLOSE */ ! 426: rf->fd = erealloc(0, sizeof(Fd)); ! 427: rf->fd->ref = 1; ! 428: rf->fd->fd = fd; ! 429: rf->fd->dir = dir; ! 430: rf->fd->offset = 0; ! 431: thdr.qid = f->qid; ! 432: } ! 433: ! 434: void ! 435: rcreate(void) ! 436: { ! 437: Rfile *rf; ! 438: File *f, *of; ! 439: char *path, *err; ! 440: int fd; ! 441: int m; ! 442: char name[NAMELEN]; ! 443: ! 444: rf = rfilefid(); ! 445: if(rf->fd) ! 446: errjmp(Eopen); ! 447: perm(rf, 2, 0); ! 448: path = bldpath(rf->file->path, rhdr.name, name); ! 449: m = omode(rhdr.mode&3); ! 450: errno = 0; ! 451: if(rhdr.perm & CHDIR){ ! 452: if(m){ ! 453: free(path); ! 454: errjmp(Eperm); ! 455: } ! 456: fd = mkdir(path, 0777); ! 457: if(fd < 0){ ! 458: free(path); ! 459: errjmp(sys_errlist[errno]); ! 460: } ! 461: fd = open(path, 0); ! 462: free(path); ! 463: if(fd >= 0){ ! 464: fchmod(fd, rhdr.perm&0777); ! 465: fchown(fd, rf->uid, rf->gid); ! 466: } ! 467: }else{ ! 468: fd = creat(path, 0666); ! 469: if(fd >= 0){ ! 470: if(m != 1){ ! 471: close(fd); ! 472: fd = open(path, m); ! 473: } ! 474: fchmod(fd, rhdr.perm&0777); ! 475: fchown(fd, rf->uid, rf->gid); ! 476: } ! 477: free(path); ! 478: if(fd < 0) ! 479: errjmp(sys_errlist[errno]); ! 480: } ! 481: f = newfile(); ! 482: of = rf->file; ! 483: f->path = estrdup(of->path); ! 484: err = dostat(f, rhdr.name); ! 485: if(err){ ! 486: free(f->path); ! 487: free(f->name); ! 488: free(f); ! 489: errjmp(err); ! 490: } ! 491: if(!devallowed && (f->stbuf.st_mode & S_IFCHR)){ ! 492: free(f->path); ! 493: free(f->name); ! 494: free(f); ! 495: errjmp(Especial); ! 496: } ! 497: if(--of->ref == 0){ ! 498: free(of->path); ! 499: free(of->name); ! 500: free(of); ! 501: } ! 502: rf->file = f; ! 503: rf->rclose = rhdr.mode & 64; /* ORCLOSE */ ! 504: rf->fd = erealloc(0, sizeof(Fd)); ! 505: rf->fd->ref = 1; ! 506: rf->fd->fd = fd; ! 507: rf->fd->dir = 0; ! 508: rf->fd->offset = 0; ! 509: thdr.qid = f->qid; ! 510: } ! 511: ! 512: void ! 513: rread(void) ! 514: { ! 515: Rfile *rf; ! 516: File *f; ! 517: long n; ! 518: DTYPE *de; ! 519: Dir d; ! 520: struct stat stbuf; ! 521: char *path; ! 522: ! 523: rf = rfilefid(); ! 524: if(rf->fd == 0) ! 525: errjmp(Enotopen); ! 526: if(rhdr.count > sizeof rdata) ! 527: errjmp(Etoolarge); ! 528: f = rf->file; ! 529: if(rf->fd->dir){ ! 530: errno = 0; ! 531: if(rf->fd->offset != rhdr.offset){ ! 532: seekdir(rf->fd->dir, 0); ! 533: for(n=0; n<rhdr.offset; ){ ! 534: de = readdir(rf->fd->dir); ! 535: if(de == 0) ! 536: break; ! 537: if(de->d_ino==0 || de->d_name[0]==0) ! 538: continue; ! 539: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) ! 540: continue; ! 541: n += DIRLEN; ! 542: } ! 543: } ! 544: for(n=0; n<rhdr.count; ){ ! 545: de = readdir(rf->fd->dir); ! 546: if(de == 0) ! 547: break; ! 548: if(de->d_ino==0 || de->d_name[0]==0) ! 549: continue; ! 550: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) ! 551: continue; ! 552: strncpy(d.name, de->d_name, NAMELEN-1); ! 553: d.name[NAMELEN-1] = 0; ! 554: path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1); ! 555: sprintf(path, "%s/%s", f->path, de->d_name); ! 556: memset(&stbuf, 0, sizeof stbuf); ! 557: if(stat(path, &stbuf) < 0){ ! 558: fprintf(stderr, "dir: bad path %s\n", path); ! 559: /* but continue... probably a bad symlink */ ! 560: } ! 561: free(path); ! 562: strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN); ! 563: strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN); ! 564: d.qid.path = qid(&stbuf); ! 565: d.qid.vers = vers(&stbuf); ! 566: d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777); ! 567: d.atime = stbuf.st_atime; ! 568: d.mtime = stbuf.st_mtime; ! 569: d.len.l.hlength = 0; ! 570: d.len.l.length = stbuf.st_size; ! 571: convD2M(&d, rdata+n); ! 572: n += DIRLEN; ! 573: } ! 574: }else{ ! 575: errno = 0; ! 576: if(rf->fd->offset != rhdr.offset){ ! 577: rf->fd->offset = rhdr.offset; ! 578: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) ! 579: errjmp(sys_errlist[errno]); ! 580: } ! 581: n = read(rf->fd->fd, rdata, rhdr.count); ! 582: if(n < 0) ! 583: errjmp(sys_errlist[errno]); ! 584: } ! 585: rf->fd->offset += n; ! 586: thdr.count = n; ! 587: thdr.data = rdata; ! 588: } ! 589: ! 590: void ! 591: rwrite(void) ! 592: { ! 593: Rfile *rf; ! 594: int n; ! 595: ! 596: rf = rfilefid(); ! 597: if(rf->fd == 0) ! 598: errjmp(Enotopen); ! 599: if(rhdr.count > sizeof rdata) ! 600: errjmp(Etoolarge); ! 601: errno = 0; ! 602: if(rf->fd->offset != rhdr.offset){ ! 603: rf->fd->offset = rhdr.offset; ! 604: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) ! 605: errjmp(sys_errlist[errno]); ! 606: } ! 607: n = write(rf->fd->fd, rhdr.data, rhdr.count); ! 608: if(n < 0) ! 609: errjmp(sys_errlist[errno]); ! 610: rf->fd->offset += n; ! 611: thdr.count = n; ! 612: } ! 613: ! 614: void ! 615: rstat(void) ! 616: { ! 617: Rfile *rf; ! 618: File *f; ! 619: Dir d; ! 620: ! 621: rf = rfilefid(); ! 622: f = rf->file; ! 623: errjmp(dostat(f, 0)); ! 624: strncpy(d.name, f->name, NAMELEN); ! 625: strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN); ! 626: strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN); ! 627: d.qid = f->qid; ! 628: d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777); ! 629: d.atime = f->stbuf.st_atime; ! 630: d.mtime = f->stbuf.st_mtime; ! 631: d.len.l.hlength = 0; ! 632: d.len.l.length = f->stbuf.st_size; ! 633: convD2M(&d, thdr.stat); ! 634: } ! 635: ! 636: void ! 637: rwstat(void) ! 638: { ! 639: Rfile *rf; ! 640: File *f; ! 641: Dir d; ! 642: Pass *p; ! 643: char *path, *dir, name[NAMELEN]; ! 644: ! 645: rf = rfilefid(); ! 646: f = rf->file; ! 647: errjmp(dostat(f, 0)); ! 648: convM2D(rhdr.stat, &d); ! 649: errno = 0; ! 650: if(rf->uid != f->stbuf.st_uid) ! 651: errjmp(Eowner); ! 652: if(strcmp(d.name, f->name) != 0){ ! 653: parentwrperm(rf); ! 654: dir = bldpath(f->path, "..", name); ! 655: path = erealloc(0, strlen(dir)+1+strlen(d.name)+1); ! 656: sprintf(path, "%s/%s", dir, d.name); ! 657: if(link(f->path, path) < 0){ ! 658: free(path); ! 659: errjmp(sys_errlist[errno]); ! 660: } ! 661: if(unlink(f->path) < 0){ ! 662: free(path); ! 663: errjmp(sys_errlist[errno]); ! 664: } ! 665: free(f->path); ! 666: free(f->name); ! 667: f->path = path; ! 668: f->name = estrdup(d.name); ! 669: } ! 670: if((d.mode&0777) != (f->stbuf.st_mode&0777)){ ! 671: if(chmod(f->path, d.mode&0777) < 0) ! 672: errjmp(sys_errlist[errno]); ! 673: f->stbuf.st_mode &= ~0777; ! 674: f->stbuf.st_mode |= d.mode&0777; ! 675: } ! 676: p = name2pass(gid, d.gid); ! 677: if(p == 0) ! 678: errjmp(Eunknown); ! 679: if(p->id != f->stbuf.st_gid){ ! 680: if(chown(f->path, f->stbuf.st_uid, p->id) < 0) ! 681: errjmp(sys_errlist[errno]); ! 682: f->stbuf.st_gid = p->id; ! 683: } ! 684: } ! 685: ! 686: void ! 687: rclunk(int rm) ! 688: { ! 689: int ret; ! 690: char *err; ! 691: Rfile *rf; ! 692: File *f; ! 693: Fd *fd; ! 694: ! 695: err = 0; ! 696: rf = rfilefid(); ! 697: f = rf->file; ! 698: if(rm){ ! 699: parentwrperm(rf); ! 700: if(f->qid.path & CHDIR) ! 701: ret = rmdir(f->path); ! 702: else ! 703: ret = unlink(f->path); ! 704: if(ret) ! 705: err = sys_errlist[errno]; ! 706: }else if(rf->rclose){ /* ignore errors */ ! 707: if(f->qid.path & CHDIR) ! 708: rmdir(f->path); ! 709: else ! 710: unlink(f->path); ! 711: } ! 712: ! 713: rf->busy = 0; ! 714: if(--f->ref == 0){ ! 715: free(f->path); ! 716: free(f->name); ! 717: free(f); ! 718: } ! 719: fd = rf->fd; ! 720: if(fd){ ! 721: if(fd->ref <= 0) ! 722: error("clunk fd count"); ! 723: if(--fd->ref == 0){ ! 724: if(fd->fd) ! 725: close(fd->fd); ! 726: if(fd->dir) ! 727: closedir(fd->dir); ! 728: free(fd); ! 729: } ! 730: rf->fd = 0; ! 731: } ! 732: if(err) ! 733: errjmp(err); ! 734: } ! 735: ! 736: char* ! 737: bldpath(char *a, char *elem, char *name) ! 738: { ! 739: char *path, *p; ! 740: ! 741: if(strcmp(elem, "..") == 0){ ! 742: if(strcmp(a, "/") == 0){ ! 743: path = estrdup(a); ! 744: strcpy(name, a); ! 745: }else{ ! 746: p = strrchr(a, '/'); ! 747: if(p == 0){ ! 748: fprintf(stderr, "path: '%s'\n", path); ! 749: error("malformed path 1"); ! 750: } ! 751: if(p == a) /* reduced to "/" */ ! 752: p++; ! 753: path = erealloc(0, (p-a)+1); ! 754: memmove(path, a, (p-a)); ! 755: path[(p-a)] = 0; ! 756: if(strcmp(path, "/") == 0) ! 757: p = path; ! 758: else{ ! 759: p = strrchr(path, '/'); ! 760: if(p == 0){ ! 761: fprintf(stderr, "path: '%s'\n", path); ! 762: error("malformed path 2"); ! 763: } ! 764: p++; ! 765: } ! 766: strcpy(name, p); ! 767: } ! 768: }else{ ! 769: if(strcmp(a, "/") == 0) ! 770: a = ""; ! 771: path = erealloc(0, strlen(a)+1+strlen(elem)+1); ! 772: sprintf(path, "%s/%s", a, elem); ! 773: strcpy(name, elem); ! 774: } ! 775: if(strlen(name) >= NAMELEN) ! 776: error("bldpath: name too long"); ! 777: return path; ! 778: } ! 779: ! 780: char* ! 781: dostat(File *f, char *elem) ! 782: { ! 783: char *path; ! 784: struct stat stbuf; ! 785: char name[NAMELEN]; ! 786: ! 787: if(elem) ! 788: path = bldpath(f->path, elem, name); ! 789: else ! 790: path = f->path; ! 791: errno = 0; ! 792: if(stat(path, &stbuf) < 0) ! 793: return sys_errlist[errno]; ! 794: if(elem){ ! 795: free(f->path); ! 796: f->path = path; ! 797: f->name = estrdup(name); ! 798: } ! 799: f->qid.path = qid(&stbuf); ! 800: f->qid.vers = vers(&stbuf); ! 801: f->stbuf = stbuf; ! 802: return 0; ! 803: } ! 804: ! 805: int ! 806: omode(int m) ! 807: { ! 808: switch(m){ ! 809: case 0: /* OREAD */ ! 810: case 3: /* OEXEC */ ! 811: return 0; ! 812: case 1: /* OWRITE */ ! 813: return 1; ! 814: case 2: /* ORDWR */ ! 815: return 2; ! 816: } ! 817: errjmp(Emode); ! 818: return 0; ! 819: } ! 820: ! 821: void ! 822: sendmsg(char *err) ! 823: { ! 824: int n; ! 825: ! 826: if(err){ ! 827: thdr.type = Rerror; ! 828: strncpy(thdr.ename, err, ERRLEN); ! 829: } ! 830: DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr))); ! 831: n = convS2M(&thdr, tdata); ! 832: if(n == 0) ! 833: error("bad sendmsg format"); ! 834: if(write(1, tdata, n) != n) ! 835: error("write error"); ! 836: } ! 837: ! 838: ! 839: int ! 840: okfid(int fid) ! 841: { ! 842: enum{ Delta=10 }; ! 843: ! 844: if(fid < 0){ ! 845: fprintf(stderr, "u9fs: negative fid %d\n", fid); ! 846: return 0; ! 847: } ! 848: if(fid >= nrfilealloc){ ! 849: fid += Delta; ! 850: rfile = erealloc(rfile, fid*sizeof(Rfile)); ! 851: memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile)); ! 852: nrfilealloc = fid; ! 853: } ! 854: return 1; ! 855: } ! 856: ! 857: Rfile* ! 858: rfilefid(void) ! 859: { ! 860: Rfile *rf; ! 861: ! 862: if(!okfid(rhdr.fid)) ! 863: errjmp(Ebadfid); ! 864: rf = &rfile[rhdr.fid]; ! 865: if(rf->busy == 0) ! 866: errjmp(Ebadfid); ! 867: if(rf->file->ref <= 0) ! 868: error("ref count"); ! 869: return rf; ! 870: } ! 871: ! 872: void ! 873: perm(Rfile *rf, int mask, struct stat *st) ! 874: { ! 875: if(st == 0) ! 876: st = &rf->file->stbuf; ! 877: /* plan 9 access semantics; simpler and more sensible */ ! 878: if(rf->uid == st->st_uid) ! 879: if((st->st_mode>>6) & mask) ! 880: return; ! 881: if(rf->gid == st->st_gid) ! 882: if((st->st_mode>>3) & mask) ! 883: return; ! 884: if((st->st_mode>>0) & mask) ! 885: return; ! 886: errjmp(Eperm); ! 887: } ! 888: ! 889: void ! 890: parentwrperm(Rfile *rf) ! 891: { ! 892: Rfile trf; ! 893: struct stat st; ! 894: char *dirp, dir[512]; ! 895: ! 896: dirp = bldpath(rf->file->path, "..", dir); ! 897: if(strlen(dirp) < sizeof dir){ /* ugly: avoid leaving dirp allocated */ ! 898: strcpy(dir, dirp); ! 899: free(dirp); ! 900: dirp = dir; ! 901: } ! 902: if(stat(dirp, &st) < 0) ! 903: errjmp(Eperm); ! 904: trf.uid = rf->uid; ! 905: trf.gid = rf->gid; ! 906: perm(&trf, 2, &st); ! 907: } ! 908: ! 909: File* ! 910: newfile(void) ! 911: { ! 912: File *f; ! 913: ! 914: f = erealloc(0, sizeof(File)); ! 915: memset(f, 0, sizeof(File)); ! 916: f->ref = 1; ! 917: return f; ! 918: } ! 919: ! 920: /* ! 921: * qids: directory bit, seven bits of device, 24 bits of inode ! 922: */ ! 923: Ulong ! 924: vers(struct stat *st) ! 925: { ! 926: return st->st_mtime; ! 927: } ! 928: ! 929: Ulong ! 930: qid(struct stat *st) ! 931: { ! 932: static int nqdev; ! 933: static Uchar *qdev; ! 934: Ulong q; ! 935: int dev; ! 936: ! 937: if(qdev == 0){ ! 938: qdev = erealloc(0, 65536U); ! 939: memset(qdev, 0, 65536U); ! 940: } ! 941: q = 0; ! 942: if((st->st_mode&S_IFMT) == S_IFDIR) ! 943: q = CHDIR; ! 944: dev = st->st_dev & 0xFFFFUL; ! 945: if(qdev[dev] == 0){ ! 946: if(++nqdev >= 128) ! 947: error("too many devices"); ! 948: qdev[dev] = nqdev; ! 949: } ! 950: q |= qdev[dev]<<24; ! 951: q |= st->st_ino & 0x00FFFFFFUL; ! 952: return q; ! 953: } ! 954: ! 955: Pass* ! 956: name2pass(Pass **pw, char *name) ! 957: { ! 958: int i; ! 959: Pass *p; ! 960: ! 961: for(i=0; i<256; i++) ! 962: for(p = pw[i]; p; p = p->next) ! 963: if(strcmp(name, p->name) == 0) ! 964: return p; ! 965: return 0; ! 966: } ! 967: ! 968: char* ! 969: id2name(Pass **pw, int id) ! 970: { ! 971: int i; ! 972: Pass *p; ! 973: char *s; ! 974: static char buf[8]; ! 975: ! 976: s = 0; ! 977: /* use last on list == first in file */ ! 978: i = (id&0xFF) ^ ((id>>8)&0xFF); ! 979: for(p = pw[i]; p; p = p->next) ! 980: if(p->id == id) ! 981: s = p->name; ! 982: if(s) ! 983: return s; ! 984: sprintf(buf, "%d", id); ! 985: return buf; ! 986: } ! 987: ! 988: void ! 989: freepass(Pass **pass) ! 990: { ! 991: int i; ! 992: Pass *p, *np; ! 993: ! 994: for(i=0; i<256; i++){ ! 995: for(p = pass[i]; p; p = np){ ! 996: np = p->next; ! 997: free(p); ! 998: } ! 999: pass[i] = 0; ! 1000: } ! 1001: } ! 1002: ! 1003: void ! 1004: getpwdf(void) ! 1005: { ! 1006: static mtime; ! 1007: struct stat stbuf; ! 1008: struct passwd *pw; ! 1009: int i; ! 1010: Pass *p; ! 1011: ! 1012: if(stat("/etc/passwd", &stbuf) < 0) ! 1013: error("can't read /etc/passwd"); ! 1014: if(stbuf.st_mtime <= mtime) ! 1015: return; ! 1016: freepass(uid); ! 1017: while(pw = getpwent()){ ! 1018: i = pw->pw_uid; ! 1019: i = (i&0xFF) ^ ((i>>8)&0xFF); ! 1020: p = erealloc(0, sizeof(Pass)); ! 1021: p->next = uid[i]; ! 1022: uid[i] = p; ! 1023: p->id = pw->pw_uid; ! 1024: p->gid = pw->pw_gid; ! 1025: p->name = estrdup(pw->pw_name); ! 1026: } ! 1027: setpwent(); ! 1028: endpwent(); ! 1029: } ! 1030: ! 1031: void ! 1032: getgrpf(void) ! 1033: { ! 1034: static mtime; ! 1035: struct stat stbuf; ! 1036: struct group *pw; ! 1037: int i; ! 1038: Pass *p; ! 1039: ! 1040: if(stat("/etc/group", &stbuf) < 0) ! 1041: error("can't read /etc/group"); ! 1042: if(stbuf.st_mtime <= mtime) ! 1043: return; ! 1044: freepass(gid); ! 1045: while(pw = getgrent()){ ! 1046: i = pw->gr_gid; ! 1047: i = (i&0xFF) ^ ((i>>8)&0xFF); ! 1048: p = erealloc(0, sizeof(Pass)); ! 1049: p->next = gid[i]; ! 1050: gid[i] = p; ! 1051: p->id = pw->gr_gid; ! 1052: p->gid = 0; ! 1053: p->name = estrdup(pw->gr_name); ! 1054: } ! 1055: setgrent(); ! 1056: endgrent(); ! 1057: } ! 1058: ! 1059: void ! 1060: error(char *s) ! 1061: { ! 1062: fprintf(stderr, "u9fs: %s\n", s); ! 1063: perror("unix error"); ! 1064: exit(1); ! 1065: } ! 1066: ! 1067: void ! 1068: errjmp(char *s) ! 1069: { ! 1070: if(s == 0) ! 1071: return; ! 1072: sendmsg(s); ! 1073: longjmp(loopjmp, 1); ! 1074: } ! 1075: ! 1076: void* ! 1077: erealloc(void *p, unsigned n) ! 1078: { ! 1079: if(p == 0) ! 1080: p = malloc(n); ! 1081: else ! 1082: p = realloc(p, n); ! 1083: if(p == 0) ! 1084: error("realloc fail"); ! 1085: return p; ! 1086: } ! 1087: ! 1088: char* ! 1089: estrdup(char *p) ! 1090: { ! 1091: p = strdup(p); ! 1092: if(p == 0) ! 1093: error("strdup fail"); ! 1094: return p; ! 1095: } ! 1096: ! 1097: #ifdef SOCKETS ! 1098: void ! 1099: remotehostname(void) ! 1100: { ! 1101: struct sockaddr_in sock; ! 1102: struct hostent *hp; ! 1103: int len; ! 1104: int on = 1; ! 1105: ! 1106: len = sizeof sock; ! 1107: if(getpeername(0, &sock, &len) < 0) ! 1108: error("getpeername"); ! 1109: hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr), ! 1110: sock.sin_family); ! 1111: if(hp == 0) ! 1112: error("gethostbyaddr"); ! 1113: strcpy(bsdhost, hp->h_name); ! 1114: fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid()); ! 1115: ! 1116: setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); ! 1117: } ! 1118: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.