Change gdb_realpath to return a unique_xmalloc_ptr

This changes gdb_realpath to return a unique_xmalloc_ptr and fixes up
the callers.  This allows removing some cleanups.  This change by
itself caused xfullpath.exp to fail; and attempting to fix that ran
into various problems (like .get() being optimized out); so this patch
also rewrites xfullpath.exp to be a C++ selftest instead.

ChangeLog
2017-08-22  Tom Tromey  <tom@tromey.com>

	* exec.c (exec_file_attach): Update.
	* linux-thread-db.c (try_thread_db_load): Update.
	* guile/scm-safe-call.c (gdbscm_safe_source_script): Update.
	* utils.c (gdb_realpath): Change return type.
	(gdb_realpath_keepfile): Update.
	(gdb_realpath_check_trailer, gdb_realpath_tests): New functions.
	(_initialize_utils): Register the new self test.
	* source.c (openp): Update.
	(find_and_open_source): Update.
	* nto-tdep.c (nto_find_and_open_solib): Update.
	* main.c (set_gdb_data_directory): Update.
	(captured_main_1): Update.
	* dwarf2read.c (dwarf2_get_dwz_file): Update
	(dw2_map_symbol_filenames): Update.
	* auto-load.c (auto_load_safe_path_vec_update): Update.
	(filename_is_in_auto_load_safe_path_vec): Change type of
	"filename_realp".
	(auto_load_objfile_script): Update.
	(file_is_auto_load_safe): Update.  Use std::string.
	* utils.h (gdb_realpath): Return a gdb::unique_xmalloc_ptr.

testsuite/ChangeLog
2017-08-22  Tom Tromey  <tom@tromey.com>

	* gdb.gdb/xfullpath.exp: Remove.
This commit is contained in:
Tom Tromey 2017-08-03 16:53:22 -06:00
parent 4971c9a74b
commit 14278e1fdb
15 changed files with 130 additions and 145 deletions

View File

@ -1,3 +1,26 @@
2017-08-22 Tom Tromey <tom@tromey.com>
* exec.c (exec_file_attach): Update.
* linux-thread-db.c (try_thread_db_load): Update.
* guile/scm-safe-call.c (gdbscm_safe_source_script): Update.
* utils.c (gdb_realpath): Change return type.
(gdb_realpath_keepfile): Update.
(gdb_realpath_check_trailer, gdb_realpath_tests): New functions.
(_initialize_utils): Register the new self test.
* source.c (openp): Update.
(find_and_open_source): Update.
* nto-tdep.c (nto_find_and_open_solib): Update.
* main.c (set_gdb_data_directory): Update.
(captured_main_1): Update.
* dwarf2read.c (dwarf2_get_dwz_file): Update
(dw2_map_symbol_filenames): Update.
* auto-load.c (auto_load_safe_path_vec_update): Update.
(filename_is_in_auto_load_safe_path_vec): Change type of
"filename_realp".
(auto_load_objfile_script): Update.
(file_is_auto_load_safe): Update. Use std::string.
* utils.h (gdb_realpath): Return a gdb::unique_xmalloc_ptr.
2017-08-22 Tom Tromey <tom@tromey.com> 2017-08-22 Tom Tromey <tom@tromey.com>
* utils.c (gdb_realpath_keepfile): Return a * utils.c (gdb_realpath_keepfile): Return a

View File

