changeset 28204:9a1b6400c706 stable

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.
author Markus Mützel <markus.muetzel@gmx.de>
date Sat, 11 Apr 2020 20:46:24 +0200
parents 6c88000fed48
children 1ef597f9b0bb 11d66485fc19
files liboctave/system/file-ops.cc
diffstat 1 files changed, 15 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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]);
         }