diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2024-04-29 13:00:37 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-04-29 13:00:37 +0200 |
commit | 32070144af66297865bc96719bffb73219b10e03 (patch) | |
tree | a2f7309509c831ce4611988500201bdb39791254 /drivers/windows | |
parent | 339cb0e2a20d7f6e65e7f971597c6354e8c23b91 (diff) | |
parent | fc948e87f6bcbd403b2a5935ceae8b9c42751dfc (diff) | |
download | redot-engine-32070144af66297865bc96719bffb73219b10e03.tar.gz |
Merge pull request #91100 from bruvzg/x_finks
Add symlink API support for Windows, expose symlink methods.
Diffstat (limited to 'drivers/windows')
-rw-r--r-- | drivers/windows/dir_access_windows.cpp | 60 | ||||
-rw-r--r-- | drivers/windows/dir_access_windows.h | 6 |
2 files changed, 63 insertions, 3 deletions
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index 43dd62cdf6..63ba6a6c96 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -396,6 +396,66 @@ bool DirAccessWindows::is_case_sensitive(const String &p_path) const { } } +bool DirAccessWindows::is_link(String p_file) { + String f = p_file; + + if (!f.is_absolute_path()) { + f = get_current_dir().path_join(f); + } + f = fix_path(f); + + DWORD attr = GetFileAttributesW((LPCWSTR)(f.utf16().get_data())); + if (attr == INVALID_FILE_ATTRIBUTES) { + return false; + } + + return (attr & FILE_ATTRIBUTE_REPARSE_POINT); +} + +String DirAccessWindows::read_link(String p_file) { + String f = p_file; + + if (!f.is_absolute_path()) { + f = get_current_dir().path_join(f); + } + f = fix_path(f); + + HANDLE hfile = CreateFileW((LPCWSTR)(f.utf16().get_data()), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (hfile == INVALID_HANDLE_VALUE) { + return f; + } + + DWORD ret = GetFinalPathNameByHandleW(hfile, nullptr, 0, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED); + if (ret == 0) { + return f; + } + Char16String cs; + cs.resize(ret + 1); + GetFinalPathNameByHandleW(hfile, (LPWSTR)cs.ptrw(), ret, VOLUME_NAME_DOS | FILE_NAME_NORMALIZED); + CloseHandle(hfile); + + return String::utf16((const char16_t *)cs.ptr(), ret).trim_prefix(R"(\\?\)"); +} + +Error DirAccessWindows::create_link(String p_source, String p_target) { + if (p_target.is_relative_path()) { + p_target = get_current_dir().path_join(p_target); + } + + p_source = fix_path(p_source); + p_target = fix_path(p_target); + + DWORD file_attr = GetFileAttributesW((LPCWSTR)(p_source.utf16().get_data())); + bool is_dir = (file_attr & FILE_ATTRIBUTE_DIRECTORY); + + DWORD flags = ((is_dir) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + if (CreateSymbolicLinkW((LPCWSTR)p_target.utf16().get_data(), (LPCWSTR)p_source.utf16().get_data(), flags) != 0) { + return OK; + } else { + return FAILED; + } +} + DirAccessWindows::DirAccessWindows() { p = memnew(DirAccessWindowsPrivate); p->h = INVALID_HANDLE_VALUE; diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 576ba18d9a..46755cbf33 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -77,9 +77,9 @@ public: virtual Error rename(String p_path, String p_new_path) override; virtual Error remove(String p_path) override; - virtual bool is_link(String p_file) override { return false; }; - virtual String read_link(String p_file) override { return p_file; }; - virtual Error create_link(String p_source, String p_target) override { return FAILED; }; + virtual bool is_link(String p_file) override; + virtual String read_link(String p_file) override; + virtual Error create_link(String p_source, String p_target) override; uint64_t get_space_left() override; |