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.Inet4Address; 32 import java.net.Inet6Address; 33 import java.net.InetAddress; 34 import java.net.InetSocketAddress; 35 import java.net.NetworkInterface; 36 import java.net.ServerSocket; 37 import java.net.SocketOptions; 38 import java.nio.ByteBuffer; 39 import java.nio.charset.StandardCharsets; 40 import java.util.Arrays; 41 import java.util.Locale; 42 import java.util.concurrent.atomic.AtomicReference; 43 import junit.framework.TestCase; 44 import static android.system.OsConstants.*; 45 46 public class OsTest extends TestCase { testIsSocket()47 public void testIsSocket() throws Exception { 48 File f = new File("/dev/null"); 49 FileInputStream fis = new FileInputStream(f); 50 assertFalse(S_ISSOCK(Libcore.os.fstat(fis.getFD()).st_mode)); 51 fis.close(); 52 53 ServerSocket s = new ServerSocket(); 54 assertTrue(S_ISSOCK(Libcore.os.fstat(s.getImpl().getFD$()).st_mode)); 55 s.close(); 56 } 57 testFcntlInt()58 public void testFcntlInt() throws Exception { 59 File f = File.createTempFile("OsTest", "tst"); 60 FileInputStream fis = null; 61 try { 62 fis = new FileInputStream(f); 63 Libcore.os.fcntlInt(fis.getFD(), F_SETFD, FD_CLOEXEC); 64 int flags = Libcore.os.fcntlVoid(fis.getFD(), F_GETFD); 65 assertTrue((flags & FD_CLOEXEC) != 0); 66 } finally { 67 IoUtils.closeQuietly(fis); 68 f.delete(); 69 } 70 } 71 testUnixDomainSockets_in_file_system()72 public void testUnixDomainSockets_in_file_system() throws Exception { 73 String path = System.getProperty("java.io.tmpdir") + "/test_unix_socket"; 74 new File(path).delete(); 75 checkUnixDomainSocket(UnixSocketAddress.createFileSystem(path), false); 76 } 77 testUnixDomainSocket_abstract_name()78 public void testUnixDomainSocket_abstract_name() throws Exception { 79 // Linux treats a sun_path starting with a NUL byte as an abstract name. See unix(7). 80 checkUnixDomainSocket(UnixSocketAddress.createAbstract("/abstract_name_unix_socket"), true); 81 } 82 testUnixDomainSocket_unnamed()83 public void testUnixDomainSocket_unnamed() throws Exception { 84 final FileDescriptor fd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 85 // unix(7) says an unbound socket is unnamed. 86 checkNoSockName(fd); 87 Libcore.os.close(fd); 88 } 89 checkUnixDomainSocket(final UnixSocketAddress address, final boolean isAbstract)90 private void checkUnixDomainSocket(final UnixSocketAddress address, final boolean isAbstract) 91 throws Exception { 92 final FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 93 Libcore.os.bind(serverFd, address); 94 Libcore.os.listen(serverFd, 5); 95 96 checkSockName(serverFd, isAbstract, address); 97 98 Thread server = new Thread(new Runnable() { 99 public void run() { 100 try { 101 UnixSocketAddress peerAddress = UnixSocketAddress.createUnnamed(); 102 FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress); 103 checkSockName(clientFd, isAbstract, address); 104 checkNoName(peerAddress); 105 106 checkNoPeerName(clientFd); 107 108 StructUcred credentials = Libcore.os.getsockoptUcred(clientFd, SOL_SOCKET, SO_PEERCRED); 109 assertEquals(Libcore.os.getpid(), credentials.pid); 110 assertEquals(Libcore.os.getuid(), credentials.uid); 111 assertEquals(Libcore.os.getgid(), credentials.gid); 112 113 byte[] request = new byte[256]; 114 Libcore.os.read(clientFd, request, 0, request.length); 115 116 String s = new String(request, "UTF-8"); 117 byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8"); 118 Libcore.os.write(clientFd, response, 0, response.length); 119 120 Libcore.os.close(clientFd); 121 } catch (Exception ex) { 122 throw new RuntimeException(ex); 123 } 124 } 125 }); 126 server.start(); 127 128 FileDescriptor clientFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0); 129 130 Libcore.os.connect(clientFd, address); 131 checkNoSockName(clientFd); 132 133 String string = "hello, world!"; 134 135 byte[] request = string.getBytes("UTF-8"); 136 assertEquals(request.length, Libcore.os.write(clientFd, request, 0, request.length)); 137 138 byte[] response = new byte[request.length]; 139 assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length)); 140 141 assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8")); 142 143 Libcore.os.close(clientFd); 144 } 145 checkSockName(FileDescriptor fd, boolean isAbstract, UnixSocketAddress address)146 private static void checkSockName(FileDescriptor fd, boolean isAbstract, 147 UnixSocketAddress address) throws Exception { 148 UnixSocketAddress isa = (UnixSocketAddress) Libcore.os.getsockname(fd); 149 assertEquals(address, isa); 150 if (isAbstract) { 151 assertEquals(0, isa.getSunPath()[0]); 152 } 153 } 154 checkNoName(UnixSocketAddress usa)155 private void checkNoName(UnixSocketAddress usa) { 156 assertEquals(0, usa.getSunPath().length); 157 } 158 checkNoPeerName(FileDescriptor fd)159 private void checkNoPeerName(FileDescriptor fd) throws Exception { 160 checkNoName((UnixSocketAddress) Libcore.os.getpeername(fd)); 161 } 162 checkNoSockName(FileDescriptor fd)163 private void checkNoSockName(FileDescriptor fd) throws Exception { 164 checkNoName((UnixSocketAddress) Libcore.os.getsockname(fd)); 165 } 166 test_strsignal()167 public void test_strsignal() throws Exception { 168 assertEquals("Killed", Libcore.os.strsignal(9)); 169 assertEquals("Unknown signal -1", Libcore.os.strsignal(-1)); 170 } 171 test_byteBufferPositions_write_pwrite()172 public void test_byteBufferPositions_write_pwrite() throws Exception { 173 FileOutputStream fos = new FileOutputStream(new File("/dev/null")); 174 FileDescriptor fd = fos.getFD(); 175 final byte[] contents = new String("goodbye, cruel world").getBytes(StandardCharsets.US_ASCII); 176 ByteBuffer byteBuffer = ByteBuffer.wrap(contents); 177 178 byteBuffer.position(0); 179 int written = Libcore.os.write(fd, byteBuffer); 180 assertTrue(written > 0); 181 assertEquals(written, byteBuffer.position()); 182 183 byteBuffer.position(4); 184 written = Libcore.os.write(fd, byteBuffer); 185 assertTrue(written > 0); 186 assertEquals(written + 4, byteBuffer.position()); 187 188 byteBuffer.position(0); 189 written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); 190 assertTrue(written > 0); 191 assertEquals(written, byteBuffer.position()); 192 193 byteBuffer.position(4); 194 written = Libcore.os.pwrite(fd, byteBuffer, 64 /* offset */); 195 assertTrue(written > 0); 196 assertEquals(written + 4, byteBuffer.position()); 197 198 fos.close(); 199 } 200 test_byteBufferPositions_read_pread()201 public void test_byteBufferPositions_read_pread() throws Exception { 202 FileInputStream fis = new FileInputStream(new File("/dev/zero")); 203 FileDescriptor fd = fis.getFD(); 204 ByteBuffer byteBuffer = ByteBuffer.allocate(64); 205 206 byteBuffer.position(0); 207 int read = Libcore.os.read(fd, byteBuffer); 208 assertTrue(read > 0); 209 assertEquals(read, byteBuffer.position()); 210 211 byteBuffer.position(4); 212 read = Libcore.os.read(fd, byteBuffer); 213 assertTrue(read > 0); 214 assertEquals(read + 4, byteBuffer.position()); 215 216 byteBuffer.position(0); 217 read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); 218 assertTrue(read > 0); 219 assertEquals(read, byteBuffer.position()); 220 221 byteBuffer.position(4); 222 read = Libcore.os.pread(fd, byteBuffer, 64 /* offset */); 223 assertTrue(read > 0); 224 assertEquals(read + 4, byteBuffer.position()); 225 226 fis.close(); 227 } 228 checkByteBufferPositions_sendto_recvfrom( int family, InetAddress loopback)229 static void checkByteBufferPositions_sendto_recvfrom( 230 int family, InetAddress loopback) throws Exception { 231 final FileDescriptor serverFd = Libcore.os.socket(family, SOCK_STREAM, 0); 232 Libcore.os.bind(serverFd, loopback, 0); 233 Libcore.os.listen(serverFd, 5); 234 235 InetSocketAddress address = (InetSocketAddress) Libcore.os.getsockname(serverFd); 236 237 final Thread server = new Thread(new Runnable() { 238 public void run() { 239 try { 240 InetSocketAddress peerAddress = new InetSocketAddress(); 241 FileDescriptor clientFd = Libcore.os.accept(serverFd, peerAddress); 242 243 // Attempt to receive a maximum of 24 bytes from the client, and then 244 // close the connection. 245 ByteBuffer buffer = ByteBuffer.allocate(16); 246 int received = Libcore.os.recvfrom(clientFd, buffer, 0, null); 247 assertTrue(received > 0); 248 assertEquals(received, buffer.position()); 249 250 ByteBuffer buffer2 = ByteBuffer.allocate(16); 251 buffer2.position(8); 252 received = Libcore.os.recvfrom(clientFd, buffer2, 0, null); 253 assertTrue(received > 0); 254 assertEquals(received + 8, buffer.position()); 255 256 Libcore.os.close(clientFd); 257 } catch (Exception ex) { 258 throw new RuntimeException(ex); 259 } 260 } 261 }); 262 263 server.start(); 264 265 FileDescriptor clientFd = Libcore.os.socket(family, SOCK_STREAM, 0); 266 Libcore.os.connect(clientFd, address.getAddress(), address.getPort()); 267 268 final byte[] bytes = "good bye, cruel black hole with fancy distortion" 269 .getBytes(StandardCharsets.US_ASCII); 270 assertTrue(bytes.length > 24); 271 272 ByteBuffer input = ByteBuffer.wrap(bytes); 273 input.position(0); 274 input.limit(16); 275 276 int sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); 277 assertTrue(sent > 0); 278 assertEquals(sent, input.position()); 279 280 input.position(16); 281 input.limit(24); 282 sent = Libcore.os.sendto(clientFd, input, 0, address.getAddress(), address.getPort()); 283 assertTrue(sent > 0); 284 assertEquals(sent + 16, input.position()); 285 286 Libcore.os.close(clientFd); 287 } 288 test_NetlinkSocket()289 public void test_NetlinkSocket() throws Exception { 290 FileDescriptor nlSocket = Libcore.os.socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); 291 Libcore.os.bind(nlSocket, new NetlinkSocketAddress()); 292 NetlinkSocketAddress address = (NetlinkSocketAddress) Libcore.os.getsockname(nlSocket); 293 assertTrue(address.getPortId() > 0); 294 assertEquals(0, address.getGroupsMask()); 295 296 NetlinkSocketAddress nlKernel = new NetlinkSocketAddress(); 297 Libcore.os.connect(nlSocket, nlKernel); 298 NetlinkSocketAddress nlPeer = (NetlinkSocketAddress) Libcore.os.getpeername(nlSocket); 299 assertEquals(0, nlPeer.getPortId()); 300 assertEquals(0, nlPeer.getGroupsMask()); 301 Libcore.os.close(nlSocket); 302 } 303 test_PacketSocketAddress()304 public void test_PacketSocketAddress() throws Exception { 305 NetworkInterface lo = NetworkInterface.getByName("lo"); 306 FileDescriptor fd = Libcore.os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6); 307 PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex()); 308 Libcore.os.bind(fd, addr); 309 310 PacketSocketAddress bound = (PacketSocketAddress) Libcore.os.getsockname(fd); 311 assertEquals((short) ETH_P_IPV6, bound.sll_protocol); // ETH_P_IPV6 is an int. 312 assertEquals(lo.getIndex(), bound.sll_ifindex); 313 assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype); 314 assertEquals(0, bound.sll_pkttype); 315 316 // The loopback address is ETH_ALEN bytes long and is all zeros. 317 // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167 318 assertEquals(6, bound.sll_addr.length); 319 for (int i = 0; i < 6; i++) { 320 assertEquals(0, bound.sll_addr[i]); 321 } 322 } 323 test_byteBufferPositions_sendto_recvfrom_af_inet()324 public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception { 325 checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1")); 326 } 327 test_byteBufferPositions_sendto_recvfrom_af_inet6()328 public void test_byteBufferPositions_sendto_recvfrom_af_inet6() throws Exception { 329 checkByteBufferPositions_sendto_recvfrom(AF_INET6, InetAddress.getByName("::1")); 330 } 331 checkSendToSocketAddress(int family, InetAddress loopback)332 private void checkSendToSocketAddress(int family, InetAddress loopback) throws Exception { 333 FileDescriptor recvFd = Libcore.os.socket(family, SOCK_DGRAM, 0); 334 Libcore.os.bind(recvFd, loopback, 0); 335 StructTimeval tv = StructTimeval.fromMillis(20); 336 Libcore.os.setsockoptTimeval(recvFd, SOL_SOCKET, SO_RCVTIMEO, tv); 337 338 InetSocketAddress to = ((InetSocketAddress) Libcore.os.getsockname(recvFd)); 339 FileDescriptor sendFd = Libcore.os.socket(family, SOCK_DGRAM, 0); 340 byte[] msg = ("Hello, I'm going to a socket address: " + to.toString()).getBytes("UTF-8"); 341 int len = msg.length; 342 343 assertEquals(len, Libcore.os.sendto(sendFd, msg, 0, len, 0, to)); 344 byte[] received = new byte[msg.length + 42]; 345 InetSocketAddress from = new InetSocketAddress(); 346 assertEquals(len, Libcore.os.recvfrom(recvFd, received, 0, received.length, 0, from)); 347 assertEquals(loopback, from.getAddress()); 348 } 349 test_sendtoSocketAddress_af_inet()350 public void test_sendtoSocketAddress_af_inet() throws Exception { 351 checkSendToSocketAddress(AF_INET, InetAddress.getByName("127.0.0.1")); 352 } 353 test_sendtoSocketAddress_af_inet6()354 public void test_sendtoSocketAddress_af_inet6() throws Exception { 355 checkSendToSocketAddress(AF_INET6, InetAddress.getByName("::1")); 356 } 357 test_socketFamilies()358 public void test_socketFamilies() throws Exception { 359 FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); 360 Libcore.os.bind(fd, InetAddress.getByName("::"), 0); 361 InetSocketAddress localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 362 assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); 363 364 fd = Libcore.os.socket(AF_INET6, SOCK_STREAM, 0); 365 Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); 366 localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 367 assertEquals(Inet6Address.ANY, localSocketAddress.getAddress()); 368 369 fd = Libcore.os.socket(AF_INET, SOCK_STREAM, 0); 370 Libcore.os.bind(fd, InetAddress.getByName("0.0.0.0"), 0); 371 localSocketAddress = (InetSocketAddress) Libcore.os.getsockname(fd); 372 assertEquals(Inet4Address.ANY, localSocketAddress.getAddress()); 373 try { 374 Libcore.os.bind(fd, InetAddress.getByName("::"), 0); 375 fail("Expected ErrnoException binding IPv4 socket to ::"); 376 } catch (ErrnoException expected) { 377 assertEquals("Expected EAFNOSUPPORT binding IPv4 socket to ::", EAFNOSUPPORT, expected.errno); 378 } 379 } 380 assertArrayEquals(byte[] expected, byte[] actual)381 private static void assertArrayEquals(byte[] expected, byte[] actual) { 382 assertTrue("Expected=" + Arrays.toString(expected) + ", actual=" + Arrays.toString(actual), 383 Arrays.equals(expected, actual)); 384 } 385 checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet, byte type, byte responseType, boolean useSendto)386 private static void checkSocketPing(FileDescriptor fd, InetAddress to, byte[] packet, 387 byte type, byte responseType, boolean useSendto) throws Exception { 388 int len = packet.length; 389 packet[0] = type; 390 if (useSendto) { 391 assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, to, 0)); 392 } else { 393 Libcore.os.connect(fd, to, 0); 394 assertEquals(len, Libcore.os.sendto(fd, packet, 0, len, 0, null, 0)); 395 } 396 397 int icmpId = ((InetSocketAddress) Libcore.os.getsockname(fd)).getPort(); 398 byte[] received = new byte[4096]; 399 InetSocketAddress srcAddress = new InetSocketAddress(); 400 assertEquals(len, Libcore.os.recvfrom(fd, received, 0, received.length, 0, srcAddress)); 401 assertEquals(to, srcAddress.getAddress()); 402 assertEquals(responseType, received[0]); 403 assertEquals(received[4], (byte) (icmpId >> 8)); 404 assertEquals(received[5], (byte) (icmpId & 0xff)); 405 406 received = Arrays.copyOf(received, len); 407 received[0] = (byte) type; 408 received[2] = received[3] = 0; // Checksum. 409 received[4] = received[5] = 0; // ICMP ID. 410 assertArrayEquals(packet, received); 411 } 412 test_socketPing()413 public void test_socketPing() throws Exception { 414 final byte ICMP_ECHO = 8, ICMP_ECHOREPLY = 0; 415 final byte ICMPV6_ECHO_REQUEST = (byte) 128, ICMPV6_ECHO_REPLY = (byte) 129; 416 final byte[] packet = ("\000\000\000\000" + // ICMP type, code. 417 "\000\000\000\003" + // ICMP ID (== port), sequence number. 418 "Hello myself").getBytes(StandardCharsets.US_ASCII); 419 420 FileDescriptor fd = Libcore.os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6); 421 InetAddress ipv6Loopback = InetAddress.getByName("::1"); 422 checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, true); 423 checkSocketPing(fd, ipv6Loopback, packet, ICMPV6_ECHO_REQUEST, ICMPV6_ECHO_REPLY, false); 424 425 fd = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); 426 InetAddress ipv4Loopback = InetAddress.getByName("127.0.0.1"); 427 checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, true); 428 checkSocketPing(fd, ipv4Loopback, packet, ICMP_ECHO, ICMP_ECHOREPLY, false); 429 } 430 test_Ipv4Fallback()431 public void test_Ipv4Fallback() throws Exception { 432 // This number of iterations gives a ~60% chance of creating the conditions that caused 433 // http://b/23088314 without making test times too long. On a hammerhead running MRZ37C using 434 // vogar, this test takes about 4s. 435 final int ITERATIONS = 10000; 436 for (int i = 0; i < ITERATIONS; i++) { 437 FileDescriptor mUdpSock = Libcore.os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 438 try { 439 Libcore.os.bind(mUdpSock, Inet4Address.ANY, 0); 440 } catch(ErrnoException e) { 441 fail("ErrnoException after " + i + " iterations: " + e); 442 } finally { 443 Libcore.os.close(mUdpSock); 444 } 445 } 446 } 447 test_unlink()448 public void test_unlink() throws Exception { 449 File f = File.createTempFile("OsTest", "tst"); 450 assertTrue(f.exists()); 451 Libcore.os.unlink(f.getAbsolutePath()); 452 assertFalse(f.exists()); 453 454 try { 455 Libcore.os.unlink(f.getAbsolutePath()); 456 fail(); 457 } catch (ErrnoException e) { 458 assertEquals(OsConstants.ENOENT, e.errno); 459 } 460 } 461 462 // b/27294715 test_recvfrom_concurrentShutdown()463 public void test_recvfrom_concurrentShutdown() throws Exception { 464 final FileDescriptor serverFd = Libcore.os.socket(AF_INET, SOCK_DGRAM, 0); 465 Libcore.os.bind(serverFd, InetAddress.getByName("127.0.0.1"), 0); 466 // Set 4s timeout 467 IoBridge.setSocketOption(serverFd, SocketOptions.SO_TIMEOUT, new Integer(4000)); 468 469 final AtomicReference<Exception> killerThreadException = new AtomicReference<Exception>(null); 470 final Thread killer = new Thread(new Runnable() { 471 public void run() { 472 try { 473 Thread.sleep(2000); 474 try { 475 Libcore.os.shutdown(serverFd, SHUT_RDWR); 476 } catch (ErrnoException expected) { 477 if (OsConstants.ENOTCONN != expected.errno) { 478 killerThreadException.set(expected); 479 } 480 } 481 } catch (Exception ex) { 482 killerThreadException.set(ex); 483 } 484 } 485 }); 486 killer.start(); 487 488 ByteBuffer buffer = ByteBuffer.allocate(16); 489 InetSocketAddress srcAddress = new InetSocketAddress(); 490 int received = Libcore.os.recvfrom(serverFd, buffer, 0, srcAddress); 491 assertTrue(received == 0); 492 Libcore.os.close(serverFd); 493 494 killer.join(); 495 assertNull(killerThreadException.get()); 496 } 497 test_xattr()498 public void test_xattr() throws Exception { 499 final String NAME_TEST = "user.meow"; 500 501 final byte[] VALUE_CAKE = "cake cake cake".getBytes(StandardCharsets.UTF_8); 502 final byte[] VALUE_PIE = "pie".getBytes(StandardCharsets.UTF_8); 503 504 File file = File.createTempFile("xattr", "test"); 505 String path = file.getAbsolutePath(); 506 507 byte[] tmp = new byte[1024]; 508 try { 509 try { 510 Libcore.os.getxattr(path, NAME_TEST, tmp); 511 fail("Expected ENODATA"); 512 } catch (ErrnoException e) { 513 assertEquals(OsConstants.ENODATA, e.errno); 514 } 515 516 Libcore.os.setxattr(path, NAME_TEST, VALUE_CAKE, OsConstants.XATTR_CREATE); 517 assertEquals(VALUE_CAKE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); 518 assertStartsWith(VALUE_CAKE, tmp); 519 520 try { 521 Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_CREATE); 522 fail("Expected EEXIST"); 523 } catch (ErrnoException e) { 524 assertEquals(OsConstants.EEXIST, e.errno); 525 } 526 527 Libcore.os.setxattr(path, NAME_TEST, VALUE_PIE, OsConstants.XATTR_REPLACE); 528 assertEquals(VALUE_PIE.length, Libcore.os.getxattr(path, NAME_TEST, tmp)); 529 assertStartsWith(VALUE_PIE, tmp); 530 531 Libcore.os.removexattr(path, NAME_TEST); 532 try { 533 Libcore.os.getxattr(path, NAME_TEST, tmp); 534 fail("Expected ENODATA"); 535 } catch (ErrnoException e) { 536 assertEquals(OsConstants.ENODATA, e.errno); 537 } 538 539 } finally { 540 file.delete(); 541 } 542 } 543 test_realpath()544 public void test_realpath() throws Exception { 545 File tmpDir = new File(System.getProperty("java.io.tmpdir")); 546 // This is a chicken and egg problem. We have no way of knowing whether 547 // the temporary directory or one of its path elements were symlinked, so 548 // we'll need this call to realpath. 549 String canonicalTmpDir = Libcore.os.realpath(tmpDir.getAbsolutePath()); 550 551 // Test that "." and ".." are resolved correctly. 552 assertEquals(canonicalTmpDir, 553 Libcore.os.realpath(canonicalTmpDir + "/./../" + tmpDir.getName())); 554 555 // Test that symlinks are resolved correctly. 556 File target = new File(tmpDir, "target"); 557 File link = new File(tmpDir, "link"); 558 try { 559 assertTrue(target.createNewFile()); 560 Libcore.os.symlink(target.getAbsolutePath(), link.getAbsolutePath()); 561 562 assertEquals(canonicalTmpDir + "/target", 563 Libcore.os.realpath(canonicalTmpDir + "/link")); 564 } finally { 565 boolean deletedTarget = target.delete(); 566 boolean deletedLink = link.delete(); 567 // Asserting this here to provide a definitive reason for 568 // a subsequent failure on the same run. 569 assertTrue("deletedTarget = " + deletedTarget + ", deletedLink =" + deletedLink, 570 deletedTarget && deletedLink); 571 } 572 } 573 assertStartsWith(byte[] expectedContents, byte[] container)574 private static void assertStartsWith(byte[] expectedContents, byte[] container) { 575 for (int i = 0; i < expectedContents.length; i++) { 576 if (expectedContents[i] != container[i]) { 577 fail("Expected " + Arrays.toString(expectedContents) + " but found " 578 + Arrays.toString(expectedContents)); 579 } 580 } 581 } 582 } 583