| /* |
| * (c) 2002 Pawel Jakub Dawidek <nick@garage.freebsd.pl> |
| * |
| * $Id: sysctlfs_vnops.c,v 1.6 2002/12/24 07:20:16 jules Exp $ |
| * |
| */ |
| |
| /* |
| * sysctlfs vnode interface |
| */ |
| |
| #include <sys/param.h> |
| #include <sys/systm.h> |
| #include <sys/time.h> |
| #include <sys/kernel.h> |
| #include <sys/lock.h> |
| #include <sys/fcntl.h> |
| #include <sys/proc.h> |
| #include <sys/signalvar.h> |
| #if __FreeBSD_version >= 500040 |
| #include <sys/vnode.h> |
| #else |
| #include "vnode_4.h" |
| #endif |
| #include <sys/uio.h> |
| #include <sys/mount.h> |
| #include <sys/namei.h> |
| #include <sys/dirent.h> |
| #include <sys/malloc.h> |
| #include <machine/reg.h> |
| #if __FreeBSD_version < 500033 |
| #include <vm/vm_zone.h> |
| #endif |
| #include <sys/pioctl.h> |
| #include <sys/sysctl.h> |
| |
| #if 0 |
| #include <miscfs/sysctlfs/sysctlfs.h> |
| #else |
| #include "sysctlfs.h" |
| #endif |
| |
| #ifndef SYSCTL_CHILDREN |
| #define SYSCTL_CHILDREN(OID_PTR) ((struct sysctl_oid_list *)(OID_PTR)->oid_arg1) |
| #endif |
| |
| #if __FreeBSD_version >= 500033 |
| #define a_p a_td |
| #endif |
| |
| static int sysctlfs_access __P((struct vop_access_args *)); |
| #if __FreeBSD_version < 600007 |
| static int sysctlfs_badop __P((void)); |
| #endif |
| static int sysctlfs_bmap __P((struct vop_bmap_args *)); |
| static int sysctlfs_close __P((struct vop_close_args *)); |
| static int sysctlfs_getattr __P((struct vop_getattr_args *)); |
| static int sysctlfs_inactive __P((struct vop_inactive_args *)); |
| static int sysctlfs_lookup __P((struct vop_lookup_args *)); |
| static int sysctlfs_open __P((struct vop_open_args *)); |
| static int sysctlfs_print __P((struct vop_print_args *)); |
| static int sysctlfs_readdir __P((struct vop_readdir_args *)); |
| static int sysctlfs_reclaim __P((struct vop_reclaim_args *)); |
| static int sysctlfs_setattr __P((struct vop_setattr_args *)); |
| |
| static int |
| sysctlfs_open(ap) |
| struct vop_open_args /* { |
| struct vnode *a_vp; |
| int a_mode; |
| struct ucred *a_cred; |
| struct proc *a_p; |
| } */ *ap; |
| { |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| |
| switch (scfs->scfs_type) { |
| case Sctl: |
| #ifdef DEBUG |
| uprintf("sysctlfs: OPEN [file: %s][mode: %o]\n", |
| scfs->scfs_oidp->oid_name, ap->a_mode); |
| #endif |
| if (((scfs->scfs_flags & FWRITE) && (ap->a_mode & O_EXCL)) || |
| ((scfs->scfs_flags & O_EXCL) && (ap->a_mode & FWRITE))) |
| return (EBUSY); |
| |
| if (ap->a_mode & FWRITE) |
| scfs->scfs_flags = ap->a_mode & (FWRITE|O_EXCL); |
| return (0); |
| |
| default: |
| break; |
| } |
| |
| return (0); |
| } |
| |
| static int |
| sysctlfs_close(ap) |
| struct vop_close_args /* { |
| struct vnode *a_vp; |
| int a_fflag; |
| struct ucred *a_cred; |
| struct proc *a_p; |
| } */ *ap; |
| { |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| |
| switch (scfs->scfs_type) { |
| case Sctl: |
| #ifdef DEBUG |
| uprintf("sysctlfs: CLOSE [file: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| if ((ap->a_fflag & FWRITE) && (scfs->scfs_flags & O_EXCL)) |
| scfs->scfs_flags &= ~(FWRITE|O_EXCL); |
| break; |
| default: |
| break; |
| } |
| |
| return (0); |
| } |
| |
| static int |
| sysctlfs_bmap(ap) |
| struct vop_bmap_args /* { |
| struct vnode *a_vp; |
| daddr_t a_bn; |
| struct vnode **a_vpp; |
| daddr_t *a_bnp; |
| int *a_runp; |
| } */ *ap; |
| { |
| #ifdef DEBUG |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| |
| uprintf("sysctlfs: BMAP [file: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| #if __FreeBSD_version < 600007 |
| if(ap->a_vpp) *ap->a_vpp = ap->a_vp; |
| #else |
| if(ap->a_bop) *ap->a_bop = &ap->a_vp->v_bufobj; |
| #endif |
| if (ap->a_bnp != NULL) |
| *ap->a_bnp = ap->a_bn; |
| if (ap->a_runp != NULL) |
| *ap->a_runp = 0; |
| return (0); |
| } |
| |
| static int |
| sysctlfs_inactive(ap) |
| struct vop_inactive_args /* { |
| struct vnode *a_vp; |
| } */ *ap; |
| { |
| #ifdef DEBUG |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| #endif |
| struct vnode *vp = ap->a_vp; |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: INACTIVE [file: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| VOP_UNLOCK(vp, 0 |
| #if __FreeBSD_version < 800011 |
| , ap->a_p |
| #endif |
| ); |
| |
| return (0); |
| } |
| |
| static int |
| sysctlfs_reclaim(ap) |
| struct vop_reclaim_args /* { |
| struct vnode *a_vp; |
| } */ *ap; |
| { |
| #ifdef DEBUG |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| |
| uprintf("sysctlfs: RECLAIM [file: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| return (sysctlfs_freevp(ap->a_vp)); |
| } |
| |
| static int |
| sysctlfs_print(ap) |
| struct vop_print_args /* { |
| struct vnode *a_vp; |
| } */ *ap; |
| { |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| |
| printf("tag VT_SYSCTLFS, type %d, oid_name %s, mode %o, flags %lx, " |
| "fileno %lu, oid_kind %x\n", scfs->scfs_type, |
| scfs->scfs_oidp->oid_name, scfs->scfs_mode, scfs->scfs_flags, |
| scfs->scfs_fileno, scfs->scfs_oidp->oid_kind); |
| return (0); |
| } |
| |
| #if __FreeBSD_version < 600007 |
| /* |
| * generic entry point for unsupported operations |
| */ |
| static int |
| sysctlfs_badop() |
| { |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: BADOP\n"); |
| #endif |
| return (EIO); |
| } |
| #endif |
| |
| /* |
| * Invent attributes for scfsnode (vp) and store |
| * them in (vap). |
| */ |
| static int |
| sysctlfs_getattr(ap) |
| struct vop_getattr_args /* { |
| struct vnode *a_vp; |
| struct vattr *a_vap; |
| struct ucred *a_cred; |
| struct proc *a_p; |
| } */ *ap; |
| { |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| struct vattr *vap = ap->a_vap; |
| int error; |
| size_t scsize; |
| |
| error = 0; |
| |
| /* 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_mode = scfs->scfs_mode; |
| vap->va_fileid = scfs->scfs_fileno; |
| vap->va_flags = 0; |
| vap->va_blocksize = PAGE_SIZE; |
| vap->va_fsid = ap->a_vp->v_mount->mnt_stat.f_fsid.val[0]; |
| |
| /* |
| * Make all times be current TOD. |
| */ |
| nanotime(&vap->va_ctime); |
| vap->va_atime = vap->va_mtime = vap->va_ctime; |
| |
| vap->va_nlink = 1; |
| vap->va_uid = 0; |
| vap->va_gid = 0; |
| |
| if (scfs->scfs_type == Sctl) { |
| error = sysctlfs_sysctl( |
| #if __FreeBSD_version < 800046 |
| ap->a_p, |
| #else |
| curthread, |
| #endif |
| scfs->scfs_oidp, NULL, 0, NULL, 0, &scsize); |
| if (error != 0) |
| return (error); |
| vap->va_bytes = vap->va_size = scsize; |
| } else if (scfs->scfs_type == Sroot || scfs->scfs_type == Snode) |
| vap->va_size = vap->va_bytes = DEV_BSIZE; |
| else |
| panic("sysctlfs_getattr"); |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: GETATTR [file: %s][uid: %u][gid: %u][mode: %o]" |
| "[size: %llu]\n", scfs->scfs_oidp->oid_name, vap->va_uid, |
| vap->va_gid, vap->va_mode, vap->va_size); |
| #endif |
| return (error); |
| } |
| |
| static int |
| sysctlfs_setattr(ap) |
| struct vop_setattr_args /* { |
| struct vnode *a_vp; |
| struct vattr *a_vap; |
| struct ucred *a_cred; |
| struct proc *a_p; |
| } */ *ap; |
| { |
| #ifdef DEBUG |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| #endif |
| |
| if (ap->a_vap->va_flags != VNOVAL) |
| return (EOPNOTSUPP); |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: SETATTR [file: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| /* |
| * just fake out attribute setting |
| * it's not good to generate an error |
| * return, otherwise things like creat() |
| * will fail when they try to set the |
| * file length to 0. |
| */ |
| |
| return (0); |
| } |
| |
| static int |
| sysctlfs_access(ap) |
| struct vop_access_args /* { |
| struct vnode *a_vp; |
| int a_mode; |
| struct ucred *a_cred; |
| struct proc *a_p; |
| } */ *ap; |
| { |
| #ifdef DEBUG |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| #endif |
| struct vattr *vap; |
| struct vattr vattr; |
| int error; |
| |
| vap = &vattr; |
| error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred |
| #if __FreeBSD_version < 800046 |
| , ap->a_p |
| #endif |
| ); |
| if (error) |
| return (error); |
| |
| if (ap->a_cred->cr_uid != vap->va_uid) { |
| gid_t *gp; |
| int i; |
| |
| #if __FreeBSD_version < 800052 |
| ap->a_mode >>= 3; |
| #else |
| ap->a_accmode >>= 3; |
| #endif |
| gp = ap->a_cred->cr_groups; |
| for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++) |
| if (vap->va_gid == *gp) |
| goto found; |
| #if __FreeBSD_version < 800052 |
| ap->a_mode >>= 3; |
| #else |
| ap->a_accmode >>= 3; |
| #endif |
| found: |
| ; |
| } |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: ACCESS [file: %s][%o & %o = %o]\n", |
| scfs->scfs_oidp->oid_name, vap->va_mode, |
| #if __FreeBSD_version < 800052 |
| ap->a_mode, vap->va_mode & ap->a_mode |
| #else |
| ap->a_accmode, vap->va_mode & ap->a_accmode |
| #endif |
| ); |
| #endif |
| #if __FreeBSD_version < 800052 |
| if ((vap->va_mode & ap->a_mode) == ap->a_mode) return 0; |
| #else |
| if ((vap->va_mode & ap->a_accmode) == ap->a_accmode) return 0; |
| #endif |
| |
| return (EACCES); |
| } |
| |
| static int |
| sysctlfs_lookup(ap) |
| struct vop_lookup_args /* { |
| struct vnode * a_dvp; |
| struct vnode ** a_vpp; |
| struct componentname * a_cnp; |
| } */ *ap; |
| { |
| struct componentname *cnp = ap->a_cnp; |
| struct vnode **vpp = ap->a_vpp; |
| struct vnode *dvp = ap->a_dvp; |
| char *pname = cnp->cn_nameptr; |
| struct scfsnode *scfs; |
| struct sysctl_oid *oidp; |
| scfstype type; |
| size_t len; |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: LOOKUP [file: %s]\n", pname); |
| #endif |
| scfs = VTOSCFS(dvp); |
| |
| *vpp = NULL; |
| |
| if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) |
| return (EROFS); |
| |
| if (cnp->cn_namelen == 1 && *pname == '.') { |
| *vpp = dvp; |
| VREF(dvp); |
| #if 0 |
| vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); |
| #endif |
| return (0); |
| } |
| |
| scfs = VTOSCFS(dvp); |
| switch (scfs->scfs_type) { |
| case Sroot: |
| if (cnp->cn_flags & ISDOTDOT) |
| return (EIO); |
| |
| oidp = SLIST_FIRST(&sysctl__children); |
| while (oidp != NULL) { |
| len = strlen(oidp->oid_name); |
| if (cnp->cn_namelen == len && |
| bcmp(oidp->oid_name, pname, cnp->cn_namelen) == 0) { |
| type = (oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE ? Snode : Sctl; |
| return (sysctlfs_allocvp(dvp->v_mount, vpp, |
| oidp, type)); |
| } |
| oidp = SLIST_NEXT(oidp, oid_link); |
| } |
| break; |
| |
| case Snode: |
| oidp = SLIST_FIRST(SYSCTL_CHILDREN(scfs->scfs_oidp)); |
| |
| if (cnp->cn_flags & ISDOTDOT) { |
| oidp = SLIST_FIRST(scfs->scfs_oidp->oid_parent); |
| if (oidp->oid_parent == &sysctl__children) |
| return (sysctlfs_root(dvp->v_mount, |
| #if __FreeBSD_version >= 600023 |
| 0, |
| #endif |
| vpp |
| #if __FreeBSD_version < 800087 && __FreeBSD_version >= 502123 |
| , curthread |
| #endif |
| )); |
| else { |
| /* For now ivalue != 0 is never returned. */ |
| if (sysctlfs_findparent(dvp->v_mount, |
| scfs->scfs_oidp, &oidp) != 0) { |
| return (sysctlfs_root(dvp->v_mount, |
| #if __FreeBSD_version >= 600023 |
| 0, |
| #endif |
| vpp |
| #if __FreeBSD_version < 800087 && __FreeBSD_version >= 502123 |
| , curthread |
| #endif |
| )); |
| } |
| return (sysctlfs_allocvp(dvp->v_mount, vpp, |
| oidp, Snode)); |
| } |
| } |
| |
| while (oidp != NULL) { |
| len = strlen(oidp->oid_name); |
| if (cnp->cn_namelen == len && |
| bcmp(oidp->oid_name, pname, cnp->cn_namelen) == 0) { |
| type = (oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE ? Snode : Sctl; |
| return (sysctlfs_allocvp(dvp->v_mount, vpp, |
| oidp, type)); |
| } |
| oidp = SLIST_NEXT(oidp, oid_link); |
| } |
| break; |
| |
| default: |
| return (ENOTDIR); |
| } |
| |
| return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); |
| } |
| |
| /* |
| * readdir() returns directory entries from scfsnode (vp). |
| * |
| * We generate just one directory entry at a time, as it would probably |
| * not pay off to buffer several entries locally to save uiomove calls. |
| */ |
| static int |
| sysctlfs_readdir(ap) |
| struct vop_readdir_args /* { |
| struct vnode *a_vp; |
| struct uio *a_uio; |
| struct ucred *a_cred; |
| int *a_eofflag; |
| int *a_ncookies; |
| u_long **a_cookies; |
| } */ *ap; |
| { |
| struct uio *uio = ap->a_uio; |
| struct dirent d; |
| struct dirent *dp = &d; |
| struct scfsnode *scfs = VTOSCFS(ap->a_vp); |
| int error, i, j, off; |
| static u_int delen; |
| static struct sysctl_oid *oidp; |
| |
| #ifdef DEBUG |
| uprintf("sysctlfs: READDIR [dir: %s]\n", scfs->scfs_oidp->oid_name); |
| #endif |
| if (ap->a_ncookies != NULL) { |
| #ifdef DEBUG |
| printf("sysctlfs: not hungry\n"); |
| #endif |
| return (EOPNOTSUPP); |
| } |
| |
| if (!delen) { |
| d.d_namlen = MAXNAMLEN; |
| delen = GENERIC_DIRSIZ(&d); |
| } |
| d.d_namlen = MAXNAMLEN; |
| delen = GENERIC_DIRSIZ(&d); |
| |
| off = (int)uio->uio_offset; |
| if (off != uio->uio_offset || off < 0 || |
| off % delen != 0 || uio->uio_resid < delen) |
| return (EINVAL); |
| |
| error = 0; |
| i = off / delen; |
| |
| switch(scfs->scfs_type) { |
| case Sroot: |
| oidp = SLIST_FIRST(&sysctl__children); |
| |
| /* 0 and 1 reserved for "." and ".." */ |
| for (j = 2; oidp != NULL && j < i; ++j) |
| oidp = SLIST_NEXT(oidp, oid_link); |
| |
| for (; oidp != NULL && uio->uio_resid >= delen; i++) { |
| bzero((char *) dp, delen); |
| dp->d_reclen = delen; |
| |
| switch (i) { |
| case 0: /* `.' */ |
| case 1: /* `..' */ |
| dp->d_fileno = i + 1; |
| dp->d_namlen = i + 1; |
| bcopy("..", dp->d_name, dp->d_namlen); |
| dp->d_name[i + 1] = '\0'; |
| dp->d_type = DT_DIR; |
| break; |
| default: |
| dp->d_namlen = snprintf(dp->d_name, |
| sizeof (dp->d_name), "%s", oidp->oid_name); |
| if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE && |
| oidp->oid_handler == NULL) |
| dp->d_type = DT_DIR; |
| else |
| dp->d_type = DT_REG; |
| dp->d_fileno = i + 3; |
| |
| oidp = SLIST_NEXT(oidp, oid_link); |
| |
| break; |
| } |
| /* |
| * And ship to userland |
| */ |
| error = uiomove((caddr_t)dp, delen, uio); |
| if (error) |
| break; |
| } |
| break; |
| case Snode: |
| if (scfs->scfs_oidp == NULL) |
| return (ENOENT); |
| |
| oidp = SLIST_FIRST(SYSCTL_CHILDREN(scfs->scfs_oidp)); |
| |
| /* 0 and 1 reserved for "." and ".." */ |
| for (j = 2; oidp != NULL && j < i; ++j) |
| oidp = SLIST_NEXT(oidp, oid_link); |
| |
| for (; oidp != NULL && uio->uio_resid >= delen; i++) { |
| bzero((char *) dp, delen); |
| dp->d_reclen = delen; |
| |
| switch (i) { |
| case 0: /* `.' */ |
| case 1: /* `..' */ |
| dp->d_fileno = i + 1; |
| dp->d_namlen = i + 1; |
| bcopy("..", dp->d_name, dp->d_namlen); |
| dp->d_name[i + 1] = '\0'; |
| dp->d_type = DT_DIR; |
| break; |
| default: |
| dp->d_namlen = snprintf(dp->d_name, |
| sizeof (dp->d_name), "%s", oidp->oid_name); |
| if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE && |
| oidp->oid_handler == NULL) |
| dp->d_type = DT_DIR; |
| else |
| dp->d_type = DT_REG; |
| dp->d_fileno = i + 3; |
| |
| oidp = SLIST_NEXT(oidp, oid_link); |
| |
| break; |
| } |
| /* |
| * And ship to userland |
| */ |
| error = uiomove((caddr_t)dp, delen, uio); |
| if (error) |
| break; |
| } |
| break; |
| default: |
| error = ENOTDIR; |
| break; |
| } |
| |
| uio->uio_offset = i * delen; |
| return (error); |
| } |
| |
| /* |
| * sysctlfs vnode operations. |
| */ |
| #if __FreeBSD_version < 600007 |
| vop_t **sysctlfs_vnodeop_p; |
| static struct vnodeopv_entry_desc sysctlfs_vnodeop_entries[] = { |
| { &vop_default_desc, (vop_t *) vop_defaultop }, |
| { &vop_pathconf_desc, (vop_t *) vop_stdpathconf }, |
| { &vop_access_desc, (vop_t *) sysctlfs_access }, |
| { &vop_bmap_desc, (vop_t *) sysctlfs_bmap }, |
| { &vop_close_desc, (vop_t *) sysctlfs_close }, |
| { &vop_getattr_desc, (vop_t *) sysctlfs_getattr }, |
| { &vop_inactive_desc, (vop_t *) sysctlfs_inactive }, |
| { &vop_lookup_desc, (vop_t *) sysctlfs_lookup }, |
| { &vop_open_desc, (vop_t *) sysctlfs_open }, |
| { &vop_print_desc, (vop_t *) sysctlfs_print }, |
| { &vop_read_desc, (vop_t *) sysctlfs_read }, |
| { &vop_readdir_desc, (vop_t *) sysctlfs_readdir }, |
| { &vop_reclaim_desc, (vop_t *) sysctlfs_reclaim }, |
| { &vop_setattr_desc, (vop_t *) sysctlfs_setattr }, |
| { &vop_write_desc, (vop_t *) sysctlfs_write }, |
| { &vop_advlock_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_create_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_ioctl_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_link_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_mkdir_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_mknod_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_readlink_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_remove_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_rename_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_rmdir_desc, (vop_t *) sysctlfs_badop }, |
| { &vop_symlink_desc, (vop_t *) sysctlfs_badop }, |
| { NULL, NULL } |
| }; |
| static struct vnodeopv_desc sysctlfs_vnodeop_opv_desc = |
| { &sysctlfs_vnodeop_p, sysctlfs_vnodeop_entries }; |
| |
| VNODEOP_SET(sysctlfs_vnodeop_opv_desc); |
| #else |
| struct vop_vector sysctlfs_vnodeops = { |
| .vop_default = &default_vnodeops, |
| .vop_pathconf = vop_stdpathconf, |
| .vop_access = sysctlfs_access, |
| .vop_bmap = sysctlfs_bmap, |
| .vop_close = sysctlfs_close, |
| .vop_getattr = sysctlfs_getattr, |
| .vop_inactive = sysctlfs_inactive, |
| .vop_lookup = sysctlfs_lookup, |
| .vop_open = sysctlfs_open, |
| .vop_print = sysctlfs_print, |
| .vop_read = sysctlfs_read, |
| .vop_readdir = sysctlfs_readdir, |
| .vop_reclaim = sysctlfs_reclaim, |
| .vop_setattr = sysctlfs_setattr, |
| .vop_write = sysctlfs_write, |
| .vop_advlock = VOP_EOPNOTSUPP, |
| .vop_create = VOP_EOPNOTSUPP, |
| .vop_ioctl = VOP_EOPNOTSUPP, |
| .vop_link = VOP_EOPNOTSUPP, |
| .vop_mkdir = VOP_EOPNOTSUPP, |
| .vop_mknod = VOP_EOPNOTSUPP, |
| .vop_readlink = VOP_EOPNOTSUPP, |
| .vop_remove = VOP_EOPNOTSUPP, |
| .vop_rename = VOP_EOPNOTSUPP, |
| .vop_rmdir = VOP_EOPNOTSUPP, |
| .vop_symlink = VOP_EOPNOTSUPP, |
| }; |
| #endif |