diff --git a/sys/miscfs/Makefile b/sys/miscfs/Makefile index 97fa1dc856c8..e57503815cce 100644 --- a/sys/miscfs/Makefile +++ b/sys/miscfs/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.6 2004/11/11 01:40:32 christos Exp $ +# $NetBSD: Makefile,v 1.7 2004/11/11 18:57:21 jdolecek Exp $ SUBDIR= fdesc fifofs genfs kernfs nullfs overlay portal -SUBDIR+= procfs ptyfs specfs syncfs umapfs +SUBDIR+= procfs specfs syncfs umapfs INCSDIR= /usr/include/miscfs diff --git a/sys/miscfs/ptyfs/Makefile b/sys/miscfs/ptyfs/Makefile deleted file mode 100644 index fa3b7ca86062..000000000000 --- a/sys/miscfs/ptyfs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $NetBSD: Makefile,v 1.1 2004/11/11 01:40:32 christos Exp $ - -INCSDIR= /usr/include/miscfs/ptyfs - -INCS= ptyfs.h - -.include diff --git a/sys/miscfs/ptyfs/files.ptyfs b/sys/miscfs/ptyfs/files.ptyfs deleted file mode 100644 index 51ef6a958f02..000000000000 --- a/sys/miscfs/ptyfs/files.ptyfs +++ /dev/null @@ -1,7 +0,0 @@ -# $NetBSD: files.ptyfs,v 1.1 2004/11/11 01:40:32 christos Exp $ - -deffs fs_ptyfs.h PTYFS # XXX - -file miscfs/ptyfs/ptyfs_subr.c ptyfs -file miscfs/ptyfs/ptyfs_vfsops.c ptyfs -file miscfs/ptyfs/ptyfs_vnops.c ptyfs diff --git a/sys/miscfs/ptyfs/ptyfs.h b/sys/miscfs/ptyfs/ptyfs.h deleted file mode 100644 index 08865883062d..000000000000 --- a/sys/miscfs/ptyfs/ptyfs.h +++ /dev/null @@ -1,141 +0,0 @@ -/* $NetBSD: ptyfs.h,v 1.2 2004/11/11 05:46:10 christos Exp $ */ - -/* - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs.h 8.9 (Berkeley) 5/14/95 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs.h 8.9 (Berkeley) 5/14/95 - */ - -#ifdef _KERNEL -/* - * The different types of node in a ptyfs filesystem - */ -typedef enum { - PTYFSpts, /* The slave side of a pty */ - PTYFSptc, /* The controlling side of a pty */ - PTYFSroot, /* the filesystem root */ -} ptyfstype; - -/* - * control data for the proc file system. - */ -struct ptyfsnode { - LIST_ENTRY(ptyfsnode) ptyfs_hash; /* hash chain */ - struct vnode *ptyfs_vnode; /* vnode associated with this ptyfsnode */ - ptyfstype ptyfs_type; /* type of ptyfs node */ - int ptyfs_pty; /* the pty index */ - u_long ptyfs_fileno; /* unique file id */ - int ptyfs_flag; /* status flag for times */ -#define PTYFS_ACCESS 1 -#define PTYFS_MODIFY 2 -#define PTYFS_CHANGE 4 - /* Attribute information */ - uid_t ptyfs_uid; - gid_t ptyfs_gid; - mode_t ptyfs_mode; - int ptyfs_flags; - struct timespec ptyfs_ctime, ptyfs_mtime, ptyfs_atime, ptyfs_birthtime; -}; - -#endif /* _KERNEL */ - -/* - * Kernel stuff follows - */ -#ifdef _KERNEL - -#define UIO_MX 32 - -#define PTYFS_FILENO(pty, type) \ - ((((uint32_t)type) << 30) | (pty + 1)) - -#define PTYFS_MAKEDEV(ptyfs) \ - pty_makedev((ptyfs)->ptyfs_type == PTYFSpts ? 't' : 'p', (ptyfs)->ptyfs_pty) - -/* - * Convert between ptyfsnode vnode - */ -#define VTOPTYFS(vp) ((struct ptyfsnode *)(vp)->v_data) -#define PTYFSTOV(ptyfs) ((ptyfs)->ptyfs_vnode) - -int ptyfs_freevp(struct vnode *); -int ptyfs_allocvp(struct mount *, struct vnode **, ptyfstype, int, - struct proc *); -void ptyfs_hashinit(void); -void ptyfs_hashreinit(void); -void ptyfs_hashdone(void); - -extern int (**ptyfs_vnodeop_p)(void *); -extern struct vfsops ptyfs_vfsops; - -int ptyfs_root(struct mount *, struct vnode **); - -#ifdef SYSCTL_SETUP_PROTO -SYSCTL_SETUP_PROTO(sysctl_vfs_ptyfs_setup); -#endif /* SYSCTL_SETUP_PROTO */ -#endif /* _KERNEL */ diff --git a/sys/miscfs/ptyfs/ptyfs_subr.c b/sys/miscfs/ptyfs/ptyfs_subr.c deleted file mode 100644 index 4ed50f180fc4..000000000000 --- a/sys/miscfs/ptyfs/ptyfs_subr.c +++ /dev/null @@ -1,421 +0,0 @@ -/* $NetBSD: ptyfs_subr.c,v 1.1 2004/11/11 01:40:32 christos Exp $ */ - -/* - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ptyfs_subr.c 8.6 (Berkeley) 5/14/95 - */ - -/* - * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. - * Copyright (c) 1993 Jan-Simon Pendry - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.1 2004/11/11 01:40:32 christos Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static struct lock ptyfs_hashlock; - -static LIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_used_tbl, *ptyfs_free_tbl; -static u_long ptyfs_used_mask, ptyfs_free_mask; /* size of hash table - 1 */ -static struct simplelock ptyfs_used_slock, ptyfs_free_slock; - -static void ptyfs_getinfo(struct ptyfsnode *, struct proc *); - -static void ptyfs_hashins(struct ptyfsnode *); -static void ptyfs_hashrem(struct ptyfsnode *); - -static struct vnode *ptyfs_used_get(ptyfstype, int, struct mount *); -static struct ptyfsnode *ptyfs_free_get(ptyfstype, int, struct proc *); - -static void ptyfs_rehash(struct simplelock *, struct ptyfs_hashhead **, - u_long *); - -#define PTYHASH(type, pty, mask) (PTYFS_FILENO(type, pty) % (mask + 1)) - - -static void -ptyfs_getinfo(struct ptyfsnode *ptyfs, struct proc *p) -{ - extern struct ptm_pty *ptyfs_save_ptm, ptm_ptyfspty; - - if (ptyfs->ptyfs_type == PTYFSroot) { - ptyfs->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| - S_IROTH|S_IXOTH; - goto out; - } else - ptyfs->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| - S_IROTH|S_IWOTH; - - if (ptyfs_save_ptm != NULL && ptyfs_save_ptm != &ptm_ptyfspty) { - int error; - struct nameidata nd; - char ttyname[64]; - struct ucred *cred; - struct vattr va; - /* - * We support traditional ptys, so we copy the info - * from the inode - */ - if ((error = (*ptyfs_save_ptm->makename)( - ptyfs_save_ptm, ttyname, sizeof(ttyname), - ptyfs->ptyfs_pty, ptyfs->ptyfs_type == PTYFSpts ? 't' - : 'p')) != 0) - goto out; - NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, ttyname, - p); - if ((error = namei(&nd)) != 0) - goto out; - cred = crget(); - error = VOP_GETATTR(nd.ni_vp, &va, cred, p); - crfree(cred); - VOP_UNLOCK(nd.ni_vp, 0); - vrele(nd.ni_vp); - if (error) - goto out; - ptyfs->ptyfs_uid = va.va_uid; - ptyfs->ptyfs_gid = va.va_gid; - ptyfs->ptyfs_mode = va.va_mode; - ptyfs->ptyfs_flags = va.va_flags; - ptyfs->ptyfs_birthtime = va.va_birthtime; - ptyfs->ptyfs_ctime = va.va_ctime; - ptyfs->ptyfs_mtime = va.va_mtime; - ptyfs->ptyfs_atime = va.va_atime; - return; - } -out: - ptyfs->ptyfs_uid = ptyfs->ptyfs_gid = 0; - TIMEVAL_TO_TIMESPEC(&time, &ptyfs->ptyfs_ctime); - ptyfs->ptyfs_birthtime = ptyfs->ptyfs_mtime = - ptyfs->ptyfs_atime = ptyfs->ptyfs_ctime; - ptyfs->ptyfs_flags = 0; -} - - -/* - * allocate a ptyfsnode/vnode pair. the vnode is - * referenced, and locked. - * - * the pid, ptyfs_type, and mount point uniquely - * identify a ptyfsnode. the mount point is needed - * because someone might mount this filesystem - * twice. - * - * all ptyfsnodes are maintained on a singly-linked - * list. new nodes are only allocated when they cannot - * be found on this list. entries on the list are - * removed when the vfs reclaim entry is called. - * - * a single lock is kept for the entire list. this is - * needed because the getnewvnode() function can block - * waiting for a vnode to become free, in which case there - * may be more than one ptyess trying to get the same - * vnode. this lock is only taken if we are going to - * call getnewvnode, since the kernel itself is single-threaded. - * - * if an entry is found on the list, then call vget() to - * take a reference. this is done because there may be - * zero references to it and so it needs to removed from - * the vnode free list. - */ -int -ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty, - struct proc *p) -{ - struct ptyfsnode *ptyfs; - struct vnode *vp, *nvp; - int error; - - do { - if ((*vpp = ptyfs_used_get(type, pty, mp)) != NULL) - return 0; - } while (lockmgr(&ptyfs_hashlock, LK_EXCLUSIVE|LK_SLEEPFAIL, 0)); - - if ((error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, &vp)) != 0) { - *vpp = NULL; - lockmgr(&ptyfs_hashlock, LK_RELEASE, NULL); - return error; - } - - vp->v_data = ptyfs = ptyfs_free_get(type, pty, p); - ptyfs->ptyfs_vnode = vp; - - switch (type) { - case PTYFSroot: /* /pts = dr-xr-xr-x */ - vp->v_type = VDIR; - vp->v_flag = VROOT; - break; - - case PTYFSpts: /* /pts/N = cxxxxxxxxx */ - case PTYFSptc: /* controlling side = cxxxxxxxxx */ - vp->v_type = VCHR; - if ((nvp = checkalias(vp, PTYFS_MAKEDEV(ptyfs), mp)) != NULL) { - /* - * Discard unneeded vnode, but save its inode. - */ - nvp->v_data = vp->v_data; - vp->v_data = NULL; - /* XXX spec_vnodeops has no locking, do it explicitly */ - VOP_UNLOCK(vp, 0); - vp->v_op = spec_vnodeop_p; - vp->v_flag &= ~VLOCKSWORK; - vrele(vp); - vgone(vp); - lockmgr(&nvp->v_lock, LK_EXCLUSIVE, &nvp->v_interlock); - /* - * Reinitialize aliased inode. - */ - vp = nvp; - ptyfs->ptyfs_vnode = vp; - } - break; - default: - panic("ptyfs_allocvp"); - } - - ptyfs_hashins(ptyfs); - uvm_vnp_setsize(vp, 0); - lockmgr(&ptyfs_hashlock, LK_RELEASE, NULL); - - *vpp = vp; - return 0; -} - -int -ptyfs_freevp(struct vnode *vp) -{ - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - ptyfs_hashrem(ptyfs); - vp->v_data = NULL; - return 0; -} - -/* - * Initialize ptyfsnode hash table. - */ -void -ptyfs_hashinit(void) -{ - lockinit(&ptyfs_hashlock, PINOD, "ptyfs_hashlock", 0, 0); - ptyfs_used_tbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, - M_WAITOK, &ptyfs_used_mask); - ptyfs_free_tbl = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, - M_WAITOK, &ptyfs_free_mask); - simple_lock_init(&ptyfs_used_slock); - simple_lock_init(&ptyfs_free_slock); -} - -void -ptyfs_hashreinit(void) -{ - ptyfs_rehash(&ptyfs_used_slock, &ptyfs_used_tbl, &ptyfs_used_mask); - ptyfs_rehash(&ptyfs_free_slock, &ptyfs_free_tbl, &ptyfs_free_mask); -} - -static void -ptyfs_rehash(struct simplelock *hlock, struct ptyfs_hashhead **hhead, - u_long *hmask) -{ - struct ptyfsnode *pp; - struct ptyfs_hashhead *oldhash, *hash; - u_long i, oldmask, mask, val; - - hash = hashinit(desiredvnodes / 4, HASH_LIST, M_UFSMNT, M_WAITOK, - &mask); - - simple_lock(hlock); - oldhash = *hhead; - oldmask = *hmask; - *hhead = hash; - *hmask = mask; - for (i = 0; i <= oldmask; i++) { - while ((pp = LIST_FIRST(&oldhash[i])) != NULL) { - LIST_REMOVE(pp, ptyfs_hash); - val = PTYHASH(pp->ptyfs_type, pp->ptyfs_pty, - ptyfs_used_mask); - LIST_INSERT_HEAD(&hash[val], pp, ptyfs_hash); - } - } - simple_unlock(hlock); - hashdone(oldhash, M_UFSMNT); -} - -/* - * Free ptyfsnode hash table. - */ -void -ptyfs_hashdone(void) -{ - hashdone(ptyfs_used_tbl, M_UFSMNT); - hashdone(ptyfs_free_tbl, M_UFSMNT); -} - -/* - * Get a ptyfsnode from the free table, or allocate one. - * Removes the node from the free table. - */ -struct ptyfsnode * -ptyfs_free_get(ptyfstype type, int pty, struct proc *p) -{ - struct ptyfs_hashhead *ppp; - struct ptyfsnode *pp; - - simple_lock(&ptyfs_free_slock); - ppp = &ptyfs_free_tbl[PTYHASH(type, pty, ptyfs_free_mask)]; - LIST_FOREACH(pp, ppp, ptyfs_hash) { - if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) { - LIST_REMOVE(pp, ptyfs_hash); - simple_unlock(&ptyfs_free_slock); - return pp; - } - } - simple_unlock(&ptyfs_free_slock); - - MALLOC(pp, void *, sizeof(struct ptyfsnode), M_TEMP, M_WAITOK); - pp->ptyfs_pty = pty; - pp->ptyfs_type = type; - pp->ptyfs_fileno = PTYFS_FILENO(pty, type); - ptyfs_getinfo(pp, p); - return pp; -} - -struct vnode * -ptyfs_used_get(ptyfstype type, int pty, struct mount *mp) -{ - struct ptyfs_hashhead *ppp; - struct ptyfsnode *pp; - struct vnode *vp; - -loop: - simple_lock(&ptyfs_used_slock); - ppp = &ptyfs_used_tbl[PTYHASH(type, pty, ptyfs_used_mask)]; - LIST_FOREACH(pp, ppp, ptyfs_hash) { - vp = PTYFSTOV(pp); - if (pty == pp->ptyfs_pty && pp->ptyfs_type == type && - vp->v_mount == mp) { - simple_lock(&vp->v_interlock); - simple_unlock(&ptyfs_used_slock); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) - goto loop; - return vp; - } - } - simple_unlock(&ptyfs_used_slock); - return NULL; -} - -/* - * Insert the ptyfsnode into the used table and lock it. - */ -static void -ptyfs_hashins(struct ptyfsnode *pp) -{ - struct ptyfs_hashhead *ppp; - - /* lock the ptyfsnode, then put it on the appropriate hash list */ - lockmgr(&pp->ptyfs_vnode->v_lock, LK_EXCLUSIVE, NULL); - - simple_lock(&ptyfs_used_slock); - ppp = &ptyfs_used_tbl[PTYHASH(pp->ptyfs_type, pp->ptyfs_pty, - ptyfs_used_mask)]; - LIST_INSERT_HEAD(ppp, pp, ptyfs_hash); - simple_unlock(&ptyfs_used_slock); -} - -/* - * Remove the ptyfsnode from the used table, and add it to the free table - */ -static void -ptyfs_hashrem(struct ptyfsnode *pp) -{ - struct ptyfs_hashhead *ppp; - - simple_lock(&ptyfs_used_slock); - LIST_REMOVE(pp, ptyfs_hash); - simple_unlock(&ptyfs_used_slock); - - simple_lock(&ptyfs_free_slock); - ppp = &ptyfs_free_tbl[PTYHASH(pp->ptyfs_type, pp->ptyfs_pty, - ptyfs_free_mask)]; - LIST_INSERT_HEAD(ppp, pp, ptyfs_hash); - simple_unlock(&ptyfs_free_slock); -} diff --git a/sys/miscfs/ptyfs/ptyfs_vfsops.c b/sys/miscfs/ptyfs/ptyfs_vfsops.c deleted file mode 100644 index 628823c171d8..000000000000 --- a/sys/miscfs/ptyfs/ptyfs_vfsops.c +++ /dev/null @@ -1,354 +0,0 @@ -/* $NetBSD: ptyfs_vfsops.c,v 1.2 2004/11/11 05:46:10 christos Exp $ */ - -/* - * Copyright (c) 1992, 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software donated to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -/* - * Pseudo-tty Filesystem - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.2 2004/11/11 05:46:10 christos Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -MALLOC_DEFINE(M_PTYFSMNT, "ptyfs mount", "ptyfs mount structures"); - -void ptyfs_init(void); -void ptyfs_reinit(void); -void ptyfs_done(void); -int ptyfs_mount(struct mount *, const char *, void *, struct nameidata *, - struct proc *); -int ptyfs_start(struct mount *, int, struct proc *); -int ptyfs_unmount(struct mount *, int, struct proc *); -int ptyfs_statvfs(struct mount *, struct statvfs *, struct proc *); -int ptyfs_quotactl(struct mount *, int, uid_t, void *, struct proc *); -int ptyfs_sync(struct mount *, int, struct ucred *, struct proc *); -int ptyfs_vget(struct mount *, ino_t, struct vnode **); -int ptyfs_fhtovp(struct mount *, struct fid *, struct vnode **); -int ptyfs_checkexp(struct mount *, struct mbuf *, int *, struct ucred **); -int ptyfs_vptofh(struct vnode *, struct fid *); - -static int ptyfs__allocvp(struct ptm_pty *, struct proc *, struct vnode **, - dev_t, char); -static int ptyfs__makename(struct ptm_pty *, char *, size_t, dev_t, char); - -/* - * ptm glue: When we mount, we make ptm point to us. - */ -struct ptm_pty *ptyfs_save_ptm; - -struct ptm_pty ptm_ptyfspty = { - ptyfs__allocvp, - ptyfs__makename, - NULL -}; - -static int -ptyfs__makename(struct ptm_pty *pt, char *buf, size_t bufsiz, dev_t dev, - char ms) -{ - struct mount *mp = pt->arg; - size_t len; - - switch (ms) { - case 'p': - /* We don't provide access to the master, should we? */ - len = snprintf(buf, bufsiz, "/dev/null"); - break; - case 't': - len = snprintf(buf, bufsiz, "%s/%d", mp->mnt_stat.f_mntonname, - minor(dev)); - break; - default: - return EINVAL; - } - - return len >= bufsiz ? ENOSPC : 0; -} - -static int -/*ARGSUSED*/ -ptyfs__allocvp(struct ptm_pty *pt, struct proc *p, struct vnode **vpp, - dev_t dev, char ms) -{ - struct mount *mp = pt->arg; - ptyfstype type; - - switch (ms) { - case 'p': - type = PTYFSptc; - break; - case 't': - type = PTYFSpts; - break; - default: - return EINVAL; - } - - return ptyfs_allocvp(mp, vpp, type, minor(dev), p); -} - -void -ptyfs_init(void) -{ -#ifdef _LKM - malloc_type_attach(M_PTYFSMNT); -#endif - ptyfs_hashinit(); -} - -void -ptyfs_reinit(void) -{ - ptyfs_hashreinit(); -} - -void -ptyfs_done(void) -{ -#ifdef _LKM - malloc_type_detach(M_PTYFSMNT); -#endif - ptyfs_hashdone(); -} - -/* - * Mount the Pseudo tty params filesystem - */ -int -ptyfs_mount(struct mount *mp, const char *path, void *data, - struct nameidata *ndp, struct proc *p) -{ - int error = 0; - - if (UIO_MX & (UIO_MX - 1)) { - log(LOG_ERR, "ptyfs: invalid directory entry size"); - return EINVAL; - } - - if (mp->mnt_flag & MNT_GETARGS) - return 0; - /* - * Update is a no-op - */ - if (mp->mnt_flag & MNT_UPDATE) - return EOPNOTSUPP; - - mp->mnt_data = NULL; - mp->mnt_flag |= MNT_LOCAL; - vfs_getnewfsid(mp); - - if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", - UIO_SYSSPACE, mp, p)) != 0) { - return error; - } - - /* Point pty access to us */ - if (ptyfs_save_ptm != NULL) - return EBUSY; - - ptm_ptyfspty.arg = mp; - ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); - return 0; -} - -/*ARGSUSED*/ -int -ptyfs_start(struct mount *mp, int flags, struct proc *p) -{ - return 0; -} - -/*ARGSUSED*/ -int -ptyfs_unmount(struct mount *mp, int mntflags, struct proc *p) -{ - int error; - int flags = 0; - - if (mntflags & MNT_FORCE) - flags |= FORCECLOSE; - - if ((error = vflush(mp, 0, flags)) != 0) - return (error); - - /* Restore where pty access was pointing */ - ptm_ptyfspty.arg = NULL; - (void)pty_sethandler(ptyfs_save_ptm); - ptyfs_save_ptm = NULL; - /* - * Finally, throw away the ptyfs_mount structure - */ - return 0; -} - -int -ptyfs_root(struct mount *mp, struct vnode **vpp) -{ - /* setup "." */ - return ptyfs_allocvp(mp, vpp, PTYFSroot, 0, NULL); -} - -/*ARGSUSED*/ -int -ptyfs_quotactl(struct mount *mp, int cmd, uid_t uid, void *arg, struct proc *p) -{ - return EOPNOTSUPP; -} - -/*ARGSUSED*/ -int -ptyfs_statvfs(struct mount *mp, struct statvfs *sbp, struct proc *p) -{ - sbp->f_bsize = DEV_BSIZE; - sbp->f_frsize = DEV_BSIZE; - sbp->f_iosize = DEV_BSIZE; - sbp->f_blocks = 2; /* 1K to keep df happy */ - sbp->f_bfree = 0; - sbp->f_bavail = 0; - sbp->f_bresvd = 0; - sbp->f_files = 1024; /* XXX lie */ - sbp->f_ffree = 128; /* XXX lie */ - sbp->f_favail = 128; /* XXX lie */ - sbp->f_fresvd = 0; - sbp->f_namemax = MAXNAMLEN; - copy_statvfs_info(sbp, mp); - return 0; -} - -/*ARGSUSED*/ -int -ptyfs_sync(struct mount *mp, int waitfor, struct ucred *uc, struct proc *p) -{ - return 0; -} - -/* - * Kernfs flat namespace lookup. - * Currently unsupported. - */ -/*ARGSUSED*/ -int -ptyfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) -{ - return EOPNOTSUPP; -} - -/*ARGSUSED*/ -int -ptyfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) -{ - return EOPNOTSUPP; -} - -/*ARGSUSED*/ -int -ptyfs_checkexp(struct mount *mp, struct mbuf *mb, int *wh, struct ucred **anon) -{ - return EOPNOTSUPP; -} - -SYSCTL_SETUP(sysctl_vfs_ptyfs_setup, "sysctl vfs.ptyfs subtree setup") -{ - - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "vfs", NULL, - NULL, 0, NULL, 0, - CTL_VFS, CTL_EOL); - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT, - CTLTYPE_NODE, "ptyfs", - SYSCTL_DESCR("Pty file system"), - NULL, 0, NULL, 0, - CTL_VFS, 23, CTL_EOL); - /* - * XXX the "23" above could be dynamic, thereby eliminating - * one more instance of the "number to vfs" mapping problem, - * but "23" is the order as taken from sys/mount.h - */ -} - - -/*ARGSUSED*/ -int -ptyfs_vptofh(struct vnode *vp, struct fid *fhp) -{ - return EOPNOTSUPP; -} - -extern const struct vnodeopv_desc ptyfs_vnodeop_opv_desc; - -const struct vnodeopv_desc * const ptyfs_vnodeopv_descs[] = { - &ptyfs_vnodeop_opv_desc, - NULL, -}; - -struct vfsops ptyfs_vfsops = { - MOUNT_PTYFS, - ptyfs_mount, - ptyfs_start, - ptyfs_unmount, - ptyfs_root, - ptyfs_quotactl, - ptyfs_statvfs, - ptyfs_sync, - ptyfs_vget, - ptyfs_fhtovp, - ptyfs_vptofh, - ptyfs_init, - ptyfs_reinit, - ptyfs_done, - NULL, - NULL, /* vfs_mountroot */ - ptyfs_checkexp, - (int (*)(struct mount *, struct vnode *, struct timespec *))eopnotsupp, - ptyfs_vnodeopv_descs, -}; diff --git a/sys/miscfs/ptyfs/ptyfs_vnops.c b/sys/miscfs/ptyfs/ptyfs_vnops.c deleted file mode 100644 index 4df998496e23..000000000000 --- a/sys/miscfs/ptyfs/ptyfs_vnops.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* $NetBSD: ptyfs_vnops.c,v 1.1 2004/11/11 01:40:32 christos Exp $ */ - -/* - * Copyright (c) 1993, 1995 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 - */ - -/* - * Copyright (c) 1993 Jan-Simon Pendry - * - * This code is derived from software contributed to Berkeley by - * Jan-Simon Pendry. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 - */ - -/* - * ptyfs vnode interface - */ - -#include -__KERNEL_RCSID(0, "$NetBSD: ptyfs_vnops.c,v 1.1 2004/11/11 01:40:32 christos Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* for PAGE_SIZE */ - -#include - -#include -#include -#include - -/* - * Vnode Operations. - * - */ - -int ptyfs_lookup (void *); -#define ptyfs_create genfs_eopnotsupp -#define ptyfs_mknod genfs_eopnotsupp -int ptyfs_open (void *); -int ptyfs_close (void *); -int ptyfs_access (void *); -int ptyfs_getattr (void *); -int ptyfs_setattr (void *); -int ptyfs_read (void *); -int ptyfs_write (void *); -#define ptyfs_fcntl genfs_fcntl -int ptyfs_ioctl (void *); -int ptyfs_poll (void *); -int ptyfs_kqfilter (void *); -#define ptyfs_revoke genfs_revoke -#define ptyfs_mmap genfs_eopnotsupp -#define ptyfs_fsync genfs_nullop -#define ptyfs_seek genfs_nullop -#define ptyfs_remove genfs_eopnotsupp -#define ptyfs_link genfs_abortop -#define ptyfs_rename genfs_eopnotsupp -#define ptyfs_mkdir genfs_eopnotsupp -#define ptyfs_rmdir genfs_eopnotsupp -#define ptyfs_symlink genfs_abortop -int ptyfs_readdir (void *); -#define ptyfs_readlink genfs_eopnotsupp -#define ptyfs_abortop genfs_abortop -int ptyfs_inactive (void *); -int ptyfs_reclaim (void *); -#define ptyfs_lock genfs_lock -#define ptyfs_unlock genfs_unlock -#define ptyfs_bmap genfs_badop -#define ptyfs_strategy genfs_badop -int ptyfs_print (void *); -int ptyfs_pathconf (void *); -#define ptyfs_islocked genfs_islocked -#define ptyfs_advlock genfs_einval -#define ptyfs_blkatoff genfs_eopnotsupp -#define ptyfs_valloc genfs_eopnotsupp -#define ptyfs_vfree genfs_nullop -#define ptyfs_truncate genfs_eopnotsupp -int ptyfs_update (void *); -#define ptyfs_bwrite genfs_eopnotsupp -#define ptyfs_putpages genfs_null_putpages - -static int ptyfs_chown(struct vnode *, uid_t, gid_t, struct ucred *, - struct proc *); -static int ptyfs_chmod(struct vnode *, mode_t, struct ucred *, struct proc *); -static void ptyfs_time(struct ptyfsnode *, struct timespec *, - struct timespec *); -static int atoi(const char *, size_t); -static u_int digits(u_int); - -extern const struct cdevsw pts_cdevsw, ptc_cdevsw; - -/* - * ptyfs vnode operations. - */ -int (**ptyfs_vnodeop_p)(void *); -const struct vnodeopv_entry_desc ptyfs_vnodeop_entries[] = { - { &vop_default_desc, vn_default_error }, - { &vop_lookup_desc, ptyfs_lookup }, /* lookup */ - { &vop_create_desc, ptyfs_create }, /* create */ - { &vop_mknod_desc, ptyfs_mknod }, /* mknod */ - { &vop_open_desc, ptyfs_open }, /* open */ - { &vop_close_desc, ptyfs_close }, /* close */ - { &vop_access_desc, ptyfs_access }, /* access */ - { &vop_getattr_desc, ptyfs_getattr }, /* getattr */ - { &vop_setattr_desc, ptyfs_setattr }, /* setattr */ - { &vop_read_desc, ptyfs_read }, /* read */ - { &vop_write_desc, ptyfs_write }, /* write */ - { &vop_ioctl_desc, ptyfs_ioctl }, /* ioctl */ - { &vop_fcntl_desc, ptyfs_fcntl }, /* fcntl */ - { &vop_poll_desc, ptyfs_poll }, /* poll */ - { &vop_kqfilter_desc, ptyfs_kqfilter }, /* kqfilter */ - { &vop_revoke_desc, ptyfs_revoke }, /* revoke */ - { &vop_mmap_desc, ptyfs_mmap }, /* mmap */ - { &vop_fsync_desc, ptyfs_fsync }, /* fsync */ - { &vop_seek_desc, ptyfs_seek }, /* seek */ - { &vop_remove_desc, ptyfs_remove }, /* remove */ - { &vop_link_desc, ptyfs_link }, /* link */ - { &vop_rename_desc, ptyfs_rename }, /* rename */ - { &vop_mkdir_desc, ptyfs_mkdir }, /* mkdir */ - { &vop_rmdir_desc, ptyfs_rmdir }, /* rmdir */ - { &vop_symlink_desc, ptyfs_symlink }, /* symlink */ - { &vop_readdir_desc, ptyfs_readdir }, /* readdir */ - { &vop_readlink_desc, ptyfs_readlink }, /* readlink */ - { &vop_abortop_desc, ptyfs_abortop }, /* abortop */ - { &vop_inactive_desc, ptyfs_inactive }, /* inactive */ - { &vop_reclaim_desc, ptyfs_reclaim }, /* reclaim */ - { &vop_lock_desc, ptyfs_lock }, /* lock */ - { &vop_unlock_desc, ptyfs_unlock }, /* unlock */ - { &vop_bmap_desc, ptyfs_bmap }, /* bmap */ - { &vop_strategy_desc, ptyfs_strategy }, /* strategy */ - { &vop_print_desc, ptyfs_print }, /* print */ - { &vop_islocked_desc, ptyfs_islocked }, /* islocked */ - { &vop_pathconf_desc, ptyfs_pathconf }, /* pathconf */ - { &vop_advlock_desc, ptyfs_advlock }, /* advlock */ - { &vop_blkatoff_desc, ptyfs_blkatoff }, /* blkatoff */ - { &vop_valloc_desc, ptyfs_valloc }, /* valloc */ - { &vop_vfree_desc, ptyfs_vfree }, /* vfree */ - { &vop_truncate_desc, ptyfs_truncate }, /* truncate */ - { &vop_update_desc, ptyfs_update }, /* update */ - { &vop_bwrite_desc, ptyfs_bwrite }, /* bwrite */ - { &vop_putpages_desc, ptyfs_putpages }, /* putpages */ - { NULL, NULL } -}; -const struct vnodeopv_desc ptyfs_vnodeop_opv_desc = - { &ptyfs_vnodeop_p, ptyfs_vnodeop_entries }; - -/* - * _inactive is called when the ptyfsnode - * is vrele'd and the reference count goes - * to zero. (vp) will be on the vnode free - * list, so to get it back vget() must be - * used. - * - * for ptyfs, check if the pty is still - * in use and if it isn't then just throw away - * the vnode by calling vgone(). - * - * (vp) is locked on entry, but must be unlocked on exit. - */ -int -ptyfs_inactive(void *v) -{ - struct vop_inactive_args /* { - struct vnode *a_vp; - struct proc *a_p; - } */ *ap = v; - struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); - - VOP_UNLOCK(ap->a_vp, 0); - if (pty_isfree(ptyfs->ptyfs_pty, 1)) - vgone(ap->a_vp); - - return 0; -} - -/* - * _reclaim is called when getnewvnode() - * wants to make use of an entry on the vnode - * free list. at this time the filesystem needs - * to free any private data and remove the node - * from any private lists. - */ -int -ptyfs_reclaim(void *v) -{ - struct vop_reclaim_args /* { - struct vnode *a_vp; - } */ *ap = v; - return ptyfs_freevp(ap->a_vp); -} - -/* - * Return POSIX pathconf information applicable to special devices. - */ -int -ptyfs_pathconf(void *v) -{ - struct vop_pathconf_args /* { - struct vnode *a_vp; - int a_name; - register_t *a_retval; - } */ *ap = v; - - switch (ap->a_name) { - case _PC_LINK_MAX: - *ap->a_retval = LINK_MAX; - return 0; - case _PC_MAX_CANON: - *ap->a_retval = MAX_CANON; - return 0; - case _PC_MAX_INPUT: - *ap->a_retval = MAX_INPUT; - return 0; - case _PC_PIPE_BUF: - *ap->a_retval = PIPE_BUF; - return 0; - case _PC_CHOWN_RESTRICTED: - *ap->a_retval = 1; - return 0; - case _PC_VDISABLE: - *ap->a_retval = _POSIX_VDISABLE; - return 0; - case _PC_SYNC_IO: - *ap->a_retval = 1; - return 0; - default: - return EINVAL; - } -} - -/* - * _print is used for debugging. - * just print a readable description - * of (vp). - */ -int -ptyfs_print(void *v) -{ - struct vop_print_args /* { - struct vnode *a_vp; - } */ *ap = v; - struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); - - printf("tag VT_PTYFS, type %d, pty %d\n", - ptyfs->ptyfs_type, ptyfs->ptyfs_pty); - return 0; -} - -/* - * Invent attributes for ptyfsnode (vp) and store - * them in (vap). - * Directories lengths are returned as zero since - * any real length would require the genuine size - * to be computed, and nothing cares anyway. - * - * this is relatively minimal for ptyfs. - */ -int -ptyfs_getattr(void *v) -{ - struct vop_getattr_args /* { - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); - struct vattr *vap = ap->a_vap; - struct timespec ts; - - TIMEVAL_TO_TIMESPEC(&time, &ts); - ptyfs_time(ptyfs, &ts, &ts); - - /* start by zeroing out the attributes */ - VATTR_NULL(vap); - - /* next do all the common fields */ - vap->va_type = ap->a_vp->v_type; - vap->va_fileid = ptyfs->ptyfs_fileno; - vap->va_gen = 0; - vap->va_flags = 0; - vap->va_nlink = 1; - vap->va_blocksize = PAGE_SIZE; - - vap->va_atime = ptyfs->ptyfs_atime; - vap->va_mtime = ptyfs->ptyfs_mtime; - vap->va_ctime = ptyfs->ptyfs_ctime; - vap->va_birthtime = ptyfs->ptyfs_birthtime; - vap->va_mode = ptyfs->ptyfs_mode; - vap->va_flags = ptyfs->ptyfs_flags; - vap->va_uid = ptyfs->ptyfs_uid; - vap->va_gid = ptyfs->ptyfs_gid; - - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - case PTYFSptc: - if (pty_isfree(ptyfs->ptyfs_pty, 1)) - return ENOENT; - vap->va_bytes = vap->va_size = digits(ptyfs->ptyfs_pty); - vap->va_rdev = ap->a_vp->v_rdev; - break; - case PTYFSroot: - vap->va_rdev = 0; - vap->va_bytes = vap->va_size = DEV_BSIZE; - break; - - default: - return EOPNOTSUPP; - } - - return 0; -} - -/*ARGSUSED*/ -int -ptyfs_setattr(void *v) -{ - struct vop_setattr_args /* { - struct vnodeop_desc *a_desc; - struct vnode *a_vp; - struct vattr *a_vap; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - struct vattr *vap = ap->a_vap; - struct ucred *cred = ap->a_cred; - struct proc *p = ap->a_p; - int error; - - if (vap->va_size != VNOVAL) { - switch (ptyfs->ptyfs_type) { - case PTYFSroot: - return EISDIR; - case PTYFSpts: - case PTYFSptc: - break; - default: - return EINVAL; - } - } - - if (vap->va_flags != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return EROFS; - if (cred->cr_uid != ptyfs->ptyfs_uid && - (error = suser(cred, &p->p_acflag)) != 0) - return error; - if (cred->cr_uid == 0) { - if ((ptyfs->ptyfs_flags & (SF_IMMUTABLE | SF_APPEND)) && - securelevel > 0) - return EPERM; - /* Snapshot flag cannot be set or cleared */ - if ((vap->va_flags & SF_SNAPSHOT) != - (ptyfs->ptyfs_flags & SF_SNAPSHOT)) - return EPERM; - ptyfs->ptyfs_flags = vap->va_flags; - } else { - if ((ptyfs->ptyfs_flags & (SF_IMMUTABLE | SF_APPEND)) || - (vap->va_flags & UF_SETTABLE) != vap->va_flags) - return EPERM; - if ((ptyfs->ptyfs_flags & SF_SETTABLE) != - (vap->va_flags & SF_SETTABLE)) - return EPERM; - ptyfs->ptyfs_flags &= SF_SETTABLE; - ptyfs->ptyfs_flags |= (vap->va_flags & UF_SETTABLE); - } - ptyfs->ptyfs_flag |= PTYFS_CHANGE; - if (vap->va_flags & (IMMUTABLE | APPEND)) - return 0; - } - if (ptyfs->ptyfs_flags & (IMMUTABLE | APPEND)) - return EPERM; - /* - * Go through the fields and update iff not VNOVAL. - */ - if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return EROFS; - if (ptyfs->ptyfs_type == PTYFSroot) - return EPERM; - error = ptyfs_chown(vp, vap->va_uid, vap->va_gid, cred, p); - if (error) - return error; - } - - if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || - vap->va_birthtime.tv_sec != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return EROFS; - if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0) - return EPERM; - if (cred->cr_uid != ptyfs->ptyfs_uid && - (error = suser(cred, &p->p_acflag)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)) - return (error); - if (vap->va_atime.tv_sec != VNOVAL) - if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) - ptyfs->ptyfs_flag |= PTYFS_ACCESS; - if (vap->va_mtime.tv_sec != VNOVAL) - ptyfs->ptyfs_flag |= PTYFS_CHANGE | PTYFS_MODIFY; - if (vap->va_birthtime.tv_sec != VNOVAL) - ptyfs->ptyfs_birthtime = vap->va_birthtime; - ptyfs->ptyfs_flag |= PTYFS_CHANGE; - error = VOP_UPDATE(vp, &vap->va_atime, &vap->va_mtime, 0); - if (error) - return error; - } - if (vap->va_mode != (mode_t)VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return EROFS; - if (ptyfs->ptyfs_type == PTYFSroot) - return EPERM; - if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0 && - (vap->va_mode & - (S_IXUSR|S_IWUSR|S_IXGRP|S_IWGRP|S_IXOTH|S_IWOTH))) - return EPERM; - error = ptyfs_chmod(vp, vap->va_mode, cred, p); - if (error) - return error; - } - VN_KNOTE(vp, NOTE_ATTRIB); - return 0; -} - -/* - * Change the mode on a file. - * Inode must be locked before calling. - */ -static int -ptyfs_chmod(struct vnode *vp, mode_t mode, struct ucred *cred, struct proc *p) -{ - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - int error; - - if (cred->cr_uid != ptyfs->ptyfs_uid && - (error = suser(cred, &p->p_acflag)) != 0) - return error; - ptyfs->ptyfs_mode &= ~ALLPERMS; - ptyfs->ptyfs_mode |= (mode & ALLPERMS); - return 0; -} - -/* - * Perform chown operation on inode ip; - * inode must be locked prior to call. - */ -static int -ptyfs_chown(struct vnode *vp, uid_t uid, gid_t gid, struct ucred *cred, - struct proc *p) -{ - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - int error; - - if (uid == (uid_t)VNOVAL) - uid = ptyfs->ptyfs_uid; - if (gid == (gid_t)VNOVAL) - gid = ptyfs->ptyfs_gid; - /* - * If we don't own the file, are trying to change the owner - * of the file, or are not a member of the target group, - * the caller's credentials must imply super-user privilege - * or the call fails. - */ - if ((cred->cr_uid != ptyfs->ptyfs_uid || uid != ptyfs->ptyfs_uid || - (gid != ptyfs->ptyfs_gid && - !(cred->cr_gid == gid || groupmember((gid_t)gid, cred)))) && - ((error = suser(cred, &p->p_acflag)) != 0)) - return error; - - ptyfs->ptyfs_gid = gid; - ptyfs->ptyfs_uid = uid; - return 0; -} - -/* - * implement access checking. - * - * actually, the check for super-user is slightly - * broken since it will allow read access to write-only - * objects. this doesn't cause any particular trouble - * but does mean that the i/o entry points need to check - * that the operation really does make sense. - */ -int -ptyfs_access(void *v) -{ - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vattr va; - int error; - - if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) != 0) - return error; - - return vaccess(va.va_type, va.va_mode, - va.va_uid, va.va_gid, ap->a_mode, ap->a_cred); -} - -/* - * lookup. this is incredibly complicated in the - * general case, however for most pseudo-filesystems - * very little needs to be done. - * - * Locking isn't hard here, just poorly documented. - * - * If we're looking up ".", just vref the parent & return it. - * - * If we're looking up "..", unlock the parent, and lock "..". If everything - * went ok, and we're on the last component and the caller requested the - * parent locked, try to re-lock the parent. We do this to prevent lock - * races. - * - * For anything else, get the needed node. Then unlock the parent if not - * the last component or not LOCKPARENT (i.e. if we wouldn't re-lock the - * parent in the .. case). - * - * We try to exit with the parent locked in error cases. - */ -int -ptyfs_lookup(void *v) -{ - struct vop_lookup_args /* { - struct vnode * a_dvp; - struct vnode ** a_vpp; - struct componentname * a_cnp; - } */ *ap = v; - struct componentname *cnp = ap->a_cnp; - struct vnode **vpp = ap->a_vpp; - struct vnode *dvp = ap->a_dvp; - const char *pname = cnp->cn_nameptr; - struct ptyfsnode *ptyfs; - int pty, error, wantpunlock; - - *vpp = NULL; - cnp->cn_flags &= ~PDIRUNLOCK; - - if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) - return EROFS; - - if (cnp->cn_namelen == 1 && *pname == '.') { - *vpp = dvp; - VREF(dvp); - return 0; - } - - wantpunlock = ~cnp->cn_flags & (LOCKPARENT | ISLASTCN); - ptyfs = VTOPTYFS(dvp); - switch (ptyfs->ptyfs_type) { - case PTYFSroot: - /* - * Shouldn't get here with .. in the root node. - */ - if (cnp->cn_flags & ISDOTDOT) - return EIO; - - pty = atoi(pname, cnp->cn_namelen); - - if (pty < 0 || pty >= npty || pty_isfree(pty, 1)) - break; - - error = ptyfs_allocvp(dvp->v_mount, vpp, PTYFSpts, pty, - curproc); - if (error == 0 && wantpunlock) { - VOP_UNLOCK(dvp, 0); - cnp->cn_flags |= PDIRUNLOCK; - } - return error; - - default: - return ENOTDIR; - } - - return cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS; -} - -/* - * readdir returns directory entries from ptyfsnode (vp). - * - * the strategy here with ptyfs is to generate a single - * directory entry at a time (struct dirent) and then - * copy that out to userland using uiomove. a more efficent - * though more complex implementation, would try to minimize - * the number of calls to uiomove(). for ptyfs, this is - * hardly worth the added code complexity. - * - * this should just be done through read() - */ -int -ptyfs_readdir(void *v) -{ - struct vop_readdir_args /* { - struct vnode *a_vp; - struct uio *a_uio; - struct ucred *a_cred; - int *a_eofflag; - off_t **a_cookies; - int *a_ncookies; - } */ *ap = v; - struct uio *uio = ap->a_uio; - struct dirent d; - struct ptyfsnode *ptyfs; - off_t i; - int error; - off_t *cookies = NULL; - int ncookies; - struct vnode *vp; - int nc = 0; - - vp = ap->a_vp; - ptyfs = VTOPTYFS(vp); - - if (uio->uio_resid < UIO_MX) - return EINVAL; - if (uio->uio_offset < 0) - return EINVAL; - - error = 0; - i = uio->uio_offset; - (void)memset(&d, 0, sizeof(d)); - d.d_reclen = UIO_MX; - ncookies = uio->uio_resid / UIO_MX; - - switch (ptyfs->ptyfs_type) { - case PTYFSroot: /* root */ - - if (i >= npty) - return 0; - - if (ap->a_ncookies) { - ncookies = min(ncookies, (npty + 2 - i)); - cookies = malloc(ncookies * sizeof (off_t), - M_TEMP, M_WAITOK); - *ap->a_cookies = cookies; - } - - for (; i < 2; i++) { - switch (i) { - case 0: /* `.' */ - case 1: /* `..' */ - d.d_fileno = PTYFS_FILENO(0, PTYFSroot); - d.d_namlen = i + 1; - (void)memcpy(d.d_name, "..", d.d_namlen); - d.d_name[i + 1] = '\0'; - d.d_type = DT_DIR; - break; - } - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - nc++; - } - if (error) { - ncookies = nc; - break; - } - for (; uio->uio_resid >= UIO_MX && i < npty; i++) { - /* check for used ptys */ - if (pty_isfree(i - 2, 1)) - continue; - - d.d_fileno = PTYFS_FILENO(i - 2, PTYFSpts); - d.d_namlen = snprintf(d.d_name, sizeof(d.d_name), - "%lld", (long long)(i - 2)); - d.d_type = DT_CHR; - if ((error = uiomove(&d, UIO_MX, uio)) != 0) - break; - if (cookies) - *cookies++ = i + 1; - nc++; - } - ncookies = nc; - break; - - default: - error = ENOTDIR; - break; - } - - if (ap->a_ncookies) { - if (error) { - if (cookies) - free(*ap->a_cookies, M_TEMP); - *ap->a_ncookies = 0; - *ap->a_cookies = NULL; - } else - *ap->a_ncookies = ncookies; - } - uio->uio_offset = i; - return error; -} - -int -ptyfs_open(void *v) -{ - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - ptyfs->ptyfs_flag |= PTYFS_CHANGE|PTYFS_ACCESS; - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - case PTYFSptc: - return spec_open(v); - case PTYFSroot: - return 0; - default: - return EINVAL; - } -} - -int -ptyfs_close(void *v) -{ - struct vop_close_args /* { - struct vnode *a_vp; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - struct timespec ts; - ptyfs_time(ptyfs, &ts, &ts); - - simple_lock(&vp->v_interlock); - if (vp->v_usecount > 1) { - TIMEVAL_TO_TIMESPEC(&time, &ts); - ptyfs_time(ptyfs, &ts, &ts); - } - simple_unlock(&vp->v_interlock); - - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - case PTYFSptc: - return spec_close(v); - case PTYFSroot: - return 0; - default: - return EINVAL; - } -} - -int -ptyfs_read(void *v) -{ - struct vop_read_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - int error; - - ptyfs->ptyfs_flag |= PTYFS_ACCESS; - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - VOP_UNLOCK(vp, 0); - error = (*pts_cdevsw.d_read)(vp->v_rdev, ap->a_uio, - ap->a_ioflag); - vn_lock(vp, LK_RETRY|LK_EXCLUSIVE); - return error; - case PTYFSptc: - VOP_UNLOCK(vp, 0); - error = (*ptc_cdevsw.d_read)(vp->v_rdev, ap->a_uio, - ap->a_ioflag); - vn_lock(vp, LK_RETRY|LK_EXCLUSIVE); - return error; - default: - return EOPNOTSUPP; - } -} - -int -ptyfs_write(void *v) -{ - struct vop_write_args /* { - struct vnode *a_vp; - struct uio *a_uio; - int a_ioflag; - struct ucred *a_cred; - } */ *ap = v; - int error; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - ptyfs->ptyfs_flag |= PTYFS_MODIFY; - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - VOP_UNLOCK(vp, 0); - error = (*pts_cdevsw.d_write)(vp->v_rdev, ap->a_uio, - ap->a_ioflag); - vn_lock(vp, LK_RETRY|LK_EXCLUSIVE); - return error; - case PTYFSptc: - VOP_UNLOCK(vp, 0); - error = (*ptc_cdevsw.d_write)(vp->v_rdev, ap->a_uio, - ap->a_ioflag); - vn_lock(vp, LK_RETRY|LK_EXCLUSIVE); - return error; - default: - return EOPNOTSUPP; - } -} - -int -ptyfs_ioctl(void *v) -{ - struct vop_ioctl_args /* { - struct vnode *a_vp; - u_long a_command; - void *a_data; - int a_fflag; - struct ucred *a_cred; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - return (*pts_cdevsw.d_ioctl)(vp->v_rdev, ap->a_command, - ap->a_data, ap->a_fflag, ap->a_p); - case PTYFSptc: - return (*ptc_cdevsw.d_ioctl)(vp->v_rdev, ap->a_command, - ap->a_data, ap->a_fflag, ap->a_p); - default: - return EOPNOTSUPP; - } -} - -int -ptyfs_poll(void *v) -{ - struct vop_poll_args /* { - struct vnode *a_vp; - int a_events; - struct proc *a_p; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - return (*pts_cdevsw.d_poll)(vp->v_rdev, ap->a_events, ap->a_p); - case PTYFSptc: - return (*ptc_cdevsw.d_poll)(vp->v_rdev, ap->a_events, ap->a_p); - default: - return genfs_poll(v); - } -} - -int -ptyfs_kqfilter(void *v) -{ - struct vop_kqfilter_args /* { - struct vnode *a_vp; - struct knote *a_kn; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct ptyfsnode *ptyfs = VTOPTYFS(vp); - - switch (ptyfs->ptyfs_type) { - case PTYFSpts: - return (*pts_cdevsw.d_kqfilter)(vp->v_rdev, ap->a_kn); - case PTYFSptc: - return (*ptc_cdevsw.d_kqfilter)(vp->v_rdev, ap->a_kn); - default: - return genfs_kqfilter(v); - } -} - -int -ptyfs_update(v) - void *v; -{ - struct vop_update_args /* { - struct vnode *a_vp; - struct timespec *a_access; - struct timespec *a_modify; - int a_flags; - } */ *ap = v; - struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); - struct timespec ts; - - if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) - return 0; - - TIMEVAL_TO_TIMESPEC(&time, &ts); - if (ap->a_access == NULL) - ap->a_access = &ts; - if (ap->a_modify == NULL) - ap->a_modify = &ts; - ptyfs_time(ptyfs, ap->a_access, ap->a_modify); - return 0; -} - -static void -ptyfs_time(struct ptyfsnode *ptyfs, struct timespec *atime, - struct timespec *mtime) -{ - if (ptyfs->ptyfs_flag & PTYFS_MODIFY) { - ptyfs->ptyfs_mtime = *mtime; - ptyfs->ptyfs_atime = *atime; - } else if (ptyfs->ptyfs_flag & PTYFS_ACCESS) - ptyfs->ptyfs_atime = *atime; - if (ptyfs->ptyfs_flag & PTYFS_CHANGE) - ptyfs->ptyfs_ctime = *atime; - ptyfs->ptyfs_flag = 0; -} - -/* - * convert decimal ascii to int - */ -static int -atoi(const char *b, size_t len) -{ - int p = 0; - - while (len--) { - char c = *b++; - if (c < '0' || c > '9') - return -1; - p = 10 * p + (c - '0'); - } - - return p; -} - -/* - * Return the number of decimal digits - */ -static u_int -digits(u_int i) -{ - u_int d; - for (d = 1; i != 0; d++) - i /= 10; - return d; -}