summaryrefslogtreecommitdiffstats
path: root/sys/fs/pseudofs
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2001-10-26 18:52:47 +0000
committerdes <des@FreeBSD.org>2001-10-26 18:52:47 +0000
commitdfb5c0da6e4852123fb12d6f6d2ba300c8c833f6 (patch)
treeaf5e5ac9126d6392810173ff252ad198769a9e44 /sys/fs/pseudofs
parent39b22ee16556aa5e491d4a88fd0f020f3cc5a963 (diff)
downloadFreeBSD-src-dfb5c0da6e4852123fb12d6f6d2ba300c8c833f6.zip
FreeBSD-src-dfb5c0da6e4852123fb12d6f6d2ba300c8c833f6.tar.gz
Add VOP_IOCTL support, and fix a bug that would cause a panic if a file or
symlink lacked a filler function.
Diffstat (limited to 'sys/fs/pseudofs')
-rw-r--r--sys/fs/pseudofs/pseudofs.h12
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c50
2 files changed, 58 insertions, 4 deletions
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 },
OpenPOWER on IntegriCloud