FreeBSD/sys/kern/vfs_vnops.c
/*
 * Common code for vnode open operations once a vnode is located.
 * Check permissions, and call the VOP_OPEN routine.
 */
Common code for vnode open operations once a vnode is located.
Check permissions, and call the VOP_OPEN routine.
Common code for vnode open operations once a vnode is located . Check permissions and call the VOP_OPEN routine .
int
vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred,
    struct thread *td, struct file *fp)
{
	accmode_t accmode;
	struct flock lf;
	int error, lock_flags, type;
	if (vp->v_type == VLNK)
		return (EMLINK);
	if (vp->v_type == VSOCK)
		return (EOPNOTSUPP);
	if (vp->v_type != VDIR && fmode & O_DIRECTORY)
		return (ENOTDIR);
	accmode = 0;
	if (fmode & (FWRITE | O_TRUNC)) {
		if (vp->v_type == VDIR)
			return (EISDIR);
		accmode |= VWRITE;
	}
	if (fmode & FREAD)
		accmode |= VREAD;
	if (fmode & FEXEC)
		accmode |= VEXEC;
	if ((fmode & O_APPEND) && (fmode & FWRITE))
		accmode |= VAPPEND;
#ifdef MAC
	if (fmode & O_CREAT)
		accmode |= VCREAT;
	if (fmode & O_VERIFY)
		accmode |= VVERIFY;
	error = mac_vnode_check_open(cred, vp, accmode);
	if (error)
		return (error);
	accmode &= ~(VCREAT | VVERIFY);
#endif
	if ((fmode & O_CREAT) == 0) {
		if (accmode & VWRITE) {
			error = vn_writechk(vp);
			if (error)
				return (error);
		}
		if (accmode) {
		        error = VOP_ACCESS(vp, accmode, cred, td);
			if (error)
				return (error);
		}
	}
	if (vp->v_type == VFIFO && VOP_ISLOCKED(vp) != LK_EXCLUSIVE)
		vn_lock(vp, LK_UPGRADE | LK_RETRY);
	if ((error = VOP_OPEN(vp, fmode, cred, td, fp)) != 0)
		return (error);
	if (fmode & (O_EXLOCK | O_SHLOCK)) {
		KASSERT(fp != NULL, ("open with flock requires fp"));
		lock_flags = VOP_ISLOCKED(vp);
		VOP_UNLOCK(vp, 0);
		lf.l_whence = SEEK_SET;
		lf.l_start = 0;
		lf.l_len = 0;
		if (fmode & O_EXLOCK)
			lf.l_type = F_WRLCK;
		else
			lf.l_type = F_RDLCK;
		type = F_FLOCK;
		if ((fmode & FNONBLOCK) == 0)
			type |= F_WAIT;
		error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
		if (error == 0)
			fp->f_flag |= FHASLOCK;
		vn_lock(vp, lock_flags | LK_RETRY);
		if (error == 0 && vp->v_iflag & VI_DOOMED)
			error = ENOENT;
		if (error == 0 && accmode & VWRITE)
			error = vn_writechk(vp);
		if (error != 0) {
			fp->f_flag |= FOPENFAILED;
			fp->f_vnode = vp;
			if (fp->f_ops == &badfileops) {
				fp->f_type = DTYPE_VNODE;
				fp->f_ops = &vnops;
			}
			vref(vp);
		}
	}
	if (error == 0 && fmode & FWRITE) {
		VOP_ADD_WRITECOUNT(vp, 1);
		CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",
		    __func__, vp, vp->v_writecount);
	}
	ASSERT_VOP_LOCKED(vp, "vn_open_vnode");
	return (error);
}
int vn_open_vnode ( struct vnode * vp , int fmode , struct ucred * cred , struct thread * td , struct file * fp ) { accmode_t accmode ; struct flock lf ; int error , lock_flags , type ; if ( vp -> v_type == VLNK ) return ( EMLINK ) ; if ( vp -> v_type == VSOCK ) return ( EOPNOTSUPP ) ; if ( vp -> v_type != VDIR && fmode & O_DIRECTORY ) return ( ENOTDIR ) ; accmode = 0 ; if ( fmode & ( FWRITE | O_TRUNC ) ) { if ( vp -> v_type == VDIR ) return ( EISDIR ) ; accmode |= VWRITE ; } if ( fmode & FREAD ) accmode |= VREAD ; if ( fmode & FEXEC ) accmode |= VEXEC ; if ( ( fmode & O_APPEND ) && ( fmode & FWRITE ) ) accmode |= VAPPEND ; #ifdef MAC if ( fmode & O_CREAT ) accmode |= VCREAT ; if ( fmode & O_VERIFY ) accmode |= VVERIFY ; error = mac_vnode_check_open ( cred , vp , accmode ) ; if ( error ) return ( error ) ; accmode &= ~ ( VCREAT | VVERIFY ) ; #endif if ( ( fmode & O_CREAT ) == 0 ) { if ( accmode & VWRITE ) { error = vn_writechk ( vp ) ; if ( error ) return ( error ) ; } if ( accmode ) { error = VOP_ACCESS ( vp , accmode , cred , td ) ; if ( error ) return ( error ) ; } } if ( vp -> v_type == VFIFO && VOP_ISLOCKED ( vp ) != LK_EXCLUSIVE ) vn_lock ( vp , LK_UPGRADE | LK_RETRY ) ; if ( ( error = VOP_OPEN ( vp , fmode , cred , td , fp ) ) != 0 ) return ( error ) ; if ( fmode & ( O_EXLOCK | O_SHLOCK ) ) { KASSERT ( fp != NULL , ( " " ) ) ; lock_flags = VOP_ISLOCKED ( vp ) ; VOP_UNLOCK ( vp , 0 ) ; lf . l_whence = SEEK_SET ; lf . l_start = 0 ; lf . l_len = 0 ; if ( fmode & O_EXLOCK ) lf . l_type = F_WRLCK ; else lf . l_type = F_RDLCK ; type = F_FLOCK ; if ( ( fmode & FNONBLOCK ) == 0 ) type |= F_WAIT ; error = VOP_ADVLOCK ( vp , ( caddr_t ) fp , F_SETLK , & lf , type ) ; if ( error == 0 ) fp -> f_flag |= FHASLOCK ; vn_lock ( vp , lock_flags | LK_RETRY ) ; if ( error == 0 && vp -> v_iflag & VI_DOOMED ) error = ENOENT ; if ( error == 0 && accmode & VWRITE ) error = vn_writechk ( vp ) ; if ( error != 0 ) { fp -> f_flag |= FOPENFAILED ; fp -> f_vnode = vp ; if ( fp -> f_ops == & badfileops ) { fp -> f_type = DTYPE_VNODE ; fp -> f_ops = & vnops ; } vref ( vp ) ; } } if ( error == 0 && fmode & FWRITE ) { VOP_ADD_WRITECOUNT ( vp , 1 ) ; CTR3 ( KTR_VFS , " " , __func__ , vp , vp -> v_writecount ) ; } ASSERT_VOP_LOCKED ( vp , " " ) ; return ( error ) ; }
Common code for vnode open operations once a vnode is located.
Common code for vnode open operations once a vnode is located .
/*
		 * Another thread might have used this vnode as an
		 * executable while the vnode lock was dropped.
		 * Ensure the vnode is still able to be opened for
		 * writing after the lock has been obtained.
		 */