Exemple #1
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);
}
Exemple #2
0
/*
 * smb_odir_create
 * Allocate and populate an odir obect and add it to the tree's list.
 */
static uint16_t
smb_odir_create(smb_request_t *sr, smb_node_t *dnode,
    char *pattern, uint16_t sattr, cred_t *cr)
{
	smb_odir_t	*od;
	smb_tree_t	*tree;
	uint16_t	odid;

	ASSERT(sr);
	ASSERT(sr->sr_magic == SMB_REQ_MAGIC);
	ASSERT(sr->tid_tree);
	ASSERT(sr->tid_tree->t_magic == SMB_TREE_MAGIC);
	ASSERT(dnode);
	ASSERT(dnode->n_magic == SMB_NODE_MAGIC);

	tree = sr->tid_tree;

	if (smb_idpool_alloc(&tree->t_odid_pool, &odid)) {
		smbsr_error(sr, NT_STATUS_TOO_MANY_OPENED_FILES,
		    ERRDOS, ERROR_TOO_MANY_OPEN_FILES);
		return (0);
	}

	od = kmem_cache_alloc(smb_cache_odir, KM_SLEEP);
	bzero(od, sizeof (smb_odir_t));

	mutex_init(&od->d_mutex, NULL, MUTEX_DEFAULT, NULL);
	od->d_refcnt = 0;
	od->d_state = SMB_ODIR_STATE_OPEN;
	od->d_magic = SMB_ODIR_MAGIC;
	od->d_opened_by_pid = sr->smb_pid;
	od->d_session = tree->t_session;
	od->d_cred = cr;
	/*
	 * grab a ref for od->d_user
	 * released in  smb_odir_delete()
	 */
	smb_user_hold_internal(sr->uid_user);
	od->d_user = sr->uid_user;
	od->d_tree = tree;
	od->d_dnode = dnode;
	smb_node_ref(dnode);
	od->d_odid = odid;
	od->d_sattr = sattr;
	(void) strlcpy(od->d_pattern, pattern, sizeof (od->d_pattern));
	od->d_flags = 0;
	if (smb_contains_wildcards(od->d_pattern))
		od->d_flags |= SMB_ODIR_FLAG_WILDCARDS;
	if (vfs_has_feature(dnode->vp->v_vfsp, VFSFT_DIRENTFLAGS))
		od->d_flags |= SMB_ODIR_FLAG_EDIRENT;
	if (smb_tree_has_feature(tree, SMB_TREE_CASEINSENSITIVE))
		od->d_flags |= SMB_ODIR_FLAG_IGNORE_CASE;
	if (smb_tree_has_feature(tree, SMB_TREE_SHORTNAMES))
		od->d_flags |= SMB_ODIR_FLAG_SHORTNAMES;
	if (SMB_TREE_SUPPORTS_CATIA(sr))
		od->d_flags |= SMB_ODIR_FLAG_CATIA;
	if (SMB_TREE_SUPPORTS_ABE(sr))
		od->d_flags |= SMB_ODIR_FLAG_ABE;
	if (dnode->flags & NODE_XATTR_DIR)
		od->d_flags |= SMB_ODIR_FLAG_XATTR;
	od->d_eof = B_FALSE;

	smb_llist_enter(&tree->t_odir_list, RW_WRITER);
	smb_llist_insert_tail(&tree->t_odir_list, od);
	smb_llist_exit(&tree->t_odir_list);

	atomic_inc_32(&tree->t_session->s_dir_cnt);
	return (odid);
}