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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user