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:
nhmall
2020-09-22 09:03:15 -04:00
parent cf482f1f42
commit 1a0ee44760
3 changed files with 99 additions and 18 deletions

View 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;
}