|
|
1.1 ! root 1: /* ! 2: * traditional disk filesystem ! 3: */ ! 4: #include "sys/param.h" ! 5: #include "sys/systm.h" ! 6: #include "sys/ino.h" ! 7: #include "sys/buf.h" ! 8: #include "sys/filsys.h" ! 9: #include "sys/mount.h" ! 10: #include "sys/dir.h" ! 11: #include "sys/user.h" ! 12: #include "sys/inode.h" ! 13: #include "sys/file.h" ! 14: #include "sys/conf.h" ! 15: #include "sys/vlimit.h" ! 16: #include "sys/stat.h" ! 17: #include "sys/filio.h" ! 18: #include "sys/cmap.h" ! 19: #include "sys/stream.h" ! 20: ! 21: int fsput(), fsupdat(), fsread(), fswrite(), fstrunc(), fsstat(); ! 22: int fsnami(), fsmount(), fsioctl(), fsdirread(); ! 23: struct inode *fsopen(); ! 24: struct fstypsw fsfs = ! 25: fsinit(fsput, fsupdat, fsread, fswrite, fstrunc, fsstat, ! 26: fsnami, fsmount, fsioctl, fsopen, fsdirread); ! 27: ! 28: extern struct mount fsmtab[]; ! 29: extern int fscnt; ! 30: ! 31: /* ! 32: * silly mount/unmount routine for fs type 0 ! 33: */ ! 34: ! 35: fsmount(sip, ip, flag, mnt, fstyp) ! 36: register struct inode *ip, *sip; ! 37: int flag, mnt, fstyp; ! 38: { ! 39: ! 40: if (!suser()) ! 41: return; ! 42: if (mnt) ! 43: fson(sip, ip, flag, fstyp); ! 44: else ! 45: fsoff(ip, fstyp); ! 46: } ! 47: ! 48: /* ! 49: * mount a type 0 filesystem (sip on ip) ! 50: * maintain the mount table for vm code's sake ! 51: * ! 52: * magic to help booting: ! 53: * if rootdir == NULL, we are being called from iinit, so ! 54: * - allow s_valid == 0 on bitmapped filesystems so root may be mounted ! 55: * - call clkinit to set the clock from the super-block time ! 56: */ ! 57: ! 58: fson(sip, ip, ronly, fstyp) ! 59: register struct inode *ip, *sip; ! 60: int ronly, fstyp; ! 61: { ! 62: dev_t dev; ! 63: register struct mount *mp; ! 64: struct mount *emp; ! 65: struct inode *rip; ! 66: register struct filsys *fp; ! 67: struct buf *bp; ! 68: struct inode pi; /* primer */ ! 69: ! 70: if ((sip->i_mode&IFMT) != IFBLK) { ! 71: u.u_error = EINVAL; ! 72: return; ! 73: } ! 74: if (ip->i_fstyp == fstyp && ip->i_dev == sip->i_un.i_rdev) { ! 75: u.u_error = EBUSY; ! 76: return; ! 77: } ! 78: emp = NULL; ! 79: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) { ! 80: if (mp->m_dev == NULL) ! 81: emp = mp; ! 82: else if (mp->m_dev == sip) ! 83: goto hopeless; ! 84: } ! 85: if (emp == NULL) ! 86: goto hopeless; ! 87: emp->m_dev = sip; ! 88: dev = (dev_t)sip->i_un.i_rdev; ! 89: bp = bread(dev, SUPERB); ! 90: if(u.u_error) { ! 91: emp->m_dev = NULL; ! 92: brelse(bp); ! 93: return; ! 94: } ! 95: bp->b_flags |= B_LOCKED; ! 96: brelse(bp); ! 97: fp = bp->b_un.b_filsys; ! 98: fp->s_ilock = 0; ! 99: fp->s_flock = 0; ! 100: fp->s_ronly = ronly & 1; ! 101: fp->s_nbehind = 0; ! 102: fp->s_lasti = 1; ! 103: if(fp->s_cylsize == 0) ! 104: fp->s_cylsize = 40; /* transition hack */ ! 105: if(fp->s_aspace == 0) ! 106: fp->s_aspace = 4; /* likewise */ ! 107: if(BITFS(dev) && !fp->s_valid && !fp->s_ronly && rootdir != NULL) ! 108: goto failed; /* NOT IMPLEMENTED */ ! 109: if(BITFS(dev) && fp->U.N.S_flag) { ! 110: if(fsbiton(dev, fp)) ! 111: goto failed; ! 112: /* hack until pjw fixes chuck */ ! 113: } else if (BITFS(dev) && fp->s_isize + BITMAP*BITCELL < fp->s_fsize) ! 114: if(fsbiton(dev, fp)) ! 115: goto failed; ! 116: pi.i_dev = dev; ! 117: pi.i_fstyp = fstyp; ! 118: pi.i_un.i_bufp = bp; ! 119: if ((rip = iget(&pi, dev, ROOTINO)) == NULL) ! 120: goto failed; ! 121: if (rip->i_count == 1 && fsiread(&pi, rip) < 0) ! 122: goto failed; ! 123: if (rip->i_count != 1) { /* already mounted */ ! 124: iput(rip); ! 125: goto failed; ! 126: } ! 127: emp->m_mroot = rip; ! 128: ip->i_mroot = rip; ! 129: rip->i_mpoint = ip; ! 130: ip->i_count++; ! 131: sip->i_count++; ! 132: prele(rip); ! 133: if (rootdir == NULL) ! 134: clkinit(fp->s_time); ! 135: return; ! 136: failed: ! 137: bp->b_flags &= ~B_LOCKED; ! 138: emp->m_dev = NULL; ! 139: hopeless: ! 140: if (u.u_error == 0) ! 141: u.u_error = EBUSY; ! 142: } ! 143: ! 144: fsoff(mip, fstyp) ! 145: register struct inode *mip; ! 146: { ! 147: dev_t dev; ! 148: register struct mount *mp; ! 149: register struct inode *rip; ! 150: struct buf *bp; ! 151: struct filsys *fp; ! 152: ! 153: rip = mip->i_mroot; ! 154: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) ! 155: if (mp->m_mroot == rip) ! 156: break; ! 157: if (mp < fsmtab) ! 158: panic("umount mp"); ! 159: plock(rip); ! 160: xumount(rip); ! 161: update(); /* silly */ ! 162: if (rip->i_count > 1 || ifsbusy(rip)) { ! 163: u.u_error = EBUSY; ! 164: prele(rip); ! 165: return; ! 166: } ! 167: plock(mip); ! 168: mip->i_mroot = NULL; ! 169: iput(mip); ! 170: dev = rip->i_dev; ! 171: if ((bp = getblk(dev, SUPERB)) != rip->i_un.i_bufp) ! 172: panic("umount"); ! 173: iput(rip); ! 174: bp->b_flags &= ~(B_LOCKED|B_ASYNC); /* ~async needed? */ ! 175: if (bp->b_un.b_filsys->s_ronly) ! 176: brelse(bp); ! 177: else { ! 178: if (BITFS(dev)) { ! 179: fp = bp->b_un.b_filsys; ! 180: fp->s_valid = 1; ! 181: if(fp->U.N.S_flag) ! 182: fsbitoff(dev, fp, 1); ! 183: } ! 184: bwrite(bp); ! 185: } ! 186: mpurge(mp - fsmtab); ! 187: idec(mp->m_dev); ! 188: mp->m_dev = NULL; ! 189: } ! 190: ! 191: fsbiton(dev, fp) ! 192: dev_t dev; ! 193: register struct filsys *fp; ! 194: { ! 195: register int i, nf; ! 196: register struct buf **bpp; ! 197: register struct buf *bp; ! 198: ! 199: /* two chuck should do */ ! 200: fp->U.N.S_flag = 1; /* bit map not in superblock */ ! 201: nf = fp->U.N.S_bsize = BSIZE(dev) * NBBY; ! 202: if (fp->s_ronly) ! 203: return (0); ! 204: nf = (fp->s_fsize + nf - 1) / nf; ! 205: bpp = fp->U.N.S_blk; ! 206: for(i = 0; i < nf; i++) ! 207: bpp[i] = 0; ! 208: for(i = 0; i < nf; i++) { ! 209: bp = bread(dev, fp->s_fsize-nf+i); ! 210: if(u.u_error) { ! 211: brelse(bp); ! 212: goto failed; ! 213: } ! 214: bp->b_flags |= B_LOCKED; ! 215: brelse(bp); ! 216: bpp[i] = bp; ! 217: } ! 218: return(0); ! 219: failed: ! 220: fsbitoff(dev, fp, 0); ! 221: return(1); ! 222: } ! 223: ! 224: fsbitoff(dev, fp, wrtflg) ! 225: dev_t dev; ! 226: struct filsys *fp; ! 227: { ! 228: register struct buf **bpp; ! 229: register struct buf *bp; ! 230: register int i, nf; ! 231: ! 232: if (fp->s_ronly) ! 233: return; ! 234: nf = fp->U.N.S_bsize; ! 235: nf = (fp->s_fsize + nf-1)/nf; ! 236: bpp = fp->U.N.S_blk; ! 237: for(i = 0; i < nf; i++) ! 238: if(bpp[i]) { ! 239: if ((bp = getblk(dev, fp->s_fsize - nf + i)) != bpp[i]) ! 240: panic("fsbitoff"); ! 241: bp->b_flags &= ~B_LOCKED; ! 242: if(wrtflg) ! 243: bwrite(bp); ! 244: bpp[i] = 0; /* safety first */ ! 245: } ! 246: } ! 247: ! 248: /* ! 249: * fill in inode ip from the disk copy ! 250: * in filesystem fip ! 251: * ip is an inode fresh from iget ! 252: */ ! 253: fsiread(fip, ip) ! 254: register struct inode *fip, *ip; ! 255: { ! 256: register struct buf *bp; ! 257: daddr_t bno; ! 258: ! 259: if (ip->i_number <= 0) { ! 260: u.u_error = EINVAL; ! 261: iput(ip); ! 262: return (-1); ! 263: } ! 264: bno = itod(fip->i_dev, (ino_t)ip->i_number); ! 265: if (bno >= getfs(fip)->s_isize) { ! 266: u.u_error = EINVAL; ! 267: iput(ip); ! 268: return (-1); ! 269: } ! 270: bp = bread(fip->i_dev, bno); ! 271: if((bp->b_flags&B_ERROR) != 0) { ! 272: brelse(bp); ! 273: iput(ip); ! 274: return(-1); ! 275: } ! 276: iexpand(ip, bp->b_un.b_dino+itoo(fip->i_dev, (ino_t)ip->i_number)); ! 277: brelse(bp); ! 278: ip->i_un.i_bufp = fip->i_un.i_bufp; ! 279: ip->i_un.i_lastr = 0; ! 280: return (0); ! 281: } ! 282: ! 283: iexpand(ip, dp) ! 284: register struct inode *ip; ! 285: register struct dinode *dp; ! 286: { ! 287: register char *p1, *p2; ! 288: register int i; ! 289: ! 290: ip->i_mode = dp->di_mode; ! 291: ip->i_nlink = dp->di_nlink; ! 292: ip->i_uid = dp->di_uid; ! 293: ip->i_gid = dp->di_gid; ! 294: ip->i_size = dp->di_size; ! 295: p1 = (char *)ip->i_un.i_addr; ! 296: p2 = (char *)dp->di_addr; ! 297: for(i=0; i<NADDR; i++) { ! 298: *p1++ = *p2++; ! 299: *p1++ = *p2++; ! 300: *p1++ = *p2++; ! 301: *p1++ = 0; ! 302: } ! 303: } ! 304: ! 305: fsput(ip) ! 306: struct inode *ip; ! 307: { ! 308: if (ip->i_nlink == 0) { ! 309: fstrunc(ip); ! 310: ifree(ip); ! 311: ip->i_mode = 0; ! 312: ip->i_flag |= IUPD|ICHG; ! 313: } ! 314: if ((ip->i_flag&(IUPD|IACC|ICHG)) != 0) ! 315: fsiupdat(ip, &time, &time, 0); ! 316: } ! 317: ! 318: fsupdat(ip, ta, tm, waitfor) ! 319: register struct inode *ip; ! 320: time_t *ta, *tm; ! 321: { ! 322: fsiupdat(ip, ta, tm, waitfor); ! 323: if (ip->i_un.i_bufp->b_un.b_filsys->s_fmod) ! 324: fsfupdat(ip); ! 325: } ! 326: ! 327: /* ! 328: * update the inode on disk ! 329: * if the super-block is dirty, write it too ! 330: */ ! 331: ! 332: fsiupdat(ip, ta, tm, waitfor) ! 333: register struct inode *ip; ! 334: time_t *ta, *tm; ! 335: { ! 336: register struct buf *bp; ! 337: struct dinode *dp; ! 338: register char *p1, *p2; ! 339: register int i; ! 340: ! 341: if (ip->i_un.i_bufp->b_un.b_filsys->s_ronly) ! 342: return; ! 343: bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number)); ! 344: if (bp->b_flags & B_ERROR) { ! 345: brelse(bp); ! 346: return; ! 347: } ! 348: dp = bp->b_un.b_dino; ! 349: dp += itoo(ip->i_dev, ip->i_number); ! 350: dp->di_mode = ip->i_mode; ! 351: dp->di_nlink = ip->i_nlink; ! 352: dp->di_uid = ip->i_uid; ! 353: dp->di_gid = ip->i_gid; ! 354: dp->di_size = ip->i_size; ! 355: p1 = (char *)dp->di_addr; ! 356: p2 = (char *)ip->i_un.i_addr; ! 357: for(i=0; i<NADDR; i++) { ! 358: *p1++ = *p2++; ! 359: *p1++ = *p2++; ! 360: *p1++ = *p2++; ! 361: if(*p2++) ! 362: printf("ino %d dev #%x addr #%x\n", ip->i_number, ip->i_dev, ip->i_un.i_addr[i]); ! 363: } ! 364: if(ip->i_flag&IACC) ! 365: dp->di_atime = *ta; ! 366: if(ip->i_flag&IUPD) ! 367: dp->di_mtime = *tm; ! 368: if(ip->i_flag&ICHG) ! 369: dp->di_ctime = time; ! 370: ip->i_flag &= ~(IUPD|IACC|ICHG); ! 371: if (waitfor) ! 372: bwrite(bp); ! 373: else ! 374: bdwrite(bp); ! 375: } ! 376: ! 377: /* ! 378: * write the super-block ! 379: */ ! 380: ! 381: fsfupdat(ip) ! 382: struct inode *ip; ! 383: { ! 384: register struct filsys *fp; ! 385: struct buf *bp; ! 386: ! 387: fp = ip->i_un.i_bufp->b_un.b_filsys; ! 388: if (fp->s_fmod == 0 || fp->s_ilock || fp->s_flock || fp->s_ronly) ! 389: return; ! 390: bp = getblk(ip->i_dev, SUPERB); ! 391: if (bp->b_un.b_filsys != fp) ! 392: panic("fsfupdat"); ! 393: fp->s_fmod = 0; ! 394: fp->s_time = time; ! 395: bwrite(bp); ! 396: } ! 397: ! 398: fsstat(ip, ub) ! 399: register struct inode *ip; ! 400: struct stat *ub; ! 401: { ! 402: register struct dinode *dp; ! 403: register struct buf *bp; ! 404: struct stat ds; ! 405: ! 406: /* ! 407: * first copy from inode table ! 408: */ ! 409: ds.st_dev = ip->i_dev; ! 410: ds.st_ino = ip->i_number; ! 411: ds.st_mode = ip->i_mode; ! 412: ds.st_nlink = ip->i_nlink; ! 413: ds.st_uid = ip->i_uid; ! 414: ds.st_gid = ip->i_gid; ! 415: ds.st_rdev = (dev_t)ip->i_un.i_rdev; ! 416: ds.st_size = ip->i_size; ! 417: /* ! 418: * next the dates in the disk ! 419: */ ! 420: bp = bread(ip->i_dev, itod(ip->i_dev, ip->i_number)); ! 421: dp = bp->b_un.b_dino; ! 422: dp += itoo(ip->i_dev, ip->i_number); ! 423: ds.st_atime = dp->di_atime; ! 424: ds.st_mtime = dp->di_mtime; ! 425: ds.st_ctime = dp->di_ctime; ! 426: brelse(bp); ! 427: if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) ! 428: u.u_error = EFAULT; ! 429: } ! 430: ! 431: fstrunc(ip) ! 432: register struct inode *ip; ! 433: { ! 434: register i; ! 435: daddr_t bn; ! 436: struct inode itmp; ! 437: ! 438: i = ip->i_mode & IFMT; ! 439: if (i!=IFREG && i!=IFDIR && i!=IFLNK) ! 440: return; ! 441: /* ! 442: * Clean inode on disk before freeing blocks ! 443: * to insure no duplicates if system crashes. ! 444: */ ! 445: itmp = *ip; ! 446: itmp.i_size = 0; ! 447: for (i = 0; i < NADDR; i++) ! 448: itmp.i_un.i_addr[i] = 0; ! 449: itmp.i_flag |= ICHG|IUPD; ! 450: fsiupdat(&itmp, &time, &time, 1); ! 451: ip->i_flag &= ~(IUPD|IACC|ICHG); ! 452: ! 453: /* ! 454: * Now return blocks to free list... if machine ! 455: * crashes, they will be harmless MISSING blocks. ! 456: */ ! 457: for(i=NADDR-1; i>=0; i--) { ! 458: bn = ip->i_un.i_addr[i]; ! 459: if(bn == (daddr_t)0) ! 460: continue; ! 461: ip->i_un.i_addr[i] = (daddr_t)0; ! 462: switch(i) { ! 463: ! 464: default: ! 465: free(ip, bn); ! 466: break; ! 467: ! 468: case NADDR-3: ! 469: tloop(ip, bn, 0, 0); ! 470: break; ! 471: ! 472: case NADDR-2: ! 473: tloop(ip, bn, 1, 0); ! 474: break; ! 475: ! 476: case NADDR-1: ! 477: tloop(ip, bn, 1, 1); ! 478: } ! 479: } ! 480: ip->i_size = 0; ! 481: /* ! 482: * Inode was written and flags updated above. ! 483: * No need to modify flags here. ! 484: */ ! 485: } ! 486: ! 487: tloop(fip, bn, f1, f2) ! 488: register struct inode *fip; ! 489: daddr_t bn; ! 490: { ! 491: register i; ! 492: register struct buf *bp; ! 493: register daddr_t *bap; ! 494: daddr_t nb; ! 495: ! 496: bp = NULL; ! 497: for(i=NINDIR(fip->i_dev)-1; i>=0; i--) { ! 498: if(bp == NULL) { ! 499: bp = bread(fip->i_dev, bn); ! 500: if (bp->b_flags & B_ERROR) { ! 501: brelse(bp); ! 502: return; ! 503: } ! 504: bap = bp->b_un.b_daddr; ! 505: } ! 506: nb = bap[i]; ! 507: if(nb == (daddr_t)0) ! 508: continue; ! 509: if(f1) { ! 510: brelse(bp); ! 511: bp = NULL; ! 512: tloop(fip, nb, f2, 0); ! 513: } else ! 514: free(fip, nb); ! 515: } ! 516: if(bp != NULL) ! 517: brelse(bp); ! 518: free(fip, bn); ! 519: } ! 520: ! 521: fsioctl(ip, cmd, cmarg, flag) ! 522: register struct inode *ip; ! 523: caddr_t cmarg; ! 524: { ! 525: int fmt; ! 526: register dev_t dev; ! 527: ! 528: fmt = ip->i_mode & IFMT; ! 529: if (fmt != IFCHR) { ! 530: if (cmd==FIONREAD && (fmt == IFREG || fmt == IFDIR)) { ! 531: off_t nread = ip->i_size; /* - fp->f_offset */ ! 532: if (copyout((caddr_t)&nread, cmarg, sizeof(off_t))) ! 533: u.u_error = EFAULT; ! 534: } else ! 535: u.u_error = ENOTTY; ! 536: return; ! 537: } ! 538: dev = ip->i_un.i_rdev; ! 539: u.u_r.r_val1 = 0; ! 540: (*cdevsw[major(dev)]->d_ioctl)(dev, cmd, cmarg, flag); ! 541: } ! 542: ! 543: struct inode * ! 544: fsopen(ip, rw) ! 545: register struct inode *ip; ! 546: { ! 547: dev_t dev; ! 548: register unsigned int maj; ! 549: ! 550: dev = (dev_t)ip->i_un.i_rdev; ! 551: maj = major(dev); ! 552: ! 553: switch(ip->i_mode&IFMT) { ! 554: case IFCHR: ! 555: if(maj >= nchrdev || cdevsw[maj] == NULL) ! 556: goto bad; ! 557: if (cdevsw[maj]->qinfo) /* stream device */ ! 558: return(stopen(cdevsw[major(dev)]->qinfo, dev, rw, ip)); ! 559: (*cdevsw[maj]->d_open)(dev, rw); ! 560: break; ! 561: ! 562: case IFBLK: ! 563: if(maj >= nblkdev || bdevsw[maj] == NULL) ! 564: goto bad; ! 565: (*bdevsw[maj]->d_open)(dev, rw); ! 566: } ! 567: if (u.u_error) { ! 568: iput(ip); ! 569: return (NULL); ! 570: } ! 571: return (ip); ! 572: ! 573: bad: ! 574: u.u_error = ENXIO; ! 575: iput(ip); ! 576: return(NULL); ! 577: } ! 578: ! 579: fsread(ip) ! 580: register struct inode *ip; ! 581: { ! 582: struct buf *bp; ! 583: dev_t dev; ! 584: daddr_t lbn, bn; ! 585: off_t diff; ! 586: register int on, type; ! 587: register unsigned n; ! 588: ! 589: dev = (dev_t)ip->i_un.i_rdev; ! 590: type = ip->i_mode&IFMT; ! 591: if (type==IFCHR) { ! 592: (*cdevsw[major(dev)]->d_read)(dev); ! 593: return; ! 594: } ! 595: if (Lsign(u.u_offset) < 0) { /* and not IFCHR */ ! 596: u.u_error = EINVAL; ! 597: return; ! 598: } ! 599: if (type != IFBLK) { /* if offset >= size, avoid overflow */ ! 600: if (Lsign(Lladd(u.u_offset, -ip->i_size))>=0) ! 601: return; ! 602: dev = ip->i_dev; ! 603: } ! 604: do { ! 605: lbn = bn = Lshift(u.u_offset, BSHIFT(dev)); ! 606: on = Ltol(u.u_offset) & BMASK(dev); ! 607: n = MIN((unsigned)(BSIZE(dev)-on), u.u_count); ! 608: if (type!=IFBLK) { ! 609: diff = ip->i_size - Ltol(u.u_offset); ! 610: if (diff <= 0) ! 611: return; ! 612: if (diff < n) ! 613: n = diff; ! 614: bn = bmap(ip, bn, B_READ); ! 615: if (u.u_error) ! 616: return; ! 617: } else ! 618: rablock = bn+1; ! 619: if ((long)bn<0) { ! 620: bp = geteblk(); ! 621: clrbuf(bp); ! 622: } else if (ip->i_un.i_lastr+1==lbn) ! 623: bp = breada(dev, bn, rablock); ! 624: else ! 625: bp = bread(dev, bn); ! 626: ip->i_un.i_lastr = lbn; ! 627: n = MIN(n, BSIZE(dev)-bp->b_resid); ! 628: if (n!=0) ! 629: iomove(bp->b_un.b_addr+on, n, B_READ); ! 630: brelse(bp); ! 631: } while(u.u_error==0 && u.u_count!=0 && n!=0); ! 632: } ! 633: ! 634: fsdirread(ip, len) ! 635: struct inode *ip; ! 636: { struct buf *bp = 0, *outb; ! 637: dev_t dev; ! 638: daddr_t bn, lbn; ! 639: int on, type, j, m, new = 0; ! 640: char *p, *lp, *lastp; ! 641: struct direct *dp; ! 642: char ncvt[24]; ! 643: ! 644: if(Lsign(u.u_offset) < 0) { ! 645: u.u_error = EINVAL; ! 646: return; ! 647: } ! 648: type = ip->i_mode & IFMT; ! 649: if(type != IFDIR) { ! 650: u.u_error = ENOTDIR; ! 651: return; ! 652: } ! 653: dev = ip->i_dev; ! 654: outb = geteblk(); /* to hold the stuff for the user */ ! 655: if(len > BSIZE(dev)) ! 656: len = BSIZE(dev); ! 657: p = lp = outb->b_un.b_addr; ! 658: lastp = p + len; ! 659: loop: ! 660: if(new <= 0) { /* get some goo */ ! 661: lbn = bn = Lshift(u.u_offset, BSHIFT(dev)); ! 662: on = Ltol(u.u_offset) & BMASK(dev); ! 663: if(ip->i_size <= Ltol(u.u_offset)) ! 664: goto done; ! 665: bn = bmap(ip, bn, B_READ); ! 666: if(u.u_error) ! 667: return; ! 668: if((long)bn < 0) { /* holes in dirs? */ ! 669: u.u_offset = Lladd(u.u_offset, BSIZE(dev)-on); ! 670: goto loop; /* try the next block */ ! 671: } ! 672: if(bp) ! 673: brelse(bp); ! 674: if(ip->i_un.i_lastr + 1 == lbn) ! 675: bp = breada(dev, bn, rablock); ! 676: else ! 677: bp = bread(dev, bn); ! 678: ip->i_un.i_lastr = lbn; ! 679: new = BSIZE(dev) - on; ! 680: if(new > BSIZE(dev) - bp->b_resid) /* io error? */ ! 681: new = BSIZE(dev) - bp->b_resid; /* or paranoia */ ! 682: if(new > ip->i_size - Ltol(u.u_offset)) ! 683: new = ip->i_size - Ltol(u.u_offset); ! 684: dp = (struct direct *) (bp->b_un.b_addr + on); ! 685: } ! 686: if(dp->d_ino == 0) ! 687: goto incr; ! 688: for(m = dp->d_ino, j = sizeof(ncvt)-1; m; j--) { ! 689: ncvt[j] = m%10 + '0'; ! 690: m /= 10; ! 691: } ! 692: for(++j; j < sizeof(ncvt) && p < lastp; ) ! 693: *p++ = ncvt[j++]; ! 694: if(j != sizeof(ncvt) || p >= lastp) ! 695: goto early; ! 696: *p++ = '\t'; ! 697: for(j = 0; j < DIRSIZ && dp->d_name[j] && p < lastp; j++) ! 698: *p++ = dp->d_name[j]; ! 699: if(p >= lastp) ! 700: goto early; ! 701: *p++ = 0; ! 702: incr: ! 703: lp = p; ! 704: new -= sizeof(*dp); ! 705: u.u_offset = Lladd(u.u_offset, sizeof(*dp)); ! 706: dp++; ! 707: if(p < lastp) ! 708: goto loop; ! 709: done: ! 710: j = lp - outb->b_un.b_addr; ! 711: if(j > 0) ! 712: if(copyout((caddr_t)outb->b_un.b_addr, u.u_base, j)) ! 713: u.u_error = EFAULT; ! 714: if(bp) ! 715: brelse(bp); ! 716: brelse(outb); ! 717: u.u_r.r_val1 = j; ! 718: return; ! 719: early: ! 720: *lp = 0; ! 721: if(lp > outb->b_un.b_addr) ! 722: goto done; ! 723: u.u_error = ENOSPC; ! 724: if(bp) ! 725: brelse(bp); ! 726: brelse(outb); ! 727: } ! 728: ! 729: fswrite(ip) ! 730: register struct inode *ip; ! 731: { ! 732: struct buf *bp; ! 733: dev_t dev; ! 734: daddr_t bn; ! 735: register int on, type; ! 736: register unsigned n; ! 737: register int i; ! 738: ! 739: dev = (dev_t)ip->i_un.i_rdev; ! 740: type = ip->i_mode&IFMT; ! 741: if (type==IFCHR) { ! 742: ip->i_flag |= IUPD|ICHG; ! 743: (*cdevsw[major(dev)]->d_write)(dev); ! 744: return; ! 745: } ! 746: if (Lsign(u.u_offset) < 0) { /* and not IFCHR */ ! 747: u.u_error = EINVAL; ! 748: return; ! 749: } ! 750: if (u.u_count == 0) ! 751: return; ! 752: if ((ip->i_mode&IFMT)==IFREG && ! 753: (Lsign(Luadd(u.u_offset, u.u_count))!=0 || ! 754: Ltol(u.u_offset) + u.u_count > u.u_limit[LIM_FSIZE])) { ! 755: u.u_error = EMFILE; ! 756: return; ! 757: } ! 758: if (type != IFBLK) ! 759: dev = ip->i_dev; ! 760: do { ! 761: bn = Lshift(u.u_offset, BSHIFT(dev)); ! 762: on = Ltol(u.u_offset) & BMASK(dev); ! 763: n = MIN((unsigned)(BSIZE(dev)-on), u.u_count); ! 764: if (type!=IFBLK) { ! 765: bn = bmap(ip, bn, B_WRITE); ! 766: if((long)bn<0) ! 767: return; ! 768: } ! 769: i = getfsx(dev); ! 770: if (bn && mfind(i, bn)) ! 771: munhash(i, bn); ! 772: if(n == BSIZE(dev)) ! 773: bp = getblk(dev, bn); ! 774: else ! 775: bp = bread(dev, bn); ! 776: iomove(bp->b_un.b_addr+on, n, B_WRITE); ! 777: if(u.u_error != 0) ! 778: brelse(bp); ! 779: else { ! 780: if ((ip->i_mode&IFMT) == IFDIR && ! 781: ((struct direct *)(bp->b_un.b_addr+on))->d_ino == 0) ! 782: bwrite(bp); /* consistency */ ! 783: else if ((n+on) == BSIZE(dev)) ! 784: bawrite(bp); ! 785: else ! 786: bdwrite(bp); ! 787: } ! 788: if(Ltol(u.u_offset) > ip->i_size && ! 789: (type==IFDIR || type==IFREG || type==IFLNK)) ! 790: ip->i_size = Ltol(u.u_offset); ! 791: ip->i_flag |= IUPD|ICHG; ! 792: } while(u.u_error==0 && u.u_count!=0); ! 793: } ! 794: ! 795: /* ! 796: * Getfsx returns the index in the file system ! 797: * table of the specified device. The swap device ! 798: * is also assigned a pseudo-index. The index may ! 799: * be used as a compressed indication of the location ! 800: * of a block, recording ! 801: * <getfsx(dev),blkno> ! 802: * rather than ! 803: * <dev, blkno> ! 804: * provided the information need remain valid only ! 805: * as long as the file system is mounted. ! 806: * ! 807: * only the vm code calls this. ! 808: */ ! 809: getfsx(dev) ! 810: dev_t dev; ! 811: { ! 812: register struct mount *mp; ! 813: ! 814: if (dev == swapdev) ! 815: return (MSWAPX); ! 816: for (mp = &fsmtab[fscnt-1]; mp >= fsmtab; mp--) { ! 817: if (mp->m_dev == NULL) ! 818: continue; ! 819: if (mp->m_dev->i_un.i_rdev == dev) ! 820: return (mp - fsmtab); ! 821: } ! 822: return (-1); ! 823: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.