From c3ad34c7fa7222ef6003ca83a3d9b17c80caa9ef Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 24 Jan 2015 12:24:27 +0000 Subject: [PATCH] ruby.c: replace with real path * ruby.c (dladdr_path): replace the executable path with symlinked real path. dladdr(3) on Linux returns the argv[0] as dli_fname instead of the real path, for a symbol defined in the executable file itself. [Bug #10776] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49394 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- file.c | 4 ++-- ruby.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/file.c b/file.c index dd05bb7038..01370030fe 100644 --- a/file.c +++ b/file.c @@ -2745,7 +2745,7 @@ rb_file_s_symlink(VALUE klass, VALUE from, VALUE to) #endif #ifdef HAVE_READLINK -static VALUE rb_readlink(VALUE path); +VALUE rb_readlink(VALUE path); /* * call-seq: @@ -2764,7 +2764,7 @@ rb_file_s_readlink(VALUE klass, VALUE path) return rb_readlink(path); } -static VALUE +VALUE rb_readlink(VALUE path) { int size = 100; diff --git a/ruby.c b/ruby.c index 9014ccdc24..51a606f8bc 100644 --- a/ruby.c +++ b/ruby.c @@ -364,6 +364,32 @@ ruby_init_loadpath(void) ruby_init_loadpath_safe(0); } +#if defined(HAVE_DLADDR) +static VALUE +dladdr_path(const void* addr) +{ + Dl_info dli; + VALUE fname, path; + + if (!dladdr(addr, &dli)) { + return rb_str_new(0, 0); + } +#ifdef __linux__ + else if (dli.dli_fname == origarg.argv[0]) { + VALUE rb_readlink(VALUE); + fname = rb_str_new_cstr("/proc/self/exe"); + path = rb_readlink(fname); + } +#endif + else { + fname = rb_str_new_cstr(dli.dli_fname); + path = rb_realpath_internal(Qnil, fname, 1); + } + rb_str_resize(fname, 0); + return path; +} +#endif + void ruby_init_loadpath_safe(int safe_level) { @@ -392,17 +418,7 @@ ruby_init_loadpath_safe(int safe_level) #elif defined(__EMX__) _execname(libpath, sizeof(libpath) - 1); #elif defined(HAVE_DLADDR) - Dl_info dli; - if (dladdr((void *)(VALUE)expand_include_path, &dli)) { - char fbuf[MAXPATHLEN]; - char *f = dln_find_file_r(dli.dli_fname, getenv(PATH_ENV), fbuf, sizeof(fbuf)); - VALUE fname = rb_str_new_cstr(f ? f : dli.dli_fname); - rb_str_freeze(fname); - sopath = rb_realpath_internal(Qnil, fname, 1); - } - else { - sopath = rb_str_new(0, 0); - } + sopath = dladdr_path((void *)(VALUE)expand_include_path); libpath = RSTRING_PTR(sopath); #endif