1 /* $NetBSD: ptyfs_subr.c,v 1.32 2014/08/16 07:22:30 hannken Exp $ */ 2 3 /* 4 * Copyright (c) 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)ptyfs_subr.c 8.6 (Berkeley) 5/14/95 35 */ 36 37 /* 38 * Copyright (c) 1994 Christopher G. Demetriou. All rights reserved. 39 * Copyright (c) 1993 Jan-Simon Pendry 40 * 41 * This code is derived from software contributed to Berkeley by 42 * Jan-Simon Pendry. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)procfs_subr.c 8.6 (Berkeley) 5/14/95 73 */ 74 75 #include <sys/cdefs.h> 76 __KERNEL_RCSID(0, "$NetBSD: ptyfs_subr.c,v 1.32 2014/08/16 07:22:30 hannken Exp $"); 77 78 #include <sys/param.h> 79 #include <sys/systm.h> 80 #include <sys/time.h> 81 #include <sys/kernel.h> 82 #include <sys/vnode.h> 83 #include <sys/stat.h> 84 #include <sys/malloc.h> 85 #include <sys/file.h> 86 #include <sys/namei.h> 87 #include <sys/filedesc.h> 88 #include <sys/select.h> 89 #include <sys/tty.h> 90 #include <sys/pty.h> 91 #include <sys/kauth.h> 92 #include <sys/lwp.h> 93 94 #include <fs/ptyfs/ptyfs.h> 95 96 static kmutex_t ptyfs_hashlock; 97 98 static SLIST_HEAD(ptyfs_hashhead, ptyfsnode) *ptyfs_node_tbl; 99 static u_long ptyfs_node_mask; /* size of hash table - 1 */ 100 101 /* 102 * allocate a ptyfsnode/vnode pair. the vnode is referenced. 103 * 104 * the pty, ptyfs_type, and mount point uniquely 105 * identify a ptyfsnode. the mount point is needed 106 * because someone might mount this filesystem 107 * twice. 108 */ 109 int 110 ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty) 111 { 112 struct ptyfskey key; 113 114 memset(&key, 0, sizeof(key)); 115 key.ptk_pty = pty; 116 key.ptk_type = type; 117 return vcache_get(mp, &key, sizeof(key), vpp); 118 } 119 120 /* 121 * Initialize ptyfsnode hash table. 122 */ 123 void 124 ptyfs_hashinit(void) 125 { 126 127 ptyfs_node_tbl = hashinit(16, HASH_SLIST, true, &ptyfs_node_mask); 128 mutex_init(&ptyfs_hashlock, MUTEX_DEFAULT, IPL_NONE); 129 } 130 131 /* 132 * Free ptyfsnode hash table. 133 */ 134 void 135 ptyfs_hashdone(void) 136 { 137 138 mutex_destroy(&ptyfs_hashlock); 139 hashdone(ptyfs_node_tbl, HASH_SLIST, ptyfs_node_mask); 140 } 141 142 /* 143 * Get a ptyfsnode from the hash table, or allocate one. 144 */ 145 struct ptyfsnode * 146 ptyfs_get_node(ptyfstype type, int pty) 147 { 148 struct ptyfs_hashhead *ppp; 149 struct ptyfsnode *pp; 150 151 ppp = &ptyfs_node_tbl[PTYFS_FILENO(type, pty) & ptyfs_node_mask]; 152 153 mutex_enter(&ptyfs_hashlock); 154 SLIST_FOREACH(pp, ppp, ptyfs_hash) { 155 if (pty == pp->ptyfs_pty && pp->ptyfs_type == type) { 156 mutex_exit(&ptyfs_hashlock); 157 return pp; 158 } 159 } 160 mutex_exit(&ptyfs_hashlock); 161 162 pp = malloc(sizeof(struct ptyfsnode), M_TEMP, M_WAITOK); 163 pp->ptyfs_pty = pty; 164 pp->ptyfs_type = type; 165 pp->ptyfs_fileno = PTYFS_FILENO(pty, type); 166 if (pp->ptyfs_type == PTYFSroot) 167 pp->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| 168 S_IROTH|S_IXOTH; 169 else 170 pp->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| 171 S_IROTH|S_IWOTH; 172 173 pp->ptyfs_uid = pp->ptyfs_gid = 0; 174 pp->ptyfs_status = PTYFS_CHANGE; 175 PTYFS_ITIMES(pp, NULL, NULL, NULL); 176 pp->ptyfs_birthtime = pp->ptyfs_mtime = 177 pp->ptyfs_atime = pp->ptyfs_ctime; 178 pp->ptyfs_flags = 0; 179 mutex_enter(&ptyfs_hashlock); 180 SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash); 181 mutex_exit(&ptyfs_hashlock); 182 return pp; 183 } 184 185 /* 186 * Mark this controlling pty as active. 187 */ 188 void 189 ptyfs_set_active(struct mount *mp, int pty) 190 { 191 struct ptyfsmount *pmnt = VFSTOPTY(mp); 192 193 KASSERT(pty >= 0); 194 /* Reallocate map if needed. */ 195 if (pty >= pmnt->pmnt_bitmap_size * NBBY) { 196 int osize, nsize; 197 uint8_t *obitmap, *nbitmap; 198 199 nsize = roundup(howmany(pty + 1, NBBY), 64); 200 nbitmap = kmem_alloc(nsize, KM_SLEEP); 201 mutex_enter(&pmnt->pmnt_lock); 202 if (pty < pmnt->pmnt_bitmap_size * NBBY) { 203 mutex_exit(&pmnt->pmnt_lock); 204 kmem_free(nbitmap, nsize); 205 } else { 206 osize = pmnt->pmnt_bitmap_size; 207 obitmap = pmnt->pmnt_bitmap; 208 pmnt->pmnt_bitmap_size = nsize; 209 pmnt->pmnt_bitmap = nbitmap; 210 if (osize > 0) 211 memcpy(pmnt->pmnt_bitmap, obitmap, osize); 212 memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize); 213 mutex_exit(&pmnt->pmnt_lock); 214 if (osize > 0) 215 kmem_free(obitmap, osize); 216 } 217 } 218 219 mutex_enter(&pmnt->pmnt_lock); 220 setbit(pmnt->pmnt_bitmap, pty); 221 mutex_exit(&pmnt->pmnt_lock); 222 } 223 224 /* 225 * Mark this controlling pty as inactive. 226 */ 227 void 228 ptyfs_clr_active(struct mount *mp, int pty) 229 { 230 struct ptyfsmount *pmnt = VFSTOPTY(mp); 231 232 KASSERT(pty >= 0); 233 mutex_enter(&pmnt->pmnt_lock); 234 if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY) 235 clrbit(pmnt->pmnt_bitmap, pty); 236 mutex_exit(&pmnt->pmnt_lock); 237 } 238 239 /* 240 * Lookup the next active controlling pty greater or equal "pty". 241 * Return -1 if not found. 242 */ 243 int 244 ptyfs_next_active(struct mount *mp, int pty) 245 { 246 struct ptyfsmount *pmnt = VFSTOPTY(mp); 247 248 KASSERT(pty >= 0); 249 mutex_enter(&pmnt->pmnt_lock); 250 while (pty < pmnt->pmnt_bitmap_size * NBBY) { 251 if (isset(pmnt->pmnt_bitmap, pty)) { 252 mutex_exit(&pmnt->pmnt_lock); 253 return pty; 254 } 255 pty++; 256 } 257 mutex_exit(&pmnt->pmnt_lock); 258 return -1; 259 } 260