/** * Returns the length of this file in bytes. * * @return the file's length in bytes. * @throws IOException * if this file is closed or some other I/O error occurs. */ public long length() throws IOException { try { return Libcore.os.fstat(fd).st_size; } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * Gets the current position within this file. All reads and * writes take place at the current file pointer position. * * @return the current offset in bytes from the beginning of the file. * * @throws IOException * if an error occurs while getting the file pointer of this * file. */ public long getFilePointer() throws IOException { try { return Libcore.os.lseek(fd, 0L, SEEK_CUR); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
@Override public long skip(long byteCount) throws IOException { if (byteCount < 0) { throw new IOException("byteCount < 0: " + byteCount); } try { // Try lseek(2). That returns the new offset, but we'll throw an // exception if it couldn't perform exactly the seek we asked for. Libcore.os.lseek(fd, byteCount, SEEK_CUR); return byteCount; } catch (ErrnoException errnoException) { if (errnoException.errno == ESPIPE) { // You can't seek on a pipe, so fall back to the superclass' implementation. return super.skip(byteCount); } throw errnoException.rethrowAsIOException(); } } }
/** * Moves this file's file pointer to a new position, from where following * {@code read}, {@code write} or {@code skip} operations are done. The * position may be greater than the current length of the file, but the * file's length will only change if the moving of the pointer is followed * by a {@code write} operation. * * @param offset * the new file pointer position. * @throws IOException * if this file is closed, {@code pos < 0} or another I/O error * occurs. */ public void seek(long offset) throws IOException { if (offset < 0) { throw new IOException("offset < 0: " + offset); } try { Libcore.os.lseek(fd, offset, SEEK_SET); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
public FileChannel position(long newPosition) throws IOException { checkOpen(); if (newPosition < 0) { throw new IllegalArgumentException("position: " + newPosition); } try { Libcore.os.lseek(fd, newPosition, SEEK_SET); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } return this; }
public long size() throws IOException { checkOpen(); try { return Libcore.os.fstat(fd).st_size; } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
public long position() throws IOException { checkOpen(); try { return Libcore.os.lseek(fd, 0L, SEEK_CUR); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * Calls close(2) on 'fd'. Also resets the internal int to -1. Does nothing if 'fd' is null * or invalid. */ public static void close(FileDescriptor fd) throws IOException { try { if (fd != null && fd.valid()) { Libcore.os.close(fd); } } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * Sets 'fd' to be blocking or non-blocking, according to the state of 'blocking'. */ public static void setBlocking(FileDescriptor fd, boolean blocking) throws IOException { try { int flags = Libcore.os.fcntlVoid(fd, F_GETFL); if (!blocking) { flags |= O_NONBLOCK; } else { flags &= ~O_NONBLOCK; } Libcore.os.fcntlLong(fd, F_SETFL, flags); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
int doTransfer(FileDescriptor fd) throws IOException { try { if (direction == Direction.READV) { int result = Libcore.os.readv(fd, ioBuffers, offsets, byteCounts); if (result == 0) { result = -1; } return result; } else { return Libcore.os.writev(fd, ioBuffers, offsets, byteCounts); } } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * java.io always writes every byte it's asked to, or fails with an error. (That is, unlike * Unix it never just writes as many bytes as happens to be convenient.) */ public static void write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws IOException { Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount); if (byteCount == 0) { return; } try { while (byteCount > 0) { int bytesWritten = Libcore.os.write(fd, bytes, byteOffset, byteCount); byteCount -= bytesWritten; byteOffset += bytesWritten; } } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
public static int available(FileDescriptor fd) throws IOException { try { MutableInt available = new MutableInt(0); Libcore.os.ioctlInt(fd, FIONREAD, available); if (available.value < 0) { // If the fd refers to a regular file, the result is the difference between // the file size and the file position. This may be negative if the position // is past the end of the file. If the fd refers to a special file masquerading // as a regular file, the result may be negative because the special file // may appear to have zero size and yet a previous read call may have // read some amount of data and caused the file position to be advanced. available.value = 0; } return available.value; } catch (ErrnoException errnoException) { if (errnoException.errno == ENOTTY) { // The fd is unwilling to opine about its read buffer. return 0; } throw errnoException.rethrowAsIOException(); } }
/** * java.io thinks that a read at EOF is an error and should return -1, contrary to traditional * Unix practice where you'd read until you got 0 bytes (and any future read would return -1). */ public static int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws IOException { Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount); if (byteCount == 0) { return 0; } try { int readCount = Libcore.os.read(fd, bytes, byteOffset, byteCount); if (readCount == 0) { return -1; } return readCount; } catch (ErrnoException errnoException) { if (errnoException.errno == EAGAIN) { // We return 0 rather than throw if we try to read from an empty non-blocking pipe. return 0; } throw errnoException.rethrowAsIOException(); } }
public void force(boolean metadata) throws IOException { checkOpen(); if ((mode & O_ACCMODE) != O_RDONLY) { try { if (metadata) { Libcore.os.fsync(fd); } else { Libcore.os.fdatasync(fd); } } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } } }
public FileChannel truncate(long size) throws IOException { checkOpen(); if (size < 0) { throw new IllegalArgumentException("size < 0: " + size); } checkWritable(); if (size < size()) { try { Libcore.os.ftruncate(fd, size); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } } return this; }
public static MemoryBlock mmap(FileDescriptor fd, long offset, long size, MapMode mapMode) throws IOException { if (size == 0) { // You can't mmap(2) a zero-length region, but Java allows it. return new MemoryBlock(0, 0); } // Check just those errors mmap(2) won't detect. if (offset < 0 || size < 0 || offset > Integer.MAX_VALUE || size > Integer.MAX_VALUE) { throw new IllegalArgumentException("offset=" + offset + " size=" + size); } int prot; int flags; if (mapMode == MapMode.PRIVATE) { prot = PROT_READ|PROT_WRITE; flags = MAP_PRIVATE; } else if (mapMode == MapMode.READ_ONLY) { prot = PROT_READ; flags = MAP_SHARED; } else { // mapMode == MapMode.READ_WRITE prot = PROT_READ|PROT_WRITE; flags = MAP_SHARED; } try { long address = Libcore.os.mmap(0L, size, prot, flags, fd, offset); return new MemoryMappedBlock(address, size); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
public PipeImpl(SelectorProvider selectorProvider) throws IOException { try { FileDescriptor fd1 = new FileDescriptor(); FileDescriptor fd2 = new FileDescriptor(); Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd1, fd2); // It doesn't matter which file descriptor we use for which end; // they're guaranteed to be indistinguishable. this.sink = new PipeSinkChannel(selectorProvider, fd1); this.source = new PipeSourceChannel(selectorProvider, fd2); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * @see java.nio.channels.DatagramChannel#disconnect() */ @Override synchronized public DatagramChannel disconnect() throws IOException { if (!isConnected() || !isOpen()) { return this; } connected = false; connectAddress = null; try { Libcore.os.connect(fd, InetAddress.UNSPECIFIED, 0); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } if (socket != null) { socket.disconnect(); } return this; }
public SelectorImpl(SelectorProvider selectorProvider) throws IOException { super(selectorProvider); /* * Create a pipe to trigger wakeup. We can't use a NIO pipe because it * would be closed if the selecting thread is interrupted. Also * configure the pipe so we can fully drain it without blocking. */ try { FileDescriptor[] pipeFds = Libcore.os.pipe(); wakeupIn = pipeFds[0]; wakeupOut = pipeFds[1]; IoUtils.setBlocking(wakeupIn, false); pollFds.add(new StructPollfd()); setPollFd(0, wakeupIn, POLLIN, null); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } }
/** * Non-API method to release a given lock on a file channel. Assumes that * the lock will mark itself invalid after successful unlocking. */ public void release(FileLock lock) throws IOException { checkOpen(); StructFlock flock = new StructFlock(); flock.l_type = (short) F_UNLCK; flock.l_whence = (short) SEEK_SET; flock.l_start = lock.position(); flock.l_len = translateLockLength(lock.size()); try { Libcore.os.fcntlFlock(fd, F_SETLKW64, flock); } catch (ErrnoException errnoException) { throw errnoException.rethrowAsIOException(); } removeLock(lock); }