From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 112783 invoked by alias); 7 Jun 2019 06:23:24 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 112769 invoked by uid 89); 7 Jun 2019 06:23:24 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-14.1 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-ot1-f68.google.com Received: from mail-ot1-f68.google.com (HELO mail-ot1-f68.google.com) (209.85.210.68) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 07 Jun 2019 06:23:21 +0000 Received: by mail-ot1-f68.google.com with SMTP id d17so861011oth.5 for ; Thu, 06 Jun 2019 23:23:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=feGBP8xmsDHaQyYtZVBDrs97Fvl6OhCfGxvO6K2BoNk=; b=YlKPKc7uKu8Z9h5shVQaa1KLegdxSp4Nq9AZB2m5FGU57oRHgHEFeqWmjsjF0mbX9K VlCF7pFyTDZ0RHPhEQnwQcyW4KQCMMa6T8vvBbMieGf9c++zX8VUU1TiVyJ8ClyAOaAQ 0yV7/eY7N7Yt8LVrnKjlQpV+PpIIIyIFEmWI80FKK8XVTA/rFzjNOIYNZctXlQZBg235 ulA50lUGicr1ocpwiNWdl6InFEZaEzUGgVBuIRhlAuadJjQHCphUWs+ddiZu9wnWmwZl fpH35p4suP5eaA37+OhxZf4gbyHymNjLCBfPQw5b5jvxpjqHaTakibn3X5GakMLVY1lZ S51g== MIME-Version: 1.0 References: <20190603193716.4861-1-orgads@gmail.com> <20190607062049.7503-1-orgads@gmail.com> In-Reply-To: <20190607062049.7503-1-orgads@gmail.com> From: Orgad Shaneh Date: Fri, 07 Jun 2019 06:23:00 -0000 Message-ID: Subject: Re: [PATCH] Fix cache dir resolving on Windows To: gdb-patches@sourceware.org Content-Type: text/plain; charset="UTF-8" X-SW-Source: 2019-06/txt/msg00153.txt.bz2 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 wrote: > > From: Orgad Shaneh > > ... 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 . */ > - > -#include "common-defs.h" > -#include "pathstuff.h" > -#include "host-defs.h" > -#include "filenames.h" > -#include "gdb_tilde_expand.h" > - > -#ifdef USE_WIN32API > -#include > -#endif > - > -/* See common/pathstuff.h. */ > - > -gdb::unique_xmalloc_ptr > -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 (xstrdup (buf)); > - } > -#else > - { > - char *rp = canonicalize_file_name (filename); > - > - if (rp != NULL) > - return gdb::unique_xmalloc_ptr (rp); > - } > -#endif > - > - /* This system is a lost cause, just dup the buffer. */ > - return gdb::unique_xmalloc_ptr (xstrdup (filename)); > -} > - > -/* See common/pathstuff.h. */ > - > -gdb::unique_xmalloc_ptr > -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 (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 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 (result); > -} > - > -/* See common/pathstuff.h. */ > - > -gdb::unique_xmalloc_ptr > -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 (xstrdup (path)); > - > - /* Beware the // my son, the Emacs barfs, the botch that catch... */ > - return gdb::unique_xmalloc_ptr > - (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 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 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 . */ > + > +#include "common-defs.h" > +#include "pathstuff.h" > +#include "host-defs.h" > +#include "filenames.h" > +#include "gdb_tilde_expand.h" > + > +#ifdef USE_WIN32API > +#include > +#endif > + > +/* See common/pathstuff.h. */ > + > +gdb::unique_xmalloc_ptr > +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 (xstrdup (buf)); > + } > +#else > + { > + char *rp = canonicalize_file_name (filename); > + > + if (rp != NULL) > + return gdb::unique_xmalloc_ptr (rp); > + } > +#endif > + > + /* This system is a lost cause, just dup the buffer. */ > + return gdb::unique_xmalloc_ptr (xstrdup (filename)); > +} > + > +/* See common/pathstuff.h. */ > + > +gdb::unique_xmalloc_ptr > +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 (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 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 (result); > +} > + > +/* See common/pathstuff.h. */ > + > +gdb::unique_xmalloc_ptr > +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 (xstrdup (path)); > + > + /* Beware the // my son, the Emacs barfs, the botch that catch... */ > + return gdb::unique_xmalloc_ptr > + (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 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 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 >