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