From 6ac951c41a091ffc723840894ddf1e774739511d Mon Sep 17 00:00:00 2001
From: Christian Heller <c.heller@plomlompom.de>
Date: Thu, 10 Jul 2014 01:04:31 +0200
Subject: [PATCH] Alarm about / don't start on finding temp file filesaving
 leftovers.

---
 TODO                        |  6 +++--
 src/client/interface_conf.c |  5 +++--
 src/common/readwrite.c      | 44 ++++++++++++++++++++++++++++++++-----
 src/common/readwrite.h      |  3 +++
 src/server/init.c           |  5 ++++-
 5 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/TODO b/TODO
index 7557ab3..276d56f 100644
--- a/TODO
+++ b/TODO
@@ -4,13 +4,15 @@ IN GENERAL:
 
 - expand use of hardcoded_strings module(s)
 
+ROGUELIKE SKRIPT
+
+- do something about the invisibility of error messages
+
 BOTH SERVER/CLIENT:
 
 - make server and client communicate by specific world state info requests 
   in server/out, replacing server/worldstate
 
-- on start, alarm about _tmp files (savefile/record) to avoid gameplay data loss
-
 SERVER:
 
 - consider
diff --git a/src/client/interface_conf.c b/src/client/interface_conf.c
index 8fc234b..853fdaa 100644
--- a/src/client/interface_conf.c
+++ b/src/client/interface_conf.c
@@ -16,8 +16,8 @@
                                    * parsetest_too_many_values(),
                                    * parse_id_uniq(), parse_init_entry()
                                    */
-#include "../common/readwrite.h" /* atomic_write_start(), atomic_write_finish()
-                                  * try_fwrite()
+#include "../common/readwrite.h" /* atomic_write_start(), atomic_write_finish(),
+                                  * detect_atomic_leftover(), try_fwrite()
                                   */
 #include "../common/rexit.h" /* exit_err(), exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
@@ -440,6 +440,7 @@ extern void load_interface_conf()
     tmp_order    = try_malloc(1, f_name);
     tmp_order[0] = '\0';
     tmp_active   = '\0';
+    detect_atomic_leftover(world.path_interface);
     parse_file(world.path_interface, tokens_into_entries);
     char * err = "Not all expected windows defined in config file.";
     exit_err(strlen(world.winDB.legal_ids) != strlen(world.winDB.ids), err);
diff --git a/src/common/readwrite.c b/src/common/readwrite.c
index 912e70d..c9e22d7 100644
--- a/src/common/readwrite.c
+++ b/src/common/readwrite.c
@@ -14,6 +14,24 @@
 
 
 
+/* Return "path" + suffix "_tmp". Value is malloc'd, must be free externally. */
+static char * build_temp_path(char * path);
+
+
+
+static char * build_temp_path(char * path)
+{
+    char * f_name = "build_temp_path";
+    char * suffix_tmp = "_tmp";
+    uint16_t size = strlen(path) + strlen(suffix_tmp) + 1;
+    char * path_tmp = try_malloc(size, f_name);
+    int test = sprintf(path_tmp, "%s%s", path, suffix_tmp);
+    exit_trouble(test < 0, f_name, "sprintf()");
+    return path_tmp;
+}
+
+
+
 extern FILE * try_fopen(char * path, char * mode, char * f)
 {
     char * f_name = "try_fopen()";
@@ -78,11 +96,7 @@ extern char * try_fgets(char * line, int linemax, FILE * file, char * f)
 extern FILE * atomic_write_start(char * path, char ** path_tmp)
 {
     char * f_name = "atomic_write_start()";
-    char * suffix_tmp = "_tmp";
-    uint16_t size = strlen(path) + strlen(suffix_tmp) + 1;
-    *path_tmp = try_malloc(size, f_name);
-    int test = sprintf(*path_tmp, "%s%s", path, suffix_tmp);
-    exit_trouble(test < 0, f_name, "sprintf()");
+    *path_tmp = build_temp_path(path);
     return try_fopen(*path_tmp, "w", f_name);
 }
 
@@ -121,6 +135,26 @@ extern void atomic_write_finish(FILE * file, char * path, char * path_tmp)
 
 
 
+extern void detect_atomic_leftover(char * path)
+{
+    char * f_name = "detect_atomic_leftover()";
+    char * path_tmp = build_temp_path(path);
+    char * part1 = "Found file '";
+    char * part2 = "' that may be a leftover from an aborted previous attempt "
+                   "to write '";
+    char * part3 = "'. Aborting until the matter is solved by (re-)moving it.";
+    uint32_t size =   strlen(part1) + strlen(path_tmp) + strlen(part2)
+                    + strlen(path) + strlen(part3) + 1;
+    char * msg = try_malloc(size, f_name);
+    int test = sprintf(msg, "%s%s%s%s%s", part1, path_tmp, part2, path, part3);
+    exit_trouble(test < 0, f_name, "sprintf()");
+    exit_err(!access(path_tmp, F_OK), msg);
+    free(msg);
+    free(path_tmp);
+}
+
+
+
 extern uint32_t textfile_width(FILE * file)
 {
     char * f_name = "textfile_width()";
diff --git a/src/common/readwrite.h b/src/common/readwrite.h
index d03aeac..eddd0e6 100644
--- a/src/common/readwrite.h
+++ b/src/common/readwrite.h
@@ -40,6 +40,9 @@ extern FILE * atomic_write_start(char * path, char ** path_tmp);
  */
 extern void atomic_write_finish(FILE * file, char * path, char * path_tmp);
 
+/* Check for temp file leftover of atomic writing of "path", abort if found. */
+extern void detect_atomic_leftover(char * path);
+
 /* Return largest line length from "file" (including  newline chars). */
 extern uint32_t textfile_width(FILE * file);
 
diff --git a/src/server/init.c b/src/server/init.c
index ea13bc1..e9bb3d4 100644
--- a/src/server/init.c
+++ b/src/server/init.c
@@ -13,7 +13,8 @@
 #include <time.h> /* time() */
 #include <unistd.h> /* optarg, getopt(), access(), unlink(), getpid() */
 #include "../common/readwrite.h" /* try_fopen(), try_fclose(), textfile_width(),
-                                  * try_fgets(), try_fwrite()
+                                  * try_fgets(), try_fwrite(),
+                                  * detect_atomic_leftover()
                                   */
 #include "../common/rexit.h" /* exit_err(), exit_trouble() */
 #include "../common/try_malloc.h" /* try_malloc() */
@@ -162,6 +163,8 @@ extern void remake_world()
 extern void run_game()
 {
     char * f_name = "run_game()";
+    detect_atomic_leftover(s[S_PATH_SAVE]);
+    detect_atomic_leftover(s[S_PATH_RECORD]);
     if (world.replay)
     {
         replay_game();
-- 
2.30.2