|
|
1.1 ! root 1: #include "netb.h" ! 2: #include "nberrno.h" ! 3: #include "rf.h" ! 4: #include "tag.h" ! 5: ! 6: #define NULL 0 ! 7: extern char *strchr(); ! 8: extern int defaultuid, defaultgid; ! 9: extern int cuid, cgid; ! 10: ! 11: #define ARB 4096 ! 12: ! 13: /* ! 14: * netb-to-local service translation ! 15: */ ! 16: ! 17: static long timeoff; ! 18: static timecheck(); ! 19: static Rfile *root; /* should this be a global? */ ! 20: static int nberrno; ! 21: ! 22: /* ! 23: * magic knowledge: fserrno and nberrno codes are the same ! 24: */ ! 25: #define fstonberr(e) (e) ! 26: ! 27: /* ! 28: * compatibility with old clients ! 29: * that don't generate NBROOTTAG ! 30: */ ! 31: static Tag oldrtag; ! 32: static int oldrdev; ! 33: #define OLDRINO 2L ! 34: static int oldclient; /* it used oldrtag */ ! 35: static int sawroot; ! 36: ! 37: static Rfile *getfile(); ! 38: static putmode(); ! 39: ! 40: /* ! 41: * make a tag from a file ! 42: * the root is an exception; it has NBROOTTAG, always ! 43: * 0x80000000 is a temporary protection against confusion with oldrtag ! 44: */ ! 45: #define maketag(f) (0x80000000|((f)->dev<<16)|((f)->ino&0xffff)) ! 46: ! 47: /* ! 48: * file modes ! 49: * not specified in netb.h, ! 50: * but they are the same as V7 Unix ! 51: */ ! 52: ! 53: #define NB_IFMT 0170000 /* file type */ ! 54: #define NB_IFDIR 0040000 /* directory */ ! 55: #define NB_IFREG 0100000 /* regular file */ ! 56: #define NB_PERM 07777 /* permissions */ ! 57: ! 58: #define fstonbmode(m) (m) /* other modes (assumed) same as rf */ ! 59: #define nbtofsmode(m) ((m)&07777) /* modes that may be set */ ! 60: ! 61: long time(); ! 62: ! 63: /* ! 64: * init things; ! 65: * called before the connection is fully open ! 66: * mainly, set up the root ! 67: */ ! 68: ! 69: int ! 70: _rfinit(argc, argv) ! 71: int argc; ! 72: char **argv; ! 73: { ! 74: ! 75: if ((root = fsinit(argc, argv)) == NULL) { ! 76: rflog("init failed\n"); ! 77: return (0); ! 78: } ! 79: if (_rfnewtag((Tag)NBROOTTAG, root) != root) { ! 80: rflog("can't install root\n"); ! 81: return (0); ! 82: } ! 83: return (1); ! 84: } ! 85: ! 86: /* ! 87: * namei ! 88: * ! 89: * hand the pathname to fswalk, a piece at a time ! 90: * on reaching the end, do the operation implied by SNB_FLAGS ! 91: * fswalk might return an Rfile that is already in our table; ! 92: * keep the older one. ! 93: * -- be careful when calling fsdone on intermediate directories ! 94: * in the path; they might be in use in some other way, and ! 95: * fsdone will wreak havoc. ! 96: * dirintab is there so _rfdone needn't be called every time, ! 97: * especially for directories we know are already in the table ! 98: */ ! 99: ! 100: _rfnamei(fd, sp, len) ! 101: int fd; ! 102: unsigned char *sp; ! 103: int len; ! 104: { ! 105: unsigned char rbuf[RNMSIZE]; ! 106: register unsigned char *pp; ! 107: register Rfile *f, *df; ! 108: Rfile *lnf; ! 109: int dirintab; ! 110: register char *cp, *ep; ! 111: Tag t; ! 112: int cruid, crgid, crmode; ! 113: long tm; ! 114: ! 115: nberrno = 0; ! 116: tonetchar(rbuf, RNB_FLAGS, 0); ! 117: pp = sp; ! 118: if (len < SNMSIZE) ! 119: rfpanic("namei: len %d\n", len); ! 120: pp[len] = 0; /* guarantee null at end of name */ ! 121: cp = (char *)pp + SNMSIZE; ! 122: while (*cp == '/') ! 123: cp++; ! 124: dirintab = 1; ! 125: if ((df = getfile(&pp[SNB_TAG])) == NULL) { ! 126: nberrno = NBEINVAL; ! 127: goto out; ! 128: } ! 129: while ((ep = strchr(cp, '/')) != NULL) { ! 130: *ep++ = 0; ! 131: while (*ep == '/') ! 132: ep++; ! 133: if (df->type != RFTDIR) { ! 134: nberrno = NBENOENT; ! 135: goto out; ! 136: } ! 137: if (_rfpdsearch(df, rfuid, rfgid) == NULL) { ! 138: nberrno = NBEACCES; ! 139: goto out; ! 140: } ! 141: if ((f = fswalk(df, cp)) == NULL) ! 142: goto eout; ! 143: if (f != df && dirintab == 0) ! 144: fsdone(df); ! 145: if (f->ino == root->ino && f->dev == root->dev) { ! 146: if (f != root) ! 147: fsdone(f); ! 148: df = root; ! 149: dirintab = 1; ! 150: } else if ((df = _rftagtof(maketag(f))) != NULL) { ! 151: fsdone(f); ! 152: dirintab = 1; ! 153: } else { ! 154: df = f; ! 155: dirintab = 0; ! 156: } ! 157: cp = ep; ! 158: } ! 159: /* ! 160: * cp is now last component ! 161: * ! 162: * the tests that follow are wrong if the root isn't a directory ! 163: * think about implications ! 164: */ ! 165: if (df->type != RFTDIR) { ! 166: nberrno = NBENOENT; ! 167: goto out; ! 168: } ! 169: if (_rfpdsearch(df, rfuid, rfgid) == 0) { ! 170: nberrno = NBEACCES; ! 171: goto out; ! 172: } ! 173: switch (frnetchar(pp, SNB_FLAGS)) { ! 174: case NI_SEARCH: ! 175: if (cp[0] == 0) { /* empty filename */ ! 176: f = df; ! 177: fsstat(f); /* get fresh info */ ! 178: break; ! 179: } ! 180: if ((f = fswalk(df, cp)) == NULL) ! 181: goto eout; ! 182: break; ! 183: ! 184: case NI_NXCREAT: ! 185: case NI_CREAT: ! 186: cruid = rfuid; ! 187: if (cruid == RFNOID && defaultuid != RFNOID) ! 188: cruid = defaultuid; ! 189: crgid = rfgid; ! 190: if (crgid == RFNOID && defaultgid != RFNOID) ! 191: crgid = defaultgid; ! 192: crmode = frnetshort(pp, SNM_MODE); ! 193: if ((f = fswalk(df, cp)) == NULL) { /* doesn't exist */ ! 194: if (cruid == RFNOID || crgid == RFNOID /* don't create ownerless files */ ! 195: || _rfpdwrite(df, cruid, crgid) == 0) { ! 196: nberrno = NBEACCES; ! 197: goto out; ! 198: } ! 199: } else if (frnetchar(pp, SNB_FLAGS) == NI_NXCREAT) { ! 200: _rfdone(f); ! 201: nberrno = NBEEXIST; /* NXCREAT means it shouldn't exist */ ! 202: goto out; ! 203: } else { ! 204: if (_rfpwrite(f, cruid, crgid) == 0) { ! 205: _rfdone(f); ! 206: nberrno = NBEACCES; ! 207: goto out; ! 208: } ! 209: cruid = f->uid; ! 210: crgid = f->gid; ! 211: crmode = f->mode; ! 212: _rfdone(f); /* we'll re-create anyway */ ! 213: } ! 214: if ((f = fscreate(df, cp, crmode, cruid, crgid)) == NULL) ! 215: goto eout; ! 216: break; ! 217: ! 218: case NI_LINK: ! 219: if ((lnf = getfile(&pp[SNM_INO])) == NULL) { ! 220: nberrno = NBEINVAL; ! 221: goto out; ! 222: } ! 223: #if NOTDEF ! 224: if (lnf->type == RFTDIR && _rfpsuper(lnf, rfuid, rfgid) == 0) { ! 225: #else ! 226: if (lnf->type == RFTDIR) { ! 227: #endif ! 228: nberrno = NBEISDIR; ! 229: goto out; ! 230: } ! 231: if (_rfpdwrite(df, rfuid, rfgid) == 0) { ! 232: nberrno = NBEACCES; ! 233: goto out; ! 234: } ! 235: if (fslink(df, cp, lnf) < 0) ! 236: goto eout; ! 237: goto out; ! 238: ! 239: case NI_MKDIR: ! 240: cruid = rfuid; ! 241: if (cruid == RFNOID && defaultuid != RFNOID) ! 242: cruid = defaultuid; ! 243: crgid = rfgid; ! 244: if (crgid == RFNOID && defaultgid != RFNOID) ! 245: crgid = defaultgid; ! 246: if (cruid == RFNOID || crgid == RFNOID ! 247: || _rfpdwrite(df, cruid, crgid) == 0) { ! 248: nberrno = NBEACCES; ! 249: goto out; ! 250: } ! 251: if (fsmkdir(df, cp, frnetshort(pp, SNM_MODE), cruid, crgid) < 0) ! 252: goto eout; ! 253: goto out; ! 254: ! 255: case NI_RMDIR: ! 256: if (_rfpdwrite(df, rfuid, rfgid) == 0) { ! 257: nberrno = NBEACCES; ! 258: goto out; ! 259: } ! 260: if (fsrmdir(df, cp) < 0) ! 261: goto eout; ! 262: goto out; ! 263: ! 264: case NI_DEL: ! 265: if (_rfpdwrite(df, rfuid, rfgid) == 0) { ! 266: nberrno = NBEACCES; ! 267: goto out; ! 268: } ! 269: if ((f = fswalk(df, cp)) == NULL) ! 270: goto eout; ! 271: #if NOTDEF ! 272: if (f->type == RFTDIR && _rfpsuper(f, rfuid, rfgid) == 0) { ! 273: #else ! 274: if (f->type == RFTDIR) { ! 275: #endif ! 276: _rfdone(f); ! 277: nberrno = NBEISDIR; ! 278: goto out; ! 279: } ! 280: _rfdone(f); ! 281: if (fsdelete(df, cp) < 0) ! 282: goto eout; ! 283: goto out; ! 284: ! 285: default: ! 286: nberrno = NBEINVAL; ! 287: goto out; ! 288: } ! 289: /* ! 290: * returning a newly-opened file ! 291: */ ! 292: if (f->dev == root->dev && f->ino == root->ino) ! 293: t = NBROOTTAG; ! 294: else ! 295: t = maketag(f); ! 296: if ((lnf = _rfnewtag(t, f)) == NULL) { ! 297: fsdone(f); ! 298: nberrno = NBEINVAL; ! 299: goto out; ! 300: } else if (lnf != f) { /* already had that file */ ! 301: fsdone(f); ! 302: f = lnf; ! 303: } ! 304: if (f == df) ! 305: dirintab = 1; /* we just made sure of that */ ! 306: pp = rbuf; ! 307: tonetlong(pp, RNM_TAG, t); ! 308: tonetlong(pp, RNM_INO, f->ino); ! 309: tonetshort(pp, RNM_DEV, f->dev); ! 310: putmode(pp, RNM_MODE, f); ! 311: tonetshort(pp, RNM_NLINK, f->nlink); ! 312: /* ! 313: * the default ownership here might be wrong...check it. ! 314: */ ! 315: if (defaultuid != RFNOID && rfuid == RFNOID && f->uid == defaultuid) ! 316: len = cuid; /* tell him he owns it */ ! 317: else ! 318: len = _rfcuid(f->uid); ! 319: tonetshort(pp, RNM_UID, len); ! 320: len = _rfcgid(f->gid); /* stub - this gid processing may be wrong */ ! 321: if (len == RFNOID) ! 322: len = cgid; ! 323: tonetshort(pp, RNM_GID, len); ! 324: tonetshort(pp, RNM_RDEV, f->rdev); ! 325: #if 0x100000000 == 0 /* 32-bit machine */ ! 326: tonetlong(pp, RNM_SIZE, f->size); ! 327: #else /* probably the Cray */ ! 328: if ((tm = f->size) > 0x7fffffff) ! 329: tm = 0x7fffffff; ! 330: tonetlong(pp, RNM_SIZE, tm); ! 331: #endif ! 332: tm = f->ta + timeoff; ! 333: tonetlong(pp, RNM_ATIME, tm); ! 334: tm = f->tm + timeoff; ! 335: tonetlong(pp, RNM_MTIME, tm); ! 336: tm = f->tc + timeoff; ! 337: tonetlong(pp, RNM_CTIME, tm); ! 338: if (oldclient) { ! 339: len = (f->dev & 0xff) | (oldrdev & 0xff00); ! 340: tonetshort(pp, RNM_DEV, len); ! 341: if (f == root) { ! 342: tonetlong(pp, RNM_TAG, oldrtag); ! 343: tonetshort(pp, RNM_DEV, oldrdev); ! 344: tonetlong(pp, RNM_INO, OLDRINO); ! 345: } ! 346: } ! 347: goto out; ! 348: ! 349: /* ! 350: * failed to find a file ! 351: * if nberrno == 0, popped out of root ! 352: */ ! 353: eout: ! 354: if (fserrno) ! 355: nberrno = fstonberr(fserrno); ! 356: else { ! 357: nberrno = 0; ! 358: tonetchar(rbuf, RNB_FLAGS, NBROOT); ! 359: while (*cp && *cp != '/') ! 360: cp++; ! 361: len = cp - (char *)(sp + SNMSIZE); ! 362: if (rfdebug) ! 363: rflog("popped out; used %d\n", len); ! 364: tonetlong(rbuf, RNM_USED, len); ! 365: } ! 366: /* ! 367: * done ! 368: */ ! 369: out: ! 370: if (dirintab == 0) ! 371: _rfdone(df); ! 372: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 373: _rfresp(fd, sp, rbuf, RNMSIZE); ! 374: } ! 375: ! 376: /* ! 377: * discard f if it is not in the tag table ! 378: * used by rfnamei to discard files fetched halfway, ! 379: * e.g. directories in the middle of a path ! 380: */ ! 381: ! 382: _rfdone(f) ! 383: register Rfile *f; ! 384: { ! 385: ! 386: if (f == root) ! 387: return; ! 388: if (_rftagtof(maketag(f)) == f) ! 389: return; ! 390: fsdone(f); ! 391: } ! 392: ! 393: /* ! 394: * put ! 395: */ ! 396: ! 397: _rfput(fd, sp, len) ! 398: int fd; ! 399: register unsigned char *sp; ! 400: int len; ! 401: { ! 402: unsigned char rbuf[RNBSIZE]; ! 403: Tag t; ! 404: Rfile *f; ! 405: ! 406: t = frnetlong(sp, SNB_TAG); ! 407: if ((f = getfile(&sp[SNB_TAG])) == NULL) ! 408: nberrno = NBEINVAL; ! 409: else { ! 410: _rfdeltag(t); ! 411: nberrno = 0; ! 412: fsdone(f); ! 413: } ! 414: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 415: _rfresp(fd, sp, rbuf, RNBSIZE); ! 416: } ! 417: ! 418: /* ! 419: * stat ! 420: */ ! 421: ! 422: _rfstat(fd, sp, len) ! 423: int fd; ! 424: unsigned char *sp; ! 425: int len; ! 426: { ! 427: int i; ! 428: unsigned char rbuf[RSTSIZE]; ! 429: register unsigned char *rp; ! 430: register Rfile *f; ! 431: long tm; ! 432: ! 433: if (len < SSTSIZE) ! 434: rfpanic("stat: len %d\n", len); ! 435: rp = rbuf; ! 436: if ((f = getfile(&sp[SNB_TAG])) == NULL) ! 437: nberrno = NBEINVAL; ! 438: else if (fsstat(f) < 0) ! 439: nberrno = fstonberr(fserrno); ! 440: else { ! 441: nberrno = 0; ! 442: /* should have hysteresis here */ ! 443: timecheck(frnetlong(sp, SST_TIME)); ! 444: tonetlong(rp, RST_INO, f->ino); ! 445: tonetshort(rp, RST_DEV, f->dev); ! 446: putmode(rp, RST_MODE, f); ! 447: tonetshort(rp, RST_NLINK, f->nlink); ! 448: if (defaultuid != RFNOID && rfuid == RFNOID && f->uid == defaultuid) ! 449: i = cuid; /* let the client think he owns it */ ! 450: else ! 451: i = _rfcuid(f->uid); ! 452: /*rflog("stat: f->uid=%d defaultuid=%d cuid=%d rfcuid=%d returning %d\n", ! 453: f->uid, defaultuid, cuid, _rfcuid(f->uid), i);*/ ! 454: tonetshort(rp, RST_UID, i); ! 455: i = _rfcgid(f->gid); /* stub - default gid processing? */ ! 456: tonetshort(rp, RST_GID, i); ! 457: #if 0x100000000 == 0 /* 32-bit machine */ ! 458: tonetlong(rp, RST_SIZE, f->size); ! 459: #else /* probably the Cray */ ! 460: if ((tm = f->size) > 0x7fffffff) ! 461: tm = 0x7fffffff; ! 462: tonetlong(rp, RST_SIZE, f->size); ! 463: #endif ! 464: tm = f->ta + timeoff; ! 465: tonetlong(rp, RST_ATIME, tm); ! 466: tm = f->tm + timeoff; ! 467: tonetlong(rp, RST_MTIME, tm); ! 468: tm = f->tc + timeoff; ! 469: tonetlong(rp, RST_CTIME, tm); ! 470: } ! 471: tonetshort(rp, RNB_ERRNO, nberrno); ! 472: _rfresp(fd, sp, rp, RSTSIZE); ! 473: } ! 474: ! 475: /* ! 476: * update: ! 477: * write attributes ! 478: */ ! 479: ! 480: _rfupdate(fd, sp, len) ! 481: int fd; ! 482: register unsigned char *sp; ! 483: int len; ! 484: { ! 485: unsigned char rbuf[RNBSIZE]; ! 486: static Rfile na; ! 487: Rfile *f; ! 488: ! 489: if (len < SUPSIZE) ! 490: rfpanic("update: len %d\n", len); ! 491: if ((f = getfile(&sp[SNB_TAG])) == NULL) ! 492: nberrno = NBEINVAL; ! 493: else { ! 494: na.mode = nbtofsmode(frnetshort(sp, SUP_MODE)); ! 495: na.ta = frnetlong(sp, SUP_ATIME); ! 496: na.tm = frnetlong(sp, SUP_MTIME); ! 497: if (na.ta == 0) /* current time: local system did it */ ! 498: na.ta = f->ta; ! 499: else ! 500: na.ta -= timeoff; ! 501: if (na.tm == 0) ! 502: na.tm = f->tm; ! 503: else ! 504: na.tm -= timeoff; ! 505: na.uid = f->uid; /* netb doesn't supply */ ! 506: na.gid = f->gid; ! 507: na.size = f->size; /* not set here */ ! 508: if ((na.mode & NB_PERM) != (fstonbmode(f->mode) & NB_PERM) ! 509: && _rfpowner(f, rfuid, rfgid) == 0) ! 510: nberrno = NBEPERM; ! 511: else if (fsupdate(f, &na) < 0) ! 512: nberrno = fstonberr(fserrno); ! 513: else ! 514: nberrno = 0; ! 515: } ! 516: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 517: _rfresp(fd, sp, rbuf, RNBSIZE); ! 518: } ! 519: ! 520: /* ! 521: * read ! 522: */ ! 523: _rfread(fd, sp, mlen) ! 524: int fd; ! 525: register unsigned char *sp; ! 526: int mlen; ! 527: { ! 528: unsigned char rbuf[RNBSIZE+ARB]; /* should be negotiated size */ ! 529: Rfile *f; ! 530: int len; ! 531: ! 532: if (mlen < SRDSIZE) ! 533: rfpanic("read: len %d\n", mlen); ! 534: len = frnetlong(sp, SRD_LEN); ! 535: tonetchar(rbuf, RNB_FLAGS, 0); ! 536: if (len <= 0 || (f = getfile(&sp[SNB_TAG])) == NULL) { ! 537: nberrno = NBEINVAL; ! 538: len = 0; ! 539: } else if (_rfpread(f, rfuid, rfgid) == 0) { ! 540: nberrno = NBEACCES; ! 541: len = 0; ! 542: } else { ! 543: if (len > ARB) ! 544: len = ARB; ! 545: len = fsread(f, frnetlong(sp, SRD_OFFSET), ! 546: (char *)rbuf + RNBSIZE, len); ! 547: if (len < 0) { ! 548: nberrno = fstonberr(fserrno); ! 549: len = 0; ! 550: } else { ! 551: nberrno = 0; ! 552: if (len == 0) ! 553: tonetchar(rbuf, RNB_FLAGS, NBEND); ! 554: } ! 555: } ! 556: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 557: len += RNBSIZE; ! 558: _rfresp(fd, sp, rbuf, len); ! 559: } ! 560: ! 561: /* ! 562: * read directory ! 563: */ ! 564: _rfdir(fd, sp, mlen) ! 565: int fd; ! 566: register unsigned char *sp; ! 567: int mlen; ! 568: { ! 569: unsigned char rbuf[RDISIZE+ARB]; ! 570: Rfile *f; ! 571: int len; ! 572: long noff; ! 573: ! 574: if (mlen < SRDSIZE) ! 575: rfpanic("readdir: len %d\n", mlen); ! 576: len = frnetlong(sp, SRD_LEN); ! 577: if (len <= 0 || (f = getfile(&sp[SNB_TAG])) == NULL) { ! 578: nberrno = NBEINVAL; ! 579: len = 0; ! 580: } else if (f->type != RFTDIR) { ! 581: nberrno = NBENOTDIR; ! 582: len = 0; ! 583: } else if (_rfpdread(f, rfuid, rfgid) == 0) { ! 584: nberrno = NBEACCES; ! 585: len = 0; ! 586: } else { ! 587: if (len > ARB) ! 588: len = ARB; ! 589: len = fsdirread(f, frnetlong(sp, SRD_OFFSET), ! 590: (char *)rbuf + RDISIZE, len, &noff); ! 591: if (len < 0) { ! 592: nberrno = fstonberr(fserrno); ! 593: len = 0; ! 594: } else { ! 595: nberrno = 0; ! 596: noff -= frnetlong(sp, SRD_OFFSET); ! 597: tonetlong(rbuf, RDI_USED, noff); ! 598: } ! 599: } ! 600: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 601: len += RDISIZE; ! 602: _rfresp(fd, sp, rbuf, len); ! 603: } ! 604: ! 605: /* ! 606: * write ! 607: * --permissions botch: ! 608: * if we just check for write permission, ! 609: * f = creat(name, 0) will leave a file descriptor we can't write ! 610: * hence the owner check ! 611: * if the client wants to protect the user better, ! 612: * it can do its own checks; ! 613: * here we are concerned with the server ! 614: */ ! 615: _rfwrite(fd, sp, mlen) ! 616: int fd; ! 617: register unsigned char *sp; ! 618: int mlen; ! 619: { ! 620: unsigned char rbuf[RNBSIZE]; ! 621: Rfile *f; ! 622: int n; ! 623: long off; ! 624: ! 625: n = frnetlong(sp, SWR_LEN); ! 626: if (mlen != SWRSIZE + n) ! 627: rfpanic("write: size skew %d\n", mlen); ! 628: off = frnetlong(sp, SWR_OFFSET); ! 629: nberrno = 0; ! 630: if ((f = getfile(&sp[SNB_TAG])) == NULL) ! 631: nberrno = NBEINVAL; ! 632: else if (_rfpwrite(f, rfuid, rfgid) == 0 ! 633: && _rfpowner(f, rfuid, rfgid) == 0) ! 634: nberrno = NBEACCES; ! 635: else if ((n = fswrite(f, off, (char *)sp + SWRSIZE, n)) < 0) ! 636: nberrno = fstonberr(fserrno); ! 637: tonetlong(rbuf, RNB_FSIZE, f->size); ! 638: tonetshort(rbuf, RNB_ERRNO, nberrno); ! 639: _rfresp(fd, sp, rbuf, RNBSIZE); ! 640: } ! 641: ! 642: /* ! 643: * truncate file ! 644: */ ! 645: _rftrunc(fd, sp, len) ! 646: int fd; ! 647: register unsigned char *sp; ! 648: int len; ! 649: { ! 650: unsigned char rbuf[RNBSIZE]; ! 651: register Rfile *f; ! 652: Rfile newf; ! 653: ! 654: nberrno = 0; ! 655: if ((f = getfile(&sp[SNB_TAG])) == NULL) ! 656: nberrno = NBEINVAL; ! 657: else if (_rfpwrite(f, rfuid, rfgid) == 0 ! 658: && _rfpowner(f, rfuid, rfgid) == 0) /* wrong? */ ! 659: nberrno = NBEACCES; ! 660: else { ! 661: newf = *f; ! 662: newf.size = 0; ! 663: if (fsupdate(f, &newf) < 0) ! 664: nberrno = fstonberr(fserrno); ! 665: } ! 666: tonetlong(rbuf, RNB_ERRNO, nberrno); ! 667: _rfresp(fd, sp, rbuf, RNBSIZE); ! 668: } ! 669: ! 670: /* ! 671: * turn SNB_TAG (or some other tag) ! 672: * into an Rfile ! 673: */ ! 674: ! 675: static Rfile * ! 676: getfile(pp) ! 677: register unsigned char *pp; ! 678: { ! 679: Tag t; ! 680: Rfile *f; ! 681: ! 682: t = frnetlong(pp, 0); ! 683: if (t == NBROOTTAG || (oldclient && t == oldrtag)) { ! 684: sawroot = 1; ! 685: return (root); /* easy */ ! 686: } ! 687: if ((f = _rftagtof(t)) != NULL) ! 688: return (f); ! 689: if (sawroot == 0 && (t & 0xffff) == OLDRINO) { /* old-style root tag? */ ! 690: oldrtag = t; ! 691: oldrdev = t >> 16; ! 692: oldclient = 1; ! 693: rflog("old client; root tag %lx\n", t); ! 694: sawroot = 1; ! 695: return (root); ! 696: } ! 697: nberrno = NBEINVAL; /* shouldn't happen */ ! 698: rflog("bad tag %lx\n", t); ! 699: return (NULL); ! 700: } ! 701: ! 702: static ! 703: putmode(pp, off, f) ! 704: register unsigned char *pp; ! 705: int off; ! 706: register Rfile *f; ! 707: { ! 708: int mode; ! 709: ! 710: mode = fstonbmode(f->mode); ! 711: if (f->type == RFTDIR) { ! 712: mode &= 07777; ! 713: mode |= NB_IFDIR; ! 714: } else if ((mode & NB_IFMT) == 0) ! 715: mode |= NB_IFREG; ! 716: /* else pass mode through unchanged for now */ ! 717: tonetshort(pp, off, mode); ! 718: } ! 719: ! 720: /* ! 721: * correct offset twixt client time and ours ! 722: * only so often, or if difference is large; ! 723: * e.g. hosts synchronize from a common clock, ! 724: * but at different times ! 725: */ ! 726: ! 727: static ! 728: timecheck(cltime) ! 729: long cltime; ! 730: { ! 731: static int stall; ! 732: static long lastck; ! 733: long ourtime; ! 734: int diff; ! 735: ! 736: if (stall-- != 0) /* only every few stats */ ! 737: return; ! 738: stall = 3; ! 739: ourtime = time((long *)0); ! 740: diff = cltime - ourtime; ! 741: if (diff == timeoff) { ! 742: lastck = ourtime; ! 743: return; /* no change */ ! 744: } ! 745: if (diff - timeoff < 2 && diff - timeoff > -2 /* modest change */ ! 746: && ourtime - lastck < 90*60) /* and last change was recent */ ! 747: return; ! 748: lastck = ourtime; ! 749: rflog("time: client %ld server %ld old diff %d new %d\n", ! 750: cltime, ourtime, timeoff, diff); ! 751: timeoff = diff; ! 752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.