Skip to content

Commit d3ee35d

Browse files
committed
Improve gdb_tilde_expand logic.
Before this patch, gdb_tilde_expand would use glob(3) in order to expand tilde at the begining of a path. This implementation has limitation when expanding a tilde leading path to a non existing file since glob fails to expand. This patch proposes to use glob only to expand the tilde component of the path and leaves the rest of the path unchanged. This patch is a followup to the following discution: https://sourceware.org/pipermail/gdb-patches/2021-January/174776.html Before the patch: gdb_tilde_expand("~") -> "/home/lsix" gdb_tilde_expand("~/a/c/b") -> error() is called After the patch: gdb_tilde_expand("~") -> "/home/lsix" gdb_tilde_expand("~/a/c/b") -> "/home/lsix/a/c/b" Tested on x84_64 linux. gdb/ChangeLog: * Makefile.in (SELFTESTS_SRCS): Add unittests/gdb_tilde_expand-selftests.c. * unittests/gdb_tilde_expand-selftests.c: New file. gdbsupport/ChangeLog: * gdb_tilde_expand.cc (gdb_tilde_expand): Improve implementation. (gdb_tilde_expand_up): Delegate logic to gdb_tilde_expand. * gdb_tilde_expand.h (gdb_tilde_expand): Update description.
1 parent ef45cb6 commit d3ee35d

File tree

6 files changed

+141
-16
lines changed

6 files changed

+141
-16
lines changed

gdb/ChangeLog

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
2021-01-23 Lancelot SIX <[email protected]>
2+
3+
* Makefile.in (SELFTESTS_SRCS): Add
4+
unittests/gdb_tilde_expand-selftests.c.
5+
* unittests/gdb_tilde_expand-selftests.c: New file.
6+
17
2021-01-22 Andrew Burgess <[email protected]>
28

39
PR cli/25956

gdb/Makefile.in

+1
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ SELFTESTS_SRCS = \
446446
unittests/filtered_iterator-selftests.c \
447447
unittests/format_pieces-selftests.c \
448448
unittests/function-view-selftests.c \
449+
unittests/gdb_tilde_expand-selftests.c \
449450
unittests/gmp-utils-selftests.c \
450451
unittests/lookup_name_info-selftests.c \
451452
unittests/memory-map-selftests.c \
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* Self tests for gdb_tilde_expand
2+
3+
Copyright (C) 2021 Free Software Foundation, Inc.
4+
5+
This file is part of GDB.
6+
7+
This program is free software; you can redistribute it and/or modify
8+
it under the terms of the GNU General Public License as published by
9+
the Free Software Foundation; either version 3 of the License, or
10+
(at your option) any later version.
11+
12+
This program is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
GNU General Public License for more details.
16+
17+
You should have received a copy of the GNU General Public License
18+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
19+
20+
#include "gdbsupport/common-defs.h"
21+
#include "gdbsupport/selftest.h"
22+
#include <cstdlib>
23+
24+
#include "gdbsupport/gdb_tilde_expand.h"
25+
26+
namespace selftests {
27+
namespace gdb_tilde_expand_tests {
28+
29+
static void
30+
do_test ()
31+
{
32+
/* Home directory of the user running the test. */
33+
const char *c_home = std::getenv ("HOME");
34+
35+
/* Skip the test if $HOME is not available in the environment. */
36+
if (c_home == nullptr)
37+
return;
38+
39+
const std::string home (c_home);
40+
41+
/* Basic situation. */
42+
SELF_CHECK (home == gdb_tilde_expand ("~"));
43+
44+
/* When given a path that begins by a tilde and refers to a file that
45+
does not exist, gdb_tilde expand must still be able to do the tilde
46+
expansion. */
47+
SELF_CHECK (gdb_tilde_expand ("~/non/existent/directory")
48+
== home + "/non/existent/directory");
49+
50+
/* gdb_tilde_expand only expands tilde and does not try to do any other
51+
substitution. */
52+
SELF_CHECK (gdb_tilde_expand ("~/*/a.out") == home + "/*/a.out");
53+
54+
/* gdb_tilde_expand does no modification to a non tilde leading path. */
55+
SELF_CHECK (gdb_tilde_expand ("/some/abs/path") == "/some/abs/path");
56+
SELF_CHECK (gdb_tilde_expand ("relative/path") == "relative/path");
57+
58+
/* If $USER is available in the env variables, check the '~user'
59+
expansion. */
60+
const char *c_user = std::getenv ("USER");
61+
if (c_user != nullptr)
62+
{
63+
const std::string user (c_user);
64+
SELF_CHECK (gdb_tilde_expand (("~" + user).c_str ()) == home);
65+
SELF_CHECK (gdb_tilde_expand (("~" + user + "/a/b").c_str ())
66+
== home + "/a/b");
67+
}
68+
69+
/* Check that an error is thrown when trying to expand home of a unknown
70+
user. */
71+
try
72+
{
73+
gdb_tilde_expand ("~no_one_should_have_that_login/a");
74+
SELF_CHECK (false);
75+
}
76+
catch (const gdb_exception_error &e)
77+
{
78+
SELF_CHECK (e.error == GENERIC_ERROR);
79+
SELF_CHECK
80+
(*e.message
81+
== "Could not find a match for '~no_one_should_have_that_login'.");
82+
}
83+
}
84+
85+
} /* namespace gdb_tilde_expand_tests */
86+
} /* namespace selftests */
87+
88+
void _initialize_gdb_tilde_expand_selftests ();
89+
void
90+
_initialize_gdb_tilde_expand_selftests ()
91+
{
92+
selftests::register_test
93+
("gdb_tilde_expand", selftests::gdb_tilde_expand_tests::do_test);
94+
}

