Commit | Line | Data |
---|---|---|
b4987c95 SDJ |
1 | /* Path manipulation routines for GDB and gdbserver. |
2 | ||
3 | Copyright (C) 1986-2018 Free Software Foundation, Inc. | |
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 | ||
b4987c95 SDJ |
30 | /* See common/pathstuff.h. */ |
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) | |
68 | return gdb::unique_xmalloc_ptr<char> (xstrdup (buf)); | |
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. */ | |
80 | return gdb::unique_xmalloc_ptr<char> (xstrdup (filename)); | |
81 | } | |
82 | ||
83 | /* See common/pathstuff.h. */ | |
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) | |
95 | return gdb::unique_xmalloc_ptr<char> (xstrdup (filename)); | |
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 | ||
127 | /* See common/pathstuff.h. */ | |
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)) | |
138 | return gdb::unique_xmalloc_ptr<char> (xstrdup (path)); | |
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 SDJ |
147 | |
148 | /* See common/pathstuff.h. */ | |
149 | ||
150 | bool | |
151 | contains_dir_separator (const char *path) | |
152 | { | |
153 | for (; *path != '\0'; path++) | |
154 | { | |
155 | if (IS_DIR_SEPARATOR (*path)) | |
156 | return true; | |
157 | } | |
158 | ||
159 | return false; | |
160 | } | |
87d6a7aa SM |
161 | |
162 | /* See common/pathstuff.h. */ | |
163 | ||
164 | std::string | |
165 | get_standard_cache_dir () | |
166 | { | |
e6cd1dc1 TT |
167 | #ifdef __APPLE__ |
168 | #define HOME_CACHE_DIR "Library/Caches" | |
169 | #else | |
170 | #define HOME_CACHE_DIR ".cache" | |
171 | #endif | |
172 | ||
173 | #ifndef __APPLE__ | |
b5a9bfbe | 174 | const char *xdg_cache_home = getenv ("XDG_CACHE_HOME"); |
87d6a7aa SM |
175 | if (xdg_cache_home != NULL) |
176 | { | |
177 | /* Make sure the path is absolute and tilde-expanded. */ | |
178 | gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (xdg_cache_home)); | |
179 | return string_printf ("%s/gdb", abs.get ()); | |
180 | } | |
e6cd1dc1 | 181 | #endif |
87d6a7aa | 182 | |
b5a9bfbe | 183 | const char *home = getenv ("HOME"); |
87d6a7aa SM |
184 | if (home != NULL) |
185 | { | |
186 | /* Make sure the path is absolute and tilde-expanded. */ | |
187 | gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (home)); | |
e6cd1dc1 | 188 | return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ()); |
87d6a7aa SM |
189 | } |
190 | ||
191 | return {}; | |
192 | } | |
974e6844 TT |
193 | |
194 | /* See common/pathstuff.h. */ | |
195 | ||
e8d8cce6 SM |
196 | std::string |
197 | get_standard_temp_dir () | |
198 | { | |
199 | #ifdef WIN32 | |
200 | const char *tmp = getenv ("TMP"); | |
201 | if (tmp != nullptr) | |
202 | return tmp; | |
203 | ||
204 | tmp = getenv ("TEMP"); | |
205 | if (tmp != nullptr) | |
206 | return tmp; | |
207 | ||
208 | error (_("Couldn't find temp dir path, both TMP and TEMP are unset.")); | |
209 | ||
210 | #else | |
211 | const char *tmp = getenv ("TMPDIR"); | |
212 | if (tmp != nullptr) | |
213 | return tmp; | |
214 | ||
215 | return "/tmp"; | |
216 | #endif | |
217 | } | |
218 | ||
219 | /* See common/pathstuff.h. */ | |
220 | ||
974e6844 TT |
221 | const char * |
222 | get_shell () | |
223 | { | |
224 | const char *ret = getenv ("SHELL"); | |
225 | if (ret == NULL) | |
226 | ret = "/bin/sh"; | |
227 | ||
228 | return ret; | |
229 | } | |
29be4d9d TT |
230 | |
231 | /* See common/pathstuff.h. */ | |
232 | ||
233 | gdb::char_vector | |
234 | make_temp_filename (const std::string &f) | |
235 | { | |
236 | gdb::char_vector filename_temp (f.length () + 8); | |
237 | strcpy (filename_temp.data (), f.c_str ()); | |
238 | strcat (filename_temp.data () + f.size (), "-XXXXXX"); | |
239 | return filename_temp; | |
240 | } |