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