예제 #1
0
/* 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;
}
예제 #2
0
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));
}
예제 #3
0
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;
}
예제 #4
0
/*
 * 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);
}
예제 #5
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);
}
예제 #6
0
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));
}
예제 #7
0
/*
 * 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);
}
예제 #8
0
/*
 * 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);
}
예제 #9
0
파일: xattr.c 프로젝트: pcd1193182/openzfs
/*
 * 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);
}