summaryrefslogtreecommitdiff
path: root/ext/fiddle
diff options
context:
space:
mode:
authorKenta Murata <mrkn@users.noreply.github.com>2021-07-14 15:51:26 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-07-14 18:56:00 +0900
commit67897762cf3cabad99effd636b50a2db26fb0f3f (patch)
treea3b5391692c2f3b2ca33a480b192eea9491f0dbc /ext/fiddle
parent169529a0c0973fa925ad3b36f4427d31e802a37e (diff)
[ruby/fiddle] Add Fiddle::Handle#file_name (https://github.com/ruby/fiddle/pull/88)
https://github.com/ruby/fiddle/commit/4ee1c6fc4b
Diffstat (limited to 'ext/fiddle')
-rw-r--r--ext/fiddle/extconf.rb5
-rw-r--r--ext/fiddle/fiddle.h4
-rw-r--r--ext/fiddle/handle.c43
3 files changed, 51 insertions, 1 deletions
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
index 8cc98fb8f6..053456d534 100644
--- a/ext/fiddle/extconf.rb
+++ b/ext/fiddle/extconf.rb
@@ -187,6 +187,7 @@ else
end
have_header 'sys/mman.h'
+have_header 'link.h'
if have_header "dlfcn.h"
have_library "dl"
@@ -196,8 +197,10 @@ if have_header "dlfcn.h"
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
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
index bf97b59d53..9de62a58cc 100644
--- a/ext/fiddle/fiddle.h
+++ b/ext/fiddle/fiddle.h
@@ -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 */
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
index a4a32f1ecb..76b90909d3 100644
--- a/ext/fiddle/handle.c
+++ b/ext/fiddle/handle.c
@@ -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)
{
@@ -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);