summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--luni/src/main/java/java/nio/DatagramChannelImpl.java22
-rw-r--r--luni/src/main/java/java/nio/FileChannelImpl.java7
-rw-r--r--luni/src/main/java/java/nio/SocketChannelImpl.java6
-rw-r--r--luni/src/main/java/libcore/io/Posix.java65
-rw-r--r--luni/src/test/java/libcore/io/OsTest.java121
5 files changed, 176 insertions, 45 deletions
diff --git a/luni/src/main/java/java/nio/DatagramChannelImpl.java b/luni/src/main/java/java/nio/DatagramChannelImpl.java
index 9008637..8dd6f29 100644
--- a/luni/src/main/java/java/nio/DatagramChannelImpl.java
+++ b/luni/src/main/java/java/nio/DatagramChannelImpl.java
@@ -274,15 +274,9 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann
private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException {
SocketAddress retAddr = null;
DatagramPacket receivePacket = new DatagramPacket(EmptyArray.BYTE, 0);
- int oldposition = target.position();
- int received;
do {
- received = IoBridge.recvfrom(false, fd, target, 0, receivePacket, isConnected());
+ IoBridge.recvfrom(false, fd, target, 0, receivePacket, isConnected());
if (receivePacket.getAddress() != null) {
- // copy the data of received packet
- if (received > 0) {
- target.position(oldposition + received);
- }
retAddr = receivePacket.getSocketAddress();
break;
}
@@ -309,11 +303,7 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann
int sendCount = 0;
try {
begin();
- int oldPosition = source.position();
sendCount = IoBridge.sendto(fd, source, 0, isa.getAddress(), isa.getPort());
- if (sendCount > 0) {
- source.position(oldPosition + sendCount);
- }
if (!isBound) {
onBind(true /* updateSocketState */);
}
@@ -336,10 +326,6 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann
int readCount;
if (target.isDirect() || target.hasArray()) {
readCount = readImpl(target);
- if (readCount > 0) {
- target.position(target.position() + readCount);
- }
-
} else {
byte[] readArray = new byte[target.remaining()];
ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
@@ -406,11 +392,7 @@ class DatagramChannelImpl extends DatagramChannel implements FileDescriptorChann
return 0;
}
- int writeCount = writeImpl(src);
- if (writeCount > 0) {
- src.position(src.position() + writeCount);
- }
- return writeCount;
+ return writeImpl(src);
}
/**
diff --git a/luni/src/main/java/java/nio/FileChannelImpl.java b/luni/src/main/java/java/nio/FileChannelImpl.java
index d72b9f0..b560864 100644
--- a/luni/src/main/java/java/nio/FileChannelImpl.java
+++ b/luni/src/main/java/java/nio/FileChannelImpl.java
@@ -323,9 +323,7 @@ final class FileChannelImpl extends FileChannel {
} finally {
end(completed && bytesRead >= 0);
}
- if (bytesRead > 0) {
- buffer.position(buffer.position() + bytesRead);
- }
+
return bytesRead;
}
@@ -508,9 +506,6 @@ final class FileChannelImpl extends FileChannel {
} finally {
end(completed);
}
- if (bytesWritten > 0) {
- buffer.position(buffer.position() + bytesWritten);
- }
return bytesWritten;
}
diff --git a/luni/src/main/java/java/nio/SocketChannelImpl.java b/luni/src/main/java/java/nio/SocketChannelImpl.java
index d5cb716..d09aaef 100644
--- a/luni/src/main/java/java/nio/SocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/SocketChannelImpl.java
@@ -340,9 +340,6 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorChannel {
begin();
}
readCount = IoBridge.recvfrom(true, fd, dst, 0, null, false);
- if (readCount > 0) {
- dst.position(dst.position() + readCount);
- }
} finally {
if (isBlocking()) {
end(readCount > 0);
@@ -404,9 +401,6 @@ class SocketChannelImpl extends SocketChannel implements FileDescriptorChannel {
begin();
}
writeCount = IoBridge.sendto(fd, src, 0, null, 0);
- if (writeCount > 0) {
- src.position(src.position() + writeCount);
- }
} finally {
if (isBlocking()) {
end(writeCount >= 0);
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index 73b0dc4..1772c34 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -112,11 +112,17 @@ public final class Posix implements Os {
public native void posix_fallocate(FileDescriptor fd, long offset, long length) throws ErrnoException;
public native int prctl(int option, long arg2, long arg3, long arg4, long arg5) throws ErrnoException;
public int pread(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
+ final int bytesRead;
+ final int position = buffer.position();
+
if (buffer.isDirect()) {
- return preadBytes(fd, buffer, buffer.position(), buffer.remaining(), offset);
+ bytesRead = preadBytes(fd, buffer, position, buffer.remaining(), offset);
} else {
- return preadBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), offset);
+ bytesRead = preadBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), offset);
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesRead);
+ return bytesRead;
}
public int pread(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -124,11 +130,17 @@ public final class Posix implements Os {
}
private native int preadBytes(FileDescriptor fd, Object buffer, int bufferOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException;
public int pwrite(FileDescriptor fd, ByteBuffer buffer, long offset) throws ErrnoException, InterruptedIOException {
+ final int bytesWritten;
+ final int position = buffer.position();
+
if (buffer.isDirect()) {
- return pwriteBytes(fd, buffer, buffer.position(), buffer.remaining(), offset);
+ bytesWritten = pwriteBytes(fd, buffer, position, buffer.remaining(), offset);
} else {
- return pwriteBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), offset);
+ bytesWritten = pwriteBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), offset);
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesWritten);
+ return bytesWritten;
}
public int pwrite(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -136,11 +148,17 @@ public final class Posix implements Os {
}
private native int pwriteBytes(FileDescriptor fd, Object buffer, int bufferOffset, int byteCount, long offset) throws ErrnoException, InterruptedIOException;
public int read(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
+ final int bytesRead;
+ final int position = buffer.position();
+
if (buffer.isDirect()) {
- return readBytes(fd, buffer, buffer.position(), buffer.remaining());
+ bytesRead = readBytes(fd, buffer, position, buffer.remaining());
} else {
- return readBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining());
+ bytesRead = readBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining());
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesRead);
+ return bytesRead;
}
public int read(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -150,11 +168,17 @@ public final class Posix implements Os {
public native String readlink(String path) throws ErrnoException;
public native int readv(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException;
public int recvfrom(FileDescriptor fd, ByteBuffer buffer, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
+ final int bytesReceived;
+ final int position = buffer.position();
+
if (buffer.isDirect()) {
- return recvfromBytes(fd, buffer, buffer.position(), buffer.remaining(), flags, srcAddress);
+ bytesReceived = recvfromBytes(fd, buffer, position, buffer.remaining(), flags, srcAddress);
} else {
- return recvfromBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), flags, srcAddress);
+ bytesReceived = recvfromBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), flags, srcAddress);
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesReceived);
+ return bytesReceived;
}
public int recvfrom(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetSocketAddress srcAddress) throws ErrnoException, SocketException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -165,11 +189,17 @@ public final class Posix implements Os {
public native void rename(String oldPath, String newPath) throws ErrnoException;
public native long sendfile(FileDescriptor outFd, FileDescriptor inFd, MutableLong inOffset, long byteCount) throws ErrnoException;
public int sendto(FileDescriptor fd, ByteBuffer buffer, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
+ final int bytesSent;
+ final int position = buffer.position();
+
if (buffer.isDirect()) {
- return sendtoBytes(fd, buffer, buffer.position(), buffer.remaining(), flags, inetAddress, port);
+ bytesSent = sendtoBytes(fd, buffer, position, buffer.remaining(), flags, inetAddress, port);
} else {
- return sendtoBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining(), flags, inetAddress, port);
+ bytesSent = sendtoBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining(), flags, inetAddress, port);
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesSent);
+ return bytesSent;
}
public int sendto(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount, int flags, InetAddress inetAddress, int port) throws ErrnoException, SocketException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -212,11 +242,16 @@ public final class Posix implements Os {
public native void unsetenv(String name) throws ErrnoException;
public native int waitpid(int pid, MutableInt status, int options) throws ErrnoException;
public int write(FileDescriptor fd, ByteBuffer buffer) throws ErrnoException, InterruptedIOException {
+ final int bytesWritten;
+ final int position = buffer.position();
if (buffer.isDirect()) {
- return writeBytes(fd, buffer, buffer.position(), buffer.remaining());
+ bytesWritten = writeBytes(fd, buffer, position, buffer.remaining());
} else {
- return writeBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + buffer.position(), buffer.remaining());
+ bytesWritten = writeBytes(fd, NioUtils.unsafeArray(buffer), NioUtils.unsafeArrayOffset(buffer) + position, buffer.remaining());
}
+
+ maybeUpdateBufferPosition(buffer, position, bytesWritten);
+ return bytesWritten;
}
public int write(FileDescriptor fd, byte[] bytes, int byteOffset, int byteCount) throws ErrnoException, InterruptedIOException {
// This indirection isn't strictly necessary, but ensures that our public interface is type safe.
@@ -224,4 +259,10 @@ public final class Posix implements Os {
}
private native int writeBytes(FileDescriptor fd, Object buffer, int offset, int byteCount) throws ErrnoException, InterruptedIOException;
public native int writev(FileDescriptor fd, Object[] buffers, int[] offsets, int[] byteCounts) throws ErrnoException, InterruptedIOException;
+
+ private static void maybeUpdateBufferPosition(ByteBuffer buffer, int originalPosition, int bytesReadOrWritten) {
+ if (bytesReadOrWritten > 0) {
+ buffer.position(bytesReadOrWritten + originalPosition);
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index cf28122..a0d1e5a 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -20,11 +20,14 @@ import android.system.StructUcred;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InetUnixAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import java.util.Locale;
import junit.framework.TestCase;
import static android.system.OsConstants.*;
@@ -77,7 +80,7 @@ public class OsTest extends TestCase {
assertEquals(Libcore.os.getgid(), credentials.gid);
byte[] request = new byte[256];
- int requestLength = Libcore.os.read(clientFd, request, 0, request.length);
+ Libcore.os.read(clientFd, request, 0, request.length);
String s = new String(request, "UTF-8");
byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
@@ -135,4 +138,120 @@ public class OsTest extends TestCase {
assertEquals("Killed", Libcore.os.strsignal(9));
assertEquals("Unknown signal -1", Libcore.os.strsignal(-1));
}
+
+ public void test_byteBufferPositions_write_pwrite() throws Exception {
+ FileOutputStream fos = new FileOutputStream(new File("/dev/null"));
+ FileDescriptor fd = fos.getFD();
+ final byte[] contents = new String("goodbye, cruel world").getBytes(StandardCharsets.US_ASCII);
+ ByteBuffer byteBuffer = ByteBuffer.wrap(contents);
+
+ byteBuffer.position(0);
+ int written = Libcore.os.write(fd, byteBuffer);
+ assertTrue(written > 0);
+ assertEquals(written, byteBuffer.position());
+
+ byteBuffer.position(4);
+ written = Libcore.os.write(fd, byteBuffer);
+ assertTrue(written > 0);
+ assertEquals(written + 4, byteBuffer.position());
+
+ byteBuffer.position(0);
+ written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */);
+ assertTrue(written > 0);
+ assertEquals(written, byteBuffer.position());
+
+ byteBuffer.position(4);
+ written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */);
+ assertTrue(written > 0);
+ assertEquals(written + 4, byteBuffer.position());
+
+ fos.close();
+ }
+
+ public void test_byteBufferPositions_read_pread() throws Exception {
+ FileInputStream fis = new FileInputStream(new File("/dev/zero"));
+ FileDescriptor fd = fis.getFD();
+ ByteBuffer byteBuffer = ByteBuffer.allocate(64);
+
+ byteBuffer.position(0);
+ int read = Libcore.os.read(fd, byteBuffer);
+ assertTrue(read > 0);
+ assertEquals(read, byteBuffer.position());
+
+ byteBuffer.position(4);
+ read = Libcore.os.read(fd, byteBuffer);
+ assertTrue(read > 0);
+ assertEquals(read + 4, byteBuffer.position());
+
+ byteBuffer.position(0);
+ read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */);
+ assertTrue(read > 0);
+ assertEquals(read, byteBuffer.position());
+
+ byteBuffer.position(4);
+ read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */);
+ assertTrue(read > 0);
+ assertEquals(read + 4, byteBuffer.position());
+
+ fis.close();
+ }
+
+ public void test_byteBufferPositions_sendto_recvfrom() throws Exception {
+ final FileDescriptor serverFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0);
+ Libcore.os.bind(serverFd, InetAddress.getLoopbackAddress(), 0);
+ Libcore.os.listen(serverFd, 5);
+
+ InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd);
+
+ final Thread server = new Thread(new Runnable() {
+ public void run() {
+ try {
+ InetSocketAddress peerAddress = new InetSocketAddress();
+ FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress);
+
+ // Attempt to receive a maximum of 24 bytes from the client, and then
+ // close the connection.
+ ByteBuffer buffer = ByteBuffer.allocate(16);
+ int received = Libcore.os.recvfrom(clientFd, buffer, 0, null);
+ assertTrue(received > 0);
+ assertEquals(received, buffer.position());
+
+ ByteBuffer buffer2 = ByteBuffer.allocate(16);
+ buffer2.position(8);
+ received = Libcore.os.recvfrom(clientFd, buffer2, 0, null);
+ assertTrue(received > 0);
+ assertEquals(received + 8, buffer.position());
+
+ Libcore.os.close(clientFd);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ });
+
+
+ server.start();
+
+ FileDescriptor clientFd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0);
+ Libcore.os.connect(clientFd, address.getAddress(), address.getPort());
+
+ final byte[] bytes = "good bye, cruel black hole with fancy distortion".getBytes(StandardCharsets.US_ASCII);
+ assertTrue(bytes.length > 24);
+
+ ByteBuffer input = ByteBuffer.wrap(bytes);
+ input.position(0);
+ input.limit(16);
+
+ int sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort());
+ assertTrue(sent > 0);
+ assertEquals(sent, input.position());
+
+ input.position(16);
+ input.limit(24);
+ sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort());
+ assertTrue(sent > 0);
+ assertEquals(sent + 16, input.position());
+
+ Libcore.os.close(clientFd);
+ }
}