Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix rename operations for a DFS path #191

Merged
merged 2 commits into from
Aug 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions src/smbclient/_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,18 +352,6 @@ def __init__(
):
tree, fd_path = get_smb_tree(path, **kwargs)

# When opening a file on a DFS tree the raw path used in the CREATE
# request is the the original DFS path as the server should normalise
# it and return STATUS_PATH_NOT_COVERED if it's served by a DFS target
# server. The fd_path returned by get_smb_tree is still kept as it's
# needed for rename operations that need the tree relative path to
# rename files/dirs to.
# https://github.com/jborean93/smbprotocol/issues/170
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/448cb979-7321-4598-89df-e5c97135b566
self._fd_path = fd_path
if tree.is_dfs_share:
fd_path = "\\".join(p for p in path.split("\\") if p)

self.share_access = share_access
self.fd = Open(tree, fd_path)
self._mode = mode
Expand Down
10 changes: 9 additions & 1 deletion src/smbclient/_os.py
Original file line number Diff line number Diff line change
Expand Up @@ -1128,10 +1128,18 @@ def _rename_information(src, dst, replace_if_exists=False, **kwargs):
if src_guid != dst_guid or src_share.lower() != dst_share.lower():
raise ValueError("Cannot %s a file to a different root than the src." % verb)

dst_tree = dst_raw.fd.tree_connect
dst_path = dst_raw.fd.file_name
if dst_tree.is_dfs_share and dst_path.startswith(dst_tree.share_name[2:]):
# Special handling when dst is on a DFS share, the renamed file
# should not include the DFS share itself that is present on the
# Open.file_name. Strip out that prefix if present.
dst_path = dst_path[len(dst_tree.share_name) - 1 :]

with SMBFileTransaction(src_raw) as transaction:
file_rename = FileRenameInformation()
file_rename["replace_if_exists"] = replace_if_exists
file_rename["file_name"] = to_text(dst_raw._fd_path)
file_rename["file_name"] = to_text(dst_path)
set_info(transaction, file_rename)


Expand Down
11 changes: 10 additions & 1 deletion src/smbclient/_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,17 @@ def get_smb_tree(

return get_smb_tree(path, **get_kwargs)

# When opening a file on a DFS tree the raw path used in the CREATE
# request is the the original DFS path as the server should normalise
# it and return STATUS_PATH_NOT_COVERED if it's served by a DFS target
# server.
# https://github.com/jborean93/smbprotocol/issues/170
# https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/448cb979-7321-4598-89df-e5c97135b566
file_path = ""
if len(path_split) > 2:
if tree.is_dfs_share:
file_path = "\\".join(path_split)

elif len(path_split) > 2:
file_path = "\\".join(path_split[2:])

return tree, file_path
Expand Down
2 changes: 1 addition & 1 deletion src/smbprotocol/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,7 @@ def _send(
header["data"] = message.pack()
header["next_command"] = next_command

if is_dfs and message.COMMAND == Commands.SMB2_CREATE:
if is_dfs:
header["flags"].set_flag(Smb2Flags.SMB2_FLAGS_DFS_OPERATIONS)

if i != 0 and related:
Expand Down