diff --git a/core/src/main/java/org/jruby/RubyIO.java b/core/src/main/java/org/jruby/RubyIO.java index a4c63d0fb54..3f32bcdc4d6 100644 --- a/core/src/main/java/org/jruby/RubyIO.java +++ b/core/src/main/java/org/jruby/RubyIO.java @@ -46,6 +46,7 @@ import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SeekableByteChannel; import java.nio.channels.SelectionKey; import java.nio.channels.WritableByteChannel; import java.util.Arrays; @@ -65,6 +66,7 @@ import org.jcodings.specific.ASCIIEncoding; import org.jcodings.transcode.EConvFlags; import org.jruby.api.API; +import org.jruby.api.Error; import org.jruby.ast.util.ArgsUtil; import org.jruby.anno.JRubyMethod; import org.jruby.anno.JRubyClass; @@ -4813,6 +4815,10 @@ private static RubyFixnum copyStreamCommon(ThreadContext context, IRubyObject ar try { if (arg1 == runtime.getArgsFile() || !(arg1 instanceof RubyFile || arg1 instanceof RubyString || arg1.respondsTo("to_path"))) { + if (offset != null) { + throw Error.argumentError(context, "cannot specify src_offset for non-IO"); + } + if (sites.respond_to_readpartial.respondsTo(context, arg1, arg1, true)) { channel1 = new IOChannel.IOReadableByteChannel(arg1, "readpartial"); } else if (sites.respond_to_read.respondsTo(context, arg1, arg1, true)) { @@ -4999,11 +5005,15 @@ private static long transfer(ThreadContext context, ReadableByteChannel from, Wr long transferred = 0; if (position != -1) { - if (from instanceof NativeSelectableChannel) { - int ret = context.runtime.getPosix().lseek(((NativeSelectableChannel)from).getFD(), position, PosixShim.SEEK_SET); + if (from instanceof NativeSelectableChannel nativeSelectableChannel) { + int ret = context.runtime.getPosix().lseek(nativeSelectableChannel.getFD(), position, PosixShim.SEEK_SET); if (ret == -1) { throw context.runtime.newErrnoFromErrno(Errno.valueOf(context.runtime.getPosix().errno()), from.toString()); } + } else if (from instanceof SeekableByteChannel seekableByteChannel) { + seekableByteChannel.position(position); + } else { + throw context.runtime.newErrnoESPIPEError(); } } diff --git a/spec/tags/ruby/core/io/copy_stream_tags.txt b/spec/tags/ruby/core/io/copy_stream_tags.txt index f594d72b697..fec1b97e907 100644 --- a/spec/tags/ruby/core/io/copy_stream_tags.txt +++ b/spec/tags/ruby/core/io/copy_stream_tags.txt @@ -1,4 +1,3 @@ -fails:IO.copy_stream from a pipe IO raises an error when an offset is specified windows:IO.copy_stream from an IO to a file name copies only length bytes from the offset windows:IO.copy_stream from an IO to an IO copies only length bytes from the offset windows:IO.copy_stream from a file name to a file name copies only length bytes from the offset