This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Fix cache dir resolving on Windows
Oops! I mixed UNIX/Windows, and that's the result.
Please ignore it. I'll post a new patch soon.
- Orgad
On Fri, Jun 7, 2019 at 9:21 AM <orgads@gmail.com> wrote:
>
> From: Orgad Shaneh <orgads@gmail.com>
>
> ... when not running from MSYS environment, and HOME is not set.
> ---
> gdb/common/pathstuff.c | 584 +++++++++++++++++++++--------------------
> 1 file changed, 294 insertions(+), 290 deletions(-)
>
> diff --git a/gdb/common/pathstuff.c b/gdb/common/pathstuff.c
> index 2b1669a5b9..33fa5bbb4d 100644
> --- a/gdb/common/pathstuff.c
> +++ b/gdb/common/pathstuff.c
> @@ -1,290 +1,294 @@
> -/* Path manipulation routines for GDB and gdbserver.
> -
> - Copyright (C) 1986-2019 Free Software Foundation, Inc.
> -
> - This file is part of GDB.
> -
> - This program is free software; you can redistribute it and/or modify
> - it under the terms of the GNU General Public License as published by
> - the Free Software Foundation; either version 3 of the License, or
> - (at your option) any later version.
> -
> - This program is distributed in the hope that it will be useful,
> - but WITHOUT ANY WARRANTY; without even the implied warranty of
> - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - GNU General Public License for more details.
> -
> - You should have received a copy of the GNU General Public License
> - along with this program. If not, see <http://www.gnu.org/licenses/>. */
> -
> -#include "common-defs.h"
> -#include "pathstuff.h"
> -#include "host-defs.h"
> -#include "filenames.h"
> -#include "gdb_tilde_expand.h"
> -
> -#ifdef USE_WIN32API
> -#include <windows.h>
> -#endif
> -
> -/* See common/pathstuff.h. */
> -
> -gdb::unique_xmalloc_ptr<char>
> -gdb_realpath (const char *filename)
> -{
> -/* On most hosts, we rely on canonicalize_file_name to compute
> - the FILENAME's realpath.
> -
> - But the situation is slightly more complex on Windows, due to some
> - versions of GCC which were reported to generate paths where
> - backlashes (the directory separator) were doubled. For instance:
> - c:\\some\\double\\slashes\\dir
> - ... instead of ...
> - c:\some\double\slashes\dir
> - Those double-slashes were getting in the way when comparing paths,
> - for instance when trying to insert a breakpoint as follow:
> - (gdb) b c:/some/double/slashes/dir/foo.c:4
> - No source file named c:/some/double/slashes/dir/foo.c:4.
> - (gdb) b c:\some\double\slashes\dir\foo.c:4
> - No source file named c:\some\double\slashes\dir\foo.c:4.
> - To prevent this from happening, we need this function to always
> - strip those extra backslashes. While canonicalize_file_name does
> - perform this simplification, it only works when the path is valid.
> - Since the simplification would be useful even if the path is not
> - valid (one can always set a breakpoint on a file, even if the file
> - does not exist locally), we rely instead on GetFullPathName to
> - perform the canonicalization. */
> -
> -#if defined (_WIN32)
> - {
> - char buf[MAX_PATH];
> - DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
> -
> - /* The file system is case-insensitive but case-preserving.
> - So it is important we do not lowercase the path. Otherwise,
> - we might not be able to display the original casing in a given
> - path. */
> - if (len > 0 && len < MAX_PATH)
> - return gdb::unique_xmalloc_ptr<char> (xstrdup (buf));
> - }
> -#else
> - {
> - char *rp = canonicalize_file_name (filename);
> -
> - if (rp != NULL)
> - return gdb::unique_xmalloc_ptr<char> (rp);
> - }
> -#endif
> -
> - /* This system is a lost cause, just dup the buffer. */
> - return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -gdb::unique_xmalloc_ptr<char>
> -gdb_realpath_keepfile (const char *filename)
> -{
> - const char *base_name = lbasename (filename);
> - char *dir_name;
> - char *result;
> -
> - /* Extract the basename of filename, and return immediately
> - a copy of filename if it does not contain any directory prefix. */
> - if (base_name == filename)
> - return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
> -
> - dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
> - /* Allocate enough space to store the dir_name + plus one extra
> - character sometimes needed under Windows (see below), and
> - then the closing \000 character. */
> - strncpy (dir_name, filename, base_name - filename);
> - dir_name[base_name - filename] = '\000';
> -
> -#ifdef HAVE_DOS_BASED_FILE_SYSTEM
> - /* We need to be careful when filename is of the form 'd:foo', which
> - is equivalent of d:./foo, which is totally different from d:/foo. */
> - if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
> - {
> - dir_name[2] = '.';
> - dir_name[3] = '\000';
> - }
> -#endif
> -
> - /* Canonicalize the directory prefix, and build the resulting
> - filename. If the dirname realpath already contains an ending
> - directory separator, avoid doubling it. */
> - gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
> - const char *real_path = path_storage.get ();
> - if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
> - result = concat (real_path, base_name, (char *) NULL);
> - else
> - result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
> -
> - return gdb::unique_xmalloc_ptr<char> (result);
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -gdb::unique_xmalloc_ptr<char>
> -gdb_abspath (const char *path)
> -{
> - gdb_assert (path != NULL && path[0] != '\0');
> -
> - if (path[0] == '~')
> - return gdb_tilde_expand_up (path);
> -
> - if (IS_ABSOLUTE_PATH (path))
> - return gdb::unique_xmalloc_ptr<char> (xstrdup (path));
> -
> - /* Beware the // my son, the Emacs barfs, the botch that catch... */
> - return gdb::unique_xmalloc_ptr<char>
> - (concat (current_directory,
> - IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
> - ? "" : SLASH_STRING,
> - path, (char *) NULL));
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -const char *
> -child_path (const char *parent, const char *child)
> -{
> - /* The child path must start with the parent path. */
> - size_t parent_len = strlen (parent);
> - if (filename_ncmp (parent, child, parent_len) != 0)
> - return NULL;
> -
> - /* The parent path must be a directory and the child must contain at
> - least one component underneath the parent. */
> - const char *child_component;
> - if (IS_DIR_SEPARATOR (parent[parent_len - 1]))
> - {
> - /* The parent path ends in a directory separator, so it is a
> - directory. The first child component starts after the common
> - prefix. */
> - child_component = child + parent_len;
> - }
> - else
> - {
> - /* The parent path does not end in a directory separator. The
> - first character in the child after the common prefix must be
> - a directory separator.
> -
> - Note that CHILD must hold at least parent_len characters for
> - filename_ncmp to return zero. If the character at parent_len
> - is nul due to CHILD containing the same path as PARENT, the
> - IS_DIR_SEPARATOR check will fail here. */
> - if (!IS_DIR_SEPARATOR (child[parent_len]))
> - return NULL;
> -
> - /* The first child component starts after the separator after the
> - common prefix. */
> - child_component = child + parent_len + 1;
> - }
> -
> - /* The child must contain at least one non-separator character after
> - the parent. */
> - while (*child_component != '\0')
> - {
> - if (!IS_DIR_SEPARATOR (*child_component))
> - return child_component;
> -
> - child_component++;
> - }
> - return NULL;
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -bool
> -contains_dir_separator (const char *path)
> -{
> - for (; *path != '\0'; path++)
> - {
> - if (IS_DIR_SEPARATOR (*path))
> - return true;
> - }
> -
> - return false;
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -std::string
> -get_standard_cache_dir ()
> -{
> -#ifdef __APPLE__
> -#define HOME_CACHE_DIR "Library/Caches"
> -#else
> -#define HOME_CACHE_DIR ".cache"
> -#endif
> -
> -#ifndef __APPLE__
> - const char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
> - if (xdg_cache_home != NULL)
> - {
> - /* Make sure the path is absolute and tilde-expanded. */
> - gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (xdg_cache_home));
> - return string_printf ("%s/gdb", abs.get ());
> - }
> -#endif
> -
> - const char *home = getenv ("HOME");
> - if (home != NULL)
> - {
> - /* Make sure the path is absolute and tilde-expanded. */
> - gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (home));
> - return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ());
> - }
> -
> - return {};
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -std::string
> -get_standard_temp_dir ()
> -{
> -#ifdef WIN32
> - const char *tmp = getenv ("TMP");
> - if (tmp != nullptr)
> - return tmp;
> -
> - tmp = getenv ("TEMP");
> - if (tmp != nullptr)
> - return tmp;
> -
> - error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
> -
> -#else
> - const char *tmp = getenv ("TMPDIR");
> - if (tmp != nullptr)
> - return tmp;
> -
> - return "/tmp";
> -#endif
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -const char *
> -get_shell ()
> -{
> - const char *ret = getenv ("SHELL");
> - if (ret == NULL)
> - ret = "/bin/sh";
> -
> - return ret;
> -}
> -
> -/* See common/pathstuff.h. */
> -
> -gdb::char_vector
> -make_temp_filename (const std::string &f)
> -{
> - gdb::char_vector filename_temp (f.length () + 8);
> - strcpy (filename_temp.data (), f.c_str ());
> - strcat (filename_temp.data () + f.size (), "-XXXXXX");
> - return filename_temp;
> -}
> +/* Path manipulation routines for GDB and gdbserver.
> +
> + Copyright (C) 1986-2019 Free Software Foundation, Inc.
> +
> + This file is part of GDB.
> +
> + This program is free software; you can redistribute it and/or modify
> + it under the terms of the GNU General Public License as published by
> + the Free Software Foundation; either version 3 of the License, or
> + (at your option) any later version.
> +
> + This program is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program. If not, see <http://www.gnu.org/licenses/>. */
> +
> +#include "common-defs.h"
> +#include "pathstuff.h"
> +#include "host-defs.h"
> +#include "filenames.h"
> +#include "gdb_tilde_expand.h"
> +
> +#ifdef USE_WIN32API
> +#include <windows.h>
> +#endif
> +
> +/* See common/pathstuff.h. */
> +
> +gdb::unique_xmalloc_ptr<char>
> +gdb_realpath (const char *filename)
> +{
> +/* On most hosts, we rely on canonicalize_file_name to compute
> + the FILENAME's realpath.
> +
> + But the situation is slightly more complex on Windows, due to some
> + versions of GCC which were reported to generate paths where
> + backlashes (the directory separator) were doubled. For instance:
> + c:\\some\\double\\slashes\\dir
> + ... instead of ...
> + c:\some\double\slashes\dir
> + Those double-slashes were getting in the way when comparing paths,
> + for instance when trying to insert a breakpoint as follow:
> + (gdb) b c:/some/double/slashes/dir/foo.c:4
> + No source file named c:/some/double/slashes/dir/foo.c:4.
> + (gdb) b c:\some\double\slashes\dir\foo.c:4
> + No source file named c:\some\double\slashes\dir\foo.c:4.
> + To prevent this from happening, we need this function to always
> + strip those extra backslashes. While canonicalize_file_name does
> + perform this simplification, it only works when the path is valid.
> + Since the simplification would be useful even if the path is not
> + valid (one can always set a breakpoint on a file, even if the file
> + does not exist locally), we rely instead on GetFullPathName to
> + perform the canonicalization. */
> +
> +#if defined (_WIN32)
> + {
> + char buf[MAX_PATH];
> + DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL);
> +
> + /* The file system is case-insensitive but case-preserving.
> + So it is important we do not lowercase the path. Otherwise,
> + we might not be able to display the original casing in a given
> + path. */
> + if (len > 0 && len < MAX_PATH)
> + return gdb::unique_xmalloc_ptr<char> (xstrdup (buf));
> + }
> +#else
> + {
> + char *rp = canonicalize_file_name (filename);
> +
> + if (rp != NULL)
> + return gdb::unique_xmalloc_ptr<char> (rp);
> + }
> +#endif
> +
> + /* This system is a lost cause, just dup the buffer. */
> + return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +gdb::unique_xmalloc_ptr<char>
> +gdb_realpath_keepfile (const char *filename)
> +{
> + const char *base_name = lbasename (filename);
> + char *dir_name;
> + char *result;
> +
> + /* Extract the basename of filename, and return immediately
> + a copy of filename if it does not contain any directory prefix. */
> + if (base_name == filename)
> + return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
> +
> + dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
> + /* Allocate enough space to store the dir_name + plus one extra
> + character sometimes needed under Windows (see below), and
> + then the closing \000 character. */
> + strncpy (dir_name, filename, base_name - filename);
> + dir_name[base_name - filename] = '\000';
> +
> +#ifdef HAVE_DOS_BASED_FILE_SYSTEM
> + /* We need to be careful when filename is of the form 'd:foo', which
> + is equivalent of d:./foo, which is totally different from d:/foo. */
> + if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
> + {
> + dir_name[2] = '.';
> + dir_name[3] = '\000';
> + }
> +#endif
> +
> + /* Canonicalize the directory prefix, and build the resulting
> + filename. If the dirname realpath already contains an ending
> + directory separator, avoid doubling it. */
> + gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
> + const char *real_path = path_storage.get ();
> + if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
> + result = concat (real_path, base_name, (char *) NULL);
> + else
> + result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
> +
> + return gdb::unique_xmalloc_ptr<char> (result);
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +gdb::unique_xmalloc_ptr<char>
> +gdb_abspath (const char *path)
> +{
> + gdb_assert (path != NULL && path[0] != '\0');
> +
> + if (path[0] == '~')
> + return gdb_tilde_expand_up (path);
> +
> + if (IS_ABSOLUTE_PATH (path))
> + return gdb::unique_xmalloc_ptr<char> (xstrdup (path));
> +
> + /* Beware the // my son, the Emacs barfs, the botch that catch... */
> + return gdb::unique_xmalloc_ptr<char>
> + (concat (current_directory,
> + IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
> + ? "" : SLASH_STRING,
> + path, (char *) NULL));
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +const char *
> +child_path (const char *parent, const char *child)
> +{
> + /* The child path must start with the parent path. */
> + size_t parent_len = strlen (parent);
> + if (filename_ncmp (parent, child, parent_len) != 0)
> + return NULL;
> +
> + /* The parent path must be a directory and the child must contain at
> + least one component underneath the parent. */
> + const char *child_component;
> + if (IS_DIR_SEPARATOR (parent[parent_len - 1]))
> + {
> + /* The parent path ends in a directory separator, so it is a
> + directory. The first child component starts after the common
> + prefix. */
> + child_component = child + parent_len;
> + }
> + else
> + {
> + /* The parent path does not end in a directory separator. The
> + first character in the child after the common prefix must be
> + a directory separator.
> +
> + Note that CHILD must hold at least parent_len characters for
> + filename_ncmp to return zero. If the character at parent_len
> + is nul due to CHILD containing the same path as PARENT, the
> + IS_DIR_SEPARATOR check will fail here. */
> + if (!IS_DIR_SEPARATOR (child[parent_len]))
> + return NULL;
> +
> + /* The first child component starts after the separator after the
> + common prefix. */
> + child_component = child + parent_len + 1;
> + }
> +
> + /* The child must contain at least one non-separator character after
> + the parent. */
> + while (*child_component != '\0')
> + {
> + if (!IS_DIR_SEPARATOR (*child_component))
> + return child_component;
> +
> + child_component++;
> + }
> + return NULL;
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +bool
> +contains_dir_separator (const char *path)
> +{
> + for (; *path != '\0'; path++)
> + {
> + if (IS_DIR_SEPARATOR (*path))
> + return true;
> + }
> +
> + return false;
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +std::string
> +get_standard_cache_dir ()
> +{
> +#ifdef __APPLE__
> +#define HOME_CACHE_DIR "Library/Caches"
> +#else
> +#define HOME_CACHE_DIR ".cache"
> +#endif
> +
> +#ifndef __APPLE__
> + const char *xdg_cache_home = getenv ("XDG_CACHE_HOME");
> + if (xdg_cache_home != NULL)
> + {
> + /* Make sure the path is absolute and tilde-expanded. */
> + gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (xdg_cache_home));
> + return string_printf ("%s/gdb", abs.get ());
> + }
> +#endif
> +
> + const char *home = getenv ("HOME");
> +#ifdef _WIN32
> + if (home == nullptr)
> + home = getenv ("APPDATA");
> +#endif
> + if (home != NULL)
> + {
> + /* Make sure the path is absolute and tilde-expanded. */
> + gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (home));
> + return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ());
> + }
> +
> + return {};
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +std::string
> +get_standard_temp_dir ()
> +{
> +#ifdef WIN32
> + const char *tmp = getenv ("TMP");
> + if (tmp != nullptr)
> + return tmp;
> +
> + tmp = getenv ("TEMP");
> + if (tmp != nullptr)
> + return tmp;
> +
> + error (_("Couldn't find temp dir path, both TMP and TEMP are unset."));
> +
> +#else
> + const char *tmp = getenv ("TMPDIR");
> + if (tmp != nullptr)
> + return tmp;
> +
> + return "/tmp";
> +#endif
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +const char *
> +get_shell ()
> +{
> + const char *ret = getenv ("SHELL");
> + if (ret == NULL)
> + ret = "/bin/sh";
> +
> + return ret;
> +}
> +
> +/* See common/pathstuff.h. */
> +
> +gdb::char_vector
> +make_temp_filename (const std::string &f)
> +{
> + gdb::char_vector filename_temp (f.length () + 8);
> + strcpy (filename_temp.data (), f.c_str ());
> + strcat (filename_temp.data () + f.size (), "-XXXXXX");
> + return filename_temp;
> +}
> --
> 2.20.1
>