diff --git a/ChangeLog b/ChangeLog index f16f57eb01..e748f6b193 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Fri Sep 5 00:29:08 2014 Tanaka Akira + + * configure.in (dirfd): Check function. + + * dir.c (dir_fileno): New method. + [ruby-dev:48265] [Feature #9880] + Thu Sep 4 23:39:52 2014 Tanaka Akira * process.c (has_privilege): New function. diff --git a/NEWS b/NEWS index 2754d8cc08..0a8de5fbcc 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,10 @@ with all sufficient information, see the ChangeLog file. * Binding#local_variables * Binding#receiver +* Dir + * New methods: + * Dir#fileno + * Enumerable * New methods: * Enumerable#slice_after diff --git a/configure.in b/configure.in index 9080ab7559..7934df7e86 100644 --- a/configure.in +++ b/configure.in @@ -1974,6 +1974,7 @@ AC_CHECK_FUNCS(chsize) AC_CHECK_FUNCS(clock_gettime) AC_CHECK_FUNCS(cosh) AC_CHECK_FUNCS(daemon) +AC_CHECK_FUNCS(dirfd) AC_CHECK_FUNCS(dl_iterate_phdr) AC_CHECK_FUNCS(dlopen) AC_CHECK_FUNCS(dladdr) diff --git a/dir.c b/dir.c index b915c4be41..09b78c6b4b 100644 --- a/dir.c +++ b/dir.c @@ -539,6 +539,37 @@ dir_inspect(VALUE dir) return rb_funcall(dir, rb_intern("to_s"), 0, 0); } +#ifdef HAVE_DIRFD +/* + * call-seq: + * dir.fileno -> integer + * + * Returns the file descriptor used in dir. + * + * d = Dir.new("..") + * d.fileno #=> 8 + * + * This method uses dirfd() function defined by POSIX 2008. + * NotImplementedError is raised on other platforms, such as Windows, + * which doesn't provide the function. + * + */ +static VALUE +dir_fileno(VALUE dir) +{ + struct dir_data *dirp; + int fd; + + GetDIR(dir, dirp); + fd = dirfd(dirp->dir); + if (fd == -1) + rb_sys_fail("dirfd"); + return INT2NUM(fd); +} +#else +#define dir_fileno rb_f_notimplement +#endif + /* * call-seq: * dir.path -> string or nil @@ -2259,6 +2290,7 @@ Init_Dir(void) rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1); rb_define_method(rb_cDir,"initialize", dir_initialize, -1); + rb_define_method(rb_cDir,"fileno", dir_fileno, 0); rb_define_method(rb_cDir,"path", dir_path, 0); rb_define_method(rb_cDir,"to_path", dir_path, 0); rb_define_method(rb_cDir,"inspect", dir_inspect, 0); diff --git a/ext/-test-/dir/extconf.rb b/ext/-test-/dir/extconf.rb deleted file mode 100644 index ce4aad142a..0000000000 --- a/ext/-test-/dir/extconf.rb +++ /dev/null @@ -1,9 +0,0 @@ -have_func("dirfd") - -$INCFLAGS << " -I$(topdir) -I$(top_srcdir)" -$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")] -inits = $srcs.map {|s| File.basename(s, ".*")} -inits.delete("init") -inits.map! {|s|"X(#{s})"} -$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\"" -create_makefile("-test-/dir") diff --git a/ext/-test-/dir/fileno.c b/ext/-test-/dir/fileno.c deleted file mode 100644 index 4872942973..0000000000 --- a/ext/-test-/dir/fileno.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "ruby.h" -#include "ruby/encoding.h" -#include "internal.h" - -#if defined HAVE_DIRENT_H && !defined _WIN32 -# include -#elif defined HAVE_DIRECT_H && !defined _WIN32 -# include -#else -# define dirent direct -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -# ifdef _WIN32 -# include "win32/dir.h" -# endif -#endif -#if defined(__native_client__) && defined(NACL_NEWLIB) -# include "nacl/dirent.h" -# include "nacl/stat.h" -#endif - -struct dir_data { - DIR *dir; - VALUE path; - rb_encoding *enc; -}; - -#ifdef HAVE_DIRFD -static void * -rb_check_typeddata0(VALUE obj /*, const rb_data_type_t *data_type */) -{ - const char *etype; - /* static const char mesg[] = "wrong argument type %s (expected %s)"; */ - - if (!RB_TYPE_P(obj, T_DATA)) { - etype = rb_builtin_class_name(obj); - /* rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); */ - rb_raise(rb_eTypeError, "wrong argument type %s", etype); - } -/* - if (!RTYPEDDATA_P(obj)) { - etype = rb_obj_classname(obj); - rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); - } - else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) { - etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name; - rb_raise(rb_eTypeError, mesg, etype, data_type->wrap_struct_name); - } -*/ - return DATA_PTR(obj); -} - -static void -dir_closed(void) -{ - rb_raise(rb_eIOError, "closed directory"); -} - -static struct dir_data * -dir_check(VALUE dir) -{ - struct dir_data *dirp; - rb_check_frozen(dir); - dirp = rb_check_typeddata0(dir /*, &dir_data_type*/); - if (!dirp->dir) dir_closed(); - return dirp; -} -#endif - -#define GetDIR(obj, dirp) ((dirp) = dir_check(obj)) - -#ifdef HAVE_DIRFD -/* - * call-seq: - * dir.fileno -> integer - * - * Returns the file descriptor used in dir. - * - * d = Dir.new("..") - * d.fileno #=> 8 - */ -static VALUE -dir_fileno(VALUE dir) -{ - struct dir_data *dirp; - int fd; - - GetDIR(dir, dirp); - fd = dirfd(dirp->dir); - if (fd == -1) - rb_sys_fail("dirfd"); - return INT2NUM(fd); -} -#else -#define dir_fileno rb_f_notimplement -#endif - -void -Init_fileno(VALUE klass) -{ - rb_define_method(rb_cDir,"fileno", dir_fileno, 0); -} diff --git a/ext/-test-/dir/init.c b/ext/-test-/dir/init.c deleted file mode 100644 index 2ca1508468..0000000000 --- a/ext/-test-/dir/init.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "ruby.h" - -#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);} - -void -Init_dir(void) -{ - VALUE mBug = rb_define_module("Bug"); - VALUE klass = rb_define_class_under(mBug, "Dir", rb_cObject); - TEST_INIT_FUNCS(init); -} diff --git a/test/lib/leakchecker.rb b/test/lib/leakchecker.rb index 599141d609..b6ed19e9c4 100644 --- a/test/lib/leakchecker.rb +++ b/test/lib/leakchecker.rb @@ -15,7 +15,6 @@ class LeakChecker def find_fds fd_dir = "/proc/self/fd" if File.directory?(fd_dir) - require "-test-/dir" fds = Dir.open(fd_dir) {|d| a = d.grep(/\A\d+\z/, &:to_i) if d.respond_to? :fileno diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb index 4ce3944cfc..ee1210cc37 100644 --- a/test/ruby/test_dir.rb +++ b/test/ruby/test_dir.rb @@ -294,4 +294,14 @@ class TestDir < Test::Unit::TestCase end end end + + def test_fileno + Dir.open(".") {|d| + if d.respond_to? :fileno + assert_kind_of(Integer, d.fileno) + else + assert_raise(NotImplementedError) { d.fileno } + end + } + end end