From e6beb2a19e42dd887749b92aab82dd1c3f13f554 Mon Sep 17 00:00:00 2001 From: Kaz Wolfe Date: Sat, 7 Jan 2023 15:31:52 -0800 Subject: [PATCH] fix: Fix broken case for relative symlinks Currently, the game will have issues saving files to a relative symlink (for example, when a .DAT file is a symlink pointing to ../CHR_12345/HOTBAR.DAT). This change replaces the symlink resolution system with one that calls `weakly_canonical` to resolve and clean up the path in a single operation. --- Dalamud.Boot/xivfixes.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Dalamud.Boot/xivfixes.cpp b/Dalamud.Boot/xivfixes.cpp index 800ed585f..3bdf4fe23 100644 --- a/Dalamud.Boot/xivfixes.cpp +++ b/Dalamud.Boot/xivfixes.cpp @@ -437,13 +437,13 @@ void xivfixes::backup_userdata_save(bool bApply) { if (ext != ".dat" && ext != ".cfg") return s_hookCreateFileW->call_original(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - for (auto i = 0; i < 16; i++) { - std::error_code ec; - auto resolved = read_symlink(path, ec); - if (ec || resolved == path) - break; - path = std::move(resolved); - } + // Resolve any symbolic links or shenanigans in the chain so that we'll always be working with a canonical + // file. If there's an error getting the canonical path, fall back to default behavior and ignore our + // fancy logic. We use weakly_canonical here so that we don't run into issues if `path` does not exist. + std::error_code ec; + path = weakly_canonical(path, ec); + if (ec) + return s_hookCreateFileW->call_original(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); std::filesystem::path temporaryPath = path; temporaryPath.replace_extension(std::format(L"{}.new.{:X}.{:X}", path.extension().c_str(), std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), GetCurrentProcessId()));