Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    **** BEGIN LICENSE BLOCK *****
    * Version: EPL 1.0/GPL 2.0/LGPL 2.1
    *
    * The contents of this file are subject to the Eclipse Public
    * License Version 1.0 (the "License"); you may not use this file
    * except in compliance with the License. You may obtain a copy of
    * the License at http://www.eclipse.org/legal/epl-v10.html
    *
   * Software distributed under the License is distributed on an "AS
   * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
   * implied. See the License for the specific language governing
   * rights and limitations under the License.
   *
   * Copyright (C) 2001-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
   * Copyright (C) 2002 Benoit Cerrina <b.cerrina@wanadoo.fr>
   * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
   * Copyright (C) 2002-2006 Thomas E Enebo <enebo@acm.org>
   * Copyright (C) 2004-2006 Charles O Nutter <headius@headius.com>
   * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
   * Copyright (C) 2006 Evan Buswell <ebuswell@gmail.com>
   * Copyright (C) 2007 Miguel Covarrubias <mlcovarrubias@gmail.com>
   * 
   * Alternatively, the contents of this file may be used under the terms of
   * either of the GNU General Public License Version 2 or later (the "GPL"),
   * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   * in which case the provisions of the GPL or the LGPL are applicable instead
   * of those above. If you wish to allow use of your version of this file only
   * under the terms of either the GPL or the LGPL, and not to allow others to
   * use your version of this file under the terms of the EPL, indicate your
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the EPL, the GPL or the LGPL.
   ***** END LICENSE BLOCK *****/
  package org.jruby;
  
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import static org.jruby.runtime.Visibility.*;
  
  
  import static org.jruby.CompatVersion.*;
 import static org.jruby.RubyEnumerator.enumeratorize;
 import static org.jruby.util.StringSupport.isIncompleteChar;

