summaryrefslogtreecommitdiff
path: root/src/misc.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2022-08-27 19:03:40 -0400
committerPaul Smith <psmith@gnu.org>2022-08-30 15:39:02 -0400
commita2ba5ccbda4606dde29503f57caab33a974af5bf (patch)
tree09ae52b4c14dd5f363aa37e1e5f35387c1c82156 /src/misc.c
parent5eff618c8cbfbe1f386e3a55499cd8fe26cd35a1 (diff)
downloadmake-git-a2ba5ccbda4606dde29503f57caab33a974af5bf.tar.gz
Add get_tmpfd() and allow anonymous temp files
The output sync feature wants a file descriptor not a FILE*. We were using tmpfile() but this returns FILE* which means we needed to dup() the descriptor then fclose() the original, which is just unnecessary overhead for every command we run. Create a get_tmpfd() method that returns a file descriptor directly by using mkstemp() if available, else do the best we can. Also allow anonymous temp files if the filename pointer is NULL. This causes the file to be unlinked. On Windows this requires a special open so add an os_anontmp() method to handle this. * src/makeint.h: Add prototype for get_tmpfd(). * src/misc.c (get_tmpfd): If we have mkstemp() use that, else just open(2). If we don't want to keep the filename, unlink the file. (get_tmpfile): Use get_tmpfd() if we have fdopen(), else use fopen(). * src/output.c (output_tmpfd): Call get_tmpfd() with NULL. * src/os.h (os_anontmp): On Windows make this a function, else fails. * src/w32/compat/posixcfn.c (tmpfile): Move to w32os.c:os_anontmp(). * src/w32/w32os.c (os_anontmp): Create a temp file that will be deleted when the process exits, and return a file descriptor to it.
Diffstat (limited to 'src/misc.c')
-rw-r--r--src/misc.c84
1 files changed, 60 insertions, 24 deletions
diff --git a/src/misc.c b/src/misc.c
index fa0669ad..4a02ae7c 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -17,6 +17,7 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
#include "makeint.h"
#include "filedef.h"
#include "dep.h"
+#include "os.h"
#include "debug.h"
/* GNU make no longer supports pre-ANSI89 environments. */
@@ -573,44 +574,79 @@ get_tmppath ()
return path;
}
-FILE *
-get_tmpfile (char **name)
+/* 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. */
+int
+get_tmpfd (char **name)
{
- FILE *file;
-#ifdef HAVE_FDOPEN
- int fd;
-#endif
+ int fd = -1;
+ char *tmpnm;
+ mode_t mask;
+
+ /* If there's an os-specific way to get an anoymous temp file use it. */
+ if (!name)
+ {
+ fd = os_anontmp ();
+ if (fd >= 0)
+ return fd;
+ }
/* Preserve the current umask, and set a restrictive one for temp files. */
- mode_t mask = umask (0077);
+ mask = umask (0077);
-#if defined(HAVE_MKSTEMP) && defined(HAVE_FDOPEN)
- *name = get_tmptemplate ();
+#if defined(HAVE_MKSTEMP)
+ tmpnm = get_tmptemplate ();
/* It's safest to use mkstemp(), if we can. */
- EINTRLOOP (fd, mkstemp (*name));
- if (fd == -1)
- file = NULL;
- else
- file = fdopen (fd, "w");
+ EINTRLOOP (fd, mkstemp (tmpnm));
#else
- *name = get_tmppath ();
+ tmpnm = get_tmppath ();
-# ifdef HAVE_FDOPEN
/* Can't use mkstemp(), but try to guard against a race condition. */
- EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
- if (fd == -1)
- return 0;
- file = fdopen (fd, "w");
-# else
- /* Not secure, but what can we do? */
- file = fopen (*name, "w");
-# endif
+ EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
#endif
umask (mask);
+ if (name)
+ *name = tmpnm;
+ else
+ {
+ unlink (tmpnm);
+ free (tmpnm);
+ }
+
+ return fd;
+}
+
+FILE *
+get_tmpfile (char **name)
+{
+#if defined(HAVE_FDOPEN)
+ int fd = get_tmpfd (name);
+
+ return fd < 0 ? NULL : fdopen (fd, "w");
+#else
+ /* Preserve the current umask, and set a restrictive one for temp files. */
+ mode_t mask = umask (0077);
+
+ char *tmpnm = get_tmppath ();
+
+ /* Not secure, but...? If name is NULL we could use tmpfile()... */
+ FILE *file = fopen (tmpnm, "w");
+
+ umask (mask);
+
+ if (name)
+ *name = tmpnm;
+ else
+ {
+ unlink (tmpnm);
+ free (tmpnm);
+ }
+
return file;
+#endif
}