Skip to content

Commit 4ee1c6f

Browse files
authored
Add Fiddle::Handle#file_name (#88)
1 parent c5abcc3 commit 4ee1c6f

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

ext/fiddle/extconf.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ def enable_debug_build_flag(flags)
187187
end
188188

189189
have_header 'sys/mman.h'
190+
have_header 'link.h'
190191

191192
if have_header "dlfcn.h"
192193
have_library "dl"
@@ -196,8 +197,10 @@ def enable_debug_build_flag(flags)
196197
end
197198

198199
have_func "dlerror"
200+
have_func "dlinfo"
201+
have_const("RTLD_DI_LINKMAP", "dlfcn.h")
199202
elsif have_header "windows.h"
200-
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
203+
%w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func|
201204
abort "missing function #{func}" unless have_func(func)
202205
end
203206

ext/fiddle/fiddle.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include <sys/mman.h>
1313
#endif
1414

15+
#if defined(HAVE_LINK_H)
16+
# include <link.h>
17+
#endif
18+
1519
#if defined(HAVE_DLFCN_H)
1620
# include <dlfcn.h>
1721
# /* some stranger systems may not define all of these */

ext/fiddle/handle.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,48 @@ fiddle_handle_sym(void *handle, VALUE symbol)
386386
return PTR2NUM(func);
387387
}
388388

389+
/*
390+
* call-seq: file_name
391+
*
392+
* Returns the file name of this handle.
393+
*/
394+
static VALUE
395+
rb_fiddle_handle_file_name(VALUE self)
396+
{
397+
struct dl_handle *fiddle_handle;
398+
399+
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
400+
401+
#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP)
402+
{
403+
struct link_map *lm = NULL;
404+
int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm);
405+
if (res == 0 && lm != NULL) {
406+
return rb_str_new_cstr(lm->l_name);
407+
}
408+
else {
409+
#if defined(HAVE_DLERROR)
410+
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
411+
#else
412+
rb_raise(rb_eFiddleDLError, "could not get handle file name");
413+
#endif
414+
}
415+
}
416+
#elif defined(HAVE_GETMODULEFILENAME)
417+
{
418+
char filename[MAX_PATH];
419+
DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH);
420+
if (res == 0) {
421+
rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
422+
}
423+
return rb_str_new_cstr(filename);
424+
}
425+
#else
426+
(void)fiddle_handle;
427+
return Qnil;
428+
#endif
429+
}
430+
389431
void
390432
Init_fiddle_handle(void)
391433
{
@@ -484,6 +526,7 @@ Init_fiddle_handle(void)
484526
rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
485527
rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
486528
rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
529+
rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0);
487530
rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
488531
rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
489532
rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0);

test/fiddle/test_handle.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ def test_disable_close
112112
assert !handle.close_enabled?, 'close is enabled'
113113
end
114114

115+
def test_file_name
116+
handle = Handle.new(LIBC_SO)
117+
assert_kind_of String, handle.file_name
118+
assert_equal File.basename(handle.file_name), File.basename(LIBC_SO)
119+
end unless /darwin/ =~ RUBY_PLATFORM
120+
115121
def test_NEXT
116122
begin
117123
# Linux / Darwin

0 commit comments

Comments
 (0)