70faed9babe98592fe1bba38d3581e27ac38edd0
* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* %sccs.include.redist.c%
* @(#)vfs_vnops.c 7.47 (Berkeley) %G%
{ 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
, fmode
, cmode
)
register struct nameidata
*ndp
;
register struct vnode
*vp
;
register struct proc
*p
= ndp
->ni_cnd
.cn_proc
;
register struct ucred
*cred
= p
->p_ucred
;
struct vattr
*vap
= &vat
;
ndp
->ni_cnd
.cn_nameiop
= CREATE
;
ndp
->ni_cnd
.cn_flags
= LOCKPARENT
| LOCKLEAF
;
if ((fmode
& O_EXCL
) == 0)
ndp
->ni_cnd
.cn_flags
|= FOLLOW
;
if (ndp
->ni_vp
== NULL
) {
LEASE_CHECK(ndp
->ni_dvp
, p
, cred
, LEASE_WRITE
);
if (error
= VOP_CREATE(ndp
->ni_dvp
, &ndp
->ni_vp
,
VOP_ABORTOP(ndp
->ni_dvp
, &ndp
->ni_cnd
);
if (ndp
->ni_dvp
== ndp
->ni_vp
)
ndp
->ni_cnd
.cn_nameiop
= LOOKUP
;
ndp
->ni_cnd
.cn_flags
= FOLLOW
| LOCKLEAF
;
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
)))
VOP_UNLOCK(vp
); /* XXX */
LEASE_CHECK(vp
, p
, cred
, LEASE_WRITE
);
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
;
LEASE_CHECK(vp
, uio
->uio_procp
, cred
, LEASE_READ
);
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
)
LEASE_CHECK(vp
, uio
->uio_procp
, cred
, LEASE_WRITE
);
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_atimespec
= vap
->va_atime
;
sb
->st_mtimespec
= vap
->va_mtime
;
sb
->st_ctimespec
= vap
->va_ctime
;
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
))
*(int *)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
,