smb_rename.c revision 8c10a8659ac31335ed870a1711c0182623f72fd6
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * CDDL HEADER START
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Common Development and Distribution License (the "License").
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You may not use this file except in compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * or http://www.opensolaris.org/os/licensing.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing permissions
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below this CDDL HEADER, with the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * information: Portions Copyright [yyyy] [name of copyright owner]
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * CDDL HEADER END
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Use is subject to license terms.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#pragma ident "%Z%%M% %I% %E% SMI"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <smbsrv/nterror.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <sys/synch.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <smbsrv/smb_incl.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <smbsrv/smb_fsops.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <sys/nbmlock.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int smb_do_rename(smb_request_t *, struct smb_fqi *, struct smb_fqi *);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * smb_com_rename
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Rename a file. Files OldFileName must exist and NewFileName must not.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Both pathnames must be relative to the Tid specified in the request.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Open files may be renamed.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Multiple files may be renamed in response to a single request as Rename
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * File supports wildcards in the file name (last component of the path).
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * NOTE: we don't support rename with wildcards.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * SearchAttributes indicates the attributes that the target file(s) must
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * have. If SearchAttributes is zero then only normal files are renamed.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If the system file or hidden attributes are specified then the rename
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is inclusive - both the specified type(s) of files and normal files are
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * renamed. The encoding of SearchAttributes is described in section 3.10
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * - File Attribute Encoding.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_sdrc_t
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_pre_rename(smb_request_t *sr)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *src_fqi = &sr->arg.dirop.fqi;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *dst_fqi = &sr->arg.dirop.dst_fqi;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((rc = smbsr_decode_vwv(sr, "w", &src_fqi->srch_attr)) == 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = smbsr_decode_data(sr, "%SS", sr, &src_fqi->path,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster &dst_fqi->path);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster dst_fqi->srch_attr = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DTRACE_SMB_2(op__Rename__start, smb_request_t *, sr,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct dirop *, &sr->arg.dirop);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_post_rename(smb_request_t *sr)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DTRACE_SMB_1(op__Rename__done, smb_request_t *, sr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_sdrc_t
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_com_rename(smb_request_t *sr)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static kmutex_t mutex;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *src_fqi = &sr->arg.dirop.fqi;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *dst_fqi = &sr->arg.dirop.dst_fqi;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_node *dst_node;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!STYPE_ISDSK(sr->tid_tree->t_res_type)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ERRDOS, ERROR_ACCESS_DENIED);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return (SDRC_ERROR);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster mutex_enter(&mutex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = smb_do_rename(sr, src_fqi, dst_fqi);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster mutex_exit(&mutex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (rc != 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The following values are based on observed WFWG,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Windows 9x, NT and Windows 2000 behaviour.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * ERROR_FILE_EXISTS doesn't work for Windows 98 clients.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Windows 95 clients don't see the problem because the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * target is deleted before the rename request.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster switch (rc) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case EEXIST:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smbsr_error(sr, NT_STATUS_OBJECT_NAME_COLLISION,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ERRDOS, ERROR_ALREADY_EXISTS);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case EPIPE:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smbsr_error(sr, NT_STATUS_SHARING_VIOLATION,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ERRDOS, ERROR_SHARING_VIOLATION);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case ENOENT:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smbsr_error(sr, NT_STATUS_OBJECT_NAME_NOT_FOUND,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ERRDOS, ERROR_FILE_NOT_FOUND);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster default:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smbsr_errno(sr, rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return (SDRC_ERROR);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (src_fqi->dir_snode)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_release(src_fqi->dir_snode);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster dst_node = dst_fqi->dir_snode;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (dst_node) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (dst_node->flags & NODE_FLAGS_NOTIFY_CHANGE) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster dst_node->flags |= NODE_FLAGS_CHANGED;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_process_node_notify_change_queue(dst_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_release(dst_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMB_NULL_FQI_NODES(*src_fqi);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SMB_NULL_FQI_NODES(*dst_fqi);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rc = smbsr_encode_empty_result(sr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * smb_do_rename
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Backend to smb_com_rename to ensure that the rename operation is atomic.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This function should be called within a mutual exclusion region. If the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * source and destination are identical, we don't actually do a rename, we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * just check that the conditions are right. If the source and destination
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * files differ only in case, we a case-sensitive rename. Otherwise, we do
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * a full case-insensitive rename.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This function should always return errno values.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Upon success, the last_snode's and dir_snode's of both src_fqi and dst_fqi
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * are not released in this routine but in smb_com_rename().
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersmb_do_rename(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_request_t *sr,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *src_fqi,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_fqi *dst_fqi)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster struct smb_node *src_node;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char *dstname;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DWORD status;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int rc;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int count;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((rc = smbd_fs_query(sr, src_fqi, FQM_PATH_MUST_EXIST)) != 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return (rc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster src_node = src_fqi->last_snode;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Break the oplock before access checks. If a client
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * has a file open, this will force a flush or close,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * which may affect the outcome of any share checking.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_oplock_break(src_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (count = 0; count <= 3; count++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (count) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_end_crit(src_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster delay(MSEC_TO_TICK(400));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_start_crit(src_node, RW_READER);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster status = smb_node_rename_check(src_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (status != NT_STATUS_SHARING_VIOLATION)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (status == NT_STATUS_SHARING_VIOLATION) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_end_crit(src_node);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster smb_node_release(src_node);
smb_node_release(src_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
return (EPIPE); /* = ERRbadshare */
}
status = smb_range_check(sr, sr->user_cr, src_node, 0, UINT64_MAX,
B_TRUE);
if (status != NT_STATUS_SUCCESS) {
smb_node_end_crit(src_node);
smb_node_release(src_node);
smb_node_release(src_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
return (EACCES);
}
if (utf8_strcasecmp(src_fqi->path, dst_fqi->path) == 0) {
if ((rc = smbd_fs_query(sr, dst_fqi, 0)) != 0) {
smb_node_end_crit(src_node);
smb_node_release(src_node);
smb_node_release(src_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
return (rc);
}
/*
* Because the fqm parameter to smbd_fs_query() was 0,
* a successful return value means that dst_fqi->last_snode
* may be NULL.
*/
if (dst_fqi->last_snode)
smb_node_release(dst_fqi->last_snode);
rc = strcmp(src_fqi->last_comp_od, dst_fqi->last_comp);
if (rc == 0) {
smb_node_end_crit(src_node);
smb_node_release(src_node);
smb_node_release(src_fqi->dir_snode);
smb_node_release(dst_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
return (0);
}
rc = smb_fsop_rename(sr, sr->user_cr,
src_fqi->dir_snode,
src_fqi->last_comp_od,
dst_fqi->dir_snode,
dst_fqi->last_comp);
if (rc != 0) {
smb_node_release(src_fqi->dir_snode);
smb_node_release(dst_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
}
smb_node_end_crit(src_node);
smb_node_release(src_node);
return (rc);
}
rc = smbd_fs_query(sr, dst_fqi, FQM_PATH_MUST_NOT_EXIST);
if (rc != 0) {
smb_node_end_crit(src_node);
smb_node_release(src_node);
smb_node_release(src_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
return (rc);
}
/*
* Because of FQM_PATH_MUST_NOT_EXIST and the successful return
* value, only dst_fqi->dir_snode is valid (dst_fqi->last_snode
* is NULL).
*/
/*
* Use the unmangled form of the destination name if the
* source and destination names are the same and the source
* name is mangled. (We are taking a chance here, assuming
* that this is what the user wants.)
*/
if ((smb_maybe_mangled_name(src_fqi->last_comp)) &&
(strcmp(src_fqi->last_comp, dst_fqi->last_comp) == 0)) {
dstname = src_fqi->last_comp_od;
} else {
dstname = dst_fqi->last_comp;
}
rc = smb_fsop_rename(sr, sr->user_cr,
src_fqi->dir_snode,
src_fqi->last_comp_od,
dst_fqi->dir_snode,
dstname);
if (rc != 0) {
smb_node_release(src_fqi->dir_snode);
smb_node_release(dst_fqi->dir_snode);
SMB_NULL_FQI_NODES(*src_fqi);
SMB_NULL_FQI_NODES(*dst_fqi);
}
smb_node_end_crit(src_node);
smb_node_release(src_node);
return (rc);
}