|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/user.h" ! 3: #include "sys/netb.h" ! 4: #include "sys/inode.h" ! 5: #include "sys/buf.h" ! 6: #include "sys/systm.h" ! 7: #include "sys/stat.h" ! 8: #include "sys/file.h" ! 9: #include "sys/conf.h" ! 10: #include "sys/nbio.h" ! 11: ! 12: static long nbtrannum; ! 13: static int nbfstyp; ! 14: int nbdebug; ! 15: int nbput(), nbupdat(), nbread(), nbwrite(), nbtrunc(), nbstat(); ! 16: int nbnami(), nbioctl(), nbmount(), nbdirread(); ! 17: struct fstypsw nbfs = ! 18: fsinit(nbput, nbupdat, nbread, nbwrite, nbtrunc, nbstat, ! 19: nbnami, nbmount, nbioctl, nullopen, nbdirread); ! 20: unsigned char *getnbbuf(); ! 21: #define NBMAXMSG (5*1024) /* probably enough */ ! 22: int nbbsz = NBMAXMSG; ! 23: ! 24: /* ! 25: * flags in i_un.i_fsflags ! 26: * valid only in the root inode ! 27: */ ! 28: #define NBUSY 01 /* already a message outstanding */ ! 29: #define NWANT 02 /* someone waiting for BUSY */ ! 30: #define NDEAD 04 /* communication line assumed dead */ ! 31: ! 32: /* ! 33: * flags valid in any netb inode ! 34: */ ! 35: #define NSTOK 010 /* inode data is fresh; skip next stat message */ ! 36: ! 37: nbput(ip) ! 38: register struct inode *ip; ! 39: { ! 40: unsigned char sbuf[SNBSIZE]; ! 41: unsigned char rbuf[RNBSIZE]; ! 42: register unsigned char *sp; ! 43: ! 44: ! 45: /* don't put root, as optimization. pointless? */ ! 46: if (ip->i_mpoint->i_mroot == ip) ! 47: return; ! 48: if(ip->i_flag & ICHG) /* this is an extra message, but not often? */ ! 49: nbupdat(ip, &time, &time, 0); ! 50: sp = sbuf; ! 51: bzero(sp, sizeof(sbuf)); ! 52: tonetchar(sp, SNB_VERSION, NETB); ! 53: tonetchar(sp, SNB_CMD, NBPUT); ! 54: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 55: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 56: nbsend(ip, sp, rbuf, sizeof(rbuf)); ! 57: } ! 58: ! 59: nbtrunc(ip) ! 60: register struct inode *ip; ! 61: { ! 62: unsigned char sbuf[SNBSIZE]; ! 63: unsigned char rbuf[RNBSIZE]; ! 64: register unsigned char *sp; ! 65: ! 66: ip->i_un.i_fsflags &=~ NSTOK; ! 67: sp = sbuf; ! 68: bzero(sp, sizeof(sbuf)); ! 69: tonetchar(sp, SNB_VERSION, NETB); ! 70: tonetchar(sp, SNB_CMD, NBTRNC); ! 71: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 72: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 73: nbsend(ip, sp, rbuf, sizeof(rbuf)); ! 74: } ! 75: ! 76: /* ! 77: * the only times we're interested in are those which have waitfor == 0 ! 78: * (or those which have ta or tb != &time) ! 79: */ ! 80: nbupdat(ip, ta, tb, waitfor) ! 81: register time_t *ta, *tb; ! 82: register struct inode *ip; ! 83: { ! 84: unsigned char sbuf[SUPSIZE]; ! 85: unsigned char rbuf[RNBSIZE]; ! 86: register unsigned char *sp; ! 87: ! 88: ip->i_un.i_fsflags &=~ NSTOK; ! 89: sp = sbuf; ! 90: bzero(sp, sizeof(sbuf)); ! 91: tonetchar(sp, SNB_VERSION, NETB); ! 92: tonetchar(sp, SNB_CMD, NBUPD); ! 93: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 94: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 95: tonetshort(sp, SUP_MODE, ip->i_mode); ! 96: /* ! 97: * in theory *ta or *tb could be incremented ! 98: * while we are copying them char-by-char ! 99: * in practice, it doesn't matter, ! 100: * as *t? != &time ! 101: */ ! 102: if((ta != &time) && (ip->i_flag & IACC)) ! 103: tonetlong(sp, SUP_ATIME, *ta); ! 104: if((tb != &time) && (ip->i_flag & IUPD)) ! 105: tonetlong(sp, SUP_MTIME, *tb); ! 106: nbsend(ip, sp, rbuf, sizeof(rbuf)); ! 107: ip->i_flag &= ~(IUPD|IACC|ICHG); ! 108: } ! 109: ! 110: /* ! 111: * if NSTOK is set, ! 112: * the inode is full of stat data from a recent namei ! 113: * for stat, NSTOK always set, because we just called namei ! 114: * (except for the root, for which namei isn't called) ! 115: * for fstat, it is probably not set ! 116: */ ! 117: nbstat(ip, ub) ! 118: register struct inode *ip; ! 119: struct stat *ub; ! 120: { ! 121: unsigned char sbuf[SSTSIZE]; ! 122: unsigned char rbuf[RSTSIZE]; ! 123: struct stat ds; ! 124: register unsigned char *p; ! 125: long now; ! 126: ! 127: if ((ip->i_un.i_fsflags & NSTOK) == 0) { ! 128: p = sbuf; ! 129: bzero(p, sizeof(sbuf)); ! 130: tonetchar(p, SNB_VERSION, NETB); ! 131: tonetchar(p, SNB_CMD, NBSTAT); ! 132: tonetlong(p, SNB_LEN, sizeof(sbuf)); ! 133: tonetlong(p, SNB_TAG, ip->i_un.i_tag); ! 134: now = time; /* in case clock ticks */ ! 135: tonetlong(p, SST_TIME, now); ! 136: nbsend(ip, p, rbuf, sizeof(rbuf)); ! 137: if(u.u_error) ! 138: return; ! 139: p = rbuf; ! 140: ip->i_mode = frnetshort(p, RST_MODE); ! 141: ip->i_nlink = frnetshort(p, RST_NLINK); ! 142: ip->i_uid = frnetshort(p, RST_UID); ! 143: ip->i_gid = frnetshort(p, RST_GID); ! 144: ip->i_size = frnetlong(p, RST_SIZE); ! 145: ip->i_un.i_netatime = frnetlong(p, RST_ATIME); ! 146: ip->i_un.i_netmtime = frnetlong(p, RST_MTIME); ! 147: ip->i_un.i_netctime = frnetlong(p, RST_CTIME); ! 148: ip->i_un.i_netrdev = frnetlong(p, RST_RDEV); ! 149: } ! 150: ds.st_dev = ip->i_dev; ! 151: ds.st_ino = ip->i_number; ! 152: ds.st_mode = ip->i_mode; ! 153: ds.st_nlink = ip->i_nlink; ! 154: ds.st_uid = ip->i_uid; ! 155: ds.st_gid = ip->i_gid; ! 156: ds.st_size = ip->i_size; ! 157: ds.st_atime = ip->i_un.i_netatime; ! 158: ds.st_mtime = ip->i_un.i_netmtime; ! 159: ds.st_ctime = ip->i_un.i_netctime; ! 160: ds.st_rdev = ip->i_un.i_netrdev; ! 161: if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds))) ! 162: u.u_error = EFAULT; ! 163: ip->i_un.i_fsflags &=~ NSTOK; /* so repeated fstats check for changes */ ! 164: } ! 165: ! 166: nbread(ip) ! 167: register struct inode *ip; ! 168: { ! 169: unsigned char sbuf[SRDSIZE]; ! 170: register unsigned char *rp; ! 171: register unsigned char *sp; ! 172: register int n; ! 173: ! 174: ip->i_un.i_fsflags &=~ NSTOK; ! 175: rp = getnbbuf(); ! 176: sp = sbuf; ! 177: bzero(sp, sizeof(sbuf)); ! 178: tonetchar(sp, SNB_VERSION, NETB); ! 179: tonetchar(sp, SNB_CMD, NBREAD); ! 180: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 181: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 182: do { ! 183: n = u.u_count; ! 184: if(n > nbbsz - RNBSIZE) ! 185: n = nbbsz - RNBSIZE; ! 186: tonetlong(sp, SRD_LEN, n); ! 187: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset)); ! 188: nbsend(ip, sp, rp, nbbsz); ! 189: if (u.u_error) ! 190: break; ! 191: n = frnetlong(rp, RNB_LEN) - RNBSIZE; ! 192: if(n > 0 && n <= nbbsz) /* give it to user */ ! 193: iomove(rp + RNBSIZE, n, B_READ); ! 194: } while (u.u_error == 0 && u.u_count > 0 && n > 0 ! 195: && frnetchar(rp, RNB_FLAGS) != NBEND); ! 196: putnbbuf(rp); ! 197: } ! 198: ! 199: nbdirread(ip, len) ! 200: register struct inode *ip; ! 201: { ! 202: unsigned char sbuf[SRDSIZE]; ! 203: register unsigned char *sp; ! 204: register unsigned char *rp; /* RDISIZE */ ! 205: int n; ! 206: ! 207: ip->i_un.i_fsflags &=~ NSTOK; ! 208: rp = getnbbuf(); ! 209: sp = sbuf; ! 210: bzero(sp, sizeof(sbuf)); ! 211: tonetchar(sp, SNB_VERSION, NETB); ! 212: tonetchar(sp, SNB_CMD, NBDIR); ! 213: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 214: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 215: if(len > nbbsz - RDISIZE) ! 216: len = nbbsz - RDISIZE; ! 217: tonetlong(sp, SRD_LEN, len); ! 218: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset)); ! 219: nbsend(ip, sp, rp, nbbsz); ! 220: if(u.u_error) ! 221: goto out; ! 222: n = frnetlong(rp, RNB_LEN) - RDISIZE; ! 223: if(n > 0) { /* why not iomove? */ ! 224: if(u.u_segflg != SEGSYS) { ! 225: if(copyout(rp + RDISIZE, u.u_base, n)) ! 226: u.u_error = EFAULT; ! 227: } ! 228: else ! 229: bcopy(rp + RDISIZE, u.u_base, n); ! 230: } ! 231: u.u_offset = Lladd(u.u_offset, frnetlong(rp, RDI_USED)); ! 232: u.u_r.r_val1 = n; ! 233: out: ! 234: putnbbuf(rp); ! 235: } ! 236: ! 237: nbwrite(ip) ! 238: register struct inode *ip; ! 239: { ! 240: register unsigned char *sp; ! 241: unsigned char rbuf[RNBSIZE]; ! 242: int n; ! 243: ! 244: ip->i_un.i_fsflags &=~ NSTOK; ! 245: sp = getnbbuf(); ! 246: bzero(sp, SWRSIZE); ! 247: tonetchar(sp, SNB_VERSION, NETB); ! 248: tonetchar(sp, SNB_CMD, NBWRT); ! 249: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 250: do { ! 251: n = u.u_count; ! 252: if(n > nbbsz - SWRSIZE) ! 253: n = nbbsz - SWRSIZE; ! 254: tonetlong(sp, SNB_LEN, n + SWRSIZE); ! 255: tonetlong(sp, SWR_LEN, n); ! 256: tonetlong(sp, SWR_OFFSET, Ltol(u.u_offset)); ! 257: iomove(sp + SWRSIZE, n, B_WRITE); ! 258: if (u.u_error) ! 259: break; ! 260: nbsend(ip, sp, rbuf, sizeof(rbuf)); ! 261: if (u.u_error) ! 262: break; ! 263: ip->i_flag |= IUPD|ICHG; ! 264: } while(u.u_count > 0); ! 265: if(u.u_error == 0) ! 266: ip->i_size = frnetlong(rbuf, RNB_FSIZE); ! 267: putnbbuf(sp); ! 268: } ! 269: ! 270: nbioctl(ip, cmd, addr, flag) /* fp->f_flag */ ! 271: register struct inode *ip; ! 272: caddr_t addr; ! 273: { ! 274: register unsigned char *p; ! 275: int size; ! 276: ! 277: switch(cmd) { ! 278: case NBIOCON: ! 279: nbdebug = 1; ! 280: return; ! 281: case NBIOCOFF: ! 282: nbdebug = 0; ! 283: return; ! 284: case NBIOCBSZ: ! 285: if (copyin(addr, (caddr_t)&size, sizeof(size))) { ! 286: u.u_error = EFAULT; ! 287: return; ! 288: } ! 289: if (size > 1024 && size <= NBMAXMSG) ! 290: nbbsz = size & ~1023; /* round to even 1K */ ! 291: if (copyout(addr, (caddr_t)&nbbsz, sizeof(nbbsz))) ! 292: u.u_error = EFAULT; ! 293: return; ! 294: } ! 295: /* ! 296: * one buffer, used first for sbuf, then for rbuf ! 297: */ ! 298: p = getnbbuf(); ! 299: bzero(p, SIOSIZE); ! 300: tonetchar(p, SNB_VERSION, NETB); ! 301: tonetchar(p, SNB_CMD, NBIOCTL); ! 302: tonetlong(p, SNB_LEN, SIOSIZE + SIODATA); ! 303: tonetlong(p, SNB_TAG, ip->i_un.i_tag); ! 304: tonetlong(p, SIO_CMD, cmd); ! 305: tonetshort(p, SIO_FLAG, flag); ! 306: if(copyin(addr, p + SIOSIZE, SIODATA)) { ! 307: u.u_error = EFAULT; ! 308: goto out; ! 309: } ! 310: nbsend(ip, p, p, RNBSIZE + SIODATA); ! 311: if (u.u_error) ! 312: goto out; ! 313: if(frnetlong(p, RNB_LEN) != RNBSIZE + SIODATA) { ! 314: printf("netb: nbioc got %d, not %d\n", ! 315: frnetlong(p, RNB_LEN), RNBSIZE+SIODATA); ! 316: u.u_error = EIO; ! 317: goto out; ! 318: } ! 319: if(copyout(p+RNBSIZE, addr, SIODATA)) ! 320: u.u_error = EFAULT; ! 321: out: ! 322: putnbbuf(p); ! 323: } ! 324: ! 325: /* ! 326: * namei: ! 327: * send the whole pathname ! 328: * wrong if another filesystem is mounted ! 329: * atop some file in this one ! 330: */ ! 331: nbnami(p, flagp, follow) ! 332: register struct nx *p; ! 333: register struct argnamei *flagp; ! 334: { ! 335: register char *cp; ! 336: register struct inode *dp; ! 337: register unsigned char *pp; ! 338: register int nlen; ! 339: int used; ! 340: dev_t dev; ! 341: ! 342: dp = p->dp; ! 343: /* ! 344: * special case: ! 345: * if simple lookup of "" in the root, ! 346: * and the connection is dead, ! 347: * return OK even though dead so it's possible to unmount ! 348: */ ! 349: if (dp->i_mpoint->i_mroot == dp ! 350: && dp->i_un.i_fsflags & NDEAD ! 351: && flagp->flag == NI_SEARCH && *p->cp == 0) ! 352: return (0); /* with the same dp and cp */ ! 353: /* ! 354: * one buffer for rbuf and sbuf ! 355: */ ! 356: pp = getnbbuf(); ! 357: bzero(pp, SNMSIZE); ! 358: tonetchar(pp, SNB_VERSION, NETB); ! 359: tonetchar(pp, SNB_CMD, NBNAMI); ! 360: tonetlong(pp, SNB_TAG, dp->i_un.i_tag); ! 361: cp = p->cp; ! 362: while (*cp++) ! 363: ; ! 364: nlen = cp - p->cp; /* length of name, including NUL */ ! 365: if (nlen + SNMSIZE >= nbbsz) { ! 366: u.u_error = ENOENT; ! 367: goto outnull; ! 368: } ! 369: used = nlen + SNMSIZE - 1; /* temporary to improve code */ ! 370: tonetlong(pp, SNB_LEN, used); ! 371: bcopy(p->cp, pp + SNMSIZE, nlen); ! 372: tonetchar(pp, SNB_FLAGS, flagp->flag); ! 373: switch (flagp->flag) { ! 374: ! 375: case NI_CREAT: ! 376: case NI_NXCREAT: ! 377: case NI_MKDIR: ! 378: tonetshort(pp, SNM_MODE, flagp->un.mode); ! 379: break; ! 380: ! 381: case NI_LINK: ! 382: tonetlong(pp, SNM_INO, flagp->un.il->i_un.i_tag); ! 383: break; ! 384: } ! 385: nbsend(dp, pp, pp, RNMSIZE); ! 386: if(u.u_error) ! 387: goto outnull; ! 388: if (frnetchar(pp, RNB_FLAGS) == NBROOT) { ! 389: /* find my root */ ! 390: dp = dp->i_mpoint; ! 391: iput(p->dp); ! 392: if(dp == NULL) { ! 393: u.u_error = EGREG; ! 394: goto out; ! 395: } ! 396: plock(dp); ! 397: dp->i_count++; ! 398: used = frnetlong(pp, RNM_USED); ! 399: if (used < 2 || used >= nlen) { ! 400: u.u_error = EGREG; ! 401: goto outnull; ! 402: } ! 403: cp = p->cp + used; ! 404: *--cp == '.'; ! 405: *--cp == '.'; ! 406: p->cp = cp; ! 407: goto outmore; ! 408: } ! 409: switch(flagp->flag) { ! 410: ! 411: default: ! 412: panic("nbnami"); ! 413: ! 414: case NI_CREAT: /* only case where flagp is used later (creat()) */ ! 415: case NI_NXCREAT: /* return an inode, like search */ ! 416: flagp->un.mode = ~flagp->un.mode; /* obscure side-effects! */ ! 417: case NI_SEARCH: ! 418: break; ! 419: ! 420: case NI_DEL: /* nothing returned */ ! 421: case NI_LINK: /* nothing returned */ ! 422: case NI_MKDIR: /* nothing returned */ ! 423: case NI_RMDIR: /* nothing returned */ ! 424: goto outnull; ! 425: } ! 426: /* ! 427: * release directory inode, construct a new one ! 428: * fill in the attributes even if inode was already in core; ! 429: * the new data is more correct (server gets priority) ! 430: */ ! 431: prele(dp); /* in case new == old */ ! 432: /* cheat: first character of RNM_DEV == minor */ ! 433: dev = makedev(major(dp->i_dev), frnetchar(pp, RNM_DEV)); ! 434: dp = iget(dp, dev, frnetlong(pp, RNM_INO)); ! 435: /* p->dp == dp before iget was called */ ! 436: if (dp == NULL) { ! 437: idec(p->dp); ! 438: goto out; ! 439: } ! 440: if (p->dp->i_mpoint != dp->i_mpoint) { /* something mounted here */ ! 441: idec(p->dp); ! 442: p->cp += nlen - 1; /* point to NUL at the end */ ! 443: goto outmore; ! 444: } ! 445: dp->i_un.i_cip = p->dp->i_un.i_cip; ! 446: idec(p->dp); ! 447: nbunpack(dp, pp); ! 448: /* ! 449: * no filename to save for accounting; oh well ! 450: */ ! 451: if(flagp->flag == NI_SEARCH && flagp->un.buf) ! 452: bcopy("netb exec", flagp->un.buf, flagp->len); ! 453: ! 454: /* ! 455: * return the inode in dp ! 456: */ ! 457: out: ! 458: p->dp = dp; ! 459: putnbbuf(pp); ! 460: return (0); ! 461: ! 462: /* ! 463: * discard dp, return NULL ! 464: */ ! 465: outnull: ! 466: iput(dp); ! 467: p->dp = NULL; ! 468: putnbbuf(pp); ! 469: return (0); ! 470: ! 471: /* ! 472: * crossed to a different filesystem; ! 473: * return cp and dp ! 474: */ ! 475: outmore: ! 476: p->dp = dp; ! 477: putnbbuf(pp); ! 478: return (1); ! 479: } ! 480: ! 481: nbmount(cip, dip, flag, mnt, fstyp) ! 482: struct inode *cip, *dip; ! 483: { ! 484: ! 485: nbfstyp = fstyp; ! 486: if (mnt) ! 487: nbon(cip, dip, flag, fstyp); ! 488: else ! 489: nboff(dip); ! 490: } ! 491: ! 492: /* ! 493: * mount the filesystem ! 494: * fake up a namei message to fetch the root ! 495: * don't call nbnami because it's too hard to get ! 496: * all the first-time error checks right ! 497: */ ! 498: ! 499: nbon(cip, dip, flag, fstyp) ! 500: struct inode *cip; ! 501: struct inode *dip; ! 502: { ! 503: register struct inode *rip; ! 504: struct inode pi; ! 505: register unsigned char *pp; ! 506: unsigned char sbuf[SNMSIZE+1]; ! 507: unsigned char rbuf[RNMSIZE]; ! 508: register dev_t dev; ! 509: ! 510: if(cip->i_sptr == NULL) { /* shouting into the storm */ ! 511: u.u_error = ENXIO; ! 512: return; ! 513: } ! 514: if (dip->i_fstyp == fstyp && major(dip->i_dev) == major(flag)) { ! 515: u.u_error = EBUSY; ! 516: return; ! 517: } ! 518: /* ! 519: * fake up an inode to represent the connection ! 520: * to nbsend and iget ! 521: */ ! 522: pi.i_fstyp = fstyp; ! 523: pi.i_mpoint = π ! 524: pi.i_mroot = π /* pi.i_mpoint->i_mroot == &pi */ ! 525: pi.i_un.i_cip = cip; ! 526: pi.i_un.i_fsflags = 0; ! 527: pp = sbuf; ! 528: bzero(pp, sizeof(sbuf)); ! 529: tonetchar(pp, SNB_VERSION, NETB); ! 530: tonetchar(pp, SNB_CMD, NBNAMI); ! 531: tonetlong(pp, SNB_TAG, NBROOTTAG); /* lookup in the root */ ! 532: tonetlong(pp, SNB_LEN, SNMSIZE+1); /* one char of filename */ ! 533: /* tonetchar(pp, SNMSIZE, 0); /* "" */ ! 534: tonetchar(pp, SNB_FLAGS, NI_SEARCH); ! 535: nbsend(&pi, pp, rbuf, sizeof(rbuf)); ! 536: if (u.u_error) ! 537: return; ! 538: pp = rbuf; ! 539: if (frnetchar(pp, RNB_FLAGS) != 0) { ! 540: u.u_error = EINVAL; ! 541: return; ! 542: } ! 543: dev = makedev(major(flag), frnetchar(pp, RNM_DEV)); ! 544: if ((rip = iget(&pi, dev, frnetlong(pp, RNM_INO))) == NULL) ! 545: return; ! 546: if (rip->i_count != 1) { ! 547: iput(rip); ! 548: u.u_error = EBUSY; ! 549: return; ! 550: } ! 551: nbunpack(rip, pp); ! 552: rip->i_un.i_cip = cip; ! 553: dip->i_mroot = rip; ! 554: rip->i_mpoint = dip; ! 555: prele(rip); ! 556: dip->i_count++; ! 557: cip->i_count++; ! 558: } ! 559: ! 560: /* ! 561: * unpack inode info from namei response ! 562: * a pity stat can't use this too, ! 563: * but the stat response isn't quite the same format ! 564: */ ! 565: nbunpack(dp, pp) ! 566: register struct inode *dp; ! 567: register unsigned char *pp; ! 568: { ! 569: ! 570: dp->i_un.i_tag = frnetlong(pp, RNM_TAG); ! 571: dp->i_mode = frnetshort(pp, RNM_MODE); ! 572: dp->i_nlink = frnetshort(pp, RNM_NLINK); ! 573: dp->i_uid = frnetshort(pp, RNM_UID); ! 574: dp->i_gid = frnetshort(pp, RNM_GID); ! 575: dp->i_size = frnetlong(pp, RNM_SIZE); ! 576: dp->i_un.i_netatime = frnetlong(pp, RNM_ATIME); ! 577: dp->i_un.i_netmtime = frnetlong(pp, RNM_MTIME); ! 578: dp->i_un.i_netctime = frnetlong(pp, RNM_CTIME); ! 579: dp->i_un.i_netrdev = frnetlong(pp, RNM_RDEV); ! 580: if (dp->i_count == 1) ! 581: dp->i_un.i_fsflags = 0; ! 582: dp->i_un.i_fsflags |= NSTOK; ! 583: } ! 584: ! 585: /* ! 586: * unmount a netb-- ! 587: * called from above, or from nbsend when there's an error ! 588: * mip is the mount point ! 589: * locking needs some thought ! 590: */ ! 591: nboff(mip) ! 592: register struct inode *mip; ! 593: { ! 594: register struct inode *rip; ! 595: ! 596: rip = mip->i_mroot; ! 597: plock(rip); ! 598: if (rip->i_mpoint != mip) { /* already unmounted */ ! 599: prele(rip); ! 600: return; ! 601: } ! 602: xumount(rip); ! 603: iupdat(rip, &time, &time, 1); ! 604: ifsinacc(rip); /* turn all, including rip, to errfs */ ! 605: plock(mip); ! 606: mip->i_mroot = NULL; ! 607: iput(mip); ! 608: if (rip->i_un.i_cip == NULL) ! 609: panic("nboff"); ! 610: iput(rip->i_un.i_cip); ! 611: iput(rip); /* errput, not nbput */ ! 612: } ! 613: ! 614: nbsend(ip, sp, rp, size) ! 615: struct inode *ip; ! 616: register unsigned char *sp; ! 617: unsigned char *rp; ! 618: { ! 619: int bad; ! 620: long tn; ! 621: struct inode *cip; ! 622: register struct inode *rip; ! 623: ! 624: cip = ip->i_un.i_cip; ! 625: rip = ip->i_mpoint->i_mroot; ! 626: if (rip == NULL || rip->i_fstyp != ip->i_fstyp) { ! 627: u.u_error = EIO; ! 628: return; ! 629: } ! 630: while ((rip->i_un.i_fsflags & (NBUSY|NDEAD)) == NBUSY ! 631: && ip->i_fstyp == nbfstyp) { ! 632: rip->i_un.i_fsflags |= NWANT; ! 633: if (tsleep((caddr_t)cip, PZERO+1, 0) != TS_OK) { ! 634: u.u_error = EIO; ! 635: return; ! 636: } ! 637: } ! 638: if (ip->i_fstyp != nbfstyp /* unmounted under us */ ! 639: || rip->i_un.i_fsflags & NDEAD) { /* or connection fell down */ ! 640: u.u_error = EIO; ! 641: return; ! 642: } ! 643: rip->i_un.i_fsflags |= NBUSY; ! 644: tonetshort(sp, SNB_UID, u.u_uid); ! 645: tonetshort(sp, SNB_GID, u.u_gid); ! 646: tn = nbtrannum++; ! 647: tonetlong(sp, SNB_TRANNUM, tn); ! 648: if (istwrite(cip, sp, frnetlong(sp, SNB_LEN)) >= 0 ! 649: && nbrecv(cip, rp, size, tn) >= 0) ! 650: bad = 0; ! 651: else ! 652: bad = 1; ! 653: if (ip->i_fstyp == nbfstyp) { /* in case unmounted while asleep */ ! 654: rip->i_un.i_fsflags &=~ NBUSY; ! 655: if (rip->i_un.i_fsflags & NWANT) { ! 656: wakeup((caddr_t)cip); ! 657: rip->i_un.i_fsflags &=~ NWANT; ! 658: } ! 659: if (bad) ! 660: rip->i_un.i_fsflags |= NDEAD; ! 661: } ! 662: if (bad) ! 663: u.u_error = EIO; ! 664: else if ((bad = frnetshort(rp, RNB_ERRNO)) != 0) ! 665: u.u_error = bad; ! 666: } ! 667: ! 668: /* ! 669: * read an answer, ! 670: * and make sure it smells like one of ours ! 671: */ ! 672: ! 673: int ! 674: nbrecv(cip, rp, size, tn) ! 675: struct inode *cip; ! 676: register unsigned char *rp; ! 677: int size; ! 678: long tn; ! 679: { ! 680: unsigned char *p; ! 681: register int n, len, netlen; ! 682: ! 683: loop: ! 684: p = rp; ! 685: len = 0; ! 686: /* ! 687: * header ! 688: */ ! 689: while (len < RNBSIZE) { ! 690: n = istread(cip, p, size - len, 0); ! 691: if (n <= 0) ! 692: return (-1); ! 693: len += n; ! 694: p += n; ! 695: } ! 696: netlen = frnetlong(rp, RNB_LEN); ! 697: if (netlen > size || netlen < RNBSIZE) { ! 698: printf("netb: rcv len %d\n", netlen); ! 699: return (-1); ! 700: } ! 701: /* ! 702: * following data, if any ! 703: */ ! 704: while (len < netlen) { ! 705: n = istread(cip, p, size - len, 0); ! 706: if (n <= 0) ! 707: return (-1); ! 708: len += n; ! 709: p += n; ! 710: } ! 711: if (frnetlong(rp, RNB_TRANNUM) != tn) { ! 712: if (frnetlong(rp, RNB_TRANNUM) < tn) /* echo from the past */ ! 713: goto loop; ! 714: printf("netb: exp tran %d, got %d\n", tn, frnetlong(rp, RNB_TRANNUM)); ! 715: return (-1); ! 716: } ! 717: return (len); ! 718: } ! 719: ! 720: /* oh no, it's got its own tiny buffer pool: want to avoid breakage on ! 721: normal (4k reads for now). we could replace this with a real ! 722: memory manager in the kernel */ ! 723: #define NBUF 7 /* who knows? */ ! 724: char nb_lock; ! 725: char nbflgs[NBUF]; ! 726: unsigned char nbbuf[NBUF][NBMAXMSG]; ! 727: ! 728: unsigned char * ! 729: getnbbuf() ! 730: { ! 731: register int i; ! 732: ! 733: loop: ! 734: for(i = 0; i < NBUF; i++) ! 735: if(!nbflgs[i]) { ! 736: nbflgs[i] = 1; ! 737: return(nbbuf[i]); ! 738: } ! 739: nb_lock = 1; ! 740: sleep((caddr_t)&nb_lock, PZERO); ! 741: goto loop; ! 742: } ! 743: ! 744: putnbbuf(s) ! 745: unsigned char *s; ! 746: { ! 747: register int i; ! 748: ! 749: for(i = 0; i < NBUF; i++) ! 750: if(nbbuf[i] == s) { ! 751: nbflgs[i] = 0; ! 752: if(nb_lock) { ! 753: nb_lock = 0; ! 754: wakeup((caddr_t) &nb_lock); ! 755: } ! 756: return; ! 757: } ! 758: panic("putnbbuf"); ! 759: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.