1*7746Sroot /* sys_generic.c 5.9 82/08/14 */ 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; 40*7746Sroot struct uio auio; 41*7746Sroot struct iovec aiov; 427423Sroot 437423Sroot uap = (struct a *)u.u_ap; 447423Sroot if ((int)uap->count < 0) { 457423Sroot u.u_error = EINVAL; 467423Sroot return; 477423Sroot } 487423Sroot GETF(fp, uap->fdes); 497423Sroot if ((fp->f_flag&FREAD) == 0) { 507423Sroot u.u_error = EBADF; 517423Sroot return; 527423Sroot } 53*7746Sroot aiov.iov_base = (caddr_t)uap->cbuf; 54*7746Sroot aiov.iov_len = uap->count; 55*7746Sroot auio.uio_iov = &aiov; 56*7746Sroot auio.uio_iovcnt = 1; 57*7746Sroot auio.uio_segflg = 0; 58*7746Sroot auio.uio_resid = uap->count; 59*7746Sroot u.u_base = (caddr_t)0xc0000000; 60*7746Sroot u.u_count = 0x40000000; 617423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 62*7746Sroot if (auio.uio_resid == uap->count) 637423Sroot u.u_eosys = RESTARTSYS; 647500Sroot } else if (fp->f_type == DTYPE_SOCKET) 65*7746Sroot u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0, &auio); 667423Sroot else { 677423Sroot ip = fp->f_inode; 68*7746Sroot auio.uio_offset = fp->f_offset; 697423Sroot if ((ip->i_mode&IFMT) == IFREG) { 707423Sroot ilock(ip); 71*7746Sroot u.u_error = readip(ip, &auio); 727423Sroot iunlock(ip); 737423Sroot } else 74*7746Sroot u.u_error = readip(ip, &auio); 75*7746Sroot fp->f_offset += uap->count - auio.uio_resid; 767423Sroot } 77*7746Sroot u.u_r.r_val1 = uap->count - auio.uio_resid; 787423Sroot } 797423Sroot 807423Sroot /* 817423Sroot * Write system call 827423Sroot */ 837423Sroot write() 847423Sroot { 857423Sroot register struct file *fp; 867423Sroot register struct inode *ip; 877423Sroot register struct a { 887423Sroot int fdes; 897423Sroot char *cbuf; 907423Sroot unsigned count; 917423Sroot } *uap; 927423Sroot 937423Sroot uap = (struct a *)u.u_ap; 947423Sroot if ((int)uap->count < 0) { 957423Sroot u.u_error = EINVAL; 967423Sroot return; 977423Sroot } 987423Sroot GETF(fp, uap->fdes); 997423Sroot if ((fp->f_flag&FWRITE) == 0) { 1007423Sroot u.u_error = EBADF; 1017423Sroot return; 1027423Sroot } 1037423Sroot u.u_base = (caddr_t)uap->cbuf; 1047423Sroot u.u_count = uap->count; 1057423Sroot u.u_segflg = 0; 1067423Sroot if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 1077423Sroot if (u.u_count == uap->count) 1087423Sroot u.u_eosys = RESTARTSYS; 1097500Sroot } else if (fp->f_type == DTYPE_SOCKET) 1107423Sroot u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); 1117423Sroot else { 1127423Sroot ip = fp->f_inode; 1137699Ssam if (fp->f_flag&FAPPEND) 1147500Sroot fp->f_offset = ip->i_size; 1157423Sroot u.u_offset = fp->f_offset; 1167423Sroot if ((ip->i_mode&IFMT) == IFREG) { 1177423Sroot ilock(ip); 1187423Sroot writei(ip); 1197423Sroot iunlock(ip); 1207423Sroot } else 1217423Sroot writei(ip); 1227423Sroot fp->f_offset += uap->count - u.u_count; 1237423Sroot } 1247423Sroot u.u_r.r_val1 = uap->count - u.u_count; 1257423Sroot } 1267423Sroot 1277500Sroot readv() 1287500Sroot { 1297423Sroot 1307500Sroot } 1317500Sroot 1327500Sroot writev() 1337500Sroot { 1347500Sroot 1357500Sroot } 1367500Sroot 1377423Sroot /* 1387423Sroot * Ioctl system call 1397624Ssam * Check legality, execute common code, 1407624Ssam * and switch out to individual device routine. 1417423Sroot */ 1427423Sroot ioctl() 1437423Sroot { 1447423Sroot register struct file *fp; 1457624Ssam struct a { 1467423Sroot int fdes; 1477423Sroot int cmd; 1487423Sroot caddr_t cmarg; 1497423Sroot } *uap; 1507624Ssam register int com, size; 1517624Ssam char data[IOCPARM_MASK+1]; 1527423Sroot 1537423Sroot uap = (struct a *)u.u_ap; 1547423Sroot if ((fp = getf(uap->fdes)) == NULL) 1557423Sroot return; 1567423Sroot if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 1577423Sroot u.u_error = EBADF; 1587423Sroot return; 1597423Sroot } 1607624Ssam com = uap->cmd; 1617624Ssam 1627699Ssam #ifndef NOCOMPAT 1637624Ssam /* 1647624Ssam * Map old style ioctl's into new for the 1657624Ssam * sake of backwards compatibility (sigh). 1667624Ssam */ 1677624Ssam if ((com&~0xffff) == 0) { 1687624Ssam com = mapioctl(com); 1697624Ssam if (com == 0) { 1707624Ssam u.u_error = EINVAL; 1717624Ssam return; 1727624Ssam } 1737624Ssam } 1747624Ssam #endif 1757624Ssam if (com == FIOCLEX) { 1767423Sroot u.u_pofile[uap->fdes] |= EXCLOSE; 1777423Sroot return; 1787423Sroot } 1797624Ssam if (com == FIONCLEX) { 1807423Sroot u.u_pofile[uap->fdes] &= ~EXCLOSE; 1817423Sroot return; 1827423Sroot } 1837624Ssam 1847624Ssam /* 1857624Ssam * Interpret high order word to find 1867624Ssam * amount of data to be copied to/from the 1877624Ssam * user's address space. 1887624Ssam * (this'll have to change if we have in+out ioctls) 1897624Ssam */ 1907624Ssam size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 1917624Ssam if (size > sizeof (data)) { 1927624Ssam u.u_error = EFAULT; 1937423Sroot return; 1947423Sroot } 1957699Ssam if (com&IOC_IN && size) { 1967624Ssam if (copyin(uap->cmarg, (caddr_t)data, size)) { 1977624Ssam u.u_error = EFAULT; 1987624Ssam return; 1997624Ssam } 2007624Ssam } else 2017624Ssam *(caddr_t *)data = uap->cmarg; 2027624Ssam /* 2037624Ssam * Zero the buffer on the stack so the user 2047624Ssam * always gets back something deterministic. 2057624Ssam */ 2067624Ssam if ((com&IOC_OUT) && size) 2077624Ssam bzero((caddr_t)data, size); 2087423Sroot 2097624Ssam if (fp->f_type == DTYPE_SOCKET) 2107624Ssam soioctl(fp->f_socket, com, data); 2117624Ssam else { 2127624Ssam register struct inode *ip = fp->f_inode; 2137624Ssam int fmt = ip->i_mode & IFMT; 2147624Ssam dev_t dev; 2157624Ssam 2167624Ssam if (fmt != IFCHR) { 2177624Ssam if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 2187624Ssam *(off_t *)data = ip->i_size - fp->f_offset; 2197624Ssam goto returndata; 2207624Ssam } 2217624Ssam if (com != FIONBIO && com != FIOASYNC) 2227624Ssam u.u_error = ENOTTY; 2237423Sroot return; 2247624Ssam } 2257624Ssam dev = ip->i_rdev; 2267624Ssam u.u_r.r_val1 = 0; 2277624Ssam if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 2287624Ssam u.u_eosys = RESTARTSYS; 2297624Ssam return; 2307624Ssam } 2317624Ssam (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0); 2327423Sroot } 2337624Ssam 2347624Ssam returndata: 2357624Ssam /* 2367624Ssam * Copy any data to user, size was 2377624Ssam * already set and checked above. 2387624Ssam */ 2397699Ssam if (u.u_error == 0 && com&IOC_OUT) 2407699Ssam if (size && copyout(data, uap->cmarg, size)) 2417699Ssam u.u_error = EFAULT; 2427423Sroot } 2437423Sroot 2447423Sroot /* 2457423Sroot * Do nothing specific version of line 2467423Sroot * discipline specific ioctl command. 2477423Sroot */ 2487423Sroot /*ARGSUSED*/ 2497624Ssam nullioctl(tp, cmd, data, flags) 2507423Sroot struct tty *tp; 2517624Ssam char *data; 2527624Ssam int flags; 2537423Sroot { 2547423Sroot 2557624Ssam #ifdef lint 2567624Ssam tp = tp; data = data; flags = flags; 2577624Ssam #endif 2587423Sroot return (cmd); 2597423Sroot } 2607423Sroot 2617423Sroot /* 2627423Sroot * Read the file corresponding to 2637423Sroot * the inode pointed at by the argument. 2647423Sroot * The actual read arguments are found 2657423Sroot * in the variables: 2667423Sroot * u_base core address for destination 2677423Sroot * u_offset byte offset in file 2687423Sroot * u_count number of bytes to read 2697423Sroot * u_segflg read to kernel/user/user I 2707423Sroot */ 2717423Sroot readi(ip) 2727423Sroot register struct inode *ip; 2737423Sroot { 2747423Sroot struct buf *bp; 2757423Sroot struct fs *fs; 2767423Sroot dev_t dev; 2777423Sroot daddr_t lbn, bn; 2787423Sroot off_t diff; 2797423Sroot register int on, type; 2807423Sroot register unsigned n; 2817423Sroot int size; 2827423Sroot long bsize; 2837423Sroot extern int mem_no; 2847423Sroot 2857423Sroot if (u.u_count == 0) 2867423Sroot return; 2877423Sroot dev = (dev_t)ip->i_rdev; 2887423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 2897423Sroot mem_no != major(dev))) { 2907423Sroot u.u_error = EINVAL; 2917423Sroot return; 2927423Sroot } 2937423Sroot ip->i_flag |= IACC; 2947423Sroot type = ip->i_mode&IFMT; 2957423Sroot if (type == IFCHR) { 2967487Skre register c = u.u_count; 2977722Swnj struct uio auio; 2987722Swnj struct iovec aiov; 2997722Swnj auio.uio_iov = &aiov; 3007722Swnj auio.uio_iovcnt = 1; 3017722Swnj aiov.iov_base = u.u_base; 3027722Swnj aiov.iov_len = u.u_count; 3037722Swnj auio.uio_offset = u.u_offset; 3047722Swnj auio.uio_segflg = u.u_segflg; 3057722Swnj auio.uio_resid = u.u_count; 3067722Swnj (*cdevsw[major(dev)].d_read)(dev, &auio); 3077722Swnj CHARGE(sc_tio * (c - auio.uio_resid)); 3087722Swnj u.u_count = auio.uio_resid; 3097423Sroot return; 3107423Sroot } 3117423Sroot if (type != IFBLK) { 3127423Sroot dev = ip->i_dev; 3137423Sroot fs = ip->i_fs; 3147423Sroot bsize = fs->fs_bsize; 3157423Sroot } else 3167423Sroot bsize = BLKDEV_IOSIZE; 3177423Sroot do { 3187423Sroot lbn = u.u_offset / bsize; 3197423Sroot on = u.u_offset % bsize; 3207423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 3217423Sroot if (type != IFBLK) { 3227423Sroot diff = ip->i_size - u.u_offset; 3237423Sroot if (diff <= 0) 3247423Sroot return; 3257423Sroot if (diff < n) 3267423Sroot n = diff; 3277423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 3287423Sroot if (u.u_error) 3297423Sroot return; 3307423Sroot size = blksize(fs, ip, lbn); 3317423Sroot } else { 3327423Sroot size = bsize; 3337423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 3347423Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 3357423Sroot rasize = bsize; 3367423Sroot } 3377423Sroot if ((long)bn<0) { 3387423Sroot bp = geteblk(size); 3397423Sroot clrbuf(bp); 3407423Sroot } else if (ip->i_lastr + 1 == lbn) 3417423Sroot bp = breada(dev, bn, size, rablock, rasize); 3427423Sroot else 3437423Sroot bp = bread(dev, bn, size); 3447423Sroot ip->i_lastr = lbn; 3457423Sroot n = MIN(n, size - bp->b_resid); 3467423Sroot if (n != 0) { 3477423Sroot if (u.u_segflg != 1) { 3487423Sroot if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { 3497423Sroot u.u_error = EFAULT; 3507423Sroot goto bad; 3517423Sroot } 3527423Sroot } else 3537423Sroot bcopy(bp->b_un.b_addr + on, u.u_base, n); 3547423Sroot u.u_base += n; 3557423Sroot u.u_offset += n; 3567423Sroot u.u_count -= n; 3577423Sroot bad: 3587423Sroot ; 3597423Sroot } 3607423Sroot if (n + on == bsize || u.u_offset == ip->i_size) 3617423Sroot bp->b_flags |= B_AGE; 3627423Sroot brelse(bp); 3637423Sroot } while (u.u_error == 0 && u.u_count != 0 && n != 0); 3647423Sroot } 3657423Sroot 3667423Sroot /* 3677423Sroot * Write the file corresponding to 3687423Sroot * the inode pointed at by the argument. 3697423Sroot * The actual write arguments are found 3707423Sroot * in the variables: 3717423Sroot * u_base core address for source 3727423Sroot * u_offset byte offset in file 3737423Sroot * u_count number of bytes to write 3747423Sroot * u_segflg write to kernel/user/user I 3757423Sroot */ 3767423Sroot writei(ip) 3777423Sroot register struct inode *ip; 3787423Sroot { 3797423Sroot struct buf *bp; 3807423Sroot register struct fs *fs; 3817423Sroot dev_t dev; 3827423Sroot daddr_t lbn, bn; 3837423Sroot register int on, type; 3847423Sroot register unsigned n; 3857423Sroot long bsize; 3867423Sroot int size, i, count; 3877423Sroot extern int mem_no; 3887423Sroot 3897423Sroot dev = (dev_t)ip->i_rdev; 3907423Sroot if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 3917423Sroot mem_no != major(dev)) ) { 3927423Sroot u.u_error = EINVAL; 3937423Sroot return; 3947423Sroot } 3957423Sroot type = ip->i_mode & IFMT; 3967423Sroot if (type == IFCHR) { 3977423Sroot ip->i_flag |= IUPD|ICHG; 3987487Skre CHARGE(sc_tio * u.u_count); 3997423Sroot (*cdevsw[major(dev)].d_write)(dev); 4007423Sroot return; 4017423Sroot } 4027423Sroot if (u.u_count == 0) 4037423Sroot return; 4047423Sroot if ((ip->i_mode & IFMT) == IFREG && 4057423Sroot u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { 4067423Sroot psignal(u.u_procp, SIGXFSZ); 4077423Sroot u.u_error = EMFILE; 4087423Sroot return; 4097423Sroot } 4107423Sroot if (type!=IFBLK) { 4117423Sroot dev = ip->i_dev; 4127423Sroot fs = ip->i_fs; 4137423Sroot bsize = fs->fs_bsize; 4147532Sroot } else 4157423Sroot bsize = BLKDEV_IOSIZE; 4167423Sroot do { 4177423Sroot lbn = u.u_offset / bsize; 4187423Sroot on = u.u_offset % bsize; 4197423Sroot n = MIN((unsigned)(bsize - on), u.u_count); 4207423Sroot if (type != IFBLK) { 4217423Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); 4227532Sroot if (u.u_error || (long)bn<0) 4237423Sroot return; 4247423Sroot if(u.u_offset + n > ip->i_size && 4257423Sroot (type == IFDIR || type == IFREG || type == IFLNK)) 4267423Sroot ip->i_size = u.u_offset + n; 4277423Sroot size = blksize(fs, ip, lbn); 4287423Sroot } else { 4297423Sroot size = bsize; 4307423Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 4317423Sroot } 4327532Sroot count = howmany(size, DEV_BSIZE); 4337532Sroot for (i = 0; i < count; i += CLSIZE) 4347532Sroot if (mfind(dev, bn + i)) 4357532Sroot munhash(dev, bn + i); 4367532Sroot if (n == bsize) 4377423Sroot bp = getblk(dev, bn, size); 4387423Sroot else 4397423Sroot bp = bread(dev, bn, size); 4407423Sroot if (u.u_segflg != 1) { 4417423Sroot if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { 4427423Sroot u.u_error = EFAULT; 4437423Sroot goto bad; 4447423Sroot } 4457423Sroot } else 4467423Sroot bcopy(u.u_base, bp->b_un.b_addr + on, n); 4477423Sroot u.u_base += n; 4487423Sroot u.u_offset += n; 4497423Sroot u.u_count -= n; 4507423Sroot bad: 4517423Sroot ; 4527423Sroot if (u.u_error != 0) 4537423Sroot brelse(bp); 4547423Sroot else { 4557423Sroot if ((ip->i_mode&IFMT) == IFDIR) 4567423Sroot /* 4577423Sroot * Writing to clear a directory entry. 4587423Sroot * Must insure the write occurs before 4597423Sroot * the inode is freed, or may end up 4607423Sroot * pointing at a new (different) file 4617423Sroot * if inode is quickly allocated again 4627423Sroot * and system crashes. 4637423Sroot */ 4647423Sroot bwrite(bp); 4657423Sroot else if (n + on == bsize) { 4667423Sroot bp->b_flags |= B_AGE; 4677423Sroot bawrite(bp); 4687423Sroot } else 4697423Sroot bdwrite(bp); 4707423Sroot } 4717423Sroot ip->i_flag |= IUPD|ICHG; 4727423Sroot if (u.u_ruid != 0) 4737423Sroot ip->i_mode &= ~(ISUID|ISGID); 4747423Sroot } while (u.u_error == 0 && u.u_count != 0); 4757423Sroot } 4767423Sroot 4777423Sroot /* 4787423Sroot * Move n bytes at byte location 4797423Sroot * &bp->b_un.b_addr[o] to/from (flag) the 4807423Sroot * user/kernel (u.segflg) area starting at u.base. 4817423Sroot * Update all the arguments by the number 4827423Sroot * of bytes moved. 4837423Sroot */ 4847423Sroot iomove(cp, n, flag) 4857423Sroot register caddr_t cp; 4867423Sroot register unsigned n; 4877423Sroot { 4887423Sroot register int t; 4897423Sroot 4907423Sroot if (n==0) 4917423Sroot return; 4927423Sroot if (u.u_segflg != 1) { 4937423Sroot if (flag==B_WRITE) 4947423Sroot t = copyin(u.u_base, (caddr_t)cp, n); 4957423Sroot else 4967423Sroot t = copyout((caddr_t)cp, u.u_base, n); 4977423Sroot if (t) { 4987423Sroot u.u_error = EFAULT; 4997423Sroot return; 5007423Sroot } 5017423Sroot } else 5027423Sroot if (flag == B_WRITE) 5037423Sroot bcopy(u.u_base, (caddr_t)cp, n); 5047423Sroot else 5057423Sroot bcopy((caddr_t)cp, u.u_base, n); 5067423Sroot u.u_base += n; 5077423Sroot u.u_offset += n; 5087423Sroot u.u_count -= n; 5097423Sroot } 5107714Sroot 5117714Sroot readip(ip, uio) 5127714Sroot register struct inode *ip; 5137714Sroot register struct uio *uio; 5147714Sroot { 515*7746Sroot register struct iovec *iov; 5167714Sroot struct buf *bp; 5177714Sroot struct fs *fs; 5187714Sroot dev_t dev; 5197714Sroot daddr_t lbn, bn; 5207714Sroot off_t diff; 5217714Sroot register int on, type; 5227714Sroot register unsigned n; 5237714Sroot int size; 5247714Sroot long bsize; 5257714Sroot extern int mem_no; 5267714Sroot int error = 0; 5277714Sroot 5287714Sroot dev = (dev_t)ip->i_rdev; 5297714Sroot if (uio->uio_offset < 0 && 530*7746Sroot ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) 531*7746Sroot return (EINVAL); 5327714Sroot ip->i_flag |= IACC; 5337714Sroot type = ip->i_mode&IFMT; 5347714Sroot if (type == IFCHR) { 5357714Sroot register c = u.u_count; 536*7746Sroot (*cdevsw[major(dev)].d_read)(dev, uio); 537*7746Sroot CHARGE(sc_tio * (c - uio->uio_resid)); 538*7746Sroot return (u.u_error); 5397714Sroot } 5407714Sroot if (type != IFBLK) { 5417714Sroot dev = ip->i_dev; 5427714Sroot fs = ip->i_fs; 5437714Sroot bsize = fs->fs_bsize; 5447714Sroot } else 5457714Sroot bsize = BLKDEV_IOSIZE; 5467714Sroot nextiov: 5477714Sroot if (uio->uio_iovcnt == 0) 548*7746Sroot return (0); 549*7746Sroot iov = uio->uio_iov; 5507714Sroot if (iov->iov_len > 0) 5517714Sroot do { 5527714Sroot lbn = uio->uio_offset / bsize; 5537714Sroot on = uio->uio_offset % bsize; 5547714Sroot n = MIN((unsigned)(bsize - on), iov->iov_len); 5557714Sroot if (type != IFBLK) { 5567714Sroot diff = ip->i_size - uio->uio_offset; 5577714Sroot if (diff <= 0) 5587714Sroot return; 5597714Sroot if (diff < n) 5607714Sroot n = diff; 5617714Sroot bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 5627714Sroot if (u.u_error) 563*7746Sroot return (u.u_error); 5647714Sroot size = blksize(fs, ip, lbn); 5657714Sroot } else { 5667714Sroot size = bsize; 5677714Sroot bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 5687714Sroot rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 5697714Sroot rasize = bsize; 5707714Sroot } 5717714Sroot if ((long)bn<0) { 5727714Sroot bp = geteblk(size); 5737714Sroot clrbuf(bp); 5747714Sroot } else if (ip->i_lastr + 1 == lbn) 5757714Sroot bp = breada(dev, bn, size, rablock, rasize); 5767714Sroot else 5777714Sroot bp = bread(dev, bn, size); 5787714Sroot ip->i_lastr = lbn; 5797714Sroot n = MIN(n, size - bp->b_resid); 5807714Sroot if (n != 0) { 5817714Sroot if (uio->uio_segflg != 1) { 5827714Sroot if (copyout(bp->b_un.b_addr+on, iov->iov_base, n)) { 583*7746Sroot brelse(bp); 584*7746Sroot return (EFAULT); 5857714Sroot } 5867714Sroot } else 5877714Sroot bcopy(bp->b_un.b_addr + on, iov->iov_base, n); 5887714Sroot iov->iov_base += n; 5897714Sroot uio->uio_offset += n; 5907714Sroot iov->iov_len -= n; 591*7746Sroot uio->uio_resid -= n; 5927714Sroot } 5937714Sroot if (n + on == bsize || uio->uio_offset == ip->i_size) 5947714Sroot bp->b_flags |= B_AGE; 5957714Sroot brelse(bp); 5967714Sroot } while (u.u_error == 0 && iov->iov_len != 0 && n != 0); 597*7746Sroot if (u.u_error == 0 && iov->iov_len == 0) { 598*7746Sroot uio->uio_iov++; 5997714Sroot uio->uio_iovcnt--; 6007714Sroot goto nextiov; 6017714Sroot } 6027714Sroot return (error); 6037714Sroot } 604*7746Sroot 605*7746Sroot uiomove(cp, n, dir, uio) 606*7746Sroot register caddr_t cp; 607*7746Sroot register unsigned n; 608*7746Sroot enum uio_direction dir; 609*7746Sroot struct uio *uio; 610*7746Sroot { 611*7746Sroot register struct iovec *iov; 612*7746Sroot int bad, cnt; 613*7746Sroot 614*7746Sroot if (n == 0) 615*7746Sroot return (0); 616*7746Sroot if (uio->uio_segflg != 1) { 617*7746Sroot if (dir == UIO_READFROM) 618*7746Sroot #ifdef notdef 619*7746Sroot bad = copyuin(uio, (caddr_t)cp, n); 620*7746Sroot #else 621*7746Sroot panic("uiomove"); 622*7746Sroot #endif 623*7746Sroot else 624*7746Sroot bad = copyuout((caddr_t)cp, n, uio); 625*7746Sroot if (bad) 626*7746Sroot return (EFAULT); 627*7746Sroot } else { 628*7746Sroot while (n > 0 && uio->uio_iovcnt) { 629*7746Sroot iov = uio->uio_iov; 630*7746Sroot cnt = iov->iov_len; 631*7746Sroot if (cnt > n) 632*7746Sroot cnt = n; 633*7746Sroot if (dir == UIO_READFROM) 634*7746Sroot bcopy(iov->iov_base, (caddr_t)cp, cnt); 635*7746Sroot else 636*7746Sroot bcopy((caddr_t)cp, iov->iov_base, cnt); 637*7746Sroot iov->iov_base += cnt; 638*7746Sroot iov->iov_len -= cnt; 639*7746Sroot uio->uio_resid -= cnt; 640*7746Sroot n -= cnt; 641*7746Sroot } 642*7746Sroot } 643*7746Sroot return (0); 644*7746Sroot } 645