/* * Mount the per-process file descriptors (/dev/fd) */ int fdesc_mount(struct mount *mp, const char *path, void *data, size_t *data_len) { struct lwp *l = curlwp; int error = 0; struct vnode *rvp; if (mp->mnt_flag & MNT_GETARGS) { *data_len = 0; return 0; } /* * Update is a no-op */ if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp); if (error) return (error); rvp->v_type = VDIR; rvp->v_vflag |= VV_ROOT; mp->mnt_stat.f_namemax = FDESC_MAXNAMLEN; mp->mnt_flag |= MNT_LOCAL; mp->mnt_data = rvp; vfs_getnewfsid(mp); error = set_statvfs_info(path, UIO_USERSPACE, "fdesc", UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l); VOP_UNLOCK(rvp); return error; }
static int fdesc_get_ino_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **rvp) { struct fdesc_get_ino_args *a; int error; a = arg; error = fdesc_allocvp(a->ftype, a->fd_fd, a->ix, mp, rvp); fdrop(a->fp, a->td); return (error); }
/* * Mount the per-process file descriptors (/dev/fd) */ static int fdesc_mount(struct mount *mp) { int error = 0; struct fdescmount *fmp; struct vnode *rvp; /* * Update is a no-op */ if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) return (EOPNOTSUPP); fmp = malloc(sizeof(struct fdescmount), M_FDESCMNT, M_WAITOK); /* XXX */ /* * We need to initialize a few bits of our local mount point struct to * avoid confusion in allocvp. */ mp->mnt_data = (qaddr_t) fmp; fmp->flags = 0; error = fdesc_allocvp(Froot, -1, FD_ROOT, mp, &rvp); if (error) { free(fmp, M_FDESCMNT); mp->mnt_data = 0; return (error); } rvp->v_type = VDIR; rvp->v_vflag |= VV_ROOT; fmp->f_root = rvp; VOP_UNLOCK(rvp, 0); /* XXX -- don't mark as local to work around fts() problems */ /*mp->mnt_flag |= MNT_LOCAL;*/ MNT_ILOCK(mp); mp->mnt_kern_flag |= MNTK_MPSAFE; MNT_IUNLOCK(mp); vfs_getnewfsid(mp); vfs_mountedfrom(mp, "fdescfs"); return (0); }
/* * Mount the per-process file descriptors (/dev/fd) */ static int fdesc_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) { int error = 0; struct fdescmount *fmp; struct vnode *rvp; if (path == NULL) panic("fdesc_mount: cannot mount as root"); /* * Update is a no-op */ if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); vfs_add_vnodeops(mp, &fdesc_vnode_vops, &mp->mnt_vn_norm_ops); error = fdesc_allocvp(Froot, FD_ROOT, mp, &rvp); if (error) return (error); fmp = kmalloc(sizeof(struct fdescmount), M_FDESCMNT, M_WAITOK); /* XXX */ rvp->v_type = VDIR; vsetflags(rvp, VROOT); fmp->f_root = rvp; /* XXX -- don't mark as local to work around fts() problems */ /*mp->mnt_flag |= MNT_LOCAL;*/ mp->mnt_data = (qaddr_t) fmp; vfs_getnewfsid(mp); bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy("fdesc", mp->mnt_stat.f_mntfromname, sizeof("fdesc")); fdesc_statfs(mp, &mp->mnt_stat, cred); return (0); }
/* * vp is the current namei directory * ndp is the name to locate in that directory... * * fdesc_lookup(struct vnode *a_dvp, struct vnode **a_vpp, * struct componentname *a_cnp) */ static int fdesc_lookup(struct vop_old_lookup_args *ap) { struct componentname *cnp = ap->a_cnp; struct thread *td = cnp->cn_td; struct proc *p = td->td_proc; struct vnode **vpp = ap->a_vpp; struct vnode *dvp = ap->a_dvp; char *pname = cnp->cn_nameptr; int nlen = cnp->cn_namelen; int nfiles; u_int fd; int error; struct vnode *fvp; KKASSERT(p); nfiles = p->p_fd->fd_nfiles; if (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME) { error = EROFS; goto bad; } vn_unlock(dvp); if (cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; vref(dvp); vn_lock(dvp, LK_SHARED | LK_RETRY); return (0); } if (VTOFDESC(dvp)->fd_type != Froot) { error = ENOTDIR; goto bad; } fd = 0; /* the only time a leading 0 is acceptable is if it's "0" */ if (*pname == '0' && nlen != 1) { error = ENOENT; goto bad; } while (nlen--) { if (*pname < '0' || *pname > '9') { error = ENOENT; goto bad; } fd = 10 * fd + *pname++ - '0'; } if (fd >= nfiles || p->p_fd->fd_files[fd].fp == NULL) { error = EBADF; goto bad; } error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); if (error) goto bad; VTOFDESC(fvp)->fd_fd = fd; vn_lock(fvp, LK_SHARED | LK_RETRY); *vpp = fvp; return (0); bad: vn_lock(dvp, LK_SHARED | LK_RETRY); *vpp = NULL; return (error); }