1 1.58 pgoyette /* $NetBSD: ptyfs_vfsops.c,v 1.58 2020/03/16 21:20:10 pgoyette Exp $ */ 2 1.1 jdolecek 3 1.1 jdolecek /* 4 1.1 jdolecek * Copyright (c) 1992, 1993, 1995 5 1.1 jdolecek * The Regents of the University of California. All rights reserved. 6 1.1 jdolecek * 7 1.1 jdolecek * This code is derived from software donated to Berkeley by 8 1.1 jdolecek * Jan-Simon Pendry. 9 1.1 jdolecek * 10 1.1 jdolecek * Redistribution and use in source and binary forms, with or without 11 1.1 jdolecek * modification, are permitted provided that the following conditions 12 1.1 jdolecek * are met: 13 1.1 jdolecek * 1. Redistributions of source code must retain the above copyright 14 1.1 jdolecek * notice, this list of conditions and the following disclaimer. 15 1.1 jdolecek * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 jdolecek * notice, this list of conditions and the following disclaimer in the 17 1.1 jdolecek * documentation and/or other materials provided with the distribution. 18 1.1 jdolecek * 3. Neither the name of the University nor the names of its contributors 19 1.1 jdolecek * may be used to endorse or promote products derived from this software 20 1.1 jdolecek * without specific prior written permission. 21 1.1 jdolecek * 22 1.1 jdolecek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 1.1 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 1.1 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 1.1 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 1.1 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 1.1 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 1.1 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 1.1 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 1.1 jdolecek * SUCH DAMAGE. 33 1.1 jdolecek * 34 1.1 jdolecek */ 35 1.1 jdolecek 36 1.1 jdolecek /* 37 1.1 jdolecek * Pseudo-tty Filesystem 38 1.1 jdolecek */ 39 1.1 jdolecek 40 1.1 jdolecek #include <sys/cdefs.h> 41 1.58 pgoyette __KERNEL_RCSID(0, "$NetBSD: ptyfs_vfsops.c,v 1.58 2020/03/16 21:20:10 pgoyette Exp $"); 42 1.1 jdolecek 43 1.1 jdolecek #include <sys/param.h> 44 1.1 jdolecek #include <sys/systm.h> 45 1.1 jdolecek #include <sys/sysctl.h> 46 1.1 jdolecek #include <sys/conf.h> 47 1.1 jdolecek #include <sys/proc.h> 48 1.1 jdolecek #include <sys/vnode.h> 49 1.1 jdolecek #include <sys/mount.h> 50 1.1 jdolecek #include <sys/namei.h> 51 1.3 christos #include <sys/stat.h> 52 1.1 jdolecek #include <sys/dirent.h> 53 1.1 jdolecek #include <sys/malloc.h> 54 1.1 jdolecek #include <sys/syslog.h> 55 1.1 jdolecek #include <sys/select.h> 56 1.13 christos #include <sys/filedesc.h> 57 1.1 jdolecek #include <sys/tty.h> 58 1.1 jdolecek #include <sys/pty.h> 59 1.15 elad #include <sys/kauth.h> 60 1.33 rumble #include <sys/module.h> 61 1.1 jdolecek 62 1.2 jdolecek #include <fs/ptyfs/ptyfs.h> 63 1.31 dholland #include <miscfs/genfs/genfs.h> 64 1.1 jdolecek #include <miscfs/specfs/specdev.h> 65 1.1 jdolecek 66 1.33 rumble MODULE(MODULE_CLASS_VFS, ptyfs, NULL); 67 1.33 rumble 68 1.24 pooka MALLOC_JUSTDEFINE(M_PTYFSMNT, "ptyfs mount", "ptyfs mount structures"); 69 1.29 rumble MALLOC_JUSTDEFINE(M_PTYFSTMP, "ptyfs temp", "ptyfs temporary structures"); 70 1.1 jdolecek 71 1.28 pooka VFS_PROTOS(ptyfs); 72 1.1 jdolecek 73 1.48 christos static int ptyfs__allocvp(struct mount *, struct lwp *, struct vnode **, 74 1.1 jdolecek dev_t, char); 75 1.48 christos static int ptyfs__makename(struct mount *, struct lwp *, char *, size_t, 76 1.13 christos dev_t, char); 77 1.48 christos static void ptyfs__getvattr(struct mount *, struct lwp *, struct vattr *); 78 1.49 christos static int ptyfs__getmp(struct lwp *, struct mount **); 79 1.1 jdolecek 80 1.1 jdolecek /* 81 1.1 jdolecek * ptm glue: When we mount, we make ptm point to us. 82 1.1 jdolecek */ 83 1.1 jdolecek struct ptm_pty *ptyfs_save_ptm; 84 1.11 christos static int ptyfs_count; 85 1.1 jdolecek 86 1.49 christos static TAILQ_HEAD(, ptyfsmount) ptyfs_head; 87 1.49 christos 88 1.1 jdolecek struct ptm_pty ptm_ptyfspty = { 89 1.1 jdolecek ptyfs__allocvp, 90 1.1 jdolecek ptyfs__makename, 91 1.3 christos ptyfs__getvattr, 92 1.49 christos ptyfs__getmp, 93 1.1 jdolecek }; 94 1.1 jdolecek 95 1.49 christos static int 96 1.49 christos ptyfs__getmp(struct lwp *l, struct mount **mpp) 97 1.49 christos { 98 1.49 christos struct cwdinfo *cwdi = l->l_proc->p_cwdi; 99 1.49 christos struct mount *mp; 100 1.49 christos struct ptyfsmount *pmnt; 101 1.49 christos 102 1.49 christos TAILQ_FOREACH(pmnt, &ptyfs_head, pmnt_le) { 103 1.49 christos mp = pmnt->pmnt_mp; 104 1.49 christos if (cwdi->cwdi_rdir == NULL) 105 1.49 christos goto ok; 106 1.49 christos 107 1.49 christos if (vn_isunder(mp->mnt_vnodecovered, cwdi->cwdi_rdir, l)) 108 1.49 christos goto ok; 109 1.49 christos } 110 1.49 christos *mpp = NULL; 111 1.49 christos return EOPNOTSUPP; 112 1.49 christos ok: 113 1.49 christos *mpp = mp; 114 1.49 christos return 0; 115 1.49 christos } 116 1.49 christos 117 1.39 christos static const char * 118 1.39 christos ptyfs__getpath(struct lwp *l, const struct mount *mp) 119 1.39 christos { 120 1.39 christos #define MAXBUF (sizeof(mp->mnt_stat.f_mntonname) + 32) 121 1.39 christos struct cwdinfo *cwdi = l->l_proc->p_cwdi; 122 1.39 christos char *buf; 123 1.39 christos const char *rv; 124 1.39 christos size_t len; 125 1.39 christos char *bp; 126 1.39 christos int error; 127 1.39 christos 128 1.39 christos rv = mp->mnt_stat.f_mntonname; 129 1.43 christos if (cwdi->cwdi_rdir == NULL) 130 1.39 christos return rv; 131 1.39 christos 132 1.39 christos buf = malloc(MAXBUF, M_TEMP, M_WAITOK); 133 1.39 christos bp = buf + MAXBUF; 134 1.39 christos *--bp = '\0'; 135 1.46 christos error = getcwd_common(mp->mnt_vnodecovered, cwdi->cwdi_rdir, &bp, 136 1.39 christos buf, MAXBUF / 2, 0, l); 137 1.46 christos if (error) { /* Mount point is out of rdir */ 138 1.46 christos rv = NULL; 139 1.39 christos goto out; 140 1.46 christos } 141 1.39 christos 142 1.39 christos len = strlen(bp); 143 1.39 christos if (len < sizeof(mp->mnt_stat.f_mntonname)) /* XXX */ 144 1.46 christos rv += strlen(rv) - len; 145 1.39 christos out: 146 1.39 christos free(buf, M_TEMP); 147 1.39 christos return rv; 148 1.39 christos } 149 1.39 christos 150 1.1 jdolecek static int 151 1.48 christos ptyfs__makename(struct mount *mp, struct lwp *l, char *tbuf, size_t bufsiz, 152 1.13 christos dev_t dev, char ms) 153 1.1 jdolecek { 154 1.1 jdolecek size_t len; 155 1.46 christos const char *np; 156 1.51 hannken int pty = minor(dev); 157 1.1 jdolecek 158 1.1 jdolecek switch (ms) { 159 1.1 jdolecek case 'p': 160 1.1 jdolecek /* We don't provide access to the master, should we? */ 161 1.8 christos len = snprintf(tbuf, bufsiz, "/dev/null"); 162 1.1 jdolecek break; 163 1.1 jdolecek case 't': 164 1.49 christos /* 165 1.49 christos * We support traditional ptys, so we can get here, 166 1.49 christos * if pty had been opened before PTYFS was mounted, 167 1.49 christos * or was opened through /dev/ptyXX devices. 168 1.49 christos * Return it only outside chroot for more security . 169 1.49 christos */ 170 1.49 christos if (l->l_proc->p_cwdi->cwdi_rdir == NULL 171 1.49 christos && ptyfs_save_ptm != NULL 172 1.51 hannken && ptyfs_next_active(mp, pty) != pty) 173 1.49 christos return (*ptyfs_save_ptm->makename)(mp, l, 174 1.49 christos tbuf, bufsiz, dev, ms); 175 1.49 christos 176 1.46 christos np = ptyfs__getpath(l, mp); 177 1.46 christos if (np == NULL) 178 1.46 christos return EOPNOTSUPP; 179 1.46 christos len = snprintf(tbuf, bufsiz, "%s/%llu", np, 180 1.46 christos (unsigned long long)minor(dev)); 181 1.1 jdolecek break; 182 1.1 jdolecek default: 183 1.1 jdolecek return EINVAL; 184 1.1 jdolecek } 185 1.1 jdolecek 186 1.1 jdolecek return len >= bufsiz ? ENOSPC : 0; 187 1.1 jdolecek } 188 1.1 jdolecek 189 1.3 christos 190 1.1 jdolecek static int 191 1.1 jdolecek /*ARGSUSED*/ 192 1.48 christos ptyfs__allocvp(struct mount *mp, struct lwp *l, struct vnode **vpp, 193 1.1 jdolecek dev_t dev, char ms) 194 1.1 jdolecek { 195 1.51 hannken int error; 196 1.1 jdolecek ptyfstype type; 197 1.1 jdolecek 198 1.1 jdolecek switch (ms) { 199 1.1 jdolecek case 'p': 200 1.1 jdolecek type = PTYFSptc; 201 1.1 jdolecek break; 202 1.1 jdolecek case 't': 203 1.1 jdolecek type = PTYFSpts; 204 1.1 jdolecek break; 205 1.1 jdolecek default: 206 1.1 jdolecek return EINVAL; 207 1.1 jdolecek } 208 1.1 jdolecek 209 1.51 hannken error = ptyfs_allocvp(mp, vpp, type, minor(dev)); 210 1.53 hannken if (error) 211 1.53 hannken return error; 212 1.53 hannken error = vn_lock(*vpp, LK_EXCLUSIVE); 213 1.53 hannken if (error) { 214 1.53 hannken vrele(*vpp); 215 1.53 hannken *vpp = NULL; 216 1.53 hannken return error; 217 1.53 hannken } 218 1.55 christos if (type == PTYFSptc) 219 1.51 hannken ptyfs_set_active(mp, minor(dev)); 220 1.53 hannken return 0; 221 1.1 jdolecek } 222 1.1 jdolecek 223 1.3 christos 224 1.3 christos static void 225 1.48 christos ptyfs__getvattr(struct mount *mp, struct lwp *l, struct vattr *vattr) 226 1.3 christos { 227 1.3 christos struct ptyfsmount *pmnt = VFSTOPTY(mp); 228 1.42 pooka vattr_null(vattr); 229 1.3 christos /* get real uid */ 230 1.18 ad vattr->va_uid = kauth_cred_getuid(l->l_cred); 231 1.3 christos vattr->va_gid = pmnt->pmnt_gid; 232 1.3 christos vattr->va_mode = pmnt->pmnt_mode; 233 1.3 christos } 234 1.3 christos 235 1.3 christos 236 1.1 jdolecek void 237 1.1 jdolecek ptyfs_init(void) 238 1.1 jdolecek { 239 1.24 pooka 240 1.49 christos TAILQ_INIT(&ptyfs_head); 241 1.1 jdolecek malloc_type_attach(M_PTYFSMNT); 242 1.29 rumble malloc_type_attach(M_PTYFSTMP); 243 1.1 jdolecek ptyfs_hashinit(); 244 1.1 jdolecek } 245 1.1 jdolecek 246 1.1 jdolecek void 247 1.1 jdolecek ptyfs_reinit(void) 248 1.1 jdolecek { 249 1.53 hannken 250 1.1 jdolecek } 251 1.1 jdolecek 252 1.1 jdolecek void 253 1.1 jdolecek ptyfs_done(void) 254 1.1 jdolecek { 255 1.24 pooka 256 1.24 pooka ptyfs_hashdone(); 257 1.29 rumble malloc_type_detach(M_PTYFSTMP); 258 1.1 jdolecek malloc_type_detach(M_PTYFSMNT); 259 1.1 jdolecek } 260 1.1 jdolecek 261 1.40 christos #define OSIZE sizeof(struct { int f; gid_t g; mode_t m; }) 262 1.1 jdolecek /* 263 1.1 jdolecek * Mount the Pseudo tty params filesystem 264 1.1 jdolecek */ 265 1.1 jdolecek int 266 1.30 pooka ptyfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) 267 1.1 jdolecek { 268 1.30 pooka struct lwp *l = curlwp; 269 1.1 jdolecek int error = 0; 270 1.3 christos struct ptyfsmount *pmnt; 271 1.25 dsl struct ptyfs_args *args = data; 272 1.25 dsl 273 1.50 maxv if (args == NULL) 274 1.50 maxv return EINVAL; 275 1.52 maxv if (*data_len != sizeof *args) { 276 1.52 maxv if (*data_len != OSIZE || args->version >= PTYFS_ARGSVERSION) 277 1.52 maxv return EINVAL; 278 1.52 maxv } 279 1.1 jdolecek 280 1.1 jdolecek if (UIO_MX & (UIO_MX - 1)) { 281 1.1 jdolecek log(LOG_ERR, "ptyfs: invalid directory entry size"); 282 1.1 jdolecek return EINVAL; 283 1.1 jdolecek } 284 1.1 jdolecek 285 1.3 christos if (mp->mnt_flag & MNT_GETARGS) { 286 1.3 christos pmnt = VFSTOPTY(mp); 287 1.3 christos if (pmnt == NULL) 288 1.3 christos return EIO; 289 1.25 dsl args->mode = pmnt->pmnt_mode; 290 1.25 dsl args->gid = pmnt->pmnt_gid; 291 1.39 christos if (args->version >= PTYFS_ARGSVERSION) { 292 1.39 christos args->flags = pmnt->pmnt_flags; 293 1.39 christos *data_len = sizeof *args; 294 1.39 christos } else { 295 1.40 christos *data_len = OSIZE; 296 1.39 christos } 297 1.25 dsl return 0; 298 1.3 christos } 299 1.3 christos 300 1.44 christos #if 0 301 1.14 christos /* Don't allow more than one mount */ 302 1.14 christos if (ptyfs_count) 303 1.14 christos return EBUSY; 304 1.44 christos #endif 305 1.14 christos 306 1.1 jdolecek if (mp->mnt_flag & MNT_UPDATE) 307 1.1 jdolecek return EOPNOTSUPP; 308 1.1 jdolecek 309 1.40 christos if (args->version > PTYFS_ARGSVERSION) 310 1.7 christos return EINVAL; 311 1.3 christos 312 1.29 rumble pmnt = malloc(sizeof(struct ptyfsmount), M_PTYFSMNT, M_WAITOK); 313 1.3 christos 314 1.3 christos mp->mnt_data = pmnt; 315 1.51 hannken mutex_init(&pmnt->pmnt_lock, MUTEX_DEFAULT, IPL_NONE); 316 1.25 dsl pmnt->pmnt_gid = args->gid; 317 1.25 dsl pmnt->pmnt_mode = args->mode; 318 1.39 christos if (args->version >= PTYFS_ARGSVERSION) 319 1.39 christos pmnt->pmnt_flags = args->flags; 320 1.39 christos else 321 1.39 christos pmnt->pmnt_flags = 0; 322 1.51 hannken pmnt->pmnt_bitmap_size = 0; 323 1.51 hannken pmnt->pmnt_bitmap = NULL; 324 1.1 jdolecek mp->mnt_flag |= MNT_LOCAL; 325 1.1 jdolecek vfs_getnewfsid(mp); 326 1.1 jdolecek 327 1.1 jdolecek if ((error = set_statvfs_info(path, UIO_USERSPACE, "ptyfs", 328 1.26 pooka UIO_SYSSPACE, mp->mnt_op->vfs_name, mp, l)) != 0) { 329 1.34 simonb free(pmnt, M_PTYFSMNT); 330 1.1 jdolecek return error; 331 1.1 jdolecek } 332 1.1 jdolecek 333 1.49 christos pmnt->pmnt_mp = mp; 334 1.49 christos TAILQ_INSERT_TAIL(&ptyfs_head, pmnt, pmnt_le); 335 1.49 christos if (ptyfs_count++ == 0) { 336 1.49 christos /* Point pty access to us */ 337 1.44 christos ptyfs_save_ptm = pty_sethandler(&ptm_ptyfspty); 338 1.44 christos } 339 1.1 jdolecek return 0; 340 1.1 jdolecek } 341 1.1 jdolecek 342 1.1 jdolecek /*ARGSUSED*/ 343 1.1 jdolecek int 344 1.30 pooka ptyfs_start(struct mount *mp, int flags) 345 1.1 jdolecek { 346 1.1 jdolecek return 0; 347 1.1 jdolecek } 348 1.1 jdolecek 349 1.1 jdolecek /*ARGSUSED*/ 350 1.1 jdolecek int 351 1.30 pooka ptyfs_unmount(struct mount *mp, int mntflags) 352 1.1 jdolecek { 353 1.1 jdolecek int error; 354 1.1 jdolecek int flags = 0; 355 1.49 christos struct ptyfsmount *pmnt; 356 1.1 jdolecek 357 1.1 jdolecek if (mntflags & MNT_FORCE) 358 1.1 jdolecek flags |= FORCECLOSE; 359 1.1 jdolecek 360 1.1 jdolecek if ((error = vflush(mp, 0, flags)) != 0) 361 1.44 christos return error; 362 1.1 jdolecek 363 1.44 christos ptyfs_count--; 364 1.44 christos if (ptyfs_count == 0) { 365 1.44 christos /* Restore where pty access was pointing */ 366 1.44 christos (void)pty_sethandler(ptyfs_save_ptm); 367 1.44 christos ptyfs_save_ptm = NULL; 368 1.44 christos } 369 1.49 christos TAILQ_FOREACH(pmnt, &ptyfs_head, pmnt_le) { 370 1.49 christos if (pmnt->pmnt_mp == mp) { 371 1.49 christos TAILQ_REMOVE(&ptyfs_head, pmnt, pmnt_le); 372 1.49 christos break; 373 1.49 christos } 374 1.49 christos } 375 1.3 christos 376 1.1 jdolecek /* 377 1.3 christos * Finally, throw away the ptyfsmount structure 378 1.1 jdolecek */ 379 1.51 hannken if (pmnt->pmnt_bitmap_size > 0) 380 1.51 hannken kmem_free(pmnt->pmnt_bitmap, pmnt->pmnt_bitmap_size); 381 1.51 hannken mutex_destroy(&pmnt->pmnt_lock); 382 1.34 simonb free(mp->mnt_data, M_PTYFSMNT); 383 1.35 simonb mp->mnt_data = NULL; 384 1.3 christos 385 1.1 jdolecek return 0; 386 1.1 jdolecek } 387 1.1 jdolecek 388 1.1 jdolecek int 389 1.57 ad ptyfs_root(struct mount *mp, int lktype, struct vnode **vpp) 390 1.1 jdolecek { 391 1.53 hannken int error; 392 1.53 hannken 393 1.1 jdolecek /* setup "." */ 394 1.53 hannken error = ptyfs_allocvp(mp, vpp, PTYFSroot, 0); 395 1.53 hannken if (error) 396 1.53 hannken return error; 397 1.57 ad error = vn_lock(*vpp, lktype); 398 1.53 hannken if (error) { 399 1.53 hannken vrele(*vpp); 400 1.53 hannken *vpp = NULL; 401 1.53 hannken return error; 402 1.53 hannken } 403 1.53 hannken return 0; 404 1.1 jdolecek } 405 1.1 jdolecek 406 1.1 jdolecek /*ARGSUSED*/ 407 1.1 jdolecek int 408 1.21 christos ptyfs_sync(struct mount *mp, int waitfor, 409 1.30 pooka kauth_cred_t uc) 410 1.1 jdolecek { 411 1.1 jdolecek return 0; 412 1.1 jdolecek } 413 1.1 jdolecek 414 1.1 jdolecek /* 415 1.53 hannken * Initialize this vnode / ptynode pair. 416 1.54 christos * Only for the slave side of a pty, caller assures 417 1.54 christos * no other thread will try to load this node. 418 1.53 hannken */ 419 1.53 hannken int 420 1.53 hannken ptyfs_loadvnode(struct mount *mp, struct vnode *vp, 421 1.53 hannken const void *key, size_t key_len, const void **new_key) 422 1.53 hannken { 423 1.53 hannken struct ptyfskey pkey; 424 1.53 hannken struct ptyfsnode *ptyfs; 425 1.53 hannken 426 1.53 hannken KASSERT(key_len == sizeof(pkey)); 427 1.53 hannken memcpy(&pkey, key, key_len); 428 1.53 hannken 429 1.53 hannken ptyfs = ptyfs_get_node(pkey.ptk_type, pkey.ptk_pty); 430 1.53 hannken KASSERT(memcmp(&ptyfs->ptyfs_key, &pkey, sizeof(pkey)) == 0); 431 1.53 hannken 432 1.53 hannken switch (pkey.ptk_type) { 433 1.53 hannken case PTYFSroot: /* /pts = dr-xr-xr-x */ 434 1.53 hannken vp->v_type = VDIR; 435 1.53 hannken vp->v_vflag = VV_ROOT; 436 1.53 hannken break; 437 1.53 hannken 438 1.53 hannken case PTYFSpts: /* /pts/N = cxxxxxxxxx */ 439 1.53 hannken case PTYFSptc: /* controlling side = cxxxxxxxxx */ 440 1.53 hannken vp->v_type = VCHR; 441 1.53 hannken spec_node_init(vp, PTYFS_MAKEDEV(ptyfs)); 442 1.53 hannken break; 443 1.53 hannken default: 444 1.53 hannken panic("ptyfs_loadvnode"); 445 1.53 hannken } 446 1.53 hannken 447 1.53 hannken vp->v_tag = VT_PTYFS; 448 1.53 hannken vp->v_op = ptyfs_vnodeop_p; 449 1.53 hannken vp->v_data = ptyfs; 450 1.53 hannken uvm_vnp_setsize(vp, 0); 451 1.53 hannken *new_key = &ptyfs->ptyfs_key; 452 1.53 hannken return 0; 453 1.53 hannken } 454 1.53 hannken 455 1.53 hannken /* 456 1.1 jdolecek * Kernfs flat namespace lookup. 457 1.1 jdolecek * Currently unsupported. 458 1.1 jdolecek */ 459 1.1 jdolecek /*ARGSUSED*/ 460 1.1 jdolecek int 461 1.57 ad ptyfs_vget(struct mount *mp, ino_t ino, int lktype, 462 1.21 christos struct vnode **vpp) 463 1.1 jdolecek { 464 1.1 jdolecek return EOPNOTSUPP; 465 1.1 jdolecek } 466 1.1 jdolecek 467 1.1 jdolecek extern const struct vnodeopv_desc ptyfs_vnodeop_opv_desc; 468 1.1 jdolecek 469 1.1 jdolecek const struct vnodeopv_desc * const ptyfs_vnodeopv_descs[] = { 470 1.1 jdolecek &ptyfs_vnodeop_opv_desc, 471 1.1 jdolecek NULL, 472 1.1 jdolecek }; 473 1.1 jdolecek 474 1.1 jdolecek struct vfsops ptyfs_vfsops = { 475 1.47 hannken .vfs_name = MOUNT_PTYFS, 476 1.47 hannken .vfs_min_mount_data = sizeof (struct ptyfs_args), 477 1.47 hannken .vfs_mount = ptyfs_mount, 478 1.47 hannken .vfs_start = ptyfs_start, 479 1.47 hannken .vfs_unmount = ptyfs_unmount, 480 1.47 hannken .vfs_root = ptyfs_root, 481 1.47 hannken .vfs_quotactl = (void *)eopnotsupp, 482 1.47 hannken .vfs_statvfs = genfs_statvfs, 483 1.47 hannken .vfs_sync = ptyfs_sync, 484 1.47 hannken .vfs_vget = ptyfs_vget, 485 1.53 hannken .vfs_loadvnode = ptyfs_loadvnode, 486 1.47 hannken .vfs_fhtovp = (void *)eopnotsupp, 487 1.47 hannken .vfs_vptofh = (void *)eopnotsupp, 488 1.47 hannken .vfs_init = ptyfs_init, 489 1.47 hannken .vfs_reinit = ptyfs_reinit, 490 1.47 hannken .vfs_done = ptyfs_done, 491 1.47 hannken .vfs_snapshot = (void *)eopnotsupp, 492 1.47 hannken .vfs_extattrctl = (void *)eopnotsupp, 493 1.56 hannken .vfs_suspendctl = genfs_suspendctl, 494 1.47 hannken .vfs_renamelock_enter = genfs_renamelock_enter, 495 1.47 hannken .vfs_renamelock_exit = genfs_renamelock_exit, 496 1.47 hannken .vfs_fsync = (void *)eopnotsupp, 497 1.47 hannken .vfs_opv_descs = ptyfs_vnodeopv_descs 498 1.1 jdolecek }; 499 1.33 rumble 500 1.58 pgoyette SYSCTL_SETUP(ptyfs_sysctl_setup, "ptyfs sysctl") 501 1.58 pgoyette { 502 1.58 pgoyette 503 1.58 pgoyette sysctl_createv(clog, 0, NULL, NULL, 504 1.58 pgoyette CTLFLAG_PERMANENT, 505 1.58 pgoyette CTLTYPE_NODE, "ptyfs", 506 1.58 pgoyette SYSCTL_DESCR("Pty file system"), 507 1.58 pgoyette NULL, 0, NULL, 0, 508 1.58 pgoyette CTL_VFS, 23, CTL_EOL); 509 1.58 pgoyette /* 510 1.58 pgoyette * XXX the "23" above could be dynamic, thereby eliminating 511 1.58 pgoyette * one more instance of the "number to vfs" mapping problem, 512 1.58 pgoyette * but "23" is the order as taken from sys/mount.h 513 1.58 pgoyette */ 514 1.58 pgoyette } 515 1.58 pgoyette 516 1.33 rumble static int 517 1.33 rumble ptyfs_modcmd(modcmd_t cmd, void *arg) 518 1.33 rumble { 519 1.36 rumble int error; 520 1.33 rumble 521 1.33 rumble switch (cmd) { 522 1.33 rumble case MODULE_CMD_INIT: 523 1.36 rumble error = vfs_attach(&ptyfs_vfsops); 524 1.36 rumble if (error != 0) 525 1.36 rumble break; 526 1.36 rumble break; 527 1.33 rumble case MODULE_CMD_FINI: 528 1.36 rumble error = vfs_detach(&ptyfs_vfsops); 529 1.36 rumble if (error != 0) 530 1.36 rumble break; 531 1.36 rumble break; 532 1.33 rumble default: 533 1.36 rumble error = ENOTTY; 534 1.36 rumble break; 535 1.33 rumble } 536 1.36 rumble 537 1.36 rumble return (error); 538 1.33 rumble } 539