jit-tempdir.c revision 1.3
1/* Managing temporary directories and their content within libgccjit.so 2 Copyright (C) 2014-2017 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 28/* Construct a tempdir path template suitable for use by mkdtemp 29 e.g. "/tmp/libgccjit-XXXXXX", but respecting the rules in 30 libiberty's choose_tempdir rather than hardcoding "/tmp/". 31 32 The memory is allocated using malloc and must be freed. 33 Aborts the process if allocation fails. */ 34 35static char * 36make_tempdir_path_template () 37{ 38 const char *tmpdir_buf; 39 size_t tmpdir_len; 40 const char *file_template_buf; 41 size_t file_template_len; 42 char *result; 43 44 /* The result of choose_tmpdir is a cached buffer within libiberty, so 45 we must *not* free it. */ 46 tmpdir_buf = choose_tmpdir (); 47 48 /* choose_tmpdir aborts on malloc failure. */ 49 gcc_assert (tmpdir_buf); 50 51 tmpdir_len = strlen (tmpdir_buf); 52 /* tmpdir_buf should now have a dir separator as the final byte. */ 53 gcc_assert (tmpdir_len > 0); 54 gcc_assert (tmpdir_buf[tmpdir_len - 1] == DIR_SEPARATOR); 55 56 file_template_buf = "libgccjit-XXXXXX"; 57 file_template_len = strlen (file_template_buf); 58 59 result = XNEWVEC (char, tmpdir_len + file_template_len + 1); 60 strcpy (result, tmpdir_buf); 61 strcpy (result + tmpdir_len, file_template_buf); 62 63 return result; 64} 65 66/* The constructor for the jit::tempdir object. 67 The real work is done by the jit::tempdir::create method. */ 68 69gcc::jit::tempdir::tempdir (logger *logger, int keep_intermediates) 70 : log_user (logger), 71 m_keep_intermediates (keep_intermediates), 72 m_path_template (NULL), 73 m_path_tempdir (NULL), 74 m_path_c_file (NULL), 75 m_path_s_file (NULL), 76 m_path_so_file (NULL) 77{ 78 JIT_LOG_SCOPE (get_logger ()); 79} 80 81/* Do the real work of creating the on-disk tempdir. 82 We do this here, rather than in the jit::tempdir constructor 83 so that we can handle failure without needing exceptions. */ 84 85bool 86gcc::jit::tempdir::create () 87{ 88 JIT_LOG_SCOPE (get_logger ()); 89 90 m_path_template = make_tempdir_path_template (); 91 if (!m_path_template) 92 return false; 93 94 log ("m_path_template: %s", m_path_template); 95 96 /* Create tempdir using mkdtemp. This is created with 0700 perms and 97 is unique. Hence no other (non-root) users should have access to 98 the paths within it. */ 99 m_path_tempdir = mkdtemp (m_path_template); 100 if (!m_path_tempdir) 101 return false; 102 log ("m_path_tempdir: %s", m_path_tempdir); 103 104 m_path_c_file = concat (m_path_tempdir, "/fake.c", NULL); 105 m_path_s_file = concat (m_path_tempdir, "/fake.s", NULL); 106 m_path_so_file = concat (m_path_tempdir, "/fake.so", NULL); 107 108 /* Success. */ 109 return true; 110} 111 112/* The destructor for the jit::tempdir object, which 113 cleans up the filesystem directory and its contents 114 (unless keep_intermediates was set). */ 115 116gcc::jit::tempdir::~tempdir () 117{ 118 JIT_LOG_SCOPE (get_logger ()); 119 120 if (m_keep_intermediates) 121 fprintf (stderr, "intermediate files written to %s\n", m_path_tempdir); 122 else 123 { 124 /* Clean up .s/.so. */ 125 if (m_path_s_file) 126 { 127 log ("unlinking .s file: %s", m_path_s_file); 128 unlink (m_path_s_file); 129 } 130 if (m_path_so_file) 131 { 132 log ("unlinking .so file: %s", m_path_so_file); 133 unlink (m_path_so_file); 134 } 135 136 /* Clean up any other tempfiles. */ 137 int i; 138 char *tempfile; 139 FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile) 140 { 141 log ("unlinking tempfile: %s", tempfile); 142 unlink (tempfile); 143 } 144 145 /* The tempdir should now be empty; remove it. */ 146 if (m_path_tempdir) 147 { 148 log ("removing tempdir: %s", m_path_tempdir); 149 rmdir (m_path_tempdir); 150 } 151 } 152 153 free (m_path_template); 154 /* m_path_tempdir aliases m_path_template, or is NULL, so don't 155 attempt to free it . */ 156 free (m_path_c_file); 157 free (m_path_s_file); 158 free (m_path_so_file); 159 160 int i; 161 char *tempfile; 162 FOR_EACH_VEC_ELT (m_tempfiles, i, tempfile) 163 free (tempfile); 164} 165