Skip to content

Commit

Permalink
Handle unseekable sources better
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Jun 19, 2024
1 parent eae532f commit 2e6d251
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 3 deletions.
14 changes: 12 additions & 2 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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();
}
}

Expand Down
1 change: 0 additions & 1 deletion spec/tags/ruby/core/io/copy_stream_tags.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit 2e6d251

Please sign in to comment.