From d609cf62a036572143e3ae65b6460d51b4fbae9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?=
<7645683+bruvzg@users.noreply.github.com>
Date: Wed, 14 May 2025 11:35:25 +0300
Subject: [PATCH] Implement `get_filesystem_type` on macOS and Linux.
---
core/io/dir_access.cpp | 2 +
doc/classes/DirAccess.xml | 7 ++
drivers/unix/dir_access_unix.cpp | 162 +++++++++++++++++++++++++
drivers/windows/dir_access_windows.cpp | 2 +-
editor/editor_file_system.cpp | 2 +-
platform/macos/dir_access_macos.h | 2 +
platform/macos/dir_access_macos.mm | 9 ++
7 files changed, 184 insertions(+), 2 deletions(-)
diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp
index 8e29af7d541..0b9a1e3a457 100644
--- a/core/io/dir_access.cpp
+++ b/core/io/dir_access.cpp
@@ -672,6 +672,8 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
ClassDB::bind_method(D_METHOD("get_include_hidden"), &DirAccess::get_include_hidden);
+ ClassDB::bind_method(D_METHOD("get_filesystem_type"), &DirAccess::get_filesystem_type);
+
ClassDB::bind_method(D_METHOD("is_case_sensitive", "path"), &DirAccess::is_case_sensitive);
ClassDB::bind_method(D_METHOD("is_equivalent", "path_a", "path_b"), &DirAccess::is_equivalent);
diff --git a/doc/classes/DirAccess.xml b/doc/classes/DirAccess.xml
index beb57aef2c3..1afc7960d88 100644
--- a/doc/classes/DirAccess.xml
+++ b/doc/classes/DirAccess.xml
@@ -213,6 +213,13 @@
[b]Note:[/b] When used on a [code]res://[/code] path in an exported project, only the files included in the PCK at the given folder level are returned. In practice, this means that since imported resources are stored in a top-level [code].godot/[/code] folder, only paths to [code].gd[/code] and [code].import[/code] files are returned (plus a few other files, such as [code]project.godot[/code] or [code]project.binary[/code] and the project icon). In an exported project, the list of returned files will also vary depending on [member ProjectSettings.editor/export/convert_text_resources_to_binary].
+
+
+
+ Returns file system type name of the current directory's disk. Returned values are uppercase strings like [code]NTFS[/code], [code]FAT32[/code], [code]EXFAT[/code], [code]APFS[/code], [code]EXT4[/code], [code]BTRFS[/code], and so on.
+ [b]Note:[/b] This method is implemented on macOS, Linux, Windows and for PCK virtual file system.
+
+
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index b8a7e062cc7..30ca040c644 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -40,6 +40,9 @@
#include
#include
#include
+#ifdef __linux__
+#include
+#endif
#include
#include
#include
@@ -516,7 +519,166 @@ uint64_t DirAccessUnix::get_space_left() {
}
String DirAccessUnix::get_filesystem_type() const {
+#ifdef __linux__
+ struct statfs fs;
+ if (statfs(current_dir.utf8().get_data(), &fs) != 0) {
+ return "";
+ }
+ switch (fs.f_type) {
+ case 0x0000adf5:
+ return "ADFS";
+ case 0x0000adff:
+ return "AFFS";
+ case 0x5346414f:
+ return "AFS";
+ case 0x00000187:
+ return "AUTOFS";
+ case 0x00c36400:
+ return "CEPH";
+ case 0x73757245:
+ return "CODA";
+ case 0x28cd3d45:
+ return "CRAMFS";
+ case 0x453dcd28:
+ return "CRAMFS";
+ case 0x64626720:
+ return "DEBUGFS";
+ case 0x73636673:
+ return "SECURITYFS";
+ case 0xf97cff8c:
+ return "SELINUX";
+ case 0x43415d53:
+ return "SMACK";
+ case 0x858458f6:
+ return "RAMFS";
+ case 0x01021994:
+ return "TMPFS";
+ case 0x958458f6:
+ return "HUGETLBFS";
+ case 0x73717368:
+ return "SQUASHFS";
+ case 0x0000f15f:
+ return "ECRYPTFS";
+ case 0x00414a53:
+ return "EFS";
+ case 0xe0f5e1e2:
+ return "EROFS";
+ case 0x0000ef53:
+ return "EXTFS";
+ case 0xabba1974:
+ return "XENFS";
+ case 0x9123683e:
+ return "BTRFS";
+ case 0x00003434:
+ return "NILFS";
+ case 0xf2f52010:
+ return "F2FS";
+ case 0xf995e849:
+ return "HPFS";
+ case 0x00009660:
+ return "ISOFS";
+ case 0x000072b6:
+ return "JFFS2";
+ case 0x58465342:
+ return "XFS";
+ case 0x6165676c:
+ return "PSTOREFS";
+ case 0xde5e81e4:
+ return "EFIVARFS";
+ case 0x00c0ffee:
+ return "HOSTFS";
+ case 0x794c7630:
+ return "OVERLAYFS";
+ case 0x65735546:
+ return "FUSE";
+ case 0xca451a4e:
+ return "BCACHEFS";
+ case 0x00004d44:
+ return "FAT32";
+ case 0x2011bab0:
+ return "EXFAT";
+ case 0x0000564c:
+ return "NCP";
+ case 0x00006969:
+ return "NFS";
+ case 0x7461636f:
+ return "OCFS2";
+ case 0x00009fa1:
+ return "OPENPROM";
+ case 0x0000002f:
+ return "QNX4";
+ case 0x68191122:
+ return "QNX6";
+ case 0x6b414653:
+ return "AFS";
+ case 0x52654973:
+ return "REISERFS";
+ case 0x0000517b:
+ return "SMB";
+ case 0xff534d42:
+ return "CIFS";
+ case 0x0027e0eb:
+ return "CGROUP";
+ case 0x63677270:
+ return "CGROUP2";
+ case 0x07655821:
+ return "RDTGROUP";
+ case 0x74726163:
+ return "TRACEFS";
+ case 0x01021997:
+ return "V9FS";
+ case 0x62646576:
+ return "BDEVFS";
+ case 0x64646178:
+ return "DAXFS";
+ case 0x42494e4d:
+ return "BINFMTFS";
+ case 0x00001cd1:
+ return "DEVPTS";
+ case 0x6c6f6f70:
+ return "BINDERFS";
+ case 0x0bad1dea:
+ return "FUTEXFS";
+ case 0x50495045:
+ return "PIPEFS";
+ case 0x00009fa0:
+ return "PROC";
+ case 0x534f434b:
+ return "SOCKFS";
+ case 0x62656572:
+ return "SYSFS";
+ case 0x00009fa2:
+ return "USBDEVICE";
+ case 0x11307854:
+ return "MTD_INODE";
+ case 0x09041934:
+ return "ANON_INODE";
+ case 0x73727279:
+ return "BTRFS";
+ case 0x6e736673:
+ return "NSFS";
+ case 0xcafe4a11:
+ return "BPF_FS";
+ case 0x5a3c69f0:
+ return "AAFS";
+ case 0x5a4f4653:
+ return "ZONEFS";
+ case 0x15013346:
+ return "UDF";
+ case 0x444d4142:
+ return "DMA_BUF";
+ case 0x454d444d:
+ return "DEVMEM";
+ case 0x5345434d:
+ return "SECRETMEM";
+ case 0x50494446:
+ return "PID_FS";
+ default:
+ return "";
+ }
+#else
return ""; //TODO this should be implemented
+#endif
}
bool DirAccessUnix::is_hidden(const String &p_name) {
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 8a93f902337..b1946594384 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -362,7 +362,7 @@ String DirAccessWindows::get_filesystem_type() const {
&dwFileSystemFlags,
szFileSystemName,
sizeof(szFileSystemName)) == TRUE) {
- return String::utf16((const char16_t *)szFileSystemName);
+ return String::utf16((const char16_t *)szFileSystemName).to_upper();
}
ERR_FAIL_V("");
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 5f48d34f6c5..0fe8ad67cf2 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -3660,7 +3660,7 @@ EditorFileSystem::EditorFileSystem() {
// This should probably also work on Unix and use the string it returns for FAT32 or exFAT
Ref da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
- using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "exFAT");
+ using_fat32_or_exfat = (da->get_filesystem_type() == "FAT32" || da->get_filesystem_type() == "EXFAT");
scan_total = 0;
ResourceSaver::set_get_resource_id_for_path(_resource_saver_get_resource_id_for_path);
diff --git a/platform/macos/dir_access_macos.h b/platform/macos/dir_access_macos.h
index de82f366ce2..d69aa0fd903 100644
--- a/platform/macos/dir_access_macos.h
+++ b/platform/macos/dir_access_macos.h
@@ -52,6 +52,8 @@ protected:
virtual bool is_hidden(const String &p_name) override;
virtual bool is_case_sensitive(const String &p_path) const override;
+ virtual String get_filesystem_type() const override;
+
virtual bool is_bundle(const String &p_file) const override;
};
diff --git a/platform/macos/dir_access_macos.mm b/platform/macos/dir_access_macos.mm
index 39d3f5c154e..b9aa4d9c66d 100644
--- a/platform/macos/dir_access_macos.mm
+++ b/platform/macos/dir_access_macos.mm
@@ -34,11 +34,20 @@
#include "core/config/project_settings.h"
+#include
#include
#import
#import
+String DirAccessMacOS::get_filesystem_type() const {
+ struct statfs fs;
+ if (statfs(current_dir.utf8().get_data(), &fs) != 0) {
+ return "";
+ }
+ return String::utf8(fs.f_fstypename).to_upper();
+}
+
String DirAccessMacOS::fix_unicode_name(const char *p_name) const {
String fname;
if (p_name != nullptr) {