]> granicus.if.org Git - nethack/commitdiff
unique temp files for makedefs invocations (GitHub issue #391)
authornhmall <nhmall@nethack.org>
Tue, 22 Sep 2020 13:03:15 +0000 (09:03 -0400)
committernhmall <nhmall@nethack.org>
Tue, 22 Sep 2020 13:03:15 +0000 (09:03 -0400)
As reported in https://github.com/NetHack/NetHack/issues/391
if make was invoked with -j, makedefs instances could end up running in
parallel and could trample on each other's grep.tmp tempory files.

Default to using mkstemp(); allow a port runtime library implementation
that lacks mkstemp() to define HAS_NO_MKSTEMP to revert to the old behaviour.

Provide a work-alike mkstemp() implementation for windows Visual Studio build
in mdlib.c so there is no requirement to define HAS_NO_MKSTEMP there.

Fixes #391

doc/fixes37.0
src/mdlib.c
util/makedefs.c

index 5329e9833022716ab922e141a82d83b678413d34..96d26a53dfb2859b0d4a5e56c47155aadc9942e3 100644 (file)
@@ -254,6 +254,12 @@ handle being interrupted by approaching monsters more consistently
 if hero attacked a peaceful monster, some other peaceful monsters with humanoid
        shape (minotaur, zruty, perhaps others) that witnessed it but which
        shouldn't be capable of normal speech expressed their surprise audibly
+when make was invoked with -j makedefs instances could end up running in
+       parallel and could trample on each other's temp files; default to
+       using mkstemp(); allow a port runtime library implementation that lacks
+       mkstemp() to define HAS_NO_MKSTEMP to revert to the old behaviour;
+       provide a work-alike mkstemp() implementation for windows visual studio
+       in mdlib.c so there is no requirement to define HAS_NO_MKSTEMP there
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 59b94b459a40c40c8deb4897ec80b71be47fdd05..79a748710bbf787db73e15988f8f708a4d268fa5 100644 (file)
@@ -66,7 +66,14 @@ static char *FDECL(eos, (char *));
 #if 0
 static char *FDECL(mdlib_strsubst, (char *, const char *, const char *));
 #endif
+
+#ifndef HAS_NO_MKSTEMP
+#ifdef _MSC_VER
+static int FDECL(mkstemp, (char *));
+#endif
+#endif
 #endif /* MAKEDEFS_C || FOR_RUNTIME */
+
 #if !defined(MAKEDEFS_C) && defined(WIN32)
 extern int GUILaunched;
 #endif
@@ -319,6 +326,23 @@ const char *build_date;
     return outbuf;
 }
 
+#ifndef HAS_NO_MKSTEMP
+#ifdef _MSC_VER
+int
+mkstemp(template)
+char *template;
+{
+    int err;
+
+    err = _mktemp_s(template, strlen(template) + 1);
+    if( err != 0 )
+        return -1;
+    return _open(template,
+                 _O_RDWR | _O_BINARY | _O_TEMPORARY | _O_CREAT,
+                 _S_IREAD | _S_IWRITE);
+}
+#endif /* _MSC_VER */
+#endif /* HAS_NO_MKSTEMP */
 #endif /* MAKEDEFS_C || FOR_RUNTIME */
 
 static int
index 8b5179c1ba56b82a04bbf0811afda0a0b791a6be..0cf4b09e31d73031af276d13b7ec027d72b25e6b 100644 (file)
@@ -124,6 +124,7 @@ static struct version_info version;
 /* Use this as an out-of-bound value in the close table.  */
 #define CLOSE_OFF_TABLE_STRING "99" /* for the close table */
 #define FAR_OFF_TABLE_STRING "0xff" /* for the far table */
+#define FLG_TEMPFILE  0x01              /* flag for temp file */
 
 #define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
 #ifdef VISION_TABLES
@@ -165,7 +166,7 @@ extern void NDECL(objects_globals_init); /* objects.c */
 
 static char *FDECL(name_file, (const char *, const char *));
 static void FDECL(delete_file, (const char *template, const char *));
-static FILE *FDECL(getfp, (const char *, const char *, const char *));
+static FILE *FDECL(getfp, (const char *, const char *, const char *, int));
 static void FDECL(do_ext_makedefs, (int, char **));
 static char *FDECL(xcrypt, (const char *));
 static unsigned long FDECL(read_rumors_file,
@@ -393,17 +394,40 @@ const char *tag;
 }
 
 static FILE *
-getfp(template, tag, mode)
+getfp(template, tag, mode, flg)
 const char *template;
 const char *tag;
 const char *mode;
