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