|
@@ -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;
|