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