summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrbgems/mruby-io/README.md2
-rw-r--r--mrbgems/mruby-io/src/io.c64
-rw-r--r--mrbgems/mruby-io/test/io.rb29
3 files changed, 93 insertions, 2 deletions
diff --git a/mrbgems/mruby-io/README.md b/mrbgems/mruby-io/README.md
index 0f50e24ec..256fb8195 100644
--- a/mrbgems/mruby-io/README.md
+++ b/mrbgems/mruby-io/README.md
@@ -40,7 +40,7 @@ Add the line below to your `build_config.rb`:
| IO#binmode? | | |
| IO#bytes | | obsolete |
| IO#chars | | obsolete |
-| IO#clone, IO#dup | | |
+| IO#clone, IO#dup | o | |
| IO#close | o | |
| IO#close_on_exec= | o | |
| IO#close_on_exec? | o | |
diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c
index afd6dc7c3..21a733b00 100644
--- a/mrbgems/mruby-io/src/io.c
+++ b/mrbgems/mruby-io/src/io.c
@@ -25,6 +25,8 @@
#include <io.h>
#define open _open
#define close _close
+ #define dup _dup
+ #define dup2 _dup2
#define read _read
#define write _write
#define lseek _lseek
@@ -33,12 +35,15 @@
typedef int fsize_t;
typedef long ftime_t;
typedef long fsuseconds_t;
+ typedef int fmode_t;
+
#else
#include <sys/wait.h>
#include <unistd.h>
typedef size_t fsize_t;
typedef time_t ftime_t;
typedef suseconds_t fsuseconds_t;
+ typedef mode_t fmode_t;
#endif
#ifdef _MSC_VER
@@ -530,6 +535,62 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
}
#endif
+static int
+mrb_dup(mrb_state *mrb, int fd, mrb_bool *failed)
+{
+ int new_fd;
+
+ *failed = FALSE;
+ if (fd < 0)
+ return fd;
+
+ new_fd = dup(fd);
+ if (new_fd == -1) *failed = TRUE;
+ return new_fd;
+}
+
+mrb_value
+mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value orig;
+ mrb_value buf;
+ struct mrb_io *fptr_copy;
+ struct mrb_io *fptr_orig;
+ mrb_bool failed = TRUE;
+
+ mrb_get_args(mrb, "o", &orig);
+ fptr_copy = (struct mrb_io *)DATA_PTR(copy);
+ if (fptr_copy != NULL) {
+ fptr_finalize(mrb, fptr_copy, FALSE);
+ mrb_free(mrb, fptr_copy);
+ }
+ fptr_copy = (struct mrb_io *)mrb_io_alloc(mrb);
+ fptr_orig = io_get_open_fptr(mrb, orig);
+
+ DATA_TYPE(copy) = &mrb_io_type;
+ DATA_PTR(copy) = fptr_copy;
+
+ buf = mrb_iv_get(mrb, orig, mrb_intern_cstr(mrb, "@buf"));
+ mrb_iv_set(mrb, copy, mrb_intern_cstr(mrb, "@buf"), buf);
+
+ fptr_copy->fd = mrb_dup(mrb, fptr_orig->fd, &failed);
+ if (failed) {
+ mrb_sys_fail(mrb, 0);
+ }
+ fptr_copy->fd2 = mrb_dup(mrb, fptr_orig->fd2, &failed);
+ if (failed) {
+ close(fptr_copy->fd);
+ mrb_sys_fail(mrb, 0);
+ }
+ fptr_copy->pid = fptr_orig->pid;
+ fptr_copy->readable = fptr_orig->readable;
+ fptr_copy->writable = fptr_orig->writable;
+ fptr_copy->sync = fptr_orig->sync;
+ fptr_copy->is_socket = fptr_orig->is_socket;
+
+ return copy;
+}
+
mrb_value
mrb_io_initialize(mrb_state *mrb, mrb_value io)
{
@@ -691,7 +752,7 @@ mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mo
flags |= O_NOINHERIT;
#endif
reopen:
- fd = open(fname, (int)flags, mode);
+ fd = open(fname, (int)flags, (fmode_t)mode);
if (fd == -1) {
if (!retry) {
switch (errno) {
@@ -1238,6 +1299,7 @@ mrb_init_io(mrb_state *mrb)
#endif
mrb_define_method(mrb, io, "initialize", mrb_io_initialize, MRB_ARGS_ANY()); /* 15.2.20.5.21 (x)*/
+ mrb_define_method(mrb, io, "initialize_copy", mrb_io_initialize_copy, MRB_ARGS_REQ(1));
mrb_define_method(mrb, io, "_check_readable", mrb_io_check_readable, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "isatty", mrb_io_isatty, MRB_ARGS_NONE());
mrb_define_method(mrb, io, "sync", mrb_io_sync, MRB_ARGS_NONE());
diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb
index 9a6328ea4..96c3495d0 100644
--- a/mrbgems/mruby-io/test/io.rb
+++ b/mrbgems/mruby-io/test/io.rb
@@ -211,6 +211,35 @@ assert('IO#<<') do
true
end
+assert('IO#dup for readable') do
+ io = IO.new(IO.sysopen($mrbtest_io_rfname))
+ dup = io.dup
+ assert_true io != dup
+ assert_true io.fileno != dup.fileno
+ assert_equal 'm', dup.sysread(1)
+ assert_equal 'r', io.sysread(1)
+ assert_equal 'u', dup.sysread(1)
+ assert_equal 'b', io.sysread(1)
+ assert_equal 'y', dup.sysread(1)
+ dup.close
+ assert_false io.closed?
+ io.close
+ true
+end
+
+assert('IO#dup for writable') do
+ io = IO.open(IO.sysopen($mrbtest_io_wfname, 'w+'), 'w+')
+ dup = io.dup
+ io.syswrite "mruby"
+ assert_equal 5, dup.sysseek(0, IO::SEEK_CUR)
+ io.sysseek 0, IO::SEEK_SET
+ assert_equal 0, dup.sysseek(0, IO::SEEK_CUR)
+ assert_equal "mruby", dup.sysread(5)
+ dup.close
+ io.close
+ true
+end
+
assert('IO.for_fd') do
fd = IO.sysopen($mrbtest_io_rfname)
io = IO.for_fd(fd)