18dffb485Schristos /* Path manipulation routines for GDB and gdbserver. 28dffb485Schristos 3*5ba1f45fSchristos Copyright (C) 1986-2024 Free Software Foundation, Inc. 48dffb485Schristos 58dffb485Schristos This file is part of GDB. 68dffb485Schristos 78dffb485Schristos This program is free software; you can redistribute it and/or modify 88dffb485Schristos it under the terms of the GNU General Public License as published by 98dffb485Schristos the Free Software Foundation; either version 3 of the License, or 108dffb485Schristos (at your option) any later version. 118dffb485Schristos 128dffb485Schristos This program is distributed in the hope that it will be useful, 138dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 148dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158dffb485Schristos GNU General Public License for more details. 168dffb485Schristos 178dffb485Schristos You should have received a copy of the GNU General Public License 188dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 198dffb485Schristos 208dffb485Schristos #include "pathstuff.h" 218dffb485Schristos #include "host-defs.h" 228dffb485Schristos #include "filenames.h" 238dffb485Schristos #include "gdb_tilde_expand.h" 248dffb485Schristos 258dffb485Schristos #ifdef USE_WIN32API 268dffb485Schristos #include <windows.h> 278dffb485Schristos #endif 288dffb485Schristos 298dffb485Schristos /* See gdbsupport/pathstuff.h. */ 308dffb485Schristos 314b169a6bSchristos char *current_directory; 324b169a6bSchristos 334b169a6bSchristos /* See gdbsupport/pathstuff.h. */ 344b169a6bSchristos 358dffb485Schristos gdb::unique_xmalloc_ptr<char> 368dffb485Schristos gdb_realpath (const char *filename) 378dffb485Schristos { 388dffb485Schristos /* On most hosts, we rely on canonicalize_file_name to compute 398dffb485Schristos the FILENAME's realpath. 408dffb485Schristos 418dffb485Schristos But the situation is slightly more complex on Windows, due to some 428dffb485Schristos versions of GCC which were reported to generate paths where 43*5ba1f45fSchristos backslashes (the directory separator) were doubled. For instance: 448dffb485Schristos c:\\some\\double\\slashes\\dir 458dffb485Schristos ... instead of ... 468dffb485Schristos c:\some\double\slashes\dir 478dffb485Schristos Those double-slashes were getting in the way when comparing paths, 488dffb485Schristos for instance when trying to insert a breakpoint as follow: 498dffb485Schristos (gdb) b c:/some/double/slashes/dir/foo.c:4 508dffb485Schristos No source file named c:/some/double/slashes/dir/foo.c:4. 518dffb485Schristos (gdb) b c:\some\double\slashes\dir\foo.c:4 528dffb485Schristos No source file named c:\some\double\slashes\dir\foo.c:4. 538dffb485Schristos To prevent this from happening, we need this function to always 548dffb485Schristos strip those extra backslashes. While canonicalize_file_name does 558dffb485Schristos perform this simplification, it only works when the path is valid. 568dffb485Schristos Since the simplification would be useful even if the path is not 578dffb485Schristos valid (one can always set a breakpoint on a file, even if the file 588dffb485Schristos does not exist locally), we rely instead on GetFullPathName to 598dffb485Schristos perform the canonicalization. */ 608dffb485Schristos 618dffb485Schristos #if defined (_WIN32) 628dffb485Schristos { 638dffb485Schristos char buf[MAX_PATH]; 648dffb485Schristos DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL); 658dffb485Schristos 668dffb485Schristos /* The file system is case-insensitive but case-preserving. 678dffb485Schristos So it is important we do not lowercase the path. Otherwise, 688dffb485Schristos we might not be able to display the original casing in a given 698dffb485Schristos path. */ 708dffb485Schristos if (len > 0 && len < MAX_PATH) 718dffb485Schristos return make_unique_xstrdup (buf); 728dffb485Schristos } 738dffb485Schristos #else 748dffb485Schristos { 758dffb485Schristos char *rp = canonicalize_file_name (filename); 768dffb485Schristos 778dffb485Schristos if (rp != NULL) 788dffb485Schristos return gdb::unique_xmalloc_ptr<char> (rp); 798dffb485Schristos } 808dffb485Schristos #endif 818dffb485Schristos 828dffb485Schristos /* This system is a lost cause, just dup the buffer. */ 838dffb485Schristos return make_unique_xstrdup (filename); 848dffb485Schristos } 858dffb485Schristos 868dffb485Schristos /* See gdbsupport/pathstuff.h. */ 878dffb485Schristos 884b169a6bSchristos std::string 898dffb485Schristos gdb_realpath_keepfile (const char *filename) 908dffb485Schristos { 918dffb485Schristos const char *base_name = lbasename (filename); 928dffb485Schristos char *dir_name; 938dffb485Schristos 948dffb485Schristos /* Extract the basename of filename, and return immediately 958dffb485Schristos a copy of filename if it does not contain any directory prefix. */ 968dffb485Schristos if (base_name == filename) 974b169a6bSchristos return filename; 988dffb485Schristos 998dffb485Schristos dir_name = (char *) alloca ((size_t) (base_name - filename + 2)); 1008dffb485Schristos /* Allocate enough space to store the dir_name + plus one extra 1018dffb485Schristos character sometimes needed under Windows (see below), and 1028dffb485Schristos then the closing \000 character. */ 1038dffb485Schristos strncpy (dir_name, filename, base_name - filename); 1048dffb485Schristos dir_name[base_name - filename] = '\000'; 1058dffb485Schristos 1068dffb485Schristos #ifdef HAVE_DOS_BASED_FILE_SYSTEM 1078dffb485Schristos /* We need to be careful when filename is of the form 'd:foo', which 1088dffb485Schristos is equivalent of d:./foo, which is totally different from d:/foo. */ 1098dffb485Schristos if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':') 1108dffb485Schristos { 1118dffb485Schristos dir_name[2] = '.'; 1128dffb485Schristos dir_name[3] = '\000'; 1138dffb485Schristos } 1148dffb485Schristos #endif 1158dffb485Schristos 1168dffb485Schristos /* Canonicalize the directory prefix, and build the resulting 1178dffb485Schristos filename. If the dirname realpath already contains an ending 1188dffb485Schristos directory separator, avoid doubling it. */ 1198dffb485Schristos gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name); 1208dffb485Schristos const char *real_path = path_storage.get (); 1214b169a6bSchristos return path_join (real_path, base_name); 1228dffb485Schristos } 1238dffb485Schristos 1248dffb485Schristos /* See gdbsupport/pathstuff.h. */ 1258dffb485Schristos 1264b169a6bSchristos std::string 1278dffb485Schristos gdb_abspath (const char *path) 1288dffb485Schristos { 1298dffb485Schristos gdb_assert (path != NULL && path[0] != '\0'); 1308dffb485Schristos 1318dffb485Schristos if (path[0] == '~') 1324b169a6bSchristos return gdb_tilde_expand (path); 1338dffb485Schristos 1348dffb485Schristos if (IS_ABSOLUTE_PATH (path) || current_directory == NULL) 1354b169a6bSchristos return path; 1368dffb485Schristos 1374b169a6bSchristos return path_join (current_directory, path); 1388dffb485Schristos } 1398dffb485Schristos 1408dffb485Schristos /* See gdbsupport/pathstuff.h. */ 1418dffb485Schristos 1428dffb485Schristos const char * 1438dffb485Schristos child_path (const char *parent, const char *child) 1448dffb485Schristos { 1458dffb485Schristos /* The child path must start with the parent path. */ 1468dffb485Schristos size_t parent_len = strlen (parent); 1478dffb485Schristos if (filename_ncmp (parent, child, parent_len) != 0) 1488dffb485Schristos return NULL; 1498dffb485Schristos 1508dffb485Schristos /* The parent path must be a directory and the child must contain at 1518dffb485Schristos least one component underneath the parent. */ 1528dffb485Schristos const char *child_component; 1538dffb485Schristos if (parent_len > 0 && IS_DIR_SEPARATOR (parent[parent_len - 1])) 1548dffb485Schristos { 1558dffb485Schristos /* The parent path ends in a directory separator, so it is a 1568dffb485Schristos directory. The first child component starts after the common 1578dffb485Schristos prefix. */ 1588dffb485Schristos child_component = child + parent_len; 1598dffb485Schristos } 1608dffb485Schristos else 1618dffb485Schristos { 1628dffb485Schristos /* The parent path does not end in a directory separator. The 1638dffb485Schristos first character in the child after the common prefix must be 1648dffb485Schristos a directory separator. 1658dffb485Schristos 1668dffb485Schristos Note that CHILD must hold at least parent_len characters for 1678dffb485Schristos filename_ncmp to return zero. If the character at parent_len 1688dffb485Schristos is nul due to CHILD containing the same path as PARENT, the 1698dffb485Schristos IS_DIR_SEPARATOR check will fail here. */ 1708dffb485Schristos if (!IS_DIR_SEPARATOR (child[parent_len])) 1718dffb485Schristos return NULL; 1728dffb485Schristos 1738dffb485Schristos /* The first child component starts after the separator after the 1748dffb485Schristos common prefix. */ 1758dffb485Schristos child_component = child + parent_len + 1; 1768dffb485Schristos } 1778dffb485Schristos 1788dffb485Schristos /* The child must contain at least one non-separator character after 1798dffb485Schristos the parent. */ 1808dffb485Schristos while (*child_component != '\0') 1818dffb485Schristos { 1828dffb485Schristos if (!IS_DIR_SEPARATOR (*child_component)) 1838dffb485Schristos return child_component; 1848dffb485Schristos 1858dffb485Schristos child_component++; 1868dffb485Schristos } 1878dffb485Schristos return NULL; 1888dffb485Schristos } 1898dffb485Schristos 1908dffb485Schristos /* See gdbsupport/pathstuff.h. */ 1918dffb485Schristos 1924b169a6bSchristos std::string 1934b169a6bSchristos path_join (gdb::array_view<const char *> paths) 1944b169a6bSchristos { 1954b169a6bSchristos std::string ret; 1964b169a6bSchristos 1974b169a6bSchristos for (int i = 0; i < paths.size (); ++i) 1984b169a6bSchristos { 1994b169a6bSchristos const char *path = paths[i]; 2004b169a6bSchristos 2014b169a6bSchristos if (i > 0) 2024b169a6bSchristos gdb_assert (strlen (path) == 0 || !IS_ABSOLUTE_PATH (path)); 2034b169a6bSchristos 2044b169a6bSchristos if (!ret.empty () && !IS_DIR_SEPARATOR (ret.back ())) 2054b169a6bSchristos ret += '/'; 2064b169a6bSchristos 2074b169a6bSchristos ret.append (path); 2084b169a6bSchristos } 2094b169a6bSchristos 2104b169a6bSchristos return ret; 2114b169a6bSchristos } 2124b169a6bSchristos 2134b169a6bSchristos /* See gdbsupport/pathstuff.h. */ 2144b169a6bSchristos 2158dffb485Schristos bool 2168dffb485Schristos contains_dir_separator (const char *path) 2178dffb485Schristos { 2188dffb485Schristos for (; *path != '\0'; path++) 2198dffb485Schristos { 2208dffb485Schristos if (IS_DIR_SEPARATOR (*path)) 2218dffb485Schristos return true; 2228dffb485Schristos } 2238dffb485Schristos 2248dffb485Schristos return false; 2258dffb485Schristos } 2268dffb485Schristos 2278dffb485Schristos /* See gdbsupport/pathstuff.h. */ 2288dffb485Schristos 2298dffb485Schristos std::string 2308dffb485Schristos get_standard_cache_dir () 2318dffb485Schristos { 2328dffb485Schristos #ifdef __APPLE__ 2338dffb485Schristos #define HOME_CACHE_DIR "Library/Caches" 2348dffb485Schristos #else 2358dffb485Schristos #define HOME_CACHE_DIR ".cache" 2368dffb485Schristos #endif 2378dffb485Schristos 2388dffb485Schristos #ifndef __APPLE__ 2398dffb485Schristos const char *xdg_cache_home = getenv ("XDG_CACHE_HOME"); 2404b169a6bSchristos if (xdg_cache_home != NULL && xdg_cache_home[0] != '\0') 2418dffb485Schristos { 2428dffb485Schristos /* Make sure the path is absolute and tilde-expanded. */ 2434b169a6bSchristos std::string abs = gdb_abspath (xdg_cache_home); 2444b169a6bSchristos return path_join (abs.c_str (), "gdb"); 2458dffb485Schristos } 2468dffb485Schristos #endif 2478dffb485Schristos 2488dffb485Schristos const char *home = getenv ("HOME"); 2494b169a6bSchristos if (home != NULL && home[0] != '\0') 2508dffb485Schristos { 2518dffb485Schristos /* Make sure the path is absolute and tilde-expanded. */ 2524b169a6bSchristos std::string abs = gdb_abspath (home); 2534b169a6bSchristos return path_join (abs.c_str (), HOME_CACHE_DIR, "gdb"); 2548dffb485Schristos } 2558dffb485Schristos 2564b169a6bSchristos #ifdef WIN32 2574b169a6bSchristos const char *win_home = getenv ("LOCALAPPDATA"); 2584b169a6bSchristos if (win_home != NULL && win_home[0] != '\0') 2594b169a6bSchristos { 2604b169a6bSchristos /* Make sure the path is absolute and tilde-expanded. */ 2614b169a6bSchristos std::string abs = gdb_abspath (win_home); 2624b169a6bSchristos return path_join (abs.c_str (), "gdb"); 2634b169a6bSchristos } 2644b169a6bSchristos #endif 2654b169a6bSchristos 2668dffb485Schristos return {}; 2678dffb485Schristos } 2688dffb485Schristos 2698dffb485Schristos /* See gdbsupport/pathstuff.h. */ 2708dffb485Schristos 2718dffb485Schristos std::string 2728dffb485Schristos get_standard_temp_dir () 2738dffb485Schristos { 2748dffb485Schristos #ifdef WIN32 2758dffb485Schristos const char *tmp = getenv ("TMP"); 2768dffb485Schristos if (tmp != nullptr) 2778dffb485Schristos return tmp; 2788dffb485Schristos 2798dffb485Schristos tmp = getenv ("TEMP"); 2808dffb485Schristos if (tmp != nullptr) 2818dffb485Schristos return tmp; 2828dffb485Schristos 2838dffb485Schristos error (_("Couldn't find temp dir path, both TMP and TEMP are unset.")); 2848dffb485Schristos 2858dffb485Schristos #else 2868dffb485Schristos const char *tmp = getenv ("TMPDIR"); 2878dffb485Schristos if (tmp != nullptr) 2888dffb485Schristos return tmp; 2898dffb485Schristos 2908dffb485Schristos return "/tmp"; 2918dffb485Schristos #endif 2928dffb485Schristos } 2938dffb485Schristos 2944b169a6bSchristos /* See pathstuff.h. */ 2954b169a6bSchristos 2964b169a6bSchristos std::string 2974b169a6bSchristos get_standard_config_dir () 2984b169a6bSchristos { 2994b169a6bSchristos #ifdef __APPLE__ 3004b169a6bSchristos #define HOME_CONFIG_DIR "Library/Preferences" 3014b169a6bSchristos #else 3024b169a6bSchristos #define HOME_CONFIG_DIR ".config" 3034b169a6bSchristos #endif 3044b169a6bSchristos 3054b169a6bSchristos #ifndef __APPLE__ 3064b169a6bSchristos const char *xdg_config_home = getenv ("XDG_CONFIG_HOME"); 3074b169a6bSchristos if (xdg_config_home != NULL && xdg_config_home[0] != '\0') 3084b169a6bSchristos { 3094b169a6bSchristos /* Make sure the path is absolute and tilde-expanded. */ 3104b169a6bSchristos std::string abs = gdb_abspath (xdg_config_home); 3114b169a6bSchristos return path_join (abs.c_str (), "gdb"); 3124b169a6bSchristos } 3134b169a6bSchristos #endif 3144b169a6bSchristos 3154b169a6bSchristos const char *home = getenv ("HOME"); 3164b169a6bSchristos if (home != NULL && home[0] != '\0') 3174b169a6bSchristos { 3184b169a6bSchristos /* Make sure the path is absolute and tilde-expanded. */ 3194b169a6bSchristos std::string abs = gdb_abspath (home); 3204b169a6bSchristos return path_join (abs.c_str (), HOME_CONFIG_DIR, "gdb"); 3214b169a6bSchristos } 3224b169a6bSchristos 3234b169a6bSchristos return {}; 3244b169a6bSchristos } 3254b169a6bSchristos 3264b169a6bSchristos /* See pathstuff.h. */ 3274b169a6bSchristos 3284b169a6bSchristos std::string 3294b169a6bSchristos get_standard_config_filename (const char *filename) 3304b169a6bSchristos { 3314b169a6bSchristos std::string config_dir = get_standard_config_dir (); 3324b169a6bSchristos if (config_dir != "") 3334b169a6bSchristos { 3344b169a6bSchristos const char *tmp = (*filename == '.') ? (filename + 1) : filename; 3354b169a6bSchristos std::string path = config_dir + SLASH_STRING + std::string (tmp); 3364b169a6bSchristos return path; 3374b169a6bSchristos } 3384b169a6bSchristos 3394b169a6bSchristos return {}; 3404b169a6bSchristos } 3414b169a6bSchristos 3424b169a6bSchristos /* See pathstuff.h. */ 3434b169a6bSchristos 3444b169a6bSchristos std::string 3454b169a6bSchristos find_gdb_home_config_file (const char *name, struct stat *buf) 3464b169a6bSchristos { 3474b169a6bSchristos gdb_assert (name != nullptr); 3484b169a6bSchristos gdb_assert (*name != '\0'); 3494b169a6bSchristos 3504b169a6bSchristos std::string config_dir_file = get_standard_config_filename (name); 3514b169a6bSchristos if (!config_dir_file.empty ()) 3524b169a6bSchristos { 3534b169a6bSchristos if (stat (config_dir_file.c_str (), buf) == 0) 3544b169a6bSchristos return config_dir_file; 3554b169a6bSchristos } 3564b169a6bSchristos 3574b169a6bSchristos const char *homedir = getenv ("HOME"); 3584b169a6bSchristos if (homedir != nullptr && homedir[0] != '\0') 3594b169a6bSchristos { 3604b169a6bSchristos /* Make sure the path is absolute and tilde-expanded. */ 3614b169a6bSchristos std::string abs = gdb_abspath (homedir); 3624b169a6bSchristos std::string path = string_printf ("%s/%s", abs.c_str (), name); 3634b169a6bSchristos if (stat (path.c_str (), buf) == 0) 3644b169a6bSchristos return path; 3654b169a6bSchristos } 3664b169a6bSchristos 3674b169a6bSchristos return {}; 3684b169a6bSchristos } 3694b169a6bSchristos 3708dffb485Schristos /* See gdbsupport/pathstuff.h. */ 3718dffb485Schristos 3728dffb485Schristos const char * 3738dffb485Schristos get_shell () 3748dffb485Schristos { 3758dffb485Schristos const char *ret = getenv ("SHELL"); 3768dffb485Schristos if (ret == NULL) 3778dffb485Schristos ret = "/bin/sh"; 3788dffb485Schristos 3798dffb485Schristos return ret; 3808dffb485Schristos } 3818dffb485Schristos 3828dffb485Schristos /* See gdbsupport/pathstuff.h. */ 3838dffb485Schristos 3848dffb485Schristos gdb::char_vector 3858dffb485Schristos make_temp_filename (const std::string &f) 3868dffb485Schristos { 3878dffb485Schristos gdb::char_vector filename_temp (f.length () + 8); 3888dffb485Schristos strcpy (filename_temp.data (), f.c_str ()); 3898dffb485Schristos strcat (filename_temp.data () + f.size (), "-XXXXXX"); 3908dffb485Schristos return filename_temp; 3918dffb485Schristos } 392