1 | /* $NetBSD: ptyfs_subr.c,v 1.33 2014/10/15 15:00:03 christos 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.33 2014/10/15 15:00:03 christos 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 | /* |
181 | * XXX We have minimum race condition when opening master side |
182 | * first time, if other threads through other mount points, trying |
183 | * opening the same device. As follow we have little chance have |
184 | * unused list entries. |
185 | */ |
186 | SLIST_INSERT_HEAD(ppp, pp, ptyfs_hash); |
187 | mutex_exit(&ptyfs_hashlock); |
188 | return pp; |
189 | } |
190 | |
191 | /* |
192 | * Mark this controlling pty as active. |
193 | */ |
194 | void |
195 | ptyfs_set_active(struct mount *mp, int pty) |
196 | { |
197 | struct ptyfsmount *pmnt = VFSTOPTY(mp); |
198 | |
199 | KASSERT(pty >= 0); |
200 | /* Reallocate map if needed. */ |
201 | if (pty >= pmnt->pmnt_bitmap_size * NBBY) { |
202 | int osize, nsize; |
203 | uint8_t *obitmap, *nbitmap; |
204 | |
205 | nsize = roundup(howmany(pty + 1, NBBY), 64); |
206 | nbitmap = kmem_alloc(nsize, KM_SLEEP); |
207 | mutex_enter(&pmnt->pmnt_lock); |
208 | if (pty < pmnt->pmnt_bitmap_size * NBBY) { |
209 | mutex_exit(&pmnt->pmnt_lock); |
210 | kmem_free(nbitmap, nsize); |
211 | } else { |
212 | osize = pmnt->pmnt_bitmap_size; |
213 | obitmap = pmnt->pmnt_bitmap; |
214 | pmnt->pmnt_bitmap_size = nsize; |
215 | pmnt->pmnt_bitmap = nbitmap; |
216 | if (osize > 0) |
217 | memcpy(pmnt->pmnt_bitmap, obitmap, osize); |
218 | memset(pmnt->pmnt_bitmap + osize, 0, nsize - osize); |
219 | mutex_exit(&pmnt->pmnt_lock); |
220 | if (osize > 0) |
221 | kmem_free(obitmap, osize); |
222 | } |
223 | } |
224 | |
225 | mutex_enter(&pmnt->pmnt_lock); |
226 | setbit(pmnt->pmnt_bitmap, pty); |
227 | mutex_exit(&pmnt->pmnt_lock); |
228 | } |
229 | |
230 | /* |
231 | * Mark this controlling pty as inactive. |
232 | */ |
233 | void |
234 | ptyfs_clr_active(struct mount *mp, int pty) |
235 | { |
236 | struct ptyfsmount *pmnt = VFSTOPTY(mp); |
237 | |
238 | KASSERT(pty >= 0); |
239 | mutex_enter(&pmnt->pmnt_lock); |
240 | if (pty >= 0 && pty < pmnt->pmnt_bitmap_size * NBBY) |
241 | clrbit(pmnt->pmnt_bitmap, pty); |
242 | mutex_exit(&pmnt->pmnt_lock); |
243 | } |
244 | |
245 | /* |
246 | * Lookup the next active controlling pty greater or equal "pty". |
247 | * Return -1 if not found. |
248 | */ |
249 | int |
250 | ptyfs_next_active(struct mount *mp, int pty) |
251 | { |
252 | struct ptyfsmount *pmnt = VFSTOPTY(mp); |
253 | |
254 | KASSERT(pty >= 0); |
255 | mutex_enter(&pmnt->pmnt_lock); |
256 | while (pty < pmnt->pmnt_bitmap_size * NBBY) { |
257 | if (isset(pmnt->pmnt_bitmap, pty)) { |
258 | mutex_exit(&pmnt->pmnt_lock); |
259 | return pty; |
260 | } |
261 | pty++; |
262 | } |
263 | mutex_exit(&pmnt->pmnt_lock); |
264 | return -1; |
265 | } |
266 | |