Skip to content

Commit

Permalink
Fixes #3736. File.open ignores :universal_newline options on Windows
Browse files Browse the repository at this point in the history
enebo committed Mar 16, 2016
1 parent 0eb7422 commit 18121a7
Showing 4 changed files with 46 additions and 2 deletions.
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -1332,7 +1332,7 @@ protected void sysopenInternal19(String path, int oflags, int perm) {
}

ChannelDescriptor descriptor = sysopen(path, modes, perm);
openFile.setMainStream(fdopen(descriptor, modes));
openFile.setMainStream(reprocessStreamInCaseECOptsWantsCRLF(fdopen(descriptor, modes), modes));
}

protected void openInternal(String path, String modeString) {
20 changes: 19 additions & 1 deletion core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
import org.jruby.runtime.Helpers;
import org.jruby.util.ResourceException;
import org.jruby.util.StringSupport;
import org.jruby.util.io.CRLFStreamWrapper;
import org.jruby.util.io.DirectoryAsFileException;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.io.FileExistsException;
@@ -318,6 +319,23 @@ public Stream getHandler() throws BadDescriptorException {
return getOpenFileChecked().getMainStreamSafe();
}

// FIXME: This is a bit wonky. 1.9 uses this special stream wrapper on windows but at the
// location it is created we do not have access to ecflags and their newline processing
// preferences. So this check was added to strip off crlf conversion if one of the IO
// options from ECONV says not to.
protected Stream reprocessStreamInCaseECOptsWantsCRLF(Stream fd, ModeFlags modes) {
// FIXME: I do not understand how a 1.8 path hits this since this is only called
// from open methods that end in 19?
if (getRuntime().is1_9() && Platform.IS_WINDOWS && !modes.isBinary() &&
(ecflags & EncodingUtils.ECONV_UNIVERSAL_NEWLINE_DECORATOR) == 0 &&
(ecflags & EncodingUtils.ECONV_CRLF_NEWLINE_DECORATOR) == 0 &&
fd instanceof CRLFStreamWrapper) {
return ((CRLFStreamWrapper) fd).getOriginalStream();
}

return fd;
}

protected void reopenPath(Ruby runtime, IRubyObject[] args) {
IRubyObject pathString;

@@ -896,7 +914,7 @@ private IRubyObject initializeCommon19(ThreadContext context, int fileno, IRubyO
ModeFlags modes = ModeFlags.createModeFlags(oflags_p[0]);

openFile.setMode(fmode_p[0]);
openFile.setMainStream(fdopen(descriptor, modes));
openFile.setMainStream(reprocessStreamInCaseECOptsWantsCRLF(fdopen(descriptor, modes), modes));
clearCodeConversion();

// io_check_tty(fp);
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/util/io/CRLFStreamWrapper.java
Original file line number Diff line number Diff line change
@@ -33,6 +33,10 @@ public ChannelDescriptor getDescriptor() {
return stream.getDescriptor();
}

public Stream getOriginalStream() {
return stream;
}

public void clearerr() {
stream.clearerr();
}
22 changes: 22 additions & 0 deletions core/src/main/java/org/jruby/util/io/EncodingUtils.java
Original file line number Diff line number Diff line change
@@ -64,6 +64,28 @@ public class EncodingUtils {

private static final byte[] NULL_BYTE_ARRAY = new byte[0];

public static String printECFlags(int flags) {
StringBuilder builder = new StringBuilder();

if ((flags & ECONV_ERROR_HANDLER_MASK) != 0) builder.append("ERROR_HANDLING ");
if ((flags & ECONV_INVALID_MASK) != 0) builder.append("INVALID_HANDLING ");
if ((flags & ECONV_DECORATOR_MASK) != 0) {
builder.append("DECORATOR_HANDLING ");

if ((flags & ECONV_UNIVERSAL_NEWLINE_DECORATOR) != 0) builder.append("UNIVERSAL NEWLINE ");
if ((flags & ECONV_CRLF_NEWLINE_DECORATOR) != 0) builder.append("CRLF NEWLINE ");
if ((flags & ECONV_CR_NEWLINE_DECORATOR) != 0) builder.append("CR NEWLINE ");
if ((flags & ECONV_XML_TEXT_DECORATOR) != 0) builder.append("XMLTEXT ");
if ((flags & ECONV_XML_ATTR_CONTENT_DECORATOR) != 0) builder.append("XMLATTRCONTENT ");

}
if ((flags & ECONV_STATEFUL_DECORATOR_MASK) != 0) builder.append("ERROR_HANDLING ");
if ((flags & ECONV_PARTIAL_INPUT) != 0) builder.append("PARTIAL INPUT ");
if ((flags & ECONV_AFTER_OUTPUT) != 0) builder.append("AFTER OUTPUT ");

return builder.toString();
}

// rb_to_encoding
public static Encoding rbToEncoding(ThreadContext context, IRubyObject enc) {
if (enc instanceof RubyEncoding) return ((RubyEncoding) enc).getEncoding();

0 comments on commit 18121a7

Please sign in to comment.