Commit | Line | Data |
---|---|---|
b4987c95 SDJ |
1 | /* Path manipulation routines for GDB and gdbserver. |
2 | ||
42a4f53d | 3 | Copyright (C) 1986-2019 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 | ||
137 | if (IS_ABSOLUTE_PATH (path)) | |
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"); |
87d6a7aa SM |
225 | if (xdg_cache_home != NULL) |
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"); |
87d6a7aa SM |
234 | if (home != NULL) |
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 | ||
241 | return {}; | |
242 | } | |
974e6844 | 243 | |
268a13a5 | 244 | /* See gdbsupport/pathstuff.h. */ |
974e6844 | 245 | |
e8d8cce6 SM |
246 | std::string |
247 | get_standard_temp_dir () | |
248 | { | |
249 | #ifdef WIN32 | |
250 | const char *tmp = getenv ("TMP"); | |
251 | if (tmp != nullptr) | |
252 | return tmp; | |
253 | ||
254 | tmp = getenv ("TEMP"); | |
255 | if (tmp != nullptr) | |
256 | return tmp; | |
257 | ||
258 | error (_("Couldn't find temp dir path, both TMP and TEMP are unset.")); | |
259 | ||
260 | #else | |
261 | const char *tmp = getenv ("TMPDIR"); | |
262 | if (tmp != nullptr) | |
263 | return tmp; | |
264 | ||
265 | return "/tmp"; | |
266 | #endif | |
267 | } | |
268 | ||
268a13a5 | 269 | /* See gdbsupport/pathstuff.h. */ |
e8d8cce6 | 270 | |
974e6844 TT |
271 | const char * |
272 | get_shell () | |
273 | { | |
274 | const char *ret = getenv ("SHELL"); | |
275 | if (ret == NULL) | |
276 | ret = "/bin/sh"; | |
277 | ||
278 | return ret; | |
279 | } | |
29be4d9d | 280 | |
268a13a5 | 281 | /* See gdbsupport/pathstuff.h. */ |
29be4d9d TT |
282 | |
283 | gdb::char_vector | |
284 | make_temp_filename (const std::string &f) | |
285 | { | |
286 | gdb::char_vector filename_temp (f.length () + 8); | |
287 | strcpy (filename_temp.data (), f.c_str ()); | |
288 | strcat (filename_temp.data () + f.size (), "-XXXXXX"); | |
289 | return filename_temp; | |
290 | } |