@ -218,7 +218,7 @@ auto_load_safe_path_vec_update (void)
{ {
char *dir = VEC_index (char_ptr, auto_load_safe_path_vec, ix); char *dir = VEC_index (char_ptr, auto_load_safe_path_vec, ix);
char *expanded = tilde_expand (dir); char *expanded = tilde_expand (dir);
char *real_path = gdb_realpath (expanded); gdb::unique_xmalloc_ptr<char> real_path = gdb_realpath (expanded);
/* Ensure the current entry is at least tilde_expand-ed. */ /* Ensure the current entry is at least tilde_expand-ed. */
VEC_replace (char_ptr, auto_load_safe_path_vec, ix, expanded); VEC_replace (char_ptr, auto_load_safe_path_vec, ix, expanded);
@ -238,16 +238,15 @@ auto_load_safe_path_vec_update (void)
xfree (dir); xfree (dir);
/* If gdb_realpath returns a different content, append it. */ /* If gdb_realpath returns a different content, append it. */
if (strcmp (real_path, expanded) == 0) if (strcmp (real_path.get (), expanded) != 0)
xfree (real_path);
else
{ {
VEC_safe_push (char_ptr, auto_load_safe_path_vec, real_path);
if (debug_auto_load) if (debug_auto_load)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
_("auto-load: And canonicalized as \"%s\".\n"), _("auto-load: And canonicalized as \"%s\".\n"),
real_path); real_path.get ());
VEC_safe_push (char_ptr, auto_load_safe_path_vec,
real_path.release ());
} }
} }
} }
@ -419,12 +418,11 @@ filename_is_in_pattern (const char *filename, const char *pattern)
/* Return 1 if FILENAME belongs to one of directory components of /* Return 1 if FILENAME belongs to one of directory components of
AUTO_LOAD_SAFE_PATH_VEC. Return 0 otherwise. AUTO_LOAD_SAFE_PATH_VEC. Return 0 otherwise.
auto_load_safe_path_vec_update is never called. auto_load_safe_path_vec_update is never called.
*FILENAME_REALP may be updated by gdb_realpath of FILENAME - it has to be *FILENAME_REALP may be updated by gdb_realpath of FILENAME. */
freed by the caller. */
static int static int
filename_is_in_auto_load_safe_path_vec (const char *filename, filename_is_in_auto_load_safe_path_vec (const char *filename,
char **filename_realp) gdb::unique_xmalloc_ptr<char> *filename_realp)
{ {
char *pattern; char *pattern;
int ix; int ix;
@ -439,17 +437,17 @@ filename_is_in_auto_load_safe_path_vec (const char *filename,
if (*filename_realp == NULL) if (*filename_realp == NULL)
{ {
*filename_realp = gdb_realpath (filename); *filename_realp = gdb_realpath (filename);
if (debug_auto_load && strcmp (*filename_realp, filename) != 0) if (debug_auto_load && strcmp (filename_realp->get (), filename) != 0)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
_("auto-load: Resolved " _("auto-load: Resolved "
"file \"%s\" as \"%s\".\n"), "file \"%s\" as \"%s\".\n"),
filename, *filename_realp); filename, filename_realp->get ());
} }
if (strcmp (*filename_realp, filename) != 0) if (strcmp (filename_realp->get (), filename) != 0)
for (ix = 0; for (ix = 0;
VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, pattern); ++ix) VEC_iterate (char_ptr, auto_load_safe_path_vec, ix, pattern); ++ix)
if (filename_is_in_pattern (*filename_realp, pattern)) if (filename_is_in_pattern (filename_realp->get (), pattern))
break; break;
} }
@ -476,8 +474,7 @@ filename_is_in_auto_load_safe_path_vec (const char *filename,
int int
file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...) file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...)
{ {
char *filename_real = NULL; gdb::unique_xmalloc_ptr<char> filename_real;
struct cleanup *back_to;
static int advice_printed = 0; static int advice_printed = 0;
if (debug_auto_load) if (debug_auto_load)
@ -489,34 +486,24 @@ file_is_auto_load_safe (const char *filename, const char *debug_fmt, ...)
va_end (debug_args); va_end (debug_args);
} }
back_to = make_cleanup (free_current_contents, &filename_real);
if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real)) if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
{ return 1;
do_cleanups (back_to);
return 1;
}
auto_load_safe_path_vec_update (); auto_load_safe_path_vec_update ();
if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real)) if (filename_is_in_auto_load_safe_path_vec (filename, &filename_real))
{ return 1;
do_cleanups (back_to);
return 1;
}
warning (_("File \"%s\" auto-loading has been declined by your " warning (_("File \"%s\" auto-loading has been declined by your "
"`auto-load safe-path' set to \"%s\"."), "`auto-load safe-path' set to \"%s\"."),
filename_real, auto_load_safe_path); filename_real.get (), auto_load_safe_path);
if (!advice_printed) if (!advice_printed)
{ {
const char *homedir = getenv ("HOME"); const char *homedir = getenv ("HOME");
char *homeinit;
if (homedir == NULL) if (homedir == NULL)
homedir = "$HOME"; homedir = "$HOME";
homeinit = xstrprintf ("%s/%s", homedir, gdbinit); std::string homeinit = string_printf ("%s/%s", homedir, gdbinit);
make_cleanup (xfree, homeinit);
printf_filtered (_("\ printf_filtered (_("\
To enable execution of this file add\n\ To enable execution of this file add\n\
@ -528,11 +515,11 @@ line to your configuration file \"%s\".\n\
For more information about this security protection see the\n\ For more information about this security protection see the\n\
\"Auto-loading safe path\" section in the GDB manual. E.g., run from the shell:\n\ \"Auto-loading safe path\" section in the GDB manual. E.g., run from the shell:\n\
\tinfo \"(gdb)Auto-loading safe path\"\n"), \tinfo \"(gdb)Auto-loading safe path\"\n"),
filename_real, homeinit, homeinit); filename_real.get (),
homeinit.c_str (), homeinit.c_str ());
advice_printed = 1; advice_printed = 1;
} }
do_cleanups (back_to);
return 0; return 0;
} }
@ -891,30 +878,28 @@ void
auto_load_objfile_script (struct objfile *objfile, auto_load_objfile_script (struct objfile *objfile,
const struct extension_language_defn *language) const struct extension_language_defn *language)
{ {
char *realname = gdb_realpath (objfile_name (objfile)); gdb::unique_xmalloc_ptr<char> realname
struct cleanup *cleanups = make_cleanup (xfree, realname); = gdb_realpath (objfile_name (objfile));
if (!auto_load_objfile_script_1 (objfile, realname, language)) if (!auto_load_objfile_script_1 (objfile, realname.get (), language))
{ {
/* For Windows/DOS .exe executables, strip the .exe suffix, so that /* For Windows/DOS .exe executables, strip the .exe suffix, so that
FOO-gdb.gdb could be used for FOO.exe, and try again. */ FOO-gdb.gdb could be used for FOO.exe, and try again. */
size_t len = strlen (realname); size_t len = strlen (realname.get ());
const size_t lexe = sizeof (".exe") - 1; const size_t lexe = sizeof (".exe") - 1;
if (len > lexe && strcasecmp (realname + len - lexe, ".exe") == 0) if (len > lexe && strcasecmp (realname.get () + len - lexe, ".exe") == 0)
{ {
len -= lexe; len -= lexe;
realname[len] = '\0'; realname.get ()[len] = '\0';
if (debug_auto_load) if (debug_auto_load)
fprintf_unfiltered (gdb_stdlog, _("auto-load: Stripped .exe suffix, " fprintf_unfiltered (gdb_stdlog, _("auto-load: Stripped .exe suffix, "
"retrying with \"%s\".\n"), "retrying with \"%s\".\n"),
realname); realname.get ());
auto_load_objfile_script_1 (objfile, realname, language); auto_load_objfile_script_1 (objfile, realname.get (), language);
} }
} }
do_cleanups (cleanups);
} }
/* Subroutine of source_section_scripts to simplify it. /* Subroutine of source_section_scripts to simplify it.

View File

@ -2717,10 +2717,10 @@ dwarf2_get_dwz_file (void)
std::string abs_storage; std::string abs_storage;
if (!IS_ABSOLUTE_PATH (filename)) if (!IS_ABSOLUTE_PATH (filename))
{ {
char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile)); gdb::unique_xmalloc_ptr<char> abs
= gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
make_cleanup (xfree, abs); abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename;
abs_storage = ldirname (abs) + SLASH_STRING + filename;
filename = abs_storage.c_str (); filename = abs_storage.c_str ();
} }
@ -3589,7 +3589,7 @@ dw2_get_real_path (struct objfile *objfile,
qfn->num_file_names, const char *); qfn->num_file_names, const char *);
if (qfn->real_names[index] == NULL) if (qfn->real_names[index] == NULL)
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]); qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release ();
return qfn->real_names[index]; return qfn->real_names[index];
} }
@ -4383,13 +4383,11 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename) dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename)
{ {
const char *this_real_name; gdb::unique_xmalloc_ptr<char> this_real_name;
if (need_fullname) if (need_fullname)
this_real_name = gdb_realpath (filename); this_real_name = gdb_realpath (filename);
else (*fun) (filename, this_real_name.get (), data);
this_real_name = NULL;
(*fun) (filename, this_real_name, data);
}); });
} }

View File

@ -249,16 +249,12 @@ exec_file_locate_attach (int pid, int defer_bp_reset, int from_tty)
void void
exec_file_attach (const char *filename, int from_tty) exec_file_attach (const char *filename, int from_tty)
{ {
struct cleanup *cleanups;
/* First, acquire a reference to the current exec_bfd. We release /* First, acquire a reference to the current exec_bfd. We release
this at the end of the function; but acquiring it now lets the this at the end of the function; but acquiring it now lets the
BFD cache return it if this call refers to the same file. */ BFD cache return it if this call refers to the same file. */
gdb_bfd_ref (exec_bfd); gdb_bfd_ref (exec_bfd);
gdb_bfd_ref_ptr exec_bfd_holder (exec_bfd); gdb_bfd_ref_ptr exec_bfd_holder (exec_bfd);
cleanups = make_cleanup (null_cleanup, NULL);
/* Remove any previous exec file. */ /* Remove any previous exec file. */
exec_close (); exec_close ();
@ -274,7 +270,7 @@ exec_file_attach (const char *filename, int from_tty)
else else
{ {
int load_via_target = 0; int load_via_target = 0;
char *scratch_pathname, *canonical_pathname; const char *scratch_pathname, *canonical_pathname;
int scratch_chan; int scratch_chan;
struct target_section *sections = NULL, *sections_end = NULL; struct target_section *sections = NULL, *sections_end = NULL;
char **matching; char **matching;
@ -287,6 +283,7 @@ exec_file_attach (const char *filename, int from_tty)
load_via_target = 1; load_via_target = 1;
} }
gdb::unique_xmalloc_ptr<char> canonical_storage, scratch_storage;
if (load_via_target) if (load_via_target)
{ {
/* gdb_bfd_fopen does not support "target:" filenames. */ /* gdb_bfd_fopen does not support "target:" filenames. */
@ -295,19 +292,18 @@ exec_file_attach (const char *filename, int from_tty)
"not supported for %s sysroots"), "not supported for %s sysroots"),
TARGET_SYSROOT_PREFIX); TARGET_SYSROOT_PREFIX);
scratch_pathname = xstrdup (filename); scratch_pathname = filename;
make_cleanup (xfree, scratch_pathname);
scratch_chan = -1; scratch_chan = -1;
canonical_pathname = scratch_pathname; canonical_pathname = scratch_pathname;
} }
else else
{ {
char *temp_pathname;
scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST, scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
filename, write_files ? filename, write_files ?
O_RDWR | O_BINARY : O_RDONLY | O_BINARY, O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
&scratch_pathname); &temp_pathname);
#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__) #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
if (scratch_chan < 0) if (scratch_chan < 0)
{ {
@ -318,18 +314,19 @@ exec_file_attach (const char *filename, int from_tty)
exename, write_files ? exename, write_files ?
O_RDWR | O_BINARY O_RDWR | O_BINARY
: O_RDONLY | O_BINARY, : O_RDONLY | O_BINARY,
&scratch_pathname); &temp_pathname);
} }
#endif #endif
if (scratch_chan < 0) if (scratch_chan < 0)
perror_with_name (filename); perror_with_name (filename);
make_cleanup (xfree, scratch_pathname); scratch_storage.reset (temp_pathname);
scratch_pathname = temp_pathname;
/* gdb_bfd_open (and its variants) prefers canonicalized /* gdb_bfd_open (and its variants) prefers canonicalized
pathname for better BFD caching. */ pathname for better BFD caching. */
canonical_pathname = gdb_realpath (scratch_pathname); canonical_storage = gdb_realpath (scratch_pathname);
make_cleanup (xfree, canonical_pathname); canonical_pathname = canonical_storage.get ();
} }
gdb_bfd_ref_ptr temp; gdb_bfd_ref_ptr temp;
@ -390,8 +387,6 @@ exec_file_attach (const char *filename, int from_tty)
(*deprecated_exec_file_display_hook) (filename); (*deprecated_exec_file_display_hook) (filename);
} }
do_cleanups (cleanups);
bfd_cache_close_all (); bfd_cache_close_all ();
observer_notify_executable_changed (); observer_notify_executable_changed ();
} }

