|
|
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: rhdr.count = (rhdr.count/DIRLEN)*DIRLEN; ! 532: if(rf->fd->offset != rhdr.offset){ ! 533: seekdir(rf->fd->dir, 0); ! 534: for(n=0; n<rhdr.offset; ){ ! 535: de = readdir(rf->fd->dir); ! 536: if(de == 0) ! 537: break; ! 538: if(de->d_ino==0 || de->d_name[0]==0) ! 539: continue; ! 540: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) ! 541: continue; ! 542: n += DIRLEN; ! 543: } ! 544: } ! 545: for(n=0; n<rhdr.count; ){ ! 546: de = readdir(rf->fd->dir); ! 547: if(de == 0) ! 548: break; ! 549: if(de->d_ino==0 || de->d_name[0]==0) ! 550: continue; ! 551: if(strcmp(de->d_name, ".")==0 || strcmp(de->d_name, "..")==0) ! 552: continue; ! 553: strncpy(d.name, de->d_name, NAMELEN-1); ! 554: d.name[NAMELEN-1] = 0; ! 555: path = erealloc(0, strlen(f->path)+1+strlen(de->d_name)+1); ! 556: sprintf(path, "%s/%s", f->path, de->d_name); ! 557: memset(&stbuf, 0, sizeof stbuf); ! 558: if(stat(path, &stbuf) < 0){ ! 559: fprintf(stderr, "dir: bad path %s\n", path); ! 560: /* but continue... probably a bad symlink */ ! 561: } ! 562: free(path); ! 563: strncpy(d.uid, id2name(uid, stbuf.st_uid), NAMELEN); ! 564: strncpy(d.gid, id2name(gid, stbuf.st_gid), NAMELEN); ! 565: d.qid.path = qid(&stbuf); ! 566: d.qid.vers = vers(&stbuf); ! 567: d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777); ! 568: d.atime = stbuf.st_atime; ! 569: d.mtime = stbuf.st_mtime; ! 570: d.len.l.hlength = 0; ! 571: d.len.l.length = stbuf.st_size; ! 572: convD2M(&d, rdata+n); ! 573: n += DIRLEN; ! 574: } ! 575: }else{ ! 576: errno = 0; ! 577: if(rf->fd->offset != rhdr.offset){ ! 578: rf->fd->offset = rhdr.offset; ! 579: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) ! 580: errjmp(sys_errlist[errno]); ! 581: } ! 582: n = read(rf->fd->fd, rdata, rhdr.count); ! 583: if(n < 0) ! 584: errjmp(sys_errlist[errno]); ! 585: } ! 586: rf->fd->offset += n; ! 587: thdr.count = n; ! 588: thdr.data = rdata; ! 589: } ! 590: ! 591: void ! 592: rwrite(void) ! 593: { ! 594: Rfile *rf; ! 595: int n; ! 596: ! 597: rf = rfilefid(); ! 598: if(rf->fd == 0) ! 599: errjmp(Enotopen); ! 600: if(rhdr.count > sizeof rdata) ! 601: errjmp(Etoolarge); ! 602: errno = 0; ! 603: if(rf->fd->offset != rhdr.offset){ ! 604: rf->fd->offset = rhdr.offset; ! 605: if(lseek(rf->fd->fd, rhdr.offset, 0) < 0) ! 606: errjmp(sys_errlist[errno]); ! 607: } ! 608: n = write(rf->fd->fd, rhdr.data, rhdr.count); ! 609: if(n < 0) ! 610: errjmp(sys_errlist[errno]); ! 611: rf->fd->offset += n; ! 612: thdr.count = n; ! 613: } ! 614: ! 615: void ! 616: rstat(void) ! 617: { ! 618: Rfile *rf; ! 619: File *f; ! 620: Dir d; ! 621: ! 622: rf = rfilefid(); ! 623: f = rf->file; ! 624: errjmp(dostat(f, 0)); ! 625: strncpy(d.name, f->name, NAMELEN); ! 626: strncpy(d.uid, id2name(uid, f->stbuf.st_uid), NAMELEN); ! 627: strncpy(d.gid, id2name(gid, f->stbuf.st_gid), NAMELEN); ! 628: d.qid = f->qid; ! 629: d.mode = (f->qid.path&CHDIR)|(f->stbuf.st_mode&0777); ! 630: d.atime = f->stbuf.st_atime; ! 631: d.mtime = f->stbuf.st_mtime; ! 632: d.len.l.hlength = 0; ! 633: d.len.l.length = f->stbuf.st_size; ! 634: convD2M(&d, thdr.stat); ! 635: } ! 636: ! 637: void ! 638: rwstat(void) ! 639: { ! 640: Rfile *rf; ! 641: File *f; ! 642: Dir d; ! 643: Pass *p; ! 644: char *path, *dir, name[NAMELEN]; ! 645: ! 646: rf = rfilefid(); ! 647: f = rf->file; ! 648: errjmp(dostat(f, 0)); ! 649: convM2D(rhdr.stat, &d); ! 650: errno = 0; ! 651: if(rf->uid != f->stbuf.st_uid) ! 652: errjmp(Eowner); ! 653: if(strcmp(d.name, f->name) != 0){ ! 654: parentwrperm(rf); ! 655: dir = bldpath(f->path, "..", name); ! 656: path = erealloc(0, strlen(dir)+1+strlen(d.name)+1); ! 657: sprintf(path, "%s/%s", dir, d.name); ! 658: if(link(f->path, path) < 0){ ! 659: free(path); ! 660: errjmp(sys_errlist[errno]); ! 661: } ! 662: if(unlink(f->path) < 0){ ! 663: free(path); ! 664: errjmp(sys_errlist[errno]); ! 665: } ! 666: free(f->path); ! 667: free(f->name); ! 668: f->path = path; ! 669: f->name = estrdup(d.name); ! 670: } ! 671: if((d.mode&0777) != (f->stbuf.st_mode&0777)){ ! 672: if(chmod(f->path, d.mode&0777) < 0) ! 673: errjmp(sys_errlist[errno]); ! 674: f->stbuf.st_mode &= ~0777; ! 675: f->stbuf.st_mode |= d.mode&0777; ! 676: } ! 677: p = name2pass(gid, d.gid); ! 678: if(p == 0) ! 679: errjmp(Eunknown); ! 680: if(p->id != f->stbuf.st_gid){ ! 681: if(chown(f->path, f->stbuf.st_uid, p->id) < 0) ! 682: errjmp(sys_errlist[errno]); ! 683: f->stbuf.st_gid = p->id; ! 684: } ! 685: } ! 686: ! 687: void ! 688: rclunk(int rm) ! 689: { ! 690: int ret; ! 691: char *err; ! 692: Rfile *rf; ! 693: File *f; ! 694: Fd *fd; ! 695: ! 696: err = 0; ! 697: rf = rfilefid(); ! 698: f = rf->file; ! 699: if(rm){ ! 700: parentwrperm(rf); ! 701: if(f->qid.path & CHDIR) ! 702: ret = rmdir(f->path); ! 703: else ! 704: ret = unlink(f->path); ! 705: if(ret) ! 706: err = sys_errlist[errno]; ! 707: }else if(rf->rclose){ /* ignore errors */ ! 708: if(f->qid.path & CHDIR) ! 709: rmdir(f->path); ! 710: else ! 711: unlink(f->path); ! 712: } ! 713: ! 714: rf->busy = 0; ! 715: if(--f->ref == 0){ ! 716: free(f->path); ! 717: free(f->name); ! 718: free(f); ! 719: } ! 720: fd = rf->fd; ! 721: if(fd){ ! 722: if(fd->ref <= 0) ! 723: error("clunk fd count"); ! 724: if(--fd->ref == 0){ ! 725: if(fd->fd) ! 726: close(fd->fd); ! 727: if(fd->dir) ! 728: closedir(fd->dir); ! 729: free(fd); ! 730: } ! 731: rf->fd = 0; ! 732: } ! 733: if(err) ! 734: errjmp(err); ! 735: } ! 736: ! 737: char* ! 738: bldpath(char *a, char *elem, char *name) ! 739: { ! 740: char *path, *p; ! 741: ! 742: if(strcmp(elem, "..") == 0){ ! 743: if(strcmp(a, "/") == 0){ ! 744: path = estrdup(a); ! 745: strcpy(name, a); ! 746: }else{ ! 747: p = strrchr(a, '/'); ! 748: if(p == 0){ ! 749: fprintf(stderr, "path: '%s'\n", path); ! 750: error("malformed path 1"); ! 751: } ! 752: if(p == a) /* reduced to "/" */ ! 753: p++; ! 754: path = erealloc(0, (p-a)+1); ! 755: memmove(path, a, (p-a)); ! 756: path[(p-a)] = 0; ! 757: if(strcmp(path, "/") == 0) ! 758: p = path; ! 759: else{ ! 760: p = strrchr(path, '/'); ! 761: if(p == 0){ ! 762: fprintf(stderr, "path: '%s'\n", path); ! 763: error("malformed path 2"); ! 764: } ! 765: p++; ! 766: } ! 767: strcpy(name, p); ! 768: } ! 769: }else{ ! 770: if(strcmp(a, "/") == 0) ! 771: a = ""; ! 772: path = erealloc(0, strlen(a)+1+strlen(elem)+1); ! 773: sprintf(path, "%s/%s", a, elem); ! 774: strcpy(name, elem); ! 775: } ! 776: if(strlen(name) >= NAMELEN) ! 777: error("bldpath: name too long"); ! 778: return path; ! 779: } ! 780: ! 781: char* ! 782: dostat(File *f, char *elem) ! 783: { ! 784: char *path; ! 785: struct stat stbuf; ! 786: char name[NAMELEN]; ! 787: ! 788: if(elem) ! 789: path = bldpath(f->path, elem, name); ! 790: else ! 791: path = f->path; ! 792: errno = 0; ! 793: if(stat(path, &stbuf) < 0) ! 794: return sys_errlist[errno]; ! 795: if(elem){ ! 796: free(f->path); ! 797: f->path = path; ! 798: f->name = estrdup(name); ! 799: } ! 800: f->qid.path = qid(&stbuf); ! 801: f->qid.vers = vers(&stbuf); ! 802: f->stbuf = stbuf; ! 803: return 0; ! 804: } ! 805: ! 806: int ! 807: omode(int m) ! 808: { ! 809: switch(m){ ! 810: case 0: /* OREAD */ ! 811: case 3: /* OEXEC */ ! 812: return 0; ! 813: case 1: /* OWRITE */ ! 814: return 1; ! 815: case 2: /* ORDWR */ ! 816: return 2; ! 817: } ! 818: errjmp(Emode); ! 819: return 0; ! 820: } ! 821: ! 822: void ! 823: sendmsg(char *err) ! 824: { ! 825: int n; ! 826: ! 827: if(err){ ! 828: thdr.type = Rerror; ! 829: strncpy(thdr.ename, err, ERRLEN); ! 830: } ! 831: DBG(fprintf(stderr, "<< %s\n", mfmt(&thdr))); ! 832: n = convS2M(&thdr, tdata); ! 833: if(n == 0) ! 834: error("bad sendmsg format"); ! 835: if(write(1, tdata, n) != n) ! 836: error("write error"); ! 837: } ! 838: ! 839: ! 840: int ! 841: okfid(int fid) ! 842: { ! 843: enum{ Delta=10 }; ! 844: ! 845: if(fid < 0){ ! 846: fprintf(stderr, "u9fs: negative fid %d\n", fid); ! 847: return 0; ! 848: } ! 849: if(fid >= nrfilealloc){ ! 850: fid += Delta; ! 851: rfile = erealloc(rfile, fid*sizeof(Rfile)); ! 852: memset(rfile+nrfilealloc, 0, (fid-nrfilealloc)*sizeof(Rfile)); ! 853: nrfilealloc = fid; ! 854: } ! 855: return 1; ! 856: } ! 857: ! 858: Rfile* ! 859: rfilefid(void) ! 860: { ! 861: Rfile *rf; ! 862: ! 863: if(!okfid(rhdr.fid)) ! 864: errjmp(Ebadfid); ! 865: rf = &rfile[rhdr.fid]; ! 866: if(rf->busy == 0) ! 867: errjmp(Ebadfid); ! 868: if(rf->file->ref <= 0) ! 869: error("ref count"); ! 870: return rf; ! 871: } ! 872: ! 873: void ! 874: perm(Rfile *rf, int mask, struct stat *st) ! 875: { ! 876: if(st == 0) ! 877: st = &rf->file->stbuf; ! 878: /* plan 9 access semantics; simpler and more sensible */ ! 879: if(rf->uid == st->st_uid) ! 880: if((st->st_mode>>6) & mask) ! 881: return; ! 882: if(rf->gid == st->st_gid) ! 883: if((st->st_mode>>3) & mask) ! 884: return; ! 885: if((st->st_mode>>0) & mask) ! 886: return; ! 887: errjmp(Eperm); ! 888: } ! 889: ! 890: void ! 891: parentwrperm(Rfile *rf) ! 892: { ! 893: Rfile trf; ! 894: struct stat st; ! 895: char *dirp, dir[512]; ! 896: ! 897: dirp = bldpath(rf->file->path, "..", dir); ! 898: if(strlen(dirp) < sizeof dir){ /* ugly: avoid leaving dirp allocated */ ! 899: strcpy(dir, dirp); ! 900: free(dirp); ! 901: dirp = dir; ! 902: } ! 903: if(stat(dirp, &st) < 0) ! 904: errjmp(Eperm); ! 905: trf.uid = rf->uid; ! 906: trf.gid = rf->gid; ! 907: perm(&trf, 2, &st); ! 908: } ! 909: ! 910: File* ! 911: newfile(void) ! 912: { ! 913: File *f; ! 914: ! 915: f = erealloc(0, sizeof(File)); ! 916: memset(f, 0, sizeof(File)); ! 917: f->ref = 1; ! 918: return f; ! 919: } ! 920: ! 921: /* ! 922: * qids: directory bit, seven bits of device, 24 bits of inode ! 923: */ ! 924: Ulong ! 925: vers(struct stat *st) ! 926: { ! 927: return st->st_mtime; ! 928: } ! 929: ! 930: Ulong ! 931: qid(struct stat *st) ! 932: { ! 933: static int nqdev; ! 934: static Uchar *qdev; ! 935: Ulong q; ! 936: int dev; ! 937: ! 938: if(qdev == 0){ ! 939: qdev = erealloc(0, 65536U); ! 940: memset(qdev, 0, 65536U); ! 941: } ! 942: q = 0; ! 943: if((st->st_mode&S_IFMT) == S_IFDIR) ! 944: q = CHDIR; ! 945: dev = st->st_dev & 0xFFFFUL; ! 946: if(qdev[dev] == 0){ ! 947: if(++nqdev >= 128) ! 948: error("too many devices"); ! 949: qdev[dev] = nqdev; ! 950: } ! 951: q |= qdev[dev]<<24; ! 952: q |= st->st_ino & 0x00FFFFFFUL; ! 953: return q; ! 954: } ! 955: ! 956: Pass* ! 957: name2pass(Pass **pw, char *name) ! 958: { ! 959: int i; ! 960: Pass *p; ! 961: ! 962: for(i=0; i<256; i++) ! 963: for(p = pw[i]; p; p = p->next) ! 964: if(strcmp(name, p->name) == 0) ! 965: return p; ! 966: return 0; ! 967: } ! 968: ! 969: char* ! 970: id2name(Pass **pw, int id) ! 971: { ! 972: int i; ! 973: Pass *p; ! 974: char *s; ! 975: static char buf[8]; ! 976: ! 977: s = 0; ! 978: /* use last on list == first in file */ ! 979: i = (id&0xFF) ^ ((id>>8)&0xFF); ! 980: for(p = pw[i]; p; p = p->next) ! 981: if(p->id == id) ! 982: s = p->name; ! 983: if(s) ! 984: return s; ! 985: sprintf(buf, "%d", id); ! 986: return buf; ! 987: } ! 988: ! 989: void ! 990: freepass(Pass **pass) ! 991: { ! 992: int i; ! 993: Pass *p, *np; ! 994: ! 995: for(i=0; i<256; i++){ ! 996: for(p = pass[i]; p; p = np){ ! 997: np = p->next; ! 998: free(p); ! 999: } ! 1000: pass[i] = 0; ! 1001: } ! 1002: } ! 1003: ! 1004: void ! 1005: getpwdf(void) ! 1006: { ! 1007: static mtime; ! 1008: struct stat stbuf; ! 1009: struct passwd *pw; ! 1010: int i; ! 1011: Pass *p; ! 1012: ! 1013: if(stat("/etc/passwd", &stbuf) < 0) ! 1014: error("can't read /etc/passwd"); ! 1015: if(stbuf.st_mtime <= mtime) ! 1016: return; ! 1017: freepass(uid); ! 1018: while(pw = getpwent()){ ! 1019: i = pw->pw_uid; ! 1020: i = (i&0xFF) ^ ((i>>8)&0xFF); ! 1021: p = erealloc(0, sizeof(Pass)); ! 1022: p->next = uid[i]; ! 1023: uid[i] = p; ! 1024: p->id = pw->pw_uid; ! 1025: p->gid = pw->pw_gid; ! 1026: p->name = estrdup(pw->pw_name); ! 1027: } ! 1028: setpwent(); ! 1029: endpwent(); ! 1030: } ! 1031: ! 1032: void ! 1033: getgrpf(void) ! 1034: { ! 1035: static mtime; ! 1036: struct stat stbuf; ! 1037: struct group *pw; ! 1038: int i; ! 1039: Pass *p; ! 1040: ! 1041: if(stat("/etc/group", &stbuf) < 0) ! 1042: error("can't read /etc/group"); ! 1043: if(stbuf.st_mtime <= mtime) ! 1044: return; ! 1045: freepass(gid); ! 1046: while(pw = getgrent()){ ! 1047: i = pw->gr_gid; ! 1048: i = (i&0xFF) ^ ((i>>8)&0xFF); ! 1049: p = erealloc(0, sizeof(Pass)); ! 1050: p->next = gid[i]; ! 1051: gid[i] = p; ! 1052: p->id = pw->gr_gid; ! 1053: p->gid = 0; ! 1054: p->name = estrdup(pw->gr_name); ! 1055: } ! 1056: setgrent(); ! 1057: endgrent(); ! 1058: } ! 1059: ! 1060: void ! 1061: error(char *s) ! 1062: { ! 1063: fprintf(stderr, "u9fs: %s\n", s); ! 1064: perror("unix error"); ! 1065: exit(1); ! 1066: } ! 1067: ! 1068: void ! 1069: errjmp(char *s) ! 1070: { ! 1071: if(s == 0) ! 1072: return; ! 1073: sendmsg(s); ! 1074: longjmp(loopjmp, 1); ! 1075: } ! 1076: ! 1077: void* ! 1078: erealloc(void *p, unsigned n) ! 1079: { ! 1080: if(p == 0) ! 1081: p = malloc(n); ! 1082: else ! 1083: p = realloc(p, n); ! 1084: if(p == 0) ! 1085: error("realloc fail"); ! 1086: return p; ! 1087: } ! 1088: ! 1089: char* ! 1090: estrdup(char *p) ! 1091: { ! 1092: p = strdup(p); ! 1093: if(p == 0) ! 1094: error("strdup fail"); ! 1095: return p; ! 1096: } ! 1097: ! 1098: #ifdef SOCKETS ! 1099: void ! 1100: remotehostname(void) ! 1101: { ! 1102: struct sockaddr_in sock; ! 1103: struct hostent *hp; ! 1104: int len; ! 1105: int on = 1; ! 1106: ! 1107: len = sizeof sock; ! 1108: if(getpeername(0, &sock, &len) < 0) ! 1109: error("getpeername"); ! 1110: hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr), ! 1111: sock.sin_family); ! 1112: if(hp == 0) ! 1113: error("gethostbyaddr"); ! 1114: strcpy(bsdhost, hp->h_name); ! 1115: fprintf(stderr, "bsdhost %s on %d\n", bsdhost, getpid()); ! 1116: ! 1117: setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)); ! 1118: } ! 1119: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.