Exemplo n.º 1
0
  /**
   * Reads up to {@code count} bytes from this channel's file starting at {@code position} and
   * writes them to {@code target}. No bytes are transferred if {@code position} is larger than the
   * size of this channel's file. Less than {@code count} bytes are transferred if there less bytes
   * available from this channel's file or if the target channel is non-blocking and has less than
   * {@code count} bytes free in its input buffer.
   *
   * <p>Note that this channel's position is not modified.
   *
   * @param position the non-negative position to begin.
   * @param count the non-negative number of bytes to transfer.
   * @param target the target channel to write to.
   * @return the number of bytes that were transferred.
   * @throws IllegalArgumentException if the parameters are invalid.
   * @throws NonReadableChannelException if this channel is not readable.
   * @throws NonWritableChannelException if the target channel is not writable.
   * @throws ClosedChannelException if either channel has already been closed.
   * @throws AsynchronousCloseException if either channel is closed by other threads during this
   *     operation.
   * @throws ClosedByInterruptException if the thread is interrupted during this operation.
   * @throws IOException if any I/O error occurs.
   */
  public long transferTo(long position, long count, WritableByteChannel target) throws IOException {
    checkOpen();
    if (!target.isOpen()) {
      throw new ClosedChannelException();
    }
    checkReadable();
    if (target instanceof IOCipherFileChannel) {
      ((IOCipherFileChannel) target).checkWritable();
    }
    if (position < 0 || count < 0) {
      throw new IllegalArgumentException("position=" + position + " count=" + count);
    }

    if (count == 0 || position >= size()) {
      return 0;
    }
    count = Math.min(count, size() - position);

    try {
      ByteBuffer buffer = ByteBuffer.allocate((int) count);
      read(buffer, position);
      buffer.flip();
      return target.write(buffer);
    } finally {
      // TODO determine whether we have memory leaking or perf issues here #567
    }
  }
Exemplo n.º 2
0
 private int writeImpl(ByteBuffer buffer, long position) throws IOException {
   checkOpen();
   checkWritable();
   if (buffer == null) {
     throw new NullPointerException("buffer == null");
   }
   if (!buffer.hasRemaining()) {
     return 0;
   }
   int bytesWritten = 0;
   boolean completed = false;
   try {
     begin();
     try {
       if (position == -1) {
         bytesWritten = Libcore.os.write(fd, buffer, this.mode);
       } else {
         bytesWritten = Libcore.os.pwrite(fd, buffer, position, this.mode);
       }
     } catch (ErrnoException errnoException) {
       throw errnoException.rethrowAsIOException();
     }
     completed = true;
   } finally {
     end(completed);
   }
   if (bytesWritten > 0) {
     buffer.position(buffer.position() + bytesWritten);
   }
   return bytesWritten;
 }
Exemplo n.º 3
0
 /**
  * Sets the file position pointer to a new value.
  *
  * <p>The argument is the number of bytes counted from the start of the file. The position cannot
  * be set to a value that is negative. The new position can be set beyond the current file size.
  * If set beyond the current file size, attempts to read will return end of file. Write operations
  * will succeed but they will fill the bytes between the current end of file and the new position
  * with the required number of (unspecified) byte values.
  *
  * @param newPosition the new file position, in bytes.
  * @return the receiver.
  * @throws IllegalArgumentException if the new position is negative.
  * @throws ClosedChannelException if this channel is closed.
  */
 public IOCipherFileChannel position(long newPosition) throws IOException {
   if (newPosition < 0)
     throw new IllegalArgumentException("negative file position not allowed: " + newPosition);
   checkOpen();
   fd.position = newPosition;
   return this;
 }
Exemplo n.º 4
0
 /**
  * Requests that all updates to this channel are committed to the storage device.
  *
  * <p>When this method returns, all modifications made to the platform file underlying this
  * channel have been committed if the file resides on a local storage device. If the file is not
  * hosted locally, for example on a networked file system, then applications cannot be certain
  * that the modifications have been committed.
  *
  * <p>There are no assurances given that changes made to the file using methods defined elsewhere
  * will be committed. For example, changes made via a mapped byte buffer may not be committed.
  *
  * <p>The <code>metadata</code> parameter indicates whether the update should include the file's
  * metadata such as last modification time, last access time, etc. Note that passing <code>true
  * </code> may invoke an underlying write to the operating system (if the platform is maintaining
  * metadata such as last access time), even if the channel is opened read-only.
  *
  * @param metadata {@code true} if the file metadata should be flushed in addition to the file
  *     content, {@code false} otherwise.
  * @throws ClosedChannelException if this channel is already closed.
  * @throws IOException if another I/O error occurs.
  */
 public void force(boolean metadata) throws IOException {
   checkOpen();
   if ((mode & O_ACCMODE) != O_RDONLY) {
     try {
       Libcore.os.fsync(fd); // FUSE only has fsync, not fdatasync
     } catch (ErrnoException errnoException) {
       throw errnoException.rethrowAsIOException();
     }
   }
 }
