libcore_io_Linux.cpp revision 50e20daf19d19acd61bb2ac0fddf4be09814defb
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#define LOG_TAG "Linux" 18 19#include <arpa/inet.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <grp.h> 23#include <ifaddrs.h> 24#include <linux/rtnetlink.h> 25#include <net/if.h> 26#include <netdb.h> 27#include <netinet/in.h> 28#include <netpacket/packet.h> 29#include <poll.h> 30#include <pwd.h> 31#include <signal.h> 32#include <stdlib.h> 33#include <sys/capability.h> 34#include <sys/ioctl.h> 35#include <sys/mman.h> 36#include <sys/prctl.h> 37#include <sys/resource.h> 38#include <sys/socket.h> 39#include <sys/stat.h> 40#include <sys/syscall.h> 41#include <sys/time.h> 42#include <sys/types.h> 43#include <sys/uio.h> 44#include <sys/un.h> 45#include <sys/utsname.h> 46#include <sys/wait.h> 47#include <sys/xattr.h> 48#include <termios.h> 49#include <unistd.h> 50 51#include <memory> 52 53#include <android-base/file.h> 54#include <android-base/logging.h> 55#include <android-base/strings.h> 56#include <log/log.h> 57#include <nativehelper/AsynchronousCloseMonitor.h> 58#include <nativehelper/JNIHelp.h> 59#include <nativehelper/JniConstants.h> 60#include <nativehelper/ScopedBytes.h> 61#include <nativehelper/ScopedLocalRef.h> 62#include <nativehelper/ScopedPrimitiveArray.h> 63#include <nativehelper/ScopedUtfChars.h> 64#include <nativehelper/toStringArray.h> 65 66#include "ExecStrings.h" 67#include "JniException.h" 68#include "NetworkUtilities.h" 69#include "Portability.h" 70 71#ifndef __unused 72#define __unused __attribute__((__unused__)) 73#endif 74 75#define TO_JAVA_STRING(NAME, EXP) \ 76 jstring NAME = env->NewStringUTF(EXP); \ 77 if ((NAME) == NULL) return NULL; 78 79namespace { 80 81jfieldID int32RefValueFid; 82jfieldID int64RefValueFid; 83 84} // namespace 85 86struct addrinfo_deleter { 87 void operator()(addrinfo* p) const { 88 if (p != NULL) { // bionic's freeaddrinfo(3) crashes when passed NULL. 89 freeaddrinfo(p); 90 } 91 } 92}; 93 94struct c_deleter { 95 void operator()(void* p) const { 96 free(p); 97 } 98}; 99 100static bool isIPv4MappedAddress(const sockaddr *sa) { 101 const sockaddr_in6 *sin6 = reinterpret_cast<const sockaddr_in6*>(sa); 102 return sa != NULL && sa->sa_family == AF_INET6 && 103 (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || 104 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)); // We map 0.0.0.0 to ::, so :: is mapped. 105} 106 107/** 108 * Perform a socket operation that specifies an IP address, possibly falling back from specifying 109 * the address as an IPv4-mapped IPv6 address in a struct sockaddr_in6 to specifying it as an IPv4 110 * address in a struct sockaddr_in. 111 * 112 * This is needed because all sockets created by the java.net APIs are IPv6 sockets, and on those 113 * sockets, IPv4 operations use IPv4-mapped addresses stored in a struct sockaddr_in6. But sockets 114 * created using Linux.socket(AF_INET, ...) are IPv4 sockets and only support operations using IPv4 115 * socket addresses structures. 116 */ 117#define NET_IPV4_FALLBACK(jni_env, return_type, syscall_name, java_fd, java_addr, port, null_addr_ok, args...) ({ \ 118 return_type _rc = -1; \ 119 do { \ 120 sockaddr_storage _ss; \ 121 socklen_t _salen; \ 122 if ((java_addr) == NULL && (null_addr_ok)) { \ 123 /* No IP address specified (e.g., sendto() on a connected socket). */ \ 124 _salen = 0; \ 125 } else if (!inetAddressToSockaddr(jni_env, java_addr, port, _ss, _salen)) { \ 126 /* Invalid socket address, return -1. inetAddressToSockaddr has already thrown. */ \ 127 break; \ 128 } \ 129 sockaddr* _sa = _salen ? reinterpret_cast<sockaddr*>(&_ss) : NULL; \ 130 /* inetAddressToSockaddr always returns an IPv6 sockaddr. Assume that java_fd was created \ 131 * by Java API calls, which always create IPv6 socket fds, and pass it in as is. */ \ 132 _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \ 133 if (_rc == -1 && errno == EAFNOSUPPORT && _salen && isIPv4MappedAddress(_sa)) { \ 134 /* We passed in an IPv4 address in an IPv6 sockaddr and the kernel told us that we got \ 135 * the address family wrong. Pass in the same address in an IPv4 sockaddr. */ \ 136 (jni_env)->ExceptionClear(); \ 137 if (!inetAddressToSockaddrVerbatim(jni_env, java_addr, port, _ss, _salen)) { \ 138 break; \ 139 } \ 140 _sa = reinterpret_cast<sockaddr*>(&_ss); \ 141 _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \ 142 } \ 143 } while (0); \ 144 _rc; }) \ 145 146/** 147 * Used to retry networking system calls that can be interrupted with a signal. Unlike 148 * TEMP_FAILURE_RETRY, this also handles the case where 149 * AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal a close() or 150 * Thread.interrupt(). Other signals that result in an EINTR result are ignored and the system call 151 * is retried. 152 * 153 * Returns the result of the system call though a Java exception will be pending if the result is 154 * -1: a SocketException if signaled via AsynchronousCloseMonitor, or ErrnoException for other 155 * failures. 156 */ 157#define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \ 158 return_type _rc = -1; \ 159 int _syscallErrno; \ 160 do { \ 161 bool _wasSignaled; \ 162 { \ 163 int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \ 164 AsynchronousCloseMonitor _monitor(_fd); \ 165 _rc = syscall_name(_fd, __VA_ARGS__); \ 166 _syscallErrno = errno; \ 167 _wasSignaled = _monitor.wasSignaled(); \ 168 } \ 169 if (_wasSignaled) { \ 170 jniThrowException(jni_env, "java/net/SocketException", "Socket closed"); \ 171 _rc = -1; \ 172 break; \ 173 } \ 174 if (_rc == -1 && _syscallErrno != EINTR) { \ 175 /* TODO: with a format string we could show the arguments too, like strace(1). */ \ 176 throwErrnoException(jni_env, # syscall_name); \ 177 break; \ 178 } \ 179 } while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \ 180 if (_rc == -1) { \ 181 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \ 182 errno = _syscallErrno; \ 183 } \ 184 _rc; }) 185 186/** 187 * Used to retry system calls that can be interrupted with a signal. Unlike TEMP_FAILURE_RETRY, this 188 * also handles the case where AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal 189 * a close() or Thread.interrupt(). Other signals that result in an EINTR result are ignored and the 190 * system call is retried. 191 * 192 * Returns the result of the system call though a Java exception will be pending if the result is 193 * -1: an IOException if the file descriptor is already closed, a InterruptedIOException if signaled 194 * via AsynchronousCloseMonitor, or ErrnoException for other failures. 195 */ 196#define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \ 197 return_type _rc = -1; \ 198 int _syscallErrno; \ 199 do { \ 200 bool _wasSignaled; \ 201 { \ 202 int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \ 203 AsynchronousCloseMonitor _monitor(_fd); \ 204 _rc = syscall_name(_fd, __VA_ARGS__); \ 205 _syscallErrno = errno; \ 206 _wasSignaled = _monitor.wasSignaled(); \ 207 } \ 208 if (_wasSignaled) { \ 209 jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \ 210 _rc = -1; \ 211 break; \ 212 } \ 213 if (_rc == -1 && _syscallErrno != EINTR) { \ 214 /* TODO: with a format string we could show the arguments too, like strace(1). */ \ 215 throwErrnoException(jni_env, # syscall_name); \ 216 break; \ 217 } \ 218 } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \ 219 if (_rc == -1) { \ 220 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \ 221 errno = _syscallErrno; \ 222 } \ 223 _rc; }) 224 225#define NULL_ADDR_OK true 226#define NULL_ADDR_FORBIDDEN false 227 228static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2, 229 const char* functionName, int error) { 230 jthrowable cause = NULL; 231 if (env->ExceptionCheck()) { 232 cause = env->ExceptionOccurred(); 233 env->ExceptionClear(); 234 } 235 236 ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName)); 237 if (detailMessage.get() == NULL) { 238 // Not really much we can do here. We're probably dead in the water, 239 // but let's try to stumble on... 240 env->ExceptionClear(); 241 } 242 243 jobject exception; 244 if (cause != NULL) { 245 exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause); 246 } else { 247 exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error); 248 } 249 env->Throw(reinterpret_cast<jthrowable>(exception)); 250} 251 252static void throwErrnoException(JNIEnv* env, const char* functionName) { 253 int error = errno; 254 static jmethodID ctor3 = env->GetMethodID(JniConstants::errnoExceptionClass, 255 "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V"); 256 static jmethodID ctor2 = env->GetMethodID(JniConstants::errnoExceptionClass, 257 "<init>", "(Ljava/lang/String;I)V"); 258 throwException(env, JniConstants::errnoExceptionClass, ctor3, ctor2, functionName, error); 259} 260 261static void throwGaiException(JNIEnv* env, const char* functionName, int error) { 262 // Cache the methods ids before we throw, so we don't call GetMethodID with a pending exception. 263 static jmethodID ctor3 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>", 264 "(Ljava/lang/String;ILjava/lang/Throwable;)V"); 265 static jmethodID ctor2 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>", 266 "(Ljava/lang/String;I)V"); 267 if (errno != 0) { 268 // EAI_SYSTEM should mean "look at errno instead", but both glibc and bionic seem to 269 // mess this up. In particular, if you don't have INTERNET permission, errno will be EACCES 270 // but you'll get EAI_NONAME or EAI_NODATA. So we want our GaiException to have a 271 // potentially-relevant ErrnoException as its cause even if error != EAI_SYSTEM. 272 // http://code.google.com/p/android/issues/detail?id=15722 273 throwErrnoException(env, functionName); 274 // Deliberately fall through to throw another exception... 275 } 276 throwException(env, JniConstants::gaiExceptionClass, ctor3, ctor2, functionName, error); 277} 278 279template <typename rc_t> 280static rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) { 281 if (rc == rc_t(-1)) { 282 throwErrnoException(env, name); 283 } 284 return rc; 285} 286 287template <typename ScopedT> 288class IoVec { 289public: 290 IoVec(JNIEnv* env, size_t bufferCount) : mEnv(env), mBufferCount(bufferCount) { 291 } 292 293 bool init(jobjectArray javaBuffers, jintArray javaOffsets, jintArray javaByteCounts) { 294 // We can't delete our local references until after the I/O, so make sure we have room. 295 if (mEnv->PushLocalFrame(mBufferCount + 16) < 0) { 296 return false; 297 } 298 ScopedIntArrayRO offsets(mEnv, javaOffsets); 299 if (offsets.get() == NULL) { 300 return false; 301 } 302 ScopedIntArrayRO byteCounts(mEnv, javaByteCounts); 303 if (byteCounts.get() == NULL) { 304 return false; 305 } 306 // TODO: Linux actually has a 1024 buffer limit. glibc works around this, and we should too. 307 // TODO: you can query the limit at runtime with sysconf(_SC_IOV_MAX). 308 for (size_t i = 0; i < mBufferCount; ++i) { 309 jobject buffer = mEnv->GetObjectArrayElement(javaBuffers, i); // We keep this local ref. 310 mScopedBuffers.push_back(new ScopedT(mEnv, buffer)); 311 jbyte* ptr = const_cast<jbyte*>(mScopedBuffers.back()->get()); 312 if (ptr == NULL) { 313 return false; 314 } 315 struct iovec iov; 316 iov.iov_base = reinterpret_cast<void*>(ptr + offsets[i]); 317 iov.iov_len = byteCounts[i]; 318 mIoVec.push_back(iov); 319 } 320 return true; 321 } 322 323 ~IoVec() { 324 for (size_t i = 0; i < mScopedBuffers.size(); ++i) { 325 delete mScopedBuffers[i]; 326 } 327 mEnv->PopLocalFrame(NULL); 328 } 329 330 iovec* get() { 331 return &mIoVec[0]; 332 } 333 334 size_t size() { 335 return mBufferCount; 336 } 337 338private: 339 JNIEnv* mEnv; 340 size_t mBufferCount; 341 std::vector<iovec> mIoVec; 342 std::vector<ScopedT*> mScopedBuffers; 343}; 344 345/** 346 * Returns a jbyteArray containing the sockaddr_un.sun_path from ss. As per unix(7) sa_len should be 347 * the length of ss as returned by getsockname(2), getpeername(2), or accept(2). 348 * If the returned array is of length 0 the sockaddr_un refers to an unnamed socket. 349 * A null pointer is returned in the event of an error. See unix(7) for more information. 350 */ 351static jbyteArray getUnixSocketPath(JNIEnv* env, const sockaddr_storage& ss, 352 const socklen_t& sa_len) { 353 if (ss.ss_family != AF_UNIX) { 354 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 355 "getUnixSocketPath unsupported ss_family: %i", ss.ss_family); 356 return NULL; 357 } 358 359 const struct sockaddr_un* un_addr = reinterpret_cast<const struct sockaddr_un*>(&ss); 360 // The length of sun_path is sa_len minus the length of the overhead (ss_family). 361 // See unix(7) for details. This calculation must match that of socket_make_sockaddr_un() in 362 // socket_local_client.c and javaUnixSocketAddressToSockaddr() to interoperate. 363 size_t pathLength = sa_len - offsetof(struct sockaddr_un, sun_path); 364 365 jbyteArray javaSunPath = env->NewByteArray(pathLength); 366 if (javaSunPath == NULL) { 367 return NULL; 368 } 369 370 if (pathLength > 0) { 371 env->SetByteArrayRegion(javaSunPath, 0, pathLength, 372 reinterpret_cast<const jbyte*>(&un_addr->sun_path)); 373 } 374 return javaSunPath; 375} 376 377static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const socklen_t sa_len) { 378 if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) { 379 jint port; 380 jobject inetAddress = sockaddrToInetAddress(env, ss, &port); 381 if (inetAddress == NULL) { 382 return NULL; // Exception already thrown. 383 } 384 static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass, 385 "<init>", "(Ljava/net/InetAddress;I)V"); 386 if (ctor == NULL) { 387 return NULL; 388 } 389 return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port); 390 } else if (ss.ss_family == AF_UNIX) { 391 static jmethodID ctor = env->GetMethodID(JniConstants::unixSocketAddressClass, 392 "<init>", "([B)V"); 393 if (ctor == NULL) { 394 return NULL; 395 } 396 jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len); 397 if (!javaSunPath) { 398 return NULL; 399 } 400 return env->NewObject(JniConstants::unixSocketAddressClass, ctor, javaSunPath); 401 } else if (ss.ss_family == AF_NETLINK) { 402 const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss); 403 static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass, 404 "<init>", "(II)V"); 405 if (ctor == NULL) { 406 return NULL; 407 } 408 return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor, 409 static_cast<jint>(nl_addr->nl_pid), 410 static_cast<jint>(nl_addr->nl_groups)); 411 } else if (ss.ss_family == AF_PACKET) { 412 const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss); 413 static jmethodID ctor = env->GetMethodID(JniConstants::packetSocketAddressClass, 414 "<init>", "(SISB[B)V"); 415 if (ctor == NULL) { 416 return NULL; 417 } 418 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(sll->sll_halen)); 419 if (byteArray.get() == NULL) { 420 return NULL; 421 } 422 env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen, 423 reinterpret_cast<const jbyte*>(sll->sll_addr)); 424 jobject packetSocketAddress = env->NewObject(JniConstants::packetSocketAddressClass, ctor, 425 static_cast<jshort>(ntohs(sll->sll_protocol)), 426 static_cast<jint>(sll->sll_ifindex), 427 static_cast<jshort>(sll->sll_hatype), 428 static_cast<jbyte>(sll->sll_pkttype), 429 byteArray.get()); 430 return packetSocketAddress; 431 } 432 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "unsupported ss_family: %d", 433 ss.ss_family); 434 return NULL; 435} 436 437static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) { 438 TO_JAVA_STRING(pw_name, pw.pw_name); 439 TO_JAVA_STRING(pw_dir, pw.pw_dir); 440 TO_JAVA_STRING(pw_shell, pw.pw_shell); 441 static jmethodID ctor = env->GetMethodID(JniConstants::structPasswdClass, "<init>", 442 "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V"); 443 if (ctor == NULL) { 444 return NULL; 445 } 446 return env->NewObject(JniConstants::structPasswdClass, ctor, 447 pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell); 448} 449 450static jobject makeStructTimespec(JNIEnv* env, const struct timespec& ts) { 451 static jmethodID ctor = env->GetMethodID(JniConstants::structTimespecClass, "<init>", 452 "(JJ)V"); 453 if (ctor == NULL) { 454 return NULL; 455 } 456 return env->NewObject(JniConstants::structTimespecClass, ctor, 457 static_cast<jlong>(ts.tv_sec), static_cast<jlong>(ts.tv_nsec)); 458} 459 460static jobject makeStructStat(JNIEnv* env, const struct stat64& sb) { 461 static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>", 462 "(JJIJIIJJLandroid/system/StructTimespec;Landroid/system/StructTimespec;Landroid/system/StructTimespec;JJ)V"); 463 if (ctor == NULL) { 464 return NULL; 465 } 466 467 jobject atim_timespec = makeStructTimespec(env, sb.st_atim); 468 if (atim_timespec == NULL) { 469 return NULL; 470 } 471 jobject mtim_timespec = makeStructTimespec(env, sb.st_mtim); 472 if (mtim_timespec == NULL) { 473 return NULL; 474 } 475 jobject ctim_timespec = makeStructTimespec(env, sb.st_ctim); 476 if (ctim_timespec == NULL) { 477 return NULL; 478 } 479 480 return env->NewObject(JniConstants::structStatClass, ctor, 481 static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino), 482 static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink), 483 static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid), 484 static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size), 485 atim_timespec, mtim_timespec, ctim_timespec, 486 static_cast<jlong>(sb.st_blksize), static_cast<jlong>(sb.st_blocks)); 487} 488 489static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) { 490 static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>", 491 "(JJJJJJJJJJJ)V"); 492 if (ctor == NULL) { 493 return NULL; 494 } 495 496 return env->NewObject(JniConstants::structStatVfsClass, ctor, 497 static_cast<jlong>(sb.f_bsize), 498 static_cast<jlong>(sb.f_frsize), 499 static_cast<jlong>(sb.f_blocks), 500 static_cast<jlong>(sb.f_bfree), 501 static_cast<jlong>(sb.f_bavail), 502 static_cast<jlong>(sb.f_files), 503 static_cast<jlong>(sb.f_ffree), 504 static_cast<jlong>(sb.f_favail), 505 static_cast<jlong>(sb.f_fsid), 506 static_cast<jlong>(sb.f_flag), 507 static_cast<jlong>(sb.f_namemax)); 508} 509 510static jobject makeStructLinger(JNIEnv* env, const struct linger& l) { 511 static jmethodID ctor = env->GetMethodID(JniConstants::structLingerClass, "<init>", "(II)V"); 512 if (ctor == NULL) { 513 return NULL; 514 } 515 return env->NewObject(JniConstants::structLingerClass, ctor, l.l_onoff, l.l_linger); 516} 517 518static jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) { 519 static jmethodID ctor = env->GetMethodID(JniConstants::structTimevalClass, "<init>", "(JJ)V"); 520 if (ctor == NULL) { 521 return NULL; 522 } 523 return env->NewObject(JniConstants::structTimevalClass, ctor, 524 static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec)); 525} 526 527static jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) { 528 static jmethodID ctor = env->GetMethodID(JniConstants::structUcredClass, "<init>", "(III)V"); 529 if (ctor == NULL) { 530 return NULL; 531 } 532 return env->NewObject(JniConstants::structUcredClass, ctor, u.pid, u.uid, u.gid); 533} 534 535static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) { 536 TO_JAVA_STRING(sysname, buf.sysname); 537 TO_JAVA_STRING(nodename, buf.nodename); 538 TO_JAVA_STRING(release, buf.release); 539 TO_JAVA_STRING(version, buf.version); 540 TO_JAVA_STRING(machine, buf.machine); 541 static jmethodID ctor = env->GetMethodID(JniConstants::structUtsnameClass, "<init>", 542 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); 543 if (ctor == NULL) { 544 return NULL; 545 } 546 return env->NewObject(JniConstants::structUtsnameClass, ctor, 547 sysname, nodename, release, version, machine); 548}; 549 550static bool fillIfreq(JNIEnv* env, jstring javaInterfaceName, struct ifreq& req) { 551 ScopedUtfChars interfaceName(env, javaInterfaceName); 552 if (interfaceName.c_str() == NULL) { 553 return false; 554 } 555 memset(&req, 0, sizeof(req)); 556 strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name)); 557 req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; 558 return true; 559} 560 561static bool fillUnixSocketAddress(JNIEnv* env, jobject javaUnixSocketAddress, 562 const sockaddr_storage& ss, const socklen_t& sa_len) { 563 if (javaUnixSocketAddress == NULL) { 564 return true; 565 } 566 jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len); 567 if (!javaSunPath) { 568 return false; 569 } 570 571 static jfieldID sunPathFid = 572 env->GetFieldID(JniConstants::unixSocketAddressClass, "sun_path", "[B"); 573 env->SetObjectField(javaUnixSocketAddress, sunPathFid, javaSunPath); 574 return true; 575} 576 577static bool fillInetSocketAddress(JNIEnv* env, jobject javaInetSocketAddress, 578 const sockaddr_storage& ss) { 579 if (javaInetSocketAddress == NULL) { 580 return true; 581 } 582 // Fill out the passed-in InetSocketAddress with the sender's IP address and port number. 583 jint port; 584 jobject sender = sockaddrToInetAddress(env, ss, &port); 585 if (sender == NULL) { 586 return false; 587 } 588 static jfieldID holderFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "holder", 589 "Ljava/net/InetSocketAddress$InetSocketAddressHolder;"); 590 jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid); 591 592 static jfieldID addressFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass, 593 "addr", "Ljava/net/InetAddress;"); 594 static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass, "port", "I"); 595 env->SetObjectField(holder, addressFid, sender); 596 env->SetIntField(holder, portFid, port); 597 return true; 598} 599 600static bool fillSocketAddress(JNIEnv* env, jobject javaSocketAddress, const sockaddr_storage& ss, 601 const socklen_t& sa_len) { 602 if (javaSocketAddress == NULL) { 603 return true; 604 } 605 606 if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) { 607 return fillInetSocketAddress(env, javaSocketAddress, ss); 608 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) { 609 return fillUnixSocketAddress(env, javaSocketAddress, ss, sa_len); 610 } 611 jniThrowException(env, "java/lang/UnsupportedOperationException", 612 "unsupported SocketAddress subclass"); 613 return false; 614 615} 616 617static void javaInetSocketAddressToInetAddressAndPort( 618 JNIEnv* env, jobject javaInetSocketAddress, jobject& javaInetAddress, jint& port) { 619 static jfieldID holderFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "holder", 620 "Ljava/net/InetSocketAddress$InetSocketAddressHolder;"); 621 jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid); 622 623 static jfieldID addressFid = env->GetFieldID( 624 JniConstants::inetSocketAddressHolderClass, "addr", "Ljava/net/InetAddress;"); 625 static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass, "port", "I"); 626 627 javaInetAddress = env->GetObjectField(holder, addressFid); 628 port = env->GetIntField(holder, portFid); 629} 630 631static bool javaInetSocketAddressToSockaddr( 632 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { 633 jobject javaInetAddress; 634 jint port; 635 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port); 636 return inetAddressToSockaddr(env, javaInetAddress, port, ss, sa_len); 637} 638 639static bool javaNetlinkSocketAddressToSockaddr( 640 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { 641 static jfieldID nlPidFid = env->GetFieldID( 642 JniConstants::netlinkSocketAddressClass, "nlPortId", "I"); 643 static jfieldID nlGroupsFid = env->GetFieldID( 644 JniConstants::netlinkSocketAddressClass, "nlGroupsMask", "I"); 645 646 sockaddr_nl *nlAddr = reinterpret_cast<sockaddr_nl *>(&ss); 647 nlAddr->nl_family = AF_NETLINK; 648 nlAddr->nl_pid = env->GetIntField(javaSocketAddress, nlPidFid); 649 nlAddr->nl_groups = env->GetIntField(javaSocketAddress, nlGroupsFid); 650 sa_len = sizeof(sockaddr_nl); 651 return true; 652} 653 654static bool javaUnixSocketAddressToSockaddr( 655 JNIEnv* env, jobject javaUnixSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { 656 static jfieldID sunPathFid = env->GetFieldID( 657 JniConstants::unixSocketAddressClass, "sun_path", "[B"); 658 659 struct sockaddr_un* un_addr = reinterpret_cast<struct sockaddr_un*>(&ss); 660 memset (un_addr, 0, sizeof(sockaddr_un)); 661 un_addr->sun_family = AF_UNIX; 662 663 jbyteArray javaSunPath = (jbyteArray) env->GetObjectField(javaUnixSocketAddress, sunPathFid); 664 jsize pathLength = env->GetArrayLength(javaSunPath); 665 if ((size_t) pathLength > sizeof(sockaddr_un::sun_path)) { 666 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", 667 "sun_path too long: max=%i, is=%i", 668 sizeof(sockaddr_un::sun_path), pathLength); 669 return false; 670 } 671 env->GetByteArrayRegion(javaSunPath, 0, pathLength, (jbyte*) un_addr->sun_path); 672 // sa_len is sun_path plus the length of the overhead (ss_family_t). See unix(7) for 673 // details. This calculation must match that of socket_make_sockaddr_un() in 674 // socket_local_client.c and getUnixSocketPath() to interoperate. 675 sa_len = offsetof(struct sockaddr_un, sun_path) + pathLength; 676 return true; 677} 678 679static bool javaPacketSocketAddressToSockaddr( 680 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { 681 static jfieldID protocolFid = env->GetFieldID( 682 JniConstants::packetSocketAddressClass, "sll_protocol", "S"); 683 static jfieldID ifindexFid = env->GetFieldID( 684 JniConstants::packetSocketAddressClass, "sll_ifindex", "I"); 685 static jfieldID hatypeFid = env->GetFieldID( 686 JniConstants::packetSocketAddressClass, "sll_hatype", "S"); 687 static jfieldID pkttypeFid = env->GetFieldID( 688 JniConstants::packetSocketAddressClass, "sll_pkttype", "B"); 689 static jfieldID addrFid = env->GetFieldID( 690 JniConstants::packetSocketAddressClass, "sll_addr", "[B"); 691 692 sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss); 693 sll->sll_family = AF_PACKET; 694 sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid)); 695 sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid); 696 sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid); 697 sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid); 698 699 jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid); 700 if (sllAddr == NULL) { 701 sll->sll_halen = 0; 702 memset(&sll->sll_addr, 0, sizeof(sll->sll_addr)); 703 } else { 704 jsize len = env->GetArrayLength(sllAddr); 705 if ((size_t) len > sizeof(sll->sll_addr)) { 706 len = sizeof(sll->sll_addr); 707 } 708 sll->sll_halen = len; 709 env->GetByteArrayRegion(sllAddr, 0, len, (jbyte*) sll->sll_addr); 710 } 711 sa_len = sizeof(sockaddr_ll); 712 return true; 713} 714 715static bool javaSocketAddressToSockaddr( 716 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { 717 if (javaSocketAddress == NULL) { 718 jniThrowNullPointerException(env, NULL); 719 return false; 720 } 721 722 if (env->IsInstanceOf(javaSocketAddress, JniConstants::netlinkSocketAddressClass)) { 723 return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); 724 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) { 725 return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); 726 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::packetSocketAddressClass)) { 727 return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); 728 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) { 729 return javaUnixSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); 730 } 731 jniThrowException(env, "java/lang/UnsupportedOperationException", 732 "unsupported SocketAddress subclass"); 733 return false; 734} 735 736static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) { 737 ScopedUtfChars path(env, javaPath); 738 if (path.c_str() == NULL) { 739 return NULL; 740 } 741 struct stat64 sb; 742 int rc = isLstat ? TEMP_FAILURE_RETRY(lstat64(path.c_str(), &sb)) 743 : TEMP_FAILURE_RETRY(stat64(path.c_str(), &sb)); 744 if (rc == -1) { 745 throwErrnoException(env, isLstat ? "lstat" : "stat"); 746 return NULL; 747 } 748 return makeStructStat(env, sb); 749} 750 751static jobject doGetSockName(JNIEnv* env, jobject javaFd, bool is_sockname) { 752 int fd = jniGetFDFromFileDescriptor(env, javaFd); 753 sockaddr_storage ss; 754 sockaddr* sa = reinterpret_cast<sockaddr*>(&ss); 755 socklen_t byteCount = sizeof(ss); 756 memset(&ss, 0, byteCount); 757 int rc = is_sockname ? TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount)) 758 : TEMP_FAILURE_RETRY(getpeername(fd, sa, &byteCount)); 759 if (rc == -1) { 760 throwErrnoException(env, is_sockname ? "getsockname" : "getpeername"); 761 return NULL; 762 } 763 return makeSocketAddress(env, ss, byteCount); 764} 765 766class Passwd { 767public: 768 explicit Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) { 769 mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); 770 mBuffer.reset(new char[mBufferSize]); 771 } 772 773 jobject getpwnam(const char* name) { 774 return process("getpwnam_r", getpwnam_r(name, &mPwd, mBuffer.get(), mBufferSize, &mResult)); 775 } 776 777 jobject getpwuid(uid_t uid) { 778 return process("getpwuid_r", getpwuid_r(uid, &mPwd, mBuffer.get(), mBufferSize, &mResult)); 779 } 780 781 struct passwd* get() { 782 return mResult; 783 } 784 785private: 786 jobject process(const char* syscall, int error) { 787 if (mResult == NULL) { 788 errno = error; 789 throwErrnoException(mEnv, syscall); 790 return NULL; 791 } 792 return makeStructPasswd(mEnv, *mResult); 793 } 794 795 JNIEnv* mEnv; 796 std::unique_ptr<char[]> mBuffer; 797 size_t mBufferSize; 798 struct passwd mPwd; 799 struct passwd* mResult; 800}; 801 802static void AssertException(JNIEnv* env) { 803 if (env->ExceptionCheck() == JNI_FALSE) { 804 env->FatalError("Expected exception"); 805 } 806} 807 808// Note for capabilities functions: 809// We assume the calls are rare enough that it does not make sense to cache class objects. The 810// advantage is lower maintenance burden. 811 812static bool ReadStructCapUserHeader( 813 JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) { 814 if (java_header == nullptr) { 815 jniThrowNullPointerException(env, "header is null"); 816 return false; 817 } 818 819 ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader")); 820 if (header_class.get() == nullptr) { 821 return false; 822 } 823 824 { 825 static jfieldID version_fid = env->GetFieldID(header_class.get(), "version", "I"); 826 if (version_fid == nullptr) { 827 return false; 828 } 829 c_header->version = env->GetIntField(java_header, version_fid); 830 } 831 832 { 833 static jfieldID pid_fid = env->GetFieldID(header_class.get(), "pid", "I"); 834 if (pid_fid == nullptr) { 835 return false; 836 } 837 c_header->pid = env->GetIntField(java_header, pid_fid); 838 } 839 840 return true; 841} 842 843static void SetStructCapUserHeaderVersion( 844 JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) { 845 ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader")); 846 if (header_class.get() == nullptr) { 847 env->ExceptionClear(); 848 return; 849 } 850 851 static jfieldID version_fid = env->GetFieldID(header_class.get(), "version", "I"); 852 if (version_fid == nullptr) { 853 env->ExceptionClear(); 854 return; 855 } 856 env->SetIntField(java_header, version_fid, c_header->version); 857} 858 859static jobject CreateStructCapUserData( 860 JNIEnv* env, jclass data_class, __user_cap_data_struct* c_data) { 861 if (c_data == nullptr) { 862 // Should not happen. 863 jniThrowNullPointerException(env, "data is null"); 864 return nullptr; 865 } 866 867 static jmethodID data_cons = env->GetMethodID(data_class, "<init>", "(III)V"); 868 if (data_cons == nullptr) { 869 return nullptr; 870 } 871 872 jint e = static_cast<jint>(c_data->effective); 873 jint p = static_cast<jint>(c_data->permitted); 874 jint i = static_cast<jint>(c_data->inheritable); 875 return env->NewObject(data_class, data_cons, e, p, i); 876} 877 878static bool ReadStructCapUserData(JNIEnv* env, jobject java_data, __user_cap_data_struct* c_data) { 879 if (java_data == nullptr) { 880 jniThrowNullPointerException(env, "data is null"); 881 return false; 882 } 883 884 ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData")); 885 if (data_class.get() == nullptr) { 886 return false; 887 } 888 889 { 890 static jfieldID effective_fid = env->GetFieldID(data_class.get(), "effective", "I"); 891 if (effective_fid == nullptr) { 892 return false; 893 } 894 c_data->effective = env->GetIntField(java_data, effective_fid); 895 } 896 897 { 898 static jfieldID permitted_fid = env->GetFieldID(data_class.get(), "permitted", "I"); 899 if (permitted_fid == nullptr) { 900 return false; 901 } 902 c_data->permitted = env->GetIntField(java_data, permitted_fid); 903 } 904 905 906 { 907 static jfieldID inheritable_fid = env->GetFieldID(data_class.get(), "inheritable", "I"); 908 if (inheritable_fid == nullptr) { 909 return false; 910 } 911 c_data->inheritable = env->GetIntField(java_data, inheritable_fid); 912 } 913 914 return true; 915} 916 917static constexpr size_t kMaxCapUserDataLength = 2U; 918#ifdef _LINUX_CAPABILITY_VERSION_1 919static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_1, "Length too small."); 920#endif 921#ifdef _LINUX_CAPABILITY_VERSION_2 922static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_2, "Length too small."); 923#endif 924#ifdef _LINUX_CAPABILITY_VERSION_3 925static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_3, "Length too small."); 926#endif 927#ifdef _LINUX_CAPABILITY_VERSION_4 928static_assert(false, "Unsupported capability version, please update."); 929#endif 930 931static size_t GetCapUserDataLength(uint32_t version) { 932#ifdef _LINUX_CAPABILITY_VERSION_1 933 if (version == _LINUX_CAPABILITY_VERSION_1) { 934 return _LINUX_CAPABILITY_U32S_1; 935 } 936#endif 937#ifdef _LINUX_CAPABILITY_VERSION_2 938 if (version == _LINUX_CAPABILITY_VERSION_2) { 939 return _LINUX_CAPABILITY_U32S_2; 940 } 941#endif 942#ifdef _LINUX_CAPABILITY_VERSION_3 943 if (version == _LINUX_CAPABILITY_VERSION_3) { 944 return _LINUX_CAPABILITY_U32S_3; 945 } 946#endif 947 return 0; 948} 949 950static jobject Linux_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) { 951 sockaddr_storage ss; 952 socklen_t sl = sizeof(ss); 953 memset(&ss, 0, sizeof(ss)); 954 sockaddr* peer = (javaSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL; 955 socklen_t* peerLength = (javaSocketAddress != NULL) ? &sl : 0; 956 jint clientFd = NET_FAILURE_RETRY(env, int, accept, javaFd, peer, peerLength); 957 if (clientFd == -1 || !fillSocketAddress(env, javaSocketAddress, ss, *peerLength)) { 958 close(clientFd); 959 return NULL; 960 } 961 return (clientFd != -1) ? jniCreateFileDescriptor(env, clientFd) : NULL; 962} 963 964static jboolean Linux_access(JNIEnv* env, jobject, jstring javaPath, jint mode) { 965 ScopedUtfChars path(env, javaPath); 966 if (path.c_str() == NULL) { 967 return JNI_FALSE; 968 } 969 int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode)); 970 if (rc == -1) { 971 throwErrnoException(env, "access"); 972 } 973 return (rc == 0); 974} 975 976static void Linux_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) { 977 // We don't need the return value because we'll already have thrown. 978 (void) NET_IPV4_FALLBACK(env, int, bind, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN); 979} 980 981static void Linux_bindSocketAddress( 982 JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) { 983 sockaddr_storage ss; 984 socklen_t sa_len; 985 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) { 986 return; // Exception already thrown. 987 } 988 989 const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss); 990 // We don't need the return value because we'll already have thrown. 991 (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len); 992} 993 994static jobjectArray Linux_capget(JNIEnv* env, jobject, jobject header) { 995 // Convert Java header struct to kernel datastructure. 996 __user_cap_header_struct cap_header; 997 if (!ReadStructCapUserHeader(env, header, &cap_header)) { 998 AssertException(env); 999 return nullptr; 1000 } 1001 1002 // Call capget. 1003 __user_cap_data_struct cap_data[kMaxCapUserDataLength]; 1004 if (capget(&cap_header, &cap_data[0]) == -1) { 1005 // Check for EINVAL. In that case, mutate the header. 1006 if (errno == EINVAL) { 1007 int saved_errno = errno; 1008 SetStructCapUserHeaderVersion(env, header, &cap_header); 1009 errno = saved_errno; 1010 } 1011 throwErrnoException(env, "capget"); 1012 return nullptr; 1013 } 1014 1015 // Create the result array. 1016 ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData")); 1017 if (data_class.get() == nullptr) { 1018 return nullptr; 1019 } 1020 size_t result_size = GetCapUserDataLength(cap_header.version); 1021 ScopedLocalRef<jobjectArray> result( 1022 env, env->NewObjectArray(result_size, data_class.get(), nullptr)); 1023 if (result.get() == nullptr) { 1024 return nullptr; 1025 } 1026 // Translate the values we got. 1027 for (size_t i = 0; i < result_size; ++i) { 1028 ScopedLocalRef<jobject> value( 1029 env, CreateStructCapUserData(env, data_class.get(), &cap_data[i])); 1030 if (value.get() == nullptr) { 1031 AssertException(env); 1032 return nullptr; 1033 } 1034 env->SetObjectArrayElement(result.get(), i, value.get()); 1035 } 1036 return result.release(); 1037} 1038 1039static void Linux_capset( 1040 JNIEnv* env, jobject, jobject header, jobjectArray data) { 1041 // Convert Java header struct to kernel datastructure. 1042 __user_cap_header_struct cap_header; 1043 if (!ReadStructCapUserHeader(env, header, &cap_header)) { 1044 AssertException(env); 1045 return; 1046 } 1047 size_t result_size = GetCapUserDataLength(cap_header.version); 1048 // Ensure that the array has the expected length. 1049 if (env->GetArrayLength(data) != static_cast<jint>(result_size)) { 1050 jniThrowExceptionFmt(env, 1051 "java/lang/IllegalArgumentException", 1052 "Unsupported input length %d (expected %zu)", 1053 env->GetArrayLength(data), 1054 result_size); 1055 return; 1056 } 1057 1058 __user_cap_data_struct cap_data[kMaxCapUserDataLength]; 1059 // Translate the values we got. 1060 for (size_t i = 0; i < result_size; ++i) { 1061 ScopedLocalRef<jobject> value(env, env->GetObjectArrayElement(data, i)); 1062 if (!ReadStructCapUserData(env, value.get(), &cap_data[i])) { 1063 AssertException(env); 1064 return; 1065 } 1066 } 1067 1068 throwIfMinusOne(env, "capset", capset(&cap_header, &cap_data[0])); 1069} 1070 1071static void Linux_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) { 1072 ScopedUtfChars path(env, javaPath); 1073 if (path.c_str() == NULL) { 1074 return; 1075 } 1076 throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode))); 1077} 1078 1079static void Linux_chown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) { 1080 ScopedUtfChars path(env, javaPath); 1081 if (path.c_str() == NULL) { 1082 return; 1083 } 1084 throwIfMinusOne(env, "chown", TEMP_FAILURE_RETRY(chown(path.c_str(), uid, gid))); 1085} 1086 1087static void Linux_close(JNIEnv* env, jobject, jobject javaFd) { 1088 // Get the FileDescriptor's 'fd' field and clear it. 1089 // We need to do this before we can throw an IOException (http://b/3222087). 1090 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1091 jniSetFileDescriptorOfFD(env, javaFd, -1); 1092 1093 // Even if close(2) fails with EINTR, the fd will have been closed. 1094 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd. 1095 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html 1096 throwIfMinusOne(env, "close", close(fd)); 1097} 1098 1099static void Linux_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) { 1100 (void) NET_IPV4_FALLBACK(env, int, connect, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN); 1101} 1102 1103static void Linux_connectSocketAddress( 1104 JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) { 1105 sockaddr_storage ss; 1106 socklen_t sa_len; 1107 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) { 1108 return; // Exception already thrown. 1109 } 1110 1111 const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss); 1112 // We don't need the return value because we'll already have thrown. 1113 (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len); 1114} 1115 1116static jobject Linux_dup(JNIEnv* env, jobject, jobject javaOldFd) { 1117 int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd); 1118 int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd))); 1119 return (newFd != -1) ? jniCreateFileDescriptor(env, newFd) : NULL; 1120} 1121 1122static jobject Linux_dup2(JNIEnv* env, jobject, jobject javaOldFd, jint newFd) { 1123 int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd); 1124 int fd = throwIfMinusOne(env, "dup2", TEMP_FAILURE_RETRY(dup2(oldFd, newFd))); 1125 return (fd != -1) ? jniCreateFileDescriptor(env, fd) : NULL; 1126} 1127 1128static jobjectArray Linux_environ(JNIEnv* env, jobject) { 1129 extern char** environ; // Standard, but not in any header file. 1130 return toStringArray(env, environ); 1131} 1132 1133static void Linux_execve(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv, jobjectArray javaEnvp) { 1134 ScopedUtfChars path(env, javaFilename); 1135 if (path.c_str() == NULL) { 1136 return; 1137 } 1138 1139 ExecStrings argv(env, javaArgv); 1140 ExecStrings envp(env, javaEnvp); 1141 TEMP_FAILURE_RETRY(execve(path.c_str(), argv.get(), envp.get())); 1142 1143 throwErrnoException(env, "execve"); 1144} 1145 1146static void Linux_execv(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv) { 1147 ScopedUtfChars path(env, javaFilename); 1148 if (path.c_str() == NULL) { 1149 return; 1150 } 1151 1152 ExecStrings argv(env, javaArgv); 1153 TEMP_FAILURE_RETRY(execv(path.c_str(), argv.get())); 1154 1155 throwErrnoException(env, "execv"); 1156} 1157 1158static void Linux_fchmod(JNIEnv* env, jobject, jobject javaFd, jint mode) { 1159 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1160 throwIfMinusOne(env, "fchmod", TEMP_FAILURE_RETRY(fchmod(fd, mode))); 1161} 1162 1163static void Linux_fchown(JNIEnv* env, jobject, jobject javaFd, jint uid, jint gid) { 1164 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1165 throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid))); 1166} 1167 1168static jint Linux_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) { 1169 static jfieldID typeFid = env->GetFieldID(JniConstants::structFlockClass, "l_type", "S"); 1170 static jfieldID whenceFid = env->GetFieldID(JniConstants::structFlockClass, "l_whence", "S"); 1171 static jfieldID startFid = env->GetFieldID(JniConstants::structFlockClass, "l_start", "J"); 1172 static jfieldID lenFid = env->GetFieldID(JniConstants::structFlockClass, "l_len", "J"); 1173 static jfieldID pidFid = env->GetFieldID(JniConstants::structFlockClass, "l_pid", "I"); 1174 1175 struct flock64 lock; 1176 memset(&lock, 0, sizeof(lock)); 1177 lock.l_type = env->GetShortField(javaFlock, typeFid); 1178 lock.l_whence = env->GetShortField(javaFlock, whenceFid); 1179 lock.l_start = env->GetLongField(javaFlock, startFid); 1180 lock.l_len = env->GetLongField(javaFlock, lenFid); 1181 lock.l_pid = env->GetIntField(javaFlock, pidFid); 1182 1183 int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock); 1184 if (rc != -1) { 1185 env->SetShortField(javaFlock, typeFid, lock.l_type); 1186 env->SetShortField(javaFlock, whenceFid, lock.l_whence); 1187 env->SetLongField(javaFlock, startFid, lock.l_start); 1188 env->SetLongField(javaFlock, lenFid, lock.l_len); 1189 env->SetIntField(javaFlock, pidFid, lock.l_pid); 1190 } 1191 return rc; 1192} 1193 1194static jint Linux_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) { 1195 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1196 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg))); 1197} 1198 1199static jint Linux_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) { 1200 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1201 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd))); 1202} 1203 1204static void Linux_fdatasync(JNIEnv* env, jobject, jobject javaFd) { 1205 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1206 throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd))); 1207} 1208 1209static jobject Linux_fstat(JNIEnv* env, jobject, jobject javaFd) { 1210 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1211 struct stat64 sb; 1212 int rc = TEMP_FAILURE_RETRY(fstat64(fd, &sb)); 1213 if (rc == -1) { 1214 throwErrnoException(env, "fstat"); 1215 return NULL; 1216 } 1217 return makeStructStat(env, sb); 1218} 1219 1220static jobject Linux_fstatvfs(JNIEnv* env, jobject, jobject javaFd) { 1221 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1222 struct statvfs sb; 1223 int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb)); 1224 if (rc == -1) { 1225 throwErrnoException(env, "fstatvfs"); 1226 return NULL; 1227 } 1228 return makeStructStatVfs(env, sb); 1229} 1230 1231static void Linux_fsync(JNIEnv* env, jobject, jobject javaFd) { 1232 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1233 throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd))); 1234} 1235 1236static void Linux_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) { 1237 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1238 throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length))); 1239} 1240 1241static jstring Linux_gai_strerror(JNIEnv* env, jobject, jint error) { 1242 return env->NewStringUTF(gai_strerror(error)); 1243} 1244 1245static jobjectArray Linux_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, 1246 jobject javaHints, jint netId) { 1247 ScopedUtfChars node(env, javaNode); 1248 if (node.c_str() == NULL) { 1249 return NULL; 1250 } 1251 1252 static jfieldID flagsFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_flags", "I"); 1253 static jfieldID familyFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_family", "I"); 1254 static jfieldID socktypeFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_socktype", "I"); 1255 static jfieldID protocolFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_protocol", "I"); 1256 1257 addrinfo hints; 1258 memset(&hints, 0, sizeof(hints)); 1259 hints.ai_flags = env->GetIntField(javaHints, flagsFid); 1260 hints.ai_family = env->GetIntField(javaHints, familyFid); 1261 hints.ai_socktype = env->GetIntField(javaHints, socktypeFid); 1262 hints.ai_protocol = env->GetIntField(javaHints, protocolFid); 1263 1264 addrinfo* addressList = NULL; 1265 errno = 0; 1266 int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList); 1267 std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList); 1268 if (rc != 0) { 1269 throwGaiException(env, "android_getaddrinfo", rc); 1270 return NULL; 1271 } 1272 1273 // Count results so we know how to size the output array. 1274 int addressCount = 0; 1275 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { 1276 if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { 1277 ++addressCount; 1278 } else { 1279 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); 1280 } 1281 } 1282 if (addressCount == 0) { 1283 return NULL; 1284 } 1285 1286 // Prepare output array. 1287 jobjectArray result = env->NewObjectArray(addressCount, JniConstants::inetAddressClass, NULL); 1288 if (result == NULL) { 1289 return NULL; 1290 } 1291 1292 // Examine returned addresses one by one, save them in the output array. 1293 int index = 0; 1294 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { 1295 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { 1296 // Unknown address family. Skip this address. 1297 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); 1298 continue; 1299 } 1300 1301 // Convert each IP address into a Java byte array. 1302 sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr); 1303 ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL)); 1304 if (inetAddress.get() == NULL) { 1305 return NULL; 1306 } 1307 env->SetObjectArrayElement(result, index, inetAddress.get()); 1308 ++index; 1309 } 1310 return result; 1311} 1312 1313static jint Linux_getegid(JNIEnv*, jobject) { 1314 return getegid(); 1315} 1316 1317static jint Linux_geteuid(JNIEnv*, jobject) { 1318 return geteuid(); 1319} 1320 1321static jint Linux_getgid(JNIEnv*, jobject) { 1322 return getgid(); 1323} 1324 1325static jintArray Linux_getgroups(JNIEnv* env, jobject) { 1326 int ngrps = throwIfMinusOne(env, "getgroups", getgroups(0, nullptr)); 1327 if (ngrps == -1) { 1328 return NULL; 1329 } 1330 std::vector<gid_t> groups(ngrps, 0); 1331 ngrps = throwIfMinusOne(env, "getgroups", getgroups(ngrps, &groups[0])); 1332 if (ngrps == -1) { 1333 return NULL; 1334 } 1335 jintArray out = env->NewIntArray(ngrps); 1336 if ((out != NULL) && (ngrps > 0)) { 1337 env->SetIntArrayRegion(out, 0, ngrps, reinterpret_cast<int*>(&groups[0])); 1338 } 1339 1340 return out; 1341} 1342 1343static jstring Linux_getenv(JNIEnv* env, jobject, jstring javaName) { 1344 ScopedUtfChars name(env, javaName); 1345 if (name.c_str() == NULL) { 1346 return NULL; 1347 } 1348 return env->NewStringUTF(getenv(name.c_str())); 1349} 1350 1351static jstring Linux_getnameinfo(JNIEnv* env, jobject, jobject javaAddress, jint flags) { 1352 sockaddr_storage ss; 1353 socklen_t sa_len; 1354 if (!inetAddressToSockaddrVerbatim(env, javaAddress, 0, ss, sa_len)) { 1355 return NULL; 1356 } 1357 char buf[NI_MAXHOST]; // NI_MAXHOST is longer than INET6_ADDRSTRLEN. 1358 errno = 0; 1359 int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_len, buf, sizeof(buf), NULL, 0, flags); 1360 if (rc != 0) { 1361 throwGaiException(env, "getnameinfo", rc); 1362 return NULL; 1363 } 1364 return env->NewStringUTF(buf); 1365} 1366 1367static jobject Linux_getpeername(JNIEnv* env, jobject, jobject javaFd) { 1368 return doGetSockName(env, javaFd, false); 1369} 1370 1371static jint Linux_getpgid(JNIEnv* env, jobject, jint pid) { 1372 return throwIfMinusOne(env, "getpgid", TEMP_FAILURE_RETRY(getpgid(pid))); 1373} 1374 1375static jint Linux_getpid(JNIEnv*, jobject) { 1376 return TEMP_FAILURE_RETRY(getpid()); 1377} 1378 1379static jint Linux_getppid(JNIEnv*, jobject) { 1380 return TEMP_FAILURE_RETRY(getppid()); 1381} 1382 1383static jobject Linux_getpwnam(JNIEnv* env, jobject, jstring javaName) { 1384 ScopedUtfChars name(env, javaName); 1385 if (name.c_str() == NULL) { 1386 return NULL; 1387 } 1388 return Passwd(env).getpwnam(name.c_str()); 1389} 1390 1391static jobject Linux_getpwuid(JNIEnv* env, jobject, jint uid) { 1392 return Passwd(env).getpwuid(uid); 1393} 1394 1395static jobject Linux_getrlimit(JNIEnv* env, jobject, jint resource) { 1396 struct rlimit r; 1397 if (throwIfMinusOne(env, "getrlimit", TEMP_FAILURE_RETRY(getrlimit(resource, &r))) == -1) { 1398 return nullptr; 1399 } 1400 1401 ScopedLocalRef<jclass> rlimit_class(env, env->FindClass("android/system/StructRlimit")); 1402 jmethodID ctor = env->GetMethodID(rlimit_class.get(), "<init>", "(JJ)V"); 1403 if (ctor == NULL) { 1404 return NULL; 1405 } 1406 return env->NewObject(rlimit_class.get(), ctor, 1407 static_cast<jlong>(r.rlim_cur), 1408 static_cast<jlong>(r.rlim_max)); 1409} 1410 1411static jobject Linux_getsockname(JNIEnv* env, jobject, jobject javaFd) { 1412 return doGetSockName(env, javaFd, true); 1413} 1414 1415static jint Linux_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1416 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1417 u_char result = 0; 1418 socklen_t size = sizeof(result); 1419 throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size))); 1420 return result; 1421} 1422 1423static jobject Linux_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1424 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1425 sockaddr_storage ss; 1426 memset(&ss, 0, sizeof(ss)); 1427 ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF. 1428 sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss); 1429 socklen_t size = sizeof(sa->sin_addr); 1430 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size)); 1431 if (rc == -1) { 1432 throwErrnoException(env, "getsockopt"); 1433 return NULL; 1434 } 1435 return sockaddrToInetAddress(env, ss, NULL); 1436} 1437 1438static jint Linux_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1439 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1440 jint result = 0; 1441 socklen_t size = sizeof(result); 1442 throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size))); 1443 return result; 1444} 1445 1446static jobject Linux_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1447 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1448 struct linger l; 1449 socklen_t size = sizeof(l); 1450 memset(&l, 0, size); 1451 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size)); 1452 if (rc == -1) { 1453 throwErrnoException(env, "getsockopt"); 1454 return NULL; 1455 } 1456 return makeStructLinger(env, l); 1457} 1458 1459static jobject Linux_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1460 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1461 struct timeval tv; 1462 socklen_t size = sizeof(tv); 1463 memset(&tv, 0, size); 1464 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size)); 1465 if (rc == -1) { 1466 throwErrnoException(env, "getsockopt"); 1467 return NULL; 1468 } 1469 return makeStructTimeval(env, tv); 1470} 1471 1472static jobject Linux_getsockoptUcred(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) { 1473 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1474 struct ucred u; 1475 socklen_t size = sizeof(u); 1476 memset(&u, 0, size); 1477 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &u, &size)); 1478 if (rc == -1) { 1479 throwErrnoException(env, "getsockopt"); 1480 return NULL; 1481 } 1482 return makeStructUcred(env, u); 1483} 1484 1485static jint Linux_gettid(JNIEnv* env __unused, jobject) { 1486#if defined(__BIONIC__) 1487 return TEMP_FAILURE_RETRY(gettid()); 1488#else 1489 return syscall(__NR_gettid); 1490#endif 1491} 1492 1493static jint Linux_getuid(JNIEnv*, jobject) { 1494 return getuid(); 1495} 1496 1497static jbyteArray Linux_getxattr(JNIEnv* env, jobject, jstring javaPath, 1498 jstring javaName) { 1499 ScopedUtfChars path(env, javaPath); 1500 if (path.c_str() == NULL) { 1501 return NULL; 1502 } 1503 ScopedUtfChars name(env, javaName); 1504 if (name.c_str() == NULL) { 1505 return NULL; 1506 } 1507 1508 while (true) { 1509 // Get the current size of the named extended attribute. 1510 ssize_t valueLength; 1511 if ((valueLength = getxattr(path.c_str(), name.c_str(), NULL, 0)) < 0) { 1512 throwErrnoException(env, "getxattr"); 1513 return NULL; 1514 } 1515 1516 // Create the actual byte array. 1517 std::vector<char> buf(valueLength); 1518 if ((valueLength = getxattr(path.c_str(), name.c_str(), buf.data(), valueLength)) < 0) { 1519 if (errno == ERANGE) { 1520 // The attribute value has changed since last getxattr call and buf no longer fits, 1521 // try again. 1522 continue; 1523 } 1524 throwErrnoException(env, "getxattr"); 1525 return NULL; 1526 } 1527 jbyteArray array = env->NewByteArray(valueLength); 1528 if (array == NULL) { 1529 return NULL; 1530 } 1531 env->SetByteArrayRegion(array, 0, valueLength, reinterpret_cast<const jbyte*>(buf.data())); 1532 return array; 1533 } 1534} 1535 1536static jobjectArray Linux_getifaddrs(JNIEnv* env, jobject) { 1537 static jmethodID ctor = env->GetMethodID(JniConstants::structIfaddrs, "<init>", 1538 "(Ljava/lang/String;ILjava/net/InetAddress;Ljava/net/InetAddress;Ljava/net/InetAddress;[B)V"); 1539 if (ctor == NULL) { 1540 return NULL; 1541 } 1542 1543 ifaddrs* ifaddr; 1544 int rc = TEMP_FAILURE_RETRY(getifaddrs(&ifaddr)); 1545 if (rc == -1) { 1546 throwErrnoException(env, "getifaddrs"); 1547 return NULL; 1548 } 1549 std::unique_ptr<ifaddrs, decltype(&freeifaddrs)> ifaddrPtr(ifaddr, freeifaddrs); 1550 1551 // Count results so we know how to size the output array. 1552 jint ifCount = 0; 1553 for (ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { 1554 ++ifCount; 1555 } 1556 1557 // Prepare output array. 1558 jobjectArray result = env->NewObjectArray(ifCount, JniConstants::structIfaddrs, NULL); 1559 if (result == NULL) { 1560 return NULL; 1561 } 1562 1563 // Traverse the list and populate the output array. 1564 int index = 0; 1565 for (ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next, ++index) { 1566 TO_JAVA_STRING(name, ifa->ifa_name); 1567 jint flags = ifa->ifa_flags; 1568 sockaddr_storage* interfaceAddr = 1569 reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr); 1570 sockaddr_storage* netmaskAddr = 1571 reinterpret_cast<sockaddr_storage*>(ifa->ifa_netmask); 1572 sockaddr_storage* broadAddr = 1573 reinterpret_cast<sockaddr_storage*>(ifa->ifa_broadaddr); 1574 1575 jobject addr, netmask, broad; 1576 jbyteArray hwaddr = NULL; 1577 if (interfaceAddr != NULL) { 1578 switch (interfaceAddr->ss_family) { 1579 case AF_INET: 1580 case AF_INET6: 1581 // IPv4 / IPv6. 1582 // interfaceAddr and netmaskAddr are never null. 1583 if ((addr = sockaddrToInetAddress(env, *interfaceAddr, NULL)) == NULL) { 1584 return NULL; 1585 } 1586 if ((netmask = sockaddrToInetAddress(env, *netmaskAddr, NULL)) == NULL) { 1587 return NULL; 1588 } 1589 if (broadAddr != NULL && (ifa->ifa_flags & IFF_BROADCAST)) { 1590 if ((broad = sockaddrToInetAddress(env, *broadAddr, NULL)) == NULL) { 1591 return NULL; 1592 } 1593 } else { 1594 broad = NULL; 1595 } 1596 break; 1597 case AF_PACKET: 1598 // Raw Interface. 1599 sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr); 1600 1601 bool allZero = true; 1602 for (int i = 0; i < sll->sll_halen; ++i) { 1603 if (sll->sll_addr[i] != 0) { 1604 allZero = false; 1605 break; 1606 } 1607 } 1608 1609 if (!allZero) { 1610 hwaddr = env->NewByteArray(sll->sll_halen); 1611 if (hwaddr == NULL) { 1612 return NULL; 1613 } 1614 env->SetByteArrayRegion(hwaddr, 0, sll->sll_halen, 1615 reinterpret_cast<const jbyte*>(sll->sll_addr)); 1616 } 1617 addr = netmask = broad = NULL; 1618 break; 1619 } 1620 } else { 1621 // Preserve the entry even if the interface has no interface address. 1622 // http://b/29243557/ 1623 addr = netmask = broad = NULL; 1624 } 1625 1626 jobject o = env->NewObject(JniConstants::structIfaddrs, ctor, name, flags, addr, netmask, 1627 broad, hwaddr); 1628 if (o == NULL) { 1629 return NULL; 1630 } 1631 env->SetObjectArrayElement(result, index, o); 1632 } 1633 1634 return result; 1635} 1636 1637static jstring Linux_if_indextoname(JNIEnv* env, jobject, jint index) { 1638 char buf[IF_NAMESIZE]; 1639 char* name = if_indextoname(index, buf); 1640 // if_indextoname(3) returns NULL on failure, which will come out of NewStringUTF unscathed. 1641 // There's no useful information in errno, so we don't bother throwing. Callers can null-check. 1642 return env->NewStringUTF(name); 1643} 1644 1645static jint Linux_if_nametoindex(JNIEnv* env, jobject, jstring name) { 1646 ScopedUtfChars cname(env, name); 1647 if (cname.c_str() == NULL) { 1648 return 0; 1649 } 1650 1651 // There's no useful information in errno, so we don't bother throwing. Callers can zero-check. 1652 return if_nametoindex(cname.c_str()); 1653} 1654 1655static jobject Linux_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) { 1656 ScopedUtfChars name(env, javaName); 1657 if (name.c_str() == NULL) { 1658 return NULL; 1659 } 1660 sockaddr_storage ss; 1661 memset(&ss, 0, sizeof(ss)); 1662 // sockaddr_in and sockaddr_in6 are at the same address, so we can use either here. 1663 void* dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr; 1664 if (inet_pton(family, name.c_str(), dst) != 1) { 1665 return NULL; 1666 } 1667 ss.ss_family = family; 1668 return sockaddrToInetAddress(env, ss, NULL); 1669} 1670 1671static jint Linux_ioctlFlags(JNIEnv* env, jobject, jobject javaFd, jstring javaInterfaceName) { 1672 struct ifreq req; 1673 if (!fillIfreq(env, javaInterfaceName, req)) { 1674 return 0; 1675 } 1676 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1677 throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, SIOCGIFFLAGS, &req))); 1678 return req.ifr_flags; 1679} 1680 1681static jobject Linux_ioctlInetAddress(JNIEnv* env, jobject, jobject javaFd, jint cmd, jstring javaInterfaceName) { 1682 struct ifreq req; 1683 if (!fillIfreq(env, javaInterfaceName, req)) { 1684 return NULL; 1685 } 1686 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1687 int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &req))); 1688 if (rc == -1) { 1689 return NULL; 1690 } 1691 return sockaddrToInetAddress(env, reinterpret_cast<sockaddr_storage&>(req.ifr_addr), NULL); 1692} 1693 1694static jint Linux_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) { 1695 // This is complicated because ioctls may return their result by updating their argument 1696 // or via their return value, so we need to support both. 1697 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1698 jint arg = env->GetIntField(javaArg, int32RefValueFid); 1699 int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &arg))); 1700 if (!env->ExceptionCheck()) { 1701 env->SetIntField(javaArg, int32RefValueFid, arg); 1702 } 1703 return rc; 1704} 1705 1706static jint Linux_ioctlMTU(JNIEnv* env, jobject, jobject javaFd, jstring javaInterfaceName) { 1707 struct ifreq req; 1708 if (!fillIfreq(env, javaInterfaceName, req)) { 1709 return 0; 1710 } 1711 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1712 throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, SIOCGIFMTU, &req))); 1713 return req.ifr_mtu; 1714} 1715 1716static jboolean Linux_isatty(JNIEnv* env, jobject, jobject javaFd) { 1717 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1718 return TEMP_FAILURE_RETRY(isatty(fd)) == 1; 1719} 1720 1721static void Linux_kill(JNIEnv* env, jobject, jint pid, jint sig) { 1722 throwIfMinusOne(env, "kill", TEMP_FAILURE_RETRY(kill(pid, sig))); 1723} 1724 1725static void Linux_lchown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) { 1726 ScopedUtfChars path(env, javaPath); 1727 if (path.c_str() == NULL) { 1728 return; 1729 } 1730 throwIfMinusOne(env, "lchown", TEMP_FAILURE_RETRY(lchown(path.c_str(), uid, gid))); 1731} 1732 1733static void Linux_link(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { 1734 ScopedUtfChars oldPath(env, javaOldPath); 1735 if (oldPath.c_str() == NULL) { 1736 return; 1737 } 1738 ScopedUtfChars newPath(env, javaNewPath); 1739 if (newPath.c_str() == NULL) { 1740 return; 1741 } 1742 throwIfMinusOne(env, "link", TEMP_FAILURE_RETRY(link(oldPath.c_str(), newPath.c_str()))); 1743} 1744 1745static void Linux_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog) { 1746 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1747 throwIfMinusOne(env, "listen", TEMP_FAILURE_RETRY(listen(fd, backlog))); 1748} 1749 1750static jobjectArray Linux_listxattr(JNIEnv* env, jobject, jstring javaPath) { 1751 ScopedUtfChars path(env, javaPath); 1752 if (path.c_str() == NULL) { 1753 return NULL; 1754 } 1755 1756 while (true) { 1757 // Get the current size of the named extended attribute. 1758 ssize_t valueLength; 1759 if ((valueLength = listxattr(path.c_str(), NULL, 0)) < 0) { 1760 throwErrnoException(env, "listxattr"); 1761 return NULL; 1762 } 1763 1764 // Create the actual byte array. 1765 std::string buf(valueLength, '\0'); 1766 if ((valueLength = listxattr(path.c_str(), &buf[0], valueLength)) < 0) { 1767 if (errno == ERANGE) { 1768 // The attribute value has changed since last listxattr call and buf no longer fits, 1769 // try again. 1770 continue; 1771 } 1772 throwErrnoException(env, "listxattr"); 1773 return NULL; 1774 } 1775 1776 // Split the output by '\0'. 1777 buf.resize(valueLength > 0 ? valueLength - 1 : 0); // Remove the trailing NULL character. 1778 std::string delim("\0", 1); 1779 auto xattrs = android::base::Split(buf, delim); 1780 1781 return toStringArray(env, xattrs); 1782 } 1783} 1784 1785static jlong Linux_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) { 1786 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1787 return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence))); 1788} 1789 1790static jobject Linux_lstat(JNIEnv* env, jobject, jstring javaPath) { 1791 return doStat(env, javaPath, true); 1792} 1793 1794static void Linux_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) { 1795 ScopedByteArrayRW vector(env, javaVector); 1796 if (vector.get() == NULL) { 1797 return; 1798 } 1799 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1800 unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get()); 1801 throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec))); 1802} 1803 1804static void Linux_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) { 1805 ScopedUtfChars path(env, javaPath); 1806 if (path.c_str() == NULL) { 1807 return; 1808 } 1809 throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode))); 1810} 1811 1812static void Linux_mkfifo(JNIEnv* env, jobject, jstring javaPath, jint mode) { 1813 ScopedUtfChars path(env, javaPath); 1814 if (path.c_str() == NULL) { 1815 return; 1816 } 1817 throwIfMinusOne(env, "mkfifo", TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode))); 1818} 1819 1820static void Linux_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) { 1821 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1822 throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount))); 1823} 1824 1825static jlong Linux_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) { 1826 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1827 void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1828 void* ptr = mmap64(suggestedPtr, byteCount, prot, flags, fd, offset); 1829 if (ptr == MAP_FAILED) { 1830 throwErrnoException(env, "mmap"); 1831 } 1832 return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr)); 1833} 1834 1835static void Linux_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) { 1836 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1837 throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags))); 1838} 1839 1840static void Linux_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) { 1841 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1842 throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount))); 1843} 1844 1845static void Linux_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) { 1846 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 1847 throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount))); 1848} 1849 1850static jobject Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) { 1851 ScopedUtfChars path(env, javaPath); 1852 if (path.c_str() == NULL) { 1853 return NULL; 1854 } 1855 int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode))); 1856 return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL; 1857} 1858 1859static jobjectArray Linux_pipe2(JNIEnv* env, jobject, jint flags __unused) { 1860 int fds[2]; 1861 int pipe2_result = throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(&fds[0], flags))); 1862 if (pipe2_result == -1) { 1863 return NULL; 1864 } 1865 jobjectArray result = env->NewObjectArray(2, JniConstants::fileDescriptorClass, NULL); 1866 if (result == NULL) { 1867 return NULL; 1868 } 1869 for (int i = 0; i < 2; ++i) { 1870 ScopedLocalRef<jobject> fd(env, jniCreateFileDescriptor(env, fds[i])); 1871 if (fd.get() == NULL) { 1872 return NULL; 1873 } 1874 env->SetObjectArrayElement(result, i, fd.get()); 1875 if (env->ExceptionCheck()) { 1876 return NULL; 1877 } 1878 } 1879 return result; 1880} 1881 1882static jint Linux_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) { 1883 static jfieldID fdFid = env->GetFieldID(JniConstants::structPollfdClass, "fd", "Ljava/io/FileDescriptor;"); 1884 static jfieldID eventsFid = env->GetFieldID(JniConstants::structPollfdClass, "events", "S"); 1885 static jfieldID reventsFid = env->GetFieldID(JniConstants::structPollfdClass, "revents", "S"); 1886 1887 // Turn the Java android.system.StructPollfd[] into a C++ struct pollfd[]. 1888 size_t arrayLength = env->GetArrayLength(javaStructs); 1889 std::unique_ptr<struct pollfd[]> fds(new struct pollfd[arrayLength]); 1890 memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength); 1891 size_t count = 0; // Some trailing array elements may be irrelevant. (See below.) 1892 for (size_t i = 0; i < arrayLength; ++i) { 1893 ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i)); 1894 if (javaStruct.get() == NULL) { 1895 break; // We allow trailing nulls in the array for caller convenience. 1896 } 1897 ScopedLocalRef<jobject> javaFd(env, env->GetObjectField(javaStruct.get(), fdFid)); 1898 if (javaFd.get() == NULL) { 1899 break; // We also allow callers to just clear the fd field (this is what Selector does). 1900 } 1901 fds[count].fd = jniGetFDFromFileDescriptor(env, javaFd.get()); 1902 fds[count].events = env->GetShortField(javaStruct.get(), eventsFid); 1903 ++count; 1904 } 1905 1906 std::vector<AsynchronousCloseMonitor*> monitors; 1907 for (size_t i = 0; i < count; ++i) { 1908 monitors.push_back(new AsynchronousCloseMonitor(fds[i].fd)); 1909 } 1910 1911 int rc; 1912 while (true) { 1913 timespec before; 1914 clock_gettime(CLOCK_MONOTONIC, &before); 1915 1916 rc = poll(fds.get(), count, timeoutMs); 1917 if (rc >= 0 || errno != EINTR) { 1918 break; 1919 } 1920 1921 // We got EINTR. Work out how much of the original timeout is still left. 1922 if (timeoutMs > 0) { 1923 timespec now; 1924 clock_gettime(CLOCK_MONOTONIC, &now); 1925 1926 timespec diff; 1927 diff.tv_sec = now.tv_sec - before.tv_sec; 1928 diff.tv_nsec = now.tv_nsec - before.tv_nsec; 1929 if (diff.tv_nsec < 0) { 1930 --diff.tv_sec; 1931 diff.tv_nsec += 1000000000; 1932 } 1933 1934 jint diffMs = diff.tv_sec * 1000 + diff.tv_nsec / 1000000; 1935 if (diffMs >= timeoutMs) { 1936 rc = 0; // We have less than 1ms left anyway, so just time out. 1937 break; 1938 } 1939 1940 timeoutMs -= diffMs; 1941 } 1942 } 1943 1944 for (size_t i = 0; i < monitors.size(); ++i) { 1945 delete monitors[i]; 1946 } 1947 if (rc == -1) { 1948 throwErrnoException(env, "poll"); 1949 return -1; 1950 } 1951 1952 // Update the revents fields in the Java android.system.StructPollfd[]. 1953 for (size_t i = 0; i < count; ++i) { 1954 ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i)); 1955 if (javaStruct.get() == NULL) { 1956 return -1; 1957 } 1958 env->SetShortField(javaStruct.get(), reventsFid, fds[i].revents); 1959 } 1960 return rc; 1961} 1962 1963static void Linux_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused, 1964 jlong offset __unused, jlong length __unused) { 1965 int fd = jniGetFDFromFileDescriptor(env, javaFd); 1966 while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) { 1967 } 1968 if (errno != 0) { 1969 throwErrnoException(env, "posix_fallocate"); 1970 } 1971} 1972 1973static jint Linux_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused, 1974 jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) { 1975 int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option), 1976 static_cast<unsigned long>(arg2), 1977 static_cast<unsigned long>(arg3), 1978 static_cast<unsigned long>(arg4), 1979 static_cast<unsigned long>(arg5))); 1980 return throwIfMinusOne(env, "prctl", result); 1981} 1982 1983static jint Linux_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) { 1984 ScopedBytesRW bytes(env, javaBytes); 1985 if (bytes.get() == NULL) { 1986 return -1; 1987 } 1988 return IO_FAILURE_RETRY(env, ssize_t, pread64, javaFd, bytes.get() + byteOffset, byteCount, offset); 1989} 1990 1991static jint Linux_pwriteBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount, jlong offset) { 1992 ScopedBytesRO bytes(env, javaBytes); 1993 if (bytes.get() == NULL) { 1994 return -1; 1995 } 1996 return IO_FAILURE_RETRY(env, ssize_t, pwrite64, javaFd, bytes.get() + byteOffset, byteCount, offset); 1997} 1998 1999static jint Linux_readBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) { 2000 ScopedBytesRW bytes(env, javaBytes); 2001 if (bytes.get() == NULL) { 2002 return -1; 2003 } 2004 return IO_FAILURE_RETRY(env, ssize_t, read, javaFd, bytes.get() + byteOffset, byteCount); 2005} 2006 2007static jstring Linux_readlink(JNIEnv* env, jobject, jstring javaPath) { 2008 ScopedUtfChars path(env, javaPath); 2009 if (path.c_str() == NULL) { 2010 return NULL; 2011 } 2012 2013 std::string result; 2014 if (!android::base::Readlink(path.c_str(), &result)) { 2015 throwErrnoException(env, "readlink"); 2016 return NULL; 2017 } 2018 return env->NewStringUTF(result.c_str()); 2019} 2020 2021static jstring Linux_realpath(JNIEnv* env, jobject, jstring javaPath) { 2022 ScopedUtfChars path(env, javaPath); 2023 if (path.c_str() == NULL) { 2024 return NULL; 2025 } 2026 2027 std::unique_ptr<char, c_deleter> real_path(realpath(path.c_str(), nullptr)); 2028 if (real_path.get() == nullptr) { 2029 throwErrnoException(env, "realpath"); 2030 return NULL; 2031 } 2032 2033 return env->NewStringUTF(real_path.get()); 2034} 2035 2036static jint Linux_readv(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) { 2037 IoVec<ScopedBytesRW> ioVec(env, env->GetArrayLength(buffers)); 2038 if (!ioVec.init(buffers, offsets, byteCounts)) { 2039 return -1; 2040 } 2041 return IO_FAILURE_RETRY(env, ssize_t, readv, javaFd, ioVec.get(), ioVec.size()); 2042} 2043 2044static jint Linux_recvfromBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetSocketAddress) { 2045 ScopedBytesRW bytes(env, javaBytes); 2046 if (bytes.get() == NULL) { 2047 return -1; 2048 } 2049 sockaddr_storage ss; 2050 socklen_t sl = sizeof(ss); 2051 memset(&ss, 0, sizeof(ss)); 2052 sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL; 2053 socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0; 2054 jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength); 2055 if (recvCount >= 0) { 2056 // The socket may have performed orderly shutdown and recvCount would return 0 (see man 2 2057 // recvfrom), in which case ss.ss_family == AF_UNIX and fillInetSocketAddress would fail. 2058 // Don't fill in the address if recvfrom didn't succeed. http://b/33483694 2059 if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) { 2060 fillInetSocketAddress(env, javaInetSocketAddress, ss); 2061 } 2062 } 2063 return recvCount; 2064} 2065 2066static void Linux_remove(JNIEnv* env, jobject, jstring javaPath) { 2067 ScopedUtfChars path(env, javaPath); 2068 if (path.c_str() == NULL) { 2069 return; 2070 } 2071 throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str()))); 2072} 2073 2074static void Linux_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) { 2075 ScopedUtfChars path(env, javaPath); 2076 if (path.c_str() == NULL) { 2077 return; 2078 } 2079 ScopedUtfChars name(env, javaName); 2080 if (name.c_str() == NULL) { 2081 return; 2082 } 2083 2084 int res = removexattr(path.c_str(), name.c_str()); 2085 if (res < 0) { 2086 throwErrnoException(env, "removexattr"); 2087 } 2088} 2089 2090static void Linux_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { 2091 ScopedUtfChars oldPath(env, javaOldPath); 2092 if (oldPath.c_str() == NULL) { 2093 return; 2094 } 2095 ScopedUtfChars newPath(env, javaNewPath); 2096 if (newPath.c_str() == NULL) { 2097 return; 2098 } 2099 throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str()))); 2100} 2101 2102static jlong Linux_sendfile(JNIEnv* env, jobject, jobject javaOutFd, jobject javaInFd, jobject javaOffset, jlong byteCount) { 2103 int outFd = jniGetFDFromFileDescriptor(env, javaOutFd); 2104 int inFd = jniGetFDFromFileDescriptor(env, javaInFd); 2105 off_t offset = 0; 2106 off_t* offsetPtr = NULL; 2107 if (javaOffset != NULL) { 2108 // TODO: fix bionic so we can have a 64-bit off_t! 2109 offset = env->GetLongField(javaOffset, int64RefValueFid); 2110 offsetPtr = &offset; 2111 } 2112 jlong result = throwIfMinusOne(env, "sendfile", TEMP_FAILURE_RETRY(sendfile(outFd, inFd, offsetPtr, byteCount))); 2113 if (result == -1) { 2114 return -1; 2115 } 2116 if (javaOffset != NULL) { 2117 env->SetLongField(javaOffset, int64RefValueFid, offset); 2118 } 2119 return result; 2120} 2121 2122static jint Linux_sendtoBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetAddress, jint port) { 2123 ScopedBytesRO bytes(env, javaBytes); 2124 if (bytes.get() == NULL) { 2125 return -1; 2126 } 2127 2128 return NET_IPV4_FALLBACK(env, ssize_t, sendto, javaFd, javaInetAddress, port, 2129 NULL_ADDR_OK, bytes.get() + byteOffset, byteCount, flags); 2130} 2131 2132static jint Linux_sendtoBytesSocketAddress(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaSocketAddress) { 2133 if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) { 2134 // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK. 2135 jobject javaInetAddress; 2136 jint port; 2137 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port); 2138 return Linux_sendtoBytes(env, NULL, javaFd, javaBytes, byteOffset, byteCount, flags, 2139 javaInetAddress, port); 2140 } 2141 2142 ScopedBytesRO bytes(env, javaBytes); 2143 if (bytes.get() == NULL) { 2144 return -1; 2145 } 2146 2147 sockaddr_storage ss; 2148 socklen_t sa_len; 2149 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) { 2150 return -1; 2151 } 2152 2153 const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss); 2154 // We don't need the return value because we'll already have thrown. 2155 return NET_FAILURE_RETRY(env, ssize_t, sendto, javaFd, bytes.get() + byteOffset, byteCount, flags, sa, sa_len); 2156} 2157 2158static void Linux_setegid(JNIEnv* env, jobject, jint egid) { 2159 throwIfMinusOne(env, "setegid", TEMP_FAILURE_RETRY(setegid(egid))); 2160} 2161 2162static void Linux_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue, jboolean overwrite) { 2163 ScopedUtfChars name(env, javaName); 2164 if (name.c_str() == NULL) { 2165 return; 2166 } 2167 ScopedUtfChars value(env, javaValue); 2168 if (value.c_str() == NULL) { 2169 return; 2170 } 2171 throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite)); 2172} 2173 2174static void Linux_seteuid(JNIEnv* env, jobject, jint euid) { 2175 throwIfMinusOne(env, "seteuid", TEMP_FAILURE_RETRY(seteuid(euid))); 2176} 2177 2178static void Linux_setgid(JNIEnv* env, jobject, jint gid) { 2179 throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid))); 2180} 2181 2182static void Linux_setgroups(JNIEnv* env, jobject, jintArray gids) { 2183 size_t ngrps = gids == NULL ? 0 : env->GetArrayLength(gids); 2184 std::vector<gid_t> groups(ngrps, 0); 2185 env->GetIntArrayRegion(gids, 0, ngrps, reinterpret_cast<int*>(&groups[0])); 2186 throwIfMinusOne(env, "setgroups", setgroups(ngrps, &groups[0])); 2187} 2188 2189static void Linux_setpgid(JNIEnv* env, jobject, jint pid, int pgid) { 2190 throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid))); 2191} 2192 2193static void Linux_setregid(JNIEnv* env, jobject, jint rgid, int egid) { 2194 throwIfMinusOne(env, "setregid", TEMP_FAILURE_RETRY(setregid(rgid, egid))); 2195} 2196 2197static void Linux_setreuid(JNIEnv* env, jobject, jint ruid, int euid) { 2198 throwIfMinusOne(env, "setreuid", TEMP_FAILURE_RETRY(setreuid(ruid, euid))); 2199} 2200 2201static jint Linux_setsid(JNIEnv* env, jobject) { 2202 return throwIfMinusOne(env, "setsid", TEMP_FAILURE_RETRY(setsid())); 2203} 2204 2205static void Linux_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) { 2206 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2207 u_char byte = value; 2208 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte)))); 2209} 2210 2211static void Linux_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring javaInterfaceName) { 2212 struct ifreq req; 2213 if (!fillIfreq(env, javaInterfaceName, req)) { 2214 return; 2215 } 2216 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2217 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)))); 2218} 2219 2220static void Linux_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) { 2221 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2222 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value)))); 2223} 2224 2225static void Linux_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) { 2226 ip_mreqn req; 2227 memset(&req, 0, sizeof(req)); 2228 req.imr_ifindex = value; 2229 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2230 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)))); 2231} 2232 2233static void Linux_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) { 2234 struct group_req req; 2235 memset(&req, 0, sizeof(req)); 2236 2237 static jfieldID grInterfaceFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_interface", "I"); 2238 req.gr_interface = env->GetIntField(javaGroupReq, grInterfaceFid); 2239 // Get the IPv4 or IPv6 multicast address to join or leave. 2240 static jfieldID grGroupFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_group", "Ljava/net/InetAddress;"); 2241 ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupReq, grGroupFid)); 2242 socklen_t sa_len; 2243 if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gr_group, sa_len)) { 2244 return; 2245 } 2246 2247 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2248 int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))); 2249 if (rc == -1 && errno == EINVAL) { 2250 // Maybe we're a 32-bit binary talking to a 64-bit kernel? 2251 // glibc doesn't automatically handle this. 2252 // http://sourceware.org/bugzilla/show_bug.cgi?id=12080 2253 struct group_req64 { 2254 uint32_t gr_interface; 2255 uint32_t my_padding; 2256 sockaddr_storage gr_group; 2257 }; 2258 group_req64 req64; 2259 req64.gr_interface = req.gr_interface; 2260 memcpy(&req64.gr_group, &req.gr_group, sizeof(req.gr_group)); 2261 rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64))); 2262 } 2263 throwIfMinusOne(env, "setsockopt", rc); 2264} 2265 2266static void Linux_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) { 2267 static jfieldID lOnoffFid = env->GetFieldID(JniConstants::structLingerClass, "l_onoff", "I"); 2268 static jfieldID lLingerFid = env->GetFieldID(JniConstants::structLingerClass, "l_linger", "I"); 2269 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2270 struct linger value; 2271 value.l_onoff = env->GetIntField(javaLinger, lOnoffFid); 2272 value.l_linger = env->GetIntField(javaLinger, lLingerFid); 2273 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value)))); 2274} 2275 2276static void Linux_setsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaTimeval) { 2277 static jfieldID tvSecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_sec", "J"); 2278 static jfieldID tvUsecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_usec", "J"); 2279 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2280 struct timeval value; 2281 value.tv_sec = env->GetLongField(javaTimeval, tvSecFid); 2282 value.tv_usec = env->GetLongField(javaTimeval, tvUsecFid); 2283 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value)))); 2284} 2285 2286static void Linux_setuid(JNIEnv* env, jobject, jint uid) { 2287 throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid))); 2288} 2289 2290static void Linux_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName, 2291 jbyteArray javaValue, jint flags) { 2292 ScopedUtfChars path(env, javaPath); 2293 if (path.c_str() == NULL) { 2294 return; 2295 } 2296 ScopedUtfChars name(env, javaName); 2297 if (name.c_str() == NULL) { 2298 return; 2299 } 2300 ScopedBytesRO value(env, javaValue); 2301 if (value.get() == NULL) { 2302 return; 2303 } 2304 size_t valueLength = env->GetArrayLength(javaValue); 2305 int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags); 2306 if (res < 0) { 2307 throwErrnoException(env, "setxattr"); 2308 } 2309} 2310 2311static void Linux_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) { 2312 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2313 throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how))); 2314} 2315 2316static jobject Linux_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) { 2317 if (domain == AF_PACKET) { 2318 protocol = htons(protocol); // Packet sockets specify the protocol in host byte order. 2319 } 2320 int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol))); 2321 return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL; 2322} 2323 2324static void Linux_socketpair(JNIEnv* env, jobject, jint domain, jint type, jint protocol, jobject javaFd1, jobject javaFd2) { 2325 int fds[2]; 2326 int rc = throwIfMinusOne(env, "socketpair", TEMP_FAILURE_RETRY(socketpair(domain, type, protocol, fds))); 2327 if (rc != -1) { 2328 jniSetFileDescriptorOfFD(env, javaFd1, fds[0]); 2329 jniSetFileDescriptorOfFD(env, javaFd2, fds[1]); 2330 } 2331} 2332 2333static jlong Linux_splice(JNIEnv* env, jobject, jobject javaFdIn, jobject javaOffIn, jobject javaFdOut, jobject javaOffOut, jlong len, jint flags) { 2334 int fdIn = jniGetFDFromFileDescriptor(env, javaFdIn); 2335 int fdOut = jniGetFDFromFileDescriptor(env, javaFdOut); 2336 int spliceErrno; 2337 2338 jlong offIn = (javaOffIn == NULL ? 0 : env->GetLongField(javaOffIn, int64RefValueFid)); 2339 jlong offOut = (javaOffOut == NULL ? 0 : env->GetLongField(javaOffOut, int64RefValueFid)); 2340 jlong ret = -1; 2341 do { 2342 bool wasSignaled = false; 2343 { 2344 AsynchronousCloseMonitor monitorIn(fdIn); 2345 AsynchronousCloseMonitor monitorOut(fdOut); 2346 ret = splice(fdIn, (javaOffIn == NULL ? NULL : &offIn), 2347 fdOut, (javaOffOut == NULL ? NULL : &offOut), 2348 len, flags); 2349 spliceErrno = errno; 2350 wasSignaled = monitorIn.wasSignaled() || monitorOut.wasSignaled(); 2351 } 2352 if (wasSignaled) { 2353 jniThrowException(env, "java/io/InterruptedIOException", "splice interrupted"); 2354 ret = -1; 2355 break; 2356 } 2357 if (ret == -1 && spliceErrno != EINTR) { 2358 throwErrnoException(env, "splice"); 2359 break; 2360 } 2361 } while (ret == -1); 2362 if (ret == -1) { 2363 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ 2364 errno = spliceErrno; 2365 } else { 2366 if (javaOffIn != NULL) { 2367 env->SetLongField(javaOffIn, int64RefValueFid, offIn); 2368 } 2369 if (javaOffOut != NULL) { 2370 env->SetLongField(javaOffOut, int64RefValueFid, offOut); 2371 } 2372 } 2373 return ret; 2374} 2375 2376 2377static jobject Linux_stat(JNIEnv* env, jobject, jstring javaPath) { 2378 return doStat(env, javaPath, false); 2379} 2380 2381static jobject Linux_statvfs(JNIEnv* env, jobject, jstring javaPath) { 2382 ScopedUtfChars path(env, javaPath); 2383 if (path.c_str() == NULL) { 2384 return NULL; 2385 } 2386 struct statvfs sb; 2387 int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb)); 2388 if (rc == -1) { 2389 throwErrnoException(env, "statvfs"); 2390 return NULL; 2391 } 2392 return makeStructStatVfs(env, sb); 2393} 2394 2395static jstring Linux_strerror(JNIEnv* env, jobject, jint errnum) { 2396 char buffer[BUFSIZ]; 2397 const char* message = jniStrError(errnum, buffer, sizeof(buffer)); 2398 return env->NewStringUTF(message); 2399} 2400 2401static jstring Linux_strsignal(JNIEnv* env, jobject, jint signal) { 2402 return env->NewStringUTF(strsignal(signal)); 2403} 2404 2405static void Linux_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { 2406 ScopedUtfChars oldPath(env, javaOldPath); 2407 if (oldPath.c_str() == NULL) { 2408 return; 2409 } 2410 ScopedUtfChars newPath(env, javaNewPath); 2411 if (newPath.c_str() == NULL) { 2412 return; 2413 } 2414 throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str()))); 2415} 2416 2417static jlong Linux_sysconf(JNIEnv* env, jobject, jint name) { 2418 // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward. 2419 errno = 0; 2420 long result = sysconf(name); 2421 if (result == -1L && errno == EINVAL) { 2422 throwErrnoException(env, "sysconf"); 2423 } 2424 return result; 2425} 2426 2427static void Linux_tcdrain(JNIEnv* env, jobject, jobject javaFd) { 2428 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2429 throwIfMinusOne(env, "tcdrain", TEMP_FAILURE_RETRY(tcdrain(fd))); 2430} 2431 2432static void Linux_tcsendbreak(JNIEnv* env, jobject, jobject javaFd, jint duration) { 2433 int fd = jniGetFDFromFileDescriptor(env, javaFd); 2434 throwIfMinusOne(env, "tcsendbreak", TEMP_FAILURE_RETRY(tcsendbreak(fd, duration))); 2435} 2436 2437static jint Linux_umaskImpl(JNIEnv*, jobject, jint mask) { 2438 return umask(mask); 2439} 2440 2441static jobject Linux_uname(JNIEnv* env, jobject) { 2442 struct utsname buf; 2443 if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) { 2444 return NULL; // Can't happen. 2445 } 2446 return makeStructUtsname(env, buf); 2447} 2448 2449static void Linux_unlink(JNIEnv* env, jobject, jstring javaPathname) { 2450 ScopedUtfChars pathname(env, javaPathname); 2451 if (pathname.c_str() == NULL) { 2452 return; 2453 } 2454 throwIfMinusOne(env, "unlink", unlink(pathname.c_str())); 2455} 2456 2457static void Linux_unsetenv(JNIEnv* env, jobject, jstring javaName) { 2458 ScopedUtfChars name(env, javaName); 2459 if (name.c_str() == NULL) { 2460 return; 2461 } 2462 throwIfMinusOne(env, "unsetenv", unsetenv(name.c_str())); 2463} 2464 2465static jint Linux_waitpid(JNIEnv* env, jobject, jint pid, jobject javaStatus, jint options) { 2466 int status; 2467 int rc = throwIfMinusOne(env, "waitpid", TEMP_FAILURE_RETRY(waitpid(pid, &status, options))); 2468 if (javaStatus != NULL && rc != -1) { 2469 env->SetIntField(javaStatus, int32RefValueFid, status); 2470 } 2471 return rc; 2472} 2473 2474static jint Linux_writeBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount) { 2475 ScopedBytesRO bytes(env, javaBytes); 2476 if (bytes.get() == NULL) { 2477 return -1; 2478 } 2479 return IO_FAILURE_RETRY(env, ssize_t, write, javaFd, bytes.get() + byteOffset, byteCount); 2480} 2481 2482static jint Linux_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) { 2483 IoVec<ScopedBytesRO> ioVec(env, env->GetArrayLength(buffers)); 2484 if (!ioVec.init(buffers, offsets, byteCounts)) { 2485 return -1; 2486 } 2487 return IO_FAILURE_RETRY(env, ssize_t, writev, javaFd, ioVec.get(), ioVec.size()); 2488} 2489 2490#define NATIVE_METHOD_OVERLOAD(className, functionName, signature, variant) \ 2491 { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) } 2492 2493static JNINativeMethod gMethods[] = { 2494 NATIVE_METHOD(Linux, accept, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;"), 2495 NATIVE_METHOD(Linux, access, "(Ljava/lang/String;I)Z"), 2496 NATIVE_METHOD(Linux, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"), 2497 NATIVE_METHOD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"), 2498 NATIVE_METHOD_OVERLOAD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress), 2499 NATIVE_METHOD(Linux, capget, 2500 "(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;"), 2501 NATIVE_METHOD(Linux, capset, 2502 "(Landroid/system/StructCapUserHeader;[Landroid/system/StructCapUserData;)V"), 2503 NATIVE_METHOD(Linux, chmod, "(Ljava/lang/String;I)V"), 2504 NATIVE_METHOD(Linux, chown, "(Ljava/lang/String;II)V"), 2505 NATIVE_METHOD(Linux, close, "(Ljava/io/FileDescriptor;)V"), 2506 NATIVE_METHOD(Linux, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"), 2507 NATIVE_METHOD_OVERLOAD(Linux, connect, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress), 2508 NATIVE_METHOD(Linux, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"), 2509 NATIVE_METHOD(Linux, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"), 2510 NATIVE_METHOD(Linux, environ, "()[Ljava/lang/String;"), 2511 NATIVE_METHOD(Linux, execv, "(Ljava/lang/String;[Ljava/lang/String;)V"), 2512 NATIVE_METHOD(Linux, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"), 2513 NATIVE_METHOD(Linux, fchmod, "(Ljava/io/FileDescriptor;I)V"), 2514 NATIVE_METHOD(Linux, fchown, "(Ljava/io/FileDescriptor;II)V"), 2515 NATIVE_METHOD(Linux, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"), 2516 NATIVE_METHOD(Linux, fcntlInt, "(Ljava/io/FileDescriptor;II)I"), 2517 NATIVE_METHOD(Linux, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"), 2518 NATIVE_METHOD(Linux, fdatasync, "(Ljava/io/FileDescriptor;)V"), 2519 NATIVE_METHOD(Linux, fstat, "(Ljava/io/FileDescriptor;)Landroid/system/StructStat;"), 2520 NATIVE_METHOD(Linux, fstatvfs, "(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;"), 2521 NATIVE_METHOD(Linux, fsync, "(Ljava/io/FileDescriptor;)V"), 2522 NATIVE_METHOD(Linux, ftruncate, "(Ljava/io/FileDescriptor;J)V"), 2523 NATIVE_METHOD(Linux, gai_strerror, "(I)Ljava/lang/String;"), 2524 NATIVE_METHOD(Linux, getegid, "()I"), 2525 NATIVE_METHOD(Linux, geteuid, "()I"), 2526 NATIVE_METHOD(Linux, getgid, "()I"), 2527 NATIVE_METHOD(Linux, getgroups, "()[I"), 2528 NATIVE_METHOD(Linux, getenv, "(Ljava/lang/String;)Ljava/lang/String;"), 2529 NATIVE_METHOD(Linux, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"), 2530 NATIVE_METHOD(Linux, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"), 2531 NATIVE_METHOD(Linux, getpgid, "(I)I"), 2532 NATIVE_METHOD(Linux, getpid, "()I"), 2533 NATIVE_METHOD(Linux, getppid, "()I"), 2534 NATIVE_METHOD(Linux, getpwnam, "(Ljava/lang/String;)Landroid/system/StructPasswd;"), 2535 NATIVE_METHOD(Linux, getpwuid, "(I)Landroid/system/StructPasswd;"), 2536 NATIVE_METHOD(Linux, getrlimit, "(I)Landroid/system/StructRlimit;"), 2537 NATIVE_METHOD(Linux, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"), 2538 NATIVE_METHOD(Linux, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"), 2539 NATIVE_METHOD(Linux, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"), 2540 NATIVE_METHOD(Linux, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"), 2541 NATIVE_METHOD(Linux, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;"), 2542 NATIVE_METHOD(Linux, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Landroid/system/StructTimeval;"), 2543 NATIVE_METHOD(Linux, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"), 2544 NATIVE_METHOD(Linux, gettid, "()I"), 2545 NATIVE_METHOD(Linux, getuid, "()I"), 2546 NATIVE_METHOD(Linux, getxattr, "(Ljava/lang/String;Ljava/lang/String;)[B"), 2547 NATIVE_METHOD(Linux, getifaddrs, "()[Landroid/system/StructIfaddrs;"), 2548 NATIVE_METHOD(Linux, if_indextoname, "(I)Ljava/lang/String;"), 2549 NATIVE_METHOD(Linux, if_nametoindex, "(Ljava/lang/String;)I"), 2550 NATIVE_METHOD(Linux, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"), 2551 NATIVE_METHOD(Linux, ioctlFlags, "(Ljava/io/FileDescriptor;Ljava/lang/String;)I"), 2552 NATIVE_METHOD(Linux, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"), 2553 NATIVE_METHOD(Linux, ioctlInt, "(Ljava/io/FileDescriptor;ILandroid/system/Int32Ref;)I"), 2554 NATIVE_METHOD(Linux, ioctlMTU, "(Ljava/io/FileDescriptor;Ljava/lang/String;)I"), 2555 NATIVE_METHOD(Linux, isatty, "(Ljava/io/FileDescriptor;)Z"), 2556 NATIVE_METHOD(Linux, kill, "(II)V"), 2557 NATIVE_METHOD(Linux, lchown, "(Ljava/lang/String;II)V"), 2558 NATIVE_METHOD(Linux, link, "(Ljava/lang/String;Ljava/lang/String;)V"), 2559 NATIVE_METHOD(Linux, listen, "(Ljava/io/FileDescriptor;I)V"), 2560 NATIVE_METHOD(Linux, listxattr, "(Ljava/lang/String;)[Ljava/lang/String;"), 2561 NATIVE_METHOD(Linux, lseek, "(Ljava/io/FileDescriptor;JI)J"), 2562 NATIVE_METHOD(Linux, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"), 2563 NATIVE_METHOD(Linux, mincore, "(JJ[B)V"), 2564 NATIVE_METHOD(Linux, mkdir, "(Ljava/lang/String;I)V"), 2565 NATIVE_METHOD(Linux, mkfifo, "(Ljava/lang/String;I)V"), 2566 NATIVE_METHOD(Linux, mlock, "(JJ)V"), 2567 NATIVE_METHOD(Linux, mmap, "(JJIILjava/io/FileDescriptor;J)J"), 2568 NATIVE_METHOD(Linux, msync, "(JJI)V"), 2569 NATIVE_METHOD(Linux, munlock, "(JJ)V"), 2570 NATIVE_METHOD(Linux, munmap, "(JJ)V"), 2571 NATIVE_METHOD(Linux, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"), 2572 NATIVE_METHOD(Linux, pipe2, "(I)[Ljava/io/FileDescriptor;"), 2573 NATIVE_METHOD(Linux, poll, "([Landroid/system/StructPollfd;I)I"), 2574 NATIVE_METHOD(Linux, posix_fallocate, "(Ljava/io/FileDescriptor;JJ)V"), 2575 NATIVE_METHOD(Linux, prctl, "(IJJJJ)I"), 2576 NATIVE_METHOD(Linux, preadBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"), 2577 NATIVE_METHOD(Linux, pwriteBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"), 2578 NATIVE_METHOD(Linux, readBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"), 2579 NATIVE_METHOD(Linux, readlink, "(Ljava/lang/String;)Ljava/lang/String;"), 2580 NATIVE_METHOD(Linux, realpath, "(Ljava/lang/String;)Ljava/lang/String;"), 2581 NATIVE_METHOD(Linux, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"), 2582 NATIVE_METHOD(Linux, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"), 2583 NATIVE_METHOD(Linux, remove, "(Ljava/lang/String;)V"), 2584 NATIVE_METHOD(Linux, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"), 2585 NATIVE_METHOD(Linux, rename, "(Ljava/lang/String;Ljava/lang/String;)V"), 2586 NATIVE_METHOD(Linux, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/system/Int64Ref;J)J"), 2587 NATIVE_METHOD(Linux, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"), 2588 NATIVE_METHOD_OVERLOAD(Linux, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/SocketAddress;)I", SocketAddress), 2589 NATIVE_METHOD(Linux, setegid, "(I)V"), 2590 NATIVE_METHOD(Linux, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"), 2591 NATIVE_METHOD(Linux, seteuid, "(I)V"), 2592 NATIVE_METHOD(Linux, setgid, "(I)V"), 2593 NATIVE_METHOD(Linux, setgroups, "([I)V"), 2594 NATIVE_METHOD(Linux, setpgid, "(II)V"), 2595 NATIVE_METHOD(Linux, setregid, "(II)V"), 2596 NATIVE_METHOD(Linux, setreuid, "(II)V"), 2597 NATIVE_METHOD(Linux, setsid, "()I"), 2598 NATIVE_METHOD(Linux, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"), 2599 NATIVE_METHOD(Linux, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"), 2600 NATIVE_METHOD(Linux, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"), 2601 NATIVE_METHOD(Linux, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"), 2602 NATIVE_METHOD(Linux, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupReq;)V"), 2603 NATIVE_METHOD(Linux, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"), 2604 NATIVE_METHOD(Linux, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"), 2605 NATIVE_METHOD(Linux, setuid, "(I)V"), 2606 NATIVE_METHOD(Linux, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"), 2607 NATIVE_METHOD(Linux, shutdown, "(Ljava/io/FileDescriptor;I)V"), 2608 NATIVE_METHOD(Linux, socket, "(III)Ljava/io/FileDescriptor;"), 2609 NATIVE_METHOD(Linux, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"), 2610 NATIVE_METHOD(Linux, splice, "(Ljava/io/FileDescriptor;Landroid/system/Int64Ref;Ljava/io/FileDescriptor;Landroid/system/Int64Ref;JI)J"), 2611 NATIVE_METHOD(Linux, stat, "(Ljava/lang/String;)Landroid/system/StructStat;"), 2612 NATIVE_METHOD(Linux, statvfs, "(Ljava/lang/String;)Landroid/system/StructStatVfs;"), 2613 NATIVE_METHOD(Linux, strerror, "(I)Ljava/lang/String;"), 2614 NATIVE_METHOD(Linux, strsignal, "(I)Ljava/lang/String;"), 2615 NATIVE_METHOD(Linux, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"), 2616 NATIVE_METHOD(Linux, sysconf, "(I)J"), 2617 NATIVE_METHOD(Linux, tcdrain, "(Ljava/io/FileDescriptor;)V"), 2618 NATIVE_METHOD(Linux, tcsendbreak, "(Ljava/io/FileDescriptor;I)V"), 2619 NATIVE_METHOD(Linux, umaskImpl, "(I)I"), 2620 NATIVE_METHOD(Linux, uname, "()Landroid/system/StructUtsname;"), 2621 NATIVE_METHOD(Linux, unlink, "(Ljava/lang/String;)V"), 2622 NATIVE_METHOD(Linux, unsetenv, "(Ljava/lang/String;)V"), 2623 NATIVE_METHOD(Linux, waitpid, "(ILandroid/system/Int32Ref;I)I"), 2624 NATIVE_METHOD(Linux, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"), 2625 NATIVE_METHOD(Linux, writev, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"), 2626}; 2627void register_libcore_io_Linux(JNIEnv* env) { 2628 // Note: it is safe to only cache the fields as boot classpath classes are never 2629 // unloaded. 2630 ScopedLocalRef<jclass> int32RefClass(env, env->FindClass("android/system/Int32Ref")); 2631 CHECK(int32RefClass != nullptr); 2632 int32RefValueFid = env->GetFieldID(int32RefClass.get(), "value", "I"); 2633 CHECK(int32RefValueFid != nullptr); 2634 2635 ScopedLocalRef<jclass> int64RefClass(env, env->FindClass("android/system/Int64Ref")); 2636 CHECK(int64RefClass != nullptr); 2637 int64RefValueFid = env->GetFieldID(int64RefClass.get(), "value", "J"); 2638 CHECK(int64RefValueFid != nullptr); 2639 2640 jniRegisterNativeMethods(env, "libcore/io/Linux", gMethods, NELEM(gMethods)); 2641} 2642