Skip to content

Commit

Permalink
[ruby/fiddle] Add Fiddle::Handle#file_name (ruby/fiddle#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkn authored and nobu committed Jul 14, 2021
1 parent 169529a commit 6789776
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 1 deletion.
5 changes: 4 additions & 1 deletion ext/fiddle/extconf.rb
Expand Up @@ -187,6 +187,7 @@ def enable_debug_build_flag(flags)
end

have_header 'sys/mman.h'
have_header 'link.h'

if have_header "dlfcn.h"
have_library "dl"
Expand All @@ -196,8 +197,10 @@ def enable_debug_build_flag(flags)
end

have_func "dlerror"
have_func "dlinfo"
have_const("RTLD_DI_LINKMAP", "dlfcn.h")
elsif have_header "windows.h"
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
%w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func|
abort "missing function #{func}" unless have_func(func)
end

Expand Down
4 changes: 4 additions & 0 deletions ext/fiddle/fiddle.h
Expand Up @@ -12,6 +12,10 @@
#include <sys/mman.h>
#endif

#if defined(HAVE_LINK_H)
# include <link.h>
#endif

#if defined(HAVE_DLFCN_H)
# include <dlfcn.h>
# /* some stranger systems may not define all of these */
Expand Down
43 changes: 43 additions & 0 deletions ext/fiddle/handle.c
Expand Up @@ -386,6 +386,48 @@ fiddle_handle_sym(void *handle, VALUE symbol)
return PTR2NUM(func);
}

/*
* call-seq: file_name
*
* Returns the file name of this handle.
*/
static VALUE
rb_fiddle_handle_file_name(VALUE self)
{
struct dl_handle *fiddle_handle;

TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);

#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP)
{
struct link_map *lm = NULL;
int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm);
if (res == 0 && lm != NULL) {
return rb_str_new_cstr(lm->l_name);
}
else {
#if defined(HAVE_DLERROR)
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
#else
rb_raise(rb_eFiddleDLError, "could not get handle file name");
#endif
}
}
#elif defined(HAVE_GETMODULEFILENAME)
{
char filename[MAX_PATH];
DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH);
if (res == 0) {
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
}
return rb_str_new_cstr(filename);
}
#else
(void)fiddle_handle;
return Qnil;
#endif
}

void
Init_fiddle_handle(void)
{
Expand Down Expand Up @@ -484,6 +526,7 @@ Init_fiddle_handle(void)
rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0);
rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0);
Expand Down
6 changes: 6 additions & 0 deletions test/fiddle/test_handle.rb
Expand Up @@ -112,6 +112,12 @@ def test_disable_close
assert !handle.close_enabled?, 'close is enabled'
end

def test_file_name
handle = Handle.new(LIBC_SO)
assert_kind_of String, handle.file_name
assert_equal File.basename(handle.file_name), File.basename(LIBC_SO)
end unless /darwin/ =~ RUBY_PLATFORM

def test_NEXT
begin
# Linux / Darwin
Expand Down

0 comments on commit 6789776

Please sign in to comment.