xref: /netbsd-src/external/gpl3/gcc/dist/gcc/jit/jit-tempdir.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along 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 
39 static char *
make_tempdir_path_template()40 make_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 
tempdir(logger * logger,int keep_intermediates)74 gcc::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 
90 bool
create()91 gcc::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 
~tempdir()126 gcc::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