Atomically overwrite config.yml

Protection against data corruption.
This commit is contained in:
Nekotekina 2020-06-08 05:28:08 +03:00 committed by Ivan
parent bd6fdf3f2d
commit e485c9c79c
2 changed files with 6 additions and 12 deletions

View File

@ -1202,8 +1202,8 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
games[m_title_id] = bdvd_dir; games[m_title_id] = bdvd_dir;
YAML::Emitter out; YAML::Emitter out;
out << games; out << games;
fs::file(fs::get_config_dir() + "/_tmp_games.yml", fs::rewrite).write(out.c_str(), out.size()); fs::file(fs::get_config_dir() + "/games.yml.tmp", fs::rewrite).write(out.c_str(), out.size());
fs::rename(fs::get_config_dir() + "/_tmp_games.yml", fs::get_config_dir() + "/games.yml", true); fs::rename(fs::get_config_dir() + "/games.yml.tmp", fs::get_config_dir() + "/games.yml", true);
} }
else if (m_cat == "1P" && from_hdd0_game) else if (m_cat == "1P" && from_hdd0_game)
{ {

View File

@ -104,7 +104,6 @@ void emu_settings::LoadSettings(const std::string& title_id)
void emu_settings::SaveSettings() void emu_settings::SaveSettings()
{ {
fs::file config;
YAML::Emitter out; YAML::Emitter out;
emitData(out, m_currentSettings); emitData(out, m_currentSettings);
@ -119,26 +118,21 @@ void emu_settings::SaveSettings()
config_name = Emulator::GetCustomConfigPath(m_title_id); config_name = Emulator::GetCustomConfigPath(m_title_id);
} }
config = fs::file(config_name, fs::read + fs::write + fs::create); // Save config atomically
fs::file(config_name + ".tmp", fs::rewrite).write(out.c_str(), out.size());
// Save config fs::rename(config_name + ".tmp", config_name, true);
config.seek(0);
config.trunc(0);
config.write(out.c_str(), out.size());
// Check if the running config/title is the same as the edited config/title. // Check if the running config/title is the same as the edited config/title.
if (config_name == g_cfg.name || m_title_id == Emu.GetTitleID()) if (config_name == g_cfg.name || m_title_id == Emu.GetTitleID())
{ {
// Update current config // Update current config
g_cfg.from_string(config.to_string(), !Emu.IsStopped()); g_cfg.from_string({out.c_str(), out.size()}, !Emu.IsStopped());
if (!Emu.IsStopped()) // Don't spam the log while emulation is stopped. The config will be logged on boot anyway. if (!Emu.IsStopped()) // Don't spam the log while emulation is stopped. The config will be logged on boot anyway.
{ {
cfg_log.notice("Updated configuration:\n%s\n", g_cfg.to_string()); cfg_log.notice("Updated configuration:\n%s\n", g_cfg.to_string());
} }
} }
config.close();
} }
void emu_settings::EnhanceComboBox(QComboBox* combobox, emu_settings_type type, bool is_ranged, bool use_max, int max, bool sorted) void emu_settings::EnhanceComboBox(QComboBox* combobox, emu_settings_type type, bool is_ranged, bool use_max, int max, bool sorted)