Răsfoiți Sursa

Merge pull request #83266 from bruvzg/linux_case_check

[Linux] Implement DirAccess.is_case_sensitive for EXT4 and F2FS.
Rémi Verschelde 1 an în urmă
părinte
comite
348c1ff96b

+ 1 - 1
doc/classes/DirAccess.xml

@@ -209,7 +209,7 @@
 			<param index="0" name="path" type="String" />
 			<description>
 				Returns [code]true[/code] if the file system or directory use case sensitive file names.
-				[b]Note:[/b] This method is implemented on macOS 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>
 		</method>
 		<method name="list_dir_begin">

+ 23 - 0
drivers/unix/dir_access_unix.cpp

@@ -38,9 +38,11 @@
 #include "core/templates/list.h"
 
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/statvfs.h>
 
 #ifdef HAVE_MNTENT
@@ -488,6 +490,27 @@ bool DirAccessUnix::is_hidden(const String &p_name) {
 	return p_name != "." && p_name != ".." && p_name.begins_with(".");
 }
 
+bool DirAccessUnix::is_case_sensitive(const String &p_path) const {
+#if defined(LINUXBSD_ENABLED)
+	String f = p_path;
+	if (!f.is_absolute_path()) {
+		f = get_current_dir().path_join(f);
+	}
+	f = fix_path(f);
+
+	int fd = ::open(f.utf8().get_data(), O_RDONLY | O_NONBLOCK);
+	if (fd) {
+		long flags = 0;
+		if (ioctl(fd, _IOR('f', 1, long), &flags) >= 0) {
+			::close(fd);
+			return !(flags & 0x40000000 /* FS_CASEFOLD_FL */);
+		}
+		::close(fd);
+	}
+#endif
+	return true;
+}
+
 DirAccessUnix::DirAccessUnix() {
 	dir_stream = nullptr;
 	_cisdir = false;

+ 2 - 0
drivers/unix/dir_access_unix.h

@@ -82,6 +82,8 @@ public:
 	virtual String read_link(String p_file) override;
 	virtual Error create_link(String p_source, String p_target) override;
 
+	virtual bool is_case_sensitive(const String &p_path) const override;
+
 	virtual uint64_t get_space_left() override;
 
 	virtual String get_filesystem_type() const override;