View File

@ -438,19 +438,18 @@ gdbscm_safe_source_script (const char *filename)
%load-path, but we don't want %load-path to be searched. At least not %load-path, but we don't want %load-path to be searched. At least not
by default. This function is invoked by the "source" GDB command which by default. This function is invoked by the "source" GDB command which
already has its own path search support. */ already has its own path search support. */
char *abs_filename = NULL; gdb::unique_xmalloc_ptr<char> abs_filename;
const char *result; const char *result;
if (!IS_ABSOLUTE_PATH (filename)) if (!IS_ABSOLUTE_PATH (filename))
{ {
abs_filename = gdb_realpath (filename); abs_filename = gdb_realpath (filename);
filename = abs_filename; filename = abs_filename.get ();
} }
result = gdbscm_with_guile (scscm_source_scheme_script, result = gdbscm_with_guile (scscm_source_scheme_script,
(void *) filename); (void *) filename);
xfree (abs_filename);
if (result != NULL) if (result != NULL)
return xstrdup (result); return xstrdup (result);
return NULL; return NULL;

View File

@ -695,7 +695,7 @@ try_thread_db_load (const char *library, int check_auto_load_safe)
/* Do not save system library name, that one is always trusted. */ /* Do not save system library name, that one is always trusted. */
if (strchr (library, '/') != NULL) if (strchr (library, '/') != NULL)
info->filename = gdb_realpath (library); info->filename = gdb_realpath (library).release ();
if (try_thread_db_load_1 (info)) if (try_thread_db_load_1 (info))
return 1; return 1;

