NTSTATUS rename_internals(TALLOC_CTX *ctx,
			connection_struct *conn,
			struct smb_request *req,
			struct smb_filename *smb_fname_src,
			struct smb_filename *smb_fname_dst,
			const char *dst_original_lcomp,
			uint32_t attrs,
			bool replace_if_exists,
			uint32_t access_mask)
{
	NTSTATUS status = NT_STATUS_OK;
	int create_options = 0;
	struct smb2_create_blobs *posx = NULL;
	struct files_struct *fsp = NULL;
	bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
	bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
	bool case_preserve = posix_pathname ? true : conn->case_preserve;
	bool short_case_preserve = posix_pathname ? true :
					conn->short_case_preserve;

	if (posix_pathname) {
		status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
		if (!NT_STATUS_IS_OK(status)) {
			DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
				    nt_errstr(status));
			goto out;
		}
	}

	DBG_NOTICE("case_sensitive = %d, "
		  "case_preserve = %d, short case preserve = %d, "
		  "directory = %s, newname = %s, "
		  "last_component_dest = %s\n",
		  case_sensitive, case_preserve,
		  short_case_preserve,
		  smb_fname_str_dbg(smb_fname_src),
		  smb_fname_str_dbg(smb_fname_dst),
		  dst_original_lcomp);

	ZERO_STRUCT(smb_fname_src->st);

	status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
	if (!NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_EQUAL(status,
				NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
			goto out;
		}
		/*
		 * Possible symlink src.
		 */
		if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
			goto out;
		}
		if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
			goto out;
		}
	}

	if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
		create_options |= FILE_DIRECTORY_FILE;
	}

	status = SMB_VFS_CREATE_FILE(
			conn,				/* conn */
			req,				/* req */
			NULL,				/* dirfsp */
			smb_fname_src,			/* fname */
			access_mask,			/* access_mask */
			(FILE_SHARE_READ |		/* share_access */
			    FILE_SHARE_WRITE),
			FILE_OPEN,			/* create_disposition*/
			create_options,			/* create_options */
			0,				/* file_attributes */
			0,				/* oplock_request */
			NULL,				/* lease */
			0,				/* allocation_size */
			0,				/* private_flags */
			NULL,				/* sd */
			NULL,				/* ea_list */
			&fsp,				/* result */
			NULL,				/* pinfo */
			posx,				/* in_context_blobs */
			NULL);				/* out_context_blobs */

	if (!NT_STATUS_IS_OK(status)) {
		DBG_NOTICE("Could not open rename source %s: %s\n",
			  smb_fname_str_dbg(smb_fname_src),
			  nt_errstr(status));
		goto out;
	}

	status = rename_internals_fsp(conn,
					fsp,
					smb_fname_dst,
					dst_original_lcomp,
					attrs,
					replace_if_exists);

	close_file_free(req, &fsp, NORMAL_CLOSE);

	DBG_NOTICE("Error %s rename %s -> %s\n",
		  nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
		  smb_fname_str_dbg(smb_fname_dst));

 out:
	TALLOC_FREE(posx);
	return status;
}
NTSTATUS rename_internals(TALLOC_CTX *ctx,
			connection_struct *conn,
			struct smb_request *req,
			struct smb_filename *smb_fname_src,
			struct smb_filename *smb_fname_dst,
			const char *dst_original_lcomp,
			uint32_t attrs,
			bool replace_if_exists,
			uint32_t access_mask)
{
	NTSTATUS status = NT_STATUS_OK;
	int create_options = 0;
	struct smb2_create_blobs *posx = NULL;
	struct files_struct *fsp = NULL;
	bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH);
	bool case_sensitive = posix_pathname ? true : conn->case_sensitive;
	bool case_preserve = posix_pathname ? true : conn->case_preserve;
	bool short_case_preserve = posix_pathname ? true :
					conn->short_case_preserve;

	if (posix_pathname) {
		status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
		if (!NT_STATUS_IS_OK(status)) {
			DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
				    nt_errstr(status));
			goto out;
		}
	}

	DBG_NOTICE("case_sensitive = %d, "
		  "case_preserve = %d, short case preserve = %d, "
		  "directory = %s, newname = %s, "
		  "last_component_dest = %s\n",
		  case_sensitive, case_preserve,
		  short_case_preserve,
		  smb_fname_str_dbg(smb_fname_src),
		  smb_fname_str_dbg(smb_fname_dst),
		  dst_original_lcomp);

	ZERO_STRUCT(smb_fname_src->st);

	status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src);
	if (!NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_EQUAL(status,
				NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
			goto out;
		}
		 
		if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) {
			goto out;
		}
		if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) {
			goto out;
		}
	}

	if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
		create_options |= FILE_DIRECTORY_FILE;
	}

	status = SMB_VFS_CREATE_FILE(
			conn,				 
			req,				 
			NULL,				 
			smb_fname_src,			 
			access_mask,			 
			(FILE_SHARE_READ |		 
			    FILE_SHARE_WRITE),
			FILE_OPEN,			 
			create_options,			 
			0,				 
			0,				 
			NULL,				 
			0,				 
			0,				 
			NULL,				 
			NULL,				 
			&fsp,				 
			NULL,				 
			posx,				 
			NULL);				 

	if (!NT_STATUS_IS_OK(status)) {
		DBG_NOTICE("Could not open rename source %s: %s\n",
			  smb_fname_str_dbg(smb_fname_src),
			  nt_errstr(status));
		goto out;
	}

	status = rename_internals_fsp(conn,
					fsp,
					smb_fname_dst,
					dst_original_lcomp,
					attrs,
					replace_if_exists);

	close_file_free(req, &fsp, NORMAL_CLOSE);

	DBG_NOTICE("Error %s rename %s -> %s\n",
		  nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
		  smb_fname_str_dbg(smb_fname_dst));

 out:
	TALLOC_FREE(posx);
	return status;
}