Exemple #1
0
  /**
   * @throws IOException
   * @throws BadDescriptorException
   */
  private int bufferedWrite(int c) throws IOException, BadDescriptorException {
    checkWritable();
    ensureWrite();

    if (!buffer.hasRemaining()) flushWrite();

    buffer.put((byte) c);

    if (isSync()) flushWrite();

    return 1;
  }
Exemple #2
0
 /**
  * Ensure buffer is ready for reading, flushing remaining writes if required
  *
  * @throws IOException
  */
 private void ensureRead() throws IOException, BadDescriptorException {
   if (reading) return;
   flushWrite();
   buffer.clear();
   buffer.flip();
   reading = true;
 }
Exemple #3
0
 /**
  * @throws IOException
  * @throws BadDescriptorException
  */
 public synchronized int fflush() throws IOException, BadDescriptorException {
   checkWritable();
   try {
     flushWrite();
   } catch (EOFException eofe) {
     return -1;
   }
   return 0;
 }
Exemple #4
0
 @Override
 public void flush() throws IOException {
   try {
     synchronized (stream) {
       stream.flushWrite(true);
     }
   } catch (BadDescriptorException ex) {
     throw new IOException(ex.getMessage());
   }
 }
Exemple #5
0
 /**
  * Invalidate buffer before a position change has occurred (e.g. seek), flushing writes if
  * required, and correcting file position if reading
  *
  * @throws IOException
  */
 private void invalidateBuffer() throws IOException, BadDescriptorException {
   if (!reading) flushWrite();
   int posOverrun = buffer.remaining(); // how far ahead we are when reading
   buffer.clear();
   if (reading) {
     buffer.flip();
     // if the read buffer is ahead, back up
     FileChannel fileChannel = (FileChannel) descriptor.getChannel();
     if (posOverrun != 0) fileChannel.position(fileChannel.position() - posOverrun);
   }
 }
Exemple #6
0
  public synchronized void freopen(Ruby runtime, String path, ModeFlags modes)
      throws DirectoryAsFileException, IOException, InvalidValueException, PipeException,
          BadDescriptorException {
    // flush first
    flushWrite();

    // reset buffer
    buffer.clear();
    if (reading) {
      buffer.flip();
    }

    this.modes = modes;

    if (descriptor.isOpen()) {
      descriptor.close();
    }

    if (path.equals("/dev/null") || path.equalsIgnoreCase("nul:") || path.equalsIgnoreCase("nul")) {
      descriptor = descriptor.reopen(new NullChannel(), modes);
    } else {
      String cwd = runtime.getCurrentDirectory();
      JRubyFile theFile = JRubyFile.create(cwd, path);

      if (theFile.isDirectory() && modes.isWritable()) throw new DirectoryAsFileException();

      if (modes.isCreate()) {
        if (theFile.exists() && modes.isExclusive()) {
          throw runtime.newErrnoEEXISTError("File exists - " + path);
        }
        theFile.createNewFile();
      } else {
        if (!theFile.exists()) {
          throw runtime.newErrnoENOENTError("file not found - " + path);
        }
      }

      // We always open this rw since we can only open it r or rw.
      RandomAccessFile file = new RandomAccessFile(theFile, modes.toJavaModeString());

      if (modes.isTruncate()) file.setLength(0L);

      descriptor = descriptor.reopen(file, modes);

      try {
        if (modes.isAppendable()) lseek(0, SEEK_END);
      } catch (PipeException pe) {
        // ignore, it's a pipe or fifo
      }
    }
  }
Exemple #7
0
  /**
   * @throws IOException
   * @throws BadDescriptorException
   */
  private int bufferedWrite(ByteBuffer buf) throws IOException, BadDescriptorException {
    checkWritable();
    ensureWrite();

    // Ruby ignores empty syswrites
    if (buf == null || !buf.hasRemaining()) return 0;

    final int nbytes = buf.remaining();
    if (nbytes >= buffer.capacity()) { // Doesn't fit in buffer. Write immediately.
      flushWrite(); // ensure nothing left to write

      descriptor.write(buf);
      // TODO: check the return value here
    } else {
      if (nbytes > buffer.remaining()) flushWrite();

      buffer.put(buf);
    }

    if (isSync()) flushWrite();

    return nbytes - buf.remaining();
  }
