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 android.system.UnixSocketAddress; 26 27 import java.io.File; 28 import java.io.FileDescriptor; 29 import java.io.FileInputStream; 30 import java.io.FileOutputStream; 31 import java.net.DatagramPacket; 32 import java.net.DatagramSocket; 33 import java.net.Inet4Address; 34 import java.net.Inet6Address; 35 import java.net.InetAddress; 36 import java.net.InetSocketAddress; 37 import java.net.NetworkInterface; 38 import java.net.ServerSocket; 39 import java.net.SocketOptions; 40 import java.nio.ByteBuffer; 41 import java.nio.charset.StandardCharsets; 42 import java.util.Arrays; 43 import java.util.Collections; 44 import java.util.List; 45 import java.util.Locale; 46 import java.util.concurrent.atomic.AtomicReference; 47 import junit.framework.TestCase; 48 49 import static android.system.OsConstants.*; 50 51 public class OsTest extends TestCase { 52 public void testIsSocket() throws Exception { 53 File f = new File("/dev/null"); 54 FileInputStream fis = new FileInputStream(f); 55 assertFalse(S_ISSOCK(Libcore.os.fstat(fis.getFD()).st_mode)); 56 fis.close(); 57 58 ServerSocket s = new ServerSocket(); 59 assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl().getFD$()).st_mode)); 60 s.close(); 61 } 62 63 public void testFcntlInt() throws Exception { 64 File f = File.createTempFile("OsTest", "tst"); 65 FileInputStream fis = null; 66 try { 67 fis = new FileInputStream(f); 68 Libcore.os.fcntlInt(fis.getFD(), F_SETFD, FD_CLOEXEC); 69 int flags = Libcore.os.fcntlVoid(fis.getFD(), F_GETFD); 70 assertTrue((flags & FD_CLOEXEC) != 0); 71 } finally { 72 IoUtils.closeQuietly(fis); 73 f.delete(); 74 } 75 } 76 77 public void testUnixDomainSockets_in_file_system() throws Exception { 78 String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket"; 79 new File(path).delete(); 80 checkUnixDomainSocket(UnixSocketAddress.createFileSystem(path), false); 81 } 82 83 public void testUnixDomainSocket_abstract_name() throws Exception { 84 // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7). 85 checkUnixDomainSocket(UnixSocketAddress.createAbstract("/abstract_name_unix_socket"), true); 86 } 87 88 public void testUnixDomainSocket_unnamed() throws Exception { 89 final FileDescriptor fd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 90 // unix(7) says an unbound socket is unnamed. 91 checkNoSockName(fd); 92 Libcore.os.close(fd); 93 } 94 95 private void checkUnixDomainSocket(final UnixSocketAddress address, final boolean isAbstract) 96 throws Exception { 97 final FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 98 Libcore.os.bind(serverFd, address); 99 Libcore.os.listen(serverFd, 5); 100 101 checkSockName(serverFd, isAbstract, address); 102 103 Thread server = new Thread(new Runnable() { 104 public void run() { 105 try { 106 UnixSocketAddress peerAddress = UnixSocketAddress.createUnnamed(); 107 FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress); 108 checkSockName(clientFd, isAbstract, address); 109 checkNoName(peerAddress); 110 111 checkNoPeerName(clientFd); 112 113 StructUcred credentials = Libcore.os.getsockoptUcred(clientFd, SOL_SOCKET, SO_PEERCRED); 114 assertEquals(Libcore.os.getpid(), credentials.pid); 115 assertEquals(Libcore.os.getuid(), credentials.uid); 116 assertEquals(Libcore.os.getgid(), credentials.gid); 117 118 byte[] request = new byte[256]; 119 Libcore.os.read(clientFd, request, 0, request.length); 120 121 String s = new String(request, "UTF-8"); 122 byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8"); 123 Libcore.os.write(clientFd, response, 0, response.length); 124 125 Libcore.os.close(clientFd); 126 } catch (Exception ex) { 127 throw new RuntimeException(ex); 128 } 129 } 130 }); 131 server.start(); 132 133 FileDescriptor clientFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 134 135 Libcore.os.connect(clientFd, address); 136 checkNoSockName(clientFd); 137 138 String string = "hello, world!"; 139 140 byte[] request = string.getBytes("UTF-8"); 141 assertEquals(request.length, Libcore.os.write(clientFd, request, 0, request.length)); 142 143 byte[] response = new byte[request.length]; 144 assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length)); 145 146 assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8")); 147 148 Libcore.os.close(clientFd); 149 } 150 151 private static void checkSockName(FileDescriptor fd, boolean isAbstract, 152 UnixSocketAddress address) throws Exception { 153 UnixSocketAddress isa = (UnixSocketAddress) Libcore.os.getsockname(fd); 154 assertEquals(address, isa); 155 if (isAbstract) { 156 assertEquals(0, isa.getSunPath()[0]); 157 } 158 } 159 160 private void checkNoName(UnixSocketAddress usa) { 161 assertEquals(0, usa.getSunPath().length); 162 } 163 164 private void checkNoPeerName(FileDescriptor fd) throws Exception { 165 checkNoName((UnixSocketAddress) Libcore.os.getpeername(fd)); 166 } 167 168 private void checkNoSockName(FileDescriptor fd) throws Exception { 169 checkNoName((UnixSocketAddress) Libcore.os.getsockname(fd)); 170 } 171 172 public void test_strsignal() throws Exception { 173 assertEquals("Killed", Libcore.os.strsignal(9)); 174 assertEquals("Unknown signal -1", Libcore.os.strsignal(-1)); 175 } 176 177 public void test_byteBufferPositions_write_pwrite() throws Exception { 178 FileOutputStream fos = new FileOutputStream(new File("/dev/null")); 179 FileDescriptor fd = fos.getFD(); 180 final byte[] contents = new String("goodbye, cruel world").getBytes(StandardCharsets.US_ASCII); 181 ByteBuffer byteBuffer = ByteBuffer.wrap(contents); 182 183 byteBuffer.position(0); 184 int written = Libcore.os.write(fd, byteBuffer); 185 assertTrue(written > 0); 186 assertEquals(written, byteBuffer.position()); 187 188 byteBuffer.position(4); 189 written = Libcore.os.write(fd, byteBuffer); 190 assertTrue(written > 0); 191 assertEquals(written + 4, byteBuffer.position()); 192 193 byteBuffer.position(0); 194 written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); 195 assertTrue(written > 0); 196 assertEquals(written, byteBuffer.position()); 197 198 byteBuffer.position(4); 199 written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); 200 assertTrue(written > 0); 201 assertEquals(written + 4, byteBuffer.position()); 202 203 fos.close(); 204 } 205 206 public void test_byteBufferPositions_read_pread() throws Exception { 207 FileInputStream fis = new FileInputStream(new File("/dev/zero")); 208 FileDescriptor fd = fis.getFD(); 209 ByteBuffer byteBuffer = ByteBuffer.allocate(64); 210 211 byteBuffer.position(0); 212 int read = Libcore.os.read(fd, byteBuffer); 213 assertTrue(read > 0); 214 assertEquals(read, byteBuffer.position()); 215 216 byteBuffer.position(4); 217 read = Libcore.os.read(fd, byteBuffer); 218 assertTrue(read > 0); 219 assertEquals(read + 4, byteBuffer.position()); 220 221 byteBuffer.position(0); 222 read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); 223 assertTrue(read > 0); 224 assertEquals(read, byteBuffer.position()); 225 226 byteBuffer.position(4); 227 read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); 228 assertTrue(read > 0); 229 assertEquals(read + 4, byteBuffer.position()); 230 231 fis.close(); 232 } 233 234 static void checkByteBufferPositions_sendto_recvfrom( 235 int family, InetAddress loopback) throws Exception { 236 final FileDescriptor serverFd = Libcore.os.socket(family, SOCK_STREAM, 0); 237 Libcore.os.bind(serverFd, loopback, 0); 238 Libcore.os.listen(serverFd, 5); 239 240 InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd); 241 242 final Thread server = new Thread(new Runnable() { 243 public void run() { 244 try { 245 InetSocketAddress peerAddress = new InetSocketAddress(); 246 FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress); 247 248 // Attempt to receive a maximum of 24 bytes from the client, and then 249 // close the connection. 250 ByteBuffer buffer = ByteBuffer.allocate(16); 251 int received = Libcore.os.recvfrom(clientFd, buffer, 0, null); 252 assertTrue(received > 0); 253 assertEquals(received, buffer.position()); 254 255 ByteBuffer buffer2 = ByteBuffer.allocate(16); 256 buffer2.position(8); 257 received = Libcore.os.recvfrom(clientFd, buffer2, 0, null); 258 assertTrue(received > 0); 259 assertEquals(received + 8, buffer.position()); 260 261 Libcore.os.close(clientFd); 262 } catch (Exception ex) { 263 throw new RuntimeException(ex); 264 } 265 } 266 }); 267 268 server.start(); 269 270 FileDescriptor clientFd = Libcore.os.socket(family, SOCK_STREAM, 0); 271 Libcore.os.connect(clientFd, address.getAddress(), address.getPort()); 272 273 final byte[] bytes = "good bye, cruel black hole with fancy distortion" 274 .getBytes(StandardCharsets.US_ASCII); 275 assertTrue(bytes.length > 24); 276 277 ByteBuffer input = ByteBuffer.wrap(bytes); 278 input.position(0); 279 input.limit(16); 280 281 int sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); 282 assertTrue(sent > 0); 283 assertEquals(sent, input.position()); 284 285 input.position(16); 286 input.limit(24); 287 sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); 288 assertTrue(sent > 0); 289 assertEquals(sent + 16, input.position()); 290 291 Libcore.os.close(clientFd); 292 } 293 294 public void test_NetlinkSocket() throws Exception { 295 FileDescriptor nlSocket = Libcore.os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); 296 Libcore.os.bind(nlSocket, new NetlinkSocketAddress()); 297 NetlinkSocketAddress address = (NetlinkSocketAddress) Libcore.os.getsockname(nlSocket); 298 assertTrue(address.getPortId() > 0); 299 assertEquals(0, address.getGroupsMask()); 300 301 NetlinkSocketAddress nlKernel = new NetlinkSocketAddress(); 302 Libcore.os.connect(nlSocket, nlKernel); 303 NetlinkSocketAddress nlPeer = (NetlinkSocketAddress) Libcore.os.getpeername(nlSocket); 304 assertEquals(0, nlPeer.getPortId()); 305 assertEquals(0, nlPeer.getGroupsMask()); 306 Libcore.os.close(nlSocket); 307 } 308 309 public void test_PacketSocketAddress() throws Exception { 310 NetworkInterface lo = NetworkInterface.getByName("lo"); 311 FileDescriptor fd = Libcore.os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6); 312 PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex()); 313 Libcore.os.bind(fd, addr); 314 315 PacketSocketAddress bound = (PacketSocketAddress) Libcore.os.getsockname(fd); 316 assertEquals((short) ETH_P_IPV6, bound.sll_protocol); // ETH_P_IPV6 is an int. 317 assertEquals(lo.getIndex(), bound.sll_ifindex); 318 assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype); 319 assertEquals(0, bound.sll_pkttype); 320 321 // The loopback address is ETH_ALEN bytes long and is all zeros. 322 // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167 323 assertEquals(6, bound.sll_addr.length); 324 for (int i = 0; i < 6; i++) { 325 assertEquals(0, bound.sll_addr[i]); 326 } 327 } 328 329 public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception { 330 checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1")); 331 } 332 333 public void test_byteBufferPositions_sendto_recvfrom_af_inet6() throws Exception { 334 checkByteBufferPositions_sendto_recvfrom(AF_INET6, InetAddress.getByName("::1")); 335 } 336 337 private void checkSendToSocketAddress(int family, InetAddress loopback) throws Exception { 338 FileDescriptor recvFd = Libcore.os.socket(family, SOCK_DGRAM, 0); 339 Libcore.os.bind(recvFd, loopback, 0); 340 StructTimeval tv = StructTimeval.fromMillis(20); 341 Libcore.os.setsockoptTimeval(recvFd, SOL_SOCKET, SO_RCVTIMEO, tv); 342 343 InetSocketAddress to = ((InetSocketAddress) Libcore.os.getsockname(recvFd)); 344 FileDescriptor sendFd = Libcore.os.socket(family, SOCK_DGRAM, 0); 345 byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes("UTF-8"); 346 int len = msg.length; 347 348 assertEquals(len, Libcore.os.sendto(sendFd, msg, 0, len, 0, to)); 349 byte[] received = new byte[msg.length + 42]; 350 InetSocketAddress from = new InetSocketAddress(); 351 assertEquals(len, Libcore.os.recvfrom(recvFd, received, 0, received.length, 0, from)); 352 assertEquals(loopback, from.getAddress()); 353 } 354 355 public void test_sendtoSocketAddress_af_inet() throws Exception { 356 checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1")); 357 } 358 359 public void test_sendtoSocketAddress_af_inet6() throws Exception { 360 checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1")); 361 } 362 363 public void test_socketFamilies() throws Exception { 364 FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); 365 Libcore.os.bind(fd, InetAddress.getByName("::"), 0); 366 InetSocketAddress localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 367 assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); 368 369 fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); 370 Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); 371 localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 372 assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); 373 374 fd = Libcore.os.socket(AF_INET, SOCK_STREAM, 0); 375 Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); 376 localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 377 assertEquals(Inet4Address.ANY, localSocketAddress.getAddress()); 378 try { 379 Libcore.os.bind(fd, InetAddress.getByName("::"), 0); 380 fail("Expected ErrnoException binding IPv4 socket to ::"); 381 } catch (ErrnoException expected) { 382 assertEquals("Expected EAFNOSUPPORT binding IPv4 socket to ::", EAFNOSUPPORT, expected.errno); 383 } 384 } 385 386 private static void assertArrayEquals(byte[] expected, byte[] actual) { 387 assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual), 388 Arrays.equals(expected, actual)); 389 } 390 391 private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet, 392 byte type, byte responseType, boolean useSendto) throws Exception { 393 int len = packet.length; 394 packet[0] = type; 395 if (useSendto) { 396 assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, to, 0)); 397 } else { 398 Libcore.os.connect(fd, to, 0); 399 assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, null, 0)); 400 } 401 402 int icmpId = ((InetSocketAddress) Libcore.os.getsockname(fd)).getPort(); 403 byte[] received = new byte[4096]; 404 InetSocketAddress srcAddress = new InetSocketAddress(); 405 assertEquals(len, Libcore.os.recvfrom(fd, received, 0, received.length, 0, srcAddress)); 406 assertEquals(to, srcAddress.getAddress()); 407 assertEquals(responseType, received[0]); 408 assertEquals(received[4], (byte) (icmpId >> 8)); 409 assertEquals(received[5], (byte) (icmpId & 0xff)); 410 411 received = Arrays.copyOf(received, len); 412 received[0] = (byte) type; 413 received[2] = received[3] = 0; // Checksum. 414 received[4] = received[5] = 0; // ICMP ID. 415 assertArrayEquals(packet, received); 416 } 417 418 public void test_socketPing() throws Exception { 419 final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0; 420 final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129; 421 final byte[] packet = ("\000\000\000\000" + // ICMP type, code. 422 "\000\000\000\003" + // ICMP ID (== port), sequence number. 423 "Hello myself").getBytes(StandardCharsets.US_ASCII); 424 425 FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); 426 InetAddress ipv6Loopback = InetAddress.getByName("::1"); 427 checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, true); 428 checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, false); 429 430 fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); 431 InetAddress ipv4Loopback = InetAddress.getByName("127.0.0.1"); 432 checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true); 433 checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false); 434 } 435 436 public void test_Ipv4Fallback() throws Exception { 437 // This number of iterations gives a ~60% chance of creating the conditions that caused 438 // http://b/23088314 without making test times too long. On a hammerhead running MRZ37C using 439 // vogar, this test takes about 4s. 440 final int ITERATIONS = 10000; 441 for (int i = 0; i < ITERATIONS; i++) { 442 FileDescriptor mUdpSock = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 443 try { 444 Libcore.os.bind(mUdpSock, Inet4Address.ANY, 0); 445 } catch(ErrnoException e) { 446 fail("ErrnoException after " + i + " iterations: " + e); 447 } finally { 448 Libcore.os.close(mUdpSock); 449 } 450 } 451 } 452 453 public void test_unlink() throws Exception { 454 File f = File.createTempFile("OsTest", "tst"); 455 assertTrue(f.exists()); 456 Libcore.os.unlink(f.getAbsolutePath()); 457 assertFalse(f.exists()); 458 459 try { 460 Libcore.os.unlink(f.getAbsolutePath()); 461 fail(); 462 } catch (ErrnoException e) { 463 assertEquals(OsConstants.ENOENT, e.errno); 464 } 465 } 466 467 // b/27294715 468 public void test_recvfrom_concurrentShutdown() throws Exception { 469 final FileDescriptor serverFd = Libcore.os.socket(AF_INET, SOCK_DGRAM, 0); 470 Libcore.os.bind(serverFd, InetAddress.getByName("127.0.0.1"), 0); 471 // Set 4s timeout 472 IoBridge.setSocketOption(serverFd, SocketOptions.SO_TIMEOUT, new Integer(4000)); 473 474 final AtomicReference<Exception> killerThreadException = new AtomicReference<Exception>(null); 475 final Thread killer = new Thread(new Runnable() { 476 public void run() { 477 try { 478 Thread.sleep(2000); 479 try { 480 Libcore.os.shutdown(serverFd, SHUT_RDWR); 481 } catch (ErrnoException expected) { 482 if (OsConstants.ENOTCONN != expected.errno) { 483 killerThreadException.set(expected); 484 } 485 } 486 } catch (Exception ex) { 487 killerThreadException.set(ex); 488 } 489 } 490 }); 491 killer.start(); 492 493 ByteBuffer buffer = ByteBuffer.allocate(16); 494 InetSocketAddress srcAddress = new InetSocketAddress(); 495 int received = Libcore.os.recvfrom(serverFd, buffer, 0, srcAddress); 496 assertTrue(received == 0); 497 Libcore.os.close(serverFd); 498 499 killer.join(); 500 assertNull(killerThreadException.get()); 501 } 502 503 public void test_xattr() throws Exception { 504 final String NAME_TEST = "user.meow"; 505 506 final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); 507 final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8); 508 509 File file = File.createTempFile("xattr", "test"); 510 String path = file.getAbsolutePath(); 511 512 try { 513 try { 514 Libcore.os.getxattr(path, NAME_TEST); 515 fail("Expected ENODATA"); 516 } catch (ErrnoException e) { 517 assertEquals(OsConstants.ENODATA, e.errno); 518 } 519 assertFalse(Arrays.asList(Libcore.os.listxattr(path)).contains(NAME_TEST)); 520 521 Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); 522 byte[] xattr_create = Libcore.os.getxattr(path, NAME_TEST); 523 assertTrue(Arrays.asList(Libcore.os.listxattr(path)).contains(NAME_TEST)); 524 assertEquals(VALUE_CAKE.length, xattr_create.length); 525 assertStartsWith(VALUE_CAKE, xattr_create); 526 527 try { 528 Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE); 529 fail("Expected EEXIST"); 530 } catch (ErrnoException e) { 531 assertEquals(OsConstants.EEXIST, e.errno); 532 } 533 534 Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE); 535 byte[] xattr_replace = Libcore.os.getxattr(path, NAME_TEST); 536 assertTrue(Arrays.asList(Libcore.os.listxattr(path)).contains(NAME_TEST)); 537 assertEquals(VALUE_PIE.length, xattr_replace.length); 538 assertStartsWith(VALUE_PIE, xattr_replace); 539 540 Libcore.os.removexattr(path, NAME_TEST); 541 try { 542 Libcore.os.getxattr(path, NAME_TEST); 543 fail("Expected ENODATA"); 544 } catch (ErrnoException e) { 545 assertEquals(OsConstants.ENODATA, e.errno); 546 } 547 assertFalse(Arrays.asList(Libcore.os.listxattr(path)).contains(NAME_TEST)); 548 549 } finally { 550 file.delete(); 551 } 552 } 553 554 public void test_xattr_NPE() throws Exception { 555 File file = File.createTempFile("xattr", "test"); 556 final String path = file.getAbsolutePath(); 557 final String NAME_TEST = "user.meow"; 558 final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); 559 560 // getxattr 561 try { 562 Libcore.os.getxattr(null, NAME_TEST); 563 fail(); 564 } catch (NullPointerException expected) { } 565 try { 566 Libcore.os.getxattr(path, null); 567 fail(); 568 } catch (NullPointerException expected) { } 569 570 // listxattr 571 try { 572 Libcore.os.listxattr(null); 573 fail(); 574 } catch (NullPointerException expected) { } 575 576 // removexattr 577 try { 578 Libcore.os.removexattr(null, NAME_TEST); 579 fail(); 580 } catch (NullPointerException expected) { } 581 try { 582 Libcore.os.removexattr(path, null); 583 fail(); 584 } catch (NullPointerException expected) { } 585 586 // setxattr 587 try { 588 Libcore.os.setxattr(null, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); 589 fail(); 590 } catch (NullPointerException expected) { } 591 try { 592 Libcore.os.setxattr(path, null, VALUE_CAKE, OsConstants.XATTR_CREATE); 593 fail(); 594 } catch (NullPointerException expected) { } 595 try { 596 Libcore.os.setxattr(path, NAME_TEST, null, OsConstants.XATTR_CREATE); 597 fail(); 598 } catch (NullPointerException expected) { } 599 } 600 601 public void test_xattr_Errno() throws Exception { 602 final String NAME_TEST = "user.meow"; 603 final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); 604 605 // ENOENT, No such file or directory. 606 try { 607 Libcore.os.getxattr("", NAME_TEST); 608 fail(); 609 } catch (ErrnoException e) { 610 assertEquals(ENOENT, e.errno); 611 } 612 try { 613 Libcore.os.listxattr(""); 614 fail(); 615 } catch (ErrnoException e) { 616 assertEquals(ENOENT, e.errno); 617 } 618 try { 619 Libcore.os.removexattr("", NAME_TEST); 620 fail(); 621 } catch (ErrnoException e) { 622 assertEquals(ENOENT, e.errno); 623 } 624 try { 625 Libcore.os.setxattr("", NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); 626 fail(); 627 } catch (ErrnoException e) { 628 assertEquals(ENOENT, e.errno); 629 } 630 631 // ENOTSUP, Extended attributes are not supported by the filesystem, or are disabled. 632 final boolean root = (Libcore.os.getuid() == 0); 633 final String path = "/proc/self/stat"; 634 try { 635 Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); 636 fail(); 637 } catch (ErrnoException e) { 638 // setxattr(2) requires root permission for writing to this file, will get EACCES otherwise. 639 assertEquals(root ? ENOTSUP : EACCES, e.errno); 640 } 641 try { 642 Libcore.os.getxattr(path, NAME_TEST); 643 fail(); 644 } catch (ErrnoException e) { 645 assertEquals(ENOTSUP, e.errno); 646 } 647 try { 648 // Linux listxattr does not set errno. 649 Libcore.os.listxattr(path); 650 } catch (ErrnoException e) { 651 fail(); 652 } 653 try { 654 Libcore.os.removexattr(path, NAME_TEST); 655 fail(); 656 } catch (ErrnoException e) { 657 assertEquals(ENOTSUP, e.errno); 658 } 659 } 660 661 public void test_realpath() throws Exception { 662 File tmpDir = new File(System.getProperty("java.io.tmpdir")); 663 // This is a chicken and egg problem. We have no way of knowing whether 664 // the temporary directory or one of its path elements were symlinked, so 665 // we'll need this call to realpath. 666 String canonicalTmpDir = Libcore.os.realpath(tmpDir.getAbsolutePath()); 667 668 // Test that "." and ".." are resolved correctly. 669 assertEquals(canonicalTmpDir, 670 Libcore.os.realpath(canonicalTmpDir + "/./../" + tmpDir.getName())); 671 672 // Test that symlinks are resolved correctly. 673 File target = new File(tmpDir, "target"); 674 File link = new File(tmpDir, "link"); 675 try { 676 assertTrue(target.createNewFile()); 677 Libcore.os.symlink(target.getAbsolutePath(), link.getAbsolutePath()); 678 679 assertEquals(canonicalTmpDir + "/target", 680 Libcore.os.realpath(canonicalTmpDir + "/link")); 681 } finally { 682 boolean deletedTarget = target.delete(); 683 boolean deletedLink = link.delete(); 684 // Asserting this here to provide a definitive reason for 685 // a subsequent failure on the same run. 686 assertTrue("deletedTarget = " + deletedTarget + ", deletedLink =" + deletedLink, 687 deletedTarget && deletedLink); 688 } 689 } 690 691 /** 692 * Tests that TCP_USER_TIMEOUT can be set on a TCP socket, but doesn't test 693 * that it behaves as expected. 694 */ 695 public void test_socket_tcpUserTimeout_setAndGet() throws Exception { 696 final FileDescriptor fd = Libcore.os.socket(AF_INET, SOCK_STREAM, 0); 697 try { 698 int v = Libcore.os.getsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_USER_TIMEOUT); 699 assertEquals(0, v); // system default value 700 int newValue = 3000; 701 Libcore.os.setsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_USER_TIMEOUT, 702 newValue); 703 assertEquals(newValue, Libcore.os.getsockoptInt(fd, OsConstants.IPPROTO_TCP, 704 OsConstants.TCP_USER_TIMEOUT)); 705 // No need to reset the value to 0, since we're throwing the socket away 706 } finally { 707 Libcore.os.close(fd); 708 } 709 } 710 711 public void test_socket_tcpUserTimeout_doesNotWorkOnDatagramSocket() throws Exception { 712 final FileDescriptor fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, 0); 713 try { 714 Libcore.os.setsockoptInt(fd, OsConstants.IPPROTO_TCP, OsConstants.TCP_USER_TIMEOUT, 715 3000); 716 fail("datagram (connectionless) sockets shouldn't support TCP_USER_TIMEOUT"); 717 } catch (ErrnoException expected) { 718 // expected 719 } finally { 720 Libcore.os.close(fd); 721 } 722 } 723 724 public void test_if_nametoindex_if_indextoname() throws Exception { 725 List<NetworkInterface> nis = Collections.list(NetworkInterface.getNetworkInterfaces()); 726 727 assertTrue(nis.size() > 0); 728 for (NetworkInterface ni : nis) { 729 int index = ni.getIndex(); 730 String name = ni.getName(); 731 assertEquals(index, Libcore.os.if_nametoindex(name)); 732 assertTrue(Libcore.os.if_indextoname(index).equals(name)); 733 } 734 735 assertEquals(0, Libcore.os.if_nametoindex("this-interface-does-not-exist")); 736 assertEquals(null, Libcore.os.if_indextoname(-1000)); 737 738 try { 739 Libcore.os.if_nametoindex(null); 740 fail(); 741 } catch (NullPointerException expected) { } 742 } 743 744 private static void assertStartsWith(byte[] expectedContents, byte[] container) { 745 for (int i = 0; i < expectedContents.length; i++) { 746 if (expectedContents[i] != container[i]) { 747 fail("Expected " + Arrays.toString(expectedContents) + " but found " 748 + Arrays.toString(expectedContents)); 749 } 750 } 751 } 752 753 public void test_readlink() throws Exception { 754 File path = new File(IoUtils.createTemporaryDirectory("test_readlink"), "symlink"); 755 756 // ext2 and ext4 have PAGE_SIZE limits on symlink targets. 757 // If file encryption is enabled, there's extra overhead to store the 758 // size of the encrypted symlink target. There's also an off-by-one 759 // in current kernels (and marlin/sailfish where we're seeing this 760 // failure are still on 3.18, far from current). Given that we don't 761 // really care here, just use 2048 instead. http://b/33306057. 762 int size = 2048; 763 String xs = ""; 764 for (int i = 0; i < size - 1; ++i) xs += "x"; 765 766 Libcore.os.symlink(xs, path.getPath()); 767 768 assertEquals(xs, Libcore.os.readlink(path.getPath())); 769 } 770 771 // Address should be correctly set for empty packets. http://b/33481605 772 public void test_recvfrom_EmptyPacket() throws Exception { 773 try (DatagramSocket ds = new DatagramSocket(); 774 DatagramSocket srcSock = new DatagramSocket()) { 775 srcSock.send(new DatagramPacket(new byte[0], 0, ds.getLocalSocketAddress())); 776 777 byte[] recvBuf = new byte[16]; 778 InetSocketAddress address = new InetSocketAddress(); 779 int recvCount = 780 android.system.Os.recvfrom(ds.getFileDescriptor$(), recvBuf, 0, 16, 0, address); 781 assertEquals(0, recvCount); 782 assertTrue(address.getAddress().isLoopbackAddress()); 783 assertEquals(srcSock.getLocalPort(), address.getPort()); 784 } 785 } 786 } 787