unique temp files for makedefs invocations (GitHub issue #391)
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
This commit is contained in:
@@ -254,6 +254,12 @@ handle being interrupted by approaching monsters more consistently
|
|||||||
if hero attacked a peaceful monster, some other peaceful monsters with humanoid
|
if hero attacked a peaceful monster, some other peaceful monsters with humanoid
|
||||||
shape (minotaur, zruty, perhaps others) that witnessed it but which
|
shape (minotaur, zruty, perhaps others) that witnessed it but which
|
||||||
shouldn't be capable of normal speech expressed their surprise audibly
|
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
|
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||||
|
|||||||
+24
@@ -66,7 +66,14 @@ static char *FDECL(eos, (char *));
|
|||||||
#if 0
|
#if 0
|
||||||
static char *FDECL(mdlib_strsubst, (char *, const char *, const char *));
|
static char *FDECL(mdlib_strsubst, (char *, const char *, const char *));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
static int FDECL(mkstemp, (char *));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif /* MAKEDEFS_C || FOR_RUNTIME */
|
#endif /* MAKEDEFS_C || FOR_RUNTIME */
|
||||||
|
|
||||||
#if !defined(MAKEDEFS_C) && defined(WIN32)
|
#if !defined(MAKEDEFS_C) && defined(WIN32)
|
||||||
extern int GUILaunched;
|
extern int GUILaunched;
|
||||||
#endif
|
#endif
|
||||||
@@ -319,6 +326,23 @@ const char *build_date;
|
|||||||
return outbuf;
|
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 */
|
#endif /* MAKEDEFS_C || FOR_RUNTIME */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
+69
-18
@@ -124,6 +124,7 @@ static struct version_info version;
|
|||||||
/* Use this as an out-of-bound value in the close table. */
|
/* Use this as an out-of-bound value in the close table. */
|
||||||
#define CLOSE_OFF_TABLE_STRING "99" /* for the close table */
|
#define CLOSE_OFF_TABLE_STRING "99" /* for the close table */
|
||||||
#define FAR_OFF_TABLE_STRING "0xff" /* for the far 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))
|
#define sign(z) ((z) < 0 ? -1 : ((z) ? 1 : 0))
|
||||||
#ifdef VISION_TABLES
|
#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 char *FDECL(name_file, (const char *, const char *));
|
||||||
static void FDECL(delete_file, (const char *template, 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 void FDECL(do_ext_makedefs, (int, char **));
|
||||||
static char *FDECL(xcrypt, (const char *));
|
static char *FDECL(xcrypt, (const char *));
|
||||||
static unsigned long FDECL(read_rumors_file,
|
static unsigned long FDECL(read_rumors_file,
|
||||||
@@ -393,17 +394,40 @@ const char *tag;
|
|||||||
}
|
}
|
||||||
|
|
||||||
static FILE *
|
static FILE *
|
||||||
getfp(template, tag, mode)
|
getfp(template, tag, mode, flg)
|
||||||
const char *template;
|
const char *template;
|
||||||
const char *tag;
|
const char *tag;
|
||||||
const char *mode;
|
const char *mode;
|
||||||
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
int flg;
|
||||||
|
#else
|
||||||
|
int flg UNUSED;
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char *name = name_file(template, tag);
|
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) {
|
if (!rv) {
|
||||||
Fprintf(stderr, "Can't open '%s'.\n", name);
|
Fprintf(stderr, "Can't open '%s'.\n",
|
||||||
exit(EXIT_FAILURE);
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
istemp ? tmpfbuf :
|
||||||
|
#endif
|
||||||
|
name);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -426,7 +450,7 @@ static int FDECL(grep_check_id, (const char *));
|
|||||||
static void FDECL(grep_show_wstack, (const char *));
|
static void FDECL(grep_show_wstack, (const char *));
|
||||||
static char *FDECL(do_grep_control, (char *));
|
static char *FDECL(do_grep_control, (char *));
|
||||||
static void NDECL(do_grep);
|
static void NDECL(do_grep);
|
||||||
static void FDECL(grep0, (FILE *, FILE *));
|
static void FDECL(grep0, (FILE *, FILE *, int));
|
||||||
|
|
||||||
static int grep_trace = 0;
|
static int grep_trace = 0;
|
||||||
|
|
||||||
@@ -775,7 +799,7 @@ char *buf;
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void grep0(FILE *, FILE *);
|
static void grep0(FILE *, FILE *, int);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_grep()
|
do_grep()
|
||||||
@@ -790,14 +814,26 @@ do_grep()
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
grep0(inputfp, outputfp);
|
grep0(inputfp, outputfp, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grep0(inputfp0, outputfp0)
|
grep0(inputfp0, outputfp0, flg)
|
||||||
FILE *inputfp0;
|
FILE *inputfp0;
|
||||||
FILE *outputfp0;
|
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 */
|
char buf[16384]; /* looong, just in case */
|
||||||
|
|
||||||
while (!feof(inputfp0) && !ferror(inputfp0)) {
|
while (!feof(inputfp0) && !ferror(inputfp0)) {
|
||||||
@@ -837,7 +873,12 @@ FILE *outputfp0;
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
fclose(inputfp0);
|
fclose(inputfp0);
|
||||||
fclose(outputfp0);
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
if (istemp)
|
||||||
|
rewind(outputfp0);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
fclose(outputfp0);
|
||||||
if (grep_sp) {
|
if (grep_sp) {
|
||||||
Fprintf(stderr, "%d unterminated conditional level%s\n", grep_sp,
|
Fprintf(stderr, "%d unterminated conditional level%s\n", grep_sp,
|
||||||
grep_sp == 1 ? "" : "s");
|
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 */
|
more likely to be picked than normal but it's nothing to worry about */
|
||||||
(void) fputs(xcrypt(deflt_content), ofp);
|
(void) fputs(xcrypt(deflt_content), ofp);
|
||||||
|
|
||||||
tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
|
tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE, FLG_TEMPFILE);
|
||||||
grep0(ifp, tfp);
|
grep0(ifp, tfp, FLG_TEMPFILE);
|
||||||
ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
ifp = tfp;
|
||||||
|
#else
|
||||||
|
ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE, 0);
|
||||||
|
#endif
|
||||||
while ((line = fgetline(ifp)) != 0) {
|
while ((line = fgetline(ifp)) != 0) {
|
||||||
if (line[0] != '#' && line[0] != '\n')
|
if (line[0] != '#' && line[0] != '\n')
|
||||||
(void) fputs(xcrypt(line), ofp);
|
(void) fputs(xcrypt(line), ofp);
|
||||||
@@ -979,7 +1023,9 @@ const char *deflt_content;
|
|||||||
Fclose(ifp);
|
Fclose(ifp);
|
||||||
Fclose(ofp);
|
Fclose(ofp);
|
||||||
|
|
||||||
|
#ifdef HAS_NO_MKSTEMP
|
||||||
delete_file(DATA_TEMPLATE, "grep.tmp");
|
delete_file(DATA_TEMPLATE, "grep.tmp");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1747,10 +1793,13 @@ do_dungeon()
|
|||||||
}
|
}
|
||||||
Fprintf(ofp, "%s", Dont_Edit_Data);
|
Fprintf(ofp, "%s", Dont_Edit_Data);
|
||||||
|
|
||||||
tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE);
|
tfp = getfp(DATA_TEMPLATE, "grep.tmp", WRTMODE, FLG_TEMPFILE);
|
||||||
grep0(ifp, tfp);
|
grep0(ifp, tfp, FLG_TEMPFILE);
|
||||||
ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE);
|
#ifndef HAS_NO_MKSTEMP
|
||||||
|
ifp = tfp;
|
||||||
|
#else
|
||||||
|
ifp = getfp(DATA_TEMPLATE, "grep.tmp", RDTMODE, 0);
|
||||||
|
#endif
|
||||||
while ((line = fgetline(ifp)) != 0) {
|
while ((line = fgetline(ifp)) != 0) {
|
||||||
SpinCursor(3);
|
SpinCursor(3);
|
||||||
|
|
||||||
@@ -1764,7 +1813,9 @@ do_dungeon()
|
|||||||
Fclose(ifp);
|
Fclose(ifp);
|
||||||
Fclose(ofp);
|
Fclose(ofp);
|
||||||
|
|
||||||
|
#ifdef HAS_NO_MKSTEMP
|
||||||
delete_file(DATA_TEMPLATE, "grep.tmp");
|
delete_file(DATA_TEMPLATE, "grep.tmp");
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user