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