Home | History | Annotate | Line # | Download | only in gdbsupport
pathstuff.cc revision 1.1.1.1
      1  1.1  christos /* Path manipulation routines for GDB and gdbserver.
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 1986-2020 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 "common-defs.h"
     21  1.1  christos #include "pathstuff.h"
     22  1.1  christos #include "host-defs.h"
     23  1.1  christos #include "filenames.h"
     24  1.1  christos #include "gdb_tilde_expand.h"
     25  1.1  christos 
     26  1.1  christos #ifdef USE_WIN32API
     27  1.1  christos #include <windows.h>
     28  1.1  christos #endif
     29  1.1  christos 
     30  1.1  christos /* See gdbsupport/pathstuff.h.  */
     31  1.1  christos 
     32  1.1  christos gdb::unique_xmalloc_ptr<char>
     33  1.1  christos gdb_realpath (const char *filename)
     34  1.1  christos {
     35  1.1  christos /* On most hosts, we rely on canonicalize_file_name to compute
     36  1.1  christos    the FILENAME's realpath.
     37  1.1  christos 
     38  1.1  christos    But the situation is slightly more complex on Windows, due to some
     39  1.1  christos    versions of GCC which were reported to generate paths where
     40  1.1  christos    backlashes (the directory separator) were doubled.  For instance:
     41  1.1  christos       c:\\some\\double\\slashes\\dir
     42  1.1  christos    ... instead of ...
     43  1.1  christos       c:\some\double\slashes\dir
     44  1.1  christos    Those double-slashes were getting in the way when comparing paths,
     45  1.1  christos    for instance when trying to insert a breakpoint as follow:
     46  1.1  christos       (gdb) b c:/some/double/slashes/dir/foo.c:4
     47  1.1  christos       No source file named c:/some/double/slashes/dir/foo.c:4.
     48  1.1  christos       (gdb) b c:\some\double\slashes\dir\foo.c:4
     49  1.1  christos       No source file named c:\some\double\slashes\dir\foo.c:4.
     50  1.1  christos    To prevent this from happening, we need this function to always
     51  1.1  christos    strip those extra backslashes.  While canonicalize_file_name does
     52  1.1  christos    perform this simplification, it only works when the path is valid.
     53  1.1  christos    Since the simplification would be useful even if the path is not
     54  1.1  christos    valid (one can always set a breakpoint on a file, even if the file
     55  1.1  christos    does not exist locally), we rely instead on GetFullPathName to
     56  1.1  christos    perform the canonicalization.  */
     57  1.1  christos 
     58  1.1  christos #if defined (_WIN32)
     59  1.1  christos   {
     60  1.1  christos     char buf[MAX_PATH];
     61  1.1  christos     DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
     62  1.1  christos 
     63  1.1  christos     /* The file system is case-insensitive but case-preserving.
     64  1.1  christos        So it is important we do not lowercase the path.  Otherwise,
     65  1.1  christos        we might not be able to display the original casing in a given
     66  1.1  christos        path.  */
     67  1.1  christos     if (len > 0 && len < MAX_PATH)
     68  1.1  christos       return make_unique_xstrdup (buf);
     69  1.1  christos   }
     70  1.1  christos #else
     71  1.1  christos   {
     72  1.1  christos     char *rp = canonicalize_file_name (filename);
     73  1.1  christos 
     74  1.1  christos     if (rp != NULL)
     75  1.1  christos       return gdb::unique_xmalloc_ptr<char> (rp);
     76  1.1  christos   }
     77  1.1  christos #endif
     78  1.1  christos 
     79  1.1  christos   /* This system is a lost cause, just dup the buffer.  */
     80  1.1  christos   return make_unique_xstrdup (filename);
     81  1.1  christos }
     82  1.1  christos 
     83  1.1  christos /* See gdbsupport/pathstuff.h.  */
     84  1.1  christos 
     85  1.1  christos gdb::unique_xmalloc_ptr<char>
     86  1.1  christos gdb_realpath_keepfile (const char *filename)
     87  1.1  christos {
     88  1.1  christos   const char *base_name = lbasename (filename);
     89  1.1  christos   char *dir_name;
     90  1.1  christos   char *result;
     91  1.1  christos 
     92  1.1  christos   /* Extract the basename of filename, and return immediately
     93  1.1  christos      a copy of filename if it does not contain any directory prefix.  */
     94  1.1  christos   if (base_name == filename)
     95  1.1  christos     return make_unique_xstrdup (filename);
     96  1.1  christos 
     97  1.1  christos   dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
     98  1.1  christos   /* Allocate enough space to store the dir_name + plus one extra
     99  1.1  christos      character sometimes needed under Windows (see below), and
    100  1.1  christos      then the closing \000 character.  */
    101  1.1  christos   strncpy (dir_name, filename, base_name - filename);
    102  1.1  christos   dir_name[base_name - filename] = '\000';
    103  1.1  christos 
    104  1.1  christos #ifdef HAVE_DOS_BASED_FILE_SYSTEM
    105  1.1  christos   /* We need to be careful when filename is of the form 'd:foo', which
    106  1.1  christos      is equivalent of d:./foo, which is totally different from d:/foo.  */
    107  1.1  christos   if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
    108  1.1  christos     {
    109  1.1  christos       dir_name[2] = '.';
    110  1.1  christos       dir_name[3] = '\000';
    111  1.1  christos     }
    112  1.1  christos #endif
    113  1.1  christos 
    114  1.1  christos   /* Canonicalize the directory prefix, and build the resulting
    115  1.1  christos      filename.  If the dirname realpath already contains an ending
    116  1.1  christos      directory separator, avoid doubling it.  */
    117  1.1  christos   gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
    118  1.1  christos   const char *real_path = path_storage.get ();
    119  1.1  christos   if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
    120  1.1  christos     result = concat (real_path, base_name, (char *) NULL);
    121  1.1  christos   else
    122  1.1  christos     result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
    123  1.1  christos 
    124  1.1  christos   return gdb::unique_xmalloc_ptr<char> (result);
    125  1.1  christos }
    126  1.1  christos 
    127  1.1  christos /* See gdbsupport/pathstuff.h.  */
    128  1.1  christos 
    129  1.1  christos gdb::unique_xmalloc_ptr<char>
    130  1.1  christos gdb_abspath (const char *path)
    131  1.1  christos {
    132  1.1  christos   gdb_assert (path != NULL && path[0] != '\0');
    133  1.1  christos 
    134  1.1  christos   if (path[0] == '~')
    135  1.1  christos     return gdb_tilde_expand_up (path);
    136  1.1  christos 
    137  1.1  christos   if (IS_ABSOLUTE_PATH (path) || current_directory == NULL)
    138  1.1  christos     return make_unique_xstrdup (path);
    139  1.1  christos 
    140  1.1  christos   /* Beware the // my son, the Emacs barfs, the botch that catch...  */
    141  1.1  christos   return gdb::unique_xmalloc_ptr<char>
    142  1.1  christos     (concat (current_directory,
    143  1.1  christos 	     IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
    144  1.1  christos 	     ? "" : SLASH_STRING,
    145  1.1  christos 	     path, (char *) NULL));
    146  1.1  christos }
    147  1.1  christos 
    148  1.1  christos /* See gdbsupport/pathstuff.h.  */
    149  1.1  christos 
    150  1.1  christos const char *
    151  1.1  christos child_path (const char *parent, const char *child)
    152  1.1  christos {
    153  1.1  christos   /* The child path must start with the parent path.  */
    154  1.1  christos   size_t parent_len = strlen (parent);
    155  1.1  christos   if (filename_ncmp (parent, child, parent_len) != 0)
    156  1.1  christos     return NULL;
    157  1.1  christos 
    158  1.1  christos   /* The parent path must be a directory and the child must contain at
    159  1.1  christos      least one component underneath the parent.  */
    160  1.1  christos   const char *child_component;
    161  1.1  christos   if (parent_len > 0 && IS_DIR_SEPARATOR (parent[parent_len - 1]))
    162  1.1  christos     {
    163  1.1  christos       /* The parent path ends in a directory separator, so it is a
    164  1.1  christos 	 directory.  The first child component starts after the common
    165  1.1  christos 	 prefix.  */
    166  1.1  christos       child_component = child + parent_len;
    167  1.1  christos     }
    168  1.1  christos   else
    169  1.1  christos     {
    170  1.1  christos       /* The parent path does not end in a directory separator.  The
    171  1.1  christos 	 first character in the child after the common prefix must be
    172  1.1  christos 	 a directory separator.
    173  1.1  christos 
    174  1.1  christos 	 Note that CHILD must hold at least parent_len characters for
    175  1.1  christos 	 filename_ncmp to return zero.  If the character at parent_len
    176  1.1  christos 	 is nul due to CHILD containing the same path as PARENT, the
    177  1.1  christos 	 IS_DIR_SEPARATOR check will fail here.  */
    178  1.1  christos       if (!IS_DIR_SEPARATOR (child[parent_len]))
    179  1.1  christos 	return NULL;
    180  1.1  christos 
    181  1.1  christos       /* The first child component starts after the separator after the
    182  1.1  christos 	 common prefix.  */
    183  1.1  christos       child_component = child + parent_len + 1;
    184  1.1  christos     }
    185  1.1  christos 
    186  1.1  christos   /* The child must contain at least one non-separator character after
    187  1.1  christos      the parent.  */
    188  1.1  christos   while (*child_component != '\0')
    189  1.1  christos     {
    190  1.1  christos       if (!IS_DIR_SEPARATOR (*child_component))
    191  1.1  christos 	return child_component;
    192  1.1  christos 
    193  1.1  christos       child_component++;
    194  1.1  christos     }
    195  1.1  christos   return NULL;
    196  1.1  christos }
    197  1.1  christos 
    198  1.1  christos /* See gdbsupport/pathstuff.h.  */
    199  1.1  christos 
    200  1.1  christos bool
    201  1.1  christos contains_dir_separator (const char *path)
    202  1.1  christos {
    203  1.1  christos   for (; *path != '\0'; path++)
    204  1.1  christos     {
    205  1.1  christos       if (IS_DIR_SEPARATOR (*path))
    206  1.1  christos 	return true;
    207  1.1  christos     }
    208  1.1  christos 
    209  1.1  christos   return false;
    210  1.1  christos }
    211  1.1  christos 
    212  1.1  christos /* See gdbsupport/pathstuff.h.  */
    213  1.1  christos 
    214  1.1  christos std::string
    215  1.1  christos get_standard_cache_dir ()
    216  1.1  christos {
    217  1.1  christos #ifdef __APPLE__
    218  1.1  christos #define HOME_CACHE_DIR "Library/Caches"
    219  1.1  christos #else
    220  1.1  christos #define HOME_CACHE_DIR ".cache"
    221  1.1  christos #endif
    222  1.1  christos 
    223  1.1  christos #ifndef __APPLE__
    224  1.1  christos   const char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
    225  1.1  christos   if (xdg_cache_home != NULL)
    226  1.1  christos     {
    227  1.1  christos       /* Make sure the path is absolute and tilde-expanded.  */
    228  1.1  christos       gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (xdg_cache_home));
    229  1.1  christos       return string_printf ("%s/gdb", abs.get ());
    230  1.1  christos     }
    231  1.1  christos #endif
    232  1.1  christos 
    233  1.1  christos   const char *home = getenv ("HOME");
    234  1.1  christos   if (home != NULL)
    235  1.1  christos     {
    236  1.1  christos       /* Make sure the path is absolute and tilde-expanded.  */
    237  1.1  christos       gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (home));
    238  1.1  christos       return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ());
    239  1.1  christos     }
    240  1.1  christos 
    241  1.1  christos   return {};
    242  1.1  christos }
    243  1.1  christos 
    244  1.1  christos /* See gdbsupport/pathstuff.h.  */
    245  1.1  christos 
    246  1.1  christos std::string
    247  1.1  christos get_standard_temp_dir ()
    248  1.1  christos {
    249  1.1  christos #ifdef WIN32
    250  1.1  christos   const char *tmp = getenv ("TMP");
    251  1.1  christos   if (tmp != nullptr)
    252  1.1  christos     return tmp;
    253  1.1  christos 
    254  1.1  christos   tmp = getenv ("TEMP");
    255  1.1  christos   if (tmp != nullptr)
    256  1.1  christos     return tmp;
    257  1.1  christos 
    258  1.1  christos   error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
    259  1.1  christos 
    260  1.1  christos #else
    261  1.1  christos   const char *tmp = getenv ("TMPDIR");
    262  1.1  christos   if (tmp != nullptr)
    263  1.1  christos     return tmp;
    264  1.1  christos 
    265  1.1  christos   return "/tmp";
    266  1.1  christos #endif
    267  1.1  christos }
    268  1.1  christos 
    269  1.1  christos /* See gdbsupport/pathstuff.h.  */
    270  1.1  christos 
    271  1.1  christos const char *
    272  1.1  christos get_shell ()
    273  1.1  christos {
    274  1.1  christos   const char *ret = getenv ("SHELL");
    275  1.1  christos   if (ret == NULL)
    276  1.1  christos     ret = "/bin/sh";
    277  1.1  christos 
    278  1.1  christos   return ret;
    279  1.1  christos }
    280  1.1  christos 
    281  1.1  christos /* See gdbsupport/pathstuff.h.  */
    282  1.1  christos 
    283  1.1  christos gdb::char_vector
    284  1.1  christos make_temp_filename (const std::string &f)
    285  1.1  christos {
    286  1.1  christos   gdb::char_vector filename_temp (f.length () + 8);
    287  1.1  christos   strcpy (filename_temp.data (), f.c_str ());
    288  1.1  christos   strcat (filename_temp.data () + f.size (), "-XXXXXX");
    289  1.1  christos   return filename_temp;
    290  1.1  christos }
    291