+#ifndef HAS_NO_MKSTEMP
+int flg;
+#else
+int flg UNUSED;
+#endif
 {
     char *name = name_file(template, tag);
-    FILE *rv = fopen(name, mode);
+    FILE *rv = (FILE *) 0;
+#ifndef HAS_NO_MKSTEMP
+    boolean istemp = (flg & FLG_TEMPFILE) != 0;
+    char tmpfbuf[MAXFNAMELEN];
+    int tmpfd;
+#endif
 
+#ifndef HAS_NO_MKSTEMP
+    if (istemp) {
+        (void) snprintf(tmpfbuf, sizeof tmpfbuf, DATA_TEMPLATE, "mdXXXXXX");
+        tmpfd = mkstemp(tmpfbuf);
+        if (tmpfd >= 0)
+            rv = fdopen(tmpfd, WRTMODE);   /* temp file is always read+write */
+    } else
+#endif
+    rv = fopen(name, mode);
     if (!rv) {
-        Fprintf(stderr, "Can't open '%s'.\n", name);
-        exit(EXIT_FAILURE);
+        Fprintf(stderr, "Can't open '%s'.\n",
+#ifndef HAS_NO_MKSTEMP
+                istemp ? tmpfbuf :
+#endif
+                 name);
+            exit(EXIT_FAILURE);
     }
     return rv;
 }
@@ -426,7 +450,7 @@ static int FDECL(grep_check_id, (const char *));
 static void FDECL(grep_show_wstack, (const char *));
 static char *FDECL(do_grep_control, (char *));
 static void NDECL(do_grep);
-static void FDECL(grep0, (FILE *, FILE *));
+static void FDECL(grep0, (FILE *, FILE *, int));
 
 static int grep_trace = 0;
 
@@ -775,7 +799,7 @@ char *buf;
 }
 #endif
 
-static void grep0(FILE *, FILE *);
+static void grep0(FILE *, FILE *, int);
 
 static void
 do_grep()
@@ -790,14 +814,26 @@ do_grep()
         exit(EXIT_FAILURE);
     }
 
-    grep0(inputfp, outputfp);
+    grep0(inputfp, outputfp, 0);
 }
 
 static void
-grep0(inputfp0, outputfp0)
+grep0(inputfp0, outputfp0, flg)
 FILE *inputfp0;
 FILE *outputfp0;
+#ifndef HAS_NO_MKSTEMP
+int flg;
+#else
+int flg UNUSED;
+#endif
 {
+#ifndef HAS_NO_MKSTEMP
+    /* if grep0 is passed FLG_TEMPFILE flag, it will
+       leave the output file open when it returns.
+       The caller will have to take care of calling
+       fclose() when it is done with the file */
+    boolean istemp = (flg & FLG_TEMPFILE) != 0;
+#endif
     char buf[16384]; /* looong, just in case */
 
     while (!feof(inputfp0) && !ferror(inputfp0)) {
@@ -837,7 +873,12 @@ FILE *outputfp0;
         exit(EXIT_FAILURE);
     }
     fclose(inputfp0);
-    fclose(outputfp0);
+#ifndef HAS_NO_MKSTEMP
+    if (istemp)
+        rewind(outputfp0);
+    else
+#endif
+        fclose(outputfp0);
     if (grep_sp) {
         Fprintf(stderr, "%d unterminated conditional level%s\n", grep_sp,
                 grep_sp == 1 ? "" : "s");
@@ -967,10 +1008,13 @@ const char *deflt_content;
        more likely to be picked than normal but it's nothing to worry about */
     (void) fputs(xcrypt(deflt_content), ofp);
 
-    tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
-    grep0(ifp, tfp);
-    ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
-
+    tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE, FLG_TEMPFILE);
+    grep0(ifp, tfp, FLG_TEMPFILE);
+#ifndef HAS_NO_MKSTEMP
+    ifp = tfp;
+#else
+    ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE, 0);
+#endif
     while ((line = fgetline(ifp)) != 0) {
         if (line[0] != '#' && line[0] != '\n')
             (void) fputs(xcrypt(line), ofp);
@@ -979,7 +1023,9 @@ const char *deflt_content;
     Fclose(ifp);
     Fclose(ofp);
 
+#ifdef HAS_NO_MKSTEMP
     delete_file(DATA_TEMPLATE, "grep.tmp");
+#endif
     return;
 }
 
@@ -1747,10 +1793,13 @@ do_dungeon()
     }
     Fprintf(ofp, "%s", Dont_Edit_Data);
 
-    tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
-    grep0(ifp, tfp);
-    ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
-
+    tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE, FLG_TEMPFILE);
+    grep0(ifp, tfp, FLG_TEMPFILE);
+#ifndef HAS_NO_MKSTEMP
+    ifp = tfp;
+#else
+    ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE, 0);
+#endif
     while ((line = fgetline(ifp)) != 0) {
         SpinCursor(3);
 
@@ -1764,7 +1813,9 @@ do_dungeon()
     Fclose(ifp);
     Fclose(ofp);
 
+#ifdef HAS_NO_MKSTEMP
     delete_file(DATA_TEMPLATE, "grep.tmp");
+#endif
     return;
 }