Author(s):
jpetersen
 
 @JRubyClass(name="IO", include="Enumerable")
 public class RubyIO extends RubyObject implements IOEncodable {
     // This should only be called by this and RubyFile.
     // It allows this object to be created without a IOHandler.
     public RubyIO(Ruby runtimeRubyClass type) {
         super(runtimetype);
     }
     
     public RubyIO(Ruby runtimeOutputStream outputStream) {
         this(runtimeoutputStreamtrue);
     }
 
     public RubyIO(Ruby runtimeOutputStream outputStreamboolean autoclose) {
         super(runtimeruntime.getIO());
         
         // We only want IO objects with valid streams (better to error now). 
         if (outputStream == null) {
             throw runtime.newRuntimeError("Opening null stream");
         }
         
          = new OpenFile();
         
         try {
             .setMainStream(ChannelStream.open(runtimenew ChannelDescriptor(Channels.newChannel(outputStream)), autoclose));
         } catch (InvalidValueException e) {
             throw getRuntime().newErrnoEINVALError();
         }
         
     }
     
     public RubyIO(Ruby runtimeInputStream inputStream) {
         super(runtimeruntime.getIO());
         
         if (inputStream == null) {
             throw runtime.newRuntimeError("Opening null stream");
         }
         
          = new OpenFile();
         
         try {
             .setMainStream(ChannelStream.open(runtimenew ChannelDescriptor(Channels.newChannel(inputStream))));
         } catch (InvalidValueException e) {
             throw getRuntime().newErrnoEINVALError();
         }
         
         .setMode(.);
     }
     
     public RubyIO(Ruby runtimeChannel channel) {
         super(runtimeruntime.getIO());
         
         // We only want IO objects with valid streams (better to error now). 
         if (channel == null) {
             throw runtime.newRuntimeError("Opening null channel");
         }
         
          = new OpenFile();
         
         try {
             .setMainStream(ChannelStream.open(runtimenew ChannelDescriptor(channel)));
         } catch (InvalidValueException e) {
             throw getRuntime().newErrnoEINVALError();
         }
         
     }
 
     public RubyIO(Ruby runtimeShellLauncher.POpenProcess processIOOptions ioOptions) {
         this(runtimeruntime.getIO(), processnullioOptions);
     }
     
     @Deprecated
     public RubyIO(Ruby runtimeRubyClass clsShellLauncher.POpenProcess processRubyHash optionsIOOptions ioOptions) {
         super(runtimecls);
 
         ioOptions = updateIOOptionsFromOptions(runtime.getCurrentContext(), (RubyHashoptionsioOptions);
 
          = new OpenFile();
         
         setupPopen(ioOptions.getModeFlags(), process);
     }
     
     public RubyIO(Ruby runtimeSTDIO stdio) {
         super(runtimeruntime.getIO());
         
          = new OpenFile();
         ChannelDescriptor descriptor;
         Stream mainStream;
 
         switch (stdio) {
         case :
             // special constructor that accepts stream, not channel
             descriptor = new ChannelDescriptor(runtime.getIn(), newModeFlags(runtime.), .);
             runtime.putFilenoMap(0, descriptor.getFileno());
             mainStream = ChannelStream.open(runtimedescriptor);
             .setMainStream(mainStream);
             break;
         case :
             descriptor = new ChannelDescriptor(Channels.newChannel(runtime.getOut()), newModeFlags(runtime. | .), .);
             runtime.putFilenoMap(1, descriptor.getFileno());
             mainStream = ChannelStream.open(runtimedescriptor);
             .setMainStream(mainStream);
             .getMainStream().setSync(true);
             break;
         case :
             descriptor = new ChannelDescriptor(Channels.newChannel(runtime.getErr()), newModeFlags(runtime. | .), .);
             runtime.putFilenoMap(2, descriptor.getFileno());
             mainStream = ChannelStream.open(runtimedescriptor);
             .setMainStream(mainStream);
             .getMainStream().setSync(true);
             break;
         }
 
         // never autoclose stdio streams
         .setAutoclose(false);
         .setStdio(true);
     }
     
     public static RubyIO newIO(Ruby runtimeChannel channel) {
         return new RubyIO(runtimechannel);
     }
     
     public OpenFile getOpenFile() {
         return ;
     }
     
     protected OpenFile getOpenFileChecked() {
         .checkClosed(getRuntime());
         return ;
     }
     
     private static ObjectAllocator IO_ALLOCATOR = new ObjectAllocator() {
         @Override
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new RubyIO(runtimeklass);
         }
     };
 
     /*
      * We use FILE versus IO to match T_FILE in MRI.
      */
     @Override
     public int getNativeTypeIndex() {
         return .;
     }
 
     public static RubyClass createIOClass(Ruby runtime) {
         RubyClass ioClass = runtime.defineClass("IO"runtime.getObject(), );
 
         ioClass.index = .;
         ioClass.setReifiedClass(RubyIO.class);
 
         ioClass.kindOf = new RubyModule.JavaClassKindOf(RubyIO.class);
 
         ioClass.includeModule(runtime.getEnumerable());
         
         // TODO: Implement tty? and isatty.  We have no real capability to
         // determine this from java, but if we could set tty status, then
         // we could invoke jruby differently to allow stdin to return true
         // on this.  This would allow things like cgi.rb to work properly.
         
         ioClass.defineAnnotatedMethods(RubyIO.class);
 
         // Constants for seek
         ioClass.setConstant("SEEK_SET"runtime.newFixnum(.));
         ioClass.setConstant("SEEK_CUR"runtime.newFixnum(.));
         ioClass.setConstant("SEEK_END"runtime.newFixnum(.));
 
         if (runtime.is1_9()) {
             ioClass.defineModuleUnder("WaitReadable");
             ioClass.defineModuleUnder("WaitWritable");
         }
 
         return ioClass;
     }
 
     public OutputStream getOutStream() {
         try {
             return getOpenFileChecked().getMainStreamSafe().newOutputStream();
         } catch (BadDescriptorException e) {
             throw getRuntime().newErrnoEBADFError();
         }
     }
 
     public InputStream getInStream() {
         try {
             return getOpenFileChecked().getMainStreamSafe().newInputStream();
         } catch (BadDescriptorException e) {
             throw getRuntime().newErrnoEBADFError();
         }
     }
 
     public Channel getChannel() {
         try {
             return getOpenFileChecked().getMainStreamSafe().getChannel();
         } catch (BadDescriptorException e) {
             throw getRuntime().newErrnoEBADFError();
         }
     }
 
     @Deprecated
     public Stream getHandler() throws BadDescriptorException {
         return getOpenFileChecked().getMainStreamSafe();
     }
 
     protected void reopenPath(Ruby runtimeIRubyObject[] args) {
         IRubyObject pathString;
         
         if (runtime.is1_9()) {
             pathString = RubyFile.get_path(runtime.getCurrentContext(), args[0]);
         } else {
             pathString = args[0].convertToString();
         }
 
         // TODO: check safe, taint on incoming string
 
         try {
             IOOptions modes;
             if (args.length > 1) {
                 IRubyObject modeString = args[1].convertToString();
                 modes = newIOOptions(runtimemodeString.toString());
 
                 .setMode(modes.getModeFlags().getOpenFileFlags());
             } else {
                 modes = newIOOptions(runtime"r");
             }
 
             String path = pathString.toString();
 
             // Ruby code frequently uses a platform check to choose "NUL:" on windows
             // but since that check doesn't work well on JRuby, we help it out
 
             .setPath(path);
 
             if (.getMainStream() == null) {
                 try {
                     .setMainStream(ChannelStream.fopen(runtimepathmodes.getModeFlags()));
                 } catch (FileExistsException fee) {
                     throw runtime.newErrnoEEXISTError(path);
                 }
 
                 if (.getPipeStream() != null) {
                     .getPipeStream().fclose();
                     .setPipeStream(null);
                 }
             } else {
                 // TODO: This is an freopen in MRI, this is close, but not quite the same
                 .getMainStreamSafe().freopen(runtimepathnewIOOptions(runtime.getModeAsString(runtime)).getModeFlags());
                 
                 if (.getPipeStream() != null) {
                     // TODO: pipe handler to be reopened with path and "w" mode
                 }
             }
         } catch (PipeException pe) {
             throw runtime.newErrnoEPIPEError();
         } catch (IOException ex) {
             throw runtime.newIOErrorFromException(ex);
         } catch (BadDescriptorException ex) {
             throw runtime.newErrnoEBADFError();
         } catch (InvalidValueException e) {
             throw runtime.newErrnoEINVALError();
         }
     }
 
     protected void reopenIO(Ruby runtimeRubyIO ios) {
         try {
             if (ios.openFile == this.return;
 
             OpenFile origFile = ios.getOpenFileChecked();
             OpenFile selfFile = getOpenFileChecked();
 
             long pos = 0;
             
             Stream origStream = origFile.getMainStreamSafe();
             ChannelDescriptor origDescriptor = origStream.getDescriptor();
             boolean origIsSeekable = origDescriptor.isSeekable();
 
             if (origFile.isReadable() && origIsSeekable) {
                 pos = origStream.fgetpos();
             }
 
             if (origFile.getPipeStream() != null) {
                 origFile.getPipeStream().fflush();
             } else if (origFile.isWritable()) {
                 origStream.fflush();
             }
 
             if (selfFile.isWritable()) {
                 selfFile.getWriteStreamSafe().fflush();
             }
 
             selfFile.setMode(origFile.getMode());
             selfFile.setProcess(origFile.getProcess());
             selfFile.setLineNumber(origFile.getLineNumber());
             selfFile.setPath(origFile.getPath());
             selfFile.setFinalizer(origFile.getFinalizer());
 
             Stream selfStream = selfFile.getMainStreamSafe();
             ChannelDescriptor selfDescriptor = selfStream.getDescriptor();
             boolean selfIsSeekable = selfDescriptor.isSeekable();
 
             // check if we're a stdio IO, and ensure we're not badly mutilated
             if (runtime.getFileno(selfDescriptor) >= 0 && runtime.getFileno(selfDescriptor) <= 2) {
                 selfStream.clearerr();
 
                 // dup2 new fd into self to preserve fileno and references to it
                 origDescriptor.dup2Into(selfDescriptor);
                 selfStream.setModes(origStream.getModes());
             } else {
                 Stream pipeFile = selfFile.getPipeStream();
                 selfStream.fclose();
                 selfFile.setPipeStream(null);
 
                 // TODO: turn off readable? am I reading this right?
                 // This only seems to be used while duping below, since modes gets
                 // reset to actual modes afterward
                 //fptr->mode &= (m & FMODE_READABLE) ? ~FMODE_READABLE : ~FMODE_WRITABLE;
 
                 if (pipeFile != null) {
                     selfFile.setMainStream(ChannelStream.fdopen(runtimeorigDescriptororigDescriptor.getOriginalModes()));
                     selfFile.setPipeStream(pipeFile);
                 } else {
                     // only use internal fileno here, stdio is handled above
                     selfFile.setMainStream(
                             ChannelStream.open(
                             runtime,
                             origDescriptor.dup2(selfDescriptor.getFileno())));
 
                     // since we're not actually duping the incoming channel into our handler, we need to
                     // copy the original sync behavior from the other handler
                     selfFile.getMainStreamSafe().setSync(selfFile.getMainStreamSafe().isSync());
                 }
             }
 
             // TODO: anything threads attached to original fd are notified of the close...
             // see rb_thread_fd_close
 
             if (origFile.isReadable() && pos >= 0) {
                 if (selfIsSeekable) {
                     selfFile.seek(pos.);
                 }
 
                 if (origIsSeekable) {
                     origFile.seek(pos.);
                 }
             }
 
             // only use internal fileno here, stdio is handled above
             if (selfFile.getPipeStream() != null && selfDescriptor.getFileno() != selfFile.getPipeStream().getDescriptor().getFileno()) {
                 int fd = selfFile.getPipeStream().getDescriptor().getFileno();
 
                 if (origFile.getPipeStream() == null) {
                     selfFile.getPipeStream().fclose();
                     selfFile.setPipeStream(null);
                 } else if (fd != origFile.getPipeStream().getDescriptor().getFileno()) {
                     selfFile.getPipeStream().fclose();
                     ChannelDescriptor newFD2 = origFile.getPipeStream().getDescriptor().dup2(fd);
                     selfFile.setPipeStream(ChannelStream.fdopen(runtimenewFD2newIOOptions(runtime"w").getModeFlags()));
                 }
             }
 
             if ((selfFile.getMode() & .) != 0) {
                 selfFile.setBinmode();
             }
 
             // TODO: set our metaclass to target's class (i.e. scary!)
 
         } catch (IOException ex) { // TODO: better error handling
             throw runtime.newIOErrorFromException(ex);
         } catch (BadDescriptorException ex) {
             throw runtime.newIOError("could not reopen: " + ex.getMessage());
         } catch (PipeException ex) {
             ex.printStackTrace();
             throw runtime.newIOError("could not reopen: " + ex.getMessage());
         } catch (InvalidValueException ive) {
             throw runtime.newErrnoEINVALError();
         }
     }
 
     @JRubyMethod(name = "reopen", required = 1, optional = 1)
     public IRubyObject reopen(ThreadContext contextIRubyObject[] args) {
         Ruby runtime = context.runtime;
     	IRubyObject tmp = TypeConverter.convertToTypeWithCheck(args[0], runtime.getIO(), "to_io");
         
     	if (!tmp.isNil()) {
             reopenIO(runtime, (RubyIOtmp);
         } else {
             reopenPath(runtimeargs);
         }
         
         return this;
     }
 
     @Deprecated
     public static ModeFlags getIOModes(Ruby runtimeString modesString) {
         return newModeFlags(runtimemodesString);
     }
 
     @Deprecated
     public static int getIOModesIntFromString(Ruby runtimeString modesString) {
         try {
             return ModeFlags.getOFlagsFromString(modesString);
         } catch (InvalidValueException ive) {
             throw runtime.newArgumentError("illegal access mode");
         }
     }
 
     /*
      * Ensure that separator is valid otherwise give it the default paragraph separator.
      */
     private ByteList separator(Ruby runtime) {
         return separator(runtimeruntime.getRecordSeparatorVar().get());
     }
 
     private ByteList separator(Ruby runtimeIRubyObject separatorValue) {
         ByteList separator = separatorValue.isNil() ? null :
             separatorValue.convertToString().getByteList();
 
         if (separator != null) {
             if (separator.getRealSize() == 0) return .;
 
             if (runtime.is1_9()) {
                 if (separator.getEncoding() != getEnc()) {
                     separator = Transcoder.strConvEncOpts(runtime.getCurrentContext(), separator,
                             getEnc2(), getEnc(), 0, runtime.getNil());
                 }
             }
         }
 
         return separator;
     }
 
     private ByteList getSeparatorFromArgs(Ruby runtimeIRubyObject[] argsint idx) {
 
         if (args.length > idx && args[idxinstanceof RubyFixnum) {
             return separator(runtimeruntime.getRecordSeparatorVar().get());
         }
 
         return separator(runtimeargs.length > idx ? args[idx] : runtime.getRecordSeparatorVar().get());
     }
 
     private ByteList getSeparatorForGets(Ruby runtimeIRubyObject[] args) {
         return getSeparatorFromArgs(runtimeargs, 0);
     }
 
     private IRubyObject getline(ThreadContext contextByteList separatorByteListCache cache) {
         return getline(contextseparator, -1, cache);
     }
 
     public IRubyObject getline(ThreadContext contextByteList separator) {
         return getline(contextseparator, -1, null);
     }

    
getline using logic of gets. If limit is -1 then read unlimited amount.
 
     public IRubyObject getline(ThreadContext contextByteList separatorlong limit) {
         return getline(contextseparatorlimitnull);
     }
 
     private IRubyObject getline(ThreadContext contextByteList separatorlong limitByteListCache cache) {
         return getlineInner(contextseparatorlimitcache);
     }
     
     private IRubyObject getlineEmptyString(Ruby runtime) {
         if (runtime.is1_9()) return RubyString.newEmptyString(runtimegetReadEncoding());
 
         return RubyString.newEmptyString(runtime);
     }
     
     private IRubyObject getlineAll(ThreadContext contextOpenFile myOpenFilethrows IOExceptionBadDescriptorException {
         Ruby runtime = context.runtime;
         RubyString str = (RubyString)readAll(context);
 
         if (str.getByteList().length() == 0) return runtime.getNil();
         incrementLineno(runtimemyOpenFile);
         
         return str;
     }
    
    
getline using logic of gets. If limit is -1 then read unlimited amount. mri: rb_io_getline_1 (mostly)
 
     private IRubyObject getlineInner(ThreadContext contextByteList separatorlong limitByteListCache cache) {
         Ruby runtime = context.runtime;
         
         try {
             boolean is19 = runtime.is1_9();
             
             OpenFile myOpenFile = getOpenFileChecked();
 
             myOpenFile.checkReadable(runtime);
             myOpenFile.setReadBuffered();
 
             boolean isParagraph = separator == .;
             separator = isParagraph ? . : separator;
             
             if (isParagraphswallow('\n');
             
             if (separator == null && limit < 0) {
                 return getlineAll(runtime.getCurrentContext(), myOpenFile);
             } else if (limit == 0) {
                 return getlineEmptyString(runtime);
             } else if (separator != null && separator.length() == 1 && limit < 0 && 
                     (!is19 || (!needsReadConversion() && getReadEncoding().isAsciiCompatible()))) {
                 return getlineFast(runtimeseparator.get(0) & 0xFF, cache);
             } else {
                 Stream readStream = myOpenFile.getMainStreamSafe();
                 int c = -1;
                 int n = -1;
                 int newline = (separator != null) ? (separator.get(separator.length() - 1) & 0xFF) : -1;
                 
                 // FIXME: Change how we consume streams to match MRI (see append_line/more_char/fill_cbuf)
                 // Awful hack.  MRI pre-transcodes lines into read-ahead whereas
                 // we read a single line at a time PRE-transcoded.  To keep our
                 // logic we need to do one additional transcode of the sep to
                 // match the pre-transcoded encoding.  This is gross and we should
                 // mimick MRI.
                 if (is19 && separator != null && separator.getEncoding() != getInputEncoding()) {
                     separator = Transcoder.strConvEncOpts(runtime.getCurrentContext(), separatorseparator.getEncoding(), getInputEncoding(), 0, context.nil);
                     newline = separator.get(separator.length() - 1) & 0xFF;
                 }
 
                 ByteList buf = cache != null ? cache.allocate(0) : new ByteList(0);
                 try {
                     boolean update = false;
                     boolean limitReached = false;
                     
                     if (is19makeReadConversion(context);
                     
                     while (true) {
                         do {
                             readCheck(readStream);
                             readStream.clearerr();
 
                             try {
                                 runtime.getCurrentContext().getThread().beforeBlockingCall();
                                 if (limit == -1) {
                                     n = readStream.getline(buf, (bytenewline);
                                 } else {
                                     n = readStream.getline(buf, (bytenewlinelimit);
 
                                     if (buf.length() > 0 && isIncompleteChar(buf.get(buf.length() - 1))) {
                                         buf.append((byte)readStream.fgetc());
                                     }
 
                                     limit -= n;
                                     if (limit <= 0) {
                                         update = limitReached = true;
                                         break;
                                     }
                                 }
 
                                 c = buf.length() > 0 ? buf.get(buf.length() - 1) & 0xff : -1;
                             } catch (EOFException e) {
                                 n = -1;
                             } finally {
                                 runtime.getCurrentContext().getThread().afterBlockingCall();
                             }
                             
                             // CRuby checks ferror(f) and retry getc for
                             // non-blocking IO.
                             if (n == 0) {
                                 waitReadable(readStream);
                                 continue;
                             } else if (n == -1) {
                                 break;
                             }
 
                             update = true;
                         } while (c != newline); // loop until we see the nth separator char
 
 
                         // if we hit EOF or reached limit then we're done
                         if (n == -1 || limitReached) {
                             break;
                         }
 
                         // if we've found the last char of the separator,
                         // and we've found at least as many characters as separator length,
                         // and the last n characters of our buffer match the separator, we're done
                         if (c == newline && separator != null && buf.length() >= separator.length() &&
                                 0 == ByteList.memcmp(buf.getUnsafeBytes(), buf.getBegin() + buf.getRealSize() - separator.length(), separator.getUnsafeBytes(), separator.getBegin(), separator.getRealSize())) {
                             break;
                         }
                     }
                     
                     if (is19 &&  != nullbuf = .transcode(contextbuf);
                     
                     if (isParagraph && c != -1) swallow('\n');
                     if (!updatereturn runtime.getNil();
 
                     incrementLineno(runtimemyOpenFile);
 
                     ByteList newBuf = cache != null ? new ByteList(buf) : buf;
                     RubyString str = RubyString.newString(runtimenewBuf);
                     
                     return ioEncStr(str);
                 } finally {
                     if (cache != nullcache.release(buf);
                 }
             }
         } catch (InvalidValueException ex) {
             throw runtime.newErrnoEINVALError();
         } catch (EOFException e) {
             return runtime.getNil();
         } catch (BadDescriptorException e) {
             throw runtime.newErrnoEBADFError();
         } catch (IOException e) {
             throw runtime.newIOErrorFromException(e);
         }
     }
 
     // fptr->enc and codeconv->enc
     public Encoding getEnc() {
         return ;
     }
     
     // mri: io_read_encoding
     public Encoding getReadEncoding() {
         return  != null ?  : EncodingUtils.defaultExternalEncoding(getRuntime());
     }
     
     // fptr->enc2 and codeconv->enc2
     public Encoding getEnc2() {
         return ;
     }
     
     // mri: io_input_encoding
     public Encoding getInputEncoding() {
         return  != null ?  : getReadEncoding();
     }
 
     private RubyString makeString(Ruby runtimeByteList bufferboolean isCached) {
         ByteList newBuf = isCached ? new ByteList(buffer) : buffer;
         if (runtime.is1_9()) newBuf.setEncoding(getReadEncoding());
 
         RubyString str = RubyString.newString(runtimenewBuf);
         str.setTaint(true);
 
         return str;
     }
 
     private void incrementLineno(Ruby runtimeOpenFile myOpenFile) {
         int lineno = myOpenFile.getLineNumber() + 1;
         myOpenFile.setLineNumber(lineno);
         runtime.setCurrentLine(lineno);
         RubyArgsFile.setCurrentLineNumber(runtime.getArgsFile(), lineno);
     }
 
     protected boolean swallow(int termthrows IOExceptionBadDescriptorException {
         Stream readStream = .getMainStreamSafe();
         int c;
         
         do {
             readCheck(readStream);
             
             try {
                 c = readStream.fgetc();
             } catch (EOFException e) {
                 c = -1;
             }
             
             if (c != term) {
                 readStream.ungetc(c);
                 return true;
             }
         } while (c != -1);
         
         return false;
     }
     
     private static String vendor;
     static { String v = SafePropertyAccessor.getProperty("java.vendor") ;  = (v == null) ? "" : v; };
     private static String msgEINTR = "Interrupted system call";
 
     public static boolean restartSystemCall(Exception e) {
         return .startsWith("Apple") && e.getMessage().equals();
     }
     
     private IRubyObject getlineFast(Ruby runtimeint delimByteListCache cachethrows IOExceptionBadDescriptorException {
         Stream readStream = .getMainStreamSafe();
         int c = -1;
 
         ByteList buf = cache != null ? cache.allocate(0) : new ByteList(0);
         try {
             boolean update = false;
             do {
                 readCheck(readStream);
                 readStream.clearerr();
                 int n;
                 try {
                     runtime.getCurrentContext().getThread().beforeBlockingCall();
                     n = readStream.getline(buf, (bytedelim);
                     c = buf.length() > 0 ? buf.get(buf.length() - 1) & 0xff : -1;
                 } catch (EOFException e) {
                     n = -1;
                 } finally {
                     runtime.getCurrentContext().getThread().afterBlockingCall();
                 }
 
                 // CRuby checks ferror(f) and retry getc for non-blocking IO.
                 if (n == 0) {
                     waitReadable(readStream);
                     continue;
                 } else if (n == -1) {
                     break;
                 }
                 
                 update = true;
             } while (c != delim);
 
             if (!updatereturn runtime.getNil();
                 
             incrementLineno(runtime);
 
             return makeString(runtimebufcache != null);
         } finally {
             if (cache != nullcache.release(buf);
         }
     }
     // IO class methods.
 
     @JRubyMethod(name = {"new""for_fd"}, rest = true, meta = true)
     public static IRubyObject newInstance(ThreadContext contextIRubyObject recvIRubyObject[] argsBlock block) {
         RubyClass klass = (RubyClass)recv;
         
         if (block.isGiven()) {
             String className = klass.getName();
             context.runtime.getWarnings().warn(
                     .,
                     className + "::new() does not take block; use " + className + "::open() instead");
         }
         
         return klass.newInstance(contextargsblock);
     }
 
     private IRubyObject initializeCommon19(ThreadContext contextint filenoIRubyObject vmodeArgIRubyObject opt) {
         Ruby runtime = context.runtime;
         
         int ofmode;
         int[] oflags_p = {.};
 
         if(opt != null && !opt.isNil() && !(opt instanceof RubyHash) && !(opt.respondsTo("to_hash"))) {
             throw runtime.newArgumentError("last argument must be a hash!");
         }
         
         if (opt != null && !opt.isNil()) {
             opt = opt.convertToHash();
         }
         
         try {
             ChannelDescriptor descriptor = ChannelDescriptor.getDescriptorByFileno(runtime.getFilenoExtMap(fileno));
 
             if (descriptor == nullthrow runtime.newErrnoEBADFError();
 
             descriptor.checkOpen();
             
             IRubyObject[] pm = new IRubyObject[] { runtime.newFixnum(0), vmodeArg };
             int[] fmode_p = {0};
             EncodingUtils.extractModeEncoding(contextthispmoptoflags_pfmode_p);
             
             oflags_p[0] = descriptor.getOriginalModes().getFlags();
 
             ofmode = ModeFlags.getOpenFileFlagsFor(oflags_p[0]);
             if (pm[.] == null || pm[.].isNil()) {
                 fmode_p[0] = ofmode;
             } else if (((~ofmode & fmode_p[0]) & .) != 0) {
                 throw runtime.newErrnoEINVALError();
             }
             
             if (!opt.isNil() && ((RubyHash)opt).op_aref(contextruntime.newSymbol("autoclose")) == runtime.getFalse()) {
                 setAutoclose(false);
             }
             
             // JRUBY-4650: Make sure we clean up the old data, if it's present.
             MakeOpenFile();
 
             ModeFlags modes = ModeFlags.createModeFlags(oflags_p[0]);
             
             .setMode(fmode_p[0]);
             .setMainStream(fdopen(descriptormodes));
             clearCodeConversion();
             
 //            io_check_tty(fp);
 //            if (fileno(stdin) == fd)
 //                fp - > stdio_file = stdin;
 //            else if (fileno(stdout) == fd)
 //                fp - > stdio_file = stdout;
 //            else if (fileno(stderr) == fd)
 //                fp - >stdio_file = stderr;
             
             if () {
                 EncodingUtils.ioSetEncodingByBOM(contextthis);
             }
         } catch (BadDescriptorException ex) {
             throw context.runtime.newErrnoEBADFError();
         }
 
         return this;
     }
 
     @JRubyMethod(name = "initialize", visibility = , compat = )
     public IRubyObject initialize19(ThreadContext contextIRubyObject fileNumberBlock unused) {
         return initializeCommon19(context, RubyNumeric.fix2int(fileNumber), nullcontext.nil);
     }
     
     @JRubyMethod(name = "initialize", visibility = , compat = )
     public IRubyObject initialize19(ThreadContext contextIRubyObject fileNumberIRubyObject secondBlock unused) {
         int fileno = RubyNumeric.fix2int(fileNumber);
         IRubyObject vmode = null;
         IRubyObject options = null;
         IRubyObject hashTest = TypeConverter.checkHashType(context.runtimesecond);
         if (hashTest instanceof RubyHash) {
             options = hashTest;
         } else {
             options = context.nil;
             vmode = second;
         }
 
         return initializeCommon19(contextfilenovmodeoptions);
     }
 
     @JRubyMethod(name = "initialize", visibility = , compat = )
     public IRubyObject initialize19(ThreadContext contextIRubyObject fileNumberIRubyObject modeValueIRubyObject optionsBlock unused) {
         int fileno = RubyNumeric.fix2int(fileNumber);
 
         return initializeCommon19(contextfilenomodeValueoptions);
     }
 
     // No encoding processing
     protected IOOptions parseIOOptions(IRubyObject arg) {
         Ruby runtime = getRuntime();
 
         if (arg instanceof RubyFixnumreturn newIOOptions(runtime, (int) RubyFixnum.fix2long(arg));
 
         return newIOOptions(runtimenewModeFlags(runtimearg.convertToString().toString()));
     }
 
     // Encoding processing
     protected IOOptions parseIOOptions19(IRubyObject arg) {
         Ruby runtime = getRuntime();
 
         if (arg instanceof RubyFixnumreturn newIOOptions(runtime, (int) RubyFixnum.fix2long(arg));
 
         String modeString = arg.convertToString().toString();
         try {
             return new IOOptions(runtimemodeString);
         } catch (InvalidValueException ive) {
             throw runtime.newArgumentError("invalid access mode " + modeString);
         }
     }
 
     @JRubyMethod(required = 1, optional = 1, visibility = , compat = )
     public IRubyObject initialize(IRubyObject[] argsBlock unusedBlock) {
         Ruby runtime = getRuntime();
         int argCount = args.length;
         IOOptions ioOptions;
         
         int fileno = RubyNumeric.fix2int(args[0]);
         
         try {
             ChannelDescriptor descriptor = ChannelDescriptor.getDescriptorByFileno(runtime.getFilenoExtMap(fileno));
             
             if (descriptor == null) {
                 throw runtime.newErrnoEBADFError();
             }
             
             descriptor.checkOpen();
             
             if (argCount == 2) {
                 if (args[1] instanceof RubyFixnum) {
                     ioOptions = newIOOptions(runtime, RubyFixnum.fix2long(args[1]));
                 } else {
                     ioOptions = newIOOptions(runtimeargs[1].convertToString().toString());
                 }
             } else {
                 // use original modes
                 ioOptions = newIOOptions(runtimedescriptor.getOriginalModes());
             }
             
             // JRUBY-4650: Make sure we clean up the old data, if it's present.
            MakeOpenFile();
            if (.isOpen()) {
                // JRUBY-4650: Make sure we clean up the old data,
                // if it's present.
                .cleanup(runtimefalse);
            }
            .setMode(ioOptions.getModeFlags().getOpenFileFlags());
        
            .setMainStream(fdopen(descriptorioOptions.getModeFlags()));
        } catch (BadDescriptorException ex) {
            throw runtime.newErrnoEBADFError();