diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -203,8 +203,13 @@ fd->fd_type = ftype; fd->fd_fd = fd_fd; fd->fd_ix = ix; - if (ftype == Fdesc && fmp->flags & FMNT_LINRDLNKF) - vp->v_vflag |= VV_READLINK; + if (ftype == Fdesc) { + if ((fmp->flags & FMNT_LINRDLNKF) != 0) + vp->v_vflag |= VV_READLINK; + VI_LOCK(vp); + vp->v_irflag |= VIRF_FDESCFS; + VI_UNLOCK(vp); + } error = insmntque1(vp, mp, fdesc_insmntque_dtr, NULL); if (error != 0) { *vpp = NULLVP; @@ -380,11 +385,18 @@ static int fdesc_open(struct vop_open_args *ap) { - struct vnode *vp = ap->a_vp; + struct vnode *vp; + struct file *fp; + struct thread *td; + int error, error1, fd, locked; + + vp = ap->a_vp; if (VTOFDESC(vp)->fd_type == Froot) return (0); + fd = VTOFDESC(vp)->fd_fd; + /* * XXX Kludge: set td->td_proc->p_dupfd to contain the value of the file * descriptor being sought for duplication. The error return ensures @@ -393,8 +405,27 @@ * Other callers of vn_open or VOP_OPEN will simply report the * error. */ - ap->a_td->td_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ - return (ENODEV); + ap->a_td->td_dupfd = fd; + + error = ENODEV; + if ((ap->a_mode & O_DIRECTORY) != 0) { + locked = VOP_ISLOCKED(vp); + VOP_UNLOCK(vp); + td = curthread; + error1 = fget_unlocked(td->td_proc->p_fd, fd, + &cap_no_rights, &fp); + if (error1 == 0) { + if (fp->f_type != DTYPE_VNODE || + fp->f_vnode->v_type != VDIR) + error = ENOTDIR; + fdrop(fp, td); + } else { + error = error1; + } + vn_lock(vp, locked | LK_RETRY); + } + + return (error); } static int diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -391,7 +391,8 @@ } if (vp->v_type == VSOCK) return (EOPNOTSUPP); - if (vp->v_type != VDIR && fmode & O_DIRECTORY) + if (vp->v_type != VDIR && (fmode & O_DIRECTORY) != 0 && + (vp->v_irflag & VIRF_FDESCFS) == 0) return (ENOTDIR); accmode = 0; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -251,6 +251,7 @@ #define VIRF_PGREAD 0x0002 /* Direct reads from the page cache are permitted, never cleared once set */ #define VIRF_MOUNTPOINT 0x0004 /* This vnode is mounted on */ +#define VIRF_FDESCFS 0x0008 /* Fdescfs, special handling on open */ #define VI_TEXT_REF 0x0001 /* Text ref grabbed use ref */ #define VI_MOUNT 0x0002 /* Mount in progress */