1 /* Path manipulation routines for GDB and gdbserver.
3 Copyright (C) 1986-2022 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "common-defs.h"
21 #include "pathstuff.h"
22 #include "host-defs.h"
23 #include "filenames.h"
24 #include "gdb_tilde_expand.h"
30 /* See gdbsupport/pathstuff.h. */
32 char *current_directory
;
34 /* See gdbsupport/pathstuff.h. */
36 gdb::unique_xmalloc_ptr
<char>
37 gdb_realpath (const char *filename
)
39 /* On most hosts, we rely on canonicalize_file_name to compute
40 the FILENAME's realpath.
42 But the situation is slightly more complex on Windows, due to some
43 versions of GCC which were reported to generate paths where
44 backlashes (the directory separator) were doubled. For instance:
45 c:\\some\\double\\slashes\\dir
47 c:\some\double\slashes\dir
48 Those double-slashes were getting in the way when comparing paths,
49 for instance when trying to insert a breakpoint as follow:
50 (gdb) b c:/some/double/slashes/dir/foo.c:4
51 No source file named c:/some/double/slashes/dir/foo.c:4.
52 (gdb) b c:\some\double\slashes\dir\foo.c:4
53 No source file named c:\some\double\slashes\dir\foo.c:4.
54 To prevent this from happening, we need this function to always
55 strip those extra backslashes. While canonicalize_file_name does
56 perform this simplification, it only works when the path is valid.
57 Since the simplification would be useful even if the path is not
58 valid (one can always set a breakpoint on a file, even if the file
59 does not exist locally), we rely instead on GetFullPathName to
60 perform the canonicalization. */
65 DWORD len
= GetFullPathName (filename
, MAX_PATH
, buf
, NULL
);
67 /* The file system is case-insensitive but case-preserving.
68 So it is important we do not lowercase the path. Otherwise,
69 we might not be able to display the original casing in a given
71 if (len
> 0 && len
< MAX_PATH
)
72 return make_unique_xstrdup (buf
);
76 char *rp
= canonicalize_file_name (filename
);
79 return gdb::unique_xmalloc_ptr
<char> (rp
);
83 /* This system is a lost cause, just dup the buffer. */
84 return make_unique_xstrdup (filename
);
87 /* See gdbsupport/pathstuff.h. */
89 gdb::unique_xmalloc_ptr
<char>
90 gdb_realpath_keepfile (const char *filename
)
92 const char *base_name
= lbasename (filename
);
96 /* Extract the basename of filename, and return immediately
97 a copy of filename if it does not contain any directory prefix. */
98 if (base_name
== filename
)
99 return make_unique_xstrdup (filename
);
101 dir_name
= (char *) alloca ((size_t) (base_name
- filename
+ 2));
102 /* Allocate enough space to store the dir_name + plus one extra
103 character sometimes needed under Windows (see below), and
104 then the closing \000 character. */
105 strncpy (dir_name
, filename
, base_name
- filename
);
106 dir_name
[base_name
- filename
] = '\000';
108 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
109 /* We need to be careful when filename is of the form 'd:foo', which
110 is equivalent of d:./foo, which is totally different from d:/foo. */
111 if (strlen (dir_name
) == 2 && isalpha (dir_name
[0]) && dir_name
[1] == ':')
114 dir_name
[3] = '\000';
118 /* Canonicalize the directory prefix, and build the resulting
119 filename. If the dirname realpath already contains an ending
120 directory separator, avoid doubling it. */
121 gdb::unique_xmalloc_ptr
<char> path_storage
= gdb_realpath (dir_name
);
122 const char *real_path
= path_storage
.get ();
123 if (IS_DIR_SEPARATOR (real_path
[strlen (real_path
) - 1]))
124 result
= concat (real_path
, base_name
, (char *) NULL
);
126 result
= concat (real_path
, SLASH_STRING
, base_name
, (char *) NULL
);
128 return gdb::unique_xmalloc_ptr
<char> (result
);
131 /* See gdbsupport/pathstuff.h. */
133 gdb::unique_xmalloc_ptr
<char>
134 gdb_abspath (const char *path
)
136 gdb_assert (path
!= NULL
&& path
[0] != '\0');
139 return gdb_tilde_expand_up (path
);
141 if (IS_ABSOLUTE_PATH (path
) || current_directory
== NULL
)
142 return make_unique_xstrdup (path
);
144 /* Beware the // my son, the Emacs barfs, the botch that catch... */
145 return gdb::unique_xmalloc_ptr
<char>
146 (concat (current_directory
,
147 IS_DIR_SEPARATOR (current_directory
[strlen (current_directory
) - 1])
149 path
, (char *) NULL
));
152 /* See gdbsupport/pathstuff.h. */
155 child_path (const char *parent
, const char *child
)
157 /* The child path must start with the parent path. */
158 size_t parent_len
= strlen (parent
);
159 if (filename_ncmp (parent
, child
, parent_len
) != 0)
162 /* The parent path must be a directory and the child must contain at
163 least one component underneath the parent. */
164 const char *child_component
;
165 if (parent_len
> 0 && IS_DIR_SEPARATOR (parent
[parent_len
- 1]))
167 /* The parent path ends in a directory separator, so it is a
168 directory. The first child component starts after the common
170 child_component
= child
+ parent_len
;
174 /* The parent path does not end in a directory separator. The
175 first character in the child after the common prefix must be
176 a directory separator.
178 Note that CHILD must hold at least parent_len characters for
179 filename_ncmp to return zero. If the character at parent_len
180 is nul due to CHILD containing the same path as PARENT, the
181 IS_DIR_SEPARATOR check will fail here. */
182 if (!IS_DIR_SEPARATOR (child
[parent_len
]))
185 /* The first child component starts after the separator after the
187 child_component
= child
+ parent_len
+ 1;
190 /* The child must contain at least one non-separator character after
192 while (*child_component
!= '\0')
194 if (!IS_DIR_SEPARATOR (*child_component
))
195 return child_component
;
202 /* See gdbsupport/pathstuff.h. */
205 contains_dir_separator (const char *path
)
207 for (; *path
!= '\0'; path
++)
209 if (IS_DIR_SEPARATOR (*path
))
216 /* See gdbsupport/pathstuff.h. */
219 get_standard_cache_dir ()
222 #define HOME_CACHE_DIR "Library/Caches"
224 #define HOME_CACHE_DIR ".cache"
228 const char *xdg_cache_home
= getenv ("XDG_CACHE_HOME");
229 if (xdg_cache_home
!= NULL
&& xdg_cache_home
[0] != '\0')
231 /* Make sure the path is absolute and tilde-expanded. */
232 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (xdg_cache_home
));
233 return string_printf ("%s/gdb", abs
.get ());
237 const char *home
= getenv ("HOME");
238 if (home
!= NULL
&& home
[0] != '\0')
240 /* Make sure the path is absolute and tilde-expanded. */
241 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (home
));
242 return string_printf ("%s/" HOME_CACHE_DIR
"/gdb", abs
.get ());
246 const char *win_home
= getenv ("LOCALAPPDATA");
247 if (win_home
!= NULL
&& win_home
[0] != '\0')
249 /* Make sure the path is absolute and tilde-expanded. */
250 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (win_home
));
251 return string_printf ("%s/gdb", abs
.get ());
258 /* See gdbsupport/pathstuff.h. */
261 get_standard_temp_dir ()
264 const char *tmp
= getenv ("TMP");
268 tmp
= getenv ("TEMP");
272 error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
275 const char *tmp
= getenv ("TMPDIR");
283 /* See pathstuff.h. */
286 get_standard_config_dir ()
289 #define HOME_CONFIG_DIR "Library/Preferences"
291 #define HOME_CONFIG_DIR ".config"
295 const char *xdg_config_home
= getenv ("XDG_CONFIG_HOME");
296 if (xdg_config_home
!= NULL
&& xdg_config_home
[0] != '\0')
298 /* Make sure the path is absolute and tilde-expanded. */
299 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (xdg_config_home
));
300 return string_printf ("%s/gdb", abs
.get ());
304 const char *home
= getenv ("HOME");
305 if (home
!= NULL
&& home
[0] != '\0')
307 /* Make sure the path is absolute and tilde-expanded. */
308 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (home
));
309 return string_printf ("%s/" HOME_CONFIG_DIR
"/gdb", abs
.get ());
315 /* See pathstuff.h. */
318 get_standard_config_filename (const char *filename
)
320 std::string config_dir
= get_standard_config_dir ();
321 if (config_dir
!= "")
323 const char *tmp
= (*filename
== '.') ? (filename
+ 1) : filename
;
324 std::string path
= config_dir
+ SLASH_STRING
+ std::string (tmp
);
331 /* See pathstuff.h. */
334 find_gdb_home_config_file (const char *name
, struct stat
*buf
)
336 gdb_assert (name
!= nullptr);
337 gdb_assert (*name
!= '\0');
339 std::string config_dir_file
= get_standard_config_filename (name
);
340 if (!config_dir_file
.empty ())
342 if (stat (config_dir_file
.c_str (), buf
) == 0)
343 return config_dir_file
;
346 const char *homedir
= getenv ("HOME");
347 if (homedir
!= nullptr && homedir
[0] != '\0')
349 /* Make sure the path is absolute and tilde-expanded. */
350 gdb::unique_xmalloc_ptr
<char> abs (gdb_abspath (homedir
));
351 std::string path
= (std::string (abs
.get ()) + SLASH_STRING
352 + std::string (name
));
353 if (stat (path
.c_str (), buf
) == 0)
360 /* See gdbsupport/pathstuff.h. */
365 const char *ret
= getenv ("SHELL");
372 /* See gdbsupport/pathstuff.h. */
375 make_temp_filename (const std::string
&f
)
377 gdb::char_vector
filename_temp (f
.length () + 8);
378 strcpy (filename_temp
.data (), f
.c_str ());
379 strcat (filename_temp
.data () + f
.size (), "-XXXXXX");
380 return filename_temp
;