From 974228a52920aeb89b3f1f19184aa9ffcc037ef5 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 19 Apr 2008 13:43:17 +0000 Subject: Don't successfully save a savegame if a buffer overrun occurs, and don't overwrite the existing savegame. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 1119 --- src/g_game.c | 30 +++++++++++++++++++++--------- src/p_saveg.c | 27 ++++++++++++++++++++++++++- src/p_saveg.h | 4 ++++ 3 files changed, 51 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/g_game.c b/src/g_game.c index c9e3879f..4f7a3d43 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1485,21 +1485,25 @@ G_SaveGame void G_DoSaveGame (void) { - char name[100]; - char* description; - - strcpy(name, P_SaveGameFile(savegameslot)); + char *savegame_file; + char *temp_savegame_file; - description = savedescription; - - save_stream = fopen(name, "wb"); + temp_savegame_file = P_TempSaveGameFile(); + savegame_file = P_SaveGameFile(savegameslot); + + // Open the savegame file for writing. We write to a temporary file + // and then rename it at the end if it was successfully written. + // This prevents an existing savegame from being overwritten by + // a corrupted one, or if a savegame buffer overrun occurs. + + save_stream = fopen(temp_savegame_file, "wb"); if (save_stream == NULL) { return; } - P_WriteSaveGameHeader(description); + P_WriteSaveGameHeader(savedescription); P_ArchivePlayers (); P_ArchiveWorld (); @@ -1516,11 +1520,19 @@ void G_DoSaveGame (void) I_Error ("Savegame buffer overrun"); } + // Finish up, close the savegame file. + fclose(save_stream); + // Now rename the temporary savegame file to the actual savegame + // file, overwriting the old savegame if there was one there. + + remove(savegame_file); + rename(temp_savegame_file, savegame_file); + gameaction = ga_nothing; strcpy(savedescription, ""); - + players[consoleplayer].message = DEH_String(GGSAVED); // draw the pattern into the back screen diff --git a/src/p_saveg.c b/src/p_saveg.c index afd3852d..40b5f988 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -44,11 +44,36 @@ FILE *save_stream; int savegamelength; +// Get the filename of a temporary file to write the savegame to. After +// the file has been successfully saved, it will be renamed to the +// real file. + +char *P_TempSaveGameFile(void) +{ + static char *filename = NULL; + + if (filename == NULL) + { + filename = malloc(strlen(savegamedir) + 32); + } + + sprintf(filename, "%stemp.dsg", savegamedir); + + return filename; +} + +// Get the filename of the save game file to use for the specified slot. + char *P_SaveGameFile(int slot) { - static char filename[256]; + static char *filename = NULL; char basename[32]; + if (filename == NULL) + { + filename = malloc(strlen(savegamedir) + 32); + } + sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot); sprintf(filename, "%s%s", savegamedir, basename); diff --git a/src/p_saveg.h b/src/p_saveg.h index 6f95585e..3a96cc3e 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -34,6 +34,10 @@ #define SAVESTRINGSIZE 24 +// temporary filename to use while saving. + +char *P_TempSaveGameFile(void); + // filename to use for a savegame slot char *P_SaveGameFile(int slot); -- cgit v1.2.3