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