/** * @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; }
/** * 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; }
/** * @throws IOException * @throws BadDescriptorException */ public synchronized int fflush() throws IOException, BadDescriptorException { checkWritable(); try { flushWrite(); } catch (EOFException eofe) { return -1; } return 0; }
@Override public void flush() throws IOException { try { synchronized (stream) { stream.flushWrite(true); } } catch (BadDescriptorException ex) { throw new IOException(ex.getMessage()); } }
/** * 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); } }
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 } } }
/** * @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(); }
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); } }
/** * @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(); }
/** * 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; } }
/** * 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 { } }
public synchronized void sync() throws IOException, BadDescriptorException { flushWrite(); }