Exemple #1
0
/*
 * Find snapshot node corresponding to 'node', and return it in
 * 'vss_node', as follows:
 * - find the path from fsrootvp to node, appending it to the
 *   the snapshot path
 * - lookup the vnode and smb_node (vss_node).
 */
static int
smb_vss_lookup_node(smb_request_t *sr, smb_node_t *node, vnode_t *fsrootvp,
    char *snapname, smb_node_t *dnode, smb_node_t **vss_node)
{
	char *p, *path;
	int err, len;
	vnode_t *vp = NULL;

	*vss_node = NULL;

	path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
	(void) snprintf(path, MAXPATHLEN, ".zfs/snapshot/%s/", snapname);
	len = strlen(path);
	p = path + len;

	err = smb_node_getpath(node, fsrootvp, p, MAXPATHLEN - len);
	if (err == 0) {
		vp = smb_lookuppathvptovp(sr, path, fsrootvp, fsrootvp);
		if (vp) {
			*vss_node = smb_node_lookup(sr, NULL, zone_kcred(),
			    vp, snapname, dnode, NULL);
			VN_RELE(vp);
		}
	}

	kmem_free(path, MAXPATHLEN);

	if (*vss_node != NULL)
		return (0);

	return (err ? err : ENOENT);
}
Exemple #2
0
/*
 * smb_odir_openat
 *
 * Create an odir representing the extended attribute directory
 * associated with the file (or directory) represented by unode.
 *
 * Returns:
 * odid - Unique identifier of newly created odir.
 *    0 - error, error details set in sr.
 */
