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