version 1.36.2.3, 2014/05/22 11:41:01 |
version 1.37, 2011/11/18 21:18:50 |
Line 141 int ptyfs_readdir (void *); |
|
Line 141 int ptyfs_readdir (void *); |
|
#define ptyfs_readlink genfs_eopnotsupp |
#define ptyfs_readlink genfs_eopnotsupp |
#define ptyfs_abortop genfs_abortop |
#define ptyfs_abortop genfs_abortop |
int ptyfs_reclaim (void *); |
int ptyfs_reclaim (void *); |
int ptyfs_inactive (void *); |
|
#define ptyfs_lock genfs_lock |
#define ptyfs_lock genfs_lock |
#define ptyfs_unlock genfs_unlock |
#define ptyfs_unlock genfs_unlock |
#define ptyfs_bmap genfs_badop |
#define ptyfs_bmap genfs_badop |
Line 149 int ptyfs_inactive (void *); |
|
Line 148 int ptyfs_inactive (void *); |
|
int ptyfs_print (void *); |
int ptyfs_print (void *); |
int ptyfs_pathconf (void *); |
int ptyfs_pathconf (void *); |
#define ptyfs_islocked genfs_islocked |
#define ptyfs_islocked genfs_islocked |
int ptyfs_advlock (void *); |
#define ptyfs_advlock genfs_einval |
#define ptyfs_bwrite genfs_eopnotsupp |
#define ptyfs_bwrite genfs_eopnotsupp |
#define ptyfs_putpages genfs_null_putpages |
#define ptyfs_putpages genfs_null_putpages |
|
|
Line 193 const struct vnodeopv_entry_desc ptyfs_v |
|
Line 192 const struct vnodeopv_entry_desc ptyfs_v |
|
{ &vop_readdir_desc, ptyfs_readdir }, /* readdir */ |
{ &vop_readdir_desc, ptyfs_readdir }, /* readdir */ |
{ &vop_readlink_desc, ptyfs_readlink }, /* readlink */ |
{ &vop_readlink_desc, ptyfs_readlink }, /* readlink */ |
{ &vop_abortop_desc, ptyfs_abortop }, /* abortop */ |
{ &vop_abortop_desc, ptyfs_abortop }, /* abortop */ |
{ &vop_inactive_desc, ptyfs_inactive }, /* inactive */ |
{ &vop_inactive_desc, spec_inactive }, /* inactive */ |
{ &vop_reclaim_desc, ptyfs_reclaim }, /* reclaim */ |
{ &vop_reclaim_desc, ptyfs_reclaim }, /* reclaim */ |
{ &vop_lock_desc, ptyfs_lock }, /* lock */ |
{ &vop_lock_desc, ptyfs_lock }, /* lock */ |
{ &vop_unlock_desc, ptyfs_unlock }, /* unlock */ |
{ &vop_unlock_desc, ptyfs_unlock }, /* unlock */ |
Line 226 ptyfs_reclaim(void *v) |
|
Line 225 ptyfs_reclaim(void *v) |
|
return ptyfs_freevp(ap->a_vp); |
return ptyfs_freevp(ap->a_vp); |
} |
} |
|
|
int |
|
ptyfs_inactive(void *v) |
|
{ |
|
struct vop_inactive_args /* { |
|
struct vnode *a_vp; |
|
bool *a_recycle; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
|
|
|
switch (ptyfs->ptyfs_type) { |
|
case PTYFSpts: |
|
case PTYFSptc: |
|
/* Emulate file deletion for call reclaim(). */ |
|
*ap->a_recycle = true; |
|
break; |
|
default: |
|
break; |
|
} |
|
return spec_inactive(v); |
|
} |
|
|
|
/* |
/* |
* Return POSIX pathconf information applicable to special devices. |
* Return POSIX pathconf information applicable to special devices. |
*/ |
*/ |
Line 306 ptyfs_print(void *v) |
|
Line 283 ptyfs_print(void *v) |
|
} |
} |
|
|
/* |
/* |
* support advisory locking on pty nodes |
|
*/ |
|
int |
|
ptyfs_advlock(void *v) |
|
{ |
|
struct vop_print_args /* { |
|
struct vnode *a_vp; |
|
} */ *ap = v; |
|
struct ptyfsnode *ptyfs = VTOPTYFS(ap->a_vp); |
|
|
|
switch (ptyfs->ptyfs_type) { |
|
case PTYFSpts: |
|
case PTYFSptc: |
|
return spec_advlock(v); |
|
default: |
|
return EOPNOTSUPP; |
|
} |
|
} |
|
|
|
/* |
|
* Invent attributes for ptyfsnode (vp) and store |
* Invent attributes for ptyfsnode (vp) and store |
* them in (vap). |
* them in (vap). |
* Directories lengths are returned as zero since |
* Directories lengths are returned as zero since |
Line 356 ptyfs_getattr(void *v) |
|
Line 313 ptyfs_getattr(void *v) |
|
vap->va_fileid = ptyfs->ptyfs_fileno; |
vap->va_fileid = ptyfs->ptyfs_fileno; |
vap->va_gen = 0; |
vap->va_gen = 0; |
vap->va_flags = 0; |
vap->va_flags = 0; |
|
vap->va_nlink = 1; |
vap->va_blocksize = PAGE_SIZE; |
vap->va_blocksize = PAGE_SIZE; |
|
|
vap->va_atime = ptyfs->ptyfs_atime; |
vap->va_atime = ptyfs->ptyfs_atime; |
Line 374 ptyfs_getattr(void *v) |
|
Line 332 ptyfs_getattr(void *v) |
|
return ENOENT; |
return ENOENT; |
vap->va_bytes = vap->va_size = 0; |
vap->va_bytes = vap->va_size = 0; |
vap->va_rdev = ap->a_vp->v_rdev; |
vap->va_rdev = ap->a_vp->v_rdev; |
vap->va_nlink = 1; |
|
break; |
break; |
case PTYFSroot: |
case PTYFSroot: |
vap->va_rdev = 0; |
vap->va_rdev = 0; |
vap->va_bytes = vap->va_size = DEV_BSIZE; |
vap->va_bytes = vap->va_size = DEV_BSIZE; |
vap->va_nlink = 2; |
|
break; |
break; |
|
|
default: |
default: |
return EOPNOTSUPP; |
return EOPNOTSUPP; |
} |
} |
Line 404 ptyfs_setattr(void *v) |
|
Line 361 ptyfs_setattr(void *v) |
|
kauth_cred_t cred = ap->a_cred; |
kauth_cred_t cred = ap->a_cred; |
struct lwp *l = curlwp; |
struct lwp *l = curlwp; |
int error; |
int error; |
kauth_action_t action = KAUTH_VNODE_WRITE_FLAGS; |
|
bool changing_sysflags = false; |
|
|
|
if (vap->va_size != VNOVAL) { |
if (vap->va_size != VNOVAL) { |
switch (ptyfs->ptyfs_type) { |
switch (ptyfs->ptyfs_type) { |
Line 422 ptyfs_setattr(void *v) |
|
Line 377 ptyfs_setattr(void *v) |
|
if (vap->va_flags != VNOVAL) { |
if (vap->va_flags != VNOVAL) { |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
if (vp->v_mount->mnt_flag & MNT_RDONLY) |
return EROFS; |
return EROFS; |
|
if (kauth_cred_geteuid(cred) != ptyfs->ptyfs_uid && |
|
(error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, |
|
NULL)) != 0) |
|
return error; |
/* Immutable and append-only flags are not supported on ptyfs. */ |
/* Immutable and append-only flags are not supported on ptyfs. */ |
if (vap->va_flags & (IMMUTABLE | APPEND)) |
if (vap->va_flags & (IMMUTABLE | APPEND)) |
return EINVAL; |
return EINVAL; |
|
if (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL) == 0) { |
/* Snapshot flag cannot be set or cleared */ |
/* Snapshot flag cannot be set or cleared */ |
if ((vap->va_flags & SF_SNAPSHOT) != (ptyfs->ptyfs_flags & SF_SNAPSHOT)) |
if ((vap->va_flags & SF_SNAPSHOT) != |
return EPERM; |
(ptyfs->ptyfs_flags & SF_SNAPSHOT)) |
|
return EPERM; |
if ((ptyfs->ptyfs_flags & SF_SETTABLE) != (vap->va_flags & SF_SETTABLE)) { |
|
changing_sysflags = true; |
|
action |= KAUTH_VNODE_WRITE_SYSFLAGS; |
|
} |
|
|
|
error = kauth_authorize_vnode(cred, action, vp, NULL, |
|
genfs_can_chflags(cred, vp->v_type, ptyfs->ptyfs_uid, |
|
changing_sysflags)); |
|
if (error) |
|
return error; |
|
|
|
if (changing_sysflags) { |
|
ptyfs->ptyfs_flags = vap->va_flags; |
ptyfs->ptyfs_flags = vap->va_flags; |
} else { |
} else { |
|
if ((ptyfs->ptyfs_flags & SF_SETTABLE) != |
|
(vap->va_flags & SF_SETTABLE)) |
|
return EPERM; |
ptyfs->ptyfs_flags &= SF_SETTABLE; |
ptyfs->ptyfs_flags &= SF_SETTABLE; |
ptyfs->ptyfs_flags |= (vap->va_flags & UF_SETTABLE); |
ptyfs->ptyfs_flags |= (vap->va_flags & UF_SETTABLE); |
} |
} |
ptyfs->ptyfs_status |= PTYFS_CHANGE; |
ptyfs->ptyfs_flag |= PTYFS_CHANGE; |
} |
} |
|
|
/* |
/* |
Line 470 ptyfs_setattr(void *v) |
|
Line 419 ptyfs_setattr(void *v) |
|
return EROFS; |
return EROFS; |
if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0) |
if ((ptyfs->ptyfs_flags & SF_SNAPSHOT) != 0) |
return EPERM; |
return EPERM; |
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, vp, |
error = genfs_can_chtimes(vp, vap->va_vaflags, ptyfs->ptyfs_uid, |
NULL, genfs_can_chtimes(vp, vap->va_vaflags, |
cred); |
ptyfs->ptyfs_uid, cred)); |
|
if (error) |
if (error) |
return (error); |
return (error); |
if (vap->va_atime.tv_sec != VNOVAL) |
if (vap->va_atime.tv_sec != VNOVAL) |
if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) |
if (!(vp->v_mount->mnt_flag & MNT_NOATIME)) |
ptyfs->ptyfs_status |= PTYFS_ACCESS; |
ptyfs->ptyfs_flag |= PTYFS_ACCESS; |
if (vap->va_mtime.tv_sec != VNOVAL) { |
if (vap->va_mtime.tv_sec != VNOVAL) { |
ptyfs->ptyfs_status |= PTYFS_CHANGE | PTYFS_MODIFY; |
ptyfs->ptyfs_flag |= PTYFS_CHANGE | PTYFS_MODIFY; |
if (vp->v_mount->mnt_flag & MNT_RELATIME) |
if (vp->v_mount->mnt_flag & MNT_RELATIME) |
ptyfs->ptyfs_status |= PTYFS_ACCESS; |
ptyfs->ptyfs_flag |= PTYFS_ACCESS; |
} |
} |
if (vap->va_birthtime.tv_sec != VNOVAL) |
if (vap->va_birthtime.tv_sec != VNOVAL) |
ptyfs->ptyfs_birthtime = vap->va_birthtime; |
ptyfs->ptyfs_birthtime = vap->va_birthtime; |
ptyfs->ptyfs_status |= PTYFS_CHANGE; |
ptyfs->ptyfs_flag |= PTYFS_CHANGE; |
error = ptyfs_update(vp, &vap->va_atime, &vap->va_mtime, 0); |
error = ptyfs_update(vp, &vap->va_atime, &vap->va_mtime, 0); |
if (error) |
if (error) |
return error; |
return error; |
Line 517 ptyfs_chmod(struct vnode *vp, mode_t mod |
|
Line 465 ptyfs_chmod(struct vnode *vp, mode_t mod |
|
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
int error; |
int error; |
|
|
error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_SECURITY, vp, |
error = genfs_can_chmod(vp, cred, ptyfs->ptyfs_uid, |
NULL, genfs_can_chmod(vp->v_type, cred, ptyfs->ptyfs_uid, |
ptyfs->ptyfs_gid, mode); |
ptyfs->ptyfs_gid, mode)); |
|
if (error) |
if (error) |
return (error); |
return (error); |
|
|
Line 544 ptyfs_chown(struct vnode *vp, uid_t uid, |
|
Line 491 ptyfs_chown(struct vnode *vp, uid_t uid, |
|
if (gid == (gid_t)VNOVAL) |
if (gid == (gid_t)VNOVAL) |
gid = ptyfs->ptyfs_gid; |
gid = ptyfs->ptyfs_gid; |
|
|
error = kauth_authorize_vnode(cred, KAUTH_VNODE_CHANGE_OWNERSHIP, vp, |
error = genfs_can_chown(vp, cred, ptyfs->ptyfs_uid, |
NULL, genfs_can_chown(cred, ptyfs->ptyfs_uid, ptyfs->ptyfs_gid, |
ptyfs->ptyfs_gid, uid, gid); |
uid, gid)); |
|
if (error) |
if (error) |
return (error); |
return (error); |
|
|
Line 555 ptyfs_chown(struct vnode *vp, uid_t uid, |
|
Line 501 ptyfs_chown(struct vnode *vp, uid_t uid, |
|
return 0; |
return 0; |
} |
} |
|
|
|
static int |
|
ptyfs_check_possible(struct vnode *vp, mode_t mode) |
|
{ |
|
|
|
return 0; |
|
} |
|
|
|
static int |
|
ptyfs_check_permitted(struct vattr *va, mode_t mode, kauth_cred_t cred) |
|
{ |
|
|
|
return genfs_can_access(va->va_type, va->va_mode, |
|
va->va_uid, va->va_gid, mode, cred); |
|
} |
|
|
/* |
/* |
* implement access checking. |
* implement access checking. |
* |
* |
Line 578 ptyfs_access(void *v) |
|
Line 539 ptyfs_access(void *v) |
|
if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) |
if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) |
return error; |
return error; |
|
|
return kauth_authorize_vnode(ap->a_cred, |
error = ptyfs_check_possible(ap->a_vp, ap->a_mode); |
KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), |
if (error) |
ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, va.va_uid, |
return error; |
va.va_gid, ap->a_mode, ap->a_cred)); |
|
|
error = ptyfs_check_permitted(&va, ap->a_mode, ap->a_cred); |
|
|
return error; |
return error; |
} |
} |
Line 605 ptyfs_access(void *v) |
|
Line 567 ptyfs_access(void *v) |
|
int |
int |
ptyfs_lookup(void *v) |
ptyfs_lookup(void *v) |
{ |
{ |
struct vop_lookup_v2_args /* { |
struct vop_lookup_args /* { |
struct vnode * a_dvp; |
struct vnode * a_dvp; |
struct vnode ** a_vpp; |
struct vnode ** a_vpp; |
struct componentname * a_cnp; |
struct componentname * a_cnp; |
Line 639 ptyfs_lookup(void *v) |
|
Line 601 ptyfs_lookup(void *v) |
|
|
|
pty = atoi(pname, cnp->cn_namelen); |
pty = atoi(pname, cnp->cn_namelen); |
|
|
if (pty < 0 || pty >= npty || pty_isfree(pty, 1) || |
if (pty < 0 || pty >= npty || pty_isfree(pty, 1)) |
ptyfs_used_get(PTYFSptc, pty, dvp->v_mount, 0) == NULL) |
|
break; |
break; |
|
|
error = ptyfs_allocvp(dvp->v_mount, vpp, PTYFSpts, pty, |
error = ptyfs_allocvp(dvp->v_mount, vpp, PTYFSpts, pty, |
curlwp); |
curlwp); |
if (error) |
return error; |
return error; |
|
VOP_UNLOCK(*vpp); |
|
return 0; |
|
|
|
default: |
default: |
return ENOTDIR; |
return ENOTDIR; |
Line 735 ptyfs_readdir(void *v) |
|
Line 693 ptyfs_readdir(void *v) |
|
} |
} |
for (; uio->uio_resid >= UIO_MX && i < npty; i++) { |
for (; uio->uio_resid >= UIO_MX && i < npty; i++) { |
/* check for used ptys */ |
/* check for used ptys */ |
if (pty_isfree(i - 2, 1) || |
if (pty_isfree(i - 2, 1)) |
ptyfs_used_get(PTYFSptc, i - 2, vp->v_mount, 0) == NULL) |
|
continue; |
continue; |
|
|
dp->d_fileno = PTYFS_FILENO(i - 2, PTYFSpts); |
dp->d_fileno = PTYFS_FILENO(i - 2, PTYFSpts); |
Line 831 ptyfs_read(void *v) |
|
Line 788 ptyfs_read(void *v) |
|
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
int error; |
int error; |
|
|
if (vp->v_type == VDIR) |
ptyfs->ptyfs_flag |= PTYFS_ACCESS; |
return EISDIR; |
|
|
|
ptyfs->ptyfs_status |= PTYFS_ACCESS; |
|
/* hardclock() resolution is good enough for ptyfs */ |
/* hardclock() resolution is good enough for ptyfs */ |
getnanotime(&ts); |
getnanotime(&ts); |
(void)ptyfs_update(vp, &ts, &ts, 0); |
(void)ptyfs_update(vp, &ts, &ts, 0); |
Line 865 ptyfs_write(void *v) |
|
Line 819 ptyfs_write(void *v) |
|
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
struct ptyfsnode *ptyfs = VTOPTYFS(vp); |
int error; |
int error; |
|
|
ptyfs->ptyfs_status |= PTYFS_MODIFY; |
ptyfs->ptyfs_flag |= PTYFS_MODIFY; |
getnanotime(&ts); |
getnanotime(&ts); |
(void)ptyfs_update(vp, &ts, &ts, 0); |
(void)ptyfs_update(vp, &ts, &ts, 0); |
|
|
Line 961 ptyfs_itimes(struct ptyfsnode *ptyfs, co |
|
Line 915 ptyfs_itimes(struct ptyfsnode *ptyfs, co |
|
{ |
{ |
struct timespec now; |
struct timespec now; |
|
|
KASSERT(ptyfs->ptyfs_status & (PTYFS_ACCESS|PTYFS_CHANGE|PTYFS_MODIFY)); |
KASSERT(ptyfs->ptyfs_flag & (PTYFS_ACCESS|PTYFS_CHANGE|PTYFS_MODIFY)); |
|
|
getnanotime(&now); |
getnanotime(&now); |
if (ptyfs->ptyfs_status & PTYFS_ACCESS) { |
if (ptyfs->ptyfs_flag & PTYFS_ACCESS) { |
if (acc == NULL) |
if (acc == NULL) |
acc = &now; |
acc = &now; |
ptyfs->ptyfs_atime = *acc; |
ptyfs->ptyfs_atime = *acc; |
} |
} |
if (ptyfs->ptyfs_status & PTYFS_MODIFY) { |
if (ptyfs->ptyfs_flag & PTYFS_MODIFY) { |
if (mod == NULL) |
if (mod == NULL) |
mod = &now; |
mod = &now; |
ptyfs->ptyfs_mtime = *mod; |
ptyfs->ptyfs_mtime = *mod; |
} |
} |
if (ptyfs->ptyfs_status & PTYFS_CHANGE) { |
if (ptyfs->ptyfs_flag & PTYFS_CHANGE) { |
if (cre == NULL) |
if (cre == NULL) |
cre = &now; |
cre = &now; |
ptyfs->ptyfs_ctime = *cre; |
ptyfs->ptyfs_ctime = *cre; |
} |
} |
ptyfs->ptyfs_status &= ~(PTYFS_ACCESS|PTYFS_CHANGE|PTYFS_MODIFY); |
ptyfs->ptyfs_flag &= ~(PTYFS_ACCESS|PTYFS_CHANGE|PTYFS_MODIFY); |
} |
} |
|
|
/* |
/* |