uint16_t
smb_odir_openat(smb_request_t *sr, smb_node_t *unode)
{
	int		rc;
	vnode_t		*xattr_dvp;
	uint16_t	odid;
	cred_t		*cr;
	char		pattern[SMB_STREAM_PREFIX_LEN + 2];

	smb_node_t	*xattr_dnode;

	ASSERT(sr);
	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
	ASSERT(unode);
	ASSERT(unode->n_magic == SMB_NODE_MAGIC);

	if (SMB_TREE_CONTAINS_NODE(sr, unode) == 0 ||
	    SMB_TREE_HAS_ACCESS(sr, ACE_LIST_DIRECTORY) == 0) {
		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
		    ERRDOS, ERROR_ACCESS_DENIED);
		return (0);
	}
	cr = zone_kcred();

	/* find the xattrdir vnode */
	rc = smb_vop_lookup_xattrdir(unode->vp, &xattr_dvp, LOOKUP_XATTR, cr);
	if (rc != 0) {
		smbsr_errno(sr, rc);
		return (0);
	}

	/* lookup the xattrdir's smb_node */
	xattr_dnode = smb_node_lookup(sr, NULL, cr, xattr_dvp, XATTR_DIR,
	    unode, NULL);
	VN_RELE(xattr_dvp);
	if (xattr_dnode == NULL) {
		smbsr_error(sr, NT_STATUS_NO_MEMORY,
		    ERRDOS, ERROR_NOT_ENOUGH_MEMORY);
		return (0);
	}

	(void) snprintf(pattern, sizeof (pattern), "%s*", SMB_STREAM_PREFIX);
	odid = smb_odir_create(sr, xattr_dnode, pattern, SMB_SEARCH_ATTRIBUTES,
	    cr);
	smb_node_release(xattr_dnode);
	return (odid);
}
Exemple #3
0
int
smb_pathname(smb_request_t *sr, char *path, int flags,
    smb_node_t *root_node, smb_node_t *cur_node, smb_node_t **dir_node,
    smb_node_t **ret_node, cred_t *cred)
{
	char		*component, *real_name, *namep;
	pathname_t	pn, rpn, upn, link_pn;
	smb_node_t	*dnode, *fnode;
	smb_attr_t	attr;
	vnode_t		*rootvp, *vp;
	size_t		pathleft;
	int		err = 0;
	int		nlink = 0;
	int		local_flags;
	uint32_t	abe_flag = 0;
	char		namebuf[MAXNAMELEN];

	if (path == NULL)
		return (EINVAL);

	ASSERT(root_node);
	ASSERT(cur_node);
	ASSERT(ret_node);

	*ret_node = NULL;

	if (dir_node)
		*dir_node = NULL;

	(void) pn_alloc(&upn);

	if ((err = pn_set(&upn, path)) != 0) {
		(void) pn_free(&upn);
		return (err);
	}

	if (SMB_TREE_SUPPORTS_ABE(sr))
		abe_flag = SMB_ABE;

	(void) pn_alloc(&pn);
	(void) pn_alloc(&rpn);

	component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
	real_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);

	fnode = NULL;
	dnode = cur_node;
	smb_node_ref(dnode);
	rootvp = root_node->vp;

	while ((pathleft = pn_pathleft(&upn)) != 0) {
		if (fnode) {
			smb_node_release(dnode);
			dnode = fnode;
			fnode = NULL;
		}

		if ((err = pn_getcomponent(&upn, component)) != 0)
			break;

		if ((namep = smb_pathname_catia_v5tov4(sr, component,
		    namebuf, sizeof (namebuf))) == NULL) {
			err = EILSEQ;
			break;
		}

		if ((err = pn_set(&pn, namep)) != 0)
			break;

		local_flags = flags & FIGNORECASE;
		err = smb_pathname_lookup(&pn, &rpn, local_flags,
		    &vp, rootvp, dnode->vp, &attr, cred);

		if (err) {
			if (!SMB_TREE_SUPPORTS_SHORTNAMES(sr) ||
			    !smb_maybe_mangled(component))
				break;

			if ((err = smb_unmangle(dnode, component,
			    real_name, MAXNAMELEN, abe_flag)) != 0)
				break;

			if ((namep = smb_pathname_catia_v5tov4(sr, real_name,
			    namebuf, sizeof (namebuf))) == NULL) {
				err = EILSEQ;
				break;
			}

			if ((err = pn_set(&pn, namep)) != 0)
				break;

			local_flags = 0;
			err = smb_pathname_lookup(&pn, &rpn, local_flags,
			    &vp, rootvp, dnode->vp, &attr, cred);
			if (err)
				break;
		}

		/*
		 * This check MUST be done before symlink check
		 * since a reparse point is of type VLNK but should
		 * not be handled like a regular symlink.
		 */
		if (attr.sa_dosattr & FILE_ATTRIBUTE_REPARSE_POINT) {
			err = EREMOTE;
			VN_RELE(vp);
			break;
		}

		if ((vp->v_type == VLNK) &&
		    ((flags & FOLLOW) || pn_pathleft(&upn))) {

			if (++nlink > MAXSYMLINKS) {
				err = ELOOP;
				VN_RELE(vp);
				break;
			}

			(void) pn_alloc(&link_pn);
			err = pn_getsymlink(vp, &link_pn, cred);
			VN_RELE(vp);

			if (err == 0) {
				if (pn_pathleft(&link_pn) == 0)
					(void) pn_set(&link_pn, ".");
				err = pn_insert(&upn, &link_pn,
				    strlen(component));
			}
			pn_free(&link_pn);

			if (err)
				break;

			if (upn.pn_pathlen == 0) {
				err = ENOENT;
				break;
			}

			if (upn.pn_path[0] == '/') {
				fnode = root_node;
				smb_node_ref(fnode);
			}

			if (pn_fixslash(&upn))
				flags |= FOLLOW;

		} else {
			if (flags & FIGNORECASE) {
				if (strcmp(rpn.pn_path, "/") != 0)
					pn_setlast(&rpn);
				namep = rpn.pn_path;
			} else {
				namep = pn.pn_path;
			}

			namep = smb_pathname_catia_v4tov5(sr, namep,
			    namebuf, sizeof (namebuf));

			fnode = smb_node_lookup(sr, NULL, cred, vp, namep,
			    dnode, NULL);
			VN_RELE(vp);

			if (fnode == NULL) {
				err = ENOMEM;
				break;
			}
		}

		while (upn.pn_path[0] == '/') {
			upn.pn_path++;
			upn.pn_pathlen--;
		}

	}

	if ((pathleft) && (err == ENOENT))
		err = ENOTDIR;

	if (err) {
		if (fnode)
			smb_node_release(fnode);
		if (dnode)
			smb_node_release(dnode);
	} else {
		*ret_node = fnode;

		if (dir_node)
			*dir_node = dnode;
		else
			smb_node_release(dnode);
	}

	kmem_free(component, MAXNAMELEN);
	kmem_free(real_name, MAXNAMELEN);
	(void) pn_free(&pn);
	(void) pn_free(&rpn);
	(void) pn_free(&upn);

	return (err);
}