예제 #1
0
/*
 * CATIA translation of a pathname component after returning from lookuppnvp
 */
static char *
smb_pathname_catia_v4tov5(smb_request_t *sr, char *name,
    char *namebuf, int buflen)
{
	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
		smb_vop_catia_v4tov5(name, namebuf, buflen);
		return (namebuf);
	}

	return (name);
}
예제 #2
0
/*
 * CATIA Translation of a pathname component prior to passing it to lookuppnvp
 *
 * If the translated component name contains a '/' NULL is returned.
 * The caller should treat this as error EILSEQ. It is not valid to
 * have a directory name with a '/'.
 */
static char *
smb_pathname_catia_v5tov4(smb_request_t *sr, char *name,
    char *namebuf, int buflen)
{
	char *namep;

	if (SMB_TREE_SUPPORTS_CATIA(sr)) {
		namep = smb_vop_catia_v5tov4(name, namebuf, buflen);
		if (strchr(namep, '/') != NULL)
			return (NULL);
		return (namep);
	}

	return (name);
}
예제 #3
0
/*
 * This function is used to delete a newly created object (file or
 * directory) if an error occurs after creation of the object.
 */
static void
smb_delete_new_object(smb_request_t *sr)
{
	smb_arg_open_t	*op = &sr->sr_open;
	smb_fqi_t	*fqi = &(op->fqi);
	uint32_t	flags = 0;

	if (SMB_TREE_IS_CASEINSENSITIVE(sr))
		flags |= SMB_IGNORE_CASE;
	if (SMB_TREE_SUPPORTS_CATIA(sr))
		flags |= SMB_CATIA;

	if (op->create_options & FILE_DIRECTORY_FILE)
		(void) smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
		    fqi->fq_last_comp, flags);
	else
		(void) smb_fsop_remove(sr, sr->user_cr, fqi->fq_dnode,
		    fqi->fq_last_comp, flags);
}
예제 #4
0
smb_sdrc_t
smb_com_delete_directory(smb_request_t *sr)
{
	int rc;
	uint32_t flags = 0;
	smb_fqi_t *fqi;
	smb_node_t *tnode;

	if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
		    ERRDOS, ERROR_ACCESS_DENIED);
		return (SDRC_ERROR);
	}

	fqi = &sr->arg.dirop.fqi;
	tnode = sr->tid_tree->t_snode;

	smb_pathname_init(sr, &fqi->fq_path, fqi->fq_path.pn_path);
	if (!smb_pathname_validate(sr, &fqi->fq_path) ||
	    !smb_validate_dirname(sr, &fqi->fq_path)) {
		return (SDRC_ERROR);
	}

	rc = smb_pathname_reduce(sr, sr->user_cr, fqi->fq_path.pn_path,
	    tnode, tnode, &fqi->fq_dnode, fqi->fq_last_comp);

	if (rc != 0) {
		smbsr_errno(sr, rc);
		return (SDRC_ERROR);
	}

	rc = smb_fsop_lookup(sr, sr->user_cr, SMB_FOLLOW_LINKS,
	    tnode, fqi->fq_dnode, fqi->fq_last_comp, &fqi->fq_fnode);
	if (rc != 0) {
		if (rc == ENOENT)
			smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
			    ERRDOS, ERROR_FILE_NOT_FOUND);
		else
			smbsr_errno(sr, rc);
		smb_node_release(fqi->fq_dnode);
		return (SDRC_ERROR);
	}

	/*
	 * Delete should fail if this is the root of a share
	 * or a DFS link
	 */
	if ((fqi->fq_fnode == tnode) || smb_node_is_dfslink(fqi->fq_fnode)) {
		smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
		    ERRDOS, ERROR_ACCESS_DENIED);
		smb_node_release(fqi->fq_dnode);
		smb_node_release(fqi->fq_fnode);
		return (SDRC_ERROR);
	}

	if (!smb_node_is_dir(fqi->fq_fnode)) {
		smbsr_error(sr, NT_STATUS_NOT_A_DIRECTORY,
		    ERRDOS, ERROR_PATH_NOT_FOUND);
		smb_node_release(fqi->fq_dnode);
		smb_node_release(fqi->fq_fnode);
		return (SDRC_ERROR);
	}

	/*
	 * Using kcred because we just want the DOS attrs
	 * and don't want access errors for this.
	 */
	fqi->fq_fattr.sa_mask = SMB_AT_DOSATTR;
	rc = smb_node_getattr(sr, fqi->fq_fnode, zone_kcred(), NULL,
	    &fqi->fq_fattr);
	if (rc != 0) {
		smbsr_errno(sr, rc);
		smb_node_release(fqi->fq_dnode);
		smb_node_release(fqi->fq_fnode);
		return (SDRC_ERROR);
	}

	if ((fqi->fq_fattr.sa_dosattr & FILE_ATTRIBUTE_READONLY) ||
	    (smb_fsop_access(sr, sr->user_cr, fqi->fq_fnode, DELETE)
	    != NT_STATUS_SUCCESS)) {
		smbsr_error(sr, NT_STATUS_CANNOT_DELETE,
		    ERRDOS, ERROR_ACCESS_DENIED);
		smb_node_release(fqi->fq_dnode);
		smb_node_release(fqi->fq_fnode);
		return (SDRC_ERROR);
	}

	if (SMB_TREE_SUPPORTS_CATIA(sr))
		flags |= SMB_CATIA;

	rc = smb_fsop_rmdir(sr, sr->user_cr, fqi->fq_dnode,
	    fqi->fq_fnode->od_name, flags);

	smb_node_release(fqi->fq_fnode);
	smb_node_release(fqi->fq_dnode);

	if (rc != 0) {
		if (rc == EEXIST)
			smbsr_error(sr, NT_STATUS_DIRECTORY_NOT_EMPTY,
			    ERRDOS, ERROR_DIR_NOT_EMPTY);
		else
			smbsr_errno(sr, rc);
		return (SDRC_ERROR);
	}

	rc = smbsr_encode_empty_result(sr);
	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
예제 #5
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);
}