diff --git a/src/init.cpp b/src/init.cpp index 19efc69aaa2ba9..5ade692a4ab0f2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -908,6 +908,23 @@ bool AppInitParameterInteraction(const ArgsManager& args) InitWarning(warnings); } + // Check if we are running on exFAT on MacOS +#ifdef __APPLE__ + std::vector paths_to_check = {args.GetDataDirNet(), args.GetBlocksDirPath()}; + for (const auto& path : paths_to_check) { + FSType fs_type = GetFilesystemType(path); + switch(fs_type) { + case FSType::EXFAT: + return InitError(strprintf(_("Specified directory \"%s\" is exFAT which is known to cause corruption on MacOS."), fs::PathToString(path))); + case FSType::ERROR: + LogPrintf("Warning: Failed to detect filesystem at %s\n", fs::PathToString(path)); + break; + default: + break; + } + } +#endif + if (!fs::is_directory(args.GetBlocksDirPath())) { return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), args.GetArg("-blocksdir", ""))); } diff --git a/src/util/fs_helpers.cpp b/src/util/fs_helpers.cpp index 4d06afe1442022..243f2dc5f64aba 100644 --- a/src/util/fs_helpers.cpp +++ b/src/util/fs_helpers.cpp @@ -41,6 +41,10 @@ #include /* For SHGetSpecialFolderPathW */ #endif // WIN32 +#ifdef __APPLE__ +#include +#endif + /** Mutex to protect dir_locks. */ static GlobalMutex cs_dir_locks; /** A map that contains all the currently held directory locks. After @@ -309,3 +313,17 @@ std::optional InterpretPermString(const std::string& s) return std::nullopt; } } + +#ifdef __APPLE__ +FSType GetFilesystemType(const fs::path& path) { + struct statfs fs_info; + if (statfs(path.c_str(), &fs_info) != 0) { + return FSType::ERROR; + } + + if (strcmp(fs_info.f_fstypename, "exfat") == 0) { + return FSType::EXFAT; + } + return FSType::OTHER; +} +#endif diff --git a/src/util/fs_helpers.h b/src/util/fs_helpers.h index 28dd6d979d5253..7423da82a42ec8 100644 --- a/src/util/fs_helpers.h +++ b/src/util/fs_helpers.h @@ -14,6 +14,23 @@ #include #include +#ifdef __APPLE__ +enum class FSType { + EXFAT, + OTHER, + ERROR +}; + +/** + * Detect filesystem type for a given path. + * Currently identifies exFAT filesystems which cause issues on MacOS. + * + * @param[in] path The directory path to check + * @return FSType enum indicating the filesystem type + */ +FSType GetFilesystemType(const fs::path& path); +#endif + /** * Ensure file contents are fully committed to disk, using a platform-specific * feature analogous to fsync().