• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.io;
18 
19 import android.system.ErrnoException;
20 import android.system.NetlinkSocketAddress;
21 import android.system.OsConstants;
22 import android.system.PacketSocketAddress;
23 import android.system.StructTimeval;
24 import android.system.StructUcred;
25 import java.io.File;
26 import java.io.FileDescriptor;
27 import java.io.FileInputStream;
28 import java.io.FileOutputStream;
29 import java.net.Inet4Address;
30 import java.net.Inet6Address;
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.InetUnixAddress;
34 import java.net.NetworkInterface;
35 import java.net.ServerSocket;
36 import java.net.SocketAddress;
37 import java.nio.ByteBuffer;
38 import java.nio.charset.StandardCharsets;
39 import java.util.Arrays;
40 import java.util.Locale;
41 import junit.framework.TestCase;
42 import static android.system.OsConstants.*;
43 
44 public class OsTest extends TestCase {
testIsSocket()45   public void testIsSocket() throws Exception {
46     File f = new File("/dev/null");
47     FileInputStream fis = new FileInputStream(f);
48     assertFalse(S_ISSOCK(Libcore.os.fstat(fis.getFD()).st_mode));
49     fis.close();
50 
51     ServerSocket s = new ServerSocket();
52     assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl$().getFD$()).st_mode));
53     s.close();
54   }
55 
testFcntlInt()56   public void testFcntlInt() throws Exception {
57     File f = File.createTempFile("OsTest", "tst");
58     FileInputStream fis = null;
59     try {
60       fis = new FileInputStream(f);
61       Libcore.os.fcntlInt(fis.getFD(), F_SETFD, FD_CLOEXEC);
62       int flags = Libcore.os.fcntlVoid(fis.getFD(), F_GETFD);
63       assertTrue((flags & FD_CLOEXEC) != 0);
64     } finally {
65       IoUtils.closeQuietly(fis);
66       f.delete();
67     }
68   }
69 
testUnixDomainSockets_in_file_system()70   public void testUnixDomainSockets_in_file_system() throws Exception {
71     String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket";
72     new File(path).delete();
73     checkUnixDomainSocket(new InetUnixAddress(path), false);
74   }
75 
testUnixDomainSocket_abstract_name()76   public void testUnixDomainSocket_abstract_name() throws Exception {
77     // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7).
78     byte[] path = "/abstract_name_unix_socket".getBytes("UTF-8");
79     path[0] = 0;
80     checkUnixDomainSocket(new InetUnixAddress(path), true);
81   }
82 
checkUnixDomainSocket(final InetUnixAddress address, final boolean isAbstract)83   private void checkUnixDomainSocket(final InetUnixAddress address, final boolean isAbstract) throws Exception {
84     final FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
85     Libcore.os.bind(serverFd, address, 0);
86     Libcore.os.listen(serverFd, 5);
87 
88     checkSockName(serverFd, isAbstract, address);
89 
90     Thread server = new Thread(new Runnable() {
91       public void run() {
92         try {
93           InetSocketAddress peerAddress = new InetSocketAddress();
94           FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress);
95           checkSockName(clientFd, isAbstract, address);
96           checkNoName(peerAddress);
97 
98           checkNoPeerName(clientFd);
99 
100           StructUcred credentials = Libcore.os.getsockoptUcred(clientFd, SOL_SOCKET, SO_PEERCRED);
101           assertEquals(Libcore.os.getpid(), credentials.pid);
102           assertEquals(Libcore.os.getuid(), credentials.uid);
103           assertEquals(Libcore.os.getgid(), credentials.gid);
104 
105           byte[] request = new byte[256];
106           Libcore.os.read(clientFd, request, 0, request.length);
107 
108           String s = new String(request, "UTF-8");
109           byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
110           Libcore.os.write(clientFd, response, 0, response.length);
111 
112           Libcore.os.close(clientFd);
113         } catch (Exception ex) {
114           throw new RuntimeException(ex);
115         }
116       }
117     });
118     server.start();
119 
120     FileDescriptor clientFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
121 
122     Libcore.os.connect(clientFd, address, 0);
123     checkNoSockName(clientFd);
124 
125     String string = "hello, world!";
126 
127     byte[] request = string.getBytes("UTF-8");
128     assertEquals(request.length, Libcore.os.write(clientFd, request, 0, request.length));
129 
130     byte[] response = new byte[request.length];
131     assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length));
132 
133     assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8"));
134 
135     Libcore.os.close(clientFd);
136   }
137 
checkSockName(FileDescriptor fd, boolean isAbstract, InetAddress address)138   private void checkSockName(FileDescriptor fd, boolean isAbstract, InetAddress address) throws Exception {
139     InetSocketAddress isa = (InetSocketAddress) Libcore.os.getsockname(fd);
140     if (isAbstract) {
141       checkNoName(isa);
142     } else {
143       assertEquals(address, isa.getAddress());
144     }
145   }
146 
checkNoName(SocketAddress sa)147   private void checkNoName(SocketAddress sa) {
148     InetSocketAddress isa = (InetSocketAddress) sa;
149     assertEquals(0, isa.getAddress().getAddress().length);
150   }
151 
checkNoPeerName(FileDescriptor fd)152   private void checkNoPeerName(FileDescriptor fd) throws Exception {
153     checkNoName(Libcore.os.getpeername(fd));
154   }
155 
checkNoSockName(FileDescriptor fd)156   private void checkNoSockName(FileDescriptor fd) throws Exception {
157     checkNoName(Libcore.os.getsockname(fd));
158   }
159 
test_strsignal()160   public void test_strsignal() throws Exception {
161     assertEquals("Killed", Libcore.os.strsignal(9));
162     assertEquals("Unknown signal -1", Libcore.os.strsignal(-1));
163   }
164 
test_byteBufferPositions_write_pwrite()165   public void test_byteBufferPositions_write_pwrite() throws Exception {
166     FileOutputStream fos = new FileOutputStream(new File("/dev/null"));
167     FileDescriptor fd = fos.getFD();
168     final byte[] contents = new String("goodbye, cruel world").getBytes(StandardCharsets.US_ASCII);
169     ByteBuffer byteBuffer = ByteBuffer.wrap(contents);
170 
171     byteBuffer.position(0);
172     int written = Libcore.os.write(fd, byteBuffer);
173     assertTrue(written > 0);
174     assertEquals(written, byteBuffer.position());
175 
176     byteBuffer.position(4);
177     written = Libcore.os.write(fd, byteBuffer);
178     assertTrue(written > 0);
179     assertEquals(written + 4, byteBuffer.position());
180 
181     byteBuffer.position(0);
182     written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */);
183     assertTrue(written > 0);
184     assertEquals(written, byteBuffer.position());
185 
186     byteBuffer.position(4);
187     written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */);
188     assertTrue(written > 0);
189     assertEquals(written + 4, byteBuffer.position());
190 
191     fos.close();
192   }
193 
test_byteBufferPositions_read_pread()194   public void test_byteBufferPositions_read_pread() throws Exception {
195     FileInputStream fis = new FileInputStream(new File("/dev/zero"));
196     FileDescriptor fd = fis.getFD();
197     ByteBuffer byteBuffer = ByteBuffer.allocate(64);
198 
199     byteBuffer.position(0);
200     int read = Libcore.os.read(fd, byteBuffer);
201     assertTrue(read > 0);
202     assertEquals(read, byteBuffer.position());
203 
204     byteBuffer.position(4);
205     read = Libcore.os.read(fd, byteBuffer);
206     assertTrue(read > 0);
207     assertEquals(read + 4, byteBuffer.position());
208 
209     byteBuffer.position(0);
210     read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */);
211     assertTrue(read > 0);
212     assertEquals(read, byteBuffer.position());
213 
214     byteBuffer.position(4);
215     read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */);
216     assertTrue(read > 0);
217     assertEquals(read + 4, byteBuffer.position());
218 
219     fis.close();
220   }
221 
checkByteBufferPositions_sendto_recvfrom( int family, InetAddress loopback)222   static void checkByteBufferPositions_sendto_recvfrom(
223           int family, InetAddress loopback) throws Exception {
224     final FileDescriptor serverFd = Libcore.os.socket(family, SOCK_STREAM, 0);
225     Libcore.os.bind(serverFd, loopback, 0);
226     Libcore.os.listen(serverFd, 5);
227 
228     InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd);
229 
230     final Thread server = new Thread(new Runnable() {
231       public void run() {
232         try {
233           InetSocketAddress peerAddress = new InetSocketAddress();
234           FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress);
235 
236           // Attempt to receive a maximum of 24 bytes from the client, and then
237           // close the connection.
238           ByteBuffer buffer = ByteBuffer.allocate(16);
239           int received = Libcore.os.recvfrom(clientFd, buffer, 0, null);
240           assertTrue(received > 0);
241           assertEquals(received, buffer.position());
242 
243           ByteBuffer buffer2 = ByteBuffer.allocate(16);
244           buffer2.position(8);
245           received = Libcore.os.recvfrom(clientFd, buffer2, 0, null);
246           assertTrue(received > 0);
247           assertEquals(received + 8, buffer.position());
248 
249           Libcore.os.close(clientFd);
250         } catch (Exception ex) {
251           throw new RuntimeException(ex);
252         }
253       }
254     });
255 
256 
257     server.start();
258 
259     FileDescriptor clientFd = Libcore.os.socket(family, SOCK_STREAM, 0);
260     Libcore.os.connect(clientFd, address.getAddress(), address.getPort());
261 
262     final byte[] bytes = "good bye, cruel black hole with fancy distortion".getBytes(StandardCharsets.US_ASCII);
263     assertTrue(bytes.length > 24);
264 
265     ByteBuffer input = ByteBuffer.wrap(bytes);
266     input.position(0);
267     input.limit(16);
268 
269     int sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort());
270     assertTrue(sent > 0);
271     assertEquals(sent, input.position());
272 
273     input.position(16);
274     input.limit(24);
275     sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort());
276     assertTrue(sent > 0);
277     assertEquals(sent + 16, input.position());
278 
279     Libcore.os.close(clientFd);
280   }
281 
test_NetlinkSocket()282   public void test_NetlinkSocket() throws Exception {
283     FileDescriptor nlSocket = Libcore.os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
284     Libcore.os.bind(nlSocket, new NetlinkSocketAddress());
285     NetlinkSocketAddress address = (NetlinkSocketAddress) Libcore.os.getsockname(nlSocket);
286     assertTrue(address.getPortId() > 0);
287     assertEquals(0, address.getGroupsMask());
288 
289     NetlinkSocketAddress nlKernel = new NetlinkSocketAddress();
290     Libcore.os.connect(nlSocket, nlKernel);
291     NetlinkSocketAddress nlPeer = (NetlinkSocketAddress) Libcore.os.getpeername(nlSocket);
292     assertEquals(0, nlPeer.getPortId());
293     assertEquals(0, nlPeer.getGroupsMask());
294     Libcore.os.close(nlSocket);
295   }
296 
test_PacketSocketAddress()297   public void test_PacketSocketAddress() throws Exception {
298     NetworkInterface lo = NetworkInterface.getByName("lo");
299     FileDescriptor fd = Libcore.os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6);
300     PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex());
301     Libcore.os.bind(fd, addr);
302 
303     PacketSocketAddress bound = (PacketSocketAddress) Libcore.os.getsockname(fd);
304     assertEquals((short) ETH_P_IPV6, bound.sll_protocol);  // ETH_P_IPV6 is an int.
305     assertEquals(lo.getIndex(), bound.sll_ifindex);
306     assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype);
307     assertEquals(0, bound.sll_pkttype);
308 
309     // The loopback address is ETH_ALEN bytes long and is all zeros.
310     // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167
311     assertEquals(6, bound.sll_addr.length);
312     for (int i = 0; i < 6; i++) {
313       assertEquals(0, bound.sll_addr[i]);
314     }
315   }
316 
test_byteBufferPositions_sendto_recvfrom_af_inet()317   public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception {
318     checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1"));
319   }
320 
test_byteBufferPositions_sendto_recvfrom_af_inet6()321   public void test_byteBufferPositions_sendto_recvfrom_af_inet6() throws Exception {
322     checkByteBufferPositions_sendto_recvfrom(AF_INET6, InetAddress.getByName("::1"));
323   }
324 
checkSendToSocketAddress(int family, InetAddress loopback)325   private void checkSendToSocketAddress(int family, InetAddress loopback) throws Exception {
326     FileDescriptor recvFd = Libcore.os.socket(family, SOCK_DGRAM, 0);
327     Libcore.os.bind(recvFd, loopback, 0);
328     StructTimeval tv = StructTimeval.fromMillis(20);
329     Libcore.os.setsockoptTimeval(recvFd, SOL_SOCKET, SO_RCVTIMEO, tv);
330 
331     InetSocketAddress to = ((InetSocketAddress) Libcore.os.getsockname(recvFd));
332     FileDescriptor sendFd = Libcore.os.socket(family, SOCK_DGRAM, 0);
333     byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes("UTF-8");
334     int len = msg.length;
335 
336     assertEquals(len, Libcore.os.sendto(sendFd, msg, 0, len, 0, to));
337     byte[] received = new byte[msg.length + 42];
338     InetSocketAddress from = new InetSocketAddress();
339     assertEquals(len, Libcore.os.recvfrom(recvFd, received, 0, received.length, 0, from));
340     assertEquals(loopback, from.getAddress());
341   }
342 
test_sendtoSocketAddress_af_inet()343   public void test_sendtoSocketAddress_af_inet() throws Exception {
344       checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1"));
345   }
346 
test_sendtoSocketAddress_af_inet6()347   public void test_sendtoSocketAddress_af_inet6() throws Exception {
348       checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1"));
349   }
350 
test_socketFamilies()351   public void test_socketFamilies() throws Exception {
352     FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0);
353     Libcore.os.bind(fd, InetAddress.getByName("::"), 0);
354     InetSocketAddress localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd);
355     assertEquals(Inet6Address.ANY, localSocketAddress.getAddress());
356 
357     fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0);
358     Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0);
359     localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd);
360     assertEquals(Inet6Address.ANY, localSocketAddress.getAddress());
361 
362     fd = Libcore.os.socket(AF_INET, SOCK_STREAM, 0);
363     Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0);
364     localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd);
365     assertEquals(Inet4Address.ANY, localSocketAddress.getAddress());
366     try {
367       Libcore.os.bind(fd, InetAddress.getByName("::"), 0);
368       fail("Expected ErrnoException binding IPv4 socket to ::");
369     } catch (ErrnoException expected) {
370       assertEquals("Expected EAFNOSUPPORT binding IPv4 socket to ::", EAFNOSUPPORT, expected.errno);
371     }
372   }
373 
assertArrayEquals(byte[] expected, byte[] actual)374   private static void assertArrayEquals(byte[] expected, byte[] actual) {
375     assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual),
376                Arrays.equals(expected, actual));
377   }
378 
checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet, byte type, byte responseType, boolean useSendto)379   private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet,
380           byte type, byte responseType, boolean useSendto) throws Exception {
381     int len = packet.length;
382     packet[0] = type;
383     if (useSendto) {
384       assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, to, 0));
385     } else {
386       Libcore.os.connect(fd, to, 0);
387       assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, null, 0));
388     }
389 
390     int icmpId = ((InetSocketAddress) Libcore.os.getsockname(fd)).getPort();
391     byte[] received = new byte[4096];
392     InetSocketAddress srcAddress = new InetSocketAddress();
393     assertEquals(len, Libcore.os.recvfrom(fd, received, 0, received.length, 0, srcAddress));
394     assertEquals(to, srcAddress.getAddress());
395     assertEquals(responseType, received[0]);
396     assertEquals(received[4], (byte) (icmpId >> 8));
397     assertEquals(received[5], (byte) (icmpId & 0xff));
398 
399     received = Arrays.copyOf(received, len);
400     received[0] = (byte) type;
401     received[2] = received[3] = 0;  // Checksum.
402     received[4] = received[5] = 0;  // ICMP ID.
403     assertArrayEquals(packet, received);
404   }
405 
test_socketPing()406   public void test_socketPing() throws Exception {
407     final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0;
408     final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129;
409     final byte[] packet = ("\000\000\000\000" +  // ICMP type, code.
410                            "\000\000\000\003" +  // ICMP ID (== port), sequence number.
411                            "Hello myself").getBytes(StandardCharsets.US_ASCII);
412 
413     FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6);
414     InetAddress ipv6Loopback = InetAddress.getByName("::1");
415     checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, true);
416     checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, false);
417 
418     fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
419     InetAddress ipv4Loopback = InetAddress.getByName("127.0.0.1");
420     checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true);
421     checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false);
422   }
423 
assertPartial(byte[] expected, byte[] actual)424     private static void assertPartial(byte[] expected, byte[] actual) {
425         for (int i = 0; i < expected.length; i++) {
426             if (expected[i] != actual[i]) {
427                 fail("Expected " + Arrays.toString(expected) + " but found "
428                         + Arrays.toString(actual));
429             }
430         }
431     }
432 
test_xattr()433     public void test_xattr() throws Exception {
434         final String NAME_TEST = "user.meow";
435 
436         final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8);
437         final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8);
438 
439         File file = File.createTempFile("xattr", "test");
440         String path = file.getAbsolutePath();
441 
442         byte[] tmp = new byte[1024];
443         try {
444             try {
445                 Libcore.os.getxattr(path, NAME_TEST, tmp);
446                 fail("Expected ENODATA");
447             } catch (ErrnoException e) {
448                 assertEquals(OsConstants.ENODATA, e.errno);
449             }
450 
451             Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE);
452             assertEquals(VALUE_CAKE.length, Libcore.os.getxattr(path, NAME_TEST, tmp));
453             assertPartial(VALUE_CAKE, tmp);
454 
455             try {
456                 Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE);
457                 fail("Expected EEXIST");
458             } catch (ErrnoException e) {
459                 assertEquals(OsConstants.EEXIST, e.errno);
460             }
461 
462             Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE);
463             assertEquals(VALUE_PIE.length, Libcore.os.getxattr(path, NAME_TEST, tmp));
464             assertPartial(VALUE_PIE, tmp);
465 
466             Libcore.os.removexattr(path, NAME_TEST);
467             try {
468                 Libcore.os.getxattr(path, NAME_TEST, tmp);
469                 fail("Expected ENODATA");
470             } catch (ErrnoException e) {
471                 assertEquals(OsConstants.ENODATA, e.errno);
472             }
473 
474         } finally {
475             file.delete();
476         }
477     }
478 }
479