pathstuff.cc revision 1.1.1.2 1 1.1 christos /* Path manipulation routines for GDB and gdbserver.
2 1.1 christos
3 1.1.1.2 christos Copyright (C) 1986-2023 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos This file is part of GDB.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 1.1 christos
20 1.1 christos #include "common-defs.h"
21 1.1 christos #include "pathstuff.h"
22 1.1 christos #include "host-defs.h"
23 1.1 christos #include "filenames.h"
24 1.1 christos #include "gdb_tilde_expand.h"
25 1.1 christos
26 1.1 christos #ifdef USE_WIN32API
27 1.1 christos #include <windows.h>
28 1.1 christos #endif
29 1.1 christos
30 1.1 christos /* See gdbsupport/pathstuff.h. */
31 1.1 christos
32 1.1.1.2 christos char *current_directory;
33 1.1.1.2 christos
34 1.1.1.2 christos /* See gdbsupport/pathstuff.h. */
35 1.1.1.2 christos
36 1.1 christos gdb::unique_xmalloc_ptr<char>
37 1.1 christos gdb_realpath (const char *filename)
38 1.1 christos {
39 1.1 christos /* On most hosts, we rely on canonicalize_file_name to compute
40 1.1 christos the FILENAME's realpath.
41 1.1 christos
42 1.1 christos But the situation is slightly more complex on Windows, due to some
43 1.1 christos versions of GCC which were reported to generate paths where
44 1.1 christos backlashes (the directory separator) were doubled. For instance:
45 1.1 christos c:\\some\\double\\slashes\\dir
46 1.1 christos ... instead of ...
47 1.1 christos c:\some\double\slashes\dir
48 1.1 christos Those double-slashes were getting in the way when comparing paths,
49 1.1 christos for instance when trying to insert a breakpoint as follow:
50 1.1 christos (gdb) b c:/some/double/slashes/dir/foo.c:4
51 1.1 christos No source file named c:/some/double/slashes/dir/foo.c:4.
52 1.1 christos (gdb) b c:\some\double\slashes\dir\foo.c:4
53 1.1 christos No source file named c:\some\double\slashes\dir\foo.c:4.
54 1.1 christos To prevent this from happening, we need this function to always
55 1.1 christos strip those extra backslashes. While canonicalize_file_name does
56 1.1 christos perform this simplification, it only works when the path is valid.
57 1.1 christos Since the simplification would be useful even if the path is not
58 1.1 christos valid (one can always set a breakpoint on a file, even if the file
59 1.1 christos does not exist locally), we rely instead on GetFullPathName to
60 1.1 christos perform the canonicalization. */
61 1.1 christos
62 1.1 christos #if defined (_WIN32)
63 1.1 christos {
64 1.1 christos char buf[MAX_PATH];
65 1.1 christos DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
66 1.1 christos
67 1.1 christos /* The file system is case-insensitive but case-preserving.
68 1.1 christos So it is important we do not lowercase the path. Otherwise,
69 1.1 christos we might not be able to display the original casing in a given
70 1.1 christos path. */
71 1.1 christos if (len > 0 && len < MAX_PATH)
72 1.1 christos return make_unique_xstrdup (buf);
73 1.1 christos }
74 1.1 christos #else
75 1.1 christos {
76 1.1 christos char *rp = canonicalize_file_name (filename);
77 1.1 christos
78 1.1 christos if (rp != NULL)
79 1.1 christos return gdb::unique_xmalloc_ptr<char> (rp);
80 1.1 christos }
81 1.1 christos #endif
82 1.1 christos
83 1.1 christos /* This system is a lost cause, just dup the buffer. */
84 1.1 christos return make_unique_xstrdup (filename);
85 1.1 christos }
86 1.1 christos
87 1.1 christos /* See gdbsupport/pathstuff.h. */
88 1.1 christos
89 1.1.1.2 christos std::string
90 1.1 christos gdb_realpath_keepfile (const char *filename)
91 1.1 christos {
92 1.1 christos const char *base_name = lbasename (filename);
93 1.1 christos char *dir_name;
94 1.1 christos
95 1.1 christos /* Extract the basename of filename, and return immediately
96 1.1 christos a copy of filename if it does not contain any directory prefix. */
97 1.1 christos if (base_name == filename)
98 1.1.1.2 christos return filename;
99 1.1 christos
100 1.1 christos dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
101 1.1 christos /* Allocate enough space to store the dir_name + plus one extra
102 1.1 christos character sometimes needed under Windows (see below), and
103 1.1 christos then the closing \000 character. */
104 1.1 christos strncpy (dir_name, filename, base_name - filename);
105 1.1 christos dir_name[base_name - filename] = '\000';
106 1.1 christos
107 1.1 christos #ifdef HAVE_DOS_BASED_FILE_SYSTEM
108 1.1 christos /* We need to be careful when filename is of the form 'd:foo', which
109 1.1 christos is equivalent of d:./foo, which is totally different from d:/foo. */
110 1.1 christos if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
111 1.1 christos {
112 1.1 christos dir_name[2] = '.';
113 1.1 christos dir_name[3] = '\000';
114 1.1 christos }
115 1.1 christos #endif
116 1.1 christos
117 1.1 christos /* Canonicalize the directory prefix, and build the resulting
118 1.1 christos filename. If the dirname realpath already contains an ending
119 1.1 christos directory separator, avoid doubling it. */
120 1.1 christos gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
121 1.1 christos const char *real_path = path_storage.get ();
122 1.1.1.2 christos return path_join (real_path, base_name);
123 1.1 christos }
124 1.1 christos
125 1.1 christos /* See gdbsupport/pathstuff.h. */
126 1.1 christos
127 1.1.1.2 christos std::string
128 1.1 christos gdb_abspath (const char *path)
129 1.1 christos {
130 1.1 christos gdb_assert (path != NULL && path[0] != '\0');
131 1.1 christos
132 1.1 christos if (path[0] == '~')
133 1.1.1.2 christos return gdb_tilde_expand (path);
134 1.1 christos
135 1.1 christos if (IS_ABSOLUTE_PATH (path) || current_directory == NULL)
136 1.1.1.2 christos return path;
137 1.1 christos
138 1.1.1.2 christos return path_join (current_directory, path);
139 1.1 christos }
140 1.1 christos
141 1.1 christos /* See gdbsupport/pathstuff.h. */
142 1.1 christos
143 1.1 christos const char *
144 1.1 christos child_path (const char *parent, const char *child)
145 1.1 christos {
146 1.1 christos /* The child path must start with the parent path. */
147 1.1 christos size_t parent_len = strlen (parent);
148 1.1 christos if (filename_ncmp (parent, child, parent_len) != 0)
149 1.1 christos return NULL;
150 1.1 christos
151 1.1 christos /* The parent path must be a directory and the child must contain at
152 1.1 christos least one component underneath the parent. */
153 1.1 christos const char *child_component;
154 1.1 christos if (parent_len > 0 && IS_DIR_SEPARATOR (parent[parent_len - 1]))
155 1.1 christos {
156 1.1 christos /* The parent path ends in a directory separator, so it is a
157 1.1 christos directory. The first child component starts after the common
158 1.1 christos prefix. */
159 1.1 christos child_component = child + parent_len;
160 1.1 christos }
161 1.1 christos else
162 1.1 christos {
163 1.1 christos /* The parent path does not end in a directory separator. The
164 1.1 christos first character in the child after the common prefix must be
165 1.1 christos a directory separator.
166 1.1 christos
167 1.1 christos Note that CHILD must hold at least parent_len characters for
168 1.1 christos filename_ncmp to return zero. If the character at parent_len
169 1.1 christos is nul due to CHILD containing the same path as PARENT, the
170 1.1 christos IS_DIR_SEPARATOR check will fail here. */
171 1.1 christos if (!IS_DIR_SEPARATOR (child[parent_len]))
172 1.1 christos return NULL;
173 1.1 christos
174 1.1 christos /* The first child component starts after the separator after the
175 1.1 christos common prefix. */
176 1.1 christos child_component = child + parent_len + 1;
177 1.1 christos }
178 1.1 christos
179 1.1 christos /* The child must contain at least one non-separator character after
180 1.1 christos the parent. */
181 1.1 christos while (*child_component != '\0')
182 1.1 christos {
183 1.1 christos if (!IS_DIR_SEPARATOR (*child_component))
184 1.1 christos return child_component;
185 1.1 christos
186 1.1 christos child_component++;
187 1.1 christos }
188 1.1 christos return NULL;
189 1.1 christos }
190 1.1 christos
191 1.1 christos /* See gdbsupport/pathstuff.h. */
192 1.1 christos
193 1.1.1.2 christos std::string
194 1.1.1.2 christos path_join (gdb::array_view<const char *> paths)
195 1.1.1.2 christos {
196 1.1.1.2 christos std::string ret;
197 1.1.1.2 christos
198 1.1.1.2 christos for (int i = 0; i < paths.size (); ++i)
199 1.1.1.2 christos {
200 1.1.1.2 christos const char *path = paths[i];
201 1.1.1.2 christos
202 1.1.1.2 christos if (i > 0)
203 1.1.1.2 christos gdb_assert (strlen (path) == 0 || !IS_ABSOLUTE_PATH (path));
204 1.1.1.2 christos
205 1.1.1.2 christos if (!ret.empty () && !IS_DIR_SEPARATOR (ret.back ()))
206 1.1.1.2 christos ret += '/';
207 1.1.1.2 christos
208 1.1.1.2 christos ret.append (path);
209 1.1.1.2 christos }
210 1.1.1.2 christos
211 1.1.1.2 christos return ret;
212 1.1.1.2 christos }
213 1.1.1.2 christos
214 1.1.1.2 christos /* See gdbsupport/pathstuff.h. */
215 1.1.1.2 christos
216 1.1 christos bool
217 1.1 christos contains_dir_separator (const char *path)
218 1.1 christos {
219 1.1 christos for (; *path != '\0'; path++)
220 1.1 christos {
221 1.1 christos if (IS_DIR_SEPARATOR (*path))
222 1.1 christos return true;
223 1.1 christos }
224 1.1 christos
225 1.1 christos return false;
226 1.1 christos }
227 1.1 christos
228 1.1 christos /* See gdbsupport/pathstuff.h. */
229 1.1 christos
230 1.1 christos std::string
231 1.1 christos get_standard_cache_dir ()
232 1.1 christos {
233 1.1 christos #ifdef __APPLE__
234 1.1 christos #define HOME_CACHE_DIR "Library/Caches"
235 1.1 christos #else
236 1.1 christos #define HOME_CACHE_DIR ".cache"
237 1.1 christos #endif
238 1.1 christos
239 1.1 christos #ifndef __APPLE__
240 1.1 christos const char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
241 1.1.1.2 christos if (xdg_cache_home != NULL && xdg_cache_home[0] != '\0')
242 1.1 christos {
243 1.1 christos /* Make sure the path is absolute and tilde-expanded. */
244 1.1.1.2 christos std::string abs = gdb_abspath (xdg_cache_home);
245 1.1.1.2 christos return path_join (abs.c_str (), "gdb");
246 1.1 christos }
247 1.1 christos #endif
248 1.1 christos
249 1.1 christos const char *home = getenv ("HOME");
250 1.1.1.2 christos if (home != NULL && home[0] != '\0')
251 1.1.1.2 christos {
252 1.1.1.2 christos /* Make sure the path is absolute and tilde-expanded. */
253 1.1.1.2 christos std::string abs = gdb_abspath (home);
254 1.1.1.2 christos return path_join (abs.c_str (), HOME_CACHE_DIR, "gdb");
255 1.1.1.2 christos }
256 1.1.1.2 christos
257 1.1.1.2 christos #ifdef WIN32
258 1.1.1.2 christos const char *win_home = getenv ("LOCALAPPDATA");
259 1.1.1.2 christos if (win_home != NULL && win_home[0] != '\0')
260 1.1 christos {
261 1.1 christos /* Make sure the path is absolute and tilde-expanded. */
262 1.1.1.2 christos std::string abs = gdb_abspath (win_home);
263 1.1.1.2 christos return path_join (abs.c_str (), "gdb");
264 1.1 christos }
265 1.1.1.2 christos #endif
266 1.1 christos
267 1.1 christos return {};
268 1.1 christos }
269 1.1 christos
270 1.1 christos /* See gdbsupport/pathstuff.h. */
271 1.1 christos
272 1.1 christos std::string
273 1.1 christos get_standard_temp_dir ()
274 1.1 christos {
275 1.1 christos #ifdef WIN32
276 1.1 christos const char *tmp = getenv ("TMP");
277 1.1 christos if (tmp != nullptr)
278 1.1 christos return tmp;
279 1.1 christos
280 1.1 christos tmp = getenv ("TEMP");
281 1.1 christos if (tmp != nullptr)
282 1.1 christos return tmp;
283 1.1 christos
284 1.1 christos error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
285 1.1 christos
286 1.1 christos #else
287 1.1 christos const char *tmp = getenv ("TMPDIR");
288 1.1 christos if (tmp != nullptr)
289 1.1 christos return tmp;
290 1.1 christos
291 1.1 christos return "/tmp";
292 1.1 christos #endif
293 1.1 christos }
294 1.1 christos
295 1.1.1.2 christos /* See pathstuff.h. */
296 1.1.1.2 christos
297 1.1.1.2 christos std::string
298 1.1.1.2 christos get_standard_config_dir ()
299 1.1.1.2 christos {
300 1.1.1.2 christos #ifdef __APPLE__
301 1.1.1.2 christos #define HOME_CONFIG_DIR "Library/Preferences"
302 1.1.1.2 christos #else
303 1.1.1.2 christos #define HOME_CONFIG_DIR ".config"
304 1.1.1.2 christos #endif
305 1.1.1.2 christos
306 1.1.1.2 christos #ifndef __APPLE__
307 1.1.1.2 christos const char *xdg_config_home = getenv ("XDG_CONFIG_HOME");
308 1.1.1.2 christos if (xdg_config_home != NULL && xdg_config_home[0] != '\0')
309 1.1.1.2 christos {
310 1.1.1.2 christos /* Make sure the path is absolute and tilde-expanded. */
311 1.1.1.2 christos std::string abs = gdb_abspath (xdg_config_home);
312 1.1.1.2 christos return path_join (abs.c_str (), "gdb");
313 1.1.1.2 christos }
314 1.1.1.2 christos #endif
315 1.1.1.2 christos
316 1.1.1.2 christos const char *home = getenv ("HOME");
317 1.1.1.2 christos if (home != NULL && home[0] != '\0')
318 1.1.1.2 christos {
319 1.1.1.2 christos /* Make sure the path is absolute and tilde-expanded. */
320 1.1.1.2 christos std::string abs = gdb_abspath (home);
321 1.1.1.2 christos return path_join (abs.c_str (), HOME_CONFIG_DIR, "gdb");
322 1.1.1.2 christos }
323 1.1.1.2 christos
324 1.1.1.2 christos return {};
325 1.1.1.2 christos }
326 1.1.1.2 christos
327 1.1.1.2 christos /* See pathstuff.h. */
328 1.1.1.2 christos
329 1.1.1.2 christos std::string
330 1.1.1.2 christos get_standard_config_filename (const char *filename)
331 1.1.1.2 christos {
332 1.1.1.2 christos std::string config_dir = get_standard_config_dir ();
333 1.1.1.2 christos if (config_dir != "")
334 1.1.1.2 christos {
335 1.1.1.2 christos const char *tmp = (*filename == '.') ? (filename + 1) : filename;
336 1.1.1.2 christos std::string path = config_dir + SLASH_STRING + std::string (tmp);
337 1.1.1.2 christos return path;
338 1.1.1.2 christos }
339 1.1.1.2 christos
340 1.1.1.2 christos return {};
341 1.1.1.2 christos }
342 1.1.1.2 christos
343 1.1.1.2 christos /* See pathstuff.h. */
344 1.1.1.2 christos
345 1.1.1.2 christos std::string
346 1.1.1.2 christos find_gdb_home_config_file (const char *name, struct stat *buf)
347 1.1.1.2 christos {
348 1.1.1.2 christos gdb_assert (name != nullptr);
349 1.1.1.2 christos gdb_assert (*name != '\0');
350 1.1.1.2 christos
351 1.1.1.2 christos std::string config_dir_file = get_standard_config_filename (name);
352 1.1.1.2 christos if (!config_dir_file.empty ())
353 1.1.1.2 christos {
354 1.1.1.2 christos if (stat (config_dir_file.c_str (), buf) == 0)
355 1.1.1.2 christos return config_dir_file;
356 1.1.1.2 christos }
357 1.1.1.2 christos
358 1.1.1.2 christos const char *homedir = getenv ("HOME");
359 1.1.1.2 christos if (homedir != nullptr && homedir[0] != '\0')
360 1.1.1.2 christos {
361 1.1.1.2 christos /* Make sure the path is absolute and tilde-expanded. */
362 1.1.1.2 christos std::string abs = gdb_abspath (homedir);
363 1.1.1.2 christos std::string path = string_printf ("%s/%s", abs.c_str (), name);
364 1.1.1.2 christos if (stat (path.c_str (), buf) == 0)
365 1.1.1.2 christos return path;
366 1.1.1.2 christos }
367 1.1.1.2 christos
368 1.1.1.2 christos return {};
369 1.1.1.2 christos }
370 1.1.1.2 christos
371 1.1 christos /* See gdbsupport/pathstuff.h. */
372 1.1 christos
373 1.1 christos const char *
374 1.1 christos get_shell ()
375 1.1 christos {
376 1.1 christos const char *ret = getenv ("SHELL");
377 1.1 christos if (ret == NULL)
378 1.1 christos ret = "/bin/sh";
379 1.1 christos
380 1.1 christos return ret;
381 1.1 christos }
382 1.1 christos
383 1.1 christos /* See gdbsupport/pathstuff.h. */
384 1.1 christos
385 1.1 christos gdb::char_vector
386 1.1 christos make_temp_filename (const std::string &f)
387 1.1 christos {
388 1.1 christos gdb::char_vector filename_temp (f.length () + 8);
389 1.1 christos strcpy (filename_temp.data (), f.c_str ());
390 1.1 christos strcat (filename_temp.data () + f.size (), "-XXXXXX");
391 1.1 christos return filename_temp;
392 1.1 christos }
393