- bsize = BLKDEV_IOSIZE;
- do {
- lbn = uio->uio_offset / bsize;
- on = uio->uio_offset % bsize;
- n = MIN((unsigned)(bsize - on), uio->uio_resid);
- if (type != IFBLK) {
- if (rw == UIO_READ) {
- int diff = ip->i_size - uio->uio_offset;
- if (diff <= 0)
- return (0);
- if (diff < n)
- n = diff;
- }
- bn = fsbtodb(fs,
- bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n)));
- if (u.u_error || rw == UIO_WRITE && (long)bn<0)
- return (u.u_error);
- if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size &&
- (type == IFDIR || type == IFREG || type == IFLNK))
- ip->i_size = uio->uio_offset + n;
- size = blksize(fs, ip, lbn);
- } else {
- bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
- rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE);
- rasize = size = bsize;
- }
- if (rw == UIO_READ) {
- if ((long)bn<0) {
- bp = geteblk(size);
- clrbuf(bp);
- } else if (ip->i_lastr + 1 == lbn)
- bp = breada(dev, bn, size, rablock, rasize);
- else
- bp = bread(dev, bn, size);
- ip->i_lastr = lbn;
- } else {
- int i, count;
-
- count = howmany(size, DEV_BSIZE);
- for (i = 0; i < count; i += CLSIZE)
- if (mfind(dev, bn + i))
- munhash(dev, bn + i);
- if (n == bsize)
- bp = getblk(dev, bn, size);
- else
- bp = bread(dev, bn, size);
- }
- n = MIN(n, size - bp->b_resid);
- if (bp->b_flags & B_ERROR) {
- error = EIO;
- brelse(bp);
- goto bad;
- }
- u.u_error =
- uiomove(bp->b_un.b_addr+on, (u_int)n, rw, uio);
- if (rw == UIO_READ) {
- if (n + on == bsize || uio->uio_offset == ip->i_size)
- bp->b_flags |= B_AGE;
- brelse(bp);
- } else {
- if ((ip->i_mode&IFMT) == IFDIR)
- bwrite(bp);
- else if (n + on == bsize) {
- bp->b_flags |= B_AGE;
- bawrite(bp);
- } else
- bdwrite(bp);
- ip->i_flag |= IUPD|ICHG;
- if (u.u_ruid != 0)
- ip->i_mode &= ~(ISUID|ISGID);
- }
- } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0);
-bad:
- return (error);
-}
-
-uiomove(cp, n, rw, uio)
- register caddr_t cp;
- register int n;
- enum uio_rw rw;
- register struct uio *uio;
-{
- register struct iovec *iov;
- int error;
- u_int cnt;
-
- while (n > 0 && uio->uio_resid) {
- iov = uio->uio_iov;
- cnt = iov->iov_len;
- if (cnt == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- continue;
- }
- if (cnt > n)
- cnt = n;
- switch (uio->uio_segflg) {
-
- case 0:
- case 2:
- if (rw == UIO_READ)
- error = copyout(cp, iov->iov_base, cnt);
- else
- error = copyin(iov->iov_base, cp, cnt);
- if (error)
- return (error);
- break;
-
- case 1:
- if (rw == UIO_READ)
- bcopy((caddr_t)cp, iov->iov_base, cnt);
- else
- bcopy(iov->iov_base, (caddr_t)cp, cnt);
- break;
- }
- iov->iov_base += cnt;
- iov->iov_len -= cnt;
- uio->uio_resid -= cnt;
- uio->uio_offset += cnt;
- cp += cnt;
- n -= cnt;
- }
- return (error);
-}
-
-/*
- * Give next character to user as result of read.
- */
-ureadc(c, uio)
- register int c;
- register struct uio *uio;
-{
- register struct iovec *iov;
-
-again:
- if (uio->uio_iovcnt == 0)
- panic("ureadc");
- iov = uio->uio_iov;
- if (iov->iov_len <= 0 || uio->uio_resid <= 0) {
- uio->uio_iovcnt--;
- uio->uio_iov++;
- goto again;
- }
- switch (uio->uio_segflg) {
-
- case 0:
- if (subyte(iov->iov_base, c) < 0)
- return (EFAULT);
- break;
-
- case 1:
- *iov->iov_base = c;
- break;
-
- case 2:
- if (suibyte(iov->iov_base, c) < 0)
- return (EFAULT);
- break;
- }
- iov->iov_base++;
- iov->iov_len--;
- uio->uio_resid--;
- uio->uio_offset++;
- return (0);
-}
-
-/*
- * Get next character written in by user from uio.
- */
-uwritec(uio)
- struct uio *uio;
-{
- register struct iovec *iov;
- register int c;
-
-again:
- if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0)
- panic("uwritec");
- iov = uio->uio_iov;
- if (iov->iov_len == 0) {
- uio->uio_iovcnt--;
- uio->uio_iov++;
- goto again;
- }
- switch (uio->uio_segflg) {
-
- case 0:
- c = fubyte(iov->iov_base);
- break;
-
- case 1:
- c = *iov->iov_base & 0377;
- break;
-
- case 2:
- c = fuibyte(iov->iov_base);
- break;
- }
- if (c < 0)
- return (-1);
- iov->iov_base++;
- iov->iov_len--;
- uio->uio_resid--;
- uio->uio_offset++;
- return (c & 0377);