blob: 2936fb7a6c21a74e10b1119c817d8812c1b91f3f [file] [log] [blame]
/* Managing temporary directories and their content within
Copyright (C) 2014-2022 Free Software Foundation, Inc.
Contributed by David Malcolm <>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<>. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "jit-tempdir.h"
#ifdef _WIN32
#include "jit-w32.h"
#ifndef _WIN32
/* Construct a tempdir path template suitable for use by mkdtemp
e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in
libiberty's choose_tempdir rather than hardcoding "/tmp/".
The memory is allocated using malloc and must be freed.
Aborts the process if allocation fails. */
static char *
make_tempdir_path_template ()
const char *tmpdir_buf;
size_t tmpdir_len;
const char *file_template_buf;
size_t file_template_len;
char *result;
/* The result of choose_tmpdir is a cached buffer within libiberty, so
we must *not* free it. */
tmpdir_buf = choose_tmpdir ();
/* choose_tmpdir aborts on malloc failure. */
gcc_assert (tmpdir_buf);
tmpdir_len = strlen (tmpdir_buf);
/* tmpdir_buf should now have a dir separator as the final byte. */
gcc_assert (tmpdir_len > 0);
gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR);
file_template_buf = "libgccjit-XXXXXX";
file_template_len = strlen (file_template_buf);
result = XNEWVEC (char, tmpdir_len + file_template_len + 1);
strcpy (result, tmpdir_buf);
strcpy (result + tmpdir_len, file_template_buf);
return result;
/* The constructor for the jit::tempdir object.
The real work is done by the jit::tempdir::create method. */
gcc::jit::tempdir::tempdir (logger *logger, int keep_intermediates)
: log_user (logger),
m_keep_intermediates (keep_intermediates),
m_path_template (NULL),
m_path_tempdir (NULL),
m_path_c_file (NULL),
m_path_s_file (NULL),
m_path_so_file (NULL)
JIT_LOG_SCOPE (get_logger ());
/* Do the real work of creating the on-disk tempdir.
We do this here, rather than in the jit::tempdir constructor
so that we can handle failure without needing exceptions. */
gcc::jit::tempdir::create ()
JIT_LOG_SCOPE (get_logger ());
#ifdef _WIN32
m_path_tempdir = win_mkdtemp ();
m_path_template = make_tempdir_path_template ();
if (!m_path_template)
return false;
log ("m_path_template: %s", m_path_template);
/* Create tempdir using mkdtemp. This is created with 0700 perms and
is unique. Hence no other (non-root) users should have access to
the paths within it. */
m_path_tempdir = mkdtemp (m_path_template);
if (!m_path_tempdir)
return false;
log ("m_path_tempdir: %s", m_path_tempdir);
m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL);
m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL);
m_path_so_file = concat (m_path_tempdir, "/", NULL);
/* Success. */
return true;
/* The destructor for the jit::tempdir object, which
cleans up the filesystem directory and its contents
(unless keep_intermediates was set). */
gcc::jit::tempdir::~tempdir ()
JIT_LOG_SCOPE (get_logger ());
if (m_keep_intermediates)
fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir);
/* Clean up .s/.so. */
if (m_path_s_file)
log ("unlinking .s file: %s", m_path_s_file);
unlink (m_path_s_file);
if (m_path_so_file)
log ("unlinking .so file: %s", m_path_so_file);
unlink (m_path_so_file);
/* Clean up any other tempfiles. */
int i;
char *tempfile;
FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile)
log ("unlinking tempfile: %s", tempfile);
unlink (tempfile);
/* The tempdir should now be empty; remove it. */
if (m_path_tempdir)
log ("removing tempdir: %s", m_path_tempdir);
rmdir (m_path_tempdir);
free (m_path_template);
/* m_path_tempdir aliases m_path_template, or is NULL, so don't
attempt to free it . */
free (m_path_c_file);
free (m_path_s_file);
free (m_path_so_file);
int i;
char *tempfile;
FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile)
free (tempfile);