Skip to content

Commit

Permalink
util: detect and warn when using exFAT on MacOS
Browse files Browse the repository at this point in the history
exFAT is known to cause corruption on MacOS. See bitcoin#28552.

Therefore we should warn when using this fs format for either the blocks
or data directories.
  • Loading branch information
willcl-ark committed Dec 10, 2024
1 parent 35000e3 commit a7d52d0
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/common/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <logging.h>
#include <tinyformat.h>
#include <util/fs.h>
#include <util/fs_helpers.h>
#include <util/translation.h>

#include <algorithm>
Expand Down Expand Up @@ -62,6 +63,32 @@ std::optional<ConfigError> InitConfig(ArgsManager& args, SettingsAbortFn setting
fs::create_directories(net_path / "wallets");
}

// Warn if we are trying to put the datadir on an exFAT fs on MacOS
// This is an upstream issue known to cause bugs, see #28552
#ifdef __APPLE__
struct PathCheck {
fs::path path;
std::string_view description;
};
std::array<PathCheck, 2> paths_to_check{{
{args.GetDataDirNet(), "data directory"},
{args.GetBlocksDirPath(), "blocks directory"}
}};
for (const auto& check : paths_to_check) {
FSType fs_type = GetFilesystemType(check.path);
switch(fs_type) {
case FSType::EXFAT:
LogWarning("Specified %s \"%s\" is exFAT which is known to have intermittent corruption problems on MacOS.", check.description, fs::PathToString(check.path));
break;
case FSType::ERROR:
LogInfo("Failed to detect filesystem type of %s: %s\n", check.description, fs::PathToString(check.path));
break;
default:
break;
}
}
#endif

// Show an error or warn/log if there is a bitcoin.conf file in the
// datadir that is being ignored.
const fs::path base_config_path = base_path / BITCOIN_CONF_FILENAME;
Expand Down
18 changes: 18 additions & 0 deletions src/util/fs_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
#include <shlobj.h> /* For SHGetSpecialFolderPathW */
#endif // WIN32

#ifdef __APPLE__
#include <sys/mount.h>
#endif

/** Mutex to protect dir_locks. */
static GlobalMutex cs_dir_locks;
/** A map that contains all the currently held directory locks. After
Expand Down Expand Up @@ -309,3 +313,17 @@ std::optional<fs::perms> 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
17 changes: 17 additions & 0 deletions src/util/fs_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@
#include <limits>
#include <optional>

#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().
Expand Down

0 comments on commit a7d52d0

Please sign in to comment.