#define MAKE_TMPDIR "MAKE_TMPDIR"
#ifdef VMS
# define DEFAULT_TMPFILE "sys$scratch:gnv$make_cmdXXXXXX.com"
-# define DEFAULT_TMPDIR "/sys$scratch/"
#else
-# define DEFAULT_TMPFILE "GmXXXXXX"
-# ifdef P_tmpdir
-# define DEFAULT_TMPDIR P_tmpdir
-# else
-# define DEFAULT_TMPDIR "/tmp"
-# endif
+# define DEFAULT_TMPFILE "GmXXXXXX"
#endif
-static const char *
+const char *
get_tmpdir ()
{
static const char *tmpdir = NULL;
{
const char *tmpdir = get_tmpdir ();
char *template;
- size_t len;
+ char *cp;
- len = strlen (tmpdir);
- template = xmalloc (len + CSTRLEN (DEFAULT_TMPFILE) + 2);
- strcpy (template, tmpdir);
+ template = xmalloc (strlen (tmpdir) + CSTRLEN (DEFAULT_TMPFILE) + 2);
+ cp = stpcpy (template, tmpdir);
-#ifdef HAVE_DOS_PATHS
- if (template[len - 1] != '/' && template[len - 1] != '\\')
- strcat (template, "/");
-#else
-# ifndef VMS
- if (template[len - 1] != '/')
- strcat (template, "/");
-# endif /* !VMS */
-#endif /* !HAVE_DOS_PATHS */
+#if !defined VMS
+ /* It's not possible for tmpdir to be empty. */
+ if (! ISDIRSEP (cp[-1]))
+ *(cp++) = '/';
+#endif
- strcat (template, DEFAULT_TMPFILE);
+ strcpy (cp, DEFAULT_TMPFILE);
return template;
}
-char *
+#if !HAVE_MKSTEMP || !HAVE_FDOPEN
+/* Generate a temporary filename. This is not safe as another program could
+ snipe our filename after we've generated it: use this only on systems
+ without more secure alternatives. */
+
+static char *
get_tmppath ()
{
char *path;
-#ifdef HAVE_MKTEMP
- path = get_tmptemplate();
+# ifdef HAVE_MKTEMP
+ path = get_tmptemplate ();
if (*mktemp (path) == '\0')
pfatal_with_name ("mktemp");
-#else
+# else
path = xmalloc (L_tmpnam + 1);
if (tmpnam (path) == NULL)
pfatal_with_name ("tmpnam");
-#endif
+# endif
return path;
}
+#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. */
{
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)
return fd;
}
- /* Preserve the current umask, and set a restrictive one for temp files. */
- mask = umask (0077);
-
#if defined(HAVE_MKSTEMP)
tmpnm = get_tmptemplate ();
/* Can't use mkstemp(), but try to guard against a race condition. */
EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
#endif
-
- umask (mask);
+ if (fd < 0)
+ OSS (fatal, NILF,
+ _("create temporary file %s: %s"), tmpnm, strerror (errno));
if (name)
*name = tmpnm;
else
{
- unlink (tmpnm);
+ int r;
+ EINTRLOOP (r, unlink (tmpnm));
+ if (r < 0)
+ OSS (fatal, NILF,
+ _("unlink temporary file %s: %s"), tmpnm, strerror (errno));
free (tmpnm);
}
return fd;
}
+/* 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! */
FILE *
get_tmpfile (char **name)
{
+ /* Be consistent with tmpfile, which opens as if by "wb+". */
+ const char *tmpfile_mode = "wb+";
+ FILE *file;
+
#if defined(HAVE_FDOPEN)
int fd = get_tmpfd (name);
- return fd < 0 ? NULL : fdopen (fd, "w");
+ ENULLLOOP (file, fdopen (fd, tmpfile_mode));
+ if (file == NULL)
+ OSS (fatal, 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;
- char *tmpnm = get_tmppath ();
+ *name = get_tmppath ();
- /* Not secure, but...? If name is NULL we could use tmpfile()... */
- FILE *file = fopen (tmpnm, "w");
+ /* Although this fopen is insecure, it is executed only on non-fdopen
+ platforms, which should be a rarity nowadays. */
- umask (mask);
+ ENULLLOOP (file, fopen (*name, tmpfile_mode));
+ if (file == NULL)
+ OSS (fatal, NILF,
+ _("fopen: temporary file %s: %s"), *name, strerror (errno));
- if (name)
- *name = tmpnm;
- else
- {
- unlink (tmpnm);
- free (tmpnm);
- }
+ umask (mask);
+#endif
return file;
-#endif
}
\f
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>. */
-
#define IO_UNKNOWN 0x0001
#define IO_COMBINED_OUTERR 0x0002
#define IO_STDIN_OK 0x0004
# define fd_inherit(_i) (0)
# define fd_noinherit(_i) (0)
# define fd_set_append(_i) (void)(0)
+# define os_anontmp() (-1)
#else
/* Determine the state of stdin/stdout/stderr. */
/* If the file descriptor is for a file put it into append mode. */
void fd_set_append (int);
-#endif
/* Return a file descriptor for a new anonymous temp file, or -1. */
-#if defined(WINDOWS32)
int os_anontmp (void);
-#else
-# define os_anontmp() (-1)
#endif
/* This section provides OS-specific functions to support the jobserver. */
#if HAVE_MKFIFO
if (style == NULL || strcmp (style, "fifo") == 0)
{
- fifo_name = get_tmppath ();
+ /* Unfortunately glibc warns about uses of mktemp even though we aren't
+ using it in dangerous way here. So avoid this by generating our own
+ temporary file name. */
+# define FNAME_PREFIX "GMfifo"
+ const char *tmpdir = get_tmpdir ();
+
+ fifo_name = xmalloc (strlen (tmpdir) + CSTRLEN (FNAME_PREFIX)
+ + INTSTR_LENGTH + 2);
+ sprintf (fifo_name, "%s/" FNAME_PREFIX "%" MK_PRI64_PREFIX "d",
+ tmpdir, (long long)make_pid ());
EINTRLOOP (r, mkfifo (fifo_name, 0600));
if (r < 0)
osync_setup ()
{
osync_handle = get_tmpfd (&osync_tmpfile);
- if (osync_handle >= 0)
- {
- fd_noinherit (osync_handle);
- sync_root = 1;
- }
+ fd_noinherit (osync_handle);
+ sync_root = 1;
}
char *
}
#endif
}
+
+/* Return a file descriptor for a new anonymous temp file, or -1. */
+int
+os_anontmp ()
+{
+ int fd = -1;
+
+#ifdef O_TMPFILE
+ EINTRLOOP (fd, open (get_tmpdir (), O_RDWR | O_TMPFILE | O_EXCL, 0600));
+ if (fd < 0)
+ pfatal_with_name ("open(O_TMPFILE)");
+#elif HAVE_DUP
+ /* We don't have O_TMPFILE but we can dup: if we are creating temp files in
+ the default location then try tmpfile() + dup() + fclose() to avoid ever
+ having a name for a file. */
+ if (streq (get_tmpdir (), DEFAULT_TMPDIR))
+ {
+ mode_t mask = umask (0077);
+ FILE *tfile;
+ ENULLLOOP (tfile, tmpfile ());
+ if (!tfile)
+ pfatal_with_name ("tmpfile");
+ umask (mask);
+
+ EINTRLOOP (fd, dup (fileno (tfile)));
+ if (fd < 0)
+ pfatal_with_name ("dup");
+ fclose (tfile);
+ }
+#endif
+
+ return fd;
+}