Exemplo n.º 5
0
 /**
  * Truncates the file underlying this channel to a given size. Any bytes beyond the given size are
  * removed from the file. If there are no bytes beyond the given size then the file contents are
  * unmodified.
  *
  * <p>If the file position is currently greater than the given size, then it is set to the new
  * size.
  *
  * @param size the maximum size of the underlying file.
  * @throws IllegalArgumentException if the requested size is negative.
  * @throws ClosedChannelException if this channel is closed.
  * @throws NonWritableChannelException if the channel cannot be written to.
  * @throws IOException if another I/O error occurs.
  * @return this channel.
  */
 public IOCipherFileChannel truncate(long size) throws IOException {
   checkOpen();
   if (size < 0) {
     throw new IllegalArgumentException("size: " + size);
   }
   checkWritable();
   if (size < size()) {
     try {
       Libcore.os.ftruncate(fd, size);
     } catch (ErrnoException errnoException) {
       throw errnoException.rethrowAsIOException();
     }
   }
   return this;
 }
Exemplo n.º 6
0
 /**
  * IOCipher version of POSIX lseek, since the underlying FUSE layer does not track the position in
  * open files for us, we do it inside of this class. This class wraps a {@link FileDescriptor}, so
  * you cannot specify one as an argument.
  *
  * @param offset the new position to seek to.
  * @param whence changes the pointer repositioning behavior:
  *     <ul>
  *       <li>if {@link info.guardianproject.libcore.io.OsConstants.SEEK_SET SEEK_SET} then file
  *           pointer is set to <i>offset</i>
  *       <li>if {@link info.guardianproject.libcore.io.OsConstants.SEEK_CUR SEEK_CUR} then file
  *           pointer is set to <i>current position + offset</i>
  *       <li>if {@link info.guardianproject.libcore.io.OsConstants.SEEK_END SEEK_END} then file
  *           pointer is set to <i>file size + offset</i>
  *     </ul>
  *
  * @throws ClosedChannelException if this channel is already closed.
  * @return new position of file pointer
  */
 public long lseek(long offset, int whence) throws IOException {
   checkOpen();
   long tmpPosition = fd.position;
   if (whence == SEEK_SET) {
     tmpPosition = offset;
   } else if (whence == SEEK_CUR) {
     tmpPosition += offset;
   } else if (whence == SEEK_END) {
     tmpPosition = size() + offset;
   } else {
     throw new IllegalArgumentException("Unknown 'whence': " + whence);
   }
   if (tmpPosition < 0) throw new IOException("negative resulting position: " + tmpPosition);
   else fd.position = tmpPosition;
   return fd.position;
 }
Exemplo n.º 7
0
  /**
   * Reads up to {@code count} bytes from {@code src} and stores them in this channel's file
   * starting at {@code position}. No bytes are transferred if {@code position} is larger than the
   * size of this channel's file. Less than {@code count} bytes are transferred if there are less
   * bytes remaining in the source channel or if the source channel is non-blocking and has less
   * than {@code count} bytes immediately available in its output buffer.
   *
   * <p>Note that this channel's position is not modified.
   *
   * @param src the source channel to read bytes from.
   * @param position the non-negative start position.
   * @param count the non-negative number of bytes to transfer.
   * @return the number of bytes that are transferred.
   * @throws IllegalArgumentException if the parameters are invalid.
   * @throws NonReadableChannelException if the source channel is not readable.
   * @throws NonWritableChannelException if this channel is not writable.
   * @throws ClosedChannelException if either channel has already been closed.
   * @throws AsynchronousCloseException if either channel is closed by other threads during this
   *     operation.
   * @throws ClosedByInterruptException if the thread is interrupted during this operation.
   * @throws IOException if any I/O error occurs.
   */
  public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException {
    checkOpen();
    if (!src.isOpen()) {
      throw new ClosedChannelException();
    }
    checkWritable();
    if (position < 0 || count < 0 || count > Integer.MAX_VALUE) {
      throw new IllegalArgumentException("position=" + position + " count=" + count);
    }
    if (position > size()) {
      return 0;
    }

    ByteBuffer buffer = ByteBuffer.allocate((int) count);
    src.read(buffer);
    buffer.flip();
    return write(buffer, position);
  }
Exemplo n.º 8
0
 private int readImpl(ByteBuffer buffer, long position) throws IOException {
   if (buffer.isReadOnly()) {
     throw new IllegalArgumentException("read-only buffer");
   }
   checkOpen();
   checkReadable();
   if (!buffer.hasRemaining()) {
     return 0;
   }
   int bytesRead = 0;
   boolean completed = false;
   try {
     begin();
     try {
       if (position == -1) {
         bytesRead = Libcore.os.read(fd, buffer);
       } else {
         bytesRead = Libcore.os.pread(fd, buffer, position);
       }
       if (bytesRead == 0) {
         bytesRead = -1;
       }
     } catch (ErrnoException errnoException) {
       if (errnoException.errno == EAGAIN) {
         // We don't throw if we try to read from an empty
         // non-blocking pipe.
         bytesRead = 0;
       } else {
         throw errnoException.rethrowAsIOException();
       }
     }
     completed = true;
   } finally {
     end(completed && bytesRead >= 0);
   }
   if (bytesRead > 0) {
     buffer.position(buffer.position() + bytesRead);
   }
   return bytesRead;
 }
Exemplo n.º 9
0
 /**
  * Returns the current value of the file position pointer.
  *
  * @return the current position as a positive integer number of bytes from the start of the file.
  * @throws ClosedChannelException if this channel is closed.
  */
 public long position() throws IOException {
   checkOpen();
   return fd.position;
 }