+ if (vp->v_flag & VTEXT)
+ xrele(vp);
+ if (vp->v_flag & VTEXT)
+ return (ETXTBSY);
+ return (0);
+}
+
+/*
+ * Vnode version of rdwri() for calls on file systems.
+ */
+vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid)
+ enum uio_rw rw;
+ struct vnode *vp;
+ caddr_t base;
+ int len;
+ off_t offset;
+ enum uio_seg segflg;
+ int ioflg;
+ struct ucred *cred;
+ int *aresid;
+{
+ struct uio auio;
+ struct iovec aiov;
+ int error;
+
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ aiov.iov_base = base;
+ aiov.iov_len = len;
+ auio.uio_resid = len;
+ auio.uio_offset = offset;
+ auio.uio_segflg = segflg;
+ auio.uio_rw = rw;
+ if (rw == UIO_READ)
+ error = VOP_READ(vp, &auio, &offset, ioflg, cred);
+ else
+ error = VOP_WRITE(vp, &auio, &offset, ioflg, cred);
+ if (aresid)
+ *aresid = auio.uio_resid;
+ else
+ if (auio.uio_resid && error == 0)
+ error = EIO;
+ return (error);
+}
+
+vn_read(fp, uio, cred)
+ struct file *fp;
+ struct uio *uio;
+ struct ucred *cred;
+{
+
+ return (VOP_READ((struct vnode *)fp->f_data, uio, &(fp->f_offset),
+ (fp->f_flag & FNDELAY) ? IO_NDELAY : 0, cred));
+}
+
+vn_write(fp, uio, cred)
+ struct file *fp;
+ struct uio *uio;
+ struct ucred *cred;
+{
+ register struct vnode *vp = (struct vnode *)fp->f_data;
+ int ioflag = 0;
+
+ if (vp->v_type == VREG && (fp->f_flag & FAPPEND))
+ ioflag |= IO_APPEND;
+ if (fp->f_flag & FNDELAY)
+ ioflag |= IO_NDELAY;
+ return (VOP_WRITE(vp, uio, &(fp->f_offset), ioflag, cred));
+}
+
+/*
+ * Get stat info for a vnode.
+ */
+vn_stat(vp, sb)
+ struct vnode *vp;
+ register struct stat *sb;
+{
+ struct vattr vattr;
+ register struct vattr *vap;
+ int error;
+ u_short mode;
+
+ vap = &vattr;
+ error = VOP_GETATTR(vp, vap, u.u_cred);
+ if (error)
+ return (error);
+ /*
+ * Copy from vattr table
+ */
+ sb->st_dev = vap->va_fsid;
+ sb->st_ino = vap->va_fileid;
+ mode = vap->va_mode;
+ switch (vp->v_type) {
+ case VREG:
+ mode |= IFREG;
+ break;
+ case VDIR:
+ mode |= IFDIR;
+ break;
+ case VBLK:
+ mode |= IFBLK;
+ break;
+ case VCHR:
+ mode |= IFCHR;
+ break;
+ case VLNK:
+ mode |= IFLNK;
+ break;
+ case VSOCK:
+ mode |= IFSOCK;
+ break;
+ default:
+ return (EBADF);
+ };
+ sb->st_mode = mode;
+ sb->st_nlink = vap->va_nlink;
+ sb->st_uid = vap->va_uid;
+ sb->st_gid = vap->va_gid;
+ sb->st_rdev = vap->va_rdev;
+ sb->st_size = vap->va_size;
+ sb->st_atime = vap->va_atime.tv_sec;
+ sb->st_spare1 = 0;
+ sb->st_mtime = vap->va_mtime.tv_sec;
+ sb->st_spare2 = 0;
+ sb->st_ctime = vap->va_ctime.tv_sec;
+ sb->st_spare3 = 0;
+ sb->st_blksize = vap->va_blocksize;
+ sb->st_flags = vap->va_flags;
+ sb->st_gen = vap->va_gen;
+ sb->st_blocks = vap->va_bytes / S_BLKSIZE;
+ return (0);
+}
+
+/*
+ * Vnode ioctl call
+ */
+vn_ioctl(fp, com, data)
+ struct file *fp;
+ int com;
+ caddr_t data;
+{
+ register struct vnode *vp = ((struct vnode *)fp->f_data);
+ struct vattr vattr;
+ int error;
+
+ switch (vp->v_type) {
+
+ case VREG:
+ case VDIR:
+ if (com == FIONREAD) {
+ if (error = VOP_GETATTR(vp, &vattr, u.u_cred))
+ return (error);
+ *(off_t *)data = vattr.va_size - fp->f_offset;
+ return (0);
+ }
+ if (com == FIONBIO || com == FIOASYNC) /* XXX */
+ return (0); /* XXX */
+ /* fall into ... */
+
+ default:
+ return (ENOTTY);
+
+ case VCHR:
+ case VBLK:
+ u.u_r.r_val1 = 0;
+ if (setjmp(&u.u_qsave)) {
+ if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+ return(EINTR);
+ u.u_eosys = RESTARTSYS;
+ return (0);
+ }
+ return (VOP_IOCTL(vp, com, data, fp->f_flag, u.u_cred));