Switch path_get_data_is_remote to returning a real class enum

End the tricky use of maybe_t<bool> by using a real class enum.
This commit is contained in:
ridiculousfish 2021-12-18 20:39:00 -08:00
parent 086d388932
commit 0d67dd19a1
5 changed files with 30 additions and 24 deletions

View File

@ -501,7 +501,7 @@ void env_universal_t::initialize_at_path(callback_data_list_t &callbacks, wcstri
void env_universal_t::initialize(callback_data_list_t &callbacks) {
// Set do_flock to false immediately if the default variable path is on a remote filesystem.
// See #7968.
if (path_get_config_is_remote() == maybe_t<bool>{true}) do_flock = false;
if (path_get_config_remoteness() == dir_remoteness_t::remote) do_flock = false;
this->initialize_at_path(callbacks, default_vars_path(), true /* migrate legacy */);
}

View File

@ -380,7 +380,7 @@ bool history_impl_t::maybe_lock_file(int fd, int lock_type) {
// is on a remote filesystem.
if (abandoned_locking) return false;
if (history_t::chaos_mode) return false;
if (path_get_data_is_remote() == maybe_t<bool>{true}) return false;
if (path_get_data_remoteness() == dir_remoteness_t::remote) return false;
double start_time = timef();
int retval = flock(fd, lock_type);

View File

@ -24,7 +24,7 @@ static bool should_mmap() {
if (history_t::never_mmap) return false;
// mmap only if we are known not-remote.
return path_get_data_is_remote() == maybe_t<bool>{false};
return path_get_config_remoteness() == dir_remoteness_t::local;
}
// Read up to len bytes from fd into address, zeroing the rest.

View File

@ -108,13 +108,13 @@ static bool path_is_executable(const std::string &path) {
return S_ISREG(buff.st_mode);
}
/// \return true if the path is remote, false if local, none() if unknown.
static maybe_t<bool> path_is_remote(const wcstring &path) {
/// \return whether the given path is on a remote filesystem.
static dir_remoteness_t path_remoteness(const wcstring &path) {
std::string narrow = wcs2string(path);
#if defined(__linux__)
struct statfs buf {};
if (statfs(narrow.c_str(), &buf) < 0) {
return none();
return dir_remoteness_t::unknown;
}
// Linux has constants for these like NFS_SUPER_MAGIC, SMB_SUPER_MAGIC, CIFS_MAGIC_NUMBER but
// these are in varying headers. Simply hard code them.
@ -124,23 +124,23 @@ static maybe_t<bool> path_is_remote(const wcstring &path) {
case 0x517B: // SMB_SUPER_MAGIC
case 0xFE534D42U: // SMB2_MAGIC_NUMBER - not in the manpage
case 0xFF534D42U: // CIFS_MAGIC_NUMBER
return true;
return dir_remoteness_t::remote;
default:
// Other FSes are assumed local.
return false;
return dir_remoteness_t::local;
}
#elif defined(ST_LOCAL)
// ST_LOCAL is a flag to statvfs, which is itself standardized.
// In practice the only system to use this path is NetBSD.
struct statvfs buf {};
if (statvfs(narrow.c_str(), &buf) < 0) return none();
if (statvfs(narrow.c_str(), &buf) < 0) return dir_remoteness_t::unknown;
return (buf.f_flag & ST_LOCAL) ? false : true;
#elif defined(MNT_LOCAL)
struct statfs buf {};
if (statfs(narrow.c_str(), &buf) < 0) return none();
return (buf.f_flags & MNT_LOCAL) ? false : true;
if (statfs(narrow.c_str(), &buf) < 0) return dir_remoteness_t::unknown;
return (buf.f_flags & MNT_LOCAL) ? dir_remoteness_t::local : dir_remoteness_t::remote;
#else
return none();
return dir_remoteness_t::unknown;
#endif
}
@ -337,9 +337,8 @@ namespace {
/// actually) to XDG spec.
struct base_directory_t {
wcstring path{}; /// the path where we attempted to create the directory.
maybe_t<bool> is_remote{
none()}; /// true if the directory is remote (e.g. NFS), false if local, none if unknown.
int err{0}; /// the error code if creating the directory failed, or 0 on success.
dir_remoteness_t remoteness{dir_remoteness_t::unknown}; // whether the dir is remote
int err{0}; /// the error code if creating the directory failed, or 0 on success.
bool success() const { return err == 0; }
bool used_xdg{false}; /// whether an XDG variable was used in resolving the directory.
};
@ -374,7 +373,7 @@ static base_directory_t make_base_directory(const wcstring &xdg_var,
} else {
result.err = 0;
// Need to append a trailing slash to check the contents of the directory, not its parent.
result.is_remote = path_is_remote(result.path + L'/');
result.remoteness = path_remoteness(result.path + L'/');
}
return result;
}
@ -395,7 +394,7 @@ void path_emit_config_directory_messages(env_stack_t &vars) {
maybe_issue_path_warning(L"data", _(L"can not save history"), data.used_xdg,
L"XDG_DATA_HOME", data.path, data.err, vars);
}
if (data.is_remote == maybe_t<bool>{true}) {
if (data.remoteness == dir_remoteness_t::remote) {
FLOG(path, "data path appears to be on a network volume");
}
@ -405,7 +404,7 @@ void path_emit_config_directory_messages(env_stack_t &vars) {
config.used_xdg, L"XDG_CONFIG_HOME", config.path, config.err,
vars);
}
if (config.is_remote == maybe_t<bool>{true}) {
if (config.remoteness == dir_remoteness_t::remote) {
FLOG(path, "config path appears to be on a network volume");
}
}
@ -422,9 +421,9 @@ bool path_get_data(wcstring &path) {
return dir.success();
}
maybe_t<bool> path_get_data_is_remote() { return get_data_directory().is_remote; }
dir_remoteness_t path_get_data_remoteness() { return get_data_directory().remoteness; }
maybe_t<bool> path_get_config_is_remote() { return get_config_directory().is_remote; }
dir_remoteness_t path_get_config_remoteness() { return get_config_directory().remoteness; }
void path_make_canonical(wcstring &path) {
// Ignore trailing slashes, unless it's the first character.

View File

@ -26,11 +26,18 @@ bool path_get_config(wcstring &path);
/// \return whether the directory was returned successfully
bool path_get_data(wcstring &path);
/// \return if the data directory is remote (eg. NFS).
maybe_t<bool> path_get_data_is_remote();
enum class dir_remoteness_t {
unknown, // directory status is unknown
local, // directory is known local
remote, // directory is known remote
};
/// Like path_get_data_is_remote but for config directory.
maybe_t<bool> path_get_config_is_remote();
/// \return the remoteness of the fish data directory.
/// This will be remote for filesystems like NFS, SMB, etc.
dir_remoteness_t path_get_data_remoteness();
/// Like path_get_data_remoteness but for the config directory.
dir_remoteness_t path_get_config_remoteness();
/// Emit any errors if config directories are missing.
/// Use the given environment stack to ensure this only occurs once.