1/* Managing temporary directories and their content within libgccjit.so 2 Copyright (C) 2014-2022 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24 25#include "jit-tempdir.h" 26 27#ifdef _WIN32 28#include "jit-w32.h" 29#endif 30 31#ifndef _WIN32 32/* Construct a tempdir path template suitable for use by mkdtemp 33 e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in 34 libiberty's choose_tempdir rather than hardcoding "/tmp/". 35 36 The memory is allocated using malloc and must be freed. 37 Aborts the process if allocation fails. */ 38 39static char * 40make_tempdir_path_template () 41{ 42 const char *tmpdir_buf; 43 size_t tmpdir_len; 44 const char *file_template_buf; 45 size_t file_template_len; 46 char *result; 47 48 /* The result of choose_tmpdir is a cached buffer within libiberty, so 49 we must *not* free it. */ 50 tmpdir_buf = choose_tmpdir (); 51 52 /* choose_tmpdir aborts on malloc failure. */ 53 gcc_assert (tmpdir_buf); 54 55 tmpdir_len = strlen (tmpdir_buf); 56 /* tmpdir_buf should now have a dir separator as the final byte. */ 57 gcc_assert (tmpdir_len > 0); 58 gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR); 59 60 file_template_buf = "libgccjit-XXXXXX"; 61 file_template_len = strlen (file_template_buf); 62 63 result = XNEWVEC (char, tmpdir_len + file_template_len + 1); 64 strcpy (result, tmpdir_buf); 65 strcpy (result + tmpdir_len, file_template_buf); 66 67 return result; 68} 69#endif 70 71/* The constructor for the jit::tempdir object. 72 The real work is done by the jit::tempdir::create method. */ 73 74gcc::jit::tempdir::tempdir (logger *logger, int keep_intermediates) 75 : log_user (logger), 76 m_keep_intermediates (keep_intermediates), 77 m_path_template (NULL), 78 m_path_tempdir (NULL), 79 m_path_c_file (NULL), 80 m_path_s_file (NULL), 81 m_path_so_file (NULL) 82{ 83 JIT_LOG_SCOPE (get_logger ()); 84} 85 86/* Do the real work of creating the on-disk tempdir. 87 We do this here, rather than in the jit::tempdir constructor 88 so that we can handle failure without needing exceptions. */ 89 90bool 91gcc::jit::tempdir::create () 92{ 93 JIT_LOG_SCOPE (get_logger ()); 94 95#ifdef _WIN32 96 m_path_tempdir = win_mkdtemp (); 97#else 98 m_path_template = make_tempdir_path_template (); 99 if (!m_path_template) 100 return false; 101 102 log ("m_path_template: %s", m_path_template); 103 104 /* Create tempdir using mkdtemp. This is created with 0700 perms and 105 is unique. Hence no other (non-root) users should have access to 106 the paths within it. */ 107 m_path_tempdir = mkdtemp (m_path_template); 108#endif 109 110 if (!m_path_tempdir) 111 return false; 112 log ("m_path_tempdir: %s", m_path_tempdir); 113 114 m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL); 115 m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL); 116 m_path_so_file = concat (m_path_tempdir, "/fake.so", NULL); 117 118 /* Success. */ 119 return true; 120} 121 122/* The destructor for the jit::tempdir object, which 123 cleans up the filesystem directory and its contents 124 (unless keep_intermediates was set). */ 125 126gcc::jit::tempdir::~tempdir () 127{ 128 JIT_LOG_SCOPE (get_logger ()); 129 130 if (m_keep_intermediates) 131 fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir); 132 else 133 { 134 /* Clean up .s/.so. */ 135 if (m_path_s_file) 136 { 137 log ("unlinking .s file: %s", m_path_s_file); 138 unlink (m_path_s_file); 139 } 140 if (m_path_so_file) 141 { 142 log ("unlinking .so file: %s", m_path_so_file); 143 unlink (m_path_so_file); 144 } 145 146 /* Clean up any other tempfiles. */ 147 int i; 148 char *tempfile; 149 FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile) 150 { 151 log ("unlinking tempfile: %s", tempfile); 152 unlink (tempfile); 153 } 154 155 /* The tempdir should now be empty; remove it. */ 156 if (m_path_tempdir) 157 { 158 log ("removing tempdir: %s", m_path_tempdir); 159 rmdir (m_path_tempdir); 160 } 161 } 162 163 free (m_path_template); 164 /* m_path_tempdir aliases m_path_template, or is NULL, so don't 165 attempt to free it . */ 166 free (m_path_c_file); 167 free (m_path_s_file); 168 free (m_path_so_file); 169 170 int i; 171 char *tempfile; 172 FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile) 173 free (tempfile); 174} 175