| @@ -1,418 +1,417 @@ | | | @@ -1,418 +1,417 @@ |
1 | /* $NetBSD: ptyfs_vfsops.c,v 1.42 2010/01/08 11:35:09 pooka Exp $ */ | | 1 | /* $NetBSD: ptyfs_vfsops.c,v 1.43 2012/09/18 21:33:55 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1992, 1993, 1995 | | 4 | * Copyright (c) 1992, 1993, 1995 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software donated to Berkeley by | | 7 | * This code is derived from software donated to Berkeley by |
8 | * Jan-Simon Pendry. | | 8 | * Jan-Simon Pendry. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * 3. Neither the name of the University nor the names of its contributors | | 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 | | 19 | * may be used to endorse or promote products derived from this software |
20 | * without specific prior written permission. | | 20 | * without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 23 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | * | | 33 | * |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | /* | | 36 | /* |
37 | * Pseudo-tty Filesystem | | 37 | * Pseudo-tty Filesystem |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/cdefs.h> | | 40 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.42 2010/01/08 11:35:09 pooka Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.43 2012/09/18 21:33:55 christos Exp $"); |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 44 | #include <sys/systm.h> |
45 | #include <sys/sysctl.h> | | 45 | #include <sys/sysctl.h> |
46 | #include <sys/conf.h> | | 46 | #include <sys/conf.h> |
47 | #include <sys/proc.h> | | 47 | #include <sys/proc.h> |
48 | #include <sys/vnode.h> | | 48 | #include <sys/vnode.h> |
49 | #include <sys/mount.h> | | 49 | #include <sys/mount.h> |
50 | #include <sys/namei.h> | | 50 | #include <sys/namei.h> |
51 | #include <sys/stat.h> | | 51 | #include <sys/stat.h> |
52 | #include <sys/dirent.h> | | 52 | #include <sys/dirent.h> |
53 | #include <sys/malloc.h> | | 53 | #include <sys/malloc.h> |
54 | #include <sys/syslog.h> | | 54 | #include <sys/syslog.h> |
55 | #include <sys/select.h> | | 55 | #include <sys/select.h> |
56 | #include <sys/filedesc.h> | | 56 | #include <sys/filedesc.h> |
57 | #include <sys/tty.h> | | 57 | #include <sys/tty.h> |
58 | #include <sys/pty.h> | | 58 | #include <sys/pty.h> |
59 | #include <sys/kauth.h> | | 59 | #include <sys/kauth.h> |
60 | #include <sys/module.h> | | 60 | #include <sys/module.h> |
61 | | | 61 | |
62 | #include <fs/ptyfs/ptyfs.h> | | 62 | #include <fs/ptyfs/ptyfs.h> |
63 | #include <miscfs/genfs/genfs.h> | | 63 | #include <miscfs/genfs/genfs.h> |
64 | #include <miscfs/specfs/specdev.h> | | 64 | #include <miscfs/specfs/specdev.h> |
65 | | | 65 | |
66 | MODULE(MODULE_CLASS_VFS, ptyfs, NULL); | | 66 | MODULE(MODULE_CLASS_VFS, ptyfs, NULL); |
67 | | | 67 | |
68 | MALLOC_JUSTDEFINE(M_PTYFSMNT, "ptyfs mount", "ptyfs mount structures"); | | 68 | MALLOC_JUSTDEFINE(M_PTYFSMNT, "ptyfs mount", "ptyfs mount structures"); |
69 | MALLOC_JUSTDEFINE(M_PTYFSTMP, "ptyfs temp", "ptyfs temporary structures"); | | 69 | MALLOC_JUSTDEFINE(M_PTYFSTMP, "ptyfs temp", "ptyfs temporary structures"); |
70 | | | 70 | |
71 | VFS_PROTOS(ptyfs); | | 71 | VFS_PROTOS(ptyfs); |
72 | | | 72 | |
73 | static struct sysctllog *ptyfs_sysctl_log; | | 73 | static struct sysctllog *ptyfs_sysctl_log; |
74 | | | 74 | |
75 | static int ptyfs__allocvp(struct ptm_pty *, struct lwp *, struct vnode **, | | 75 | static int ptyfs__allocvp(struct ptm_pty *, struct lwp *, struct vnode **, |
76 | dev_t, char); | | 76 | dev_t, char); |
77 | static int ptyfs__makename(struct ptm_pty *, struct lwp *, char *, size_t, | | 77 | static int ptyfs__makename(struct ptm_pty *, struct lwp *, char *, size_t, |
78 | dev_t, char); | | 78 | dev_t, char); |
79 | static void ptyfs__getvattr(struct ptm_pty *, struct lwp *, struct vattr *); | | 79 | static void ptyfs__getvattr(struct ptm_pty *, struct lwp *, struct vattr *); |
80 | | | 80 | |
81 | /* | | 81 | /* |
82 | * ptm glue: When we mount, we make ptm point to us. | | 82 | * ptm glue: When we mount, we make ptm point to us. |
83 | */ | | 83 | */ |
84 | struct ptm_pty *ptyfs_save_ptm; | | 84 | struct ptm_pty *ptyfs_save_ptm; |
85 | static int ptyfs_count; | | 85 | static int ptyfs_count; |
86 | | | 86 | |
87 | struct ptm_pty ptm_ptyfspty = { | | 87 | struct ptm_pty ptm_ptyfspty = { |
88 | ptyfs__allocvp, | | 88 | ptyfs__allocvp, |
89 | ptyfs__makename, | | 89 | ptyfs__makename, |
90 | ptyfs__getvattr, | | 90 | ptyfs__getvattr, |
91 | NULL | | 91 | NULL |
92 | }; | | 92 | }; |
93 | | | 93 | |
94 | static const char * | | 94 | static const char * |
95 | ptyfs__getpath(struct lwp *l, const struct mount *mp) | | 95 | ptyfs__getpath(struct lwp *l, const struct mount *mp) |
96 | { | | 96 | { |
97 | #define MAXBUF (sizeof(mp->mnt_stat.f_mntonname) + 32) | | 97 | #define MAXBUF (sizeof(mp->mnt_stat.f_mntonname) + 32) |
98 | struct cwdinfo *cwdi = l->l_proc->p_cwdi; | | 98 | struct cwdinfo *cwdi = l->l_proc->p_cwdi; |
99 | char *buf; | | 99 | char *buf; |
100 | const char *rv; | | 100 | const char *rv; |
101 | size_t len; | | 101 | size_t len; |
102 | char *bp; | | 102 | char *bp; |
103 | int error; | | 103 | int error; |
104 | struct ptyfsmount *pmnt = mp->mnt_data; | | 104 | struct ptyfsmount *pmnt = mp->mnt_data; |
105 | | | 105 | |
106 | rv = mp->mnt_stat.f_mntonname; | | 106 | rv = mp->mnt_stat.f_mntonname; |
107 | if (cwdi->cwdi_rdir == NULL || | | 107 | if (cwdi->cwdi_rdir == NULL) |
108 | (pmnt->pmnt_flags & PTYFSMNT_CHROOT) == 0) | | | |
109 | return rv; | | 108 | return rv; |
110 | | | 109 | |
111 | buf = malloc(MAXBUF, M_TEMP, M_WAITOK); | | 110 | buf = malloc(MAXBUF, M_TEMP, M_WAITOK); |
112 | bp = buf + MAXBUF; | | 111 | bp = buf + MAXBUF; |
113 | *--bp = '\0'; | | 112 | *--bp = '\0'; |
114 | error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, | | 113 | error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, |
115 | buf, MAXBUF / 2, 0, l); | | 114 | buf, MAXBUF / 2, 0, l); |
116 | if (error) /* XXX */ | | 115 | if (error) /* XXX */ |
117 | goto out; | | 116 | goto out; |
118 | | | 117 | |
119 | len = strlen(bp); | | 118 | len = strlen(bp); |
120 | if (len < sizeof(mp->mnt_stat.f_mntonname)) /* XXX */ | | 119 | if (len < sizeof(mp->mnt_stat.f_mntonname)) /* XXX */ |
121 | rv += len; | | 120 | rv += len; |
122 | out: | | 121 | out: |
123 | free(buf, M_TEMP); | | 122 | free(buf, M_TEMP); |
124 | return rv; | | 123 | return rv; |
125 | } | | 124 | } |
126 | | | 125 | |
127 | static int | | 126 | static int |
128 | ptyfs__makename(struct ptm_pty *pt, struct lwp *l, char *tbuf, size_t bufsiz, | | 127 | ptyfs__makename(struct ptm_pty *pt, struct lwp *l, char *tbuf, size_t bufsiz, |
129 | dev_t dev, char ms) | | 128 | dev_t dev, char ms) |
130 | { | | 129 | { |
131 | struct mount *mp = pt->arg; | | 130 | struct mount *mp = pt->arg; |
132 | size_t len; | | 131 | size_t len; |
133 | | | 132 | |
134 | switch (ms) { | | 133 | switch (ms) { |
135 | case 'p': | | 134 | case 'p': |
136 | /* We don't provide access to the master, should we? */ | | 135 | /* We don't provide access to the master, should we? */ |
137 | len = snprintf(tbuf, bufsiz, "/dev/null"); | | 136 | len = snprintf(tbuf, bufsiz, "/dev/null"); |
138 | break; | | 137 | break; |
139 | case 't': | | 138 | case 't': |
140 | len = snprintf(tbuf, bufsiz, "%s/%llu", ptyfs__getpath(l, mp), | | 139 | len = snprintf(tbuf, bufsiz, "%s/%llu", ptyfs__getpath(l, mp), |
141 | (unsigned long long)minor(dev)); | | 140 | (unsigned long long)minor(dev)); |
142 | break; | | 141 | break; |
143 | default: | | 142 | default: |
144 | return EINVAL; | | 143 | return EINVAL; |
145 | } | | 144 | } |
146 | | | 145 | |
147 | return len >= bufsiz ? ENOSPC : 0; | | 146 | return len >= bufsiz ? ENOSPC : 0; |
148 | } | | 147 | } |
149 | | | 148 | |
150 | | | 149 | |
151 | static int | | 150 | static int |
152 | /*ARGSUSED*/ | | 151 | /*ARGSUSED*/ |
153 | ptyfs__allocvp(struct ptm_pty *pt, struct lwp *l, struct vnode **vpp, | | 152 | ptyfs__allocvp(struct ptm_pty *pt, struct lwp *l, struct vnode **vpp, |
154 | dev_t dev, char ms) | | 153 | dev_t dev, char ms) |
155 | { | | 154 | { |
156 | struct mount *mp = pt->arg; | | 155 | struct mount *mp = pt->arg; |
157 | ptyfstype type; | | 156 | ptyfstype type; |
158 | | | 157 | |
159 | switch (ms) { | | 158 | switch (ms) { |
160 | case 'p': | | 159 | case 'p': |
161 | type = PTYFSptc; | | 160 | type = PTYFSptc; |
162 | break; | | 161 | break; |
163 | case 't': | | 162 | case 't': |
164 | type = PTYFSpts; | | 163 | type = PTYFSpts; |
165 | break; | | 164 | break; |
166 | default: | | 165 | default: |
167 | return EINVAL; | | 166 | return EINVAL; |
168 | } | | 167 | } |
169 | | | 168 | |
170 | return ptyfs_allocvp(mp, vpp, type, minor(dev), l); | | 169 | return ptyfs_allocvp(mp, vpp, type, minor(dev), l); |
171 | } | | 170 | } |
172 | | | 171 | |
173 | | | 172 | |
174 | static void | | 173 | static void |
175 | ptyfs__getvattr(struct ptm_pty *pt, struct lwp *l, struct vattr *vattr) | | 174 | ptyfs__getvattr(struct ptm_pty *pt, struct lwp *l, struct vattr *vattr) |
176 | { | | 175 | { |
177 | struct mount *mp = pt->arg; | | 176 | struct mount *mp = pt->arg; |
178 | struct ptyfsmount *pmnt = VFSTOPTY(mp); | | 177 | struct ptyfsmount *pmnt = VFSTOPTY(mp); |
179 | vattr_null(vattr); | | 178 | vattr_null(vattr); |
180 | /* get real uid */ | | 179 | /* get real uid */ |
181 | vattr->va_uid = kauth_cred_getuid(l->l_cred); | | 180 | vattr->va_uid = kauth_cred_getuid(l->l_cred); |
182 | vattr->va_gid = pmnt->pmnt_gid; | | 181 | vattr->va_gid = pmnt->pmnt_gid; |
183 | vattr->va_mode = pmnt->pmnt_mode; | | 182 | vattr->va_mode = pmnt->pmnt_mode; |
184 | } | | 183 | } |
185 | | | 184 | |
186 | | | 185 | |
187 | void | | 186 | void |
188 | ptyfs_init(void) | | 187 | ptyfs_init(void) |
189 | { | | 188 | { |
190 | | | 189 | |
191 | malloc_type_attach(M_PTYFSMNT); | | 190 | malloc_type_attach(M_PTYFSMNT); |
192 | malloc_type_attach(M_PTYFSTMP); | | 191 | malloc_type_attach(M_PTYFSTMP); |
193 | ptyfs_hashinit(); | | 192 | ptyfs_hashinit(); |
194 | } | | 193 | } |
195 | | | 194 | |
196 | void | | 195 | void |
197 | ptyfs_reinit(void) | | 196 | ptyfs_reinit(void) |
198 | { | | 197 | { |
199 | ptyfs_hashreinit(); | | 198 | ptyfs_hashreinit(); |
200 | } | | 199 | } |
201 | | | 200 | |
202 | void | | 201 | void |
203 | ptyfs_done(void) | | 202 | ptyfs_done(void) |
204 | { | | 203 | { |
205 | | | 204 | |
206 | ptyfs_hashdone(); | | 205 | ptyfs_hashdone(); |
207 | malloc_type_detach(M_PTYFSTMP); | | 206 | malloc_type_detach(M_PTYFSTMP); |
208 | malloc_type_detach(M_PTYFSMNT); | | 207 | malloc_type_detach(M_PTYFSMNT); |
209 | } | | 208 | } |
210 | | | 209 | |
211 | #define OSIZE sizeof(struct { int f; gid_t g; mode_t m; }) | | 210 | #define OSIZE sizeof(struct { int f; gid_t g; mode_t m; }) |
212 | /* | | 211 | /* |
213 | * Mount the Pseudo tty params filesystem | | 212 | * Mount the Pseudo tty params filesystem |
214 | */ | | 213 | */ |
215 | int | | 214 | int |
216 | ptyfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) | | 215 | ptyfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) |
217 | { | | 216 | { |
218 | struct lwp *l = curlwp; | | 217 | struct lwp *l = curlwp; |
219 | int error = 0; | | 218 | int error = 0; |
220 | struct ptyfsmount *pmnt; | | 219 | struct ptyfsmount *pmnt; |
221 | struct ptyfs_args *args = data; | | 220 | struct ptyfs_args *args = data; |
222 | | | 221 | |
223 | if (*data_len != sizeof *args && *data_len != OSIZE) | | 222 | if (*data_len != sizeof *args && *data_len != OSIZE) |
224 | return EINVAL; | | 223 | return EINVAL; |
225 | | | 224 | |
226 | if (UIO_MX & (UIO_MX - 1)) { | | 225 | if (UIO_MX & (UIO_MX - 1)) { |
227 | log(LOG_ERR, "ptyfs: invalid directory entry size"); | | 226 | log(LOG_ERR, "ptyfs: invalid directory entry size"); |
228 | return EINVAL; | | 227 | return EINVAL; |
229 | } | | 228 | } |
230 | | | 229 | |
231 | if (mp->mnt_flag & MNT_GETARGS) { | | 230 | if (mp->mnt_flag & MNT_GETARGS) { |
232 | pmnt = VFSTOPTY(mp); | | 231 | pmnt = VFSTOPTY(mp); |
233 | if (pmnt == NULL) | | 232 | if (pmnt == NULL) |
234 | return EIO; | | 233 | return EIO; |
235 | args->mode = pmnt->pmnt_mode; | | 234 | args->mode = pmnt->pmnt_mode; |
236 | args->gid = pmnt->pmnt_gid; | | 235 | args->gid = pmnt->pmnt_gid; |
237 | if (args->version >= PTYFS_ARGSVERSION) { | | 236 | if (args->version >= PTYFS_ARGSVERSION) { |
238 | args->flags = pmnt->pmnt_flags; | | 237 | args->flags = pmnt->pmnt_flags; |
239 | *data_len = sizeof *args; | | 238 | *data_len = sizeof *args; |
240 | } else { | | 239 | } else { |
241 | *data_len = OSIZE; | | 240 | *data_len = OSIZE; |
242 | } | | 241 | } |
243 | return 0; | | 242 | return 0; |
244 | } | | 243 | } |
245 | | | 244 | |
246 | /* Don't allow more than one mount */ | | 245 | /* Don't allow more than one mount */ |
247 | if (ptyfs_count) | | 246 | if (ptyfs_count) |
248 | return EBUSY; | | 247 | return EBUSY; |
249 | | | 248 | |
250 | if (mp->mnt_flag & MNT_UPDATE) | | 249 | if (mp->mnt_flag & MNT_UPDATE) |
251 | return EOPNOTSUPP; | | 250 | return EOPNOTSUPP; |
252 | | | 251 | |
253 | if (args->version > PTYFS_ARGSVERSION) | | 252 | if (args->version > PTYFS_ARGSVERSION) |
254 | return EINVAL; | | 253 | return EINVAL; |
255 | | | 254 | |
256 | pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); | | 255 | pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); |
257 | | | 256 | |
258 | mp->mnt_data = pmnt; | | 257 | mp->mnt_data = pmnt; |
259 | pmnt->pmnt_gid = args->gid; | | 258 | pmnt->pmnt_gid = args->gid; |
260 | pmnt->pmnt_mode = args->mode; | | 259 | pmnt->pmnt_mode = args->mode; |
261 | if (args->version >= PTYFS_ARGSVERSION) | | 260 | if (args->version >= PTYFS_ARGSVERSION) |
262 | pmnt->pmnt_flags = args->flags; | | 261 | pmnt->pmnt_flags = args->flags; |
263 | else | | 262 | else |
264 | pmnt->pmnt_flags = 0; | | 263 | pmnt->pmnt_flags = 0; |
265 | mp->mnt_flag |= MNT_LOCAL; | | 264 | mp->mnt_flag |= MNT_LOCAL; |
266 | vfs_getnewfsid(mp); | | 265 | vfs_getnewfsid(mp); |
267 | | | 266 | |
268 | if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", | | 267 | if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", |
269 | UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l)) != 0) { | | 268 | UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l)) != 0) { |
270 | free(pmnt, M_PTYFSMNT); | | 269 | free(pmnt, M_PTYFSMNT); |
271 | return error; | | 270 | return error; |
272 | } | | 271 | } |
273 | | | 272 | |
274 | /* Point pty access to us */ | | 273 | /* Point pty access to us */ |
275 | | | 274 | |
276 | ptm_ptyfspty.arg = mp; | | 275 | ptm_ptyfspty.arg = mp; |
277 | ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); | | 276 | ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); |
278 | ptyfs_count++; | | 277 | ptyfs_count++; |
279 | return 0; | | 278 | return 0; |
280 | } | | 279 | } |
281 | | | 280 | |
282 | /*ARGSUSED*/ | | 281 | /*ARGSUSED*/ |
283 | int | | 282 | int |
284 | ptyfs_start(struct mount *mp, int flags) | | 283 | ptyfs_start(struct mount *mp, int flags) |
285 | { | | 284 | { |
286 | return 0; | | 285 | return 0; |
287 | } | | 286 | } |
288 | | | 287 | |
289 | /*ARGSUSED*/ | | 288 | /*ARGSUSED*/ |
290 | int | | 289 | int |
291 | ptyfs_unmount(struct mount *mp, int mntflags) | | 290 | ptyfs_unmount(struct mount *mp, int mntflags) |
292 | { | | 291 | { |
293 | int error; | | 292 | int error; |
294 | int flags = 0; | | 293 | int flags = 0; |
295 | | | 294 | |
296 | if (mntflags & MNT_FORCE) | | 295 | if (mntflags & MNT_FORCE) |
297 | flags |= FORCECLOSE; | | 296 | flags |= FORCECLOSE; |
298 | | | 297 | |
299 | if ((error = vflush(mp, 0, flags)) != 0) | | 298 | if ((error = vflush(mp, 0, flags)) != 0) |
300 | return (error); | | 299 | return (error); |
301 | | | 300 | |
302 | /* Restore where pty access was pointing */ | | 301 | /* Restore where pty access was pointing */ |
303 | (void)pty_sethandler(ptyfs_save_ptm); | | 302 | (void)pty_sethandler(ptyfs_save_ptm); |
304 | ptyfs_save_ptm = NULL; | | 303 | ptyfs_save_ptm = NULL; |
305 | ptm_ptyfspty.arg = NULL; | | 304 | ptm_ptyfspty.arg = NULL; |
306 | | | 305 | |
307 | /* | | 306 | /* |
308 | * Finally, throw away the ptyfsmount structure | | 307 | * Finally, throw away the ptyfsmount structure |
309 | */ | | 308 | */ |
310 | free(mp->mnt_data, M_PTYFSMNT); | | 309 | free(mp->mnt_data, M_PTYFSMNT); |
311 | mp->mnt_data = NULL; | | 310 | mp->mnt_data = NULL; |
312 | ptyfs_count--; | | 311 | ptyfs_count--; |
313 | | | 312 | |
314 | return 0; | | 313 | return 0; |
315 | } | | 314 | } |
316 | | | 315 | |
317 | int | | 316 | int |
318 | ptyfs_root(struct mount *mp, struct vnode **vpp) | | 317 | ptyfs_root(struct mount *mp, struct vnode **vpp) |
319 | { | | 318 | { |
320 | /* setup "." */ | | 319 | /* setup "." */ |
321 | return ptyfs_allocvp(mp, vpp, PTYFSroot, 0, NULL); | | 320 | return ptyfs_allocvp(mp, vpp, PTYFSroot, 0, NULL); |
322 | } | | 321 | } |
323 | | | 322 | |
324 | /*ARGSUSED*/ | | 323 | /*ARGSUSED*/ |
325 | int | | 324 | int |
326 | ptyfs_sync(struct mount *mp, int waitfor, | | 325 | ptyfs_sync(struct mount *mp, int waitfor, |
327 | kauth_cred_t uc) | | 326 | kauth_cred_t uc) |
328 | { | | 327 | { |
329 | return 0; | | 328 | return 0; |
330 | } | | 329 | } |
331 | | | 330 | |
332 | /* | | 331 | /* |
333 | * Kernfs flat namespace lookup. | | 332 | * Kernfs flat namespace lookup. |
334 | * Currently unsupported. | | 333 | * Currently unsupported. |
335 | */ | | 334 | */ |
336 | /*ARGSUSED*/ | | 335 | /*ARGSUSED*/ |
337 | int | | 336 | int |
338 | ptyfs_vget(struct mount *mp, ino_t ino, | | 337 | ptyfs_vget(struct mount *mp, ino_t ino, |
339 | struct vnode **vpp) | | 338 | struct vnode **vpp) |
340 | { | | 339 | { |
341 | return EOPNOTSUPP; | | 340 | return EOPNOTSUPP; |
342 | } | | 341 | } |
343 | | | 342 | |
344 | extern const struct vnodeopv_desc ptyfs_vnodeop_opv_desc; | | 343 | extern const struct vnodeopv_desc ptyfs_vnodeop_opv_desc; |
345 | | | 344 | |
346 | const struct vnodeopv_desc * const ptyfs_vnodeopv_descs[] = { | | 345 | const struct vnodeopv_desc * const ptyfs_vnodeopv_descs[] = { |
347 | &ptyfs_vnodeop_opv_desc, | | 346 | &ptyfs_vnodeop_opv_desc, |
348 | NULL, | | 347 | NULL, |
349 | }; | | 348 | }; |
350 | | | 349 | |
351 | struct vfsops ptyfs_vfsops = { | | 350 | struct vfsops ptyfs_vfsops = { |
352 | MOUNT_PTYFS, | | 351 | MOUNT_PTYFS, |
353 | sizeof (struct ptyfs_args), | | 352 | sizeof (struct ptyfs_args), |
354 | ptyfs_mount, | | 353 | ptyfs_mount, |
355 | ptyfs_start, | | 354 | ptyfs_start, |
356 | ptyfs_unmount, | | 355 | ptyfs_unmount, |
357 | ptyfs_root, | | 356 | ptyfs_root, |
358 | (void *)eopnotsupp, /* vfs_quotactl */ | | 357 | (void *)eopnotsupp, /* vfs_quotactl */ |
359 | genfs_statvfs, | | 358 | genfs_statvfs, |
360 | ptyfs_sync, | | 359 | ptyfs_sync, |
361 | ptyfs_vget, | | 360 | ptyfs_vget, |
362 | (void *)eopnotsupp, /* vfs_fhtovp */ | | 361 | (void *)eopnotsupp, /* vfs_fhtovp */ |
363 | (void *)eopnotsupp, /* vfs_vptofp */ | | 362 | (void *)eopnotsupp, /* vfs_vptofp */ |
364 | ptyfs_init, | | 363 | ptyfs_init, |
365 | ptyfs_reinit, | | 364 | ptyfs_reinit, |
366 | ptyfs_done, | | 365 | ptyfs_done, |
367 | NULL, /* vfs_mountroot */ | | 366 | NULL, /* vfs_mountroot */ |
368 | (void *)eopnotsupp, | | 367 | (void *)eopnotsupp, |
369 | (void *)eopnotsupp, | | 368 | (void *)eopnotsupp, |
370 | (void *)eopnotsupp, /* vfs_suspendctl */ | | 369 | (void *)eopnotsupp, /* vfs_suspendctl */ |
371 | genfs_renamelock_enter, | | 370 | genfs_renamelock_enter, |
372 | genfs_renamelock_exit, | | 371 | genfs_renamelock_exit, |
373 | (void *)eopnotsupp, | | 372 | (void *)eopnotsupp, |
374 | ptyfs_vnodeopv_descs, | | 373 | ptyfs_vnodeopv_descs, |
375 | 0, | | 374 | 0, |
376 | { NULL, NULL }, | | 375 | { NULL, NULL }, |
377 | }; | | 376 | }; |
378 | | | 377 | |
379 | static int | | 378 | static int |
380 | ptyfs_modcmd(modcmd_t cmd, void *arg) | | 379 | ptyfs_modcmd(modcmd_t cmd, void *arg) |
381 | { | | 380 | { |
382 | int error; | | 381 | int error; |
383 | | | 382 | |
384 | switch (cmd) { | | 383 | switch (cmd) { |
385 | case MODULE_CMD_INIT: | | 384 | case MODULE_CMD_INIT: |
386 | error = vfs_attach(&ptyfs_vfsops); | | 385 | error = vfs_attach(&ptyfs_vfsops); |
387 | if (error != 0) | | 386 | if (error != 0) |
388 | break; | | 387 | break; |
389 | sysctl_createv(&ptyfs_sysctl_log, 0, NULL, NULL, | | 388 | sysctl_createv(&ptyfs_sysctl_log, 0, NULL, NULL, |
390 | CTLFLAG_PERMANENT, | | 389 | CTLFLAG_PERMANENT, |
391 | CTLTYPE_NODE, "vfs", NULL, | | 390 | CTLTYPE_NODE, "vfs", NULL, |
392 | NULL, 0, NULL, 0, | | 391 | NULL, 0, NULL, 0, |
393 | CTL_VFS, CTL_EOL); | | 392 | CTL_VFS, CTL_EOL); |
394 | sysctl_createv(&ptyfs_sysctl_log, 0, NULL, NULL, | | 393 | sysctl_createv(&ptyfs_sysctl_log, 0, NULL, NULL, |
395 | CTLFLAG_PERMANENT, | | 394 | CTLFLAG_PERMANENT, |
396 | CTLTYPE_NODE, "ptyfs", | | 395 | CTLTYPE_NODE, "ptyfs", |
397 | SYSCTL_DESCR("Pty file system"), | | 396 | SYSCTL_DESCR("Pty file system"), |
398 | NULL, 0, NULL, 0, | | 397 | NULL, 0, NULL, 0, |
399 | CTL_VFS, 23, CTL_EOL); | | 398 | CTL_VFS, 23, CTL_EOL); |
400 | /* | | 399 | /* |
401 | * XXX the "23" above could be dynamic, thereby eliminating | | 400 | * XXX the "23" above could be dynamic, thereby eliminating |
402 | * one more instance of the "number to vfs" mapping problem, | | 401 | * one more instance of the "number to vfs" mapping problem, |
403 | * but "23" is the order as taken from sys/mount.h | | 402 | * but "23" is the order as taken from sys/mount.h |
404 | */ | | 403 | */ |
405 | break; | | 404 | break; |
406 | case MODULE_CMD_FINI: | | 405 | case MODULE_CMD_FINI: |
407 | error = vfs_detach(&ptyfs_vfsops); | | 406 | error = vfs_detach(&ptyfs_vfsops); |
408 | if (error != 0) | | 407 | if (error != 0) |
409 | break; | | 408 | break; |
410 | sysctl_teardown(&ptyfs_sysctl_log); | | 409 | sysctl_teardown(&ptyfs_sysctl_log); |
411 | break; | | 410 | break; |
412 | default: | | 411 | default: |
413 | error = ENOTTY; | | 412 | error = ENOTTY; |
414 | break; | | 413 | break; |
415 | } | | 414 | } |
416 | | | 415 | |
417 | return (error); | | 416 | return (error); |
418 | } | | 417 | } |