From dfb5c0da6e4852123fb12d6f6d2ba300c8c833f6 Mon Sep 17 00:00:00 2001 From: des Date: Fri, 26 Oct 2001 18:52:47 +0000 Subject: Add VOP_IOCTL support, and fix a bug that would cause a panic if a file or symlink lacked a filler function. --- sys/fs/pseudofs/pseudofs.h | 12 +++++++++- sys/fs/pseudofs/pseudofs_vnops.c | 50 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 58 insertions(+), 4 deletions(-) (limited to 'sys/fs/pseudofs') diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h index ab8a542..fdcde59 100644 --- a/sys/fs/pseudofs/pseudofs.h +++ b/sys/fs/pseudofs/pseudofs.h @@ -109,6 +109,16 @@ struct pfs_bitmap; /* opaque */ typedef int (*pfs_vis_t)(PFS_VIS_ARGS); /* + * Ioctl callback + */ +#define PFS_IOCTL_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn, \ + unsigned long cmd, caddr_t data +#define PFS_IOCTL_PROTO(name) \ + int name(PFS_IOCTL_ARGS); +typedef int (*pfs_ioctl_t)(PFS_IOCTL_ARGS); + +/* * pfs_info: describes a pseudofs instance */ struct pfs_info { @@ -135,7 +145,7 @@ struct pfs_node { } u1; #define pn_func u1._pn_func #define pn_nodes u1._pn_nodes - /*pfs_ioctl_t pn_ioctl;*/ + pfs_ioctl_t pn_ioctl; pfs_attr_t pn_attr; pfs_vis_t pn_vis; void *pn_data; diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index 4c675aec..91614d6 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -183,6 +183,49 @@ pfs_getattr(struct vop_getattr_args *va) } /* + * Perform an ioctl + */ +static int +pfs_ioctl(struct vop_ioctl_args *va) +{ + struct vnode *vn = va->a_vp; + struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; + struct pfs_node *pn = pvd->pvd_pn; + struct proc *proc = NULL; + int error; + + PFS_TRACE(("%s: %d", pn->pn_name, va->a_com)); + + if (vn->v_type != VREG) + PFS_RETURN (EINVAL); + + if (pn->pn_ioctl == NULL) + PFS_RETURN (ENOTTY); + + /* + * This is necessary because either process' privileges may + * have changed since the open() call. + */ + if (!pfs_visible(curthread, pn, pvd->pvd_pid)) + PFS_RETURN (EIO); + + /* XXX duplicates bits of pfs_visible() */ + if (pvd->pvd_pid != NO_PID) { + if ((proc = pfind(pvd->pvd_pid)) == NULL) + PFS_RETURN (EIO); + _PHOLD(proc); + PROC_UNLOCK(proc); + } + + error = (pn->pn_ioctl)(curthread, proc, pn, va->a_command, va->a_data); + + if (proc != NULL) + PRELE(proc); + + PFS_RETURN (error); +} + +/* * Look up a file or directory */ static int @@ -343,7 +386,7 @@ pfs_read(struct vop_read_args *va) PFS_RETURN (EBADF); if (pn->pn_func == NULL) - error = EIO; + PFS_RETURN (EIO); /* * This is necessary because either process' privileges may @@ -545,7 +588,7 @@ pfs_readlink(struct vop_readlink_args *va) PFS_RETURN (EINVAL); if (pn->pn_func == NULL) - error = EIO; + PFS_RETURN (EIO); if (pvd->pvd_pid != NO_PID) { if ((proc = pfind(pvd->pvd_pid)) == NULL) @@ -625,7 +668,7 @@ pfs_write(struct vop_read_args *va) PFS_RETURN (EBADF); if (pn->pn_func == NULL) - error = EIO; + PFS_RETURN (EIO); /* * This is necessary because either process' privileges may @@ -680,6 +723,7 @@ static struct vnodeopv_entry_desc pfs_vnodeop_entries[] = { { &vop_close_desc, (vop_t *)pfs_close }, { &vop_create_desc, (vop_t *)pfs_badop }, { &vop_getattr_desc, (vop_t *)pfs_getattr }, + { &vop_ioctl_desc, (vop_t *)pfs_ioctl }, { &vop_link_desc, (vop_t *)pfs_badop }, { &vop_lookup_desc, (vop_t *)pfs_lookup }, { &vop_mkdir_desc, (vop_t *)pfs_badop }, -- cgit v1.1