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