| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ptyfs_vfsops.c,v 1.38 2009/01/11 02:45:51 christos Exp $ */ | | 1 | /* $NetBSD: ptyfs_vfsops.c,v 1.39 2009/03/15 16:43: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. |
| @@ -28,27 +28,27 @@ | | | @@ -28,27 +28,27 @@ |
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.38 2009/01/11 02:45:51 christos Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.39 2009/03/15 16:43: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> |
| @@ -81,41 +81,73 @@ static void ptyfs__getvattr(struct ptm_p | | | @@ -81,41 +81,73 @@ static void ptyfs__getvattr(struct ptm_p |
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 * |
| | | 95 | ptyfs__getpath(struct lwp *l, const struct mount *mp) |
| | | 96 | { |
| | | 97 | #define MAXBUF (sizeof(mp->mnt_stat.f_mntonname) + 32) |
| | | 98 | struct cwdinfo *cwdi = l->l_proc->p_cwdi; |
| | | 99 | char *buf; |
| | | 100 | const char *rv; |
| | | 101 | size_t len; |
| | | 102 | char *bp; |
| | | 103 | int error; |
| | | 104 | struct ptyfsmount *pmnt = mp->mnt_data; |
| | | 105 | |
| | | 106 | rv = mp->mnt_stat.f_mntonname; |
| | | 107 | if (cwdi->cwdi_rdir == NULL || |
| | | 108 | (pmnt->pmnt_flags & PTYFSMNT_CHROOT) == 0) |
| | | 109 | return rv; |
| | | 110 | |
| | | 111 | buf = malloc(MAXBUF, M_TEMP, M_WAITOK); |
| | | 112 | bp = buf + MAXBUF; |
| | | 113 | *--bp = '\0'; |
| | | 114 | error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, |
| | | 115 | buf, MAXBUF / 2, 0, l); |
| | | 116 | if (error) /* XXX */ |
| | | 117 | goto out; |
| | | 118 | |
| | | 119 | len = strlen(bp); |
| | | 120 | if (len < sizeof(mp->mnt_stat.f_mntonname)) /* XXX */ |
| | | 121 | rv += len; |
| | | 122 | out: |
| | | 123 | free(buf, M_TEMP); |
| | | 124 | return rv; |
| | | 125 | } |
| | | 126 | |
94 | static int | | 127 | static int |
95 | ptyfs__makename(struct ptm_pty *pt, struct lwp *l, char *tbuf, size_t bufsiz, | | 128 | ptyfs__makename(struct ptm_pty *pt, struct lwp *l, char *tbuf, size_t bufsiz, |
96 | dev_t dev, char ms) | | 129 | dev_t dev, char ms) |
97 | { | | 130 | { |
98 | struct mount *mp = pt->arg; | | 131 | struct mount *mp = pt->arg; |
99 | size_t len; | | 132 | size_t len; |
100 | | | 133 | |
101 | switch (ms) { | | 134 | switch (ms) { |
102 | case 'p': | | 135 | case 'p': |
103 | /* We don't provide access to the master, should we? */ | | 136 | /* We don't provide access to the master, should we? */ |
104 | len = snprintf(tbuf, bufsiz, "/dev/null"); | | 137 | len = snprintf(tbuf, bufsiz, "/dev/null"); |
105 | break; | | 138 | break; |
106 | case 't': | | 139 | case 't': |
107 | len = snprintf(tbuf, bufsiz, "%s/%llu", | | 140 | len = snprintf(tbuf, bufsiz, "%s/%llu", ptyfs__getpath(l, mp), |
108 | mp->mnt_stat.f_mntonname, | | | |
109 | (unsigned long long)minor(dev)); | | 141 | (unsigned long long)minor(dev)); |
110 | break; | | 142 | break; |
111 | default: | | 143 | default: |
112 | return EINVAL; | | 144 | return EINVAL; |
113 | } | | 145 | } |
114 | | | 146 | |
115 | return len >= bufsiz ? ENOSPC : 0; | | 147 | return len >= bufsiz ? ENOSPC : 0; |
116 | } | | 148 | } |
117 | | | 149 | |
118 | | | 150 | |
119 | static int | | 151 | static int |
120 | /*ARGSUSED*/ | | 152 | /*ARGSUSED*/ |
121 | ptyfs__allocvp(struct ptm_pty *pt, struct lwp *l, struct vnode **vpp, | | 153 | ptyfs__allocvp(struct ptm_pty *pt, struct lwp *l, struct vnode **vpp, |
| @@ -189,48 +221,57 @@ ptyfs_mount(struct mount *mp, const char | | | @@ -189,48 +221,57 @@ ptyfs_mount(struct mount *mp, const char |
189 | | | 221 | |
190 | if (*data_len < sizeof *args) | | 222 | if (*data_len < sizeof *args) |
191 | return EINVAL; | | 223 | return EINVAL; |
192 | | | 224 | |
193 | if (UIO_MX & (UIO_MX - 1)) { | | 225 | if (UIO_MX & (UIO_MX - 1)) { |
194 | log(LOG_ERR, "ptyfs: invalid directory entry size"); | | 226 | log(LOG_ERR, "ptyfs: invalid directory entry size"); |
195 | return EINVAL; | | 227 | return EINVAL; |
196 | } | | 228 | } |
197 | | | 229 | |
198 | if (mp->mnt_flag & MNT_GETARGS) { | | 230 | if (mp->mnt_flag & MNT_GETARGS) { |
199 | pmnt = VFSTOPTY(mp); | | 231 | pmnt = VFSTOPTY(mp); |
200 | if (pmnt == NULL) | | 232 | if (pmnt == NULL) |
201 | return EIO; | | 233 | return EIO; |
202 | args->version = PTYFS_ARGSVERSION; | | | |
203 | args->mode = pmnt->pmnt_mode; | | 234 | args->mode = pmnt->pmnt_mode; |
204 | args->gid = pmnt->pmnt_gid; | | 235 | args->gid = pmnt->pmnt_gid; |
205 | *data_len = sizeof *args; | | 236 | if (args->version >= PTYFS_ARGSVERSION) { |
| | | 237 | args->flags = pmnt->pmnt_flags; |
| | | 238 | *data_len = sizeof *args; |
| | | 239 | } else { |
| | | 240 | *data_len = |
| | | 241 | sizeof(struct { int f; gid_t g; mode_t m; }); |
| | | 242 | } |
206 | return 0; | | 243 | return 0; |
207 | } | | 244 | } |
208 | | | 245 | |
209 | /* Don't allow more than one mount */ | | 246 | /* Don't allow more than one mount */ |
210 | if (ptyfs_count) | | 247 | if (ptyfs_count) |
211 | return EBUSY; | | 248 | return EBUSY; |
212 | | | 249 | |
213 | if (mp->mnt_flag & MNT_UPDATE) | | 250 | if (mp->mnt_flag & MNT_UPDATE) |
214 | return EOPNOTSUPP; | | 251 | return EOPNOTSUPP; |
215 | | | 252 | |
216 | if (args->version != PTYFS_ARGSVERSION) | | 253 | if (args->version != PTYFS_ARGSVERSION) |
217 | return EINVAL; | | 254 | return EINVAL; |
218 | | | 255 | |
219 | pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); | | 256 | pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); |
220 | | | 257 | |
221 | mp->mnt_data = pmnt; | | 258 | mp->mnt_data = pmnt; |
222 | pmnt->pmnt_gid = args->gid; | | 259 | pmnt->pmnt_gid = args->gid; |
223 | pmnt->pmnt_mode = args->mode; | | 260 | pmnt->pmnt_mode = args->mode; |
| | | 261 | if (args->version >= PTYFS_ARGSVERSION) |
| | | 262 | pmnt->pmnt_flags = args->flags; |
| | | 263 | else |
| | | 264 | pmnt->pmnt_flags = 0; |
224 | mp->mnt_flag |= MNT_LOCAL; | | 265 | mp->mnt_flag |= MNT_LOCAL; |
225 | vfs_getnewfsid(mp); | | 266 | vfs_getnewfsid(mp); |
226 | | | 267 | |
227 | if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", | | 268 | if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", |
228 | UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l)) != 0) { | | 269 | UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l)) != 0) { |
229 | free(pmnt, M_PTYFSMNT); | | 270 | free(pmnt, M_PTYFSMNT); |
230 | return error; | | 271 | return error; |
231 | } | | 272 | } |
232 | | | 273 | |
233 | /* Point pty access to us */ | | 274 | /* Point pty access to us */ |
234 | | | 275 | |
235 | ptm_ptyfspty.arg = mp; | | 276 | ptm_ptyfspty.arg = mp; |
236 | ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); | | 277 | ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); |