View File

@ -120,7 +120,7 @@ set_gdb_data_directory (const char *new_datadir)
warning (_("%s is not a directory."), new_datadir); warning (_("%s is not a directory."), new_datadir);
xfree (gdb_datadir); xfree (gdb_datadir);
gdb_datadir = gdb_realpath (new_datadir); gdb_datadir = gdb_realpath (new_datadir).release ();
/* gdb_realpath won't return an absolute path if the path doesn't exist, /* gdb_realpath won't return an absolute path if the path doesn't exist,
but we still want to record an absolute path here. If the user entered but we still want to record an absolute path here. If the user entered
@ -1083,7 +1083,8 @@ captured_main_1 (struct captured_main_args *context)
the same as the $HOME/.gdbinit file (it should exist, also). */ the same as the $HOME/.gdbinit file (it should exist, also). */
if (local_gdbinit) if (local_gdbinit)
{ {
auto_load_local_gdbinit_pathname = gdb_realpath (local_gdbinit); auto_load_local_gdbinit_pathname
= gdb_realpath (local_gdbinit).release ();
if (!inhibit_gdbinit && auto_load_local_gdbinit if (!inhibit_gdbinit && auto_load_local_gdbinit
&& file_is_auto_load_safe (local_gdbinit, && file_is_auto_load_safe (local_gdbinit,

View File

@ -142,7 +142,7 @@ nto_find_and_open_solib (const char *solib, unsigned o_flags,
if (temp_pathname) if (temp_pathname)
{ {
if (ret >= 0) if (ret >= 0)
*temp_pathname = gdb_realpath (arch_path); *temp_pathname = gdb_realpath (arch_path).release ();
else else
*temp_pathname = NULL; *temp_pathname = NULL;
} }

View File

@ -376,7 +376,7 @@ struct objfile *
allocate_objfile (bfd *abfd, const char *name, objfile_flags flags) allocate_objfile (bfd *abfd, const char *name, objfile_flags flags)
{ {
struct objfile *objfile; struct objfile *objfile;
char *expanded_name; const char *expanded_name;
objfile = XCNEW (struct objfile); objfile = XCNEW (struct objfile);
objfile->psymbol_cache = psymbol_bcache_init (); objfile->psymbol_cache = psymbol_bcache_init ();

View File

@ -911,7 +911,7 @@ done:
if (fd < 0) if (fd < 0)
*filename_opened = NULL; *filename_opened = NULL;
else if ((opts & OPF_RETURN_REALPATH) != 0) else if ((opts & OPF_RETURN_REALPATH) != 0)
*filename_opened = gdb_realpath (filename); *filename_opened = gdb_realpath (filename).release ();
else else
*filename_opened = gdb_abspath (filename).release (); *filename_opened = gdb_abspath (filename).release ();
} }
@ -1050,7 +1050,7 @@ find_and_open_source (const char *filename,
result = gdb_open_cloexec (*fullname, OPEN_MODE, 0); result = gdb_open_cloexec (*fullname, OPEN_MODE, 0);
if (result >= 0) if (result >= 0)
{ {
char *lpath = gdb_realpath (*fullname); char *lpath = gdb_realpath (*fullname).release ();
xfree (*fullname); xfree (*fullname);
*fullname = lpath; *fullname = lpath;

View File

@ -468,7 +468,7 @@ iterate_over_symtabs (const char *name,
absolutizing a relative path. */ absolutizing a relative path. */
if (IS_ABSOLUTE_PATH (name)) if (IS_ABSOLUTE_PATH (name))
{ {
real_path.reset (gdb_realpath (name)); real_path = gdb_realpath (name);
gdb_assert (IS_ABSOLUTE_PATH (real_path.get ())); gdb_assert (IS_ABSOLUTE_PATH (real_path.get ()));
} }

View File

@ -1,3 +1,7 @@
2017-08-22 Tom Tromey <tom@tromey.com>
* gdb.gdb/xfullpath.exp: Remove.
2017-08-21 Pedro Alves <palves@redhat.com> 2017-08-21 Pedro Alves <palves@redhat.com>
PR gdb/19487 PR gdb/19487

View File

@ -1,60 +0,0 @@
# Copyright 2002-2017 Free Software Foundation, Inc.
# 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/>.
# This file was written by Joel Brobecker. (brobecker@gnat.com), derived
# from selftest.exp, written by Rob Savoye.
load_lib selftest-support.exp
proc test_with_self {} {
# A file which contains a directory prefix
gdb_test "print gdb_realpath (\"./xfullpath.exp\")" \
".\[0-9\]+ =.*\".*/xfullpath.exp\"" \
"A filename with ./ as the directory prefix"
# A file which contains a directory prefix
gdb_test "print gdb_realpath (\"../../defs.h\")" \
".\[0-9\]+ =.*\".*/defs.h\"" \
"A filename with ../ in the directory prefix"
# A one-character filename
gdb_test "print gdb_realpath (\"./a\")" \
".\[0-9\]+ =.*\".*/a\"" \
"A one-char filename in the current directory"
# A file in the root directory
gdb_test "print gdb_realpath (\"/root_file_which_should_exist\")" \
".\[0-9\]+ =.*\"/root_file_which_should_exist\"" \
"A filename in the root directory"
# A file which does not have a directory prefix
gdb_test "print gdb_realpath (\"xfullpath.exp\")" \
".\[0-9\]+ =.*\"xfullpath.exp\"" \
"A filename without any directory prefix"
# A one-char filename without any directory prefix
gdb_test "print gdb_realpath (\"a\")" \
".\[0-9\]+ =.*\"a\"" \
"A one-char filename without any directory prefix"
# An empty filename
gdb_test "print gdb_realpath (\"\")" \
".\[0-9\]+ =.*\"\"" \
"an empty filename"
return 0
}
do_self_tests captured_main test_with_self

View File

@ -66,6 +66,7 @@
#include "interps.h" #include "interps.h"
#include "gdb_regex.h" #include "gdb_regex.h"
#include "job-control.h" #include "job-control.h"
#include "common/selftest.h"
#if !HAVE_DECL_MALLOC #if !HAVE_DECL_MALLOC
extern PTR malloc (); /* ARI: PTR */ extern PTR malloc (); /* ARI: PTR */
@ -2662,7 +2663,7 @@ string_to_core_addr (const char *my_string)
return addr; return addr;
} }
char * gdb::unique_xmalloc_ptr<char>
gdb_realpath (const char *filename) gdb_realpath (const char *filename)
{ {
/* On most hosts, we rely on canonicalize_file_name to compute /* On most hosts, we rely on canonicalize_file_name to compute
@ -2698,21 +2699,57 @@ gdb_realpath (const char *filename)
we might not be able to display the original casing in a given we might not be able to display the original casing in a given
path. */ path. */
if (len > 0 && len < MAX_PATH) if (len > 0 && len < MAX_PATH)
return xstrdup (buf); return gdb::unique_xmalloc_ptr<char> (xstrdup (buf));
} }
#else #else
{ {
char *rp = canonicalize_file_name (filename); char *rp = canonicalize_file_name (filename);
if (rp != NULL) if (rp != NULL)
return rp; return gdb::unique_xmalloc_ptr<char> (rp);
} }
#endif #endif
/* This system is a lost cause, just dup the buffer. */ /* This system is a lost cause, just dup the buffer. */
return xstrdup (filename); return gdb::unique_xmalloc_ptr<char> (xstrdup (filename));
} }
#if GDB_SELF_TEST
static void
gdb_realpath_check_trailer (const char *input, const char *trailer)
{
gdb::unique_xmalloc_ptr<char> result = gdb_realpath (input);
size_t len = strlen (result.get ());
size_t trail_len = strlen (trailer);
SELF_CHECK (len >= trail_len
&& strcmp (result.get () + len - trail_len, trailer) == 0);
}
static void
gdb_realpath_tests ()
{
/* A file which contains a directory prefix. */
gdb_realpath_check_trailer ("./xfullpath.exp", "/xfullpath.exp");
/* A file which contains a directory prefix. */
gdb_realpath_check_trailer ("../../defs.h", "/defs.h");
/* A one-character filename. */
gdb_realpath_check_trailer ("./a", "/a");
/* A file in the root directory. */
gdb_realpath_check_trailer ("/root_file_which_should_exist",
"/root_file_which_should_exist");
/* A file which does not have a directory prefix. */
gdb_realpath_check_trailer ("xfullpath.exp", "xfullpath.exp");
/* A one-char filename without any directory prefix. */
gdb_realpath_check_trailer ("a", "a");
/* An empty filename. */
gdb_realpath_check_trailer ("", "");
}
#endif /* GDB_SELF_TEST */
/* Return a copy of FILENAME, with its directory prefix canonicalized /* Return a copy of FILENAME, with its directory prefix canonicalized
by gdb_realpath. */ by gdb_realpath. */
@ -2721,7 +2758,6 @@ gdb_realpath_keepfile (const char *filename)
{ {
const char *base_name = lbasename (filename); const char *base_name = lbasename (filename);
char *dir_name; char *dir_name;
char *real_path;
char *result; char *result;
/* Extract the basename of filename, and return immediately /* Extract the basename of filename, and return immediately
@ -2749,13 +2785,13 @@ gdb_realpath_keepfile (const char *filename)
/* Canonicalize the directory prefix, and build the resulting /* Canonicalize the directory prefix, and build the resulting
filename. If the dirname realpath already contains an ending filename. If the dirname realpath already contains an ending
directory separator, avoid doubling it. */ directory separator, avoid doubling it. */
real_path = gdb_realpath (dir_name); 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])) if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
result = concat (real_path, base_name, (char *) NULL); result = concat (real_path, base_name, (char *) NULL);
else else
result = concat (real_path, SLASH_STRING, base_name, (char *) NULL); result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
xfree (real_path);
return gdb::unique_xmalloc_ptr<char> (result); return gdb::unique_xmalloc_ptr<char> (result);
} }
@ -3283,4 +3319,8 @@ _initialize_utils (void)
add_internal_problem_command (&internal_error_problem); add_internal_problem_command (&internal_error_problem);
add_internal_problem_command (&internal_warning_problem); add_internal_problem_command (&internal_warning_problem);
add_internal_problem_command (&demangler_warning_problem); add_internal_problem_command (&demangler_warning_problem);
#if GDB_SELF_TEST
selftests::register_test (gdb_realpath_tests);
#endif
} }

View File

@ -252,7 +252,7 @@ extern struct cleanup *make_bpstat_clear_actions_cleanup (void);
/* Path utilities. */ /* Path utilities. */
extern char *gdb_realpath (const char *); extern gdb::unique_xmalloc_ptr<char> gdb_realpath (const char *);
extern gdb::unique_xmalloc_ptr<char> gdb_realpath_keepfile (const char *); extern gdb::unique_xmalloc_ptr<char> gdb_realpath_keepfile (const char *);