Home | History | Annotate | Download | only in native
      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 "Posix"
     18 
     19 #include "AsynchronousSocketCloseMonitor.h"
     20 #include "JNIHelp.h"
     21 #include "JniConstants.h"
     22 #include "JniException.h"
     23 #include "NetworkUtilities.h"
     24 #include "ScopedBytes.h"
     25 #include "ScopedLocalRef.h"
     26 #include "ScopedPrimitiveArray.h"
     27 #include "ScopedUtfChars.h"
     28 #include "StaticAssert.h"
     29 #include "UniquePtr.h"
     30 #include "toStringArray.h"
     31 
     32 #include <arpa/inet.h>
     33 #include <errno.h>
     34 #include <fcntl.h>
     35 #include <net/if.h>
     36 #include <netdb.h>
     37 #include <netinet/in.h>
     38 #include <netinet/in.h>
     39 #include <poll.h>
     40 #include <pwd.h>
     41 #include <signal.h>
     42 #include <stdlib.h>
     43 #include <sys/ioctl.h>
     44 #include <sys/mman.h>
     45 #include <sys/sendfile.h>
     46 #include <sys/socket.h>
     47 #include <sys/socket.h>
     48 #include <sys/stat.h>
     49 #include <sys/time.h>
     50 #include <sys/types.h>
     51 #include <sys/uio.h>
     52 #include <sys/utsname.h>
     53 #include <sys/vfs.h> // Bionic doesn't have <sys/statvfs.h>
     54 #include <sys/wait.h>
     55 #include <unistd.h>
     56 
     57 #define TO_JAVA_STRING(NAME, EXP) \
     58         jstring NAME = env->NewStringUTF(EXP); \
     59         if (NAME == NULL) return NULL;
     60 
     61 struct addrinfo_deleter {
     62     void operator()(addrinfo* p) const {
     63         if (p != NULL) { // bionic's freeaddrinfo(3) crashes when passed NULL.
     64             freeaddrinfo(p);
     65         }
     66     }
     67 };
     68 
     69 /**
     70  * Used to retry syscalls that can return EINTR. This differs from TEMP_FAILURE_RETRY in that
     71  * it also considers the case where the reason for failure is that another thread called
     72  * Socket.close.
     73  *
     74  * Assumes 'JNIEnv* env' and 'jobject javaFd' (which is a java.io.FileDescriptor) are in scope.
     75  *
     76  * Returns the result of 'exp', though a Java exception will be pending if the result is -1.
     77  *
     78  * Correct usage looks like this:
     79  *
     80  * void Posix_syscall(JNIEnv* env, jobject javaFd, ...) {
     81  *     ...
     82  *     int fd;
     83  *     NET_FAILURE_RETRY("syscall", syscall(fd, ...)); // Throws on error.
     84  * }
     85  */
     86 #define NET_FAILURE_RETRY(syscall_name, exp) ({ \
     87     typeof (exp) _rc = -1; \
     88     do { \
     89         { \
     90             fd = jniGetFDFromFileDescriptor(env, javaFd); \
     91             AsynchronousSocketCloseMonitor monitor(fd); \
     92             _rc = (exp); \
     93         } \
     94         if (_rc == -1) { \
     95             if (jniGetFDFromFileDescriptor(env, javaFd) == -1) { \
     96                 jniThrowException(env, "java/net/SocketException", "Socket closed"); \
     97                 break; \
     98             } else if (errno != EINTR) { \
     99                 throwErrnoException(env, syscall_name); \
    100                 break; \
    101             } \
    102         } \
    103     } while (_rc == -1); \
    104     _rc; })
    105 
    106 static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
    107         const char* functionName, int error) {
    108     jthrowable cause = NULL;
    109     if (env->ExceptionCheck()) {
    110         cause = env->ExceptionOccurred();
    111         env->ExceptionClear();
    112     }
    113 
    114     ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
    115     if (detailMessage.get() == NULL) {
    116         // Not really much we can do here. We're probably dead in the water,
    117         // but let's try to stumble on...
    118         env->ExceptionClear();
    119     }
    120 
    121     jobject exception;
    122     if (cause != NULL) {
    123         exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause);
    124     } else {
    125         exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error);
    126     }
    127     env->Throw(reinterpret_cast<jthrowable>(exception));
    128 }
    129 
    130 static void throwErrnoException(JNIEnv* env, const char* functionName) {
    131     int error = errno;
    132     static jmethodID ctor3 = env->GetMethodID(JniConstants::errnoExceptionClass,
    133             "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
    134     static jmethodID ctor2 = env->GetMethodID(JniConstants::errnoExceptionClass,
    135             "<init>", "(Ljava/lang/String;I)V");
    136     throwException(env, JniConstants::errnoExceptionClass, ctor3, ctor2, functionName, error);
    137 }
    138 
    139 static void throwGaiException(JNIEnv* env, const char* functionName, int error) {
    140     if (error == EAI_SYSTEM) {
    141         // EAI_SYSTEM means "look at errno instead", so we want our GaiException to have the
    142         // relevant ErrnoException as its cause.
    143         throwErrnoException(env, functionName);
    144         // Deliberately fall through to throw another exception...
    145     }
    146     static jmethodID ctor3 = env->GetMethodID(JniConstants::gaiExceptionClass,
    147             "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
    148     static jmethodID ctor2 = env->GetMethodID(JniConstants::gaiExceptionClass,
    149             "<init>", "(Ljava/lang/String;I)V");
    150     throwException(env, JniConstants::gaiExceptionClass, ctor3, ctor2, functionName, error);
    151 }
    152 
    153 template <typename rc_t>
    154 static rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) {
    155     if (rc == rc_t(-1)) {
    156         throwErrnoException(env, name);
    157     }
    158     return rc;
    159 }
    160 
    161 template <typename ScopedT>
    162 class IoVec {
    163 public:
    164     IoVec(JNIEnv* env, size_t bufferCount) : mEnv(env), mBufferCount(bufferCount) {
    165     }
    166 
    167     bool init(jobjectArray javaBuffers, jintArray javaOffsets, jintArray javaByteCounts) {
    168         // We can't delete our local references until after the I/O, so make sure we have room.
    169         if (mEnv->PushLocalFrame(mBufferCount + 16) < 0) {
    170             return false;
    171         }
    172         ScopedIntArrayRO offsets(mEnv, javaOffsets);
    173         if (offsets.get() == NULL) {
    174             return false;
    175         }
    176         ScopedIntArrayRO byteCounts(mEnv, javaByteCounts);
    177         if (byteCounts.get() == NULL) {
    178             return false;
    179         }
    180         // TODO: Linux actually has a 1024 buffer limit. glibc works around this, and we should too.
    181         // TODO: you can query the limit at runtime with sysconf(_SC_IOV_MAX).
    182         for (size_t i = 0; i < mBufferCount; ++i) {
    183             jobject buffer = mEnv->GetObjectArrayElement(javaBuffers, i); // We keep this local ref.
    184             mScopedBuffers.push_back(new ScopedT(mEnv, buffer));
    185             jbyte* ptr = const_cast<jbyte*>(mScopedBuffers.back()->get());
    186             if (ptr == NULL) {
    187                 return false;
    188             }
    189             struct iovec iov;
    190             iov.iov_base = reinterpret_cast<void*>(ptr + offsets[i]);
    191             iov.iov_len = byteCounts[i];
    192             mIoVec.push_back(iov);
    193         }
    194         return true;
    195     }
    196 
    197     ~IoVec() {
    198         for (size_t i = 0; i < mScopedBuffers.size(); ++i) {
    199             delete mScopedBuffers[i];
    200         }
    201         mEnv->PopLocalFrame(NULL);
    202     }
    203 
    204     iovec* get() {
    205         return &mIoVec[0];
    206     }
    207 
    208     size_t size() {
    209         return mBufferCount;
    210     }
    211 
    212 private:
    213     JNIEnv* mEnv;
    214     size_t mBufferCount;
    215     std::vector<iovec> mIoVec;
    216     std::vector<ScopedT*> mScopedBuffers;
    217 };
    218 
    219 static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage* ss) {
    220     // TODO: support AF_UNIX and AF_UNSPEC (and other families?)
    221     jint port;
    222     jobject inetAddress = sockaddrToInetAddress(env, ss, &port);
    223     if (inetAddress == NULL) {
    224         return NULL;
    225     }
    226     static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass, "<init>",
    227             "(Ljava/net/InetAddress;I)V");
    228     return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port);
    229 }
    230 
    231 static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) {
    232     TO_JAVA_STRING(pw_name, pw.pw_name);
    233     TO_JAVA_STRING(pw_dir, pw.pw_dir);
    234     TO_JAVA_STRING(pw_shell, pw.pw_shell);
    235     static jmethodID ctor = env->GetMethodID(JniConstants::structPasswdClass, "<init>",
    236             "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
    237     return env->NewObject(JniConstants::structPasswdClass, ctor,
    238             pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell);
    239 }
    240 
    241 static jobject makeStructStat(JNIEnv* env, const struct stat& sb) {
    242     static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>",
    243             "(JJIJIIJJJJJJJ)V");
    244     return env->NewObject(JniConstants::structStatClass, ctor,
    245             static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino),
    246             static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink),
    247             static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid),
    248             static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size),
    249             static_cast<jlong>(sb.st_atime), static_cast<jlong>(sb.st_mtime),
    250             static_cast<jlong>(sb.st_ctime), static_cast<jlong>(sb.st_blksize),
    251             static_cast<jlong>(sb.st_blocks));
    252 }
    253 
    254 static jobject makeStructStatFs(JNIEnv* env, const struct statfs& sb) {
    255     STATIC_ASSERT(sizeof(sb.f_bavail) == sizeof(jlong), statfs_not_64_bit);
    256     STATIC_ASSERT(sizeof(sb.f_bfree) == sizeof(jlong), statfs_not_64_bit);
    257     STATIC_ASSERT(sizeof(sb.f_blocks) == sizeof(jlong), statfs_not_64_bit);
    258 
    259     static jmethodID ctor = env->GetMethodID(JniConstants::structStatFsClass, "<init>",
    260             "(JJJJJJJJ)V");
    261     return env->NewObject(JniConstants::structStatFsClass, ctor, static_cast<jlong>(sb.f_bsize),
    262             static_cast<jlong>(sb.f_blocks), static_cast<jlong>(sb.f_bfree),
    263             static_cast<jlong>(sb.f_bavail), static_cast<jlong>(sb.f_files),
    264             static_cast<jlong>(sb.f_ffree), static_cast<jlong>(sb.f_namelen),
    265             static_cast<jlong>(sb.f_frsize));
    266 }
    267 
    268 static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
    269     static jmethodID ctor = env->GetMethodID(JniConstants::structLingerClass, "<init>", "(II)V");
    270     return env->NewObject(JniConstants::structLingerClass, ctor, l.l_onoff, l.l_linger);
    271 }
    272 
    273 static jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) {
    274     static jmethodID ctor = env->GetMethodID(JniConstants::structTimevalClass, "<init>", "(JJ)V");
    275     return env->NewObject(JniConstants::structTimevalClass, ctor,
    276             static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
    277 }
    278 
    279 static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
    280     TO_JAVA_STRING(sysname, buf.sysname);
    281     TO_JAVA_STRING(nodename, buf.nodename);
    282     TO_JAVA_STRING(release, buf.release);
    283     TO_JAVA_STRING(version, buf.version);
    284     TO_JAVA_STRING(machine, buf.machine);
    285     static jmethodID ctor = env->GetMethodID(JniConstants::structUtsnameClass, "<init>",
    286             "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
    287     return env->NewObject(JniConstants::structUtsnameClass, ctor,
    288             sysname, nodename, release, version, machine);
    289 };
    290 
    291 static bool fillIfreq(JNIEnv* env, jstring javaInterfaceName, struct ifreq& req) {
    292     ScopedUtfChars interfaceName(env, javaInterfaceName);
    293     if (interfaceName.c_str() == NULL) {
    294         return false;
    295     }
    296     memset(&req, 0, sizeof(req));
    297     strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name));
    298     req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
    299     return true;
    300 }
    301 
    302 static bool fillInetSocketAddress(JNIEnv* env, jint rc, jobject javaInetSocketAddress, const sockaddr_storage* ss) {
    303     if (rc == -1 || javaInetSocketAddress == NULL) {
    304         return true;
    305     }
    306     // Fill out the passed-in InetSocketAddress with the sender's IP address and port number.
    307     jint port;
    308     jobject sender = sockaddrToInetAddress(env, ss, &port);
    309     if (sender == NULL) {
    310         return false;
    311     }
    312     static jfieldID addressFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "addr", "Ljava/net/InetAddress;");
    313     static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "port", "I");
    314     env->SetObjectField(javaInetSocketAddress, addressFid, sender);
    315     env->SetIntField(javaInetSocketAddress, portFid, port);
    316     return true;
    317 }
    318 
    319 static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) {
    320     ScopedUtfChars path(env, javaPath);
    321     if (path.c_str() == NULL) {
    322         return NULL;
    323     }
    324     struct stat sb;
    325     int rc = isLstat ? TEMP_FAILURE_RETRY(lstat(path.c_str(), &sb))
    326                      : TEMP_FAILURE_RETRY(stat(path.c_str(), &sb));
    327     if (rc == -1) {
    328         throwErrnoException(env, isLstat ? "lstat" : "stat");
    329         return NULL;
    330     }
    331     return makeStructStat(env, sb);
    332 }
    333 
    334 class Passwd {
    335 public:
    336     Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
    337         mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
    338         if (mBufferSize == -1UL) {
    339             // We're probably on bionic, where 1KiB should be enough for anyone.
    340             // TODO: fix bionic to return 1024 like glibc.
    341             mBufferSize = 1024;
    342         }
    343         mBuffer.reset(new char[mBufferSize]);
    344     }
    345 
    346     jobject getpwnam(const char* name) {
    347         return process("getpwnam_r", getpwnam_r(name, &mPwd, mBuffer.get(), mBufferSize, &mResult));
    348     }
    349 
    350     jobject getpwuid(uid_t uid) {
    351         return process("getpwuid_r", getpwuid_r(uid, &mPwd, mBuffer.get(), mBufferSize, &mResult));
    352     }
    353 
    354     struct passwd* get() {
    355         return mResult;
    356     }
    357 
    358 private:
    359     jobject process(const char* syscall, int error) {
    360         if (mResult == NULL) {
    361             errno = error;
    362             throwErrnoException(mEnv, syscall);
    363             return NULL;
    364         }
    365         return makeStructPasswd(mEnv, *mResult);
    366     }
    367 
    368     JNIEnv* mEnv;
    369     UniquePtr<char[]> mBuffer;
    370     size_t mBufferSize;
    371     struct passwd mPwd;
    372     struct passwd* mResult;
    373 };
    374 
    375 static jobject Posix_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaInetSocketAddress) {
    376     sockaddr_storage ss;
    377     socklen_t sl = sizeof(ss);
    378     memset(&ss, 0, sizeof(ss));
    379     int fd;
    380     sockaddr* peer = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
    381     socklen_t* peerLength = (javaInetSocketAddress != NULL) ? &sl : 0;
    382     jint clientFd = NET_FAILURE_RETRY("accept", accept(fd, peer, peerLength));
    383     if (clientFd == -1 || !fillInetSocketAddress(env, clientFd, javaInetSocketAddress, &ss)) {
    384         close(clientFd);
    385         return NULL;
    386     }
    387     return (clientFd != -1) ? jniCreateFileDescriptor(env, clientFd) : NULL;
    388 }
    389 
    390 static jboolean Posix_access(JNIEnv* env, jobject, jstring javaPath, jint mode) {
    391     ScopedUtfChars path(env, javaPath);
    392     if (path.c_str() == NULL) {
    393         return JNI_FALSE;
    394     }
    395     int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode));
    396     if (rc == -1) {
    397         throwErrnoException(env, "access");
    398     }
    399     return (rc == 0);
    400 }
    401 
    402 static void Posix_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
    403     sockaddr_storage ss;
    404     if (!inetAddressToSockaddr(env, javaAddress, port, &ss)) {
    405         return;
    406     }
    407     int fd;
    408     const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
    409     NET_FAILURE_RETRY("bind", bind(fd, sa, sizeof(sockaddr_storage)));
    410 }
    411 
    412 static void Posix_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) {
    413     ScopedUtfChars path(env, javaPath);
    414     if (path.c_str() == NULL) {
    415         return;
    416     }
    417     throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode)));
    418 }
    419 
    420 static void Posix_close(JNIEnv* env, jobject, jobject javaFd) {
    421     // Get the FileDescriptor's 'fd' field and clear it.
    422     // We need to do this before we can throw an IOException (http://b/3222087).
    423     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    424     jniSetFileDescriptorOfFD(env, javaFd, -1);
    425 
    426     // Even if close(2) fails with EINTR, the fd will have been closed.
    427     // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
    428     // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
    429     throwIfMinusOne(env, "close", close(fd));
    430 }
    431 
    432 static void Posix_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
    433     sockaddr_storage ss;
    434     if (!inetAddressToSockaddr(env, javaAddress, port, &ss)) {
    435         return;
    436     }
    437     int fd;
    438     const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
    439     NET_FAILURE_RETRY("connect", connect(fd, sa, sizeof(sockaddr_storage)));
    440 }
    441 
    442 static jobject Posix_dup(JNIEnv* env, jobject, jobject javaOldFd) {
    443     int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
    444     int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd)));
    445     return (newFd != -1) ? jniCreateFileDescriptor(env, newFd) : NULL;
    446 }
    447 
    448 static jobject Posix_dup2(JNIEnv* env, jobject, jobject javaOldFd, jint newFd) {
    449     int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
    450     int fd = throwIfMinusOne(env, "dup2", TEMP_FAILURE_RETRY(dup2(oldFd, newFd)));
    451     return (fd != -1) ? jniCreateFileDescriptor(env, fd) : NULL;
    452 }
    453 
    454 static jobjectArray Posix_environ(JNIEnv* env, jobject) {
    455     extern char** environ; // Standard, but not in any header file.
    456     return toStringArray(env, environ);
    457 }
    458 
    459 static jint Posix_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) {
    460     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    461     return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd)));
    462 }
    463 
    464 static jint Posix_fcntlLong(JNIEnv* env, jobject, jobject javaFd, jint cmd, jlong arg) {
    465     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    466     return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
    467 }
    468 
    469 static jint Posix_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) {
    470     static jfieldID typeFid = env->GetFieldID(JniConstants::structFlockClass, "l_type", "S");
    471     static jfieldID whenceFid = env->GetFieldID(JniConstants::structFlockClass, "l_whence", "S");
    472     static jfieldID startFid = env->GetFieldID(JniConstants::structFlockClass, "l_start", "J");
    473     static jfieldID lenFid = env->GetFieldID(JniConstants::structFlockClass, "l_len", "J");
    474     static jfieldID pidFid = env->GetFieldID(JniConstants::structFlockClass, "l_pid", "I");
    475 
    476     struct flock64 lock;
    477     memset(&lock, 0, sizeof(lock));
    478     lock.l_type = env->GetShortField(javaFlock, typeFid);
    479     lock.l_whence = env->GetShortField(javaFlock, whenceFid);
    480     lock.l_start = env->GetLongField(javaFlock, startFid);
    481     lock.l_len = env->GetLongField(javaFlock, lenFid);
    482     lock.l_pid = env->GetIntField(javaFlock, pidFid);
    483 
    484     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    485     int rc = throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, &lock)));
    486     if (rc != -1) {
    487         env->SetShortField(javaFlock, typeFid, lock.l_type);
    488         env->SetShortField(javaFlock, whenceFid, lock.l_whence);
    489         env->SetLongField(javaFlock, startFid, lock.l_start);
    490         env->SetLongField(javaFlock, lenFid, lock.l_len);
    491         env->SetIntField(javaFlock, pidFid, lock.l_pid);
    492     }
    493     return rc;
    494 }
    495 
    496 static void Posix_fdatasync(JNIEnv* env, jobject, jobject javaFd) {
    497     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    498     throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd)));
    499 }
    500 
    501 static jobject Posix_fstat(JNIEnv* env, jobject, jobject javaFd) {
    502     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    503     struct stat sb;
    504     int rc = TEMP_FAILURE_RETRY(fstat(fd, &sb));
    505     if (rc == -1) {
    506         throwErrnoException(env, "fstat");
    507         return NULL;
    508     }
    509     return makeStructStat(env, sb);
    510 }
    511 
    512 static jobject Posix_fstatfs(JNIEnv* env, jobject, jobject javaFd) {
    513     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    514     struct statfs sb;
    515     int rc = TEMP_FAILURE_RETRY(fstatfs(fd, &sb));
    516     if (rc == -1) {
    517         throwErrnoException(env, "fstatfs");
    518         return NULL;
    519     }
    520     return makeStructStatFs(env, sb);
    521 }
    522 
    523 static void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) {
    524     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    525     throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd)));
    526 }
    527 
    528 static void Posix_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) {
    529     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    530     throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length)));
    531 }
    532 
    533 static jstring Posix_gai_strerror(JNIEnv* env, jobject, jint error) {
    534     return env->NewStringUTF(gai_strerror(error));
    535 }
    536 
    537 static jobjectArray Posix_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, jobject javaHints) {
    538     ScopedUtfChars node(env, javaNode);
    539     if (node.c_str() == NULL) {
    540         return NULL;
    541     }
    542 
    543     static jfieldID flagsFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_flags", "I");
    544     static jfieldID familyFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_family", "I");
    545     static jfieldID socktypeFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_socktype", "I");
    546     static jfieldID protocolFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_protocol", "I");
    547 
    548     addrinfo hints;
    549     memset(&hints, 0, sizeof(hints));
    550     hints.ai_flags = env->GetIntField(javaHints, flagsFid);
    551     hints.ai_family = env->GetIntField(javaHints, familyFid);
    552     hints.ai_socktype = env->GetIntField(javaHints, socktypeFid);
    553     hints.ai_protocol = env->GetIntField(javaHints, protocolFid);
    554 
    555     addrinfo* addressList = NULL;
    556     int rc = getaddrinfo(node.c_str(), NULL, &hints, &addressList);
    557     UniquePtr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
    558     if (rc != 0) {
    559         throwGaiException(env, "getaddrinfo", rc);
    560         return NULL;
    561     }
    562 
    563     // Count results so we know how to size the output array.
    564     int addressCount = 0;
    565     for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
    566         if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
    567             ++addressCount;
    568         } else {
    569             LOGE("getaddrinfo unexpected ai_family %i", ai->ai_family);
    570         }
    571     }
    572     if (addressCount == 0) {
    573         return NULL;
    574     }
    575 
    576     // Prepare output array.
    577     jobjectArray result = env->NewObjectArray(addressCount, JniConstants::inetAddressClass, NULL);
    578     if (result == NULL) {
    579         return NULL;
    580     }
    581 
    582     // Examine returned addresses one by one, save them in the output array.
    583     int index = 0;
    584     for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
    585         if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
    586             // Unknown address family. Skip this address.
    587             LOGE("getaddrinfo unexpected ai_family %i", ai->ai_family);
    588             continue;
    589         }
    590 
    591         // Convert each IP address into a Java byte array.
    592         sockaddr_storage* address = reinterpret_cast<sockaddr_storage*>(ai->ai_addr);
    593         ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL));
    594         if (inetAddress.get() == NULL) {
    595             return NULL;
    596         }
    597         env->SetObjectArrayElement(result, index, inetAddress.get());
    598         ++index;
    599     }
    600     return result;
    601 }
    602 
    603 static jint Posix_getegid(JNIEnv*, jobject) {
    604     return getegid();
    605 }
    606 
    607 static jint Posix_geteuid(JNIEnv*, jobject) {
    608     return geteuid();
    609 }
    610 
    611 static jint Posix_getgid(JNIEnv*, jobject) {
    612     return getgid();
    613 }
    614 
    615 static jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) {
    616     ScopedUtfChars name(env, javaName);
    617     if (name.c_str() == NULL) {
    618         return NULL;
    619     }
    620     return env->NewStringUTF(getenv(name.c_str()));
    621 }
    622 
    623 static jstring Posix_getnameinfo(JNIEnv* env, jobject, jobject javaAddress, jint flags) {
    624     sockaddr_storage ss;
    625     if (!inetAddressToSockaddrVerbatim(env, javaAddress, 0, &ss)) {
    626         return NULL;
    627     }
    628     // TODO: bionic's getnameinfo(3) seems to want its length parameter to be exactly
    629     // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
    630     // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
    631     // then remove this hack.
    632     socklen_t size = (ss.ss_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
    633     char buf[NI_MAXHOST]; // NI_MAXHOST is longer than INET6_ADDRSTRLEN.
    634     int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), size, buf, sizeof(buf), NULL, 0, flags);
    635     if (rc != 0) {
    636         throwGaiException(env, "getnameinfo", rc);
    637         return NULL;
    638     }
    639     return env->NewStringUTF(buf);
    640 }
    641 
    642 static jint Posix_getpid(JNIEnv*, jobject) {
    643     return getpid();
    644 }
    645 
    646 static jint Posix_getppid(JNIEnv*, jobject) {
    647     return getppid();
    648 }
    649 
    650 static jobject Posix_getpwnam(JNIEnv* env, jobject, jstring javaName) {
    651     ScopedUtfChars name(env, javaName);
    652     if (name.c_str() == NULL) {
    653         return NULL;
    654     }
    655     return Passwd(env).getpwnam(name.c_str());
    656 }
    657 
    658 static jobject Posix_getpwuid(JNIEnv* env, jobject, jint uid) {
    659     return Passwd(env).getpwuid(uid);
    660 }
    661 
    662 static jobject Posix_getsockname(JNIEnv* env, jobject, jobject javaFd) {
    663     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    664     sockaddr_storage ss;
    665     sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
    666     socklen_t byteCount = sizeof(ss);
    667     memset(&ss, 0, byteCount);
    668     int rc = TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount));
    669     if (rc == -1) {
    670         throwErrnoException(env, "getsockname");
    671         return NULL;
    672     }
    673     return makeSocketAddress(env, &ss);
    674 }
    675 
    676 static jint Posix_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
    677     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    678     u_char result = 0;
    679     socklen_t size = sizeof(result);
    680     throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
    681     return result;
    682 }
    683 
    684 static jobject Posix_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
    685     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    686     sockaddr_storage ss;
    687     memset(&ss, 0, sizeof(ss));
    688     ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF.
    689     sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
    690     socklen_t size = sizeof(sa->sin_addr);
    691     int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size));
    692     if (rc == -1) {
    693         throwErrnoException(env, "getsockopt");
    694         return NULL;
    695     }
    696     return sockaddrToInetAddress(env, &ss, NULL);
    697 }
    698 
    699 static jint Posix_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
    700     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    701     jint result = 0;
    702     socklen_t size = sizeof(result);
    703     throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
    704     return result;
    705 }
    706 
    707 static jobject Posix_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
    708     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    709     struct linger l;
    710     socklen_t size = sizeof(l);
    711     memset(&l, 0, size);
    712     int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size));
    713     if (rc == -1) {
    714         throwErrnoException(env, "getsockopt");
    715         return NULL;
    716     }
    717     return makeStructLinger(env, l);
    718 }
    719 
    720 static jobject Posix_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
    721     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    722     struct timeval tv;
    723     socklen_t size = sizeof(tv);
    724     memset(&tv, 0, size);
    725     int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size));
    726     if (rc == -1) {
    727         throwErrnoException(env, "getsockopt");
    728         return NULL;
    729     }
    730     return makeStructTimeval(env, tv);
    731 }
    732 
    733 static jint Posix_getuid(JNIEnv*, jobject) {
    734     return getuid();
    735 }
    736 
    737 static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) {
    738     char buf[IF_NAMESIZE];
    739     char* name = if_indextoname(index, buf);
    740     // if_indextoname(3) returns NULL on failure, which will come out of NewStringUTF unscathed.
    741     // There's no useful information in errno, so we don't bother throwing. Callers can null-check.
    742     return env->NewStringUTF(name);
    743 }
    744 
    745 static jobject Posix_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) {
    746     ScopedUtfChars name(env, javaName);
    747     if (name.c_str() == NULL) {
    748         return NULL;
    749     }
    750     sockaddr_storage ss;
    751     memset(&ss, 0, sizeof(ss));
    752     // sockaddr_in and sockaddr_in6 are at the same address, so we can use either here.
    753     void* dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr;
    754     if (inet_pton(family, name.c_str(), dst) != 1) {
    755         return NULL;
    756     }
    757     ss.ss_family = family;
    758     return sockaddrToInetAddress(env, &ss, NULL);
    759 }
    760 
    761 static jobject Posix_ioctlInetAddress(JNIEnv* env, jobject, jobject javaFd, jint cmd, jstring javaInterfaceName) {
    762     struct ifreq req;
    763     if (!fillIfreq(env, javaInterfaceName, req)) {
    764         return NULL;
    765     }
    766     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    767     int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &req)));
    768     if (rc == -1) {
    769         return NULL;
    770     }
    771     return sockaddrToInetAddress(env, reinterpret_cast<sockaddr_storage*>(&req.ifr_addr), NULL);
    772 }
    773 
    774 static jint Posix_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) {
    775     // This is complicated because ioctls may return their result by updating their argument
    776     // or via their return value, so we need to support both.
    777     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    778     static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
    779     jint arg = env->GetIntField(javaArg, valueFid);
    780     int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &arg)));
    781     if (!env->ExceptionCheck()) {
    782         env->SetIntField(javaArg, valueFid, arg);
    783     }
    784     return rc;
    785 }
    786 
    787 static jboolean Posix_isatty(JNIEnv* env, jobject, jobject javaFd) {
    788     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    789     return TEMP_FAILURE_RETRY(isatty(fd)) == 0;
    790 }
    791 
    792 static void Posix_kill(JNIEnv* env, jobject, jint pid, jint sig) {
    793     throwIfMinusOne(env, "kill", TEMP_FAILURE_RETRY(kill(pid, sig)));
    794 }
    795 
    796 static void Posix_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog) {
    797     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    798     throwIfMinusOne(env, "listen", TEMP_FAILURE_RETRY(listen(fd, backlog)));
    799 }
    800 
    801 static jlong Posix_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) {
    802     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    803     return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)));
    804 }
    805 
    806 static jobject Posix_lstat(JNIEnv* env, jobject, jstring javaPath) {
    807     return doStat(env, javaPath, true);
    808 }
    809 
    810 static void Posix_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) {
    811     ScopedByteArrayRW vector(env, javaVector);
    812     if (vector.get() == NULL) {
    813         return;
    814     }
    815     void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    816     unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get());
    817     throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec)));
    818 }
    819 
    820 static void Posix_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) {
    821     ScopedUtfChars path(env, javaPath);
    822     if (path.c_str() == NULL) {
    823         return;
    824     }
    825     throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode)));
    826 }
    827 
    828 static void Posix_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
    829     void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    830     throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount)));
    831 }
    832 
    833 static jlong Posix_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) {
    834     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    835     void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    836     void* ptr = mmap(suggestedPtr, byteCount, prot, flags, fd, offset);
    837     if (ptr == MAP_FAILED) {
    838         throwErrnoException(env, "mmap");
    839     }
    840     return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
    841 }
    842 
    843 static void Posix_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) {
    844     void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    845     throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags)));
    846 }
    847 
    848 static void Posix_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
    849     void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    850     throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount)));
    851 }
    852 
    853 static void Posix_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) {
    854     void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
    855     throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount)));
    856 }
    857 
    858 static jobject Posix_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) {
    859     ScopedUtfChars path(env, javaPath);
    860     if (path.c_str() == NULL) {
    861         return NULL;
    862     }
    863     int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
    864     return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
    865 }
    866 
    867 static jobjectArray Posix_pipe(JNIEnv* env, jobject) {
    868     int fds[2];
    869     throwIfMinusOne(env, "pipe", TEMP_FAILURE_RETRY(pipe(&fds[0])));
    870     jobjectArray result = env->NewObjectArray(2, JniConstants::fileDescriptorClass, NULL);
    871     if (result == NULL) {
    872         return NULL;
    873     }
    874     for (int i = 0; i < 2; ++i) {
    875         ScopedLocalRef<jobject> fd(env, jniCreateFileDescriptor(env, fds[i]));
    876         if (fd.get() == NULL) {
    877             return NULL;
    878         }
    879         env->SetObjectArrayElement(result, i, fd.get());
    880         if (env->ExceptionCheck()) {
    881             return NULL;
    882         }
    883     }
    884     return result;
    885 }
    886 
    887 static jint Posix_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) {
    888     static jfieldID fdFid = env->GetFieldID(JniConstants::structPollfdClass, "fd", "Ljava/io/FileDescriptor;");
    889     static jfieldID eventsFid = env->GetFieldID(JniConstants::structPollfdClass, "events", "S");
    890     static jfieldID reventsFid = env->GetFieldID(JniConstants::structPollfdClass, "revents", "S");
    891 
    892     // Turn the Java libcore.io.StructPollfd[] into a C++ struct pollfd[].
    893     size_t arrayLength = env->GetArrayLength(javaStructs);
    894     UniquePtr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
    895     memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength);
    896     size_t count = 0; // Some trailing array elements may be irrelevant. (See below.)
    897     for (size_t i = 0; i < arrayLength; ++i) {
    898         ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
    899         if (javaStruct.get() == NULL) {
    900             break; // We allow trailing nulls in the array for caller convenience.
    901         }
    902         ScopedLocalRef<jobject> javaFd(env, env->GetObjectField(javaStruct.get(), fdFid));
    903         if (javaFd.get() == NULL) {
    904             break; // We also allow callers to just clear the fd field (this is what Selector does).
    905         }
    906         fds[count].fd = jniGetFDFromFileDescriptor(env, javaFd.get());
    907         fds[count].events = env->GetShortField(javaStruct.get(), eventsFid);
    908         ++count;
    909     }
    910 
    911     int rc = TEMP_FAILURE_RETRY(poll(fds.get(), count, timeoutMs));
    912     if (rc == -1) {
    913         throwErrnoException(env, "poll");
    914         return -1;
    915     }
    916 
    917     // Update the revents fields in the Java libcore.io.StructPollfd[].
    918     for (size_t i = 0; i < count; ++i) {
    919         ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
    920         if (javaStruct.get() == NULL) {
    921             return -1;
    922         }
    923         env->SetShortField(javaStruct.get(), reventsFid, fds[i].revents);
    924     }
    925     return rc;
    926 }
    927 
    928 static jint Posix_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
    929     ScopedBytesRW bytes(env, javaBytes);
    930     if (bytes.get() == NULL) {
    931         return -1;
    932     }
    933     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    934     return throwIfMinusOne(env, "pread", TEMP_FAILURE_RETRY(pread64(fd, bytes.get() + byteOffset, byteCount, offset)));
    935 }
    936 
    937 static jint Posix_pwriteBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount, jlong offset) {
    938     ScopedBytesRO bytes(env, javaBytes);
    939     if (bytes.get() == NULL) {
    940         return -1;
    941     }
    942     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    943     return throwIfMinusOne(env, "pwrite", TEMP_FAILURE_RETRY(pwrite64(fd, bytes.get() + byteOffset, byteCount, offset)));
    944 }
    945 
    946 static jint Posix_readBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {
    947     ScopedBytesRW bytes(env, javaBytes);
    948     if (bytes.get() == NULL) {
    949         return -1;
    950     }
    951     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    952     return throwIfMinusOne(env, "read", TEMP_FAILURE_RETRY(read(fd, bytes.get() + byteOffset, byteCount)));
    953 }
    954 
    955 static jint Posix_readv(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
    956     IoVec<ScopedBytesRW> ioVec(env, env->GetArrayLength(buffers));
    957     if (!ioVec.init(buffers, offsets, byteCounts)) {
    958         return -1;
    959     }
    960     int fd = jniGetFDFromFileDescriptor(env, javaFd);
    961     return throwIfMinusOne(env, "readv", TEMP_FAILURE_RETRY(readv(fd, ioVec.get(), ioVec.size())));
    962 }
    963 
    964 static jint Posix_recvfromBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetSocketAddress) {
    965     ScopedBytesRW bytes(env, javaBytes);
    966     if (bytes.get() == NULL) {
    967         return -1;
    968     }
    969     sockaddr_storage ss;
    970     socklen_t sl = sizeof(ss);
    971     memset(&ss, 0, sizeof(ss));
    972     int fd;
    973     sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
    974     socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
    975     jint recvCount = NET_FAILURE_RETRY("recvfrom", recvfrom(fd, bytes.get() + byteOffset, byteCount, flags, from, fromLength));
    976     fillInetSocketAddress(env, recvCount, javaInetSocketAddress, &ss);
    977     return recvCount;
    978 }
    979 
    980 static void Posix_remove(JNIEnv* env, jobject, jstring javaPath) {
    981     ScopedUtfChars path(env, javaPath);
    982     if (path.c_str() == NULL) {
    983         return;
    984     }
    985     throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str())));
    986 }
    987 
    988 static void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
    989     ScopedUtfChars oldPath(env, javaOldPath);
    990     if (oldPath.c_str() == NULL) {
    991         return;
    992     }
    993     ScopedUtfChars newPath(env, javaNewPath);
    994     if (newPath.c_str() == NULL) {
    995         return;
    996     }
    997     throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str())));
    998 }
    999 
   1000 static jlong Posix_sendfile(JNIEnv* env, jobject, jobject javaOutFd, jobject javaInFd, jobject javaOffset, jlong byteCount) {
   1001     int outFd = jniGetFDFromFileDescriptor(env, javaOutFd);
   1002     int inFd = jniGetFDFromFileDescriptor(env, javaInFd);
   1003     static jfieldID valueFid = env->GetFieldID(JniConstants::mutableLongClass, "value", "J");
   1004     off_t offset = 0;
   1005     off_t* offsetPtr = NULL;
   1006     if (javaOffset != NULL) {
   1007         // TODO: fix bionic so we can have a 64-bit off_t!
   1008         offset = env->GetLongField(javaOffset, valueFid);
   1009         offsetPtr = &offset;
   1010     }
   1011     jlong result = throwIfMinusOne(env, "sendfile", TEMP_FAILURE_RETRY(sendfile(outFd, inFd, offsetPtr, byteCount)));
   1012     if (javaOffset != NULL) {
   1013         env->SetLongField(javaOffset, valueFid, offset);
   1014     }
   1015     return result;
   1016 }
   1017 
   1018 static jint Posix_sendtoBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetAddress, jint port) {
   1019     ScopedBytesRO bytes(env, javaBytes);
   1020     if (bytes.get() == NULL) {
   1021         return -1;
   1022     }
   1023     sockaddr_storage ss;
   1024     if (javaInetAddress != NULL && !inetAddressToSockaddr(env, javaInetAddress, port, &ss)) {
   1025         return -1;
   1026     }
   1027     int fd;
   1028     const sockaddr* to = (javaInetAddress != NULL) ? reinterpret_cast<const sockaddr*>(&ss) : NULL;
   1029     socklen_t toLength = (javaInetAddress != NULL) ? sizeof(ss) : 0;
   1030     return NET_FAILURE_RETRY("sendto", sendto(fd, bytes.get() + byteOffset, byteCount, flags, to, toLength));
   1031 }
   1032 
   1033 static void Posix_setegid(JNIEnv* env, jobject, jint egid) {
   1034     throwIfMinusOne(env, "setegid", TEMP_FAILURE_RETRY(setegid(egid)));
   1035 }
   1036 
   1037 static void Posix_seteuid(JNIEnv* env, jobject, jint euid) {
   1038     throwIfMinusOne(env, "seteuid", TEMP_FAILURE_RETRY(seteuid(euid)));
   1039 }
   1040 
   1041 static void Posix_setgid(JNIEnv* env, jobject, jint gid) {
   1042     throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
   1043 }
   1044 
   1045 static void Posix_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
   1046     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1047     u_char byte = value;
   1048     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte))));
   1049 }
   1050 
   1051 static void Posix_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring javaInterfaceName) {
   1052     struct ifreq req;
   1053     if (!fillIfreq(env, javaInterfaceName, req)) {
   1054         return;
   1055     }
   1056     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1057     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
   1058 }
   1059 
   1060 static void Posix_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
   1061     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1062     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
   1063 }
   1064 
   1065 static void Posix_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
   1066     ip_mreqn req;
   1067     memset(&req, 0, sizeof(req));
   1068     req.imr_ifindex = value;
   1069     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1070     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
   1071 }
   1072 
   1073 static void Posix_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) {
   1074     struct group_req req;
   1075     memset(&req, 0, sizeof(req));
   1076 
   1077     static jfieldID grInterfaceFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_interface", "I");
   1078     req.gr_interface = env->GetIntField(javaGroupReq, grInterfaceFid);
   1079     // Get the IPv4 or IPv6 multicast address to join or leave.
   1080     static jfieldID grGroupFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_group", "Ljava/net/InetAddress;");
   1081     ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupReq, grGroupFid));
   1082     if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, &req.gr_group)) {
   1083         return;
   1084     }
   1085 
   1086     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1087     int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
   1088     if (rc == -1 && errno == EINVAL) {
   1089         // Maybe we're a 32-bit binary talking to a 64-bit kernel?
   1090         // glibc doesn't automatically handle this.
   1091         struct GCC_HIDDEN group_req64 {
   1092             uint32_t gr_interface;
   1093             uint32_t my_padding;
   1094             sockaddr_storage gr_group;
   1095         };
   1096         group_req64 req64;
   1097         req64.gr_interface = req.gr_interface;
   1098         memcpy(&req64.gr_group, &req.gr_group, sizeof(req.gr_group));
   1099         rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
   1100     }
   1101     throwIfMinusOne(env, "setsockopt", rc);
   1102 }
   1103 
   1104 static void Posix_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) {
   1105     static jfieldID lOnoffFid = env->GetFieldID(JniConstants::structLingerClass, "l_onoff", "I");
   1106     static jfieldID lLingerFid = env->GetFieldID(JniConstants::structLingerClass, "l_linger", "I");
   1107     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1108     struct linger value;
   1109     value.l_onoff = env->GetIntField(javaLinger, lOnoffFid);
   1110     value.l_linger = env->GetIntField(javaLinger, lLingerFid);
   1111     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
   1112 }
   1113 
   1114 static void Posix_setsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaTimeval) {
   1115     static jfieldID tvSecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_sec", "J");
   1116     static jfieldID tvUsecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_usec", "J");
   1117     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1118     struct timeval value;
   1119     value.tv_sec = env->GetLongField(javaTimeval, tvSecFid);
   1120     value.tv_usec = env->GetLongField(javaTimeval, tvUsecFid);
   1121     throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
   1122 }
   1123 
   1124 static void Posix_setuid(JNIEnv* env, jobject, jint uid) {
   1125     throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid)));
   1126 }
   1127 
   1128 static void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
   1129     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1130     throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how)));
   1131 }
   1132 
   1133 static jobject Posix_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
   1134     int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
   1135     return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
   1136 }
   1137 
   1138 static jobject Posix_stat(JNIEnv* env, jobject, jstring javaPath) {
   1139     return doStat(env, javaPath, false);
   1140 }
   1141 
   1142 static jobject Posix_statfs(JNIEnv* env, jobject, jstring javaPath) {
   1143     ScopedUtfChars path(env, javaPath);
   1144     if (path.c_str() == NULL) {
   1145         return NULL;
   1146     }
   1147     struct statfs sb;
   1148     int rc = TEMP_FAILURE_RETRY(statfs(path.c_str(), &sb));
   1149     if (rc == -1) {
   1150         throwErrnoException(env, "statfs");
   1151         return NULL;
   1152     }
   1153     return makeStructStatFs(env, sb);
   1154 }
   1155 
   1156 static jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) {
   1157     char buffer[BUFSIZ];
   1158     const char* message = jniStrError(errnum, buffer, sizeof(buffer));
   1159     return env->NewStringUTF(message);
   1160 }
   1161 
   1162 static void Posix_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
   1163     ScopedUtfChars oldPath(env, javaOldPath);
   1164     if (oldPath.c_str() == NULL) {
   1165         return;
   1166     }
   1167     ScopedUtfChars newPath(env, javaNewPath);
   1168     if (newPath.c_str() == NULL) {
   1169         return;
   1170     }
   1171     throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str())));
   1172 }
   1173 
   1174 static jlong Posix_sysconf(JNIEnv* env, jobject, jint name) {
   1175     // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward.
   1176     errno = 0;
   1177     long result = sysconf(name);
   1178     if (result == -1L && errno == EINVAL) {
   1179         throwErrnoException(env, "sysconf");
   1180     }
   1181     return result;
   1182 }
   1183 
   1184 static jobject Posix_uname(JNIEnv* env, jobject) {
   1185     struct utsname buf;
   1186     if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) {
   1187         return NULL; // Can't happen.
   1188     }
   1189     return makeStructUtsname(env, buf);
   1190 }
   1191 
   1192 static jint Posix_waitpid(JNIEnv* env, jobject, jint pid, jobject javaStatus, jint options) {
   1193     int status;
   1194     int rc = throwIfMinusOne(env, "waitpid", TEMP_FAILURE_RETRY(waitpid(pid, &status, options)));
   1195     if (rc != -1) {
   1196         static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
   1197         env->SetIntField(javaStatus, valueFid, status);
   1198     }
   1199     return rc;
   1200 }
   1201 
   1202 static jint Posix_writeBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount) {
   1203     ScopedBytesRO bytes(env, javaBytes);
   1204     if (bytes.get() == NULL) {
   1205         return -1;
   1206     }
   1207     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1208     return throwIfMinusOne(env, "write", TEMP_FAILURE_RETRY(write(fd, bytes.get() + byteOffset, byteCount)));
   1209 }
   1210 
   1211 static jint Posix_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
   1212     IoVec<ScopedBytesRO> ioVec(env, env->GetArrayLength(buffers));
   1213     if (!ioVec.init(buffers, offsets, byteCounts)) {
   1214         return -1;
   1215     }
   1216     int fd = jniGetFDFromFileDescriptor(env, javaFd);
   1217     return throwIfMinusOne(env, "writev", TEMP_FAILURE_RETRY(writev(fd, ioVec.get(), ioVec.size())));
   1218 }
   1219 
   1220 static JNINativeMethod gMethods[] = {
   1221     NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/InetSocketAddress;)Ljava/io/FileDescriptor;"),
   1222     NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"),
   1223     NATIVE_METHOD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
   1224     NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"),
   1225     NATIVE_METHOD(Posix, close, "(Ljava/io/FileDescriptor;)V"),
   1226     NATIVE_METHOD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
   1227     NATIVE_METHOD(Posix, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"),
   1228     NATIVE_METHOD(Posix, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"),
   1229     NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"),
   1230     NATIVE_METHOD(Posix, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"),
   1231     NATIVE_METHOD(Posix, fcntlLong, "(Ljava/io/FileDescriptor;IJ)I"),
   1232     NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILlibcore/io/StructFlock;)I"),
   1233     NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"),
   1234     NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStat;"),
   1235     NATIVE_METHOD(Posix, fstatfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatFs;"),
   1236     NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
   1237     NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
   1238     NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"),
   1239     NATIVE_METHOD(Posix, getaddrinfo, "(Ljava/lang/String;Llibcore/io/StructAddrinfo;)[Ljava/net/InetAddress;"),
   1240     NATIVE_METHOD(Posix, getegid, "()I"),
   1241     NATIVE_METHOD(Posix, geteuid, "()I"),
   1242     NATIVE_METHOD(Posix, getgid, "()I"),
   1243     NATIVE_METHOD(Posix, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
   1244     NATIVE_METHOD(Posix, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
   1245     NATIVE_METHOD(Posix, getpid, "()I"),
   1246     NATIVE_METHOD(Posix, getppid, "()I"),
   1247     NATIVE_METHOD(Posix, getpwnam, "(Ljava/lang/String;)Llibcore/io/StructPasswd;"),
   1248     NATIVE_METHOD(Posix, getpwuid, "(I)Llibcore/io/StructPasswd;"),
   1249     NATIVE_METHOD(Posix, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
   1250     NATIVE_METHOD(Posix, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
   1251     NATIVE_METHOD(Posix, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
   1252     NATIVE_METHOD(Posix, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"),
   1253     NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructLinger;"),
   1254     NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructTimeval;"),
   1255     NATIVE_METHOD(Posix, getuid, "()I"),
   1256     NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
   1257     NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
   1258     NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"),
   1259     NATIVE_METHOD(Posix, ioctlInt, "(Ljava/io/FileDescriptor;ILlibcore/util/MutableInt;)I"),
   1260     NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"),
   1261     NATIVE_METHOD(Posix, kill, "(II)V"),
   1262     NATIVE_METHOD(Posix, listen, "(Ljava/io/FileDescriptor;I)V"),
   1263     NATIVE_METHOD(Posix, lseek, "(Ljava/io/FileDescriptor;JI)J"),
   1264     NATIVE_METHOD(Posix, lstat, "(Ljava/lang/String;)Llibcore/io/StructStat;"),
   1265     NATIVE_METHOD(Posix, mincore, "(JJ[B)V"),
   1266     NATIVE_METHOD(Posix, mkdir, "(Ljava/lang/String;I)V"),
   1267     NATIVE_METHOD(Posix, mlock, "(JJ)V"),
   1268     NATIVE_METHOD(Posix, mmap, "(JJIILjava/io/FileDescriptor;J)J"),
   1269     NATIVE_METHOD(Posix, msync, "(JJI)V"),
   1270     NATIVE_METHOD(Posix, munlock, "(JJ)V"),
   1271     NATIVE_METHOD(Posix, munmap, "(JJ)V"),
   1272     NATIVE_METHOD(Posix, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"),
   1273     NATIVE_METHOD(Posix, pipe, "()[Ljava/io/FileDescriptor;"),
   1274     NATIVE_METHOD(Posix, poll, "([Llibcore/io/StructPollfd;I)I"),
   1275     NATIVE_METHOD(Posix, preadBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
   1276     NATIVE_METHOD(Posix, pwriteBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
   1277     NATIVE_METHOD(Posix, readBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
   1278     NATIVE_METHOD(Posix, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
   1279     NATIVE_METHOD(Posix, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"),
   1280     NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"),
   1281     NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"),
   1282     NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Llibcore/util/MutableLong;J)J"),
   1283     NATIVE_METHOD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"),
   1284     NATIVE_METHOD(Posix, setegid, "(I)V"),
   1285     NATIVE_METHOD(Posix, seteuid, "(I)V"),
   1286     NATIVE_METHOD(Posix, setgid, "(I)V"),
   1287     NATIVE_METHOD(Posix, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"),
   1288     NATIVE_METHOD(Posix, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"),
   1289     NATIVE_METHOD(Posix, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"),
   1290     NATIVE_METHOD(Posix, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"),
   1291     NATIVE_METHOD(Posix, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILlibcore/io/StructGroupReq;)V"),
   1292     NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILlibcore/io/StructLinger;)V"),
   1293     NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILlibcore/io/StructTimeval;)V"),
   1294     NATIVE_METHOD(Posix, setuid, "(I)V"),
   1295     NATIVE_METHOD(Posix, shutdown, "(Ljava/io/FileDescriptor;I)V"),
   1296     NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
   1297     NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Llibcore/io/StructStat;"),
   1298     NATIVE_METHOD(Posix, statfs, "(Ljava/lang/String;)Llibcore/io/StructStatFs;"),
   1299     NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"),
   1300     NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
   1301     NATIVE_METHOD(Posix, sysconf, "(I)J"),
   1302     NATIVE_METHOD(Posix, uname, "()Llibcore/io/StructUtsname;"),
   1303     NATIVE_METHOD(Posix, waitpid, "(ILlibcore/util/MutableInt;I)I"),
   1304     NATIVE_METHOD(Posix, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
   1305     NATIVE_METHOD(Posix, writev, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
   1306 };
   1307 int register_libcore_io_Posix(JNIEnv* env) {
   1308     return jniRegisterNativeMethods(env, "libcore/io/Posix", gMethods, NELEM(gMethods));
   1309 }
   1310