mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 19:42:43 +00:00
Add symlink API support for Windows, expose symlink methods.
This commit is contained in:
parent
6118592c6d
commit
fc948e87f6
@ -582,6 +582,10 @@ void DirAccess::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("remove", "path"), &DirAccess::remove);
|
ClassDB::bind_method(D_METHOD("remove", "path"), &DirAccess::remove);
|
||||||
ClassDB::bind_static_method("DirAccess", D_METHOD("remove_absolute", "path"), &DirAccess::remove_absolute);
|
ClassDB::bind_static_method("DirAccess", D_METHOD("remove_absolute", "path"), &DirAccess::remove_absolute);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("is_link", "path"), &DirAccess::is_link);
|
||||||
|
ClassDB::bind_method(D_METHOD("read_link", "path"), &DirAccess::read_link);
|
||||||
|
ClassDB::bind_method(D_METHOD("create_link", "source", "target"), &DirAccess::create_link);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
|
ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
|
||||||
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
|
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
|
||||||
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
|
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
|
||||||
|
@ -94,6 +94,16 @@
|
|||||||
Static version of [method copy]. Supports only absolute paths.
|
Static version of [method copy]. Supports only absolute paths.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="create_link">
|
||||||
|
<return type="int" enum="Error" />
|
||||||
|
<param index="0" name="source" type="String" />
|
||||||
|
<param index="1" name="target" type="String" />
|
||||||
|
<description>
|
||||||
|
Creates symbolic link between files or folders.
|
||||||
|
[b]Note:[/b] On Windows, this method works only if the application is running with elevated privileges or Developer Mode is enabled.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS, Linux, and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="current_is_dir" qualifiers="const">
|
<method name="current_is_dir" qualifiers="const">
|
||||||
<return type="bool" />
|
<return type="bool" />
|
||||||
<description>
|
<description>
|
||||||
@ -212,6 +222,14 @@
|
|||||||
[b]Note:[/b] This method is implemented on macOS, Linux (for EXT4 and F2FS filesystems only) and Windows. On other platforms, it always returns [code]true[/code].
|
[b]Note:[/b] This method is implemented on macOS, Linux (for EXT4 and F2FS filesystems only) and Windows. On other platforms, it always returns [code]true[/code].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="is_link">
|
||||||
|
<return type="bool" />
|
||||||
|
<param index="0" name="path" type="String" />
|
||||||
|
<description>
|
||||||
|
Returns [code]true[/code] if the file or directory is a symbolic link, directory junction, or other reparse point.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS, Linux, and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="list_dir_begin">
|
<method name="list_dir_begin">
|
||||||
<return type="int" enum="Error" />
|
<return type="int" enum="Error" />
|
||||||
<description>
|
<description>
|
||||||
@ -264,6 +282,14 @@
|
|||||||
Returns [code]null[/code] if opening the directory failed. You can use [method get_open_error] to check the error that occurred.
|
Returns [code]null[/code] if opening the directory failed. You can use [method get_open_error] to check the error that occurred.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="read_link">
|
||||||
|
<return type="String" />
|
||||||
|
<param index="0" name="path" type="String" />
|
||||||
|
<description>
|
||||||
|
Returns target of the symbolic link.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS, Linux, and Windows.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="remove">
|
<method name="remove">
|
||||||
<return type="int" enum="Error" />
|
<return type="int" enum="Error" />
|
||||||
<param index="0" name="path" type="String" />
|
<param index="0" name="path" type="String" />
|
||||||
|
@ -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() {
|
DirAccessWindows::DirAccessWindows() {
|
||||||
p = memnew(DirAccessWindowsPrivate);
|
p = memnew(DirAccessWindowsPrivate);
|
||||||
p->h = INVALID_HANDLE_VALUE;
|
p->h = INVALID_HANDLE_VALUE;
|
||||||
|
@ -77,9 +77,9 @@ public:
|
|||||||
virtual Error rename(String p_path, String p_new_path) override;
|
virtual Error rename(String p_path, String p_new_path) override;
|
||||||
virtual Error remove(String p_path) override;
|
virtual Error remove(String p_path) override;
|
||||||
|
|
||||||
virtual bool is_link(String p_file) override { return false; };
|
virtual bool is_link(String p_file) override;
|
||||||
virtual String read_link(String p_file) override { return p_file; };
|
virtual String read_link(String p_file) override;
|
||||||
virtual Error create_link(String p_source, String p_target) override { return FAILED; };
|
virtual Error create_link(String p_source, String p_target) override;
|
||||||
|
|
||||||
uint64_t get_space_left() override;
|
uint64_t get_space_left() override;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user