mirror of
https://github.com/mirror/make.git
synced 2026-09-02 12:48:09 +08:00
[SV 63333] Be more lenient when failing to create temporary files
If make cannot create a temporary lock file for output sync, continue without output sync enabled rather than dying. However, if make cannot store a makefile from stdin to a temporary file that is still a fatal error. * misc.c (get_tmppath): Keep running on failure to generate a temporary file name. (get_tmpfd): Keep running on failure to get a temporary file. (get_tmpfile): Keep running on failure to open a temporary file. Ensure memory is freed if we return an error. * posixos.c (os_anontmp): Keep running on failure to open an anonymous temporary file. * output.c (setup_tmpfile): Print an error on failure to create an output sync lock file. * main.c (main): Die on failure to store makefile from stdin to a temporary file. * tests/scripts/features/output-sync: Add tests. * tests/scripts/features/temp_stdin: Ditto.
This commit is contained in:
committed by
Paul Smith
parent
4c9d87f4ae
commit
1b51ba1f5d
@@ -1928,6 +1928,9 @@ main (int argc, char **argv, char **envp)
|
||||
_("Makefile from standard input specified twice"));
|
||||
|
||||
outfile = get_tmpfile (&newnm);
|
||||
if (!outfile)
|
||||
O (fatal, NILF,
|
||||
_("cannot store makefile from stdin to a temporary file"));
|
||||
|
||||
while (!feof (stdin) && ! ferror (stdin))
|
||||
{
|
||||
|
||||
64
src/misc.c
64
src/misc.c
@@ -20,8 +20,7 @@ this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include "os.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* GNU make no longer supports pre-ANSI89 environments. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef WINDOWS32
|
||||
@@ -650,11 +649,19 @@ get_tmppath ()
|
||||
# ifdef HAVE_MKTEMP
|
||||
path = get_tmptemplate ();
|
||||
if (*mktemp (path) == '\0')
|
||||
pfatal_with_name ("mktemp");
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot generate temp path from %s: %s"), path, strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
# else
|
||||
path = xmalloc (L_tmpnam + 1);
|
||||
if (tmpnam (path) == NULL)
|
||||
pfatal_with_name ("tmpnam");
|
||||
{
|
||||
OS (error, NILF,
|
||||
_("cannot generate temp name: %s"), strerror (errno));
|
||||
return NULL;
|
||||
}
|
||||
# endif
|
||||
|
||||
return path;
|
||||
@@ -662,7 +669,9 @@ get_tmppath ()
|
||||
#endif
|
||||
|
||||
/* Generate a temporary file and return an fd for it. If name is NULL then
|
||||
the temp file is anonymous and will be deleted when the process exits. */
|
||||
the temp file is anonymous and will be deleted when the process exits. If
|
||||
name is not null then *name will point to an allocated buffer, or set to
|
||||
NULL on failure. */
|
||||
int
|
||||
get_tmpfd (char **name)
|
||||
{
|
||||
@@ -670,9 +679,11 @@ get_tmpfd (char **name)
|
||||
char *tmpnm;
|
||||
mode_t mask;
|
||||
|
||||
/* If there's an os-specific way to get an anoymous temp file use it. */
|
||||
if (!name)
|
||||
if (name)
|
||||
*name = NULL;
|
||||
else
|
||||
{
|
||||
/* If there's an os-specific way to get an anoymous temp file use it. */
|
||||
fd = os_anontmp ();
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
@@ -689,13 +700,19 @@ get_tmpfd (char **name)
|
||||
EINTRLOOP (fd, mkstemp (tmpnm));
|
||||
#else
|
||||
tmpnm = get_tmppath ();
|
||||
if (!tmpnm)
|
||||
return -1;
|
||||
|
||||
/* Can't use mkstemp(), but try to guard against a race condition. */
|
||||
EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
|
||||
#endif
|
||||
if (fd < 0)
|
||||
OSS (fatal, NILF,
|
||||
_("create temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("cannot create temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
free (tmpnm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (name)
|
||||
*name = tmpnm;
|
||||
@@ -704,8 +721,8 @@ get_tmpfd (char **name)
|
||||
int r;
|
||||
EINTRLOOP (r, unlink (tmpnm));
|
||||
if (r < 0)
|
||||
OSS (fatal, NILF,
|
||||
_("unlink temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
OSS (error, NILF,
|
||||
_("cannot unlink temporary file %s: %s"), tmpnm, strerror (errno));
|
||||
free (tmpnm);
|
||||
}
|
||||
|
||||
@@ -715,8 +732,8 @@ get_tmpfd (char **name)
|
||||
}
|
||||
|
||||
/* Return a FILE* for a temporary file, opened in the safest way possible.
|
||||
Set name to point to an allocated buffer containing the name of the file.
|
||||
Note, this cannot be NULL! */
|
||||
Set name to point to an allocated buffer containing the name of the file,
|
||||
or NULL on failure. Note, name cannot be NULL! */
|
||||
FILE *
|
||||
get_tmpfile (char **name)
|
||||
{
|
||||
@@ -725,26 +742,37 @@ get_tmpfile (char **name)
|
||||
FILE *file;
|
||||
|
||||
#if defined(HAVE_FDOPEN)
|
||||
int fd = get_tmpfd (name);
|
||||
int fd;
|
||||
assert (name);
|
||||
fd = get_tmpfd (name);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
assert (*name);
|
||||
|
||||
ENULLLOOP (file, fdopen (fd, tmpfile_mode));
|
||||
if (file == NULL)
|
||||
OSS (fatal, NILF,
|
||||
OSS (error, NILF,
|
||||
_("fdopen: temporary file %s: %s"), *name, strerror (errno));
|
||||
#else
|
||||
/* Preserve the current umask, and set a restrictive one for temp files. */
|
||||
mode_t mask = umask (0077);
|
||||
int err;
|
||||
|
||||
assert (name);
|
||||
*name = get_tmppath ();
|
||||
if (!*name)
|
||||
return NULL;
|
||||
|
||||
/* Although this fopen is insecure, it is executed only on non-fdopen
|
||||
platforms, which should be a rarity nowadays. */
|
||||
|
||||
ENULLLOOP (file, fopen (*name, tmpfile_mode));
|
||||
if (file == NULL)
|
||||
OSS (fatal, NILF,
|
||||
_("fopen: temporary file %s: %s"), *name, strerror (errno));
|
||||
{
|
||||
OSS (error, NILF,
|
||||
_("fopen: temporary file %s: %s"), *name, strerror (errno));
|
||||
free (*name);
|
||||
*name = NULL;
|
||||
}
|
||||
|
||||
umask (mask);
|
||||
#endif
|
||||
|
||||
@@ -248,6 +248,9 @@ setup_tmpfile (struct output *out)
|
||||
|
||||
/* If we failed to create a temp file, disable output sync going forward. */
|
||||
error:
|
||||
O (error, NILF,
|
||||
_("cannot open output-sync lock file, suppressing output-sync."));
|
||||
|
||||
output_close (out);
|
||||
output_sync = OUTPUT_SYNC_NONE;
|
||||
osync_clear ();
|
||||
|
||||
@@ -872,12 +872,15 @@ os_anontmp ()
|
||||
FILE *tfile;
|
||||
ENULLLOOP (tfile, tmpfile ());
|
||||
if (!tfile)
|
||||
pfatal_with_name ("tmpfile");
|
||||
{
|
||||
OS (error, NILF, "tmpfile: %s", strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
umask (mask);
|
||||
|
||||
EINTRLOOP (fd, dup (fileno (tfile)));
|
||||
if (fd < 0)
|
||||
pfatal_with_name ("dup");
|
||||
OS (error, NILF, "dup: %s", strerror (errno));
|
||||
fclose (tfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -363,8 +363,24 @@ pid:=$(shell echo $$PPID)
|
||||
all:; @#HELPER# term $(pid) sleep 10
|
||||
!, '-O -j2', '/#MAKE#: \*\*\* \[#MAKEFILE#:3: all] Terminated/', POSIX::SIGTERM);
|
||||
}
|
||||
|
||||
unlink($fout);
|
||||
|
||||
# SV 63333. Test that make continues to run without output sync when we
|
||||
# cannot create a temporary file.
|
||||
# Create a non-writable temporary directory.
|
||||
# Run the test twice, because run_make_test cannot match a regex againt a
|
||||
# multiline input.
|
||||
my $tdir = 'test_tmp_dir';
|
||||
mkdir($tdir, 0500);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
|
||||
run_make_test(q!
|
||||
all:; $(info hello, world)
|
||||
!, '-Orecurse', "/suppressing output-sync/");
|
||||
|
||||
run_make_test(undef, '-Orecurse', "/#MAKE#: 'all' is up to date./");
|
||||
|
||||
rmdir($tdir);
|
||||
}
|
||||
|
||||
# This tells the test driver that the perl test script executed properly.
|
||||
|
||||
@@ -109,6 +109,21 @@ force:
|
||||
@make_command = @make_orig;
|
||||
unlink($makecopy);
|
||||
rmdir($tmakedir);
|
||||
|
||||
# SV 63333. Test that make exits with an error message if we cannot store a
|
||||
# makefile from stdin to a temporary file.
|
||||
# Create a non-writable temporary directory.
|
||||
|
||||
my $tdir = 'test_tmp_dir';
|
||||
mkdir($tdir, 0500);
|
||||
$ENV{'TMPDIR'} = $tdir;
|
||||
close(STDIN);
|
||||
open(STDIN, "<", 'input.mk') || die "$0: cannot open input.mk for reading: $!";
|
||||
|
||||
run_make_test(q!
|
||||
all:; $(info hello, world)
|
||||
!, '-f-', '/cannot store makefile from stdin to a temporary file. Stop./', 512);
|
||||
rmdir($tdir);
|
||||
}
|
||||
|
||||
close(STDIN);
|
||||
|
||||
Reference in New Issue
Block a user