| 1 | /* Path manipulation routines for GDB and gdbserver. |
| 2 | |
| 3 | Copyright (C) 1986-2020 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 | |
| 26 | #ifdef USE_WIN32API |
| 27 | #include <windows.h> |
| 28 | #endif |
| 29 | |
| 30 | /* See gdbsupport/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 make_unique_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 make_unique_xstrdup (filename); |
| 81 | } |
| 82 | |
| 83 | /* See gdbsupport/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 make_unique_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 gdbsupport/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) || current_directory == NULL) |
| 138 | return make_unique_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 | } |
| 147 | |
| 148 | /* See gdbsupport/pathstuff.h. */ |
| 149 | |
| 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; |
| 161 | if (parent_len > 0 && IS_DIR_SEPARATOR (parent[parent_len - 1])) |
| 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 | |
| 198 | /* See gdbsupport/pathstuff.h. */ |
| 199 | |
| 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 | } |
| 211 | |
| 212 | /* See gdbsupport/pathstuff.h. */ |
| 213 | |
| 214 | std::string |
| 215 | get_standard_cache_dir () |
| 216 | { |
| 217 | #ifdef __APPLE__ |
| 218 | #define HOME_CACHE_DIR "Library/Caches" |
| 219 | #else |
| 220 | #define HOME_CACHE_DIR ".cache" |
| 221 | #endif |
| 222 | |
| 223 | #ifndef __APPLE__ |
| 224 | const char *xdg_cache_home = getenv ("XDG_CACHE_HOME"); |
| 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 | } |
| 231 | #endif |
| 232 | |
| 233 | const char *home = getenv ("HOME"); |
| 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)); |
| 238 | return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ()); |
| 239 | } |
| 240 | |
| 241 | return {}; |
| 242 | } |
| 243 | |
| 244 | /* See gdbsupport/pathstuff.h. */ |
| 245 | |
| 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 | |
| 269 | /* See gdbsupport/pathstuff.h. */ |
| 270 | |
| 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 | } |
| 280 | |
| 281 | /* See gdbsupport/pathstuff.h. */ |
| 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 | } |