# HG changeset patch # User Markus Mützel # Date 1659630771 -7200 # Thu Aug 04 18:32:51 2022 +0200 # Node ID dcbc3caa80e60a1a9c5428ccca498f8f31266d49 # Parent bf6376a754a40ae94a8e939ebd9bccbb0d592439 canonicalize_file_name: Handle symlinks on mapped network drives (bug #62847). * liboctave/system/file-ops.cc (canonicalize_file_name): Check if canonical path of UNC share corresponds to UNC path of mapped network drive. Support canonicalizing paths to symbolic link directories. diff -r bf6376a754a4 -r dcbc3caa80e6 liboctave/system/file-ops.cc --- a/liboctave/system/file-ops.cc Wed Aug 03 15:50:54 2022 -0700 +++ b/liboctave/system/file-ops.cc Thu Aug 04 18:32:51 2022 +0200 @@ -707,7 +707,8 @@ std::wstring wname = u8_to_wstring (name); HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, nullptr); + FILE_FLAG_BACKUP_SEMANTICS + | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h_file == INVALID_HANDLE_VALUE) { @@ -742,12 +743,48 @@ // "\\server\share" portion of path with drive root. if (name[1] == ':') { - // Find where "share" portion of UNC path ends + // Find where "share" portion of UNC path ends. std::size_t sep_pos = retval.find_first_of (file_ops::dir_sep_chars (), 2); if (sep_pos != std::string::npos) sep_pos = retval.find_first_of (file_ops::dir_sep_chars (), sep_pos + 1); + + // Check if the original root was a map to this UNC share. + std::wstring orig_map = wname.substr (0, 2); + HANDLE h_map = CreateFileW (orig_map.c_str (), GENERIC_READ, + FILE_SHARE_READ, nullptr, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS + | FILE_FLAG_OPEN_REPARSE_POINT, + nullptr); + if (h_file != INVALID_HANDLE_VALUE) + { + unwind_action close_map_handle (CloseHandle, h_map); + len = GetFinalPathNameByHandleW (h_map, buffer, buf_size, + FILE_NAME_NORMALIZED); + std::string orig_dest + = u8_from_wstring (std::wstring (buffer, len)); + + if (orig_dest.compare (0, 8, R"(\\?\UNC\)") == 0) + { + orig_dest = orig_dest.erase (2, 6); + // Find where "share" portion of UNC path ends. + std::size_t sep_pos_orig + = orig_dest.find_first_of (file_ops::dir_sep_chars (), + 2); + if (sep_pos_orig != std::string::npos) + sep_pos_orig + = retval.find_first_of (file_ops::dir_sep_chars (), + sep_pos_orig + 1); + if (retval.substr (0, sep_pos) + .compare (orig_dest.substr (0, sep_pos_orig))) + // share doesn't match mapped drive + return retval; + } + } + + // File is on mapped share. if (sep_pos != std::string::npos) retval = retval.substr (sep_pos-2); else