# HG changeset patch # User Markus Mützel # Date 1659862516 -7200 # Node ID 7f4ad92265d2c67e00a0d6eb3af73cfe434a4cbd # Parent bf6376a754a40ae94a8e939ebd9bccbb0d592439# Parent 51311efef5dde75525b1dbf8fa22ec4b81240402 maint: Merge stable to default. diff -r bf6376a754a4 -r 7f4ad92265d2 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 Sun Aug 07 10:55:16 2022 +0200 @@ -709,6 +709,16 @@ FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + // Might have been a symbolic link that points to a network share. + // It looks like opening a network share itself (not a file or folder + // *on* a share) might return an invalid handle. As a workaround, try to + // open a handle to the symbolic link itself (and do not resolve it). + if (h_file == INVALID_HANDLE_VALUE) + h_file = CreateFileW (wname.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) { msg = "Unable to open file \"" + name + "\""; @@ -742,12 +752,49 @@ // "\\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 original drive letter 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