int ptyfs_close(void *v) { struct vop_close_args /* { struct vnode *a_vp; int a_fflag; kauth_cred_t a_cred; } */ *ap = v; struct vnode *vp = ap->a_vp; struct ptyfsnode *ptyfs = VTOPTYFS(vp); mutex_enter(&vp->v_interlock); if (vp->v_usecount > 1) PTYFS_ITIMES(ptyfs, NULL, NULL, NULL); mutex_exit(&vp->v_interlock); switch (ptyfs->ptyfs_type) { case PTYFSpts: case PTYFSptc: return spec_close(v); case PTYFSroot: return 0; default: return EINVAL; } }
static int ptyfs_update(struct vnode *vp, const struct timespec *acc, const struct timespec *mod, int flags) { struct ptyfsnode *ptyfs = VTOPTYFS(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) return 0; PTYFS_ITIMES(ptyfs, acc, mod, NULL); return 0; }
/* * Invent attributes for ptyfsnode (vp) and store * them in (vap). * Directories lengths are returned as zero since * any real length would require the genuine size * to be computed, and nothing cares anyway. * * this is relatively minimal for ptyfs. */ int ptyfs_getattr(void *v) { struct vop_getattr_args /* { struct vnode *a_vp; struct vattr *a_vap; kauth_cred_t a_cred; } */ *ap = v; struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); struct vattr *vap = ap->a_vap; PTYFS_ITIMES(ptyfs, NULL, NULL, NULL); /* start by zeroing out the attributes */ VATTR_NULL(vap); /* next do all the common fields */ vap->va_type = ap->a_vp->v_type; vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsidx.__fsid_val[0]; vap->va_fileid = ptyfs->ptyfs_fileno; vap->va_gen = 0; vap->va_flags = 0; vap->va_nlink = 1; vap->va_blocksize = PAGE_SIZE; vap->va_atime = ptyfs->ptyfs_atime; vap->va_mtime = ptyfs->ptyfs_mtime; vap->va_ctime = ptyfs->ptyfs_ctime; vap->va_birthtime = ptyfs->ptyfs_birthtime; vap->va_mode = ptyfs->ptyfs_mode; vap->va_flags = ptyfs->ptyfs_flags; vap->va_uid = ptyfs->ptyfs_uid; vap->va_gid = ptyfs->ptyfs_gid; switch (ptyfs->ptyfs_type) { case PTYFSpts: case PTYFSptc: if (pty_isfree(ptyfs->ptyfs_pty, 1)) return ENOENT; vap->va_bytes = vap->va_size = 0; vap->va_rdev = ap->a_vp->v_rdev; break; case PTYFSroot: vap->va_rdev = 0; vap->va_bytes = vap->va_size = DEV_BSIZE; break; default: return EOPNOTSUPP; } return 0; }
static void ptyfs_getinfo(struct ptyfsnode *ptyfs, struct lwp *l) { extern struct ptm_pty *ptyfs_save_ptm, ptm_ptyfspty; if (ptyfs->ptyfs_type == PTYFSroot) { ptyfs->ptyfs_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP| S_IROTH|S_IXOTH; goto out; } else ptyfs->ptyfs_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP| S_IROTH|S_IWOTH; if (ptyfs_save_ptm != NULL && ptyfs_save_ptm != &ptm_ptyfspty) { int error; struct pathbuf *pb; struct nameidata nd; char ttyname[64]; kauth_cred_t cred; struct vattr va; /* * We support traditional ptys, so we copy the info * from the inode */ if ((error = (*ptyfs_save_ptm->makename)( ptyfs_save_ptm, l, ttyname, sizeof(ttyname), ptyfs->ptyfs_pty, ptyfs->ptyfs_type == PTYFSpts ? 't' : 'p')) != 0) goto out; pb = pathbuf_create(ttyname); if (pb == NULL) { error = ENOMEM; goto out; } NDINIT(&nd, LOOKUP, NOFOLLOW|LOCKLEAF, pb); if ((error = namei(&nd)) != 0) { pathbuf_destroy(pb); goto out; } cred = kauth_cred_alloc(); error = VOP_GETATTR(nd.ni_vp, &va, cred); kauth_cred_free(cred); VOP_UNLOCK(nd.ni_vp); vrele(nd.ni_vp); pathbuf_destroy(pb); if (error) goto out; ptyfs->ptyfs_uid = va.va_uid; ptyfs->ptyfs_gid = va.va_gid; ptyfs->ptyfs_mode = va.va_mode; ptyfs->ptyfs_flags = va.va_flags; ptyfs->ptyfs_birthtime = va.va_birthtime; ptyfs->ptyfs_ctime = va.va_ctime; ptyfs->ptyfs_mtime = va.va_mtime; ptyfs->ptyfs_atime = va.va_atime; return; } out: ptyfs->ptyfs_uid = ptyfs->ptyfs_gid = 0; ptyfs->ptyfs_status |= PTYFS_CHANGE; PTYFS_ITIMES(ptyfs, NULL, NULL, NULL); ptyfs->ptyfs_birthtime = ptyfs->ptyfs_mtime = ptyfs->ptyfs_atime = ptyfs->ptyfs_ctime; ptyfs->ptyfs_flags = 0; }