libcore_io_Posix.cpp revision 90246a0ae7117d780e077c9e84cdb73ff5b44af7
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 "AsynchronousCloseMonitor.h"
20#include "cutils/log.h"
21#include "ExecStrings.h"
22#include "JNIHelp.h"
23#include "JniConstants.h"
24#include "JniException.h"
25#include "NetworkUtilities.h"
26#include "Portability.h"
27#include "readlink.h"
28#include "ScopedBytes.h"
29#include "ScopedLocalRef.h"
30#include "ScopedPrimitiveArray.h"
31#include "ScopedUtfChars.h"
32#include "toStringArray.h"
33
34#include <arpa/inet.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <linux/rtnetlink.h>
38#include <net/if.h>
39#include <netdb.h>
40#include <netinet/in.h>
41#include <netpacket/packet.h>
42#include <poll.h>
43#include <pwd.h>
44#include <signal.h>
45#include <stdlib.h>
46#include <sys/ioctl.h>
47#include <sys/mman.h>
48#ifndef __APPLE__
49#include <sys/prctl.h>
50#endif
51#include <sys/socket.h>
52#include <sys/stat.h>
53#ifdef __APPLE__
54#include <sys/statvfs.h>
55#endif
56#include <sys/syscall.h>
57#include <sys/time.h>
58#include <sys/types.h>
59#include <sys/uio.h>
60#include <sys/utsname.h>
61#include <sys/wait.h>
62#include <sys/xattr.h>
63#include <termios.h>
64#include <unistd.h>
65#include <memory>
66
67#ifndef __unused
68#define __unused __attribute__((__unused__))
69#endif
70
71#define TO_JAVA_STRING(NAME, EXP) \
72        jstring NAME = env->NewStringUTF(EXP); \
73        if (NAME == NULL) return NULL;
74
75struct addrinfo_deleter {
76    void operator()(addrinfo* p) const {
77        if (p != NULL) { // bionic's freeaddrinfo(3) crashes when passed NULL.
78            freeaddrinfo(p);
79        }
80    }
81};
82
83static bool isIPv4MappedAddress(const sockaddr *sa) {
84    const sockaddr_in6 *sin6 = reinterpret_cast<const sockaddr_in6*>(sa);
85    return sa != NULL && sa->sa_family == AF_INET6 &&
86           (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
87            IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr));  // We map 0.0.0.0 to ::, so :: is mapped.
88}
89
90/**
91 * Perform a socket operation that specifies an IP address, possibly falling back from specifying
92 * the address as an IPv4-mapped IPv6 address in a struct sockaddr_in6 to specifying it as an IPv4
93 * address in a struct sockaddr_in.
94 *
95 * This is needed because all sockets created by the java.net APIs are IPv6 sockets, and on those
96 * sockets, IPv4 operations use IPv4-mapped addresses stored in a struct sockaddr_in6. But sockets
97 * created using Posix.socket(AF_INET, ...) are IPv4 sockets and only support operations using IPv4
98 * socket addresses structures.
99 */
100#define NET_IPV4_FALLBACK(jni_env, return_type, syscall_name, java_fd, java_addr, port, null_addr_ok, args...) ({ \
101    return_type _rc = -1; \
102    do { \
103        sockaddr_storage _ss; \
104        socklen_t _salen; \
105        if (java_addr == NULL && null_addr_ok) { \
106            /* No IP address specified (e.g., sendto() on a connected socket). */ \
107            _salen = 0; \
108        } else if (!inetAddressToSockaddr(jni_env, java_addr, port, _ss, _salen)) { \
109            /* Invalid socket address, return -1. inetAddressToSockaddr has already thrown. */ \
110            break; \
111        } \
112        sockaddr* _sa = _salen ? reinterpret_cast<sockaddr*>(&_ss) : NULL; \
113        /* inetAddressToSockaddr always returns an IPv6 sockaddr. Assume that java_fd was created \
114         * by Java API calls, which always create IPv6 socket fds, and pass it in as is. */ \
115        _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
116        if (_rc == -1 && errno == EAFNOSUPPORT && _salen && isIPv4MappedAddress(_sa)) { \
117            /* We passed in an IPv4 address in an IPv6 sockaddr and the kernel told us that we got \
118             * the address family wrong. Pass in the same address in an IPv4 sockaddr. */ \
119            jni_env->ExceptionClear(); \
120            if (!inetAddressToSockaddrVerbatim(jni_env, java_addr, port, _ss, _salen)) { \
121                break; \
122            } \
123            _sa = reinterpret_cast<sockaddr*>(&_ss); \
124            _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
125        } \
126    } while (0); \
127    _rc; }) \
128
129/**
130 * Used to retry networking system calls that can be interrupted with a signal. Unlike
131 * TEMP_FAILURE_RETRY, this also handles the case where
132 * AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal a close() or
133 * Thread.interrupt(). Other signals that result in an EINTR result are ignored and the system call
134 * is retried.
135 *
136 * Returns the result of the system call though a Java exception will be pending if the result is
137 * -1:  a SocketException if signaled via AsynchronousCloseMonitor, or ErrnoException for other
138 * failures.
139 */
140#define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
141    return_type _rc = -1; \
142    do { \
143        bool _wasSignaled; \
144        int _syscallErrno; \
145        { \
146            int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
147            AsynchronousCloseMonitor _monitor(_fd); \
148            _rc = syscall_name(_fd, __VA_ARGS__); \
149            _syscallErrno = errno; \
150            _wasSignaled = _monitor.wasSignaled(); \
151        } \
152        if (_wasSignaled) { \
153            jniThrowException(jni_env, "java/net/SocketException", "Socket closed"); \
154            _rc = -1; \
155            break; \
156        } \
157        if (_rc == -1 && _syscallErrno != EINTR) { \
158            /* TODO: with a format string we could show the arguments too, like strace(1). */ \
159            throwErrnoException(jni_env, # syscall_name); \
160            break; \
161        } \
162    } while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \
163    _rc; })
164
165/**
166 * Used to retry system calls that can be interrupted with a signal. Unlike TEMP_FAILURE_RETRY, this
167 * also handles the case where AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal
168 * a close() or Thread.interrupt(). Other signals that result in an EINTR result are ignored and the
169 * system call is retried.
170 *
171 * Returns the result of the system call though a Java exception will be pending if the result is
172 * -1: an IOException if the file descriptor is already closed, a InterruptedIOException if signaled
173 * via AsynchronousCloseMonitor, or ErrnoException for other failures.
174 */
175#define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
176    return_type _rc = -1; \
177    do { \
178        bool _wasSignaled; \
179        int _syscallErrno; \
180        { \
181            int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
182            AsynchronousCloseMonitor _monitor(_fd); \
183            _rc = syscall_name(_fd, __VA_ARGS__); \
184            _syscallErrno = errno; \
185            _wasSignaled = _monitor.wasSignaled(); \
186        } \
187        if (_wasSignaled) { \
188            jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \
189            _rc = -1; \
190            break; \
191        } \
192        if (_rc == -1 && _syscallErrno != EINTR) { \
193            /* TODO: with a format string we could show the arguments too, like strace(1). */ \
194            throwErrnoException(jni_env, # syscall_name); \
195            break; \
196        } \
197    } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
198    _rc; })
199
200#define NULL_ADDR_OK         true
201#define NULL_ADDR_FORBIDDEN  false
202
203static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
204        const char* functionName, int error) {
205    jthrowable cause = NULL;
206    if (env->ExceptionCheck()) {
207        cause = env->ExceptionOccurred();
208        env->ExceptionClear();
209    }
210
211    ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
212    if (detailMessage.get() == NULL) {
213        // Not really much we can do here. We're probably dead in the water,
214        // but let's try to stumble on...
215        env->ExceptionClear();
216    }
217
218    jobject exception;
219    if (cause != NULL) {
220        exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause);
221    } else {
222        exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error);
223    }
224    env->Throw(reinterpret_cast<jthrowable>(exception));
225}
226
227static void throwErrnoException(JNIEnv* env, const char* functionName) {
228    int error = errno;
229    static jmethodID ctor3 = env->GetMethodID(JniConstants::errnoExceptionClass,
230            "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
231    static jmethodID ctor2 = env->GetMethodID(JniConstants::errnoExceptionClass,
232            "<init>", "(Ljava/lang/String;I)V");
233    throwException(env, JniConstants::errnoExceptionClass, ctor3, ctor2, functionName, error);
234}
235
236static void throwGaiException(JNIEnv* env, const char* functionName, int error) {
237  // Cache the methods ids before we throw, so we don't call GetMethodID with a pending exception.
238  static jmethodID ctor3 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>",
239                                            "(Ljava/lang/String;ILjava/lang/Throwable;)V");
240  static jmethodID ctor2 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>",
241                                            "(Ljava/lang/String;I)V");
242  if (errno != 0) {
243        // EAI_SYSTEM should mean "look at errno instead", but both glibc and bionic seem to
244        // mess this up. In particular, if you don't have INTERNET permission, errno will be EACCES
245        // but you'll get EAI_NONAME or EAI_NODATA. So we want our GaiException to have a
246        // potentially-relevant ErrnoException as its cause even if error != EAI_SYSTEM.
247        // http://code.google.com/p/android/issues/detail?id=15722
248        throwErrnoException(env, functionName);
249        // Deliberately fall through to throw another exception...
250    }
251    throwException(env, JniConstants::gaiExceptionClass, ctor3, ctor2, functionName, error);
252}
253
254template <typename rc_t>
255static rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) {
256    if (rc == rc_t(-1)) {
257        throwErrnoException(env, name);
258    }
259    return rc;
260}
261
262template <typename ScopedT>
263class IoVec {
264public:
265    IoVec(JNIEnv* env, size_t bufferCount) : mEnv(env), mBufferCount(bufferCount) {
266    }
267
268    bool init(jobjectArray javaBuffers, jintArray javaOffsets, jintArray javaByteCounts) {
269        // We can't delete our local references until after the I/O, so make sure we have room.
270        if (mEnv->PushLocalFrame(mBufferCount + 16) < 0) {
271            return false;
272        }
273        ScopedIntArrayRO offsets(mEnv, javaOffsets);
274        if (offsets.get() == NULL) {
275            return false;
276        }
277        ScopedIntArrayRO byteCounts(mEnv, javaByteCounts);
278        if (byteCounts.get() == NULL) {
279            return false;
280        }
281        // TODO: Linux actually has a 1024 buffer limit. glibc works around this, and we should too.
282        // TODO: you can query the limit at runtime with sysconf(_SC_IOV_MAX).
283        for (size_t i = 0; i < mBufferCount; ++i) {
284            jobject buffer = mEnv->GetObjectArrayElement(javaBuffers, i); // We keep this local ref.
285            mScopedBuffers.push_back(new ScopedT(mEnv, buffer));
286            jbyte* ptr = const_cast<jbyte*>(mScopedBuffers.back()->get());
287            if (ptr == NULL) {
288                return false;
289            }
290            struct iovec iov;
291            iov.iov_base = reinterpret_cast<void*>(ptr + offsets[i]);
292            iov.iov_len = byteCounts[i];
293            mIoVec.push_back(iov);
294        }
295        return true;
296    }
297
298    ~IoVec() {
299        for (size_t i = 0; i < mScopedBuffers.size(); ++i) {
300            delete mScopedBuffers[i];
301        }
302        mEnv->PopLocalFrame(NULL);
303    }
304
305    iovec* get() {
306        return &mIoVec[0];
307    }
308
309    size_t size() {
310        return mBufferCount;
311    }
312
313private:
314    JNIEnv* mEnv;
315    size_t mBufferCount;
316    std::vector<iovec> mIoVec;
317    std::vector<ScopedT*> mScopedBuffers;
318};
319
320static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss) {
321    if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6 || ss.ss_family == AF_UNIX) {
322        jint port;
323        jobject inetAddress = sockaddrToInetAddress(env, ss, &port);
324        if (inetAddress == NULL) {
325            return NULL;  // Exception already thrown.
326        }
327        static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass,
328                "<init>", "(Ljava/net/InetAddress;I)V");
329        return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port);
330    } else if (ss.ss_family == AF_NETLINK) {
331        const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss);
332        static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass,
333                "<init>", "(II)V");
334        return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor,
335                static_cast<jint>(nl_addr->nl_pid),
336                static_cast<jint>(nl_addr->nl_groups));
337    } else if (ss.ss_family == AF_PACKET) {
338        const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
339        static jmethodID ctor = env->GetMethodID(JniConstants::packetSocketAddressClass,
340                "<init>", "(SISB[B)V");
341        ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(sll->sll_halen));
342        if (byteArray.get() == NULL) {
343            return NULL;
344        }
345        env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen,
346                reinterpret_cast<const jbyte*>(sll->sll_addr));
347        jobject packetSocketAddress = env->NewObject(JniConstants::packetSocketAddressClass, ctor,
348                static_cast<jshort>(ntohs(sll->sll_protocol)),
349                static_cast<jint>(sll->sll_ifindex),
350                static_cast<jshort>(sll->sll_hatype),
351                static_cast<jbyte>(sll->sll_pkttype),
352                byteArray.get());
353        return packetSocketAddress;
354    }
355    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "unsupported ss_family: %d",
356            ss.ss_family);
357    return NULL;
358}
359
360static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) {
361    TO_JAVA_STRING(pw_name, pw.pw_name);
362    TO_JAVA_STRING(pw_dir, pw.pw_dir);
363    TO_JAVA_STRING(pw_shell, pw.pw_shell);
364    static jmethodID ctor = env->GetMethodID(JniConstants::structPasswdClass, "<init>",
365            "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
366    return env->NewObject(JniConstants::structPasswdClass, ctor,
367            pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell);
368}
369
370static jobject makeStructStat(JNIEnv* env, const struct stat& sb) {
371    static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>",
372            "(JJIJIIJJJJJJJ)V");
373    return env->NewObject(JniConstants::structStatClass, ctor,
374            static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino),
375            static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink),
376            static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid),
377            static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size),
378            static_cast<jlong>(sb.st_atime), static_cast<jlong>(sb.st_mtime),
379            static_cast<jlong>(sb.st_ctime), static_cast<jlong>(sb.st_blksize),
380            static_cast<jlong>(sb.st_blocks));
381}
382
383static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
384#if defined(__APPLE__)
385    // Mac OS has no f_namelen field in struct statfs.
386    jlong max_name_length = 255; // __DARWIN_MAXNAMLEN
387#else
388    jlong max_name_length = static_cast<jlong>(sb.f_namemax);
389#endif
390
391    static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
392            "(JJJJJJJJJJJ)V");
393    return env->NewObject(JniConstants::structStatVfsClass, ctor,
394                          static_cast<jlong>(sb.f_bsize),
395                          static_cast<jlong>(sb.f_frsize),
396                          static_cast<jlong>(sb.f_blocks),
397                          static_cast<jlong>(sb.f_bfree),
398                          static_cast<jlong>(sb.f_bavail),
399                          static_cast<jlong>(sb.f_files),
400                          static_cast<jlong>(sb.f_ffree),
401                          static_cast<jlong>(sb.f_favail),
402                          static_cast<jlong>(sb.f_fsid),
403                          static_cast<jlong>(sb.f_flag),
404                          max_name_length);
405}
406
407static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
408    static jmethodID ctor = env->GetMethodID(JniConstants::structLingerClass, "<init>", "(II)V");
409    return env->NewObject(JniConstants::structLingerClass, ctor, l.l_onoff, l.l_linger);
410}
411
412static jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) {
413    static jmethodID ctor = env->GetMethodID(JniConstants::structTimevalClass, "<init>", "(JJ)V");
414    return env->NewObject(JniConstants::structTimevalClass, ctor,
415            static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
416}
417
418static jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) {
419#ifdef __APPLE__
420  jniThrowException(env, "java/lang/UnsupportedOperationException", "unimplemented support for ucred on a Mac");
421  return NULL;
422#else
423  static jmethodID ctor = env->GetMethodID(JniConstants::structUcredClass, "<init>", "(III)V");
424  return env->NewObject(JniConstants::structUcredClass, ctor, u.pid, u.uid, u.gid);
425#endif
426}
427
428static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
429    TO_JAVA_STRING(sysname, buf.sysname);
430    TO_JAVA_STRING(nodename, buf.nodename);
431    TO_JAVA_STRING(release, buf.release);
432    TO_JAVA_STRING(version, buf.version);
433    TO_JAVA_STRING(machine, buf.machine);
434    static jmethodID ctor = env->GetMethodID(JniConstants::structUtsnameClass, "<init>",
435            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
436    return env->NewObject(JniConstants::structUtsnameClass, ctor,
437            sysname, nodename, release, version, machine);
438};
439
440static bool fillIfreq(JNIEnv* env, jstring javaInterfaceName, struct ifreq& req) {
441    ScopedUtfChars interfaceName(env, javaInterfaceName);
442    if (interfaceName.c_str() == NULL) {
443        return false;
444    }
445    memset(&req, 0, sizeof(req));
446    strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name));
447    req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
448    return true;
449}
450
451static bool fillInetSocketAddress(JNIEnv* env, jint rc, jobject javaInetSocketAddress, const sockaddr_storage& ss) {
452    if (rc == -1 || javaInetSocketAddress == NULL) {
453        return true;
454    }
455    // Fill out the passed-in InetSocketAddress with the sender's IP address and port number.
456    jint port;
457    jobject sender = sockaddrToInetAddress(env, ss, &port);
458    if (sender == NULL) {
459        return false;
460    }
461    static jfieldID addressFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "addr", "Ljava/net/InetAddress;");
462    static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "port", "I");
463    env->SetObjectField(javaInetSocketAddress, addressFid, sender);
464    env->SetIntField(javaInetSocketAddress, portFid, port);
465    return true;
466}
467
468static void javaInetSocketAddressToInetAddressAndPort(
469        JNIEnv* env, jobject javaInetSocketAddress, jobject& javaInetAddress, jint& port) {
470    static jfieldID addressFid = env->GetFieldID(
471            JniConstants::inetSocketAddressClass, "addr", "Ljava/net/InetAddress;");
472    static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "port", "I");
473    javaInetAddress = env->GetObjectField(javaInetSocketAddress, addressFid);
474    port = env->GetIntField(javaInetSocketAddress, portFid);
475}
476
477static bool javaInetSocketAddressToSockaddr(
478        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
479    jobject javaInetAddress;
480    jint port;
481    javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
482    return inetAddressToSockaddr(env, javaInetAddress, port, ss, sa_len);
483}
484
485static bool javaNetlinkSocketAddressToSockaddr(
486        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
487    static jfieldID nlPidFid = env->GetFieldID(
488            JniConstants::netlinkSocketAddressClass, "nlPortId", "I");
489    static jfieldID nlGroupsFid = env->GetFieldID(
490            JniConstants::netlinkSocketAddressClass, "nlGroupsMask", "I");
491
492    sockaddr_nl *nlAddr = reinterpret_cast<sockaddr_nl *>(&ss);
493    nlAddr->nl_family = AF_NETLINK;
494    nlAddr->nl_pid = env->GetIntField(javaSocketAddress, nlPidFid);
495    nlAddr->nl_groups = env->GetIntField(javaSocketAddress, nlGroupsFid);
496    sa_len = sizeof(sockaddr_nl);
497    return true;
498}
499
500static bool javaPacketSocketAddressToSockaddr(
501        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
502    static jfieldID protocolFid = env->GetFieldID(
503            JniConstants::packetSocketAddressClass, "sll_protocol", "S");
504    static jfieldID ifindexFid = env->GetFieldID(
505            JniConstants::packetSocketAddressClass, "sll_ifindex", "I");
506    static jfieldID hatypeFid = env->GetFieldID(
507            JniConstants::packetSocketAddressClass, "sll_hatype", "S");
508    static jfieldID pkttypeFid = env->GetFieldID(
509            JniConstants::packetSocketAddressClass, "sll_pkttype", "B");
510    static jfieldID addrFid = env->GetFieldID(
511            JniConstants::packetSocketAddressClass, "sll_addr", "[B");
512
513    sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss);
514    sll->sll_family = AF_PACKET;
515    sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid));
516    sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid);
517    sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid);
518    sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid);
519
520    jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid);
521    if (sllAddr == NULL) {
522        sll->sll_halen = 0;
523        memset(&sll->sll_addr, 0, sizeof(sll->sll_addr));
524    } else {
525        jsize len = env->GetArrayLength(sllAddr);
526        if ((size_t) len > sizeof(sll->sll_addr)) {
527            len = sizeof(sll->sll_addr);
528        }
529        sll->sll_halen = len;
530        env->GetByteArrayRegion(sllAddr, 0, len, (jbyte*) sll->sll_addr);
531    }
532    sa_len = sizeof(sockaddr_ll);
533    return true;
534}
535
536static bool javaSocketAddressToSockaddr(
537        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
538    if (javaSocketAddress == NULL) {
539        jniThrowNullPointerException(env, NULL);
540        return false;
541    }
542
543    if (env->IsInstanceOf(javaSocketAddress, JniConstants::netlinkSocketAddressClass)) {
544        return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
545    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
546        return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
547    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::packetSocketAddressClass)) {
548        return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
549    }
550    jniThrowException(env, "java/lang/UnsupportedOperationException",
551            "unsupported SocketAddress subclass");
552    return false;
553}
554
555static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) {
556    ScopedUtfChars path(env, javaPath);
557    if (path.c_str() == NULL) {
558        return NULL;
559    }
560    struct stat sb;
561    int rc = isLstat ? TEMP_FAILURE_RETRY(lstat(path.c_str(), &sb))
562                     : TEMP_FAILURE_RETRY(stat(path.c_str(), &sb));
563    if (rc == -1) {
564        throwErrnoException(env, isLstat ? "lstat" : "stat");
565        return NULL;
566    }
567    return makeStructStat(env, sb);
568}
569
570static jobject doGetSockName(JNIEnv* env, jobject javaFd, bool is_sockname) {
571  int fd = jniGetFDFromFileDescriptor(env, javaFd);
572  sockaddr_storage ss;
573  sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
574  socklen_t byteCount = sizeof(ss);
575  memset(&ss, 0, byteCount);
576  int rc = is_sockname ? TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount))
577      : TEMP_FAILURE_RETRY(getpeername(fd, sa, &byteCount));
578  if (rc == -1) {
579    throwErrnoException(env, is_sockname ? "getsockname" : "getpeername");
580    return NULL;
581  }
582  return makeSocketAddress(env, ss);
583}
584
585class Passwd {
586public:
587    Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
588        mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
589        mBuffer.reset(new char[mBufferSize]);
590    }
591
592    jobject getpwnam(const char* name) {
593        return process("getpwnam_r", getpwnam_r(name, &mPwd, mBuffer.get(), mBufferSize, &mResult));
594    }
595
596    jobject getpwuid(uid_t uid) {
597        return process("getpwuid_r", getpwuid_r(uid, &mPwd, mBuffer.get(), mBufferSize, &mResult));
598    }
599
600    struct passwd* get() {
601        return mResult;
602    }
603
604private:
605    jobject process(const char* syscall, int error) {
606        if (mResult == NULL) {
607            errno = error;
608            throwErrnoException(mEnv, syscall);
609            return NULL;
610        }
611        return makeStructPasswd(mEnv, *mResult);
612    }
613
614    JNIEnv* mEnv;
615    std::unique_ptr<char[]> mBuffer;
616    size_t mBufferSize;
617    struct passwd mPwd;
618    struct passwd* mResult;
619};
620
621static jobject Posix_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaInetSocketAddress) {
622    sockaddr_storage ss;
623    socklen_t sl = sizeof(ss);
624    memset(&ss, 0, sizeof(ss));
625    sockaddr* peer = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
626    socklen_t* peerLength = (javaInetSocketAddress != NULL) ? &sl : 0;
627    jint clientFd = NET_FAILURE_RETRY(env, int, accept, javaFd, peer, peerLength);
628    if (clientFd == -1 || !fillInetSocketAddress(env, clientFd, javaInetSocketAddress, ss)) {
629        close(clientFd);
630        return NULL;
631    }
632    return (clientFd != -1) ? jniCreateFileDescriptor(env, clientFd) : NULL;
633}
634
635static jboolean Posix_access(JNIEnv* env, jobject, jstring javaPath, jint mode) {
636    ScopedUtfChars path(env, javaPath);
637    if (path.c_str() == NULL) {
638        return JNI_FALSE;
639    }
640    int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode));
641    if (rc == -1) {
642        throwErrnoException(env, "access");
643    }
644    return (rc == 0);
645}
646
647static void Posix_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
648    // We don't need the return value because we'll already have thrown.
649    (void) NET_IPV4_FALLBACK(env, int, bind, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
650}
651
652static void Posix_bindSocketAddress(
653        JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
654    sockaddr_storage ss;
655    socklen_t sa_len;
656    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
657        return;  // Exception already thrown.
658    }
659
660    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
661    // We don't need the return value because we'll already have thrown.
662    (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len);
663}
664
665static void Posix_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) {
666    ScopedUtfChars path(env, javaPath);
667    if (path.c_str() == NULL) {
668        return;
669    }
670    throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode)));
671}
672
673static void Posix_chown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
674    ScopedUtfChars path(env, javaPath);
675    if (path.c_str() == NULL) {
676        return;
677    }
678    throwIfMinusOne(env, "chown", TEMP_FAILURE_RETRY(chown(path.c_str(), uid, gid)));
679}
680
681static void Posix_close(JNIEnv* env, jobject, jobject javaFd) {
682    // Get the FileDescriptor's 'fd' field and clear it.
683    // We need to do this before we can throw an IOException (http://b/3222087).
684    int fd = jniGetFDFromFileDescriptor(env, javaFd);
685    jniSetFileDescriptorOfFD(env, javaFd, -1);
686
687    // Even if close(2) fails with EINTR, the fd will have been closed.
688    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
689    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
690    throwIfMinusOne(env, "close", close(fd));
691}
692
693static void Posix_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
694    (void) NET_IPV4_FALLBACK(env, int, connect, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
695}
696
697static void Posix_connectSocketAddress(
698        JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
699    sockaddr_storage ss;
700    socklen_t sa_len;
701    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
702        return;  // Exception already thrown.
703    }
704
705    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
706    // We don't need the return value because we'll already have thrown.
707    (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len);
708}
709
710static jobject Posix_dup(JNIEnv* env, jobject, jobject javaOldFd) {
711    int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
712    int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd)));
713    return (newFd != -1) ? jniCreateFileDescriptor(env, newFd) : NULL;
714}
715
716static jobject Posix_dup2(JNIEnv* env, jobject, jobject javaOldFd, jint newFd) {
717    int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
718    int fd = throwIfMinusOne(env, "dup2", TEMP_FAILURE_RETRY(dup2(oldFd, newFd)));
719    return (fd != -1) ? jniCreateFileDescriptor(env, fd) : NULL;
720}
721
722static jobjectArray Posix_environ(JNIEnv* env, jobject) {
723    extern char** environ; // Standard, but not in any header file.
724    return toStringArray(env, environ);
725}
726
727static void Posix_execve(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv, jobjectArray javaEnvp) {
728    ScopedUtfChars path(env, javaFilename);
729    if (path.c_str() == NULL) {
730        return;
731    }
732
733    ExecStrings argv(env, javaArgv);
734    ExecStrings envp(env, javaEnvp);
735    TEMP_FAILURE_RETRY(execve(path.c_str(), argv.get(), envp.get()));
736
737    throwErrnoException(env, "execve");
738}
739
740static void Posix_execv(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv) {
741    ScopedUtfChars path(env, javaFilename);
742    if (path.c_str() == NULL) {
743        return;
744    }
745
746    ExecStrings argv(env, javaArgv);
747    TEMP_FAILURE_RETRY(execv(path.c_str(), argv.get()));
748
749    throwErrnoException(env, "execv");
750}
751
752static void Posix_fchmod(JNIEnv* env, jobject, jobject javaFd, jint mode) {
753    int fd = jniGetFDFromFileDescriptor(env, javaFd);
754    throwIfMinusOne(env, "fchmod", TEMP_FAILURE_RETRY(fchmod(fd, mode)));
755}
756
757static void Posix_fchown(JNIEnv* env, jobject, jobject javaFd, jint uid, jint gid) {
758    int fd = jniGetFDFromFileDescriptor(env, javaFd);
759    throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid)));
760}
761
762static jint Posix_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) {
763    static jfieldID typeFid = env->GetFieldID(JniConstants::structFlockClass, "l_type", "S");
764    static jfieldID whenceFid = env->GetFieldID(JniConstants::structFlockClass, "l_whence", "S");
765    static jfieldID startFid = env->GetFieldID(JniConstants::structFlockClass, "l_start", "J");
766    static jfieldID lenFid = env->GetFieldID(JniConstants::structFlockClass, "l_len", "J");
767    static jfieldID pidFid = env->GetFieldID(JniConstants::structFlockClass, "l_pid", "I");
768
769    struct flock64 lock;
770    memset(&lock, 0, sizeof(lock));
771    lock.l_type = env->GetShortField(javaFlock, typeFid);
772    lock.l_whence = env->GetShortField(javaFlock, whenceFid);
773    lock.l_start = env->GetLongField(javaFlock, startFid);
774    lock.l_len = env->GetLongField(javaFlock, lenFid);
775    lock.l_pid = env->GetIntField(javaFlock, pidFid);
776
777    int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock);
778    if (rc != -1) {
779        env->SetShortField(javaFlock, typeFid, lock.l_type);
780        env->SetShortField(javaFlock, whenceFid, lock.l_whence);
781        env->SetLongField(javaFlock, startFid, lock.l_start);
782        env->SetLongField(javaFlock, lenFid, lock.l_len);
783        env->SetIntField(javaFlock, pidFid, lock.l_pid);
784    }
785    return rc;
786}
787
788static jint Posix_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) {
789    int fd = jniGetFDFromFileDescriptor(env, javaFd);
790    return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
791}
792
793static jint Posix_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) {
794    int fd = jniGetFDFromFileDescriptor(env, javaFd);
795    return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd)));
796}
797
798static void Posix_fdatasync(JNIEnv* env, jobject, jobject javaFd) {
799    int fd = jniGetFDFromFileDescriptor(env, javaFd);
800    throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd)));
801}
802
803static jobject Posix_fstat(JNIEnv* env, jobject, jobject javaFd) {
804    int fd = jniGetFDFromFileDescriptor(env, javaFd);
805    struct stat sb;
806    int rc = TEMP_FAILURE_RETRY(fstat(fd, &sb));
807    if (rc == -1) {
808        throwErrnoException(env, "fstat");
809        return NULL;
810    }
811    return makeStructStat(env, sb);
812}
813
814static jobject Posix_fstatvfs(JNIEnv* env, jobject, jobject javaFd) {
815    int fd = jniGetFDFromFileDescriptor(env, javaFd);
816    struct statvfs sb;
817    int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb));
818    if (rc == -1) {
819        throwErrnoException(env, "fstatvfs");
820        return NULL;
821    }
822    return makeStructStatVfs(env, sb);
823}
824
825static void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) {
826    int fd = jniGetFDFromFileDescriptor(env, javaFd);
827    throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd)));
828}
829
830static void Posix_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) {
831    int fd = jniGetFDFromFileDescriptor(env, javaFd);
832    throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length)));
833}
834
835static jstring Posix_gai_strerror(JNIEnv* env, jobject, jint error) {
836    return env->NewStringUTF(gai_strerror(error));
837}
838
839static jobjectArray Posix_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode,
840        jobject javaHints, jint netId) {
841    ScopedUtfChars node(env, javaNode);
842    if (node.c_str() == NULL) {
843        return NULL;
844    }
845
846    static jfieldID flagsFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_flags", "I");
847    static jfieldID familyFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_family", "I");
848    static jfieldID socktypeFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_socktype", "I");
849    static jfieldID protocolFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_protocol", "I");
850
851    addrinfo hints;
852    memset(&hints, 0, sizeof(hints));
853    hints.ai_flags = env->GetIntField(javaHints, flagsFid);
854    hints.ai_family = env->GetIntField(javaHints, familyFid);
855    hints.ai_socktype = env->GetIntField(javaHints, socktypeFid);
856    hints.ai_protocol = env->GetIntField(javaHints, protocolFid);
857
858    addrinfo* addressList = NULL;
859    errno = 0;
860    int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList);
861    std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
862    if (rc != 0) {
863        throwGaiException(env, "android_getaddrinfo", rc);
864        return NULL;
865    }
866
867    // Count results so we know how to size the output array.
868    int addressCount = 0;
869    for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
870        if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
871            ++addressCount;
872        } else {
873            ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
874        }
875    }
876    if (addressCount == 0) {
877        return NULL;
878    }
879
880    // Prepare output array.
881    jobjectArray result = env->NewObjectArray(addressCount, JniConstants::inetAddressClass, NULL);
882    if (result == NULL) {
883        return NULL;
884    }
885
886    // Examine returned addresses one by one, save them in the output array.
887    int index = 0;
888    for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
889        if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
890            // Unknown address family. Skip this address.
891            ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
892            continue;
893        }
894
895        // Convert each IP address into a Java byte array.
896        sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr);
897        ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL));
898        if (inetAddress.get() == NULL) {
899            return NULL;
900        }
901        env->SetObjectArrayElement(result, index, inetAddress.get());
902        ++index;
903    }
904    return result;
905}
906
907static jint Posix_getegid(JNIEnv*, jobject) {
908    return getegid();
909}
910
911static jint Posix_geteuid(JNIEnv*, jobject) {
912    return geteuid();
913}
914
915static jint Posix_getgid(JNIEnv*, jobject) {
916    return getgid();
917}
918
919static jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) {
920    ScopedUtfChars name(env, javaName);
921    if (name.c_str() == NULL) {
922        return NULL;
923    }
924    return env->NewStringUTF(getenv(name.c_str()));
925}
926
927static jstring Posix_getnameinfo(JNIEnv* env, jobject, jobject javaAddress, jint flags) {
928    sockaddr_storage ss;
929    socklen_t sa_len;
930    if (!inetAddressToSockaddrVerbatim(env, javaAddress, 0, ss, sa_len)) {
931        return NULL;
932    }
933    char buf[NI_MAXHOST]; // NI_MAXHOST is longer than INET6_ADDRSTRLEN.
934    errno = 0;
935    int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_len, buf, sizeof(buf), NULL, 0, flags);
936    if (rc != 0) {
937        throwGaiException(env, "getnameinfo", rc);
938        return NULL;
939    }
940    return env->NewStringUTF(buf);
941}
942
943static jobject Posix_getpeername(JNIEnv* env, jobject, jobject javaFd) {
944  return doGetSockName(env, javaFd, false);
945}
946
947static jint Posix_getpgid(JNIEnv* env, jobject, jint pid) {
948    return throwIfMinusOne(env, "getpgid", TEMP_FAILURE_RETRY(getpgid(pid)));
949}
950
951static jint Posix_getpid(JNIEnv*, jobject) {
952    return TEMP_FAILURE_RETRY(getpid());
953}
954
955static jint Posix_getppid(JNIEnv*, jobject) {
956    return TEMP_FAILURE_RETRY(getppid());
957}
958
959static jobject Posix_getpwnam(JNIEnv* env, jobject, jstring javaName) {
960    ScopedUtfChars name(env, javaName);
961    if (name.c_str() == NULL) {
962        return NULL;
963    }
964    return Passwd(env).getpwnam(name.c_str());
965}
966
967static jobject Posix_getpwuid(JNIEnv* env, jobject, jint uid) {
968    return Passwd(env).getpwuid(uid);
969}
970
971static jobject Posix_getsockname(JNIEnv* env, jobject, jobject javaFd) {
972  return doGetSockName(env, javaFd, true);
973}
974
975static jint Posix_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
976    int fd = jniGetFDFromFileDescriptor(env, javaFd);
977    u_char result = 0;
978    socklen_t size = sizeof(result);
979    throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
980    return result;
981}
982
983static jobject Posix_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
984    int fd = jniGetFDFromFileDescriptor(env, javaFd);
985    sockaddr_storage ss;
986    memset(&ss, 0, sizeof(ss));
987    ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF.
988    sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
989    socklen_t size = sizeof(sa->sin_addr);
990    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size));
991    if (rc == -1) {
992        throwErrnoException(env, "getsockopt");
993        return NULL;
994    }
995    return sockaddrToInetAddress(env, ss, NULL);
996}
997
998static jint Posix_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
999    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1000    jint result = 0;
1001    socklen_t size = sizeof(result);
1002    throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
1003    return result;
1004}
1005
1006static jobject Posix_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1007    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1008    struct linger l;
1009    socklen_t size = sizeof(l);
1010    memset(&l, 0, size);
1011    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size));
1012    if (rc == -1) {
1013        throwErrnoException(env, "getsockopt");
1014        return NULL;
1015    }
1016    return makeStructLinger(env, l);
1017}
1018
1019static jobject Posix_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1020    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1021    struct timeval tv;
1022    socklen_t size = sizeof(tv);
1023    memset(&tv, 0, size);
1024    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size));
1025    if (rc == -1) {
1026        throwErrnoException(env, "getsockopt");
1027        return NULL;
1028    }
1029    return makeStructTimeval(env, tv);
1030}
1031
1032static jobject Posix_getsockoptUcred(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1033  int fd = jniGetFDFromFileDescriptor(env, javaFd);
1034  struct ucred u;
1035  socklen_t size = sizeof(u);
1036  memset(&u, 0, size);
1037  int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &u, &size));
1038  if (rc == -1) {
1039    throwErrnoException(env, "getsockopt");
1040    return NULL;
1041  }
1042  return makeStructUcred(env, u);
1043}
1044
1045static jint Posix_gettid(JNIEnv* env __unused, jobject) {
1046#if defined(__APPLE__)
1047  uint64_t owner;
1048  int rc = pthread_threadid_np(NULL, &owner);  // Requires Mac OS 10.6
1049  if (rc != 0) {
1050    throwErrnoException(env, "gettid");
1051    return 0;
1052  }
1053  return static_cast<jint>(owner);
1054#elif defined(__BIONIC__)
1055  return TEMP_FAILURE_RETRY(gettid());
1056#else
1057  return syscall(__NR_gettid);
1058#endif
1059}
1060
1061static jint Posix_getuid(JNIEnv*, jobject) {
1062    return getuid();
1063}
1064
1065static jint Posix_getxattr(JNIEnv* env, jobject, jstring javaPath,
1066        jstring javaName, jbyteArray javaOutValue) {
1067    ScopedUtfChars path(env, javaPath);
1068    if (path.c_str() == NULL) {
1069        return -1;
1070    }
1071    ScopedUtfChars name(env, javaName);
1072    if (name.c_str() == NULL) {
1073        return -1;
1074    }
1075    ScopedBytesRW outValue(env, javaOutValue);
1076    if (outValue.get() == NULL) {
1077        return -1;
1078    }
1079    size_t outValueLength = env->GetArrayLength(javaOutValue);
1080    ssize_t size = getxattr(path.c_str(), name.c_str(), outValue.get(), outValueLength);
1081    if (size < 0) {
1082        throwErrnoException(env, "getxattr");
1083    }
1084    return size;
1085}
1086
1087static jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) {
1088    char buf[IF_NAMESIZE];
1089    char* name = if_indextoname(index, buf);
1090    // if_indextoname(3) returns NULL on failure, which will come out of NewStringUTF unscathed.
1091    // There's no useful information in errno, so we don't bother throwing. Callers can null-check.
1092    return env->NewStringUTF(name);
1093}
1094
1095static jobject Posix_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) {
1096    ScopedUtfChars name(env, javaName);
1097    if (name.c_str() == NULL) {
1098        return NULL;
1099    }
1100    sockaddr_storage ss;
1101    memset(&ss, 0, sizeof(ss));
1102    // sockaddr_in and sockaddr_in6 are at the same address, so we can use either here.
1103    void* dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr;
1104    if (inet_pton(family, name.c_str(), dst) != 1) {
1105        return NULL;
1106    }
1107    ss.ss_family = family;
1108    return sockaddrToInetAddress(env, ss, NULL);
1109}
1110
1111static jobject Posix_ioctlInetAddress(JNIEnv* env, jobject, jobject javaFd, jint cmd, jstring javaInterfaceName) {
1112    struct ifreq req;
1113    if (!fillIfreq(env, javaInterfaceName, req)) {
1114        return NULL;
1115    }
1116    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1117    int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &req)));
1118    if (rc == -1) {
1119        return NULL;
1120    }
1121    return sockaddrToInetAddress(env, reinterpret_cast<sockaddr_storage&>(req.ifr_addr), NULL);
1122}
1123
1124static jint Posix_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) {
1125    // This is complicated because ioctls may return their result by updating their argument
1126    // or via their return value, so we need to support both.
1127    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1128    static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
1129    jint arg = env->GetIntField(javaArg, valueFid);
1130    int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &arg)));
1131    if (!env->ExceptionCheck()) {
1132        env->SetIntField(javaArg, valueFid, arg);
1133    }
1134    return rc;
1135}
1136
1137static jboolean Posix_isatty(JNIEnv* env, jobject, jobject javaFd) {
1138    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1139    return TEMP_FAILURE_RETRY(isatty(fd)) == 1;
1140}
1141
1142static void Posix_kill(JNIEnv* env, jobject, jint pid, jint sig) {
1143    throwIfMinusOne(env, "kill", TEMP_FAILURE_RETRY(kill(pid, sig)));
1144}
1145
1146static void Posix_lchown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
1147    ScopedUtfChars path(env, javaPath);
1148    if (path.c_str() == NULL) {
1149        return;
1150    }
1151    throwIfMinusOne(env, "lchown", TEMP_FAILURE_RETRY(lchown(path.c_str(), uid, gid)));
1152}
1153
1154static void Posix_link(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1155    ScopedUtfChars oldPath(env, javaOldPath);
1156    if (oldPath.c_str() == NULL) {
1157        return;
1158    }
1159    ScopedUtfChars newPath(env, javaNewPath);
1160    if (newPath.c_str() == NULL) {
1161        return;
1162    }
1163    throwIfMinusOne(env, "link", TEMP_FAILURE_RETRY(link(oldPath.c_str(), newPath.c_str())));
1164}
1165
1166static void Posix_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog) {
1167    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1168    throwIfMinusOne(env, "listen", TEMP_FAILURE_RETRY(listen(fd, backlog)));
1169}
1170
1171static jlong Posix_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) {
1172    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1173    return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)));
1174}
1175
1176static jobject Posix_lstat(JNIEnv* env, jobject, jstring javaPath) {
1177    return doStat(env, javaPath, true);
1178}
1179
1180static void Posix_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) {
1181    ScopedByteArrayRW vector(env, javaVector);
1182    if (vector.get() == NULL) {
1183        return;
1184    }
1185    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1186    unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get());
1187    throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec)));
1188}
1189
1190static void Posix_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1191    ScopedUtfChars path(env, javaPath);
1192    if (path.c_str() == NULL) {
1193        return;
1194    }
1195    throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode)));
1196}
1197
1198static void Posix_mkfifo(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1199    ScopedUtfChars path(env, javaPath);
1200    if (path.c_str() == NULL) {
1201        return;
1202    }
1203    throwIfMinusOne(env, "mkfifo", TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode)));
1204}
1205
1206static void Posix_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1207    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1208    throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount)));
1209}
1210
1211static jlong Posix_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) {
1212    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1213    void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1214    void* ptr = mmap(suggestedPtr, byteCount, prot, flags, fd, offset);
1215    if (ptr == MAP_FAILED) {
1216        throwErrnoException(env, "mmap");
1217    }
1218    return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
1219}
1220
1221static void Posix_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) {
1222    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1223    throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags)));
1224}
1225
1226static void Posix_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1227    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1228    throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount)));
1229}
1230
1231static void Posix_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1232    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1233    throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount)));
1234}
1235
1236static jobject Posix_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) {
1237    ScopedUtfChars path(env, javaPath);
1238    if (path.c_str() == NULL) {
1239        return NULL;
1240    }
1241    int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
1242    return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
1243}
1244
1245static jobjectArray Posix_pipe2(JNIEnv* env, jobject, jint flags __unused) {
1246#ifdef __APPLE__
1247    jniThrowException(env, "java/lang/UnsupportedOperationException", "no pipe2 on Mac OS");
1248    return NULL;
1249#else
1250    int fds[2];
1251    throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(&fds[0], flags)));
1252    jobjectArray result = env->NewObjectArray(2, JniConstants::fileDescriptorClass, NULL);
1253    if (result == NULL) {
1254        return NULL;
1255    }
1256    for (int i = 0; i < 2; ++i) {
1257        ScopedLocalRef<jobject> fd(env, jniCreateFileDescriptor(env, fds[i]));
1258        if (fd.get() == NULL) {
1259            return NULL;
1260        }
1261        env->SetObjectArrayElement(result, i, fd.get());
1262        if (env->ExceptionCheck()) {
1263            return NULL;
1264        }
1265    }
1266    return result;
1267#endif
1268}
1269
1270static jint Posix_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) {
1271    static jfieldID fdFid = env->GetFieldID(JniConstants::structPollfdClass, "fd", "Ljava/io/FileDescriptor;");
1272    static jfieldID eventsFid = env->GetFieldID(JniConstants::structPollfdClass, "events", "S");
1273    static jfieldID reventsFid = env->GetFieldID(JniConstants::structPollfdClass, "revents", "S");
1274
1275    // Turn the Java android.system.StructPollfd[] into a C++ struct pollfd[].
1276    size_t arrayLength = env->GetArrayLength(javaStructs);
1277    std::unique_ptr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
1278    memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength);
1279    size_t count = 0; // Some trailing array elements may be irrelevant. (See below.)
1280    for (size_t i = 0; i < arrayLength; ++i) {
1281        ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
1282        if (javaStruct.get() == NULL) {
1283            break; // We allow trailing nulls in the array for caller convenience.
1284        }
1285        ScopedLocalRef<jobject> javaFd(env, env->GetObjectField(javaStruct.get(), fdFid));
1286        if (javaFd.get() == NULL) {
1287            break; // We also allow callers to just clear the fd field (this is what Selector does).
1288        }
1289        fds[count].fd = jniGetFDFromFileDescriptor(env, javaFd.get());
1290        fds[count].events = env->GetShortField(javaStruct.get(), eventsFid);
1291        ++count;
1292    }
1293
1294    std::vector<AsynchronousCloseMonitor*> monitors;
1295    for (size_t i = 0; i < count; ++i) {
1296        monitors.push_back(new AsynchronousCloseMonitor(fds[i].fd));
1297    }
1298
1299    int rc;
1300    while (true) {
1301        timespec before;
1302        clock_gettime(CLOCK_MONOTONIC, &before);
1303
1304        rc = poll(fds.get(), count, timeoutMs);
1305        if (rc >= 0 || errno != EINTR) {
1306            break;
1307        }
1308
1309        // We got EINTR. Work out how much of the original timeout is still left.
1310        if (timeoutMs > 0) {
1311            timespec now;
1312            clock_gettime(CLOCK_MONOTONIC, &now);
1313
1314            timespec diff;
1315            diff.tv_sec = now.tv_sec - before.tv_sec;
1316            diff.tv_nsec = now.tv_nsec - before.tv_nsec;
1317            if (diff.tv_nsec < 0) {
1318                --diff.tv_sec;
1319                diff.tv_nsec += 1000000000;
1320            }
1321
1322            jint diffMs = diff.tv_sec * 1000 + diff.tv_nsec / 1000000;
1323            if (diffMs >= timeoutMs) {
1324                rc = 0; // We have less than 1ms left anyway, so just time out.
1325                break;
1326            }
1327
1328            timeoutMs -= diffMs;
1329        }
1330    }
1331
1332    for (size_t i = 0; i < monitors.size(); ++i) {
1333        delete monitors[i];
1334    }
1335    if (rc == -1) {
1336        throwErrnoException(env, "poll");
1337        return -1;
1338    }
1339
1340    // Update the revents fields in the Java android.system.StructPollfd[].
1341    for (size_t i = 0; i < count; ++i) {
1342        ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
1343        if (javaStruct.get() == NULL) {
1344            return -1;
1345        }
1346        env->SetShortField(javaStruct.get(), reventsFid, fds[i].revents);
1347    }
1348    return rc;
1349}
1350
1351static void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
1352                                  jlong offset __unused, jlong length __unused) {
1353#ifdef __APPLE__
1354    jniThrowException(env, "java/lang/UnsupportedOperationException",
1355                      "fallocate doesn't exist on a Mac");
1356#else
1357    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1358    while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) {
1359    }
1360    if (errno != 0) {
1361        throwErrnoException(env, "posix_fallocate");
1362    }
1363#endif
1364}
1365
1366static jint Posix_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused,
1367                        jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) {
1368#ifdef __APPLE__
1369    jniThrowException(env, "java/lang/UnsupportedOperationException", "prctl doesn't exist on a Mac");
1370    return 0;
1371#else
1372    int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option),
1373                                          static_cast<unsigned long>(arg2),
1374                                          static_cast<unsigned long>(arg3),
1375                                          static_cast<unsigned long>(arg4),
1376                                          static_cast<unsigned long>(arg5)));
1377    return throwIfMinusOne(env, "prctl", result);
1378#endif
1379}
1380
1381static jint Posix_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
1382    ScopedBytesRW bytes(env, javaBytes);
1383    if (bytes.get() == NULL) {
1384        return -1;
1385    }
1386    return IO_FAILURE_RETRY(env, ssize_t, pread64, javaFd, bytes.get() + byteOffset, byteCount, offset);
1387}
1388
1389static jint Posix_pwriteBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount, jlong offset) {
1390    ScopedBytesRO bytes(env, javaBytes);
1391    if (bytes.get() == NULL) {
1392        return -1;
1393    }
1394    return IO_FAILURE_RETRY(env, ssize_t, pwrite64, javaFd, bytes.get() + byteOffset, byteCount, offset);
1395}
1396
1397static jint Posix_readBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {
1398    ScopedBytesRW bytes(env, javaBytes);
1399    if (bytes.get() == NULL) {
1400        return -1;
1401    }
1402    return IO_FAILURE_RETRY(env, ssize_t, read, javaFd, bytes.get() + byteOffset, byteCount);
1403}
1404
1405static jstring Posix_readlink(JNIEnv* env, jobject, jstring javaPath) {
1406    ScopedUtfChars path(env, javaPath);
1407    if (path.c_str() == NULL) {
1408        return NULL;
1409    }
1410
1411    std::string result;
1412    if (!readlink(path.c_str(), result)) {
1413        throwErrnoException(env, "readlink");
1414        return NULL;
1415    }
1416    return env->NewStringUTF(result.c_str());
1417}
1418
1419static jint Posix_readv(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
1420    IoVec<ScopedBytesRW> ioVec(env, env->GetArrayLength(buffers));
1421    if (!ioVec.init(buffers, offsets, byteCounts)) {
1422        return -1;
1423    }
1424    return IO_FAILURE_RETRY(env, ssize_t, readv, javaFd, ioVec.get(), ioVec.size());
1425}
1426
1427static jint Posix_recvfromBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetSocketAddress) {
1428    ScopedBytesRW bytes(env, javaBytes);
1429    if (bytes.get() == NULL) {
1430        return -1;
1431    }
1432    sockaddr_storage ss;
1433    socklen_t sl = sizeof(ss);
1434    memset(&ss, 0, sizeof(ss));
1435    sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
1436    socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
1437    jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
1438    fillInetSocketAddress(env, recvCount, javaInetSocketAddress, ss);
1439    return recvCount;
1440}
1441
1442static void Posix_remove(JNIEnv* env, jobject, jstring javaPath) {
1443    ScopedUtfChars path(env, javaPath);
1444    if (path.c_str() == NULL) {
1445        return;
1446    }
1447    throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str())));
1448}
1449
1450static void Posix_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) {
1451    ScopedUtfChars path(env, javaPath);
1452    if (path.c_str() == NULL) {
1453        return;
1454    }
1455    ScopedUtfChars name(env, javaName);
1456    if (name.c_str() == NULL) {
1457        return;
1458    }
1459
1460    int res = removexattr(path.c_str(), name.c_str());
1461    if (res < 0) {
1462        throwErrnoException(env, "removexattr");
1463    }
1464}
1465
1466static void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1467    ScopedUtfChars oldPath(env, javaOldPath);
1468    if (oldPath.c_str() == NULL) {
1469        return;
1470    }
1471    ScopedUtfChars newPath(env, javaNewPath);
1472    if (newPath.c_str() == NULL) {
1473        return;
1474    }
1475    throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str())));
1476}
1477
1478static jlong Posix_sendfile(JNIEnv* env, jobject, jobject javaOutFd, jobject javaInFd, jobject javaOffset, jlong byteCount) {
1479    int outFd = jniGetFDFromFileDescriptor(env, javaOutFd);
1480    int inFd = jniGetFDFromFileDescriptor(env, javaInFd);
1481    static jfieldID valueFid = env->GetFieldID(JniConstants::mutableLongClass, "value", "J");
1482    off_t offset = 0;
1483    off_t* offsetPtr = NULL;
1484    if (javaOffset != NULL) {
1485        // TODO: fix bionic so we can have a 64-bit off_t!
1486        offset = env->GetLongField(javaOffset, valueFid);
1487        offsetPtr = &offset;
1488    }
1489    jlong result = throwIfMinusOne(env, "sendfile", TEMP_FAILURE_RETRY(sendfile(outFd, inFd, offsetPtr, byteCount)));
1490    if (javaOffset != NULL) {
1491        env->SetLongField(javaOffset, valueFid, offset);
1492    }
1493    return result;
1494}
1495
1496static jint Posix_sendtoBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetAddress, jint port) {
1497    ScopedBytesRO bytes(env, javaBytes);
1498    if (bytes.get() == NULL) {
1499        return -1;
1500    }
1501
1502    return NET_IPV4_FALLBACK(env, ssize_t, sendto, javaFd, javaInetAddress, port,
1503                             NULL_ADDR_OK, bytes.get() + byteOffset, byteCount, flags);
1504}
1505
1506static jint Posix_sendtoBytesSocketAddress(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaSocketAddress) {
1507    if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
1508        // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
1509        jobject javaInetAddress;
1510        jint port;
1511        javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
1512        return Posix_sendtoBytes(env, NULL, javaFd, javaBytes, byteOffset, byteCount, flags,
1513                                 javaInetAddress, port);
1514    }
1515
1516    ScopedBytesRO bytes(env, javaBytes);
1517    if (bytes.get() == NULL) {
1518        return -1;
1519    }
1520
1521    sockaddr_storage ss;
1522    socklen_t sa_len;
1523    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
1524        return -1;
1525    }
1526
1527    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
1528    // We don't need the return value because we'll already have thrown.
1529    return NET_FAILURE_RETRY(env, ssize_t, sendto, javaFd, bytes.get() + byteOffset, byteCount, flags, sa, sa_len);
1530}
1531
1532static void Posix_setegid(JNIEnv* env, jobject, jint egid) {
1533    throwIfMinusOne(env, "setegid", TEMP_FAILURE_RETRY(setegid(egid)));
1534}
1535
1536static void Posix_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue, jboolean overwrite) {
1537    ScopedUtfChars name(env, javaName);
1538    if (name.c_str() == NULL) {
1539        return;
1540    }
1541    ScopedUtfChars value(env, javaValue);
1542    if (value.c_str() == NULL) {
1543        return;
1544    }
1545    throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite));
1546}
1547
1548static void Posix_seteuid(JNIEnv* env, jobject, jint euid) {
1549    throwIfMinusOne(env, "seteuid", TEMP_FAILURE_RETRY(seteuid(euid)));
1550}
1551
1552static void Posix_setgid(JNIEnv* env, jobject, jint gid) {
1553    throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
1554}
1555
1556static void Posix_setpgid(JNIEnv* env, jobject, jint pid, int pgid) {
1557    throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid)));
1558}
1559
1560static void Posix_setregid(JNIEnv* env, jobject, jint rgid, int egid) {
1561    throwIfMinusOne(env, "setregid", TEMP_FAILURE_RETRY(setregid(rgid, egid)));
1562}
1563
1564static void Posix_setreuid(JNIEnv* env, jobject, jint ruid, int euid) {
1565    throwIfMinusOne(env, "setreuid", TEMP_FAILURE_RETRY(setreuid(ruid, euid)));
1566}
1567
1568static jint Posix_setsid(JNIEnv* env, jobject) {
1569    return throwIfMinusOne(env, "setsid", TEMP_FAILURE_RETRY(setsid()));
1570}
1571
1572static void Posix_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1573    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1574    u_char byte = value;
1575    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte))));
1576}
1577
1578static void Posix_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring javaInterfaceName) {
1579    struct ifreq req;
1580    if (!fillIfreq(env, javaInterfaceName, req)) {
1581        return;
1582    }
1583    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1584    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
1585}
1586
1587static void Posix_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1588    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1589    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1590}
1591
1592#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1070
1593// Mac OS didn't support modern multicast APIs until 10.7.
1594static void Posix_setsockoptIpMreqn(JNIEnv*, jobject, jobject, jint, jint, jint) { abort(); }
1595static void Posix_setsockoptGroupReq(JNIEnv*, jobject, jobject, jint, jint, jobject) { abort(); }
1596static void Posix_setsockoptGroupSourceReq(JNIEnv*, jobject, jobject, jint, jint, jobject) { abort(); }
1597#else
1598static void Posix_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1599    ip_mreqn req;
1600    memset(&req, 0, sizeof(req));
1601    req.imr_ifindex = value;
1602    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1603    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
1604}
1605
1606static void Posix_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) {
1607    struct group_req req;
1608    memset(&req, 0, sizeof(req));
1609
1610    static jfieldID grInterfaceFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_interface", "I");
1611    req.gr_interface = env->GetIntField(javaGroupReq, grInterfaceFid);
1612    // Get the IPv4 or IPv6 multicast address to join or leave.
1613    static jfieldID grGroupFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_group", "Ljava/net/InetAddress;");
1614    ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupReq, grGroupFid));
1615    socklen_t sa_len;
1616    if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gr_group, sa_len)) {
1617        return;
1618    }
1619
1620    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1621    int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
1622    if (rc == -1 && errno == EINVAL) {
1623        // Maybe we're a 32-bit binary talking to a 64-bit kernel?
1624        // glibc doesn't automatically handle this.
1625        // http://sourceware.org/bugzilla/show_bug.cgi?id=12080
1626        struct group_req64 {
1627            uint32_t gr_interface;
1628            uint32_t my_padding;
1629            sockaddr_storage gr_group;
1630        };
1631        group_req64 req64;
1632        req64.gr_interface = req.gr_interface;
1633        memcpy(&req64.gr_group, &req.gr_group, sizeof(req.gr_group));
1634        rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
1635    }
1636    throwIfMinusOne(env, "setsockopt", rc);
1637}
1638
1639static void Posix_setsockoptGroupSourceReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupSourceReq) {
1640    socklen_t sa_len;
1641    struct group_source_req req;
1642    memset(&req, 0, sizeof(req));
1643
1644    static jfieldID gsrInterfaceFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_interface", "I");
1645    req.gsr_interface = env->GetIntField(javaGroupSourceReq, gsrInterfaceFid);
1646    // Get the IPv4 or IPv6 multicast address to join or leave.
1647    static jfieldID gsrGroupFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_group", "Ljava/net/InetAddress;");
1648    ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupSourceReq, gsrGroupFid));
1649    if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gsr_group, sa_len)) {
1650        return;
1651    }
1652
1653    // Get the IPv4 or IPv6 multicast address to add to the filter.
1654    static jfieldID gsrSourceFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_source", "Ljava/net/InetAddress;");
1655    ScopedLocalRef<jobject> javaSource(env, env->GetObjectField(javaGroupSourceReq, gsrSourceFid));
1656    if (!inetAddressToSockaddrVerbatim(env, javaSource.get(), 0, req.gsr_source, sa_len)) {
1657        return;
1658    }
1659
1660    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1661    int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
1662    if (rc == -1 && errno == EINVAL) {
1663        // Maybe we're a 32-bit binary talking to a 64-bit kernel?
1664        // glibc doesn't automatically handle this.
1665        // http://sourceware.org/bugzilla/show_bug.cgi?id=12080
1666        struct group_source_req64 {
1667            uint32_t gsr_interface;
1668            uint32_t my_padding;
1669            sockaddr_storage gsr_group;
1670            sockaddr_storage gsr_source;
1671        };
1672        group_source_req64 req64;
1673        req64.gsr_interface = req.gsr_interface;
1674        memcpy(&req64.gsr_group, &req.gsr_group, sizeof(req.gsr_group));
1675        memcpy(&req64.gsr_source, &req.gsr_source, sizeof(req.gsr_source));
1676        rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
1677    }
1678    throwIfMinusOne(env, "setsockopt", rc);
1679}
1680#endif
1681
1682static void Posix_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) {
1683    static jfieldID lOnoffFid = env->GetFieldID(JniConstants::structLingerClass, "l_onoff", "I");
1684    static jfieldID lLingerFid = env->GetFieldID(JniConstants::structLingerClass, "l_linger", "I");
1685    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1686    struct linger value;
1687    value.l_onoff = env->GetIntField(javaLinger, lOnoffFid);
1688    value.l_linger = env->GetIntField(javaLinger, lLingerFid);
1689    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1690}
1691
1692static void Posix_setsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaTimeval) {
1693    static jfieldID tvSecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_sec", "J");
1694    static jfieldID tvUsecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_usec", "J");
1695    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1696    struct timeval value;
1697    value.tv_sec = env->GetLongField(javaTimeval, tvSecFid);
1698    value.tv_usec = env->GetLongField(javaTimeval, tvUsecFid);
1699    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1700}
1701
1702static void Posix_setuid(JNIEnv* env, jobject, jint uid) {
1703    throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid)));
1704}
1705
1706static void Posix_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName,
1707        jbyteArray javaValue, jint flags) {
1708    ScopedUtfChars path(env, javaPath);
1709    if (path.c_str() == NULL) {
1710        return;
1711    }
1712    ScopedUtfChars name(env, javaName);
1713    if (name.c_str() == NULL) {
1714        return;
1715    }
1716    ScopedBytesRO value(env, javaValue);
1717    if (value.get() == NULL) {
1718        return;
1719    }
1720    size_t valueLength = env->GetArrayLength(javaValue);
1721    int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags);
1722    if (res < 0) {
1723        throwErrnoException(env, "setxattr");
1724    }
1725}
1726
1727static void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
1728    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1729    throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how)));
1730}
1731
1732static jobject Posix_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
1733    if (domain == AF_PACKET) {
1734        protocol = htons(protocol);  // Packet sockets specify the protocol in host byte order.
1735    }
1736    int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
1737    return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
1738}
1739
1740static void Posix_socketpair(JNIEnv* env, jobject, jint domain, jint type, jint protocol, jobject javaFd1, jobject javaFd2) {
1741    int fds[2];
1742    int rc = throwIfMinusOne(env, "socketpair", TEMP_FAILURE_RETRY(socketpair(domain, type, protocol, fds)));
1743    if (rc != -1) {
1744        jniSetFileDescriptorOfFD(env, javaFd1, fds[0]);
1745        jniSetFileDescriptorOfFD(env, javaFd2, fds[1]);
1746    }
1747}
1748
1749static jobject Posix_stat(JNIEnv* env, jobject, jstring javaPath) {
1750    return doStat(env, javaPath, false);
1751}
1752
1753static jobject Posix_statvfs(JNIEnv* env, jobject, jstring javaPath) {
1754    ScopedUtfChars path(env, javaPath);
1755    if (path.c_str() == NULL) {
1756        return NULL;
1757    }
1758    struct statvfs sb;
1759    int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
1760    if (rc == -1) {
1761        throwErrnoException(env, "statvfs");
1762        return NULL;
1763    }
1764    return makeStructStatVfs(env, sb);
1765}
1766
1767static jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) {
1768    char buffer[BUFSIZ];
1769    const char* message = jniStrError(errnum, buffer, sizeof(buffer));
1770    return env->NewStringUTF(message);
1771}
1772
1773static jstring Posix_strsignal(JNIEnv* env, jobject, jint signal) {
1774    return env->NewStringUTF(strsignal(signal));
1775}
1776
1777static void Posix_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1778    ScopedUtfChars oldPath(env, javaOldPath);
1779    if (oldPath.c_str() == NULL) {
1780        return;
1781    }
1782    ScopedUtfChars newPath(env, javaNewPath);
1783    if (newPath.c_str() == NULL) {
1784        return;
1785    }
1786    throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str())));
1787}
1788
1789static jlong Posix_sysconf(JNIEnv* env, jobject, jint name) {
1790    // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward.
1791    errno = 0;
1792    long result = sysconf(name);
1793    if (result == -1L && errno == EINVAL) {
1794        throwErrnoException(env, "sysconf");
1795    }
1796    return result;
1797}
1798
1799static void Posix_tcdrain(JNIEnv* env, jobject, jobject javaFd) {
1800    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1801    throwIfMinusOne(env, "tcdrain", TEMP_FAILURE_RETRY(tcdrain(fd)));
1802}
1803
1804static void Posix_tcsendbreak(JNIEnv* env, jobject, jobject javaFd, jint duration) {
1805  int fd = jniGetFDFromFileDescriptor(env, javaFd);
1806  throwIfMinusOne(env, "tcsendbreak", TEMP_FAILURE_RETRY(tcsendbreak(fd, duration)));
1807}
1808
1809static jint Posix_umaskImpl(JNIEnv*, jobject, jint mask) {
1810    return umask(mask);
1811}
1812
1813static jobject Posix_uname(JNIEnv* env, jobject) {
1814    struct utsname buf;
1815    if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) {
1816        return NULL; // Can't happen.
1817    }
1818    return makeStructUtsname(env, buf);
1819}
1820
1821static void Posix_unsetenv(JNIEnv* env, jobject, jstring javaName) {
1822    ScopedUtfChars name(env, javaName);
1823    if (name.c_str() == NULL) {
1824        return;
1825    }
1826    throwIfMinusOne(env, "unsetenv", unsetenv(name.c_str()));
1827}
1828
1829static jint Posix_waitpid(JNIEnv* env, jobject, jint pid, jobject javaStatus, jint options) {
1830    int status;
1831    int rc = throwIfMinusOne(env, "waitpid", TEMP_FAILURE_RETRY(waitpid(pid, &status, options)));
1832    if (rc != -1) {
1833        static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
1834        env->SetIntField(javaStatus, valueFid, status);
1835    }
1836    return rc;
1837}
1838
1839static jint Posix_writeBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount) {
1840    ScopedBytesRO bytes(env, javaBytes);
1841    if (bytes.get() == NULL) {
1842        return -1;
1843    }
1844    return IO_FAILURE_RETRY(env, ssize_t, write, javaFd, bytes.get() + byteOffset, byteCount);
1845}
1846
1847static jint Posix_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
1848    IoVec<ScopedBytesRO> ioVec(env, env->GetArrayLength(buffers));
1849    if (!ioVec.init(buffers, offsets, byteCounts)) {
1850        return -1;
1851    }
1852    return IO_FAILURE_RETRY(env, ssize_t, writev, javaFd, ioVec.get(), ioVec.size());
1853}
1854
1855#define NATIVE_METHOD_OVERLOAD(className, functionName, signature, variant) \
1856    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) }
1857
1858static JNINativeMethod gMethods[] = {
1859    NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/InetSocketAddress;)Ljava/io/FileDescriptor;"),
1860    NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"),
1861    NATIVE_METHOD(Posix, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"),
1862    NATIVE_METHOD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
1863    NATIVE_METHOD_OVERLOAD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
1864    NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"),
1865    NATIVE_METHOD(Posix, chown, "(Ljava/lang/String;II)V"),
1866    NATIVE_METHOD(Posix, close, "(Ljava/io/FileDescriptor;)V"),
1867    NATIVE_METHOD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
1868    NATIVE_METHOD_OVERLOAD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
1869    NATIVE_METHOD(Posix, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"),
1870    NATIVE_METHOD(Posix, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"),
1871    NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"),
1872    NATIVE_METHOD(Posix, execv, "(Ljava/lang/String;[Ljava/lang/String;)V"),
1873    NATIVE_METHOD(Posix, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"),
1874    NATIVE_METHOD(Posix, fchmod, "(Ljava/io/FileDescriptor;I)V"),
1875    NATIVE_METHOD(Posix, fchown, "(Ljava/io/FileDescriptor;II)V"),
1876    NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"),
1877    NATIVE_METHOD(Posix, fcntlInt, "(Ljava/io/FileDescriptor;II)I"),
1878    NATIVE_METHOD(Posix, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"),
1879    NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"),
1880    NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Landroid/system/StructStat;"),
1881    NATIVE_METHOD(Posix, fstatvfs, "(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;"),
1882    NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
1883    NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
1884    NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"),
1885    NATIVE_METHOD(Posix, getegid, "()I"),
1886    NATIVE_METHOD(Posix, geteuid, "()I"),
1887    NATIVE_METHOD(Posix, getgid, "()I"),
1888    NATIVE_METHOD(Posix, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
1889    NATIVE_METHOD(Posix, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
1890    NATIVE_METHOD(Posix, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
1891    NATIVE_METHOD(Posix, getpgid, "(I)I"),
1892    NATIVE_METHOD(Posix, getpid, "()I"),
1893    NATIVE_METHOD(Posix, getppid, "()I"),
1894    NATIVE_METHOD(Posix, getpwnam, "(Ljava/lang/String;)Landroid/system/StructPasswd;"),
1895    NATIVE_METHOD(Posix, getpwuid, "(I)Landroid/system/StructPasswd;"),
1896    NATIVE_METHOD(Posix, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
1897    NATIVE_METHOD(Posix, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
1898    NATIVE_METHOD(Posix, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
1899    NATIVE_METHOD(Posix, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"),
1900    NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;"),
1901    NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Landroid/system/StructTimeval;"),
1902    NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"),
1903    NATIVE_METHOD(Posix, gettid, "()I"),
1904    NATIVE_METHOD(Posix, getuid, "()I"),
1905    NATIVE_METHOD(Posix, getxattr, "(Ljava/lang/String;Ljava/lang/String;[B)I"),
1906    NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
1907    NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
1908    NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"),
1909    NATIVE_METHOD(Posix, ioctlInt, "(Ljava/io/FileDescriptor;ILandroid/util/MutableInt;)I"),
1910    NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"),
1911    NATIVE_METHOD(Posix, kill, "(II)V"),
1912    NATIVE_METHOD(Posix, lchown, "(Ljava/lang/String;II)V"),
1913    NATIVE_METHOD(Posix, link, "(Ljava/lang/String;Ljava/lang/String;)V"),
1914    NATIVE_METHOD(Posix, listen, "(Ljava/io/FileDescriptor;I)V"),
1915    NATIVE_METHOD(Posix, lseek, "(Ljava/io/FileDescriptor;JI)J"),
1916    NATIVE_METHOD(Posix, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
1917    NATIVE_METHOD(Posix, mincore, "(JJ[B)V"),
1918    NATIVE_METHOD(Posix, mkdir, "(Ljava/lang/String;I)V"),
1919    NATIVE_METHOD(Posix, mkfifo, "(Ljava/lang/String;I)V"),
1920    NATIVE_METHOD(Posix, mlock, "(JJ)V"),
1921    NATIVE_METHOD(Posix, mmap, "(JJIILjava/io/FileDescriptor;J)J"),
1922    NATIVE_METHOD(Posix, msync, "(JJI)V"),
1923    NATIVE_METHOD(Posix, munlock, "(JJ)V"),
1924    NATIVE_METHOD(Posix, munmap, "(JJ)V"),
1925    NATIVE_METHOD(Posix, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"),
1926    NATIVE_METHOD(Posix, pipe2, "(I)[Ljava/io/FileDescriptor;"),
1927    NATIVE_METHOD(Posix, poll, "([Landroid/system/StructPollfd;I)I"),
1928    NATIVE_METHOD(Posix, posix_fallocate, "(Ljava/io/FileDescriptor;JJ)V"),
1929    NATIVE_METHOD(Posix, prctl, "(IJJJJ)I"),
1930    NATIVE_METHOD(Posix, preadBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
1931    NATIVE_METHOD(Posix, pwriteBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
1932    NATIVE_METHOD(Posix, readBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
1933    NATIVE_METHOD(Posix, readlink, "(Ljava/lang/String;)Ljava/lang/String;"),
1934    NATIVE_METHOD(Posix, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
1935    NATIVE_METHOD(Posix, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"),
1936    NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"),
1937    NATIVE_METHOD(Posix, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"),
1938    NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"),
1939    NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/util/MutableLong;J)J"),
1940    NATIVE_METHOD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"),
1941    NATIVE_METHOD_OVERLOAD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/SocketAddress;)I", SocketAddress),
1942    NATIVE_METHOD(Posix, setegid, "(I)V"),
1943    NATIVE_METHOD(Posix, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"),
1944    NATIVE_METHOD(Posix, seteuid, "(I)V"),
1945    NATIVE_METHOD(Posix, setgid, "(I)V"),
1946    NATIVE_METHOD(Posix, setpgid, "(II)V"),
1947    NATIVE_METHOD(Posix, setregid, "(II)V"),
1948    NATIVE_METHOD(Posix, setreuid, "(II)V"),
1949    NATIVE_METHOD(Posix, setsid, "()I"),
1950    NATIVE_METHOD(Posix, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"),
1951    NATIVE_METHOD(Posix, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"),
1952    NATIVE_METHOD(Posix, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"),
1953    NATIVE_METHOD(Posix, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"),
1954    NATIVE_METHOD(Posix, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupReq;)V"),
1955    NATIVE_METHOD(Posix, setsockoptGroupSourceReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupSourceReq;)V"),
1956    NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"),
1957    NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"),
1958    NATIVE_METHOD(Posix, setuid, "(I)V"),
1959    NATIVE_METHOD(Posix, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"),
1960    NATIVE_METHOD(Posix, shutdown, "(Ljava/io/FileDescriptor;I)V"),
1961    NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
1962    NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
1963    NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
1964    NATIVE_METHOD(Posix, statvfs, "(Ljava/lang/String;)Landroid/system/StructStatVfs;"),
1965    NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"),
1966    NATIVE_METHOD(Posix, strsignal, "(I)Ljava/lang/String;"),
1967    NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
1968    NATIVE_METHOD(Posix, sysconf, "(I)J"),
1969    NATIVE_METHOD(Posix, tcdrain, "(Ljava/io/FileDescriptor;)V"),
1970    NATIVE_METHOD(Posix, tcsendbreak, "(Ljava/io/FileDescriptor;I)V"),
1971    NATIVE_METHOD(Posix, umaskImpl, "(I)I"),
1972    NATIVE_METHOD(Posix, uname, "()Landroid/system/StructUtsname;"),
1973    NATIVE_METHOD(Posix, unsetenv, "(Ljava/lang/String;)V"),
1974    NATIVE_METHOD(Posix, waitpid, "(ILandroid/util/MutableInt;I)I"),
1975    NATIVE_METHOD(Posix, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
1976    NATIVE_METHOD(Posix, writev, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
1977};
1978void register_libcore_io_Posix(JNIEnv* env) {
1979    jniRegisterNativeMethods(env, "libcore/io/Posix", gMethods, NELEM(gMethods));
1980}
1981