/* ARGSUSED */ void acl3_getxattrdir(GETXATTRDIR3args *args, GETXATTRDIR3res *resp, struct exportinfo *exi, struct svc_req *req, cred_t *cr, bool_t ro) { int error; int flags; vnode_t *vp, *avp; vp = nfs3_fhtovp(&args->fh, exi); if (vp == NULL) { resp->status = NFS3ERR_STALE; return; } flags = LOOKUP_XATTR; if (args->create) flags |= CREATE_XATTR_DIR; else { ulong_t val = 0; error = VOP_PATHCONF(vp, _PC_SATTR_EXISTS, &val, cr, NULL); if (!error && val == 0) { error = VOP_PATHCONF(vp, _PC_XATTR_EXISTS, &val, cr, NULL); if (!error && val == 0) { VN_RELE(vp); resp->status = NFS3ERR_NOENT; return; } } } error = VOP_LOOKUP(vp, "", &avp, NULL, flags, NULL, cr, NULL, NULL, NULL); if (!error && avp == vp) { /* lookup of "" on old FS? */ error = EINVAL; VN_RELE(avp); } if (!error) { struct vattr va; va.va_mask = AT_ALL; error = rfs4_delegated_getattr(avp, &va, 0, cr); if (!error) { vattr_to_post_op_attr(&va, &resp->resok.attr); error = makefh3(&resp->resok.fh, avp, exi); } VN_RELE(avp); } VN_RELE(vp); if (error) { resp->status = puterrno3(error); return; } resp->status = NFS3_OK; }
static int unionfs_pathconf(void *v) { struct vop_pathconf_args *ap = v; struct unionfs_node *unp; struct vnode *vp; unp = VTOUNIONFS(ap->a_vp); vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); return (VOP_PATHCONF(vp, ap->a_name, ap->a_retval)); }
int RUMP_VOP_PATHCONF(struct vnode *vp, int name, register_t *retval) { int error; rump_schedule(); error = VOP_PATHCONF(vp, name, retval); rump_unschedule(); return error; }
/* * Determine if the file system supports NFSv4 ACLs. * Return 1 if it does, 0 otherwise. */ int nfs_supportsnfsv4acls(struct vnode *vp) { int error; register_t retval; ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls"); if (nfsrv_useacl == 0) return (0); error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval); if (error == 0 && retval != 0) return (1); return (0); }
/* * Return pathconf information about a file descriptor. */ int sys_fpathconf(struct lwp *l, const struct sys_fpathconf_args *uap, register_t *retval) { /* { syscallarg(int) fd; syscallarg(int) name; } */ int fd, error; file_t *fp; fd = SCARG(uap, fd); error = 0; if ((fp = fd_getfile(fd)) == NULL) { return (EBADF); } switch (fp->f_type) { case DTYPE_SOCKET: case DTYPE_PIPE: if (SCARG(uap, name) != _PC_PIPE_BUF) error = EINVAL; else *retval = PIPE_BUF; break; case DTYPE_VNODE: error = VOP_PATHCONF(fp->f_vnode, SCARG(uap, name), retval); break; case DTYPE_KQUEUE: error = EINVAL; break; default: error = EOPNOTSUPP; break; } fd_putfile(fd); return (error); }
static int devfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr) { switch (cmd) { case _PC_ACL_ENABLED: /* * We rely on the underlying filesystem for ACLs, * so direct the query for ACL support there. * ACL support isn't relative to the file * and we can't guarantee that the dv node * has an attribute node, so any valid * attribute node will suffice. */ ASSERT(dvroot); ASSERT(dvroot->dv_attrvp); return (VOP_PATHCONF(dvroot->dv_attrvp, cmd, valp, cr)); /*NOTREACHED*/ } return (fs_pathconf(vp, cmd, valp, cr)); }
/* * Do the pathconf vnode op. */ int nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, struct ucred *cred, struct thread *p) { int error; error = VOP_PATHCONF(vp, flag, retf); if (error == EOPNOTSUPP || error == EINVAL) { /* * Some file systems return EINVAL for name arguments not * supported and some return EOPNOTSUPP for this case. * So the NFSv3 Pathconf RPC doesn't fail for these cases, * just fake them. */ switch (flag) { case _PC_LINK_MAX: *retf = LINK_MAX; break; case _PC_NAME_MAX: *retf = NAME_MAX; break; case _PC_CHOWN_RESTRICTED: *retf = 1; break; case _PC_NO_TRUNC: *retf = 1; break; default: /* * Only happens if a _PC_xxx is added to the server, * but this isn't updated. */ *retf = 0; printf("nfsrvd pathconf flag=%d not supp\n", flag); }; error = 0; } NFSEXITCODE(error); return (error); }
/* * smb_vop_acl_type * * Determines the ACL type for the given vnode. * ACLENT_T is a Posix ACL and ACE_T is a ZFS ACL. */ acl_type_t smb_vop_acl_type(vnode_t *vp) { int error; ulong_t whichacl; error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &whichacl, kcred, NULL); if (error != 0) { /* * If we got an error, then the filesystem * likely does not understand the _PC_ACL_ENABLED * pathconf. In this case, we fall back to trying * POSIX-draft (aka UFS-style) ACLs. */ whichacl = _ACL_ACLENT_ENABLED; } if (!(whichacl & (_ACL_ACE_ENABLED | _ACL_ACLENT_ENABLED))) { /* * If the file system supports neither ACE nor * ACLENT ACLs we will fall back to UFS-style ACLs * like we did above if there was an error upon * calling VOP_PATHCONF. * * ACE and ACLENT type ACLs are the only interfaces * supported thus far. If any other bits are set on * 'whichacl' upon return from VOP_PATHCONF, we will * ignore them. */ whichacl = _ACL_ACLENT_ENABLED; } if (whichacl == _ACL_ACLENT_ENABLED) return (ACLENT_T); return (ACE_T); }
/* * Get the XATTR dir for some file or directory. * See vnode.c: fop_lookup() * * Note this only gets the GFS XATTR directory. We'll get the * real XATTR directory later, in xattr_dir_realdir. */ int xattr_dir_lookup(vnode_t *dvp, vnode_t **vpp, int flags, cred_t *cr) { int error = 0; *vpp = NULL; if (dvp->v_type != VDIR && dvp->v_type != VREG) return (EINVAL); mutex_enter(&dvp->v_lock); /* * If we're already in sysattr space, don't allow creation * of another level of sysattrs. */ if (dvp->v_flag & V_SYSATTR) { mutex_exit(&dvp->v_lock); return (EINVAL); } if (dvp->v_xattrdir != NULL) { *vpp = dvp->v_xattrdir; VN_HOLD(*vpp); } else { ulong_t val; int xattrs_allowed = dvp->v_vfsp->vfs_flag & VFS_XATTR; int sysattrs_allowed = 1; /* * We have to drop the lock on dvp. gfs_dir_create will * grab it for a VN_HOLD. */ mutex_exit(&dvp->v_lock); /* * If dvp allows xattr creation, but not sysattr * creation, return the real xattr dir vp. We can't * use the vfs feature mask here because _PC_SATTR_ENABLED * has vnode-level granularity (e.g. .zfs). */ error = VOP_PATHCONF(dvp, _PC_SATTR_ENABLED, &val, cr, NULL); if (error != 0 || val == 0) sysattrs_allowed = 0; if (!xattrs_allowed && !sysattrs_allowed) return (EINVAL); if (!sysattrs_allowed) { struct pathname pn; char *nm = ""; error = pn_get(nm, UIO_SYSSPACE, &pn); if (error) return (error); error = VOP_LOOKUP(dvp, nm, vpp, &pn, flags|LOOKUP_HAVE_SYSATTR_DIR, rootvp, cr, NULL, NULL, NULL); pn_free(&pn); return (error); } /* * Note that we act as if we were given CREATE_XATTR_DIR, * but only for creation of the GFS directory. */ *vpp = gfs_dir_create( sizeof (xattr_dir_t), dvp, xattr_dir_ops, xattr_dirents, xattrdir_do_ino, MAXNAMELEN, NULL, xattr_lookup_cb); mutex_enter(&dvp->v_lock); if (dvp->v_xattrdir != NULL) { /* * We lost the race to create the xattr dir. * Destroy this one, use the winner. We can't * just call VN_RELE(*vpp), because the vnode * is only partially initialized. */ gfs_dir_t *dp = (*vpp)->v_data; ASSERT((*vpp)->v_count == 1); vn_free(*vpp); mutex_destroy(&dp->gfsd_lock); kmem_free(dp->gfsd_static, dp->gfsd_nstatic * sizeof (gfs_dirent_t)); kmem_free(dp, dp->gfsd_file.gfs_size); /* * There is an implied VN_HOLD(dvp) here. We should * be doing a VN_RELE(dvp) to clean up the reference * from *vpp, and then a VN_HOLD(dvp) for the new * reference. Instead, we just leave the count alone. */ *vpp = dvp->v_xattrdir; VN_HOLD(*vpp); } else { (*vpp)->v_flag |= (V_XATTRDIR|V_SYSATTR); dvp->v_xattrdir = *vpp; } } mutex_exit(&dvp->v_lock); return (error); }