diff --git a/beets/util/__init__.py b/beets/util/__init__.py index a32c44908..1f9279b25 100644 --- a/beets/util/__init__.py +++ b/beets/util/__init__.py @@ -16,6 +16,7 @@ from __future__ import (division, absolute_import, print_function, unicode_literals) +import ctypes import os import sys @@ -781,26 +782,30 @@ def is_filesystem_case_sensitive(path): # python < 3.0 return not os.path.samefile(path.lower(), path.upper()) - # On windows we create a file with a lower case name - # and try to find the file using an upper case name. - base_file_name = 'beetsCaseSensitivityCheck' - lower = os.path.join(path, base_file_name.lower()) - upper = os.path.join(path, base_file_name.upper()) - # Check if one of the files (upper and lower case) do exist - # already - i = 0 - while os.path.exists(lower) or os.path.exists(upper): - file_name = '{0}{1}'.format(base_file_name, i) - lower = os.path.join(path, file_name.lower()) - upper = os.path.join(path, file_name.upper()) - # Create the file using a lower case name - with open(lower, 'w'): - pass - # Check if the file can be found using the upper cas name - case_sensitive = not os.path.exists(upper) - # Remove the temporary file - os.remove(lower) - return case_sensitive + + # On windows we use GetLongPathNameW to determine the real path + # using the actual case. + def get_long_path_name(short_path): + if not isinstance(short_path, unicode): + short_path = unicode(short_path) + buf = ctypes.create_unicode_buffer(260) + get_long_path_name_w = ctypes.windll.kernel32.GetLongPathNameW + return_value = get_long_path_name_w(short_path, buf, 260) + if return_value == 0 or return_value > 260: + # An error occurred + return short_path + else: + long_path = buf.value + # GetLongPathNameW does not change the case of the drive + # letter. + if len(long_path) > 1 and long_path[1] == ':': + long_path = long_path[0].upper() + long_path[1:] + return long_path + + lower = get_long_path_name(path.lower()) + upper = get_long_path_name(path.upper()) + + return lower != upper else: return True # By default, the case sensitivity depends on the platform.