1*7722Swnj /* sys_generic.c 5.8 82/08/13 */ 27423Sroot 37423Sroot #include "../h/param.h" 47423Sroot #include "../h/systm.h" 57423Sroot #include "../h/dir.h" 67423Sroot #include "../h/user.h" 77423Sroot #include "../h/tty.h" 87423Sroot #include "../h/file.h" 97423Sroot #include "../h/inode.h" 107423Sroot #include "../h/buf.h" 117423Sroot #include "../h/proc.h" 127423Sroot #include "../h/inline.h" 137423Sroot #include "../h/conf.h" 147423Sroot #include "../h/socket.h" 157423Sroot #include "../h/socketvar.h" 167423Sroot #include "../h/cmap.h" 177423Sroot #include "../h/vlimit.h" 187423Sroot #include "../h/fs.h" 197487Skre #ifdef MUSH 207487Skre #include "../h/quota.h" 217487Skre #include "../h/share.h" 227487Skre #else 237487Skre #define CHARGE(nothing) 247487Skre #endif 257500Sroot #include "../h/descrip.h" 267714Sroot #include "../h/uio.h" 277423Sroot 287423Sroot /* 297423Sroot * Read system call. 307423Sroot */ 317423Sroot read() 327423Sroot { 337423Sroot register struct file *fp; 347423Sroot register struct inode *ip; 357423Sroot register struct a { 367423Sroot int fdes; 377423Sroot char *cbuf; 387423Sroot unsigned count; 397423Sroot } *uap; 407423Sroot 417423Sroot uap = (struct a *)u.u_ap; 427423Sroot if ((int)uap->count < 0) { 437423Sroot u.u_error = EINVAL; 447423Sroot return; 457423Sroot } 467423Sroot GETF(fp, uap->fdes); 477423Sroot if ((fp->f_flag&FREAD) == 0) { 487423Sroot u.u_error = EBADF; 497423Sroot return; 507423Sroot } 517423Sroot u.u_base = (caddr_t)uap->cbuf; 527423Sroot u.u_count = uap->count; 537423Sroot u.u_segflg = 0; 547423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 557423Sroot if (u.u_count == uap->count) 567423Sroot u.u_eosys = RESTARTSYS; 577500Sroot } else if (fp->f_type == DTYPE_SOCKET) 587423Sroot u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0); 597423Sroot else { 607423Sroot ip = fp->f_inode; 617423Sroot u.u_offset = fp->f_offset; 627423Sroot if ((ip->i_mode&IFMT) == IFREG) { 637423Sroot ilock(ip); 647423Sroot readi(ip); 657423Sroot iunlock(ip); 667423Sroot } else 677423Sroot readi(ip); 687423Sroot fp->f_offset += uap->count - u.u_count; 697423Sroot } 707423Sroot u.u_r.r_val1 = uap->count - u.u_count; 717423Sroot } 727423Sroot 737423Sroot /* 747423Sroot * Write system call 757423Sroot */ 767423Sroot write() 777423Sroot { 787423Sroot register struct file *fp; 797423Sroot register struct inode *ip; 807423Sroot register struct a { 817423Sroot int fdes; 827423Sroot char *cbuf; 837423Sroot unsigned count; 847423Sroot } *uap; 857423Sroot 867423Sroot uap = (struct a *)u.u_ap; 877423Sroot if ((int)uap->count < 0) { 887423Sroot u.u_error = EINVAL; 897423Sroot return; 907423Sroot } 917423Sroot GETF(fp, uap->fdes); 927423Sroot if ((fp->f_flag&FWRITE) == 0) { 937423Sroot u.u_error = EBADF; 947423Sroot return; 957423Sroot } 967423Sroot u.u_base = (caddr_t)uap->cbuf; 977423Sroot u.u_count = uap->count; 987423Sroot u.u_segflg = 0; 997423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 1007423Sroot if (u.u_count == uap->count) 1017423Sroot u.u_eosys = RESTARTSYS; 1027500Sroot } else if (fp->f_type == DTYPE_SOCKET) 1037423Sroot u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); 1047423Sroot else { 1057423Sroot ip = fp->f_inode; 1067699Ssam if (fp->f_flag&FAPPEND) 1077500Sroot fp->f_offset = ip->i_size; 1087423Sroot u.u_offset = fp->f_offset; 1097423Sroot if ((ip->i_mode&IFMT) == IFREG) { 1107423Sroot ilock(ip); 1117423Sroot writei(ip); 1127423Sroot iunlock(ip); 1137423Sroot } else 1147423Sroot writei(ip); 1157423Sroot fp->f_offset += uap->count - u.u_count; 1167423Sroot } 1177423Sroot u.u_r.r_val1 = uap->count - u.u_count; 1187423Sroot } 1197423Sroot 1207500Sroot readv() 1217500Sroot { 1227423Sroot 1237500Sroot } 1247500Sroot 1257500Sroot writev() 1267500Sroot { 1277500Sroot 1287500Sroot } 1297500Sroot 1307423Sroot /* 1317423Sroot * Ioctl system call 1327624Ssam * Check legality, execute common code, 1337624Ssam * and switch out to individual device routine. 1347423Sroot */ 1357423Sroot ioctl() 1367423Sroot { 1377423Sroot register struct file *fp; 1387624Ssam struct a { 1397423Sroot int fdes; 1407423Sroot int cmd; 1417423Sroot caddr_t cmarg; 1427423Sroot } *uap; 1437624Ssam register int com, size; 1447624Ssam char data[IOCPARM_MASK+1]; 1457423Sroot 1467423Sroot uap = (struct a *)u.u_ap; 1477423Sroot if ((fp = getf(uap->fdes)) == NULL) 1487423Sroot return; 1497423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1507423Sroot u.u_error = EBADF; 1517423Sroot return; 1527423Sroot } 1537624Ssam com = uap->cmd; 1547624Ssam 1557699Ssam #ifndef NOCOMPAT 1567624Ssam /* 1577624Ssam * Map old style ioctl's into new for the 1587624Ssam * sake of backwards compatibility (sigh). 1597624Ssam */ 1607624Ssam if ((com&~0xffff) == 0) { 1617624Ssam com = mapioctl(com); 1627624Ssam if (com == 0) { 1637624Ssam u.u_error = EINVAL; 1647624Ssam return; 1657624Ssam } 1667624Ssam } 1677624Ssam #endif 1687624Ssam if (com == FIOCLEX) { 1697423Sroot u.u_pofile[uap->fdes] |= EXCLOSE; 1707423Sroot return; 1717423Sroot } 1727624Ssam if (com == FIONCLEX) { 1737423Sroot u.u_pofile[uap->fdes] &= ~EXCLOSE; 1747423Sroot return; 1757423Sroot } 1767624Ssam 1777624Ssam /* 1787624Ssam * Interpret high order word to find 1797624Ssam * amount of data to be copied to/from the 1807624Ssam * user's address space. 1817624Ssam * (this'll have to change if we have in+out ioctls) 1827624Ssam */ 1837624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 1847624Ssam if (size > sizeof (data)) { 1857624Ssam u.u_error = EFAULT; 1867423Sroot return; 1877423Sroot } 1887699Ssam if (com&IOC_IN && size) { 1897624Ssam if (copyin(uap->cmarg, (caddr_t)data, size)) { 1907624Ssam u.u_error = EFAULT; 1917624Ssam return; 1927624Ssam } 1937624Ssam } else 1947624Ssam *(caddr_t *)data = uap->cmarg; 1957624Ssam /* 1967624Ssam * Zero the buffer on the stack so the user 1977624Ssam * always gets back something deterministic. 1987624Ssam */ 1997624Ssam if ((com&IOC_OUT) && size) 2007624Ssam bzero((caddr_t)data, size); 2017423Sroot 2027624Ssam if (fp->f_type == DTYPE_SOCKET) 2037624Ssam soioctl(fp->f_socket, com, data); 2047624Ssam else { 2057624Ssam register struct inode *ip = fp->f_inode; 2067624Ssam int fmt = ip->i_mode & IFMT; 2077624Ssam dev_t dev; 2087624Ssam 2097624Ssam if (fmt != IFCHR) { 2107624Ssam if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 2117624Ssam *(off_t *)data = ip->i_size - fp->f_offset; 2127624Ssam goto returndata; 2137624Ssam } 2147624Ssam if (com != FIONBIO && com != FIOASYNC) 2157624Ssam u.u_error = ENOTTY; 2167423Sroot return; 2177624Ssam } 2187624Ssam dev = ip->i_rdev; 2197624Ssam u.u_r.r_val1 = 0; 2207624Ssam if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 2217624Ssam u.u_eosys = RESTARTSYS; 2227624Ssam return; 2237624Ssam } 2247624Ssam (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0); 2257423Sroot } 2267624Ssam 2277624Ssam returndata: 2287624Ssam /* 2297624Ssam * Copy any data to user, size was 2307624Ssam * already set and checked above. 2317624Ssam */ 2327699Ssam if (u.u_error == 0 && com&IOC_OUT) 2337699Ssam if (size && copyout(data, uap->cmarg, size)) 2347699Ssam u.u_error = EFAULT; 2357423Sroot } 2367423Sroot 2377423Sroot /* 2387423Sroot * Do nothing specific version of line 2397423Sroot * discipline specific ioctl command. 2407423Sroot */ 2417423Sroot /*ARGSUSED*/ 2427624Ssam nullioctl(tp, cmd, data, flags) 2437423Sroot struct tty *tp; 2447624Ssam char *data; 2457624Ssam int flags; 2467423Sroot { 2477423Sroot 2487624Ssam #ifdef lint 2497624Ssam tp = tp; data = data; flags = flags; 2507624Ssam #endif 2517423Sroot return (cmd); 2527423Sroot } 2537423Sroot 2547423Sroot /* 2557423Sroot * Read the file corresponding to 2567423Sroot * the inode pointed at by the argument. 2577423Sroot * The actual read arguments are found 2587423Sroot * in the variables: 2597423Sroot * u_base core address for destination 2607423Sroot * u_offset byte offset in file 2617423Sroot * u_count number of bytes to read 2627423Sroot * u_segflg read to kernel/user/user I 2637423Sroot */ 2647423Sroot readi(ip) 2657423Sroot register struct inode *ip; 2667423Sroot { 2677423Sroot struct buf *bp; 2687423Sroot struct fs *fs; 2697423Sroot dev_t dev; 2707423Sroot daddr_t lbn, bn; 2717423Sroot off_t diff; 2727423Sroot register int on, type; 2737423Sroot register unsigned n; 2747423Sroot int size; 2757423Sroot long bsize; 2767423Sroot extern int mem_no; 2777423Sroot 2787423Sroot if (u.u_count == 0) 2797423Sroot return; 2807423Sroot dev = (dev_t)ip->i_rdev; 2817423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 2827423Sroot mem_no != major(dev))) { 2837423Sroot u.u_error = EINVAL; 2847423Sroot return; 2857423Sroot } 2867423Sroot ip->i_flag |= IACC; 2877423Sroot type = ip->i_mode&IFMT; 2887423Sroot if (type == IFCHR) { 2897487Skre register c = u.u_count; 290*7722Swnj struct uio auio; 291*7722Swnj struct iovec aiov; 292*7722Swnj auio.uio_iov = &aiov; 293*7722Swnj auio.uio_iovcnt = 1; 294*7722Swnj aiov.iov_base = u.u_base; 295*7722Swnj aiov.iov_len = u.u_count; 296*7722Swnj auio.uio_offset = u.u_offset; 297*7722Swnj auio.uio_segflg = u.u_segflg; 298*7722Swnj auio.uio_resid = u.u_count; 299*7722Swnj (*cdevsw[major(dev)].d_read)(dev, &auio); 300*7722Swnj CHARGE(sc_tio * (c - auio.uio_resid)); 301*7722Swnj u.u_count = auio.uio_resid; 3027423Sroot return; 3037423Sroot } 3047423Sroot if (type != IFBLK) { 3057423Sroot dev = ip->i_dev; 3067423Sroot fs = ip->i_fs; 3077423Sroot bsize = fs->fs_bsize; 3087423Sroot } else 3097423Sroot bsize = BLKDEV_IOSIZE; 3107423Sroot do { 3117423Sroot lbn = u.u_offset / bsize; 3127423Sroot on = u.u_offset % bsize; 3137423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 3147423Sroot if (type != IFBLK) { 3157423Sroot diff = ip->i_size - u.u_offset; 3167423Sroot if (diff <= 0) 3177423Sroot return; 3187423Sroot if (diff < n) 3197423Sroot n = diff; 3207423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 3217423Sroot if (u.u_error) 3227423Sroot return; 3237423Sroot size = blksize(fs, ip, lbn); 3247423Sroot } else { 3257423Sroot size = bsize; 3267423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 3277423Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 3287423Sroot rasize = bsize; 3297423Sroot } 3307423Sroot if ((long)bn<0) { 3317423Sroot bp = geteblk(size); 3327423Sroot clrbuf(bp); 3337423Sroot } else if (ip->i_lastr + 1 == lbn) 3347423Sroot bp = breada(dev, bn, size, rablock, rasize); 3357423Sroot else 3367423Sroot bp = bread(dev, bn, size); 3377423Sroot ip->i_lastr = lbn; 3387423Sroot n = MIN(n, size - bp->b_resid); 3397423Sroot if (n != 0) { 3407423Sroot if (u.u_segflg != 1) { 3417423Sroot if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { 3427423Sroot u.u_error = EFAULT; 3437423Sroot goto bad; 3447423Sroot } 3457423Sroot } else 3467423Sroot bcopy(bp->b_un.b_addr + on, u.u_base, n); 3477423Sroot u.u_base += n; 3487423Sroot u.u_offset += n; 3497423Sroot u.u_count -= n; 3507423Sroot bad: 3517423Sroot ; 3527423Sroot } 3537423Sroot if (n + on == bsize || u.u_offset == ip->i_size) 3547423Sroot bp->b_flags |= B_AGE; 3557423Sroot brelse(bp); 3567423Sroot } while (u.u_error == 0 && u.u_count != 0 && n != 0); 3577423Sroot } 3587423Sroot 3597423Sroot /* 3607423Sroot * Write the file corresponding to 3617423Sroot * the inode pointed at by the argument. 3627423Sroot * The actual write arguments are found 3637423Sroot * in the variables: 3647423Sroot * u_base core address for source 3657423Sroot * u_offset byte offset in file 3667423Sroot * u_count number of bytes to write 3677423Sroot * u_segflg write to kernel/user/user I 3687423Sroot */ 3697423Sroot writei(ip) 3707423Sroot register struct inode *ip; 3717423Sroot { 3727423Sroot struct buf *bp; 3737423Sroot register struct fs *fs; 3747423Sroot dev_t dev; 3757423Sroot daddr_t lbn, bn; 3767423Sroot register int on, type; 3777423Sroot register unsigned n; 3787423Sroot long bsize; 3797423Sroot int size, i, count; 3807423Sroot extern int mem_no; 3817423Sroot 3827423Sroot dev = (dev_t)ip->i_rdev; 3837423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 3847423Sroot mem_no != major(dev)) ) { 3857423Sroot u.u_error = EINVAL; 3867423Sroot return; 3877423Sroot } 3887423Sroot type = ip->i_mode & IFMT; 3897423Sroot if (type == IFCHR) { 3907423Sroot ip->i_flag |= IUPD|ICHG; 3917487Skre CHARGE(sc_tio * u.u_count); 3927423Sroot (*cdevsw[major(dev)].d_write)(dev); 3937423Sroot return; 3947423Sroot } 3957423Sroot if (u.u_count == 0) 3967423Sroot return; 3977423Sroot if ((ip->i_mode & IFMT) == IFREG && 3987423Sroot u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { 3997423Sroot psignal(u.u_procp, SIGXFSZ); 4007423Sroot u.u_error = EMFILE; 4017423Sroot return; 4027423Sroot } 4037423Sroot if (type!=IFBLK) { 4047423Sroot dev = ip->i_dev; 4057423Sroot fs = ip->i_fs; 4067423Sroot bsize = fs->fs_bsize; 4077532Sroot } else 4087423Sroot bsize = BLKDEV_IOSIZE; 4097423Sroot do { 4107423Sroot lbn = u.u_offset / bsize; 4117423Sroot on = u.u_offset % bsize; 4127423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 4137423Sroot if (type != IFBLK) { 4147423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); 4157532Sroot if (u.u_error || (long)bn<0) 4167423Sroot return; 4177423Sroot if(u.u_offset + n > ip->i_size && 4187423Sroot (type == IFDIR || type == IFREG || type == IFLNK)) 4197423Sroot ip->i_size = u.u_offset + n; 4207423Sroot size = blksize(fs, ip, lbn); 4217423Sroot } else { 4227423Sroot size = bsize; 4237423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 4247423Sroot } 4257532Sroot count = howmany(size, DEV_BSIZE); 4267532Sroot for (i = 0; i < count; i += CLSIZE) 4277532Sroot if (mfind(dev, bn + i)) 4287532Sroot munhash(dev, bn + i); 4297532Sroot if (n == bsize) 4307423Sroot bp = getblk(dev, bn, size); 4317423Sroot else 4327423Sroot bp = bread(dev, bn, size); 4337423Sroot if (u.u_segflg != 1) { 4347423Sroot if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { 4357423Sroot u.u_error = EFAULT; 4367423Sroot goto bad; 4377423Sroot } 4387423Sroot } else 4397423Sroot bcopy(u.u_base, bp->b_un.b_addr + on, n); 4407423Sroot u.u_base += n; 4417423Sroot u.u_offset += n; 4427423Sroot u.u_count -= n; 4437423Sroot bad: 4447423Sroot ; 4457423Sroot if (u.u_error != 0) 4467423Sroot brelse(bp); 4477423Sroot else { 4487423Sroot if ((ip->i_mode&IFMT) == IFDIR) 4497423Sroot /* 4507423Sroot * Writing to clear a directory entry. 4517423Sroot * Must insure the write occurs before 4527423Sroot * the inode is freed, or may end up 4537423Sroot * pointing at a new (different) file 4547423Sroot * if inode is quickly allocated again 4557423Sroot * and system crashes. 4567423Sroot */ 4577423Sroot bwrite(bp); 4587423Sroot else if (n + on == bsize) { 4597423Sroot bp->b_flags |= B_AGE; 4607423Sroot bawrite(bp); 4617423Sroot } else 4627423Sroot bdwrite(bp); 4637423Sroot } 4647423Sroot ip->i_flag |= IUPD|ICHG; 4657423Sroot if (u.u_ruid != 0) 4667423Sroot ip->i_mode &= ~(ISUID|ISGID); 4677423Sroot } while (u.u_error == 0 && u.u_count != 0); 4687423Sroot } 4697423Sroot 4707423Sroot /* 4717423Sroot * Move n bytes at byte location 4727423Sroot * &bp->b_un.b_addr[o] to/from (flag) the 4737423Sroot * user/kernel (u.segflg) area starting at u.base. 4747423Sroot * Update all the arguments by the number 4757423Sroot * of bytes moved. 4767423Sroot */ 4777423Sroot iomove(cp, n, flag) 4787423Sroot register caddr_t cp; 4797423Sroot register unsigned n; 4807423Sroot { 4817423Sroot register int t; 4827423Sroot 4837423Sroot if (n==0) 4847423Sroot return; 4857423Sroot if (u.u_segflg != 1) { 4867423Sroot if (flag==B_WRITE) 4877423Sroot t = copyin(u.u_base, (caddr_t)cp, n); 4887423Sroot else 4897423Sroot t = copyout((caddr_t)cp, u.u_base, n); 4907423Sroot if (t) { 4917423Sroot u.u_error = EFAULT; 4927423Sroot return; 4937423Sroot } 4947423Sroot } else 4957423Sroot if (flag == B_WRITE) 4967423Sroot bcopy(u.u_base, (caddr_t)cp, n); 4977423Sroot else 4987423Sroot bcopy((caddr_t)cp, u.u_base, n); 4997423Sroot u.u_base += n; 5007423Sroot u.u_offset += n; 5017423Sroot u.u_count -= n; 5027423Sroot } 5037714Sroot 5047714Sroot readip(ip, uio) 5057714Sroot register struct inode *ip; 5067714Sroot register struct uio *uio; 5077714Sroot { 5087714Sroot register struct iovec *iov = uio->uio_iov; 5097714Sroot struct buf *bp; 5107714Sroot struct fs *fs; 5117714Sroot dev_t dev; 5127714Sroot daddr_t lbn, bn; 5137714Sroot off_t diff; 5147714Sroot register int on, type; 5157714Sroot register unsigned n; 5167714Sroot int size; 5177714Sroot long bsize; 5187714Sroot extern int mem_no; 5197714Sroot int error = 0; 5207714Sroot 5217714Sroot uio->uio_resid = 0; 5227714Sroot if (uio->uio_iovcnt == 0) 5237714Sroot return (0); 5247714Sroot dev = (dev_t)ip->i_rdev; 5257714Sroot if (uio->uio_offset < 0 && 5267714Sroot ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) { 5277714Sroot error = EINVAL; 5287714Sroot goto bad; 5297714Sroot } 5307714Sroot ip->i_flag |= IACC; 5317714Sroot type = ip->i_mode&IFMT; 5327714Sroot if (type == IFCHR) { 5337714Sroot register c = u.u_count; 5347714Sroot error = (*cdevsw[major(dev)].d_read)(dev, uio); 5357714Sroot CHARGE(sc_tio * (c - u.u_count)); 5367714Sroot return (error); 5377714Sroot } 5387714Sroot if (type != IFBLK) { 5397714Sroot dev = ip->i_dev; 5407714Sroot fs = ip->i_fs; 5417714Sroot bsize = fs->fs_bsize; 5427714Sroot } else 5437714Sroot bsize = BLKDEV_IOSIZE; 5447714Sroot nextiov: 5457714Sroot if (uio->uio_iovcnt == 0) 5467714Sroot goto getresid; 5477714Sroot if (iov->iov_len > 0) 5487714Sroot do { 5497714Sroot lbn = uio->uio_offset / bsize; 5507714Sroot on = uio->uio_offset % bsize; 5517714Sroot n = MIN((unsigned)(bsize - on), iov->iov_len); 5527714Sroot if (type != IFBLK) { 5537714Sroot diff = ip->i_size - uio->uio_offset; 5547714Sroot if (diff <= 0) 5557714Sroot return; 5567714Sroot if (diff < n) 5577714Sroot n = diff; 5587714Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 5597714Sroot if (u.u_error) 5607714Sroot goto getresid; 5617714Sroot size = blksize(fs, ip, lbn); 5627714Sroot } else { 5637714Sroot size = bsize; 5647714Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 5657714Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 5667714Sroot rasize = bsize; 5677714Sroot } 5687714Sroot if ((long)bn<0) { 5697714Sroot bp = geteblk(size); 5707714Sroot clrbuf(bp); 5717714Sroot } else if (ip->i_lastr + 1 == lbn) 5727714Sroot bp = breada(dev, bn, size, rablock, rasize); 5737714Sroot else 5747714Sroot bp = bread(dev, bn, size); 5757714Sroot ip->i_lastr = lbn; 5767714Sroot n = MIN(n, size - bp->b_resid); 5777714Sroot if (n != 0) { 5787714Sroot if (uio->uio_segflg != 1) { 5797714Sroot if (copyout(bp->b_un.b_addr+on, iov->iov_base, n)) { 5807714Sroot error = EFAULT; 5817714Sroot goto getresid; 5827714Sroot } 5837714Sroot } else 5847714Sroot bcopy(bp->b_un.b_addr + on, iov->iov_base, n); 5857714Sroot iov->iov_base += n; 5867714Sroot uio->uio_offset += n; 5877714Sroot iov->iov_len -= n; 5887714Sroot bad: 5897714Sroot ; 5907714Sroot } 5917714Sroot if (n + on == bsize || uio->uio_offset == ip->i_size) 5927714Sroot bp->b_flags |= B_AGE; 5937714Sroot brelse(bp); 5947714Sroot } while (u.u_error == 0 && iov->iov_len != 0 && n != 0); 5957714Sroot if (u.u_error == 0 && n > 0) { 5967714Sroot iov++; 5977714Sroot uio->uio_iovcnt--; 5987714Sroot goto nextiov; 5997714Sroot } 6007714Sroot getresid: 6017714Sroot while (uio->uio_iovcnt > 0) { 6027714Sroot uio->uio_resid += iov->iov_len; 6037714Sroot iov++; 6047714Sroot uio->uio_iovcnt--; 6057714Sroot } 6067714Sroot return (error); 6077714Sroot } 608