# HG changeset patch # User Markus Mützel # Date 1586630784 -7200 # Node ID 9a1b6400c706d565ef425e6f3b7daad32d0a1dfd # Parent 6c88000fed4826c9632ab3dea24411eb69ef54bd Canonicalize case of long parts of path on Windows file systems (bug #58148). * file-ops.cc (canonicalize_file_name): Call GetShortPathNameW before GetLongPathNameW to also get actual letter case for parts of the path that are longer than the 8.3 short file names. diff -r 6c88000fed48 -r 9a1b6400c706 liboctave/system/file-ops.cc --- a/liboctave/system/file-ops.cc Sat Apr 11 08:19:45 2020 -0400 +++ b/liboctave/system/file-ops.cc Sat Apr 11 20:46:24 2020 +0200 @@ -736,14 +736,25 @@ if (! w_tmp.empty ()) { // Get a more canonical name wrt case and full names - wchar_t w_long[32767] = L""; - int w_len = GetLongPathNameW (w_tmp.c_str (), w_long, 32767); + // FIXME: To make this work on partitions that don't store short file + // names, use FindFirstFileW on each component of the path. + // Insufficient access permissions on parent folders might make this + // tricky. + + // Parts of the path that wouldn't fit into a short 8.3 file name are + // copied as is by GetLongPathNameW. To also get the correct case + // for these parts, first convert to short file names and than back + // to long. + wchar_t buffer[32767] = L""; + int w_len = GetShortPathNameW (w_tmp.c_str (), buffer, 32767); + w_len = GetLongPathNameW (buffer, buffer, 32767); if (! strip_marker) - retval = u8_from_wstring (std::wstring (w_long, w_len)); + retval = u8_from_wstring (std::wstring (buffer, w_len)); else if (w_len > 4) - retval = u8_from_wstring (std::wstring (w_long+4, w_len-4)); + retval = u8_from_wstring (std::wstring (buffer+4, w_len-4)); + // If root is a drive, use an upper case letter for the drive letter. if (retval.length () > 1 && retval[1] == ':') retval[0] = toupper (retval[0]); }