Home | History | Annotate | Line # | Download | only in gdbsupport
      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