Skip to content
This repository has been archived by the owner on Oct 31, 2023. It is now read-only.

Commit

Permalink
Always use long Windows paths for shared directories
Browse files Browse the repository at this point in the history
Name of the share is a hash of the shared directory's path. Any
non-canonical forms of the path would break file sharing because they
would have a different hash. Therefore we make sure to standardize the
path before computing the hash function.
This commit improves the path standardization by introducing expansion
of shortened paths (a.k.a. 8.3 paths, DOS paths). Such paths have been
observed during Golem installation as "Jack Daniel's" user.
  • Loading branch information
Wiezzel committed Apr 3, 2019
1 parent 1ae76b7 commit c10fbf3
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
8 changes: 6 additions & 2 deletions golem/docker/smbshare.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import hashlib
from os import path, makedirs
from pathlib import Path
import subprocess
from subprocess import CalledProcessError, TimeoutExpired
import sys

from golem.core.common import get_golem_path, is_windows
Expand All @@ -29,8 +27,14 @@ def create_share(user_name: str, shared_dir_path: Path) -> None:


def get_share_name(shared_dir_path: Path) -> str:
import win32file # pylint: disable=import-error

if not shared_dir_path.is_dir():
raise ValueError(f"There's no such directory as '{shared_dir_path}'")

# normalize -> encode -> MD5 digest -> hexlify -> decode -> uppercase
norm_path: str = path.normpath(shared_dir_path) # type: ignore
norm_path = win32file.GetLongPathName(norm_path)
norm_path = path.normcase(norm_path)
return binascii.hexlify(
hashlib.md5(
Expand Down
2 changes: 1 addition & 1 deletion scripts/docker/create-share.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ if (!(Test-Path -Path $SharedDirPath -PathType Container)) {
}

# Normalize path
$SharedDirPath = (Convert-Path -Path $SharedDirPath).TrimEnd("\").ToLower()
$SharedDirPath = (Get-Item -Path $SharedDirPath).FullName.TrimEnd("\").ToLower()

"Setting directory ACL..."

Expand Down
46 changes: 37 additions & 9 deletions tests/golem/docker/test_smbshare.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os
import shutil
from pathlib import Path
from unittest import TestCase, skipUnless

Expand All @@ -8,7 +10,30 @@
@skipUnless(is_windows(), 'Windows only')
class TestGetShareName(TestCase):

DEFAULT_SHARE_NAME = "C37A161EDD52B4F2C7C59E6144A47595"
DEFAULT_SHARE_PATH = "C:\\Users\\Public\\AppData\\Local\\golem\\golem\\" \
"default\\rinkeby\\ComputerRes"
DEFAULT_SHARE_NAME = "C97956C9B0D048CCC69B36413DBC994E"

@classmethod
def setUpClass(cls):
# The path must exist for get_share_name() to work correctly.
# We cannot use a temp directory because it does not have a fixed path
# and, in turn, a fixed share name.
# In the cleanup we want to remove only what we created.
current_path = Path("C:\\")
for dirname in cls.DEFAULT_SHARE_PATH.split('\\')[1:]:
current_path /= dirname
if not current_path.is_dir():
cls._path_to_remove = current_path
break
else:
cls._path_to_remove = None

os.makedirs(cls.DEFAULT_SHARE_PATH, exist_ok=True)

@classmethod
def tearDownClass(cls):
shutil.rmtree(cls._path_to_remove)

def _assert_share_name(self, path, share_name=DEFAULT_SHARE_NAME):
self.assertEqual(
Expand All @@ -17,31 +42,34 @@ def _assert_share_name(self, path, share_name=DEFAULT_SHARE_NAME):
)

def test_normal_path(self):
self._assert_share_name(
"C:\\Users\\golem\\AppData\\Local\\golem\\golem\\default\\"
"rinkeby\\ComputerRes"
)
self._assert_share_name(self.DEFAULT_SHARE_PATH)

def test_trailing_backslash(self):
self._assert_share_name(
"C:\\Users\\golem\\AppData\\Local\\golem\\golem\\default\\"
"C:\\Users\\Public\\AppData\\Local\\golem\\golem\\default\\"
"rinkeby\\ComputerRes\\"
)

def test_slashes(self):
self._assert_share_name(
"C:/Users/golem/AppData/Local/golem/golem/default/"
"C:/Users/Public/AppData/Local/golem/golem/default/"
"rinkeby/ComputerRes"
)

def test_dots(self):
self._assert_share_name(
"C:\\Users\\golem\\AppData\\Local\\golem\\golem\\default\\"
"C:\\Users\\Public\\AppData\\Local\\golem\\golem\\default\\"
"rinkeby\\ComputerRes\\.\\tmp\\.."
)

def test_letter_case(self):
self._assert_share_name(
"c:\\USERS\\Golem\\appdata\\LOCAL\\GoLeM\\golem\\DEFAULT\\"
"c:\\USERS\\puBlic\\appdata\\LOCAL\\GoLeM\\golem\\DEFAULT\\"
"rinkeBY\\computerres"
)

def test_shortened_path(self):
self._assert_share_name(
"C:\\Users\\Public\\AppData\\Local\\golem\\golem\\default\\"
"rinkeby\\COMPUT~1"
)

0 comments on commit c10fbf3

Please sign in to comment.