Home | History | Annotate | Line # | Download | only in gdbsupport
pathstuff.cc revision 1.1.1.2.2.1
      1          1.1  christos /* Path manipulation routines for GDB and gdbserver.
      2          1.1  christos 
      3  1.1.1.2.2.1  perseant    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.2.2.1  perseant    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  christos gdb_abspath (const char *path)
    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  christos   if (IS_ABSOLUTE_PATH (path) || current_directory == NULL)
    135      1.1.1.2  christos     return path;
    136          1.1  christos 
    137      1.1.1.2  christos   return path_join (current_directory, 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.2  christos       if (i > 0)
    202      1.1.1.2  christos 	gdb_assert (strlen (path) == 0 || !IS_ABSOLUTE_PATH (path));
    203      1.1.1.2  christos 
    204      1.1.1.2  christos       if (!ret.empty () && !IS_DIR_SEPARATOR (ret.back ()))
    205      1.1.1.2  christos 	  ret += '/';
    206      1.1.1.2  christos 
    207      1.1.1.2  christos       ret.append (path);
    208      1.1.1.2  christos     }
    209      1.1.1.2  christos 
    210      1.1.1.2  christos   return ret;
    211      1.1.1.2  christos }
    212      1.1.1.2  christos 
    213      1.1.1.2  christos /* See gdbsupport/pathstuff.h.  */
    214      1.1.1.2  christos 
    215          1.1  christos bool
    216          1.1  christos contains_dir_separator (const char *path)
    217          1.1  christos {
    218          1.1  christos   for (; *path != '\0'; path++)
    219          1.1  christos     {
    220          1.1  christos       if (IS_DIR_SEPARATOR (*path))
    221          1.1  christos 	return true;
    222          1.1  christos     }
    223          1.1  christos 
    224          1.1  christos   return false;
    225          1.1  christos }
    226          1.1  christos 
    227          1.1  christos /* See gdbsupport/pathstuff.h.  */
    228          1.1  christos 
    229          1.1  christos std::string
    230          1.1  christos get_standard_cache_dir ()
    231          1.1  christos {
    232          1.1  christos #ifdef __APPLE__
    233          1.1  christos #define HOME_CACHE_DIR "Library/Caches"
    234          1.1  christos #else
    235          1.1  christos #define HOME_CACHE_DIR ".cache"
    236          1.1  christos #endif
    237          1.1  christos 
    238          1.1  christos #ifndef __APPLE__
    239          1.1  christos   const char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
    240      1.1.1.2  christos   if (xdg_cache_home != NULL && xdg_cache_home[0] != '\0')
    241          1.1  christos     {
    242          1.1  christos       /* Make sure the path is absolute and tilde-expanded.  */
    243      1.1.1.2  christos       std::string abs = gdb_abspath (xdg_cache_home);
    244      1.1.1.2  christos       return path_join (abs.c_str (), "gdb");
    245          1.1  christos     }
    246          1.1  christos #endif
    247          1.1  christos 
    248          1.1  christos   const char *home = getenv ("HOME");
    249      1.1.1.2  christos   if (home != NULL && home[0] != '\0')
    250      1.1.1.2  christos     {
    251      1.1.1.2  christos       /* Make sure the path is absolute and tilde-expanded.  */
    252      1.1.1.2  christos       std::string abs = gdb_abspath (home);
    253      1.1.1.2  christos       return path_join (abs.c_str (), HOME_CACHE_DIR,  "gdb");
    254      1.1.1.2  christos     }
    255      1.1.1.2  christos 
    256      1.1.1.2  christos #ifdef WIN32
    257      1.1.1.2  christos   const char *win_home = getenv ("LOCALAPPDATA");
    258      1.1.1.2  christos   if (win_home != NULL && win_home[0] != '\0')
    259          1.1  christos     {
    260          1.1  christos       /* Make sure the path is absolute and tilde-expanded.  */
    261      1.1.1.2  christos       std::string abs = gdb_abspath (win_home);
    262      1.1.1.2  christos       return path_join (abs.c_str (), "gdb");
    263          1.1  christos     }
    264      1.1.1.2  christos #endif
    265          1.1  christos 
    266          1.1  christos   return {};
    267          1.1  christos }
    268          1.1  christos 
    269          1.1  christos /* See gdbsupport/pathstuff.h.  */
    270          1.1  christos 
    271          1.1  christos std::string
    272          1.1  christos get_standard_temp_dir ()
    273          1.1  christos {
    274          1.1  christos #ifdef WIN32
    275          1.1  christos   const char *tmp = getenv ("TMP");
    276          1.1  christos   if (tmp != nullptr)
    277          1.1  christos     return tmp;
    278          1.1  christos 
    279          1.1  christos   tmp = getenv ("TEMP");
    280          1.1  christos   if (tmp != nullptr)
    281          1.1  christos     return tmp;
    282          1.1  christos 
    283          1.1  christos   error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
    284          1.1  christos 
    285          1.1  christos #else
    286          1.1  christos   const char *tmp = getenv ("TMPDIR");
    287          1.1  christos   if (tmp != nullptr)
    288          1.1  christos     return tmp;
    289          1.1  christos 
    290          1.1  christos   return "/tmp";
    291          1.1  christos #endif
    292          1.1  christos }
    293          1.1  christos 
    294      1.1.1.2  christos /* See pathstuff.h.  */
    295      1.1.1.2  christos 
    296      1.1.1.2  christos std::string
    297      1.1.1.2  christos get_standard_config_dir ()
    298      1.1.1.2  christos {
    299      1.1.1.2  christos #ifdef __APPLE__
    300      1.1.1.2  christos #define HOME_CONFIG_DIR "Library/Preferences"
    301      1.1.1.2  christos #else
    302      1.1.1.2  christos #define HOME_CONFIG_DIR ".config"
    303      1.1.1.2  christos #endif
    304      1.1.1.2  christos 
    305      1.1.1.2  christos #ifndef __APPLE__
    306      1.1.1.2  christos   const char *xdg_config_home = getenv ("XDG_CONFIG_HOME");
    307      1.1.1.2  christos   if (xdg_config_home != NULL && xdg_config_home[0] != '\0')
    308      1.1.1.2  christos     {
    309      1.1.1.2  christos       /* Make sure the path is absolute and tilde-expanded.  */
    310      1.1.1.2  christos       std::string abs = gdb_abspath (xdg_config_home);
    311      1.1.1.2  christos       return path_join (abs.c_str (), "gdb");
    312      1.1.1.2  christos     }
    313      1.1.1.2  christos #endif
    314      1.1.1.2  christos 
    315      1.1.1.2  christos   const char *home = getenv ("HOME");
    316      1.1.1.2  christos   if (home != NULL && home[0] != '\0')
    317      1.1.1.2  christos     {
    318      1.1.1.2  christos       /* Make sure the path is absolute and tilde-expanded.  */
    319      1.1.1.2  christos       std::string abs = gdb_abspath (home);
    320      1.1.1.2  christos       return path_join (abs.c_str (), HOME_CONFIG_DIR, "gdb");
    321      1.1.1.2  christos     }
    322      1.1.1.2  christos 
    323      1.1.1.2  christos   return {};
    324      1.1.1.2  christos }
    325      1.1.1.2  christos 
    326      1.1.1.2  christos /* See pathstuff.h. */
    327      1.1.1.2  christos 
    328      1.1.1.2  christos std::string
    329      1.1.1.2  christos get_standard_config_filename (const char *filename)
    330      1.1.1.2  christos {
    331      1.1.1.2  christos   std::string config_dir = get_standard_config_dir ();
    332      1.1.1.2  christos   if (config_dir != "")
    333      1.1.1.2  christos     {
    334      1.1.1.2  christos       const char *tmp = (*filename == '.') ? (filename + 1) : filename;
    335      1.1.1.2  christos       std::string path = config_dir + SLASH_STRING + std::string (tmp);
    336      1.1.1.2  christos       return path;
    337      1.1.1.2  christos     }
    338      1.1.1.2  christos 
    339      1.1.1.2  christos   return {};
    340      1.1.1.2  christos }
    341      1.1.1.2  christos 
    342      1.1.1.2  christos /* See pathstuff.h.  */
    343      1.1.1.2  christos 
    344      1.1.1.2  christos std::string
    345      1.1.1.2  christos find_gdb_home_config_file (const char *name, struct stat *buf)
    346      1.1.1.2  christos {
    347      1.1.1.2  christos   gdb_assert (name != nullptr);
    348      1.1.1.2  christos   gdb_assert (*name != '\0');
    349      1.1.1.2  christos 
    350      1.1.1.2  christos   std::string config_dir_file = get_standard_config_filename (name);
    351      1.1.1.2  christos   if (!config_dir_file.empty ())
    352      1.1.1.2  christos     {
    353      1.1.1.2  christos       if (stat (config_dir_file.c_str (), buf) == 0)
    354      1.1.1.2  christos 	return config_dir_file;
    355      1.1.1.2  christos     }
    356      1.1.1.2  christos 
    357      1.1.1.2  christos   const char *homedir = getenv ("HOME");
    358      1.1.1.2  christos   if (homedir != nullptr && homedir[0] != '\0')
    359      1.1.1.2  christos     {
    360      1.1.1.2  christos       /* Make sure the path is absolute and tilde-expanded.  */
    361      1.1.1.2  christos       std::string abs = gdb_abspath (homedir);
    362      1.1.1.2  christos       std::string path = string_printf ("%s/%s", abs.c_str (), name);
    363      1.1.1.2  christos       if (stat (path.c_str (), buf) == 0)
    364      1.1.1.2  christos 	return path;
    365      1.1.1.2  christos     }
    366      1.1.1.2  christos 
    367      1.1.1.2  christos   return {};
    368      1.1.1.2  christos }
    369      1.1.1.2  christos 
    370          1.1  christos /* See gdbsupport/pathstuff.h.  */
    371          1.1  christos 
    372          1.1  christos const char *
    373          1.1  christos get_shell ()
    374          1.1  christos {
    375          1.1  christos   const char *ret = getenv ("SHELL");
    376          1.1  christos   if (ret == NULL)
    377          1.1  christos     ret = "/bin/sh";
    378          1.1  christos 
    379          1.1  christos   return ret;
    380          1.1  christos }
    381          1.1  christos 
    382          1.1  christos /* See gdbsupport/pathstuff.h.  */
    383          1.1  christos 
    384          1.1  christos gdb::char_vector
    385          1.1  christos make_temp_filename (const std::string &f)
    386          1.1  christos {
    387          1.1  christos   gdb::char_vector filename_temp (f.length () + 8);
    388          1.1  christos   strcpy (filename_temp.data (), f.c_str ());
    389          1.1  christos   strcat (filename_temp.data () + f.size (), "-XXXXXX");
    390          1.1  christos   return filename_temp;
    391          1.1  christos }
    392