gdbsupport/ChangeLog

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2021-01-23 Lancelot SIX <[email protected]>
2+
3+
* gdb_tilde_expand.cc (gdb_tilde_expand): Improve
4+
implementation.
5+
(gdb_tilde_expand_up): Delegate logic to gdb_tilde_expand.
6+
* gdb_tilde_expand.h (gdb_tilde_expand): Update description.
7+
18
2021-01-22 Simon Marchi <[email protected]>
29

310
* common-debug.h (debug_prefixed_printf_cond_nofunc): New.

gdbsupport/gdb_tilde_expand.cc

+32-14
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
along with this program. If not, see <http://www.gnu.org/licenses/>. */
1919

2020
#include "common-defs.h"
21+
#include <algorithm>
22+
#include "filenames.h"
2123
#include "gdb_tilde_expand.h"
2224
#include <glob.h>
2325

@@ -71,25 +73,41 @@ class gdb_glob
7173
std::string
7274
gdb_tilde_expand (const char *dir)
7375
{
74-
gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
75-
76-
gdb_assert (glob.pathc () > 0);
77-
/* "glob" may return more than one match to the path provided by the
78-
user, but we are only interested in the first match. */
79-
std::string expanded_dir = glob.pathv ()[0];
80-
81-
return expanded_dir;
76+
if (dir[0] != '~')
77+
return std::string (dir);
78+
79+
/* This function uses glob in order to expand the ~. However, this function
80+
will fail to expand if the actual dir we are looking for does not exist.
81+
Given "~/does/not/exist", glob will fail.
82+
83+
In order to avoid such limitation, we only use glob to expand "~" and keep
84+
"/does/not/exist" unchanged.
85+
86+
Similarly, to expand ~gdb/might/not/exist, we only expand "~gdb" using
87+
glob and leave "/might/not/exist" unchanged. */
88+
const std::string d (dir);
89+
90+
/* Look for the first dir separator (if any) and split d around it. */
91+
const auto first_sep
92+
= std::find_if (d.cbegin (), d.cend(),
93+
[] (const char c) -> bool
94+
{
95+
return IS_DIR_SEPARATOR (c);
96+
});
97+
const std::string to_expand (d.cbegin (), first_sep);
98+
const std::string remainder (first_sep, d.cend ());
99+
100+
const gdb_glob glob (to_expand.c_str (), GLOB_TILDE_CHECK, nullptr);
101+
102+
gdb_assert (glob.pathc () == 1);
103+
return std::string (glob.pathv ()[0]) + remainder;
82104
}
83105

84106
/* See gdbsupport/gdb_tilde_expand.h. */
85107

86108
gdb::unique_xmalloc_ptr<char>
87109
gdb_tilde_expand_up (const char *dir)
88110
{
89-
gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
90-
91-
gdb_assert (glob.pathc () > 0);
92-
/* "glob" may return more than one match to the path provided by the
93-
user, but we are only interested in the first match. */
94-
return make_unique_xstrdup (glob.pathv ()[0]);
111+
const std::string expanded = gdb_tilde_expand (dir);
112+
return make_unique_xstrdup (expanded.c_str ());
95113
}

gdbsupport/gdb_tilde_expand.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
#ifndef COMMON_GDB_TILDE_EXPAND_H
2121
#define COMMON_GDB_TILDE_EXPAND_H
2222

23-
/* Perform path expansion (i.e., tilde expansion) on DIR, and return
24-
the full path. */
23+
/* Perform tilde expansion on DIR, and return the full path. */
2524
extern std::string gdb_tilde_expand (const char *dir);
2625

2726
/* Same as GDB_TILDE_EXPAND, but return the full path as a

0 commit comments

Comments
 (0)