Exemple #8
0
  private void finish(boolean close) throws BadDescriptorException, IOException {
    try {
      flushWrite();

      if (DEBUG) LOG.info("Descriptor for fileno {} closed by stream", descriptor.getFileno());
    } finally {
      buffer = EMPTY_BUFFER;

      // clear runtime so it doesn't get stuck in memory (JRUBY-2933)
      runtime = null;

      // finish descriptor
      descriptor.finish(close);
    }
  }
Exemple #9
0
  /**
   * @throws IOException
   * @throws BadDescriptorException
   */
  private int bufferedWrite(ByteList buf) throws IOException, BadDescriptorException {
    checkWritable();
    ensureWrite();

    // Ruby ignores empty syswrites
    if (buf == null || buf.length() == 0) return 0;

    if (buf.length() > buffer.capacity()) { // Doesn't fit in buffer. Write immediately.
      flushWrite(); // ensure nothing left to write

      int n = descriptor.write(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin(), buf.length()));
      if (n != buf.length()) {
        // TODO: check the return value here
      }
    } else {
      if (buf.length() > buffer.remaining()) flushWrite();

      buffer.put(buf.getUnsafeBytes(), buf.begin(), buf.length());
    }

    if (isSync()) flushWrite();

    return buf.getRealSize();
  }
Exemple #10
0
 /**
  * Ensure buffer is ready for reading, flushing remaining writes if required
  *
  * @throws IOException
  */
 private void ensureReadNonBuffered() throws IOException, BadDescriptorException {
   if (reading) {
     if (buffer.hasRemaining()) {
       Ruby localRuntime = getRuntime();
       if (localRuntime != null) {
         throw localRuntime.newIOError("sysread for buffered IO");
       } else {
         throw new IOException("sysread for buffered IO");
       }
     }
   } else {
     // libc flushes writes on any read from the actual file, so we flush here
     flushWrite();
     buffer.clear();
     buffer.flip();
     reading = true;
   }
 }
Exemple #11
0
 /**
  * Implementation of libc "lseek", which seeks on seekable streams, raises EPIPE if the fd is
  * assocated with a pipe, socket, or FIFO, and doesn't do anything for other cases (like stdio).
  *
  * @throws IOException
  * @throws InvalidValueException
  */
 public synchronized void lseek(long offset, int type)
     throws IOException, InvalidValueException, PipeException, BadDescriptorException {
   if (descriptor.isSeekable()) {
     FileChannel fileChannel = (FileChannel) descriptor.getChannel();
     ungotc = -1;
     int adj = 0;
     if (reading) {
       // for SEEK_CUR, need to adjust for buffered data
       adj = buffer.remaining();
       buffer.clear();
       buffer.flip();
     } else {
       flushWrite();
     }
     try {
       switch (type) {
         case SEEK_SET:
           fileChannel.position(offset);
           break;
         case SEEK_CUR:
           fileChannel.position(fileChannel.position() - adj + offset);
           break;
         case SEEK_END:
           fileChannel.position(fileChannel.size() + offset);
           break;
       }
     } catch (IllegalArgumentException e) {
       throw new InvalidValueException();
     } catch (IOException ioe) {
       throw ioe;
     }
   } else if (descriptor.getChannel() instanceof SelectableChannel) {
     // TODO: It's perhaps just a coincidence that all the channels for
     // which we should raise are instanceof SelectableChannel, since
     // stdio is not...so this bothers me slightly. -CON
     throw new PipeException();
   } else {
   }
 }
Exemple #12
0
 public synchronized void sync() throws IOException, BadDescriptorException {
   flushWrite();
 }