diff --git a/src/g_gamedata.cpp b/src/g_gamedata.cpp index e4a2b6b7a..bd2939c75 100644 --- a/src/g_gamedata.cpp +++ b/src/g_gamedata.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -286,7 +287,8 @@ void srb2::save_ng_gamedata() std::string gamedataname_s {gamedatafilename}; fs::path savepath {fmt::format("{}/{}", srb2home, gamedataname_s)}; - fs::path tmpsavepath {fmt::format("{}/{}.tmp", srb2home, gamedataname_s)}; + int random_number = rand(); + fs::path tmpsavepath {fmt::format("{}/{}_{}.tmp", srb2home, gamedataname_s, random_number)}; json ngdata_json = ng; @@ -294,20 +296,17 @@ void srb2::save_ng_gamedata() { std::string tmpsavepathstring = tmpsavepath.string(); srb2::io::FileStream file {tmpsavepathstring, srb2::io::FileStreamMode::kWrite}; - srb2::io::BufferedOutputStream bos {std::move(file)}; // The header is necessary to validate during loading. - srb2::io::write(static_cast(GD_VERSION_MAJOR), bos); // major - srb2::io::write(static_cast(GD_VERSION_MINOR), bos); // minor/flags - srb2::io::write(static_cast(gamedata->evercrashed), bos); // dirty (crash recovery) + srb2::io::write(static_cast(GD_VERSION_MAJOR), file); // major + srb2::io::write(static_cast(GD_VERSION_MINOR), file); // minor/flags + srb2::io::write(static_cast(gamedata->evercrashed), file); // dirty (crash recovery) std::vector ubjson = json::to_ubjson(ng); - srb2::io::write_exact(bos, tcb::as_bytes(tcb::make_span(ubjson))); - bos.flush(); - file = bos.stream(); + srb2::io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); file.close(); } - catch (const srb2::io::FileStreamException& ex) + catch (const std::exception& ex) { CONS_Alert(CONS_ERROR, "NG Gamedata save failed: %s\n", ex.what()); } @@ -434,6 +433,13 @@ void srb2::load_ng_gamedata() json parsed = json::from_ubjson(remainder_as_u8); js = parsed.template get(); } + catch (const std::exception& ex) + { + const char* gdfolder = G_GameDataFolder(); + const char* what = ex.what(); + I_Error("Game data is corrupt.\nDelete %s (maybe in %s) and try again.\n\nException: %s", gamedatafilename, gdfolder, what); + return; + } catch (...) { const char* gdfolder = G_GameDataFolder(); diff --git a/src/k_profiles.cpp b/src/k_profiles.cpp index eb5371f98..89354bb1c 100644 --- a/src/k_profiles.cpp +++ b/src/k_profiles.cpp @@ -12,6 +12,7 @@ /// \brief implements methods for profiles etc. #include +#include #include @@ -315,26 +316,28 @@ void PR_SaveProfiles(void) std::vector ubjson = json::to_ubjson(ng); std::string realpath = fmt::format("{}/{}", srb2home, PROFILESFILE); - std::string tmppath = fmt::format("{}.tmp", realpath); + int random_number = rand(); + std::string tmppath = fmt::format("{}_{}.tmp", realpath, random_number); try { io::FileStream file {tmppath, io::FileStreamMode::kWrite}; - io::BufferedOutputStream bos {std::move(file)}; - io::write(static_cast(0x52494E47), bos, io::Endian::kBE); // "RING" - io::write(static_cast(0x5052464C), bos, io::Endian::kBE); // "PRFL" - io::write(static_cast(0), bos); // reserved1 - io::write(static_cast(0), bos); // reserved2 - io::write(static_cast(0), bos); // reserved3 - io::write(static_cast(0), bos); // reserved4 - io::write_exact(bos, tcb::as_bytes(tcb::make_span(ubjson))); - bos.flush(); - file = bos.stream(); + io::write(static_cast(0x52494E47), file, io::Endian::kBE); // "RING" + io::write(static_cast(0x5052464C), file, io::Endian::kBE); // "PRFL" + io::write(static_cast(0), file); // reserved1 + io::write(static_cast(0), file); // reserved2 + io::write(static_cast(0), file); // reserved3 + io::write(static_cast(0), file); // reserved4 + io::write_exact(file, tcb::as_bytes(tcb::make_span(ubjson))); file.close(); fs::rename(tmppath, realpath); } + catch (const std::exception& ex) + { + I_Error("Couldn't save profiles. Are you out of Disk space / playing in a protected folder?\n\nException: %s", ex.what()); + } catch (...) { I_Error("Couldn't save profiles. Are you out of Disk space / playing in a protected folder?"); @@ -398,9 +401,14 @@ void PR_LoadProfiles(void) json parsed = json::from_ubjson(remainder_as_u8); js = parsed.template get(); } + catch (const std::exception& ex) + { + I_Error("Profiles file is corrupt.\n\nException: %s", ex.what()); + return; + } catch (...) { - I_Error("Profiles file is corrupt"); + I_Error("Profiles file is corrupt."); return; }