changeset 25660:4de7535ece11

Relative path specifications for non-ASCII files on Windows. * lo-sysdep.cc (get_ASCII_filename): Produce ASCII-only file name for files with relative path specification.
author Markus Mützel <markus.muetzel@gmx.de>
date Thu, 19 Jul 2018 22:43:17 +0200
parents e6d3f4f9473c
children e189ee5cd537
files liboctave/system/lo-sysdep.cc
diffstat 1 files changed, 32 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/system/lo-sysdep.cc	Mon Jul 23 10:15:26 2018 -0400
+++ b/liboctave/system/lo-sysdep.cc	Thu Jul 19 22:43:17 2018 +0200
@@ -259,34 +259,50 @@
       // 2. Check if file system stores short filenames (always
       // ASCII-only).
 
-      const wchar_t *w_orig_file_name = u8_to_wstring (orig_file_name).c_str ();
+      std::wstring w_orig_file_name_str = u8_to_wstring (orig_file_name);
+      const wchar_t *w_orig_file_name = w_orig_file_name_str.c_str ();
+
+      // Get full path to file
+      wchar_t w_full_file_name[_MAX_PATH];
+      if (_wfullpath (w_full_file_name, w_orig_file_name, _MAX_PATH) == nullptr)
+        return orig_file_name;
+
+      std::wstring w_full_file_name_str = w_full_file_name;
 
       // Get short filename (8.3) from UTF-16 filename.
 
-      long length = GetShortPathNameW (w_orig_file_name, NULL, 0);
+      long length = GetShortPathNameW (w_full_file_name, nullptr, 0);
 
-      // Dynamically allocate the correct size (terminating null char
-      // was included in length).
+      if (length > 0)
+        {
+          // Dynamically allocate the correct size (terminating null char
+          // was included in length).
 
-      wchar_t *w_short_file_name = new wchar_t[length];
-      length = GetShortPathNameW (w_orig_file_name, w_short_file_name, length);
+          wchar_t *w_short_file_name = new wchar_t[length];
+          GetShortPathNameW (w_full_file_name, w_short_file_name, length);
 
-      std::string short_file_name
-        = u8_from_wstring (std::wstring (w_short_file_name));
+          std::wstring w_short_file_name_str
+            = std::wstring (w_short_file_name, length);
+          std::string short_file_name = u8_from_wstring (w_short_file_name_str);
 
-      if (short_file_name.compare (orig_file_name) != 0)
-        return short_file_name;
+          if (w_short_file_name_str.compare (0, length-1, w_full_file_name_str) != 0)
+            return short_file_name;
+        }
 
       // 3. Create hard link with only-ASCII characters.
       // Get longest possible part of path that only contains ASCII chars.
 
-      std::string tmp_substr
-        = std::string (orig_file_name.begin (), first_non_ASCII);
+      std::wstring::iterator w_first_non_ASCII
+        = std::find_if (w_full_file_name_str.begin (), w_full_file_name_str.end (),
+                        [](wchar_t c) { return (c < 0 || c >= 128); });
+      std::wstring tmp_substr
+        = std::wstring (w_full_file_name_str.begin (), w_first_non_ASCII);
 
       size_t pos
-        = tmp_substr.find_last_of (octave::sys::file_ops::dir_sep_chars ());
+        = tmp_substr.find_last_of (u8_to_wstring (file_ops::dir_sep_chars ()));
 
-      std::string par_dir = orig_file_name.substr (0, pos+1);
+      std::string par_dir
+        = u8_from_wstring (w_full_file_name_str.substr (0, pos+1));
 
       // Create .oct_ascii directory.
       // FIXME: We need to have write permission in this location.
@@ -314,14 +330,14 @@
       std::string abs_filename_hash = canonicalize_file_name (filename_hash);
 
       if (! abs_filename_hash.empty ())
-        return abs_filename_hash;
+        octave::sys::unlink (filename_hash);
 
       wchar_t w_filename_hash[filename_hash.length ()+1] = {0};
 
       for (size_t i=0; i < filename_hash.length (); i++)
         w_filename_hash[i] = filename_hash.at (i);
 
-      if (CreateHardLinkW (w_filename_hash, w_orig_file_name, NULL))
+      if (CreateHardLinkW (w_filename_hash, w_orig_file_name, nullptr))
         return filename_hash;
 
 #endif