diff options
author | Dmitry Goncharov <dgoncharov@users.sf.net> | 2022-11-13 16:20:33 -0500 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2022-11-13 16:34:01 -0500 |
commit | 1b51ba1f5d448281ddeea5a252814bdec56a86fa (patch) | |
tree | feb32c324984b4f3eeae9134811702c94f3d5090 /src | |
parent | 4c9d87f4ae938a20fc21d2a0538c74dad0518f20 (diff) | |
download | make-git-1b51ba1f5d448281ddeea5a252814bdec56a86fa.tar.gz |
[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.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/misc.c | 64 | ||||
-rw-r--r-- | src/output.c | 3 | ||||
-rw-r--r-- | src/posixos.c | 7 |
4 files changed, 57 insertions, 20 deletions
@@ -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)) { @@ -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 diff --git a/src/output.c b/src/output.c index 43eb2f06..22387dff 100644 --- a/src/output.c +++ b/src/output.c @@ -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 (); diff --git a/src/posixos.c b/src/posixos.c index 3d7d6614..78358dd8 100644 --- a/src/posixos.c +++ b/src/posixos.c @@ -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 |