|
|
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: /* ! 167: * here and in nbwrite, `tonetlong(..., Ltol(u.u_offset))' is OK. ! 168: * it looks like four function calls, one per byte, ! 169: * but Ltol is a macro without side effects. ! 170: * maybe there should just be a temporary for clarity ! 171: */ ! 172: nbread(ip) ! 173: register struct inode *ip; ! 174: { ! 175: unsigned char sbuf[SRDSIZE]; ! 176: register unsigned char *rp; ! 177: register unsigned char *sp; ! 178: register int n; ! 179: ! 180: ip->i_un.i_fsflags &=~ NSTOK; ! 181: rp = getnbbuf(); ! 182: sp = sbuf; ! 183: bzero(sp, sizeof(sbuf)); ! 184: tonetchar(sp, SNB_VERSION, NETB); ! 185: tonetchar(sp, SNB_CMD, NBREAD); ! 186: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 187: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 188: do { ! 189: n = u.u_count; ! 190: if(n > nbbsz - RNBSIZE) ! 191: n = nbbsz - RNBSIZE; ! 192: tonetlong(sp, SRD_LEN, n); ! 193: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset)); ! 194: nbsend(ip, sp, rp, nbbsz); ! 195: if (u.u_error) ! 196: break; ! 197: n = frnetlong(rp, RNB_LEN) - RNBSIZE; ! 198: if(n > 0 && n <= nbbsz) /* give it to user */ ! 199: iomove(rp + RNBSIZE, n, B_READ); ! 200: } while (u.u_error == 0 && u.u_count > 0 && n > 0 ! 201: && frnetchar(rp, RNB_FLAGS) != NBEND); ! 202: putnbbuf(rp); ! 203: } ! 204: ! 205: nbdirread(ip, len) ! 206: register struct inode *ip; ! 207: { ! 208: unsigned char sbuf[SRDSIZE]; ! 209: register unsigned char *sp; ! 210: register unsigned char *rp; /* RDISIZE */ ! 211: int n; ! 212: llong_t oldoff; ! 213: long netoff; /* just the 32-bit part */ ! 214: ! 215: ip->i_un.i_fsflags &=~ NSTOK; ! 216: rp = getnbbuf(); ! 217: sp = sbuf; ! 218: bzero(sp, sizeof(sbuf)); ! 219: tonetchar(sp, SNB_VERSION, NETB); ! 220: tonetchar(sp, SNB_CMD, NBDIR); ! 221: tonetlong(sp, SNB_LEN, sizeof(sbuf)); ! 222: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 223: if(len > nbbsz - RDISIZE) ! 224: len = nbbsz - RDISIZE; ! 225: tonetlong(sp, SRD_LEN, len); ! 226: oldoff = u.u_offset; ! 227: netoff = Ltol(u.u_offset); ! 228: tonetlong(sp, SRD_OFFSET, netoff); ! 229: nbsend(ip, sp, rp, nbbsz); ! 230: if(u.u_error) ! 231: goto out; ! 232: n = frnetlong(rp, RNB_LEN) - RDISIZE; ! 233: if (n > 0 && n <= nbbsz) ! 234: iomove(rp + RDISIZE, n, B_READ); ! 235: if (u.u_error) ! 236: goto out; ! 237: u.u_offset = Lladd(oldoff, frnetlong(rp, RDI_USED)); ! 238: u.u_r.r_val1 = n; ! 239: out: ! 240: putnbbuf(rp); ! 241: } ! 242: ! 243: nbwrite(ip) ! 244: register struct inode *ip; ! 245: { ! 246: register unsigned char *sp; ! 247: unsigned char rbuf[RNBSIZE]; ! 248: int n; ! 249: ! 250: ip->i_un.i_fsflags &=~ NSTOK; ! 251: sp = getnbbuf(); ! 252: bzero(sp, SWRSIZE); ! 253: tonetchar(sp, SNB_VERSION, NETB); ! 254: tonetchar(sp, SNB_CMD, NBWRT); ! 255: tonetlong(sp, SNB_TAG, ip->i_un.i_tag); ! 256: do { ! 257: n = u.u_count; ! 258: if(n > nbbsz - SWRSIZE) ! 259: n = nbbsz - SWRSIZE; ! 260: tonetlong(sp, SNB_LEN, n + SWRSIZE); ! 261: tonetlong(sp, SWR_LEN, n); ! 262: tonetlong(sp, SWR_OFFSET, Ltol(u.u_offset)); ! 263: iomove(sp + SWRSIZE, n, B_WRITE); ! 264: if (u.u_error) ! 265: break; ! 266: nbsend(ip, sp, rbuf, sizeof(rbuf)); ! 267: if (u.u_error) ! 268: break; ! 269: ip->i_flag |= IUPD|ICHG; ! 270: } while(u.u_count > 0); ! 271: if(u.u_error == 0) ! 272: ip->i_size = frnetlong(rbuf, RNB_FSIZE); ! 273: putnbbuf(sp); ! 274: } ! 275: ! 276: nbioctl(ip, cmd, addr, flag) /* fp->f_flag */ ! 277: register struct inode *ip; ! 278: caddr_t addr; ! 279: { ! 280: register unsigned char *p; ! 281: int size; ! 282: ! 283: switch(cmd) { ! 284: case NBIOCON: ! 285: nbdebug = 1; ! 286: return; ! 287: case NBIOCOFF: ! 288: nbdebug = 0; ! 289: return; ! 290: case NBIOCBSZ: ! 291: if (copyin(addr, (caddr_t)&size, sizeof(size))) { ! 292: u.u_error = EFAULT; ! 293: return; ! 294: } ! 295: if (size > 1024 && size <= NBMAXMSG) ! 296: nbbsz = size & ~1023; /* round to even 1K */ ! 297: if (copyout(addr, (caddr_t)&nbbsz, sizeof(nbbsz))) ! 298: u.u_error = EFAULT; ! 299: return; ! 300: } ! 301: /* ! 302: * one buffer, used first for sbuf, then for rbuf ! 303: */ ! 304: p = getnbbuf(); ! 305: bzero(p, SIOSIZE); ! 306: tonetchar(p, SNB_VERSION, NETB); ! 307: tonetchar(p, SNB_CMD, NBIOCTL); ! 308: tonetlong(p, SNB_LEN, SIOSIZE + SIODATA); ! 309: tonetlong(p, SNB_TAG, ip->i_un.i_tag); ! 310: tonetlong(p, SIO_CMD, cmd); ! 311: tonetshort(p, SIO_FLAG, flag); ! 312: if(copyin(addr, p + SIOSIZE, SIODATA)) { ! 313: u.u_error = EFAULT; ! 314: goto out; ! 315: } ! 316: nbsend(ip, p, p, RNBSIZE + SIODATA); ! 317: if (u.u_error) ! 318: goto out; ! 319: if(frnetlong(p, RNB_LEN) != RNBSIZE + SIODATA) { ! 320: printf("netb: nbioc got %d, not %d\n", ! 321: frnetlong(p, RNB_LEN), RNBSIZE+SIODATA); ! 322: u.u_error = EIO; ! 323: goto out; ! 324: } ! 325: if(copyout(p+RNBSIZE, addr, SIODATA)) ! 326: u.u_error = EFAULT; ! 327: out: ! 328: putnbbuf(p); ! 329: } ! 330: ! 331: /* ! 332: * namei: ! 333: * send the whole pathname ! 334: * wrong if another filesystem is mounted ! 335: * atop some file in this one ! 336: */ ! 337: nbnami(p, flagp, follow) ! 338: register struct nx *p; ! 339: register struct argnamei *flagp; ! 340: { ! 341: register char *cp; ! 342: register struct inode *dp; ! 343: register unsigned char *pp; ! 344: register int nlen; ! 345: int used; ! 346: dev_t dev; ! 347: ! 348: dp = p->dp; ! 349: /* ! 350: * special case: ! 351: * if simple lookup of "" in the root, ! 352: * and the connection is dead, ! 353: * return OK even though dead so it's possible to unmount ! 354: */ ! 355: if (dp->i_mpoint->i_mroot == dp ! 356: && dp->i_un.i_fsflags & NDEAD ! 357: && flagp->flag == NI_SEARCH && *p->cp == 0) ! 358: return (0); /* with the same dp and cp */ ! 359: /* ! 360: * one buffer for rbuf and sbuf ! 361: */ ! 362: pp = getnbbuf(); ! 363: bzero(pp, SNMSIZE); ! 364: tonetchar(pp, SNB_VERSION, NETB); ! 365: tonetchar(pp, SNB_CMD, NBNAMI); ! 366: tonetlong(pp, SNB_TAG, dp->i_un.i_tag); ! 367: cp = p->cp; ! 368: while (*cp++) ! 369: ; ! 370: nlen = cp - p->cp; /* length of name, including NUL */ ! 371: if (nlen + SNMSIZE >= nbbsz) { ! 372: u.u_error = ENOENT; ! 373: goto outnull; ! 374: } ! 375: used = nlen + SNMSIZE - 1; /* temporary to improve code */ ! 376: tonetlong(pp, SNB_LEN, used); ! 377: bcopy(p->cp, pp + SNMSIZE, nlen); ! 378: tonetchar(pp, SNB_FLAGS, flagp->flag); ! 379: switch (flagp->flag) { ! 380: ! 381: case NI_CREAT: ! 382: case NI_NXCREAT: ! 383: case NI_MKDIR: ! 384: tonetshort(pp, SNM_MODE, flagp->un.mode); ! 385: break; ! 386: ! 387: case NI_LINK: ! 388: tonetlong(pp, SNM_INO, flagp->un.il->i_un.i_tag); ! 389: break; ! 390: } ! 391: nbsend(dp, pp, pp, RNMSIZE); ! 392: if(u.u_error) ! 393: goto outnull; ! 394: if (frnetchar(pp, RNB_FLAGS) == NBROOT) { ! 395: /* find my root */ ! 396: dp = dp->i_mpoint; ! 397: iput(p->dp); ! 398: if(dp == NULL) { ! 399: u.u_error = EGREG; ! 400: goto out; ! 401: } ! 402: plock(dp); ! 403: dp->i_count++; ! 404: used = frnetlong(pp, RNM_USED); ! 405: if (used < 2 || used >= nlen) { ! 406: u.u_error = EGREG; ! 407: goto outnull; ! 408: } ! 409: cp = p->cp + used; ! 410: *--cp == '.'; ! 411: *--cp == '.'; ! 412: p->cp = cp; ! 413: goto outmore; ! 414: } ! 415: switch(flagp->flag) { ! 416: ! 417: default: ! 418: panic("nbnami"); ! 419: ! 420: case NI_CREAT: /* only case where flagp is used later (creat()) */ ! 421: case NI_NXCREAT: /* return an inode, like search */ ! 422: flagp->un.mode = ~flagp->un.mode; /* obscure side-effects! */ ! 423: case NI_SEARCH: ! 424: break; ! 425: ! 426: case NI_DEL: /* nothing returned */ ! 427: case NI_LINK: /* nothing returned */ ! 428: case NI_MKDIR: /* nothing returned */ ! 429: case NI_RMDIR: /* nothing returned */ ! 430: goto outnull; ! 431: } ! 432: /* ! 433: * release directory inode, construct a new one ! 434: * fill in the attributes even if inode was already in core; ! 435: * the new data is more correct (server gets priority) ! 436: */ ! 437: prele(dp); /* in case new == old */ ! 438: /* cheat: first character of RNM_DEV == minor */ ! 439: dev = makedev(major(dp->i_dev), frnetchar(pp, RNM_DEV)); ! 440: dp = iget(dp, dev, frnetlong(pp, RNM_INO)); ! 441: /* p->dp == dp before iget was called */ ! 442: if (dp == NULL) { ! 443: idec(p->dp); ! 444: goto out; ! 445: } ! 446: if (p->dp->i_mpoint != dp->i_mpoint) { /* something mounted here */ ! 447: idec(p->dp); ! 448: p->cp += nlen - 1; /* point to NUL at the end */ ! 449: goto outmore; ! 450: } ! 451: dp->i_un.i_cip = p->dp->i_un.i_cip; ! 452: idec(p->dp); ! 453: nbunpack(dp, pp); ! 454: /* ! 455: * no filename to save for accounting; oh well ! 456: */ ! 457: if(flagp->flag == NI_SEARCH && flagp->un.buf) ! 458: bcopy("netb exec", flagp->un.buf, flagp->len); ! 459: ! 460: /* ! 461: * return the inode in dp ! 462: */ ! 463: out: ! 464: p->dp = dp; ! 465: putnbbuf(pp); ! 466: return (0); ! 467: ! 468: /* ! 469: * discard dp, return NULL ! 470: */ ! 471: outnull: ! 472: iput(dp); ! 473: p->dp = NULL; ! 474: putnbbuf(pp); ! 475: return (0); ! 476: ! 477: /* ! 478: * crossed to a different filesystem; ! 479: * return cp and dp ! 480: */ ! 481: outmore: ! 482: p->dp = dp; ! 483: putnbbuf(pp); ! 484: return (1); ! 485: } ! 486: ! 487: nbmount(cip, dip, flag, mnt, fstyp) ! 488: struct inode *cip, *dip; ! 489: { ! 490: ! 491: nbfstyp = fstyp; ! 492: if (mnt) ! 493: nbon(cip, dip, flag, fstyp); ! 494: else ! 495: nboff(dip); ! 496: } ! 497: ! 498: /* ! 499: * data structures for keeping track of device numbers in use ! 500: */ ! 501: #define NDEVS 256 ! 502: static char nbdevs[NDEVS]; ! 503: ! 504: #define D_SET(dev) nbdevs[dev] = 1 ! 505: #define D_CLR(dev) nbdevs[dev] = 0 ! 506: #define D_ISSET(dev) nbdevs[dev] ! 507: ! 508: /* ! 509: * mount the filesystem ! 510: * fake up a namei message to fetch the root ! 511: * don't call nbnami because it's too hard to get ! 512: * all the first-time error checks right ! 513: */ ! 514: ! 515: nbon(cip, dip, flag, fstyp) ! 516: struct inode *cip; ! 517: struct inode *dip; ! 518: { ! 519: register struct inode *rip; ! 520: struct inode pi; ! 521: register unsigned char *pp; ! 522: unsigned char sbuf[SNMSIZE+1]; ! 523: unsigned char rbuf[RNMSIZE]; ! 524: register int dmaj; ! 525: ! 526: if(cip->i_sptr == NULL) { /* shouting into the storm */ ! 527: u.u_error = ENXIO; ! 528: return; ! 529: } ! 530: for (dmaj = 0; dmaj < NDEVS; dmaj++) ! 531: if (D_ISSET(dmaj) == 0) ! 532: break; ! 533: if (dmaj >= NDEVS) { ! 534: u.u_error = EMFILE; ! 535: return; ! 536: } ! 537: D_SET(dmaj); ! 538: /* ! 539: * fake up an inode to represent the connection ! 540: * to nbsend and iget ! 541: */ ! 542: pi.i_fstyp = fstyp; ! 543: pi.i_mpoint = π ! 544: pi.i_mroot = π /* pi.i_mpoint->i_mroot == &pi */ ! 545: pi.i_un.i_cip = cip; ! 546: pi.i_un.i_fsflags = 0; ! 547: pp = sbuf; ! 548: bzero(pp, sizeof(sbuf)); ! 549: tonetchar(pp, SNB_VERSION, NETB); ! 550: tonetchar(pp, SNB_CMD, NBNAMI); ! 551: tonetlong(pp, SNB_TAG, NBROOTTAG); /* lookup in the root */ ! 552: tonetlong(pp, SNB_LEN, SNMSIZE+1); /* one char of filename */ ! 553: /* tonetchar(pp, SNMSIZE, 0); /* "" */ ! 554: tonetchar(pp, SNB_FLAGS, NI_SEARCH); ! 555: nbsend(&pi, pp, rbuf, sizeof(rbuf)); ! 556: if (u.u_error) { ! 557: D_CLR(dmaj); ! 558: return; ! 559: } ! 560: pp = rbuf; ! 561: if (frnetchar(pp, RNB_FLAGS) != 0) { ! 562: D_CLR(dmaj); ! 563: u.u_error = EINVAL; ! 564: return; ! 565: } ! 566: if ((rip = iget(&pi, makedev(dmaj, frnetchar(pp, RNM_DEV)), frnetlong(pp, RNM_INO))) == NULL) { ! 567: D_CLR(dmaj); ! 568: return; ! 569: } ! 570: if (rip->i_count != 1) { ! 571: printf("nbon busy, dev %d\n", dmaj); /* shouldn't happen */ ! 572: iput(rip); ! 573: D_CLR(dmaj); ! 574: u.u_error = EBUSY; ! 575: return; ! 576: } ! 577: nbunpack(rip, pp); ! 578: rip->i_un.i_cip = cip; ! 579: dip->i_mroot = rip; ! 580: rip->i_mpoint = dip; ! 581: prele(rip); ! 582: dip->i_count++; ! 583: cip->i_count++; ! 584: } ! 585: ! 586: /* ! 587: * unpack inode info from namei response ! 588: * a pity stat can't use this too, ! 589: * but the stat response isn't quite the same format ! 590: */ ! 591: nbunpack(dp, pp) ! 592: register struct inode *dp; ! 593: register unsigned char *pp; ! 594: { ! 595: ! 596: dp->i_un.i_tag = frnetlong(pp, RNM_TAG); ! 597: dp->i_mode = frnetshort(pp, RNM_MODE); ! 598: dp->i_nlink = frnetshort(pp, RNM_NLINK); ! 599: dp->i_uid = frnetshort(pp, RNM_UID); ! 600: dp->i_gid = frnetshort(pp, RNM_GID); ! 601: dp->i_size = frnetlong(pp, RNM_SIZE); ! 602: dp->i_un.i_netatime = frnetlong(pp, RNM_ATIME); ! 603: dp->i_un.i_netmtime = frnetlong(pp, RNM_MTIME); ! 604: dp->i_un.i_netctime = frnetlong(pp, RNM_CTIME); ! 605: dp->i_un.i_netrdev = frnetlong(pp, RNM_RDEV); ! 606: if (dp->i_count == 1) ! 607: dp->i_un.i_fsflags = 0; ! 608: dp->i_un.i_fsflags |= NSTOK; ! 609: } ! 610: ! 611: /* ! 612: * unmount a netb-- ! 613: * mip is the mount point ! 614: * locking needs some thought ! 615: */ ! 616: nboff(mip) ! 617: register struct inode *mip; ! 618: { ! 619: register struct inode *rip; ! 620: ! 621: rip = mip->i_mroot; ! 622: plock(rip); ! 623: if (rip->i_mpoint != mip) { /* already unmounted */ ! 624: prele(rip); ! 625: return; ! 626: } ! 627: xumount(rip); ! 628: iupdat(rip, &time, &time, 1); ! 629: ifsinacc(rip); /* turn all, including rip, to errfs */ ! 630: plock(mip); ! 631: mip->i_mroot = NULL; ! 632: iput(mip); ! 633: if (rip->i_un.i_cip == NULL) ! 634: panic("nboff"); ! 635: iput(rip->i_un.i_cip); ! 636: D_CLR(major(rip->i_dev)); ! 637: iput(rip); /* errput, not nbput */ ! 638: } ! 639: ! 640: nbsend(ip, sp, rp, size) ! 641: struct inode *ip; ! 642: register unsigned char *sp; ! 643: unsigned char *rp; ! 644: { ! 645: int bad; ! 646: long tn; ! 647: struct inode *cip; ! 648: register struct inode *rip; ! 649: ! 650: cip = ip->i_un.i_cip; ! 651: rip = ip->i_mpoint->i_mroot; ! 652: if (rip == NULL || rip->i_fstyp != ip->i_fstyp) { ! 653: u.u_error = EIO; ! 654: return; ! 655: } ! 656: while ((rip->i_un.i_fsflags & (NBUSY|NDEAD)) == NBUSY ! 657: && ip->i_fstyp == nbfstyp) { ! 658: rip->i_un.i_fsflags |= NWANT; ! 659: if (tsleep((caddr_t)cip, PZERO+1, 0) != TS_OK) { ! 660: u.u_error = EIO; ! 661: return; ! 662: } ! 663: } ! 664: if (ip->i_fstyp != nbfstyp /* unmounted under us */ ! 665: || rip->i_un.i_fsflags & NDEAD) { /* or connection fell down */ ! 666: u.u_error = EIO; ! 667: return; ! 668: } ! 669: rip->i_un.i_fsflags |= NBUSY; ! 670: tonetshort(sp, SNB_UID, u.u_uid); ! 671: tonetshort(sp, SNB_GID, u.u_gid); ! 672: tn = nbtrannum++; ! 673: tonetlong(sp, SNB_TRANNUM, tn); ! 674: if (istwrite(cip, sp, frnetlong(sp, SNB_LEN)) >= 0 ! 675: && nbrecv(cip, rp, size, tn) >= 0) ! 676: bad = 0; ! 677: else ! 678: bad = 1; ! 679: if (ip->i_fstyp == nbfstyp) { /* in case unmounted while asleep */ ! 680: rip->i_un.i_fsflags &=~ NBUSY; ! 681: if (rip->i_un.i_fsflags & NWANT) { ! 682: wakeup((caddr_t)cip); ! 683: rip->i_un.i_fsflags &=~ NWANT; ! 684: } ! 685: if (bad) ! 686: rip->i_un.i_fsflags |= NDEAD; ! 687: } ! 688: if (bad) ! 689: u.u_error = EIO; ! 690: else if ((bad = frnetshort(rp, RNB_ERRNO)) != 0) ! 691: u.u_error = bad; ! 692: } ! 693: ! 694: /* ! 695: * read an answer, ! 696: * and make sure it smells like one of ours ! 697: */ ! 698: ! 699: int ! 700: nbrecv(cip, rp, size, tn) ! 701: struct inode *cip; ! 702: register unsigned char *rp; ! 703: int size; ! 704: long tn; ! 705: { ! 706: unsigned char *p; ! 707: register int n, len, netlen; ! 708: ! 709: loop: ! 710: p = rp; ! 711: len = 0; ! 712: /* ! 713: * header ! 714: */ ! 715: while (len < RNBSIZE) { ! 716: n = istread(cip, p, size - len, 0); ! 717: if (n <= 0) ! 718: return (-1); ! 719: len += n; ! 720: p += n; ! 721: } ! 722: netlen = frnetlong(rp, RNB_LEN); ! 723: if (netlen > size || netlen < RNBSIZE) { ! 724: printf("netb: rcv len %d\n", netlen); ! 725: return (-1); ! 726: } ! 727: /* ! 728: * following data, if any ! 729: */ ! 730: while (len < netlen) { ! 731: n = istread(cip, p, size - len, 0); ! 732: if (n <= 0) ! 733: return (-1); ! 734: len += n; ! 735: p += n; ! 736: } ! 737: if (frnetlong(rp, RNB_TRANNUM) != tn) { ! 738: if (frnetlong(rp, RNB_TRANNUM) < tn) /* echo from the past */ ! 739: goto loop; ! 740: printf("netb: exp tran %d, got %d\n", tn, frnetlong(rp, RNB_TRANNUM)); ! 741: return (-1); ! 742: } ! 743: return (len); ! 744: } ! 745: ! 746: /* oh no, it's got its own tiny buffer pool: want to avoid breakage on ! 747: normal (4k reads for now). we could replace this with a real ! 748: memory manager in the kernel */ ! 749: #define NBUF 7 /* who knows? */ ! 750: char nb_lock; ! 751: char nbflgs[NBUF]; ! 752: unsigned char nbbuf[NBUF][NBMAXMSG]; ! 753: ! 754: unsigned char * ! 755: getnbbuf() ! 756: { ! 757: register int i; ! 758: ! 759: loop: ! 760: for(i = 0; i < NBUF; i++) ! 761: if(!nbflgs[i]) { ! 762: nbflgs[i] = 1; ! 763: return(nbbuf[i]); ! 764: } ! 765: nb_lock = 1; ! 766: sleep((caddr_t)&nb_lock, PZERO); ! 767: goto loop; ! 768: } ! 769: ! 770: putnbbuf(s) ! 771: unsigned char *s; ! 772: { ! 773: register int i; ! 774: ! 775: for(i = 0; i < NBUF; i++) ! 776: if(nbbuf[i] == s) { ! 777: nbflgs[i] = 0; ! 778: if(nb_lock) { ! 779: nb_lock = 0; ! 780: wakeup((caddr_t) &nb_lock); ! 781: } ! 782: return; ! 783: } ! 784: panic("putnbbuf"); ! 785: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.