* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)vfs_vnops.c 7.33 (Berkeley) 6/27/91
{ vn_read
, vn_write
, vn_ioctl
, vn_select
, vn_closefile
};
* Common code for vnode open operations.
* Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
vn_open(ndp
, p
, fmode
, cmode
)
register struct nameidata
*ndp
;
register struct vnode
*vp
;
register struct ucred
*cred
= p
->p_ucred
;
struct vattr
*vap
= &vat
;
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
| LOCKLEAF
;
if ((fmode
& O_EXCL
) == 0)
ndp
->ni_nameiop
|= FOLLOW
;
if (error
= namei(ndp
, p
))
if (ndp
->ni_vp
== NULL
) {
if (error
= VOP_CREATE(ndp
, vap
, p
))
if (ndp
->ni_dvp
== ndp
->ni_vp
)
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
if (error
= namei(ndp
, p
))
if (vp
->v_type
== VSOCK
) {
if ((fmode
& O_CREAT
) == 0) {
if (error
= VOP_ACCESS(vp
, VREAD
, cred
, p
))
if (fmode
& (FWRITE
| O_TRUNC
)) {
if (vp
->v_type
== VDIR
) {
if ((error
= vn_writechk(vp
)) ||
(error
= VOP_ACCESS(vp
, VWRITE
, cred
, p
)))
if (error
= VOP_SETATTR(vp
, vap
, cred
, p
))
if (error
= VOP_OPEN(vp
, fmode
, cred
, p
))
* Check for write permissions on the specified vnode.
* The read-only status of the file system is checked.
* Also, prototype text segments cannot be written.
register struct vnode
*vp
;
* Disallow write attempts on read-only file systems;
* unless the file is a socket or a block or character
* device resident on the file system.
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
case VREG
: case VDIR
: case VLNK
:
* If there's shared text associated with
* the vnode, try to free it up once. If
* we fail, we can't allow writing.
if ((vp
->v_flag
& VTEXT
) && !vnode_pager_uncache(vp
))
vn_close(vp
, flags
, cred
, p
)
register struct vnode
*vp
;
error
= VOP_CLOSE(vp
, flags
, cred
, p
);
* Package up an I/O request on a vnode into a uio and do it.
vn_rdwr(rw
, vp
, base
, len
, offset
, segflg
, ioflg
, cred
, aresid
, p
)
if ((ioflg
& IO_NODELOCKED
) == 0)
auio
.uio_offset
= offset
;
auio
.uio_segflg
= segflg
;
error
= VOP_READ(vp
, &auio
, ioflg
, cred
);
error
= VOP_WRITE(vp
, &auio
, ioflg
, cred
);
*aresid
= auio
.uio_resid
;
if (auio
.uio_resid
&& error
== 0)
if ((ioflg
& IO_NODELOCKED
) == 0)
* File table vnode read routine.
register struct vnode
*vp
= (struct vnode
*)fp
->f_data
;
uio
->uio_offset
= fp
->f_offset
;
error
= VOP_READ(vp
, uio
, (fp
->f_flag
& FNONBLOCK
) ? IO_NDELAY
: 0,
fp
->f_offset
+= count
- uio
->uio_resid
;
* File table vnode write routine.
register struct vnode
*vp
= (struct vnode
*)fp
->f_data
;
int count
, error
, ioflag
= 0;
if (vp
->v_type
== VREG
&& (fp
->f_flag
& O_APPEND
))
if (fp
->f_flag
& FNONBLOCK
)
uio
->uio_offset
= fp
->f_offset
;
error
= VOP_WRITE(vp
, uio
, ioflag
, cred
);
fp
->f_offset
= uio
->uio_offset
;
fp
->f_offset
+= count
- uio
->uio_resid
;
* File table vnode stat routine.
register struct stat
*sb
;
register struct vattr
*vap
;
error
= VOP_GETATTR(vp
, vap
, p
->p_ucred
, p
);
sb
->st_dev
= vap
->va_fsid
;
sb
->st_ino
= vap
->va_fileid
;
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_mtime
= vap
->va_mtime
.tv_sec
;
sb
->st_ctime
= vap
->va_ctime
.tv_sec
;
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
;
* File table vnode ioctl routine.
vn_ioctl(fp
, com
, data
, p
)
register struct vnode
*vp
= ((struct vnode
*)fp
->f_data
);
if (error
= VOP_GETATTR(vp
, &vattr
, p
->p_ucred
, p
))
*(off_t
*)data
= vattr
.va_size
- fp
->f_offset
;
if (com
== FIONBIO
|| com
== FIOASYNC
) /* XXX */
error
= VOP_IOCTL(vp
, com
, data
, fp
->f_flag
, p
->p_ucred
, p
);
if (error
== 0 && com
== TIOCSCTTY
) {
p
->p_session
->s_ttyvp
= vp
;
* File table vnode select routine.
return (VOP_SELECT(((struct vnode
*)fp
->f_data
), which
, fp
->f_flag
,
* File table vnode close routine.
return (vn_close(((struct vnode
*)fp
->f_data
), fp
->f_flag
,
* vn_fhtovp() - convert a fh to a vnode ptr (optionally locked)
* - look up fsid in mount list (if not found ret error)
* - get vp by calling VFS_FHTOVP() macro
* - if lockflag lock it with VOP_LOCK()
vn_fhtovp(fhp
, lockflag
, vpp
)
register struct mount
*mp
;
if ((mp
= getvfs(&fhp
->fh_fsid
)) == NULL
)
if (VFS_FHTOVP(mp
, &fhp
->fh_fid
, vpp
))