|
|
1.1 ! root 1: #include "sys/param.h" ! 2: #include "sys/systm.h" ! 3: #include "sys/inode.h" ! 4: #include "sys/dir.h" ! 5: #include "sys/user.h" ! 6: #include "sys/proc.h" ! 7: #include "sys/stat.h" ! 8: #include "sys/neta.h" ! 9: #include "sys/buf.h" ! 10: #include "sys/stream.h" ! 11: #include "sys/conf.h" ! 12: ! 13: /* ! 14: * obsolete network filesystem protocol ! 15: * ! 16: * i_fsflags is used in various places instead of the ! 17: * obsolete i_key ! 18: * this is a cheat ! 19: * it is allowed only because neta will soon vanish ! 20: */ ! 21: ! 22: struct senda nilx; ! 23: static long natrannum; ! 24: #define ND 100 ! 25: struct { ! 26: char len, s, n; ! 27: struct senda x[ND]; ! 28: struct rcva y[ND]; ! 29: } netabuf = {ND}; ! 30: #define addx(z) netabuf.x[netabuf.n] = *z; netabuf.s = 1; ! 31: #define addy(z) netabuf.y[netabuf.n++] = *z; if(netabuf.n >= ND) netabuf.n = 0; netabuf.s = 0; ! 32: ! 33: int naput(), naupdat(), naread(), nawrite(), natrunc(), nastat(); ! 34: int nanami(), namount(); ! 35: struct fstypsw nafs = ! 36: fsinit(naput, naupdat, naread, nawrite, natrunc, nastat, ! 37: nanami, namount, nodev, nullopen, nodev); ! 38: ! 39: namount(sip, ip, flag, mnt, fstyp) ! 40: struct inode *ip, *sip; ! 41: { ! 42: if (!suser()) ! 43: return; ! 44: if (mnt) ! 45: nadomount(sip, ip, flag, fstyp); ! 46: else ! 47: naunmount(ip, fstyp); ! 48: } ! 49: ! 50: nadomount(cip, dip, flag, fstyp) ! 51: register struct inode *cip, *dip; ! 52: { ! 53: struct inode pi; ! 54: register struct inode *rip; ! 55: ! 56: if(cip->i_sptr == NULL) { ! 57: u.u_error = ENXIO; ! 58: return; ! 59: } ! 60: if((dip->i_mode & IFMT) != IFDIR) { ! 61: u.u_error = ENOTDIR; ! 62: return; ! 63: } ! 64: /* ! 65: * take care, because of the stupid user-generated device ! 66: */ ! 67: if (dip->i_fstyp == fstyp && dip->i_dev == flag) { ! 68: u.u_error = EBUSY; ! 69: return; ! 70: } ! 71: pi.i_dev = flag; ! 72: pi.i_fstyp = fstyp; ! 73: if ((rip = iget(&pi, flag, ROOTINO)) == NULL) ! 74: return; ! 75: if (rip->i_count > 1) { ! 76: iput(rip); ! 77: u.u_error = EBUSY; ! 78: return; ! 79: } ! 80: /* ! 81: * fake the root, rather than sending NAGET now, ! 82: * to avoid a deadlock when a server mounts itself ! 83: * the next stat will correct it ! 84: */ ! 85: rip->i_mode = IFDIR|0555; ! 86: rip->i_un.i_tag = (flag<<16)|ROOTINO; ! 87: rip->i_un.i_cip = cip; ! 88: rip->i_nlink = 2; ! 89: rip->i_size = 32; ! 90: rip->i_uid = rip->i_gid = -1; ! 91: dip->i_mroot = rip; ! 92: rip->i_mpoint = dip; ! 93: prele(rip); ! 94: dip->i_count++; ! 95: cip->i_count++; ! 96: cip->i_un.i_fsflags = 0; ! 97: } ! 98: ! 99: naunmount(mip, fstyp) ! 100: register struct inode *mip; ! 101: { ! 102: register struct inode *rip; ! 103: ! 104: rip = mip->i_mroot; ! 105: plock(rip); ! 106: xumount(rip); /* shared text from remote root */ ! 107: if (rip->i_count > 1 || ifsbusy(rip)) { ! 108: u.u_error = EBUSY; ! 109: prele(rip); ! 110: return; ! 111: } ! 112: plock(mip); ! 113: mip->i_mroot = NULL; ! 114: iput(mip); ! 115: if ((mip = rip->i_un.i_cip) == NULL) ! 116: panic("naunmount"); ! 117: iput(rip); ! 118: iput(mip); ! 119: } ! 120: ! 121: naput(ip) ! 122: struct inode *ip; ! 123: { struct senda x; ! 124: struct rcva y; ! 125: ! 126: if (ip->i_un.i_cip == NULL) ! 127: return; /* obscure gmount safety */ ! 128: if(ip->i_flag & ICHG) ! 129: naupdat(ip, &time, &time, 0); ! 130: x = nilx; ! 131: x.trannum = natrannum++; ! 132: x.cmd = NPUT; ! 133: x.uid = u.u_uid; ! 134: x.tag = ip->i_un.i_tag; ! 135: x.dev = ip->i_dev; ! 136: x.ino = ip->i_number; ! 137: send(ip->i_un.i_cip, &x, &y); ! 138: if(y.errno) ! 139: u.u_error = y.errno; ! 140: } ! 141: ! 142: /* ! 143: * special case: ! 144: * the root is faked up locally ! 145: * really just to avoid a silly deadlock in the face server ! 146: */ ! 147: nafillin(fip, ip) ! 148: struct inode *fip; ! 149: register struct inode *ip; ! 150: { struct senda x; ! 151: struct rcva y; ! 152: ! 153: ip->i_un.i_cip = NULL; /* in case we have to put it */ ! 154: if (fip->i_un.i_cip == NULL) { ! 155: u.u_error = ENXIO; ! 156: iput(ip); ! 157: return (-1); ! 158: } ! 159: x = nilx; ! 160: x.trannum = natrannum++; ! 161: x.cmd = NGET; ! 162: x.uid = u.u_uid; ! 163: x.dev = ip->i_dev; ! 164: x.ino = ip->i_number; ! 165: send(fip->i_un.i_cip, &x, &y); ! 166: if(y.errno == 0) { ! 167: ip->i_mode = y.mode; ! 168: ip->i_un.i_tag = y.tag; ! 169: ip->i_un.i_cip = fip->i_un.i_cip; ! 170: ip->i_nlink = y.nlink; ! 171: ip->i_size = y.size; ! 172: ip->i_uid = y.uid; ! 173: ip->i_gid = y.gid; ! 174: return (0); ! 175: } ! 176: iput(ip); ! 177: u.u_error = y.errno; ! 178: return(-1); ! 179: } ! 180: ! 181: /* this is used by CREAT */ ! 182: naupdat(ip, ta, tm, waitfor) ! 183: struct inode *ip; ! 184: time_t *ta, *tm; ! 185: { struct senda x; ! 186: struct rcva y; ! 187: ! 188: if (ip->i_un.i_cip == NULL) ! 189: return; /* obscure gmount safety */ ! 190: x = nilx; ! 191: x.trannum = natrannum++; ! 192: x.cmd = NUPDAT; ! 193: x.uid = u.u_uid; ! 194: x.gid = u.u_gid; ! 195: x.newuid = ip->i_uid; ! 196: x.newgid = ip->i_gid; ! 197: x.mode = ip->i_mode; ! 198: x.tag = ip->i_un.i_tag; ! 199: x.dev = ip->i_dev; ! 200: x.ino = ip->i_number; ! 201: if(ip->i_flag & IACC) ! 202: x.ta = *ta; ! 203: else ! 204: x.ta = 0; ! 205: if(ip->i_flag & ICHG) ! 206: x.tm = *tm; ! 207: else ! 208: x.tm = 0; ! 209: send(ip->i_un.i_cip, &x, &y); ! 210: if(y.errno) { ! 211: u.u_error = y.errno; ! 212: return; ! 213: } ! 214: ip->i_mode = y.mode; ! 215: ip->i_nlink = y.nlink; ! 216: ip->i_size = y.size; ! 217: ip->i_uid = y.uid; ! 218: ip->i_gid = y.gid; ! 219: ip->i_flag &= ~(IUPD|IACC|ICHG); ! 220: } ! 221: ! 222: naread(ip) ! 223: struct inode *ip; ! 224: { struct senda x; ! 225: struct rcva y; ! 226: struct buf *bp; ! 227: int n; ! 228: ! 229: bp = geteblk(); ! 230: clrbuf(bp); /* could use user's buffer */ ! 231: x = nilx; ! 232: x.trannum = natrannum++; ! 233: x.cmd = NREAD; ! 234: x.uid = u.u_uid; ! 235: x.tag = ip->i_un.i_tag; ! 236: x.dev = ip->i_dev; ! 237: x.ino = ip->i_number; ! 238: x.buf = bp->b_un.b_addr; ! 239: do { ! 240: n = u.u_count; ! 241: if(n > BUFSIZE) ! 242: n = BUFSIZE; ! 243: x.count = n; ! 244: x.offset = Ltol(u.u_offset); ! 245: send(ip->i_un.i_cip, &x, &y); ! 246: if((n = y.count) > 0) { ! 247: if(u.u_segflg != SEGSYS) { ! 248: if(copyout(bp->b_un.b_addr, u.u_base, n)) { ! 249: u.u_error = EFAULT; ! 250: break; ! 251: } ! 252: } ! 253: else ! 254: bcopy(bp->b_un.b_addr, u.u_base, n); ! 255: u.u_base += n; ! 256: u.u_offset = Lladd(u.u_offset, n); ! 257: u.u_count -= n; ! 258: } ! 259: if(y.errno) ! 260: u.u_error = y.errno; ! 261: } while(u.u_error == 0 && u.u_count != 0 && n > 0); ! 262: brelse(bp); ! 263: } ! 264: nawrite(ip) ! 265: struct inode *ip; ! 266: { struct senda x; ! 267: struct rcva y; ! 268: struct buf *bp; ! 269: int n; ! 270: ! 271: bp = geteblk(); ! 272: x = nilx; ! 273: x.trannum = natrannum++; ! 274: x.cmd = NWRT; ! 275: x.uid = u.u_uid; ! 276: x.tag = ip->i_un.i_tag; ! 277: x.dev = ip->i_dev; ! 278: x.ino = ip->i_number; ! 279: x.buf = bp->b_un.b_addr; ! 280: do { ! 281: n = u.u_count; ! 282: if(n > BUFSIZE) /* should be bufsiz, but ... */ ! 283: n = BUFSIZE; ! 284: if(u.u_segflg != SEGSYS) { ! 285: if(copyin(u.u_base, bp->b_un.b_addr, n)) { ! 286: u.u_error = EFAULT; ! 287: break; ! 288: } ! 289: } ! 290: else ! 291: bcopy(u.u_base, bp->b_un.b_addr, n); ! 292: x.count = n; ! 293: x.offset = Ltol(u.u_offset); ! 294: send(ip->i_un.i_cip, &x, &y); ! 295: if(y.errno) { ! 296: u.u_error = y.errno; ! 297: break; ! 298: } ! 299: ip->i_flag |= IUPD|ICHG; ! 300: u.u_count -= n; ! 301: u.u_offset = Lladd(u.u_offset, n); ! 302: u.u_base += n; ! 303: } while(u.u_error == 0 && u.u_count != 0); ! 304: brelse(bp); ! 305: } ! 306: ! 307: natrunc(ip) ! 308: struct inode *ip; ! 309: { struct senda x; ! 310: struct rcva y; ! 311: ! 312: x = nilx; ! 313: x.trannum = natrannum++; ! 314: x.cmd = NTRUNC; ! 315: x.uid = u.u_uid; ! 316: x.tag = ip->i_un.i_tag; ! 317: x.dev = ip->i_dev; ! 318: x.ino = ip->i_number; ! 319: send(ip->i_un.i_cip, &x, &y); ! 320: if(y.errno) ! 321: u.u_error = y.errno; ! 322: } ! 323: ! 324: nastat(ip, ub) ! 325: struct inode *ip; ! 326: struct stat *ub; ! 327: { struct senda x; ! 328: struct rcva y; ! 329: struct stat ds; ! 330: ! 331: x = nilx; ! 332: x.trannum = natrannum++; ! 333: x.cmd = NSTAT; ! 334: x.uid = u.u_uid; ! 335: x.tag = ip->i_un.i_tag; ! 336: x.dev = ip->i_dev; ! 337: x.ino = ip->i_number; ! 338: x.ta = time; ! 339: send(ip->i_un.i_cip, &x, &y); ! 340: if(y.errno) { ! 341: u.u_error = y.errno; ! 342: return; ! 343: } ! 344: ds.st_dev = ip->i_dev; ! 345: ds.st_ino = ip->i_number; ! 346: ip->i_mode = ds.st_mode = y.mode; ! 347: ip->i_nlink = ds.st_nlink = y.nlink; ! 348: ip->i_uid = ds.st_uid = y.uid; ! 349: ip->i_gid = ds.st_gid = y.gid; ! 350: ds.st_size = ip->i_size = y.size; ! 351: ds.st_atime = y.tm[0]; ! 352: ds.st_mtime = y.tm[1]; ! 353: ds.st_ctime = y.tm[2]; ! 354: if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) ! 355: u.u_error = EFAULT; ! 356: } ! 357: ! 358: /* a lot like fsnami */ ! 359: nanami(p, flagp, follow) ! 360: struct nx *p; ! 361: struct argnamei *flagp; ! 362: { register struct inode *dp, *dip; ! 363: register char *cp; ! 364: int i, fstyp; ! 365: dev_t d; ! 366: struct direct dent; ! 367: struct senda x; ! 368: struct rcva y; ! 369: ! 370: cp = p->cp; ! 371: dp = p->dp; ! 372: x = nilx; ! 373: x.cmd = NNAMI; ! 374: x.uid = u.u_uid; ! 375: x.gid = u.u_gid; ! 376: ! 377: /* ! 378: * dp must be a directory and ! 379: * must have X permission. ! 380: * cp is a path name relative to that directory. ! 381: */ ! 382: ! 383: dirloop: ! 384: if((dp->i_mode&IFMT) != IFDIR) ! 385: u.u_error = ENOTDIR; ! 386: (void) access(dp, IEXEC); ! 387: for (i=0; *cp!='\0' && *cp!='/'; i++) { ! 388: if (i >= DIRSIZ) { ! 389: u.u_error = ENOENT; ! 390: break; ! 391: } ! 392: dent.d_name[i] = *cp++; ! 393: } ! 394: if(u.u_error) ! 395: goto outnull; ! 396: while (i < DIRSIZ) ! 397: dent.d_name[i++] = '\0'; ! 398: if (dent.d_name[0] == '\0') { /* null name, e.g. "/" or "" */ ! 399: if (flagp->flag != NI_SEARCH) { ! 400: u.u_error = ENOENT; ! 401: goto outnull; ! 402: } ! 403: goto out; ! 404: } ! 405: u.u_segflg = SEGSYS; ! 406: ! 407: /* send off the request, get back ino, dev, flagp stuff */ ! 408: x.trannum = natrannum++; ! 409: x.tag = dp->i_un.i_tag; ! 410: x.dev = dp->i_dev; ! 411: x.ino = dp->i_number; ! 412: x.count = DIRSIZ; ! 413: x.buf = dent.d_name; ! 414: while(*cp == '/') ! 415: cp++; ! 416: if(*cp=='\0') { ! 417: switch(flagp->flag) { ! 418: case NI_SEARCH: ! 419: x.flags = NSEARCH; ! 420: break; ! 421: case NI_DEL: ! 422: x.flags = NDEL; ! 423: break; ! 424: case NI_LINK: ! 425: x.flags = NLINK; ! 426: x.dev = flagp->un.il->i_dev; ! 427: x.ino = flagp->un.il->i_number; ! 428: break; ! 429: case NI_CREAT: ! 430: case NI_NXCREAT: ! 431: x.flags = NCREAT; ! 432: x.mode = flagp->un.mode; ! 433: break; ! 434: case NI_MKDIR: ! 435: x.flags = NMKDIR; ! 436: x.mode = flagp->un.mode; ! 437: break; ! 438: case NI_RMDIR: ! 439: x.flags = NRMDIR; ! 440: break; ! 441: default: ! 442: u.u_error = ENXIO; ! 443: goto outnull; ! 444: } ! 445: } ! 446: send(dp->i_un.i_cip, &x, &y); ! 447: if(y.errno) { ! 448: u.u_error = y.errno; ! 449: goto outnull; ! 450: } ! 451: if(y.flags == NOMATCH) ! 452: goto nomatch; ! 453: dent.d_ino = y.ino; ! 454: if (y.ino == 0) { ! 455: printf("y.ino 0 in nanami\n"); ! 456: u.u_error = ENOENT; ! 457: goto outnull; ! 458: } ! 459: d = y.dev; ! 460: ! 461: if(*cp == 0 && (flagp->flag==NI_DEL || flagp->flag==NI_RMDIR)) { ! 462: /* delete the entry, server did all but xrele */ ! 463: dip = iget(dp, d, dent.d_ino); ! 464: if (dip == NULL) ! 465: goto outnull; ! 466: if (dip->i_count == 1) { ! 467: dip->i_un.i_cip = NULL; ! 468: iput(dip); ! 469: goto outnull; ! 470: } ! 471: if(dip->i_flag&ITEXT) ! 472: xrele(dip); /* free busy text */ ! 473: dip->i_nlink--; ! 474: dip->i_flag |= ICHG; ! 475: iput(dip); ! 476: goto outnull; ! 477: } ! 478: /* ! 479: * Special handling for ".." ! 480: */ ! 481: fstyp = dp->i_fstyp; ! 482: ! 483: if(y.flags == NROOT) { /* popped out of net fs */ ! 484: if (dp == u.u_rdir) ! 485: dent.d_ino = dp->i_number; ! 486: else if (dp != rootdir && dent.d_ino==ROOTINO ! 487: && dp->i_number == ROOTINO) { ! 488: if ((dip = dp->i_mpoint) == NULL) ! 489: panic("namei: mpoint"); ! 490: iput(dp); ! 491: dp = dip; ! 492: plock(dp); ! 493: dp->i_count++; ! 494: /* was there always .. there? */ ! 495: if(*cp && cp < p->nbuf + 3) ! 496: panic("nanami"); ! 497: if(!*cp && cp < p->nbuf + 2) ! 498: panic("nanami2"); ! 499: if(*cp) ! 500: *--cp = '/'; ! 501: *--cp = '.'; ! 502: *--cp = '.'; ! 503: if(fstyp != dp->i_fstyp) ! 504: goto more; ! 505: goto dirloop; ! 506: } ! 507: } ! 508: dip = dp; ! 509: prele(dip); ! 510: dp = iget(dip, d, dent.d_ino); ! 511: if(dp == NULL) { ! 512: iput(dip); ! 513: goto out; ! 514: } ! 515: if (dp->i_count == 1 && nafillin(dip, dp) < 0) { ! 516: iput(dip); ! 517: dp = NULL; ! 518: goto out; ! 519: } ! 520: if(fstyp != dp->i_fstyp) { ! 521: iput(dip); ! 522: goto more; ! 523: } ! 524: /* ! 525: * Check for symbolic link ! 526: */ ! 527: if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp)) { ! 528: char *ocp; ! 529: ! 530: ocp = cp; ! 531: while (*cp++) ! 532: ; ! 533: if (dp->i_size + (cp-ocp) >= p->nlen-1 ! 534: || ++p->nlink>8) { ! 535: u.u_error = ELOOP; ! 536: iput(dip); ! 537: goto outnull; ! 538: } ! 539: bcopy(ocp, p->nbuf+dp->i_size + 1, cp-ocp); ! 540: *(p->nbuf + dp->i_size) = '/'; ! 541: u.u_base = p->nbuf; ! 542: u.u_count = dp->i_size; ! 543: u.u_offset = ltoL(0); ! 544: readi(dp); ! 545: if(u.u_error) { ! 546: iput(dip); ! 547: goto outnull; ! 548: } ! 549: cp = p->nbuf; ! 550: iput(dp); ! 551: if (*cp == '/') { ! 552: iput(dip); ! 553: while (*cp == '/') ! 554: cp++; ! 555: if ((dp = u.u_rdir) == NULL) ! 556: dp = rootdir; ! 557: plock(dp); ! 558: dp->i_count++; ! 559: } else { ! 560: dp = dip; ! 561: plock(dp); ! 562: } ! 563: if(fstyp != dp->i_fstyp) ! 564: goto more; ! 565: goto dirloop; ! 566: } ! 567: iput(dip); ! 568: if(*cp) ! 569: goto dirloop; ! 570: if(flagp->flag == NI_SEARCH && flagp->un.buf) ! 571: bcopy((caddr_t)dent.d_name, flagp->un.buf, flagp->len); ! 572: goto out; ! 573: ! 574: nomatch: ! 575: /* ! 576: * Search failed. ! 577: */ ! 578: switch(flagp->flag) { /* probably creating a new file */ ! 579: case NI_LINK: /* make a link */ ! 580: case NI_MKDIR: /* make directory */ ! 581: goto outnull; ! 582: case NI_CREAT: /* create a new file */ ! 583: case NI_NXCREAT: ! 584: if(y.errno == EACCES || y.ino == 0) { ! 585: u.u_error = EACCES; ! 586: goto outnull; ! 587: } ! 588: dip = iget(dp, y.dev, y.ino); ! 589: if(dip == NULL) ! 590: goto outnull; ! 591: if (dip->i_count == 1 && nafillin(dp, dip) < 0) ! 592: goto outnull; ! 593: iput(dp); ! 594: dp = dip; ! 595: flagp->un.mode = ~flagp->un.mode; ! 596: goto out; ! 597: ! 598: default: ! 599: u.u_error = ENOENT; ! 600: goto outnull; ! 601: } ! 602: ! 603: out: ! 604: p->dp = dp; ! 605: return (0); ! 606: ! 607: outnull: ! 608: iput(dp); ! 609: p->dp = NULL; ! 610: return (0); ! 611: ! 612: more: ! 613: p->cp = cp; ! 614: p->dp = dp; ! 615: return (1); ! 616: } ! 617: ! 618: struct { ! 619: int tran; ! 620: short proc, dev; ! 621: } ntx[32]; /* more debuggery */ ! 622: send(cip, x, y) ! 623: struct inode *cip; ! 624: struct senda *x; ! 625: struct rcva *y; ! 626: { int n, tn, ix; ! 627: x->version = NETVERSION; ! 628: /* until demux works, use key as a lock */ ! 629: while(cip->i_un.i_fsflags) ! 630: sleep((caddr_t)cip, PZERO); ! 631: cip->i_un.i_fsflags = 1; ! 632: tn = x->trannum; ! 633: netabuf.s = 2; ! 634: for(ix = 0; ntx[ix].tran && ix < 32; ix++) { ! 635: ntx[ix].tran = tn; ! 636: ntx[ix].proc = u.u_procp->p_pid; ! 637: ntx[ix].dev = x->dev; ! 638: } ! 639: n = istwrite(cip, (char *)x, sizeof(*x)); ! 640: netabuf.s = 3; ! 641: if(n == -1) { ! 642: y->errno = EIO; ! 643: goto bad; ! 644: } ! 645: netabuf.s = 4; ! 646: if(x->count > 0 && x->buf && x->cmd != NREAD) { ! 647: n = istwrite(cip, x->buf, x->count); ! 648: if(n == -1) ! 649: goto bad; ! 650: } ! 651: readagain: ! 652: netabuf.s = 5; ! 653: n = istread(cip, (char *)y, sizeof(*y), 0); ! 654: netabuf.s = 6; ! 655: if(n != sizeof(*y)) ! 656: goto bad; ! 657: if(y->errno == 0 && x->cmd == NREAD) { ! 658: n = istread(cip, x->buf, y->count, 0); ! 659: if(n != y->count) { ! 660: printf("neta: read %d expected %d\n", n, y->count); ! 661: /* shut it down */ ! 662: istwrite(cip, (char *)x, 0); ! 663: goto bad; ! 664: } ! 665: } ! 666: if(y->errno == 0) { ! 667: if(y->trannum != tn) { ! 668: if(y->trannum < tn) /* distant past */ ! 669: goto readagain; ! 670: printf("neta: sent %d got %d\n", tn, y->trannum); ! 671: goto bad; ! 672: } ! 673: addx(x); ! 674: addy(y); ! 675: if(ix < 32) ! 676: ntx[ix].tran = 0; ! 677: cip->i_un.i_fsflags = 0; ! 678: wakeup((caddr_t)cip); ! 679: return; ! 680: } ! 681: bad: ! 682: cip->i_un.i_fsflags = 0; ! 683: if(ix < 32) ! 684: ntx[ix].tran = 0; ! 685: for(ix = 0; ix < 32; ix++) ! 686: if(ntx[ix].tran) ! 687: printf("tran %d proc %d 0x%x\n", ntx[ix].tran, ntx[ix].proc, ntx[ix].dev); ! 688: wakeup((caddr_t)cip); ! 689: addx(x); ! 690: addy(y); ! 691: if(y->errno) ! 692: return; ! 693: y->errno = EIO; ! 694: } ! 695: static struct D { struct D *a; char *b;} VER = {&VER,"\n85/6/9:neta.c\n"};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.