libcore_io_Linux.cpp revision 6e888e9390649a9ab2557da5b28bb75be39e1b74
1ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes/*
2ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project
3ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes *
4ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * you may not use this file except in compliance with the License.
6ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * You may obtain a copy of the License at
7ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes *
8ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes *
10ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * See the License for the specific language governing permissions and
14ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * limitations under the License.
15ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes */
16ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes
17ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#define LOG_TAG "Posix"
18ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes
19f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller#include "AsynchronousCloseMonitor.h"
2015c1945bb1810d061ea2d5b07a11e3ecc5ec8536Ruben Brunk#include "cutils/log.h"
21ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes#include "ExecStrings.h"
22ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "JNIHelp.h"
23ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "JniConstants.h"
24ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include "JniException.h"
250a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes#include "NetworkUtilities.h"
266c1e5f4ad36c1f51687aa2b059e998a7c2db2e36Elliott Hughes#include "Portability.h"
270b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes#include "readlink.h"
280568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes#include "ScopedBytes.h"
29e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes#include "ScopedLocalRef.h"
300f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes#include "ScopedPrimitiveArray.h"
31ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "ScopedUtfChars.h"
32ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include "toStringArray.h"
33ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes
341c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes#include <arpa/inet.h>
35ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include <errno.h>
360ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <fcntl.h>
378f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline#include <linux/rtnetlink.h>
38b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes#include <net/if.h>
394f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes#include <netdb.h>
400a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes#include <netinet/in.h>
41a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti#include <netpacket/packet.h>
4270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes#include <poll.h>
43d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes#include <pwd.h>
44a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes#include <signal.h>
45ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include <stdlib.h>
46461d0d860814c68154d8dd06d24f94118f33d28aElliott Hughes#include <sys/ioctl.h>
477e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes#include <sys/mman.h>
485215e4c0db7530519981f1e505e6db82401802f2Nick Kralevich#include <sys/prctl.h>
4959e4744d27231f260271dbbca406e0cc39768116Elliott Hughes#include <sys/socket.h>
5047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes#include <sys/stat.h>
51069525a39125c203b658c805685b6045a7d4dfebElliott Hughes#include <sys/syscall.h>
520a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes#include <sys/time.h>
530ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <sys/types.h>
54bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes#include <sys/uio.h>
550ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller#include <sys/un.h>
567341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes#include <sys/utsname.h>
579e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes#include <sys/wait.h>
5890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey#include <sys/xattr.h>
59bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig#include <termios.h>
600ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <unistd.h>
61b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers#include <memory>
62efae3837b3eb79dea3400735fdcdd5a39020e0b0Ian Rogers
63efae3837b3eb79dea3400735fdcdd5a39020e0b0Ian Rogers#ifndef __unused
6437dd0ac5767197bf7e3e90f1a5d4e54c8f1fe93dIan Rogers#define __unused __attribute__((__unused__))
65efae3837b3eb79dea3400735fdcdd5a39020e0b0Ian Rogers#endif
6637dd0ac5767197bf7e3e90f1a5d4e54c8f1fe93dIan Rogers
67d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes#define TO_JAVA_STRING(NAME, EXP) \
68d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        jstring NAME = env->NewStringUTF(EXP); \
69d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        if (NAME == NULL) return NULL;
70d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
711c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughesstruct addrinfo_deleter {
721c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    void operator()(addrinfo* p) const {
731c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        if (p != NULL) { // bionic's freeaddrinfo(3) crashes when passed NULL.
741c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes            freeaddrinfo(p);
751c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        }
761c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
771c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes};
781c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
79b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colittistatic bool isIPv4MappedAddress(const sockaddr *sa) {
80b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    const sockaddr_in6 *sin6 = reinterpret_cast<const sockaddr_in6*>(sa);
81b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    return sa != NULL && sa->sa_family == AF_INET6 &&
82b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti           (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
83b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr));  // We map 0.0.0.0 to ::, so :: is mapped.
84b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti}
85b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti
86b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti/**
87b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * Perform a socket operation that specifies an IP address, possibly falling back from specifying
88b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * the address as an IPv4-mapped IPv6 address in a struct sockaddr_in6 to specifying it as an IPv4
89b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * address in a struct sockaddr_in.
90b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti *
91b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * This is needed because all sockets created by the java.net APIs are IPv6 sockets, and on those
92b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * sockets, IPv4 operations use IPv4-mapped addresses stored in a struct sockaddr_in6. But sockets
93b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * created using Posix.socket(AF_INET, ...) are IPv4 sockets and only support operations using IPv4
94b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti * socket addresses structures.
95b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti */
96b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti#define NET_IPV4_FALLBACK(jni_env, return_type, syscall_name, java_fd, java_addr, port, null_addr_ok, args...) ({ \
97b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    return_type _rc = -1; \
98b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    do { \
99b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        sockaddr_storage _ss; \
100b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        socklen_t _salen; \
101b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        if (java_addr == NULL && null_addr_ok) { \
102b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            /* No IP address specified (e.g., sendto() on a connected socket). */ \
103b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            _salen = 0; \
104b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        } else if (!inetAddressToSockaddr(jni_env, java_addr, port, _ss, _salen)) { \
105b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            /* Invalid socket address, return -1. inetAddressToSockaddr has already thrown. */ \
106b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            break; \
107b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        } \
108b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        sockaddr* _sa = _salen ? reinterpret_cast<sockaddr*>(&_ss) : NULL; \
109b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        /* inetAddressToSockaddr always returns an IPv6 sockaddr. Assume that java_fd was created \
110b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti         * by Java API calls, which always create IPv6 socket fds, and pass it in as is. */ \
111b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
112b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        if (_rc == -1 && errno == EAFNOSUPPORT && _salen && isIPv4MappedAddress(_sa)) { \
113b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            /* We passed in an IPv4 address in an IPv6 sockaddr and the kernel told us that we got \
114b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti             * the address family wrong. Pass in the same address in an IPv4 sockaddr. */ \
115b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            jni_env->ExceptionClear(); \
116b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            if (!inetAddressToSockaddrVerbatim(jni_env, java_addr, port, _ss, _salen)) { \
117b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti                break; \
118b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            } \
119b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            _sa = reinterpret_cast<sockaddr*>(&_ss); \
120b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti            _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
121b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti        } \
122b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    } while (0); \
123b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    _rc; }) \
124b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti
125996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes/**
126f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Used to retry networking system calls that can be interrupted with a signal. Unlike
127f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * TEMP_FAILURE_RETRY, this also handles the case where
128f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal a close() or
129f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Thread.interrupt(). Other signals that result in an EINTR result are ignored and the system call
130f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * is retried.
131996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes *
132f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Returns the result of the system call though a Java exception will be pending if the result is
133f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * -1:  a SocketException if signaled via AsynchronousCloseMonitor, or ErrnoException for other
134f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * failures.
135996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes */
1361124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes#define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
1371124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes    return_type _rc = -1; \
138b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    int _syscallErrno; \
139996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes    do { \
140f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        bool _wasSignaled; \
141996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes        { \
1421124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes            int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
143f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            AsynchronousCloseMonitor _monitor(_fd); \
1441124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes            _rc = syscall_name(_fd, __VA_ARGS__); \
145f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            _syscallErrno = errno; \
146f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            _wasSignaled = _monitor.wasSignaled(); \
147996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes        } \
148f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        if (_wasSignaled) { \
149f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            jniThrowException(jni_env, "java/net/SocketException", "Socket closed"); \
1505d7c0a378be3f7f505b30e634e7aabf072c4edd0Serguei Katkov            _rc = -1; \
151f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            break; \
152f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        } \
153f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        if (_rc == -1 && _syscallErrno != EINTR) { \
154f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            /* TODO: with a format string we could show the arguments too, like strace(1). */ \
155f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            throwErrnoException(jni_env, # syscall_name); \
156f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller            break; \
157f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        } \
158f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    } while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \
159b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    if (_rc == -1) { \
160b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti        /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
161b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti        errno = _syscallErrno; \
162b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    } \
163f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    _rc; })
164f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller
165f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller/**
166f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Used to retry system calls that can be interrupted with a signal. Unlike TEMP_FAILURE_RETRY, this
167f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * also handles the case where AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal
168f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * a close() or Thread.interrupt(). Other signals that result in an EINTR result are ignored and the
169f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * system call is retried.
170f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller *
171f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * Returns the result of the system call though a Java exception will be pending if the result is
172f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * -1: an IOException if the file descriptor is already closed, a InterruptedIOException if signaled
173f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller * via AsynchronousCloseMonitor, or ErrnoException for other failures.
174f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller */
175f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller#define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
176f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return_type _rc = -1; \
177b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    int _syscallErrno; \
17899a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller    do { \
17999a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        bool _wasSignaled; \
18099a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        { \
18199a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
18299a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            AsynchronousCloseMonitor _monitor(_fd); \
18399a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            _rc = syscall_name(_fd, __VA_ARGS__); \
18499a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            _syscallErrno = errno; \
18599a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            _wasSignaled = _monitor.wasSignaled(); \
18699a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        } \
18799a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        if (_wasSignaled) { \
18899a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \
18999a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            _rc = -1; \
19099a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            break; \
19199a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        } \
19299a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        if (_rc == -1 && _syscallErrno != EINTR) { \
19399a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            /* TODO: with a format string we could show the arguments too, like strace(1). */ \
19499a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            throwErrnoException(jni_env, # syscall_name); \
19599a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller            break; \
19699a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller        } \
19799a0c82619a88c6aea038757cf14090f5d33afebNeil Fuller    } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
198b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    if (_rc == -1) { \
199b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti        /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
200b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti        errno = _syscallErrno; \
201b4af0b52e1190846edde87f352ca722a7d9e0259Lorenzo Colitti    } \
202996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes    _rc; })
203996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes
204b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti#define NULL_ADDR_OK         true
205b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti#define NULL_ADDR_FORBIDDEN  false
206b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti
2074f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughesstatic void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
2084f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        const char* functionName, int error) {
209ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    jthrowable cause = NULL;
210ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    if (env->ExceptionCheck()) {
211ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes        cause = env->ExceptionOccurred();
212ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes        env->ExceptionClear();
213ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    }
214ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes
2154f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
2164f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    if (detailMessage.get() == NULL) {
217f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes        // Not really much we can do here. We're probably dead in the water,
218f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes        // but let's try to stumble on...
219f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes        env->ExceptionClear();
220f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes    }
221f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes
222ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    jobject exception;
223ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    if (cause != NULL) {
2244f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause);
225ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    } else {
2264f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error);
227ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    }
228ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    env->Throw(reinterpret_cast<jthrowable>(exception));
229dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes}
230dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes
2314f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughesstatic void throwErrnoException(JNIEnv* env, const char* functionName) {
2324f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    int error = errno;
2334f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    static jmethodID ctor3 = env->GetMethodID(JniConstants::errnoExceptionClass,
2344f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes            "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
2354f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    static jmethodID ctor2 = env->GetMethodID(JniConstants::errnoExceptionClass,
2364f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes            "<init>", "(Ljava/lang/String;I)V");
2374f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    throwException(env, JniConstants::errnoExceptionClass, ctor3, ctor2, functionName, error);
2384f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes}
2394f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes
2404f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughesstatic void throwGaiException(JNIEnv* env, const char* functionName, int error) {
241c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes  // Cache the methods ids before we throw, so we don't call GetMethodID with a pending exception.
242c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes  static jmethodID ctor3 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>",
243c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes                                            "(Ljava/lang/String;ILjava/lang/Throwable;)V");
244c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes  static jmethodID ctor2 = env->GetMethodID(JniConstants::gaiExceptionClass, "<init>",
245c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes                                            "(Ljava/lang/String;I)V");
246c1cee0db58ec7bc61d5caac79915d744862cbe75Elliott Hughes  if (errno != 0) {
24775cf14944d476670f6f915e5efd849e238a16250Elliott Hughes        // EAI_SYSTEM should mean "look at errno instead", but both glibc and bionic seem to
24875cf14944d476670f6f915e5efd849e238a16250Elliott Hughes        // mess this up. In particular, if you don't have INTERNET permission, errno will be EACCES
24975cf14944d476670f6f915e5efd849e238a16250Elliott Hughes        // but you'll get EAI_NONAME or EAI_NODATA. So we want our GaiException to have a
25075cf14944d476670f6f915e5efd849e238a16250Elliott Hughes        // potentially-relevant ErrnoException as its cause even if error != EAI_SYSTEM.
25175cf14944d476670f6f915e5efd849e238a16250Elliott Hughes        // http://code.google.com/p/android/issues/detail?id=15722
2524f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        throwErrnoException(env, functionName);
2534f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        // Deliberately fall through to throw another exception...
2544f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    }
2554f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    throwException(env, JniConstants::gaiExceptionClass, ctor3, ctor2, functionName, error);
2564f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes}
2574f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes
258dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughestemplate <typename rc_t>
2597e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) {
260dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    if (rc == rc_t(-1)) {
2617e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, name);
262dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    }
263dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    return rc;
26447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes}
26547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes
2668dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughestemplate <typename ScopedT>
267bbac92e691de7d570928ddfba639067978e55b06Elliott Hughesclass IoVec {
268bbac92e691de7d570928ddfba639067978e55b06Elliott Hughespublic:
269bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    IoVec(JNIEnv* env, size_t bufferCount) : mEnv(env), mBufferCount(bufferCount) {
270bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
271bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
272bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    bool init(jobjectArray javaBuffers, jintArray javaOffsets, jintArray javaByteCounts) {
273bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        // We can't delete our local references until after the I/O, so make sure we have room.
274bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        if (mEnv->PushLocalFrame(mBufferCount + 16) < 0) {
275bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            return false;
276bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        }
277bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        ScopedIntArrayRO offsets(mEnv, javaOffsets);
278bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        if (offsets.get() == NULL) {
279bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            return false;
280bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        }
281bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        ScopedIntArrayRO byteCounts(mEnv, javaByteCounts);
282bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        if (byteCounts.get() == NULL) {
283bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            return false;
284bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        }
285bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        // TODO: Linux actually has a 1024 buffer limit. glibc works around this, and we should too.
286d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        // TODO: you can query the limit at runtime with sysconf(_SC_IOV_MAX).
287bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        for (size_t i = 0; i < mBufferCount; ++i) {
288e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes            jobject buffer = mEnv->GetObjectArrayElement(javaBuffers, i); // We keep this local ref.
2898dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes            mScopedBuffers.push_back(new ScopedT(mEnv, buffer));
2908dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes            jbyte* ptr = const_cast<jbyte*>(mScopedBuffers.back()->get());
291bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            if (ptr == NULL) {
292bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes                return false;
293bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            }
294bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            struct iovec iov;
295bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            iov.iov_base = reinterpret_cast<void*>(ptr + offsets[i]);
296bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            iov.iov_len = byteCounts[i];
297bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes            mIoVec.push_back(iov);
298bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        }
299bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return true;
300bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
301bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
302bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    ~IoVec() {
3038dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes        for (size_t i = 0; i < mScopedBuffers.size(); ++i) {
3048dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes            delete mScopedBuffers[i];
305bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        }
306bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        mEnv->PopLocalFrame(NULL);
307bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
308bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
309bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    iovec* get() {
310bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return &mIoVec[0];
311bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
312bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
313bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    size_t size() {
314bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return mBufferCount;
315bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
316bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
317bbac92e691de7d570928ddfba639067978e55b06Elliott Hughesprivate:
318bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    JNIEnv* mEnv;
319bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    size_t mBufferCount;
320bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    std::vector<iovec> mIoVec;
3218dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes    std::vector<ScopedT*> mScopedBuffers;
322bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes};
323bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
3240ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller/**
3252550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller * Returns a jbyteArray containing the sockaddr_un.sun_path from ss. As per unix(7) sa_len should be
3262550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller * the length of ss as returned by getsockname(2), getpeername(2), or accept(2).
3272550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller * If the returned array is of length 0 the sockaddr_un refers to an unnamed socket.
3282550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller * A null pointer is returned in the event of an error. See unix(7) for more information.
3290ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller */
3302550a252387631b49a00d2ee5587717cd2a6dda3Neil Fullerstatic jbyteArray getUnixSocketPath(JNIEnv* env, const sockaddr_storage& ss,
3312550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        const socklen_t& sa_len) {
3320ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (ss.ss_family != AF_UNIX) {
3330ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
3340ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller                "getUnixSocketPath unsupported ss_family: %i", ss.ss_family);
3352550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return NULL;
3360ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
3372550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller
3380ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    const struct sockaddr_un* un_addr = reinterpret_cast<const struct sockaddr_un*>(&ss);
3392550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // The length of sun_path is sa_len minus the length of the overhead (ss_family).
3402550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // See unix(7) for details. This calculation must match that of socket_make_sockaddr_un() in
3412550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // socket_local_client.c and javaUnixSocketAddressToSockaddr() to interoperate.
3422550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    size_t pathLength = sa_len - offsetof(struct sockaddr_un, sun_path);
3432550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller
3442550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    jbyteArray javaSunPath = env->NewByteArray(pathLength);
3452550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    if (javaSunPath == NULL) {
3462550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return NULL;
3470ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
3482550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller
3492550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    if (pathLength > 0) {
3502550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        env->SetByteArrayRegion(javaSunPath, 0, pathLength,
3512550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller                reinterpret_cast<const jbyte*>(&un_addr->sun_path));
3522550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    }
3532550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    return javaSunPath;
3540ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller}
3550ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
3560ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const socklen_t sa_len) {
3570ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
3588f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        jint port;
3598f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        jobject inetAddress = sockaddrToInetAddress(env, ss, &port);
3608f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        if (inetAddress == NULL) {
3618f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline            return NULL;  // Exception already thrown.
3628f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        }
3638f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass,
3648f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline                "<init>", "(Ljava/net/InetAddress;I)V");
3658f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port);
3660ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    } else if (ss.ss_family == AF_UNIX) {
3670ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        static jmethodID ctor = env->GetMethodID(JniConstants::unixSocketAddressClass,
3680ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller                "<init>", "([B)V");
3690ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
3702550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
3712550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        if (!javaSunPath) {
3720ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            return NULL;
3730ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        }
3742550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return env->NewObject(JniConstants::unixSocketAddressClass, ctor, javaSunPath);
3758f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    } else if (ss.ss_family == AF_NETLINK) {
3768f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss);
3778f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass,
3788f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline                "<init>", "(II)V");
3796e888e9390649a9ab2557da5b28bb75be39e1b74Przemyslaw Szczepaniak        return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor,
3806e888e9390649a9ab2557da5b28bb75be39e1b74Przemyslaw Szczepaniak                static_cast<jint>(nl_addr->nl_pid),
3818f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline                static_cast<jint>(nl_addr->nl_groups));
38200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    } else if (ss.ss_family == AF_PACKET) {
38300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
38400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        static jmethodID ctor = env->GetMethodID(JniConstants::packetSocketAddressClass,
38500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                "<init>", "(SISB[B)V");
38600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(sll->sll_halen));
38700bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        if (byteArray.get() == NULL) {
38800bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            return NULL;
38900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        }
39000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen,
39100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                reinterpret_cast<const jbyte*>(sll->sll_addr));
39200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        jobject packetSocketAddress = env->NewObject(JniConstants::packetSocketAddressClass, ctor,
39300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                static_cast<jshort>(ntohs(sll->sll_protocol)),
39400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                static_cast<jint>(sll->sll_ifindex),
39500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                static_cast<jshort>(sll->sll_hatype),
39600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                static_cast<jbyte>(sll->sll_pkttype),
39700bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti                byteArray.get());
39800bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        return packetSocketAddress;
39900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    }
40000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "unsupported ss_family: %d",
40100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            ss.ss_family);
4028f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    return NULL;
4030a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
4040a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
405d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughesstatic jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) {
406d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(pw_name, pw.pw_name);
407d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(pw_dir, pw.pw_dir);
408d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(pw_shell, pw.pw_shell);
409d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structPasswdClass, "<init>",
410d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes            "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
411d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    return env->NewObject(JniConstants::structPasswdClass, ctor,
412d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes            pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell);
413d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes}
414d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
41547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject makeStructStat(JNIEnv* env, const struct stat& sb) {
41647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>",
41747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes            "(JJIJIIJJJJJJJ)V");
41847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    return env->NewObject(JniConstants::structStatClass, ctor,
41959fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino),
42059fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink),
42159fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid),
42259fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size),
42359fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jlong>(sb.st_atime), static_cast<jlong>(sb.st_mtime),
42459fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jlong>(sb.st_ctime), static_cast<jlong>(sb.st_blksize),
42559fa7163774d6930a174bc038414a4b780581957Elliott Hughes            static_cast<jlong>(sb.st_blocks));
42659fa7163774d6930a174bc038414a4b780581957Elliott Hughes}
42759fa7163774d6930a174bc038414a4b780581957Elliott Hughes
428721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughesstatic jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
429721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
430721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes            "(JJJJJJJJJJJ)V");
431721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    return env->NewObject(JniConstants::structStatVfsClass, ctor,
432721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_bsize),
433721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_frsize),
434721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_blocks),
435721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_bfree),
436721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_bavail),
437721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_files),
438721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_ffree),
439721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_favail),
440721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_fsid),
441721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes                          static_cast<jlong>(sb.f_flag),
442efe42934a8523f2b051a351e5eceebf6216454aeElliott Hughes                          static_cast<jlong>(sb.f_namemax));
44347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes}
44447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes
4450a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
4460a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structLingerClass, "<init>", "(II)V");
4470a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return env->NewObject(JniConstants::structLingerClass, ctor, l.l_onoff, l.l_linger);
4480a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
4490a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
4500a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) {
4510a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structTimevalClass, "<init>", "(JJ)V");
4520a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return env->NewObject(JniConstants::structTimevalClass, ctor,
4530a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes            static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
4540a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
4550a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
4563deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogersstatic jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) {
457482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  static jmethodID ctor = env->GetMethodID(JniConstants::structUcredClass, "<init>", "(III)V");
458482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  return env->NewObject(JniConstants::structUcredClass, ctor, u.pid, u.uid, u.gid);
459482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes}
460482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes
4617341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughesstatic jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
462d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(sysname, buf.sysname);
463d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(nodename, buf.nodename);
464d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(release, buf.release);
465d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(version, buf.version);
466d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    TO_JAVA_STRING(machine, buf.machine);
4677341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes    static jmethodID ctor = env->GetMethodID(JniConstants::structUtsnameClass, "<init>",
4687341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
4697341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes    return env->NewObject(JniConstants::structUtsnameClass, ctor,
4707341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes            sysname, nodename, release, version, machine);
4717341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes};
4727341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes
473a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesstatic bool fillIfreq(JNIEnv* env, jstring javaInterfaceName, struct ifreq& req) {
474a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    ScopedUtfChars interfaceName(env, javaInterfaceName);
475a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    if (interfaceName.c_str() == NULL) {
476a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return false;
477a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
478a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    memset(&req, 0, sizeof(req));
479a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name));
480a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
481a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    return true;
482a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes}
483a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
4840ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic bool fillUnixSocketAddress(JNIEnv* env, jobject javaUnixSocketAddress,
4850ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        const sockaddr_storage& ss, const socklen_t& sa_len) {
4860ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (javaUnixSocketAddress == NULL) {
4870ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return true;
4880ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
4892550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
4902550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    if (!javaSunPath) {
4910ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return false;
4920ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
4930ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
4940ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    static jfieldID sunPathFid =
4950ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            env->GetFieldID(JniConstants::unixSocketAddressClass, "sun_path", "[B");
4962550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    env->SetObjectField(javaUnixSocketAddress, sunPathFid, javaSunPath);
4970ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    return true;
4980ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller}
4990ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
5000ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic bool fillInetSocketAddress(JNIEnv* env, jobject javaInetSocketAddress,
5010ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        const sockaddr_storage& ss) {
5020ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (javaInetSocketAddress == NULL) {
503553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return true;
504553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    }
505553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    // Fill out the passed-in InetSocketAddress with the sender's IP address and port number.
506553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    jint port;
507553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    jobject sender = sockaddrToInetAddress(env, ss, &port);
508553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    if (sender == NULL) {
509553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return false;
510553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    }
5114cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    static jfieldID holderFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "holder",
5124cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath                                                "Ljava/net/InetSocketAddress$InetSocketAddressHolder;");
513ea544eccd7c78b693804d763dabbd8f7247dc802Piotr Jastrzebski    jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid);
514ea544eccd7c78b693804d763dabbd8f7247dc802Piotr Jastrzebski
5154cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    static jfieldID addressFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass,
5164cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath                                                 "addr", "Ljava/net/InetAddress;");
517ea544eccd7c78b693804d763dabbd8f7247dc802Piotr Jastrzebski    static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass, "port", "I");
518ea544eccd7c78b693804d763dabbd8f7247dc802Piotr Jastrzebski    env->SetObjectField(holder, addressFid, sender);
519ea544eccd7c78b693804d763dabbd8f7247dc802Piotr Jastrzebski    env->SetIntField(holder, portFid, port);
520553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    return true;
521553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes}
522553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes
5230ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic bool fillSocketAddress(JNIEnv* env, jobject javaSocketAddress, const sockaddr_storage& ss,
5240ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        const socklen_t& sa_len) {
5250ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (javaSocketAddress == NULL) {
5260ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return true;
5270ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
5280ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
5290ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
5300ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return fillInetSocketAddress(env, javaSocketAddress, ss);
5310ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) {
5320ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return fillUnixSocketAddress(env, javaSocketAddress, ss, sa_len);
5330ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
5340ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    jniThrowException(env, "java/lang/UnsupportedOperationException",
5350ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            "unsupported SocketAddress subclass");
5360ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    return false;
5370ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
5380ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller}
5390ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
540f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colittistatic void javaInetSocketAddressToInetAddressAndPort(
541f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        JNIEnv* env, jobject javaInetSocketAddress, jobject& javaInetAddress, jint& port) {
5424cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    static jfieldID holderFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "holder",
5434cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath                                                "Ljava/net/InetSocketAddress$InetSocketAddressHolder;");
5444cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid);
5454cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath
5468f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    static jfieldID addressFid = env->GetFieldID(
5474cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath            JniConstants::inetSocketAddressHolderClass, "addr", "Ljava/net/InetAddress;");
5484cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressHolderClass, "port", "I");
5494cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath
5504cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    javaInetAddress = env->GetObjectField(holder, addressFid);
5514cb97fe003dcf14ccd8f6e381cd172020248efaeNarayan Kamath    port = env->GetIntField(holder, portFid);
552f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti}
553f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti
554f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colittistatic bool javaInetSocketAddressToSockaddr(
555f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
556f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    jobject javaInetAddress;
557f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    jint port;
558f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
559f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    return inetAddressToSockaddr(env, javaInetAddress, port, ss, sa_len);
5608f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline}
5618f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
5628f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Klinestatic bool javaNetlinkSocketAddressToSockaddr(
5638f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
5648f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    static jfieldID nlPidFid = env->GetFieldID(
5658f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline            JniConstants::netlinkSocketAddressClass, "nlPortId", "I");
5668f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    static jfieldID nlGroupsFid = env->GetFieldID(
5678f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline            JniConstants::netlinkSocketAddressClass, "nlGroupsMask", "I");
5688f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
5698f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    sockaddr_nl *nlAddr = reinterpret_cast<sockaddr_nl *>(&ss);
5708f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    nlAddr->nl_family = AF_NETLINK;
5718f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    nlAddr->nl_pid = env->GetIntField(javaSocketAddress, nlPidFid);
5728f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    nlAddr->nl_groups = env->GetIntField(javaSocketAddress, nlGroupsFid);
5738f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    sa_len = sizeof(sockaddr_nl);
5748f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    return true;
5758f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline}
5768f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
5770ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic bool javaUnixSocketAddressToSockaddr(
5780ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        JNIEnv* env, jobject javaUnixSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
5790ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    static jfieldID sunPathFid = env->GetFieldID(
5800ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller            JniConstants::unixSocketAddressClass, "sun_path", "[B");
5810ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
5820ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    struct sockaddr_un* un_addr = reinterpret_cast<struct sockaddr_un*>(&ss);
5832550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    memset (un_addr, 0, sizeof(sockaddr_un));
5840ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    un_addr->sun_family = AF_UNIX;
5850ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
5860ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    jbyteArray javaSunPath = (jbyteArray) env->GetObjectField(javaUnixSocketAddress, sunPathFid);
5870ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    jsize pathLength = env->GetArrayLength(javaSunPath);
5882550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    if ((size_t) pathLength > sizeof(sockaddr_un::sun_path)) {
5892550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
5902550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller                "sun_path too long: max=%i, is=%i",
5912550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller                sizeof(sockaddr_un::sun_path), pathLength);
5922550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller        return false;
5930ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
5942550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    env->GetByteArrayRegion(javaSunPath, 0, pathLength, (jbyte*) un_addr->sun_path);
5952550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // sa_len is sun_path plus the length of the overhead (ss_family_t). See unix(7) for
5962550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // details. This calculation must match that of socket_make_sockaddr_un() in
5972550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    // socket_local_client.c and getUnixSocketPath() to interoperate.
5982550a252387631b49a00d2ee5587717cd2a6dda3Neil Fuller    sa_len = offsetof(struct sockaddr_un, sun_path) + pathLength;
5990ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    return true;
6000ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller}
6010ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller
60200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colittistatic bool javaPacketSocketAddressToSockaddr(
60300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
60400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    static jfieldID protocolFid = env->GetFieldID(
60500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            JniConstants::packetSocketAddressClass, "sll_protocol", "S");
60600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    static jfieldID ifindexFid = env->GetFieldID(
60700bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            JniConstants::packetSocketAddressClass, "sll_ifindex", "I");
60800bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    static jfieldID hatypeFid = env->GetFieldID(
60900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            JniConstants::packetSocketAddressClass, "sll_hatype", "S");
61000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    static jfieldID pkttypeFid = env->GetFieldID(
61100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            JniConstants::packetSocketAddressClass, "sll_pkttype", "B");
61200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    static jfieldID addrFid = env->GetFieldID(
61300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            JniConstants::packetSocketAddressClass, "sll_addr", "[B");
61400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti
61500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss);
61600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sll->sll_family = AF_PACKET;
617e0273519773d7b14680fe0aa8bc180836042f245Lorenzo Colitti    sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid));
61800bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid);
61900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid);
62000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid);
62100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti
62200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid);
62300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    if (sllAddr == NULL) {
62400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        sll->sll_halen = 0;
62500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        memset(&sll->sll_addr, 0, sizeof(sll->sll_addr));
62600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    } else {
62700bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        jsize len = env->GetArrayLength(sllAddr);
62800bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        if ((size_t) len > sizeof(sll->sll_addr)) {
62900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti            len = sizeof(sll->sll_addr);
63000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        }
63100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        sll->sll_halen = len;
63200bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        env->GetByteArrayRegion(sllAddr, 0, len, (jbyte*) sll->sll_addr);
63300bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    }
63400bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    sa_len = sizeof(sockaddr_ll);
63500bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    return true;
63600bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti}
63700bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti
6388f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Klinestatic bool javaSocketAddressToSockaddr(
6398f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
6408f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    if (javaSocketAddress == NULL) {
6418f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        jniThrowNullPointerException(env, NULL);
6428f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return false;
6438f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    }
6448f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
6458f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    if (env->IsInstanceOf(javaSocketAddress, JniConstants::netlinkSocketAddressClass)) {
6468f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
6478f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
6488f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
64900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::packetSocketAddressClass)) {
65000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
6510ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::unixSocketAddressClass)) {
6520ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller        return javaUnixSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
6538f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    }
6548f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    jniThrowException(env, "java/lang/UnsupportedOperationException",
6558f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline            "unsupported SocketAddress subclass");
6568f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    return false;
6578f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline}
6588f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
65947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) {
66047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    ScopedUtfChars path(env, javaPath);
66147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    if (path.c_str() == NULL) {
66247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes        return NULL;
66347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    }
66447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    struct stat sb;
66547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    int rc = isLstat ? TEMP_FAILURE_RETRY(lstat(path.c_str(), &sb))
66647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes                     : TEMP_FAILURE_RETRY(stat(path.c_str(), &sb));
667dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    if (rc == -1) {
6687e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, isLstat ? "lstat" : "stat");
66947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes        return NULL;
67047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    }
67147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    return makeStructStat(env, sb);
672ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes}
673ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes
674482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughesstatic jobject doGetSockName(JNIEnv* env, jobject javaFd, bool is_sockname) {
675482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  int fd = jniGetFDFromFileDescriptor(env, javaFd);
676482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  sockaddr_storage ss;
677482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
678482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  socklen_t byteCount = sizeof(ss);
679482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  memset(&ss, 0, byteCount);
680482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  int rc = is_sockname ? TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount))
681482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes      : TEMP_FAILURE_RETRY(getpeername(fd, sa, &byteCount));
682482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  if (rc == -1) {
683482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    throwErrnoException(env, is_sockname ? "getsockname" : "getpeername");
684482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    return NULL;
685482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  }
6860ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller  return makeSocketAddress(env, ss, byteCount);
687482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes}
688482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes
689d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughesclass Passwd {
690d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughespublic:
691d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
692d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
693d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        mBuffer.reset(new char[mBufferSize]);
694d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
695d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
696d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    jobject getpwnam(const char* name) {
697d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        return process("getpwnam_r", getpwnam_r(name, &mPwd, mBuffer.get(), mBufferSize, &mResult));
698d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
699d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
700d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    jobject getpwuid(uid_t uid) {
701d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        return process("getpwuid_r", getpwuid_r(uid, &mPwd, mBuffer.get(), mBufferSize, &mResult));
702d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
703d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
704d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    struct passwd* get() {
705d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        return mResult;
706d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
707d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
708d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughesprivate:
709d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    jobject process(const char* syscall, int error) {
710d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        if (mResult == NULL) {
711d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes            errno = error;
712d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes            throwErrnoException(mEnv, syscall);
713d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes            return NULL;
714d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        }
715d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        return makeStructPasswd(mEnv, *mResult);
716d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
717d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
718d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    JNIEnv* mEnv;
719b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers    std::unique_ptr<char[]> mBuffer;
720d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    size_t mBufferSize;
721d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    struct passwd mPwd;
722d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    struct passwd* mResult;
723d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes};
724d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
7250ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fullerstatic jobject Posix_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
726553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    sockaddr_storage ss;
727553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    socklen_t sl = sizeof(ss);
728553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    memset(&ss, 0, sizeof(ss));
7290ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    sockaddr* peer = (javaSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
7300ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    socklen_t* peerLength = (javaSocketAddress != NULL) ? &sl : 0;
7311124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes    jint clientFd = NET_FAILURE_RETRY(env, int, accept, javaFd, peer, peerLength);
7320ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    if (clientFd == -1 || !fillSocketAddress(env, javaSocketAddress, ss, *peerLength)) {
733553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        close(clientFd);
734553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes        return NULL;
735553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    }
736553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes    return (clientFd != -1) ? jniCreateFileDescriptor(env, clientFd) : NULL;
737553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes}
738553d98af897f7202de5e5a776287de0b5ca8fe39Elliott Hughes
739ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jboolean Posix_access(JNIEnv* env, jobject, jstring javaPath, jint mode) {
740ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    ScopedUtfChars path(env, javaPath);
741ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    if (path.c_str() == NULL) {
742ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes        return JNI_FALSE;
743ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    }
74447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode));
745dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    if (rc == -1) {
7467e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, "access");
747dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    }
748ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    return (rc == 0);
749ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes}
750ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes
751da15009528cc8300a6251f1d0931ac8657c9fc31Elliott Hughesstatic void Posix_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
7521124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes    // We don't need the return value because we'll already have thrown.
753b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    (void) NET_IPV4_FALLBACK(env, int, bind, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
754da15009528cc8300a6251f1d0931ac8657c9fc31Elliott Hughes}
755da15009528cc8300a6251f1d0931ac8657c9fc31Elliott Hughes
7568f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Klinestatic void Posix_bindSocketAddress(
7578f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
7588f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    sockaddr_storage ss;
7598f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    socklen_t sa_len;
7608f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
7618f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return;  // Exception already thrown.
7628f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    }
7638f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
7648f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
7658f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    // We don't need the return value because we'll already have thrown.
7668f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len);
7678f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline}
7688f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
769b7190190e0ef8de883c952efb319ce7748831faaElliott Hughesstatic void Posix_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) {
770b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes    ScopedUtfChars path(env, javaPath);
771b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes    if (path.c_str() == NULL) {
772b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes        return;
773b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes    }
774b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes    throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode)));
775b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes}
776b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes
77744f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughesstatic void Posix_chown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
77844f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    ScopedUtfChars path(env, javaPath);
77944f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    if (path.c_str() == NULL) {
78044f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes        return;
78144f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    }
78244f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    throwIfMinusOne(env, "chown", TEMP_FAILURE_RETRY(chown(path.c_str(), uid, gid)));
78344f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes}
78444f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes
785462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughesstatic void Posix_close(JNIEnv* env, jobject, jobject javaFd) {
786462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    // Get the FileDescriptor's 'fd' field and clear it.
787462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    // We need to do this before we can throw an IOException (http://b/3222087).
788462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
789462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    jniSetFileDescriptorOfFD(env, javaFd, -1);
790462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes
791462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    // Even if close(2) fails with EINTR, the fd will have been closed.
792462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
793462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
794462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    throwIfMinusOne(env, "close", close(fd));
795462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes}
796462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes
797996bf79565ac88402920bd826d6f85952c83be20Elliott Hughesstatic void Posix_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
798b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    (void) NET_IPV4_FALLBACK(env, int, connect, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
799996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes}
800996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes
8018f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Klinestatic void Posix_connectSocketAddress(
8028f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
8038f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    sockaddr_storage ss;
8048f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    socklen_t sa_len;
8058f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
8068f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline        return;  // Exception already thrown.
8078f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    }
8088f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
8098f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
8108f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    // We don't need the return value because we'll already have thrown.
8118f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len);
8128f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline}
8138f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
814396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jobject Posix_dup(JNIEnv* env, jobject, jobject javaOldFd) {
815396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
816396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd)));
817396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    return (newFd != -1) ? jniCreateFileDescriptor(env, newFd) : NULL;
818396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
819396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
820396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jobject Posix_dup2(JNIEnv* env, jobject, jobject javaOldFd, jint newFd) {
821396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
822396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    int fd = throwIfMinusOne(env, "dup2", TEMP_FAILURE_RETRY(dup2(oldFd, newFd)));
823396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    return (fd != -1) ? jniCreateFileDescriptor(env, fd) : NULL;
824396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
825396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
826ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jobjectArray Posix_environ(JNIEnv* env, jobject) {
827ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    extern char** environ; // Standard, but not in any header file.
828ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    return toStringArray(env, environ);
829ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes}
830ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes
831798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevichstatic void Posix_execve(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv, jobjectArray javaEnvp) {
832798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    ScopedUtfChars path(env, javaFilename);
833798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    if (path.c_str() == NULL) {
834798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich        return;
835798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    }
836798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
837ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes    ExecStrings argv(env, javaArgv);
838ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes    ExecStrings envp(env, javaEnvp);
839fa542091e45db699a937c5ac0191194405107827Elliott Hughes    TEMP_FAILURE_RETRY(execve(path.c_str(), argv.get(), envp.get()));
840798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
841798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    throwErrnoException(env, "execve");
842798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich}
843798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
844798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevichstatic void Posix_execv(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv) {
845798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    ScopedUtfChars path(env, javaFilename);
846798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    if (path.c_str() == NULL) {
847798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich        return;
848798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    }
849798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
850ad9208affa02f92a6b85354a33123d51d80febe1Elliott Hughes    ExecStrings argv(env, javaArgv);
851fa542091e45db699a937c5ac0191194405107827Elliott Hughes    TEMP_FAILURE_RETRY(execv(path.c_str(), argv.get()));
852798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
853798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    throwErrnoException(env, "execv");
854798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich}
855798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich
85644f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughesstatic void Posix_fchmod(JNIEnv* env, jobject, jobject javaFd, jint mode) {
85744f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
85844f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    throwIfMinusOne(env, "fchmod", TEMP_FAILURE_RETRY(fchmod(fd, mode)));
85944f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes}
86044f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes
86144f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughesstatic void Posix_fchown(JNIEnv* env, jobject, jobject javaFd, jint uid, jint gid) {
86244f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
86344f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid)));
86444f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes}
86544f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes
866fc549a0b0388987b26dea524894d75a63d14783bElliott Hughesstatic jint Posix_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) {
867fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    static jfieldID typeFid = env->GetFieldID(JniConstants::structFlockClass, "l_type", "S");
868fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    static jfieldID whenceFid = env->GetFieldID(JniConstants::structFlockClass, "l_whence", "S");
869fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    static jfieldID startFid = env->GetFieldID(JniConstants::structFlockClass, "l_start", "J");
870fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    static jfieldID lenFid = env->GetFieldID(JniConstants::structFlockClass, "l_len", "J");
871fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    static jfieldID pidFid = env->GetFieldID(JniConstants::structFlockClass, "l_pid", "I");
872fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes
873fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    struct flock64 lock;
874fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    memset(&lock, 0, sizeof(lock));
875fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    lock.l_type = env->GetShortField(javaFlock, typeFid);
876fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    lock.l_whence = env->GetShortField(javaFlock, whenceFid);
877fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    lock.l_start = env->GetLongField(javaFlock, startFid);
878fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    lock.l_len = env->GetLongField(javaFlock, lenFid);
879fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    lock.l_pid = env->GetIntField(javaFlock, pidFid);
880fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes
8818add3229ceb13f2aa5d15b84cc59f5ecc6b90214Neil Fuller    int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock);
882fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    if (rc != -1) {
883fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes        env->SetShortField(javaFlock, typeFid, lock.l_type);
884fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes        env->SetShortField(javaFlock, whenceFid, lock.l_whence);
885fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes        env->SetLongField(javaFlock, startFid, lock.l_start);
886fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes        env->SetLongField(javaFlock, lenFid, lock.l_len);
887fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes        env->SetIntField(javaFlock, pidFid, lock.l_pid);
888fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    }
889fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes    return rc;
890fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes}
891fc549a0b0388987b26dea524894d75a63d14783bElliott Hughes
892c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamathstatic jint Posix_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) {
893c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    int fd = jniGetFDFromFileDescriptor(env, javaFd);
894c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
895c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath}
896c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath
897c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamathstatic jint Posix_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) {
898c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    int fd = jniGetFDFromFileDescriptor(env, javaFd);
899c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd)));
900c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath}
901c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath
90252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesstatic void Posix_fdatasync(JNIEnv* env, jobject, jobject javaFd) {
90352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
9047e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd)));
90552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes}
90652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
90747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_fstat(JNIEnv* env, jobject, jobject javaFd) {
90847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
90947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    struct stat sb;
91047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    int rc = TEMP_FAILURE_RETRY(fstat(fd, &sb));
911dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    if (rc == -1) {
9127e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, "fstat");
91347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes        return NULL;
91447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    }
91547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    return makeStructStat(env, sb);
91647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes}
91747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes
918721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughesstatic jobject Posix_fstatvfs(JNIEnv* env, jobject, jobject javaFd) {
91959fa7163774d6930a174bc038414a4b780581957Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
920721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    struct statvfs sb;
921721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb));
92259fa7163774d6930a174bc038414a4b780581957Elliott Hughes    if (rc == -1) {
923721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes        throwErrnoException(env, "fstatvfs");
92459fa7163774d6930a174bc038414a4b780581957Elliott Hughes        return NULL;
92559fa7163774d6930a174bc038414a4b780581957Elliott Hughes    }
926721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    return makeStructStatVfs(env, sb);
92759fa7163774d6930a174bc038414a4b780581957Elliott Hughes}
92859fa7163774d6930a174bc038414a4b780581957Elliott Hughes
92952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesstatic void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) {
93052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
9317e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd)));
932f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes}
933f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes
934f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughesstatic void Posix_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) {
935f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
9367e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length)));
93752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes}
93852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes
9394f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughesstatic jstring Posix_gai_strerror(JNIEnv* env, jobject, jint error) {
9404f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    return env->NewStringUTF(gai_strerror(error));
9414f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes}
9424f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes
9433e58734d651080009c9190c7062837fca5c7cf4ePaul Jensenstatic jobjectArray Posix_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode,
9443e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen        jobject javaHints, jint netId) {
9451c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    ScopedUtfChars node(env, javaNode);
9461c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    if (node.c_str() == NULL) {
9471c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
9481c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
9491c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9501c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    static jfieldID flagsFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_flags", "I");
9511c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    static jfieldID familyFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_family", "I");
9521c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    static jfieldID socktypeFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_socktype", "I");
9531c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    static jfieldID protocolFid = env->GetFieldID(JniConstants::structAddrinfoClass, "ai_protocol", "I");
9541c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9551c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    addrinfo hints;
9561c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    memset(&hints, 0, sizeof(hints));
9571c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    hints.ai_flags = env->GetIntField(javaHints, flagsFid);
9581c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    hints.ai_family = env->GetIntField(javaHints, familyFid);
9591c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    hints.ai_socktype = env->GetIntField(javaHints, socktypeFid);
9601c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    hints.ai_protocol = env->GetIntField(javaHints, protocolFid);
9611c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9621c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    addrinfo* addressList = NULL;
96375cf14944d476670f6f915e5efd849e238a16250Elliott Hughes    errno = 0;
9643e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen    int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList);
965b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers    std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
9661c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    if (rc != 0) {
9673e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen        throwGaiException(env, "android_getaddrinfo", rc);
9681c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
9691c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
9701c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9711c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    // Count results so we know how to size the output array.
9721c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    int addressCount = 0;
9731c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
9741c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
9751c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes            ++addressCount;
9761c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        } else {
9773e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen            ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
9781c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        }
9791c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
9801c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    if (addressCount == 0) {
9811c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
9821c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
9831c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9841c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    // Prepare output array.
9851c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    jobjectArray result = env->NewObjectArray(addressCount, JniConstants::inetAddressClass, NULL);
9861c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    if (result == NULL) {
9871c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
9881c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
9891c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9901c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    // Examine returned addresses one by one, save them in the output array.
9911c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    int index = 0;
9921c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
9931c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
9941c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes            // Unknown address family. Skip this address.
9953e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen            ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
9961c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes            continue;
9971c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        }
9981c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
9991c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        // Convert each IP address into a Java byte array.
1000482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes        sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr);
100123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL));
10021c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        if (inetAddress.get() == NULL) {
10031c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes            return NULL;
10041c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        }
10051c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        env->SetObjectArrayElement(result, index, inetAddress.get());
10061c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        ++index;
10071c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
10081c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    return result;
10091c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes}
10101c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
1011396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_getegid(JNIEnv*, jobject) {
1012564312855784c9ae57e2af73affc48b0807b13eeElliott Hughes    return getegid();
1013396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1014396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1015396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_geteuid(JNIEnv*, jobject) {
1016564312855784c9ae57e2af73affc48b0807b13eeElliott Hughes    return geteuid();
1017396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1018396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1019396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_getgid(JNIEnv*, jobject) {
1020564312855784c9ae57e2af73affc48b0807b13eeElliott Hughes    return getgid();
1021396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1022396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1023ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughesstatic jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) {
1024ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes    ScopedUtfChars name(env, javaName);
1025ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes    if (name.c_str() == NULL) {
1026ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes        return NULL;
1027ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes    }
1028ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes    return env->NewStringUTF(getenv(name.c_str()));
1029ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes}
1030ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes
10314f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughesstatic jstring Posix_getnameinfo(JNIEnv* env, jobject, jobject javaAddress, jint flags) {
10324f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    sockaddr_storage ss;
1033482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    socklen_t sa_len;
1034482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    if (!inetAddressToSockaddrVerbatim(env, javaAddress, 0, ss, sa_len)) {
10354f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        return NULL;
10364f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    }
10374f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    char buf[NI_MAXHOST]; // NI_MAXHOST is longer than INET6_ADDRSTRLEN.
103875cf14944d476670f6f915e5efd849e238a16250Elliott Hughes    errno = 0;
1039482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_len, buf, sizeof(buf), NULL, 0, flags);
10404f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    if (rc != 0) {
10414f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        throwGaiException(env, "getnameinfo", rc);
10424f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes        return NULL;
10434f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    }
10444f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    return env->NewStringUTF(buf);
10454f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes}
10464f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes
1047482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughesstatic jobject Posix_getpeername(JNIEnv* env, jobject, jobject javaFd) {
1048482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  return doGetSockName(env, javaFd, false);
1049482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes}
1050482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes
10518f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughesstatic jint Posix_getpgid(JNIEnv* env, jobject, jint pid) {
10528f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    return throwIfMinusOne(env, "getpgid", TEMP_FAILURE_RETRY(getpgid(pid)));
10538f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes}
10548f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes
1055396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_getpid(JNIEnv*, jobject) {
1056fa542091e45db699a937c5ac0191194405107827Elliott Hughes    return TEMP_FAILURE_RETRY(getpid());
1057396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1058396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1059396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_getppid(JNIEnv*, jobject) {
1060fa542091e45db699a937c5ac0191194405107827Elliott Hughes    return TEMP_FAILURE_RETRY(getppid());
1061396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1062396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1063d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughesstatic jobject Posix_getpwnam(JNIEnv* env, jobject, jstring javaName) {
1064d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    ScopedUtfChars name(env, javaName);
1065d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    if (name.c_str() == NULL) {
1066d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes        return NULL;
1067d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    }
1068d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    return Passwd(env).getpwnam(name.c_str());
1069d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes}
1070d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
1071d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughesstatic jobject Posix_getpwuid(JNIEnv* env, jobject, jint uid) {
1072d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes    return Passwd(env).getpwuid(uid);
1073d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes}
1074d4419fce71d11ec8494525eca65e54d1aab51de6Elliott Hughes
10750a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject Posix_getsockname(JNIEnv* env, jobject, jobject javaFd) {
1076482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  return doGetSockName(env, javaFd, true);
10770a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
10780a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
10790a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jint Posix_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
10800a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
10810a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    u_char result = 0;
10820a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    socklen_t size = sizeof(result);
10830a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
10840a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return result;
10850a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
10860a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
10870a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject Posix_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
10880a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
10890a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    sockaddr_storage ss;
10900a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    memset(&ss, 0, sizeof(ss));
10910a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF.
10920a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
10930a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    socklen_t size = sizeof(sa->sin_addr);
10940a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size));
10950a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    if (rc == -1) {
10960a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        throwErrnoException(env, "getsockopt");
10970a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        return NULL;
10980a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    }
1099482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    return sockaddrToInetAddress(env, ss, NULL);
11000a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
11010a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
11020a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jint Posix_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
11030a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
11040a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    jint result = 0;
11050a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    socklen_t size = sizeof(result);
11060a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
11070a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return result;
11080a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
11090a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
11100a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject Posix_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
11110a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
11120a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    struct linger l;
11130a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    socklen_t size = sizeof(l);
11140a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    memset(&l, 0, size);
11150a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size));
11160a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    if (rc == -1) {
11170a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        throwErrnoException(env, "getsockopt");
11180a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        return NULL;
11190a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    }
11200a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return makeStructLinger(env, l);
11210a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
11220a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
11230a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughesstatic jobject Posix_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
11240a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
11250a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    struct timeval tv;
11260a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    socklen_t size = sizeof(tv);
11270a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    memset(&tv, 0, size);
11280a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size));
11290a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    if (rc == -1) {
11300a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        throwErrnoException(env, "getsockopt");
11310a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes        return NULL;
11320a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    }
11330a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    return makeStructTimeval(env, tv);
11340a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes}
11350a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes
1136482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughesstatic jobject Posix_getsockoptUcred(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1137482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  int fd = jniGetFDFromFileDescriptor(env, javaFd);
1138482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  struct ucred u;
1139482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  socklen_t size = sizeof(u);
1140482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  memset(&u, 0, size);
1141482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &u, &size));
1142482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  if (rc == -1) {
1143482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    throwErrnoException(env, "getsockopt");
1144482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    return NULL;
1145482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  }
1146482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes  return makeStructUcred(env, u);
1147482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes}
1148482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes
11493deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogersstatic jint Posix_gettid(JNIEnv* env __unused, jobject) {
1150efe42934a8523f2b051a351e5eceebf6216454aeElliott Hughes#if defined(__BIONIC__)
1151fa542091e45db699a937c5ac0191194405107827Elliott Hughes  return TEMP_FAILURE_RETRY(gettid());
11523deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogers#else
1153069525a39125c203b658c805685b6045a7d4dfebElliott Hughes  return syscall(__NR_gettid);
11543deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogers#endif
1155069525a39125c203b658c805685b6045a7d4dfebElliott Hughes}
1156069525a39125c203b658c805685b6045a7d4dfebElliott Hughes
1157396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic jint Posix_getuid(JNIEnv*, jobject) {
1158564312855784c9ae57e2af73affc48b0807b13eeElliott Hughes    return getuid();
1159396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1160396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
116190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkeystatic jint Posix_getxattr(JNIEnv* env, jobject, jstring javaPath,
116290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        jstring javaName, jbyteArray javaOutValue) {
116390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars path(env, javaPath);
116490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (path.c_str() == NULL) {
116590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return -1;
116690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
116790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars name(env, javaName);
116890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (name.c_str() == NULL) {
116990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return -1;
117090246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
117190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedBytesRW outValue(env, javaOutValue);
117290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (outValue.get() == NULL) {
117390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return -1;
117490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
117590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    size_t outValueLength = env->GetArrayLength(javaOutValue);
117690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ssize_t size = getxattr(path.c_str(), name.c_str(), outValue.get(), outValueLength);
117790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (size < 0) {
117890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        throwErrnoException(env, "getxattr");
117990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
118090246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    return size;
118190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey}
118290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey
1183a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesstatic jstring Posix_if_indextoname(JNIEnv* env, jobject, jint index) {
1184a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    char buf[IF_NAMESIZE];
1185a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    char* name = if_indextoname(index, buf);
1186a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    // if_indextoname(3) returns NULL on failure, which will come out of NewStringUTF unscathed.
1187a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    // There's no useful information in errno, so we don't bother throwing. Callers can null-check.
1188a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    return env->NewStringUTF(name);
1189a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes}
1190a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
1191fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughesstatic jobject Posix_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) {
11921c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    ScopedUtfChars name(env, javaName);
11931c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    if (name.c_str() == NULL) {
11941c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
11951c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
11961c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    sockaddr_storage ss;
11971c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    memset(&ss, 0, sizeof(ss));
1198fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughes    // sockaddr_in and sockaddr_in6 are at the same address, so we can use either here.
1199fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughes    void* dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr;
1200fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughes    if (inet_pton(family, name.c_str(), dst) != 1) {
12011c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes        return NULL;
12021c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes    }
1203fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughes    ss.ss_family = family;
1204482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    return sockaddrToInetAddress(env, ss, NULL);
12051c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes}
12061c039d71d3879f39e3a75b8788e656f7b4f88f08Elliott Hughes
1207a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesstatic jobject Posix_ioctlInetAddress(JNIEnv* env, jobject, jobject javaFd, jint cmd, jstring javaInterfaceName) {
1208a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    struct ifreq req;
1209a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    if (!fillIfreq(env, javaInterfaceName, req)) {
1210a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return NULL;
1211a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
1212a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1213a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &req)));
1214a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    if (rc == -1) {
1215a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes        return NULL;
1216a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    }
1217482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    return sockaddrToInetAddress(env, reinterpret_cast<sockaddr_storage&>(req.ifr_addr), NULL);
1218a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes}
1219a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes
12208b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughesstatic jint Posix_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) {
12218b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    // This is complicated because ioctls may return their result by updating their argument
12228b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    // or via their return value, so we need to support both.
1223461d0d860814c68154d8dd06d24f94118f33d28aElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
12248b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
12258b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    jint arg = env->GetIntField(javaArg, valueFid);
12268b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &arg)));
12278b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    if (!env->ExceptionCheck()) {
12288b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes        env->SetIntField(javaArg, valueFid, arg);
12298b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    }
12308b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    return rc;
1231461d0d860814c68154d8dd06d24f94118f33d28aElliott Hughes}
1232461d0d860814c68154d8dd06d24f94118f33d28aElliott Hughes
12339a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughesstatic jboolean Posix_isatty(JNIEnv* env, jobject, jobject javaFd) {
12349a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1235bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig    return TEMP_FAILURE_RETRY(isatty(fd)) == 1;
12369a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes}
12379a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes
1238a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughesstatic void Posix_kill(JNIEnv* env, jobject, jint pid, jint sig) {
1239a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes    throwIfMinusOne(env, "kill", TEMP_FAILURE_RETRY(kill(pid, sig)));
1240a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes}
1241a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes
124244f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughesstatic void Posix_lchown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
124344f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    ScopedUtfChars path(env, javaPath);
124444f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    if (path.c_str() == NULL) {
124544f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes        return;
124644f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    }
124744f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    throwIfMinusOne(env, "lchown", TEMP_FAILURE_RETRY(lchown(path.c_str(), uid, gid)));
124844f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes}
124944f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes
125004428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughesstatic void Posix_link(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
125104428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    ScopedUtfChars oldPath(env, javaOldPath);
125204428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    if (oldPath.c_str() == NULL) {
125304428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes        return;
125404428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    }
125504428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    ScopedUtfChars newPath(env, javaNewPath);
125604428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    if (newPath.c_str() == NULL) {
125704428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes        return;
125804428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    }
125904428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    throwIfMinusOne(env, "link", TEMP_FAILURE_RETRY(link(oldPath.c_str(), newPath.c_str())));
126004428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes}
126104428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes
1262e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughesstatic void Posix_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog) {
1263e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1264e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes    throwIfMinusOne(env, "listen", TEMP_FAILURE_RETRY(listen(fd, backlog)));
1265e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes}
1266e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes
1267dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesstatic jlong Posix_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) {
1268dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
12697e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)));
1270dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes}
1271dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes
127247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_lstat(JNIEnv* env, jobject, jstring javaPath) {
127347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    return doStat(env, javaPath, true);
127447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes}
127547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes
12760f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughesstatic void Posix_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) {
12770f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    ScopedByteArrayRW vector(env, javaVector);
12780f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    if (vector.get() == NULL) {
12790f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes        return;
12800f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    }
12810f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
12820f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get());
12830f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec)));
12840f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes}
12850f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes
1286c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughesstatic void Posix_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1287c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    ScopedUtfChars path(env, javaPath);
1288c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    if (path.c_str() == NULL) {
1289c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes        return;
1290c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    }
1291c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode)));
1292c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes}
1293c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes
1294f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fullerstatic void Posix_mkfifo(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1295f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    ScopedUtfChars path(env, javaPath);
1296f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    if (path.c_str() == NULL) {
1297f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        return;
1298f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    }
1299f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    throwIfMinusOne(env, "mkfifo", TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode)));
1300f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller}
1301f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller
13027e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughesstatic void Posix_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
13037e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
13047e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount)));
13057e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes}
13067e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes
13077e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic jlong Posix_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) {
13087e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
13097e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
13107e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    void* ptr = mmap(suggestedPtr, byteCount, prot, flags, fd, offset);
13117e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    if (ptr == MAP_FAILED) {
13127e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, "mmap");
13137e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    }
13147e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
13157e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes}
13167e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes
13177e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic void Posix_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) {
13187e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
13197e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags)));
13207e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes}
13217e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes
13227e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughesstatic void Posix_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
13237e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
13247e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount)));
13257e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes}
13267e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes
13277e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic void Posix_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) {
13287e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
13297e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount)));
13307e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes}
13317e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes
13320ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughesstatic jobject Posix_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) {
13330ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    ScopedUtfChars path(env, javaPath);
13340ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    if (path.c_str() == NULL) {
13350ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes        return NULL;
13360ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    }
13370ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
13380ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
13390ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes}
13400ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes
13415e92aa60a8a7103c71a4607ac05880e536f4195eElliott Hughesstatic jobjectArray Posix_pipe2(JNIEnv* env, jobject, jint flags __unused) {
134241f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    int fds[2];
13430d8b5c3692c36837d22c4e7d9c4d7d95f6a10235Elliott Hughes    throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(&fds[0], flags)));
134441f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    jobjectArray result = env->NewObjectArray(2, JniConstants::fileDescriptorClass, NULL);
134541f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    if (result == NULL) {
134641f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        return NULL;
134741f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    }
134841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    for (int i = 0; i < 2; ++i) {
134941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        ScopedLocalRef<jobject> fd(env, jniCreateFileDescriptor(env, fds[i]));
135041f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        if (fd.get() == NULL) {
135141f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes            return NULL;
135241f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        }
135341f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        env->SetObjectArrayElement(result, i, fd.get());
135441f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        if (env->ExceptionCheck()) {
135541f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes            return NULL;
135641f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes        }
135741f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    }
135841f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes    return result;
135941f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes}
136041f0605d2c809bd9bc1c0fb68d86b49a0f59b6c5Elliott Hughes
136170c820401677ca251ad09ac64cc23c760764e75dElliott Hughesstatic jint Posix_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) {
136270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    static jfieldID fdFid = env->GetFieldID(JniConstants::structPollfdClass, "fd", "Ljava/io/FileDescriptor;");
136370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    static jfieldID eventsFid = env->GetFieldID(JniConstants::structPollfdClass, "events", "S");
136470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    static jfieldID reventsFid = env->GetFieldID(JniConstants::structPollfdClass, "revents", "S");
136570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes
13665d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    // Turn the Java android.system.StructPollfd[] into a C++ struct pollfd[].
136770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    size_t arrayLength = env->GetArrayLength(javaStructs);
1368b3aacde3d8af759ee4a7b395c636ea360547d92dIan Rogers    std::unique_ptr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
136970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength);
137070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    size_t count = 0; // Some trailing array elements may be irrelevant. (See below.)
137170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    for (size_t i = 0; i < arrayLength; ++i) {
137270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
137370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        if (javaStruct.get() == NULL) {
137470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes            break; // We allow trailing nulls in the array for caller convenience.
137570c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        }
137670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        ScopedLocalRef<jobject> javaFd(env, env->GetObjectField(javaStruct.get(), fdFid));
137770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        if (javaFd.get() == NULL) {
137870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes            break; // We also allow callers to just clear the fd field (this is what Selector does).
137970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        }
138070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        fds[count].fd = jniGetFDFromFileDescriptor(env, javaFd.get());
138170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        fds[count].events = env->GetShortField(javaStruct.get(), eventsFid);
138270c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        ++count;
138370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    }
138470c820401677ca251ad09ac64cc23c760764e75dElliott Hughes
1385f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    std::vector<AsynchronousCloseMonitor*> monitors;
1386796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes    for (size_t i = 0; i < count; ++i) {
1387f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller        monitors.push_back(new AsynchronousCloseMonitor(fds[i].fd));
1388796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes    }
1389fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1390fa542091e45db699a937c5ac0191194405107827Elliott Hughes    int rc;
1391fa542091e45db699a937c5ac0191194405107827Elliott Hughes    while (true) {
1392fa542091e45db699a937c5ac0191194405107827Elliott Hughes        timespec before;
1393fa542091e45db699a937c5ac0191194405107827Elliott Hughes        clock_gettime(CLOCK_MONOTONIC, &before);
1394fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1395fa542091e45db699a937c5ac0191194405107827Elliott Hughes        rc = poll(fds.get(), count, timeoutMs);
1396fa542091e45db699a937c5ac0191194405107827Elliott Hughes        if (rc >= 0 || errno != EINTR) {
1397fa542091e45db699a937c5ac0191194405107827Elliott Hughes            break;
1398fa542091e45db699a937c5ac0191194405107827Elliott Hughes        }
1399fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1400fa542091e45db699a937c5ac0191194405107827Elliott Hughes        // We got EINTR. Work out how much of the original timeout is still left.
1401fa542091e45db699a937c5ac0191194405107827Elliott Hughes        if (timeoutMs > 0) {
1402fa542091e45db699a937c5ac0191194405107827Elliott Hughes            timespec now;
1403fa542091e45db699a937c5ac0191194405107827Elliott Hughes            clock_gettime(CLOCK_MONOTONIC, &now);
1404fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1405fa542091e45db699a937c5ac0191194405107827Elliott Hughes            timespec diff;
1406fa542091e45db699a937c5ac0191194405107827Elliott Hughes            diff.tv_sec = now.tv_sec - before.tv_sec;
1407fa542091e45db699a937c5ac0191194405107827Elliott Hughes            diff.tv_nsec = now.tv_nsec - before.tv_nsec;
1408fa542091e45db699a937c5ac0191194405107827Elliott Hughes            if (diff.tv_nsec < 0) {
1409fa542091e45db699a937c5ac0191194405107827Elliott Hughes                --diff.tv_sec;
1410fa542091e45db699a937c5ac0191194405107827Elliott Hughes                diff.tv_nsec += 1000000000;
1411fa542091e45db699a937c5ac0191194405107827Elliott Hughes            }
1412fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1413fa542091e45db699a937c5ac0191194405107827Elliott Hughes            jint diffMs = diff.tv_sec * 1000 + diff.tv_nsec / 1000000;
1414fa542091e45db699a937c5ac0191194405107827Elliott Hughes            if (diffMs >= timeoutMs) {
1415fa542091e45db699a937c5ac0191194405107827Elliott Hughes                rc = 0; // We have less than 1ms left anyway, so just time out.
1416fa542091e45db699a937c5ac0191194405107827Elliott Hughes                break;
1417fa542091e45db699a937c5ac0191194405107827Elliott Hughes            }
1418fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1419fa542091e45db699a937c5ac0191194405107827Elliott Hughes            timeoutMs -= diffMs;
1420fa542091e45db699a937c5ac0191194405107827Elliott Hughes        }
1421fa542091e45db699a937c5ac0191194405107827Elliott Hughes    }
1422fa542091e45db699a937c5ac0191194405107827Elliott Hughes
1423796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes    for (size_t i = 0; i < monitors.size(); ++i) {
1424796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes        delete monitors[i];
1425796f0d5a4e7b83c3efc5e587b6766977dc20b0c3Elliott Hughes    }
142670c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    if (rc == -1) {
142770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        throwErrnoException(env, "poll");
142870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        return -1;
142970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    }
143070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes
14315d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    // Update the revents fields in the Java android.system.StructPollfd[].
143298b23d4d9894d21be1eacf498f48aeb707ca1e41Elliott Hughes    for (size_t i = 0; i < count; ++i) {
143370c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
143498b23d4d9894d21be1eacf498f48aeb707ca1e41Elliott Hughes        if (javaStruct.get() == NULL) {
143598b23d4d9894d21be1eacf498f48aeb707ca1e41Elliott Hughes            return -1;
143698b23d4d9894d21be1eacf498f48aeb707ca1e41Elliott Hughes        }
143770c820401677ca251ad09ac64cc23c760764e75dElliott Hughes        env->SetShortField(javaStruct.get(), reventsFid, fds[i].revents);
143870c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    }
143970c820401677ca251ad09ac64cc23c760764e75dElliott Hughes    return rc;
144070c820401677ca251ad09ac64cc23c760764e75dElliott Hughes}
144170c820401677ca251ad09ac64cc23c760764e75dElliott Hughes
14423deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogersstatic void Posix_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
14433deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogers                                  jlong offset __unused, jlong length __unused) {
144411f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1445fa542091e45db699a937c5ac0191194405107827Elliott Hughes    while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) {
1446fa542091e45db699a937c5ac0191194405107827Elliott Hughes    }
144711f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    if (errno != 0) {
144811f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes        throwErrnoException(env, "posix_fallocate");
144911f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    }
145011f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes}
145111f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes
14523deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogersstatic jint Posix_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused,
14533deabd220cf7b1ca0824987e90b8ecc07087f05aIan Rogers                        jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) {
1454fa542091e45db699a937c5ac0191194405107827Elliott Hughes    int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option),
1455fa542091e45db699a937c5ac0191194405107827Elliott Hughes                                          static_cast<unsigned long>(arg2),
1456fa542091e45db699a937c5ac0191194405107827Elliott Hughes                                          static_cast<unsigned long>(arg3),
1457fa542091e45db699a937c5ac0191194405107827Elliott Hughes                                          static_cast<unsigned long>(arg4),
1458fa542091e45db699a937c5ac0191194405107827Elliott Hughes                                          static_cast<unsigned long>(arg5)));
14595215e4c0db7530519981f1e505e6db82401802f2Nick Kralevich    return throwIfMinusOne(env, "prctl", result);
14605215e4c0db7530519981f1e505e6db82401802f2Nick Kralevich}
14615215e4c0db7530519981f1e505e6db82401802f2Nick Kralevich
1462e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughesstatic jint Posix_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
1463e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    ScopedBytesRW bytes(env, javaBytes);
1464e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    if (bytes.get() == NULL) {
1465e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return -1;
1466e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
1467f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, pread64, javaFd, bytes.get() + byteOffset, byteCount, offset);
1468e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes}
1469e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
1470e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughesstatic jint Posix_pwriteBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount, jlong offset) {
1471e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    ScopedBytesRO bytes(env, javaBytes);
1472e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    if (bytes.get() == NULL) {
1473e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes        return -1;
1474e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    }
1475f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, pwrite64, javaFd, bytes.get() + byteOffset, byteCount, offset);
1476e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes}
1477e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes
14780568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughesstatic jint Posix_readBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {
14790568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    ScopedBytesRW bytes(env, javaBytes);
148026c7025a7a919044771fb89031161bd26fe03032Elliott Hughes    if (bytes.get() == NULL) {
148126c7025a7a919044771fb89031161bd26fe03032Elliott Hughes        return -1;
148226c7025a7a919044771fb89031161bd26fe03032Elliott Hughes    }
1483f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, read, javaFd, bytes.get() + byteOffset, byteCount);
148426c7025a7a919044771fb89031161bd26fe03032Elliott Hughes}
148526c7025a7a919044771fb89031161bd26fe03032Elliott Hughes
14860b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughesstatic jstring Posix_readlink(JNIEnv* env, jobject, jstring javaPath) {
14870b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    ScopedUtfChars path(env, javaPath);
14880b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    if (path.c_str() == NULL) {
14890b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes        return NULL;
14900b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    }
14910b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes
14920b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    std::string result;
14930b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    if (!readlink(path.c_str(), result)) {
14940b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes        throwErrnoException(env, "readlink");
14950b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes        return NULL;
14960b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    }
14970b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    return env->NewStringUTF(result.c_str());
14980b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes}
14990b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes
1500bbac92e691de7d570928ddfba639067978e55b06Elliott Hughesstatic jint Posix_readv(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
15018dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes    IoVec<ScopedBytesRW> ioVec(env, env->GetArrayLength(buffers));
1502bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    if (!ioVec.init(buffers, offsets, byteCounts)) {
1503bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return -1;
1504bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
1505f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, readv, javaFd, ioVec.get(), ioVec.size());
1506bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes}
1507bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
150823ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughesstatic jint Posix_recvfromBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetSocketAddress) {
150923ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    ScopedBytesRW bytes(env, javaBytes);
151023ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    if (bytes.get() == NULL) {
151123ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes        return -1;
151223ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    }
151323ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    sockaddr_storage ss;
151423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    socklen_t sl = sizeof(ss);
151523ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    memset(&ss, 0, sizeof(ss));
151623ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
151723ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
15181124a814d698ed6fd68ac501f5dddfa103d656fdElliott Hughes    jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
15196e888e9390649a9ab2557da5b28bb75be39e1b74Przemyslaw Szczepaniak    if (recvCount > 0) {
15206e888e9390649a9ab2557da5b28bb75be39e1b74Przemyslaw Szczepaniak        fillInetSocketAddress(env, javaInetSocketAddress, ss);
15210ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    }
152223ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    return recvCount;
152323ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes}
152423ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes
1525c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughesstatic void Posix_remove(JNIEnv* env, jobject, jstring javaPath) {
1526c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    ScopedUtfChars path(env, javaPath);
1527c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    if (path.c_str() == NULL) {
1528c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes        return;
1529c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    }
1530c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str())));
1531c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes}
1532c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes
153390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkeystatic void Posix_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) {
153490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars path(env, javaPath);
153590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (path.c_str() == NULL) {
153690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return;
153790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
153890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars name(env, javaName);
153990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (name.c_str() == NULL) {
154090246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return;
154190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
154290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey
154390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    int res = removexattr(path.c_str(), name.c_str());
154490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (res < 0) {
154590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        throwErrnoException(env, "removexattr");
154690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
154790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey}
154890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey
1549a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughesstatic void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1550a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    ScopedUtfChars oldPath(env, javaOldPath);
1551a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    if (oldPath.c_str() == NULL) {
1552a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes        return;
1553a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    }
1554a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    ScopedUtfChars newPath(env, javaNewPath);
1555a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    if (newPath.c_str() == NULL) {
1556a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes        return;
1557a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    }
1558a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str())));
1559a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes}
1560a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes
15618b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughesstatic jlong Posix_sendfile(JNIEnv* env, jobject, jobject javaOutFd, jobject javaInFd, jobject javaOffset, jlong byteCount) {
15628b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    int outFd = jniGetFDFromFileDescriptor(env, javaOutFd);
15638b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    int inFd = jniGetFDFromFileDescriptor(env, javaInFd);
15648b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    static jfieldID valueFid = env->GetFieldID(JniConstants::mutableLongClass, "value", "J");
15658b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    off_t offset = 0;
15668b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    off_t* offsetPtr = NULL;
15678b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    if (javaOffset != NULL) {
15688b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes        // TODO: fix bionic so we can have a 64-bit off_t!
15698b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes        offset = env->GetLongField(javaOffset, valueFid);
15708b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes        offsetPtr = &offset;
15718b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    }
15728b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    jlong result = throwIfMinusOne(env, "sendfile", TEMP_FAILURE_RETRY(sendfile(outFd, inFd, offsetPtr, byteCount)));
15738b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    if (javaOffset != NULL) {
15748b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes        env->SetLongField(javaOffset, valueFid, offset);
15758b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    }
15768b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes    return result;
15778b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes}
15788b15dcc5890963edad4dfcf558cc16027c7985e5Elliott Hughes
157990d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughesstatic jint Posix_sendtoBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetAddress, jint port) {
158090d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    ScopedBytesRO bytes(env, javaBytes);
158190d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    if (bytes.get() == NULL) {
158290d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes        return -1;
158390d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    }
1584b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti
1585b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti    return NET_IPV4_FALLBACK(env, ssize_t, sendto, javaFd, javaInetAddress, port,
1586b2a9923fa2006e384013734d3e1c6a7fbe3d9074Lorenzo Colitti                             NULL_ADDR_OK, bytes.get() + byteOffset, byteCount, flags);
158790d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes}
158890d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes
1589a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colittistatic jint Posix_sendtoBytesSocketAddress(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaSocketAddress) {
1590f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
1591f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
1592f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        jobject javaInetAddress;
1593f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        jint port;
1594f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
1595f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti        return Posix_sendtoBytes(env, NULL, javaFd, javaBytes, byteOffset, byteCount, flags,
1596f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti                                 javaInetAddress, port);
1597f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti    }
1598f5fc4ade3ab082f545e2aafdb1942c1f14e0df5dLorenzo Colitti
1599a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    ScopedBytesRO bytes(env, javaBytes);
1600a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    if (bytes.get() == NULL) {
1601a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti        return -1;
1602a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    }
1603a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti
1604a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    sockaddr_storage ss;
1605a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    socklen_t sa_len;
1606a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
1607a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti        return -1;
1608a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    }
1609a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti
1610a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
1611a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    // We don't need the return value because we'll already have thrown.
1612a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    return NET_FAILURE_RETRY(env, ssize_t, sendto, javaFd, bytes.get() + byteOffset, byteCount, flags, sa, sa_len);
1613a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti}
1614a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti
1615396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic void Posix_setegid(JNIEnv* env, jobject, jint egid) {
1616396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    throwIfMinusOne(env, "setegid", TEMP_FAILURE_RETRY(setegid(egid)));
1617396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1618396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1619895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughesstatic void Posix_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue, jboolean overwrite) {
1620895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    ScopedUtfChars name(env, javaName);
1621895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    if (name.c_str() == NULL) {
1622895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes        return;
1623895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    }
1624895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    ScopedUtfChars value(env, javaValue);
1625895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    if (value.c_str() == NULL) {
1626895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes        return;
1627895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    }
1628895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite));
1629895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes}
1630895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes
1631396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic void Posix_seteuid(JNIEnv* env, jobject, jint euid) {
1632396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    throwIfMinusOne(env, "seteuid", TEMP_FAILURE_RETRY(seteuid(euid)));
1633396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1634396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
1635396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic void Posix_setgid(JNIEnv* env, jobject, jint gid) {
1636396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
1637396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1638396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
16398f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughesstatic void Posix_setpgid(JNIEnv* env, jobject, jint pid, int pgid) {
16408f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid)));
16418f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes}
16428f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes
16438f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughesstatic void Posix_setregid(JNIEnv* env, jobject, jint rgid, int egid) {
16448f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    throwIfMinusOne(env, "setregid", TEMP_FAILURE_RETRY(setregid(rgid, egid)));
16458f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes}
16468f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes
16478f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughesstatic void Posix_setreuid(JNIEnv* env, jobject, jint ruid, int euid) {
16488f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    throwIfMinusOne(env, "setreuid", TEMP_FAILURE_RETRY(setreuid(ruid, euid)));
16498f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes}
16508f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes
16516c9b5377550a9649ed1532d1fcdfeba116c74eadElliott Hughesstatic jint Posix_setsid(JNIEnv* env, jobject) {
16526c9b5377550a9649ed1532d1fcdfeba116c74eadElliott Hughes    return throwIfMinusOne(env, "setsid", TEMP_FAILURE_RETRY(setsid()));
16536c9b5377550a9649ed1532d1fcdfeba116c74eadElliott Hughes}
16546c9b5377550a9649ed1532d1fcdfeba116c74eadElliott Hughes
1655c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughesstatic void Posix_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1656c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1657c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    u_char byte = value;
1658c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte))));
1659c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes}
1660c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes
1661a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughesstatic void Posix_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring javaInterfaceName) {
1662a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    struct ifreq req;
1663a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    if (!fillIfreq(env, javaInterfaceName, req)) {
1664b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes        return;
1665b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    }
1666b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1667b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
1668b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes}
1669b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes
1670454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughesstatic void Posix_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1671454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1672454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1673454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes}
1674454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes
1675b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughesstatic void Posix_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
1676b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    ip_mreqn req;
1677b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    memset(&req, 0, sizeof(req));
1678b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    req.imr_ifindex = value;
1679b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1680b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
1681b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes}
1682b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes
1683438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughesstatic void Posix_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) {
16848ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes    struct group_req req;
16858ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes    memset(&req, 0, sizeof(req));
1686438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes
1687438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    static jfieldID grInterfaceFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_interface", "I");
16888ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes    req.gr_interface = env->GetIntField(javaGroupReq, grInterfaceFid);
1689438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    // Get the IPv4 or IPv6 multicast address to join or leave.
1690438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    static jfieldID grGroupFid = env->GetFieldID(JniConstants::structGroupReqClass, "gr_group", "Ljava/net/InetAddress;");
1691e9f12043a1e2a29c60779cdb55c58eb156963570Elliott Hughes    ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupReq, grGroupFid));
1692482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    socklen_t sa_len;
1693482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gr_group, sa_len)) {
1694438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes        return;
1695438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    }
1696438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes
1697438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
16988ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes    int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
1699438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    if (rc == -1 && errno == EINVAL) {
1700438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes        // Maybe we're a 32-bit binary talking to a 64-bit kernel?
1701438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes        // glibc doesn't automatically handle this.
1702df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        // http://sourceware.org/bugzilla/show_bug.cgi?id=12080
17039634b569a92841f32268907c88c408f22cb00486Elliott Hughes        struct group_req64 {
1704438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes            uint32_t gr_interface;
1705438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes            uint32_t my_padding;
1706438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes            sockaddr_storage gr_group;
1707438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes        };
17088ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes        group_req64 req64;
17098ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes        req64.gr_interface = req.gr_interface;
17108ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes        memcpy(&req64.gr_group, &req.gr_group, sizeof(req.gr_group));
17118ecbb3f6a89983adb1a085469befc70488f4f04fElliott Hughes        rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
1712438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    }
1713438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes    throwIfMinusOne(env, "setsockopt", rc);
1714438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes}
1715df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
1716df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fullerstatic void Posix_setsockoptGroupSourceReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupSourceReq) {
1717df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    socklen_t sa_len;
1718df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    struct group_source_req req;
1719df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    memset(&req, 0, sizeof(req));
1720df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
1721df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    static jfieldID gsrInterfaceFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_interface", "I");
1722df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    req.gsr_interface = env->GetIntField(javaGroupSourceReq, gsrInterfaceFid);
1723df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    // Get the IPv4 or IPv6 multicast address to join or leave.
1724df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    static jfieldID gsrGroupFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_group", "Ljava/net/InetAddress;");
1725df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupSourceReq, gsrGroupFid));
1726df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gsr_group, sa_len)) {
1727df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        return;
1728df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    }
1729df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
1730df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    // Get the IPv4 or IPv6 multicast address to add to the filter.
1731df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    static jfieldID gsrSourceFid = env->GetFieldID(JniConstants::structGroupSourceReqClass, "gsr_source", "Ljava/net/InetAddress;");
1732df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    ScopedLocalRef<jobject> javaSource(env, env->GetObjectField(javaGroupSourceReq, gsrSourceFid));
1733df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    if (!inetAddressToSockaddrVerbatim(env, javaSource.get(), 0, req.gsr_source, sa_len)) {
1734df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        return;
1735df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    }
1736df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller
1737df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1738df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
1739df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    if (rc == -1 && errno == EINVAL) {
1740df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        // Maybe we're a 32-bit binary talking to a 64-bit kernel?
1741df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        // glibc doesn't automatically handle this.
1742df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        // http://sourceware.org/bugzilla/show_bug.cgi?id=12080
1743df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        struct group_source_req64 {
1744df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller            uint32_t gsr_interface;
1745df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller            uint32_t my_padding;
1746df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller            sockaddr_storage gsr_group;
1747df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller            sockaddr_storage gsr_source;
1748df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        };
1749df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        group_source_req64 req64;
1750df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        req64.gsr_interface = req.gsr_interface;
1751df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        memcpy(&req64.gsr_group, &req.gsr_group, sizeof(req.gsr_group));
1752df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        memcpy(&req64.gsr_source, &req.gsr_source, sizeof(req.gsr_source));
1753df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller        rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
1754df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    }
1755df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller    throwIfMinusOne(env, "setsockopt", rc);
1756df29508a7aa622f265aaebdc472eb7d679185ebbNeil Fuller}
1757438cb9e440d250c8aa5daf4fae0c400dce8b1499Elliott Hughes
1758c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughesstatic void Posix_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) {
1759c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    static jfieldID lOnoffFid = env->GetFieldID(JniConstants::structLingerClass, "l_onoff", "I");
1760c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    static jfieldID lLingerFid = env->GetFieldID(JniConstants::structLingerClass, "l_linger", "I");
1761c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1762c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    struct linger value;
1763c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    value.l_onoff = env->GetIntField(javaLinger, lOnoffFid);
1764c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    value.l_linger = env->GetIntField(javaLinger, lLingerFid);
1765c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1766c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes}
1767c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes
1768c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughesstatic void Posix_setsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaTimeval) {
1769c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    static jfieldID tvSecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_sec", "J");
1770c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    static jfieldID tvUsecFid = env->GetFieldID(JniConstants::structTimevalClass, "tv_usec", "J");
1771c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1772c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    struct timeval value;
177339fd5e164f93ab821841aa4d1fac09055c102b8bElliott Hughes    value.tv_sec = env->GetLongField(javaTimeval, tvSecFid);
177439fd5e164f93ab821841aa4d1fac09055c102b8bElliott Hughes    value.tv_usec = env->GetLongField(javaTimeval, tvUsecFid);
1775c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
1776c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes}
1777c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes
1778396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughesstatic void Posix_setuid(JNIEnv* env, jobject, jint uid) {
1779396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid)));
1780396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes}
1781396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes
178290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkeystatic void Posix_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName,
178390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        jbyteArray javaValue, jint flags) {
178490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars path(env, javaPath);
178590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (path.c_str() == NULL) {
178690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return;
178790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
178890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedUtfChars name(env, javaName);
178990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (name.c_str() == NULL) {
179090246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return;
179190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
179290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    ScopedBytesRO value(env, javaValue);
179390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (value.get() == NULL) {
179490246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        return;
179590246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
179690246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    size_t valueLength = env->GetArrayLength(javaValue);
179790246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags);
179890246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    if (res < 0) {
179990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey        throwErrnoException(env, "setxattr");
180090246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    }
180190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey}
180290246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey
180359e4744d27231f260271dbbca406e0cc39768116Elliott Hughesstatic void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
180459e4744d27231f260271dbbca406e0cc39768116Elliott Hughes    int fd = jniGetFDFromFileDescriptor(env, javaFd);
180559e4744d27231f260271dbbca406e0cc39768116Elliott Hughes    throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how)));
180659e4744d27231f260271dbbca406e0cc39768116Elliott Hughes}
180759e4744d27231f260271dbbca406e0cc39768116Elliott Hughes
1808454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughesstatic jobject Posix_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
180900bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    if (domain == AF_PACKET) {
181000bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti        protocol = htons(protocol);  // Packet sockets specify the protocol in host byte order.
181100bb2a5e5d619cbfd172793ca9bf7130192765ebLorenzo Colitti    }
1812454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
1813454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
1814454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes}
1815454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes
18163218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughesstatic void Posix_socketpair(JNIEnv* env, jobject, jint domain, jint type, jint protocol, jobject javaFd1, jobject javaFd2) {
18173218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    int fds[2];
18183218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    int rc = throwIfMinusOne(env, "socketpair", TEMP_FAILURE_RETRY(socketpair(domain, type, protocol, fds)));
18193218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    if (rc != -1) {
18203218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        jniSetFileDescriptorOfFD(env, javaFd1, fds[0]);
18213218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes        jniSetFileDescriptorOfFD(env, javaFd2, fds[1]);
18223218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    }
18233218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes}
18243218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes
182547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_stat(JNIEnv* env, jobject, jstring javaPath) {
182647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes    return doStat(env, javaPath, false);
182747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes}
182847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes
1829721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughesstatic jobject Posix_statvfs(JNIEnv* env, jobject, jstring javaPath) {
183059fa7163774d6930a174bc038414a4b780581957Elliott Hughes    ScopedUtfChars path(env, javaPath);
183159fa7163774d6930a174bc038414a4b780581957Elliott Hughes    if (path.c_str() == NULL) {
183259fa7163774d6930a174bc038414a4b780581957Elliott Hughes        return NULL;
183359fa7163774d6930a174bc038414a4b780581957Elliott Hughes    }
1834721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    struct statvfs sb;
1835721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
183659fa7163774d6930a174bc038414a4b780581957Elliott Hughes    if (rc == -1) {
1837721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes        throwErrnoException(env, "statvfs");
183859fa7163774d6930a174bc038414a4b780581957Elliott Hughes        return NULL;
183959fa7163774d6930a174bc038414a4b780581957Elliott Hughes    }
1840721ceca2a52a3c27aa751476c8562e1e68088e15Elliott Hughes    return makeStructStatVfs(env, sb);
184159fa7163774d6930a174bc038414a4b780581957Elliott Hughes}
184259fa7163774d6930a174bc038414a4b780581957Elliott Hughes
1843ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) {
184452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    char buffer[BUFSIZ];
1845ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    const char* message = jniStrError(errnum, buffer, sizeof(buffer));
1846ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    return env->NewStringUTF(message);
1847ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes}
1848ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes
1849763f8ed6195707d0c30bfae1ca8a3bb886b746ccElliott Hughesstatic jstring Posix_strsignal(JNIEnv* env, jobject, jint signal) {
1850763f8ed6195707d0c30bfae1ca8a3bb886b746ccElliott Hughes    return env->NewStringUTF(strsignal(signal));
1851763f8ed6195707d0c30bfae1ca8a3bb886b746ccElliott Hughes}
1852763f8ed6195707d0c30bfae1ca8a3bb886b746ccElliott Hughes
1853a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughesstatic void Posix_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1854a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    ScopedUtfChars oldPath(env, javaOldPath);
1855a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    if (oldPath.c_str() == NULL) {
1856a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes        return;
1857a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    }
1858a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    ScopedUtfChars newPath(env, javaNewPath);
1859a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    if (newPath.c_str() == NULL) {
1860a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes        return;
1861a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    }
1862a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str())));
1863a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes}
1864a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes
18656fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughesstatic jlong Posix_sysconf(JNIEnv* env, jobject, jint name) {
18666fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward.
18676fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    errno = 0;
18686fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    long result = sysconf(name);
18696fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    if (result == -1L && errno == EINVAL) {
18707e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes        throwErrnoException(env, "sysconf");
18716fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    }
18726fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    return result;
18736fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes}
18746fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes
1875bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestigstatic void Posix_tcdrain(JNIEnv* env, jobject, jobject javaFd) {
1876bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig    int fd = jniGetFDFromFileDescriptor(env, javaFd);
1877bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig    throwIfMinusOne(env, "tcdrain", TEMP_FAILURE_RETRY(tcdrain(fd)));
1878bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig}
1879bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig
1880039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughesstatic void Posix_tcsendbreak(JNIEnv* env, jobject, jobject javaFd, jint duration) {
1881039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughes  int fd = jniGetFDFromFileDescriptor(env, javaFd);
1882039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughes  throwIfMinusOne(env, "tcsendbreak", TEMP_FAILURE_RETRY(tcsendbreak(fd, duration)));
1883039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughes}
1884039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughes
1885c79d3ef4dcd25f0e264bf957861e2632da93e62dNick Kralevichstatic jint Posix_umaskImpl(JNIEnv*, jobject, jint mask) {
188644f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    return umask(mask);
188744f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes}
188844f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes
18897341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughesstatic jobject Posix_uname(JNIEnv* env, jobject) {
18907341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes    struct utsname buf;
18919b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes    if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) {
18929b510df35b57946d843ffc34cf23fdcfc84c5220Elliott Hughes        return NULL; // Can't happen.
18937341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes    }
18947341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes    return makeStructUtsname(env, buf);
18957341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes}
18967341b9ed7157a1e37a3e69a0974676da358b735aElliott Hughes
18975e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fullerstatic void Posix_unlink(JNIEnv* env, jobject, jstring javaPathname) {
18985e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller    ScopedUtfChars pathname(env, javaPathname);
18995e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller    if (pathname.c_str() == NULL) {
19005e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller        return;
19015e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller    }
19025e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller    throwIfMinusOne(env, "unlink", unlink(pathname.c_str()));
19035e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller}
19045e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller
1905895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughesstatic void Posix_unsetenv(JNIEnv* env, jobject, jstring javaName) {
1906895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    ScopedUtfChars name(env, javaName);
1907895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    if (name.c_str() == NULL) {
1908895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes        return;
1909895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    }
1910895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    throwIfMinusOne(env, "unsetenv", unsetenv(name.c_str()));
1911895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes}
1912895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes
19139e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughesstatic jint Posix_waitpid(JNIEnv* env, jobject, jint pid, jobject javaStatus, jint options) {
19149e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes    int status;
19159e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes    int rc = throwIfMinusOne(env, "waitpid", TEMP_FAILURE_RETRY(waitpid(pid, &status, options)));
19169e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes    if (rc != -1) {
19179e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes        static jfieldID valueFid = env->GetFieldID(JniConstants::mutableIntClass, "value", "I");
19189e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes        env->SetIntField(javaStatus, valueFid, status);
19199e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes    }
19209e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes    return rc;
19219e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes}
19229e67ca71d3d4a489a157abadc5ba519ced7a0b50Elliott Hughes
19230568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughesstatic jint Posix_writeBytes(JNIEnv* env, jobject, jobject javaFd, jbyteArray javaBytes, jint byteOffset, jint byteCount) {
19240568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    ScopedBytesRO bytes(env, javaBytes);
192578c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes    if (bytes.get() == NULL) {
192678c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes        return -1;
192778c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes    }
1928f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, write, javaFd, bytes.get() + byteOffset, byteCount);
192978c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes}
193078c7cc547101002b9f9043cf3845970719d1bda8Elliott Hughes
1931bbac92e691de7d570928ddfba639067978e55b06Elliott Hughesstatic jint Posix_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
19328dc754726bb5303c25e2c48decdf76d9323ee231Elliott Hughes    IoVec<ScopedBytesRO> ioVec(env, env->GetArrayLength(buffers));
1933bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    if (!ioVec.init(buffers, offsets, byteCounts)) {
1934bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes        return -1;
1935bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    }
1936f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    return IO_FAILURE_RETRY(env, ssize_t, writev, javaFd, ioVec.get(), ioVec.size());
1937bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes}
1938bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes
19398f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline#define NATIVE_METHOD_OVERLOAD(className, functionName, signature, variant) \
19408f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) }
19418f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline
1942ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughesstatic JNINativeMethod gMethods[] = {
19430ab1a26ca767ae36fbbe27b62893670b208fa494Neil Fuller    NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;"),
1944ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"),
19453e58734d651080009c9190c7062837fca5c7cf4ePaul Jensen    NATIVE_METHOD(Posix, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"),
1946da15009528cc8300a6251f1d0931ac8657c9fc31Elliott Hughes    NATIVE_METHOD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
19478f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    NATIVE_METHOD_OVERLOAD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
1948b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes    NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"),
194944f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    NATIVE_METHOD(Posix, chown, "(Ljava/lang/String;II)V"),
1950462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes    NATIVE_METHOD(Posix, close, "(Ljava/io/FileDescriptor;)V"),
1951996bf79565ac88402920bd826d6f85952c83be20Elliott Hughes    NATIVE_METHOD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
19528f5b46d72e5c1b1b1dd4357580c4fb5a60e3f4deErik Kline    NATIVE_METHOD_OVERLOAD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
1953396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"),
1954396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"),
1955ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"),
1956798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    NATIVE_METHOD(Posix, execv, "(Ljava/lang/String;[Ljava/lang/String;)V"),
1957798f855f67b74d481346d9dc2293ba0eedd8daf9Nick Kralevich    NATIVE_METHOD(Posix, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"),
195844f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    NATIVE_METHOD(Posix, fchmod, "(Ljava/io/FileDescriptor;I)V"),
195944f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    NATIVE_METHOD(Posix, fchown, "(Ljava/io/FileDescriptor;II)V"),
19605d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"),
1961c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    NATIVE_METHOD(Posix, fcntlInt, "(Ljava/io/FileDescriptor;II)I"),
1962c8d9ea662de6f4856b28907b4119087cfc5a44d2Narayan Kamath    NATIVE_METHOD(Posix, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"),
196352724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"),
19645d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Landroid/system/StructStat;"),
19655d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, fstatvfs, "(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;"),
196652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes    NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
1967f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes    NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
19684f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"),
1969396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, getegid, "()I"),
1970396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, geteuid, "()I"),
1971396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, getgid, "()I"),
1972ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes    NATIVE_METHOD(Posix, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
19734f11ebea266eada830d507b8f011e811a8e5d7bcElliott Hughes    NATIVE_METHOD(Posix, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
1974482a3fc5635ac431b8a7476d7fe3397af4c2e8ecElliott Hughes    NATIVE_METHOD(Posix, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
19758f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    NATIVE_METHOD(Posix, getpgid, "(I)I"),
1976396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, getpid, "()I"),
1977396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, getppid, "()I"),
19785d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, getpwnam, "(Ljava/lang/String;)Landroid/system/StructPasswd;"),
19795d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, getpwuid, "(I)Landroid/system/StructPasswd;"),
19800a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    NATIVE_METHOD(Posix, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
19810a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    NATIVE_METHOD(Posix, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
19820a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    NATIVE_METHOD(Posix, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
19830a9d1ee45a9884a9616624d747172e18734e8fe0Elliott Hughes    NATIVE_METHOD(Posix, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"),
19845d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;"),
19855d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Landroid/system/StructTimeval;"),
19865d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"),
1987069525a39125c203b658c805685b6045a7d4dfebElliott Hughes    NATIVE_METHOD(Posix, gettid, "()I"),
1988396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, getuid, "()I"),
198990246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    NATIVE_METHOD(Posix, getxattr, "(Ljava/lang/String;Ljava/lang/String;[B)I"),
1990a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
1991fc041ff241f9a7556e72236f130de0215ecd17dbElliott Hughes    NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
1992a37e971343883bb582a93ffbd9f0ba84f10e55baElliott Hughes    NATIVE_METHOD(Posix, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"),
19935d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, ioctlInt, "(Ljava/io/FileDescriptor;ILandroid/util/MutableInt;)I"),
19949a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes    NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"),
1995a5fb706fe4a6dbeaaf4cb1f8bbc2c68b0a2a3f3cElliott Hughes    NATIVE_METHOD(Posix, kill, "(II)V"),
199644f7875f2985d7944c5afecc8394ad9f2219c806Elliott Hughes    NATIVE_METHOD(Posix, lchown, "(Ljava/lang/String;II)V"),
199704428d61d7000e17ab21d08a1d672c34eb68f6e2Elliott Hughes    NATIVE_METHOD(Posix, link, "(Ljava/lang/String;Ljava/lang/String;)V"),
1998e1502d64e937001636fca3d62b2552ef2a34d05fElliott Hughes    NATIVE_METHOD(Posix, listen, "(Ljava/io/FileDescriptor;I)V"),
1999dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes    NATIVE_METHOD(Posix, lseek, "(Ljava/io/FileDescriptor;JI)J"),
20005d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
20010f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes    NATIVE_METHOD(Posix, mincore, "(JJ[B)V"),
2002c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    NATIVE_METHOD(Posix, mkdir, "(Ljava/lang/String;I)V"),
2003f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller    NATIVE_METHOD(Posix, mkfifo, "(Ljava/lang/String;I)V"),
20047e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    NATIVE_METHOD(Posix, mlock, "(JJ)V"),
20057e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    NATIVE_METHOD(Posix, mmap, "(JJIILjava/io/FileDescriptor;J)J"),
20067e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    NATIVE_METHOD(Posix, msync, "(JJI)V"),
20077e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes    NATIVE_METHOD(Posix, munlock, "(JJ)V"),
20087e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes    NATIVE_METHOD(Posix, munmap, "(JJ)V"),
20090ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes    NATIVE_METHOD(Posix, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"),
201075781e7ed9373d97f5959b5b20e7343b8f7e1417Elliott Hughes    NATIVE_METHOD(Posix, pipe2, "(I)[Ljava/io/FileDescriptor;"),
20115d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, poll, "([Landroid/system/StructPollfd;I)I"),
201211f07d30d2e344b48f132ec6ed105d85423052c2Elliott Hughes    NATIVE_METHOD(Posix, posix_fallocate, "(Ljava/io/FileDescriptor;JJ)V"),
20135215e4c0db7530519981f1e505e6db82401802f2Nick Kralevich    NATIVE_METHOD(Posix, prctl, "(IJJJJ)I"),
2014e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    NATIVE_METHOD(Posix, preadBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
2015e3b6fa2bf357f2712ab2ee9e8487f157595ea0c7Elliott Hughes    NATIVE_METHOD(Posix, pwriteBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
20160568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    NATIVE_METHOD(Posix, readBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
20170b6b3e10459fc3a3f4dd280dab8d4a145f7bf2f0Elliott Hughes    NATIVE_METHOD(Posix, readlink, "(Ljava/lang/String;)Ljava/lang/String;"),
2018bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    NATIVE_METHOD(Posix, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
201923ec09188303a874b3b391f96ae0a29af002bff9Elliott Hughes    NATIVE_METHOD(Posix, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"),
2020c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes    NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"),
202190246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    NATIVE_METHOD(Posix, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"),
2022a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"),
20235d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/util/MutableLong;J)J"),
202490d96a4f168b7e56cff54dc94dca2f3cde60ebcdElliott Hughes    NATIVE_METHOD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"),
2025a8b7587c5001db3489c64ac1d16c254a683f76bdLorenzo Colitti    NATIVE_METHOD_OVERLOAD(Posix, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/SocketAddress;)I", SocketAddress),
2026396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, setegid, "(I)V"),
2027895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    NATIVE_METHOD(Posix, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"),
2028396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, seteuid, "(I)V"),
2029396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, setgid, "(I)V"),
20308f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    NATIVE_METHOD(Posix, setpgid, "(II)V"),
20318f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    NATIVE_METHOD(Posix, setregid, "(II)V"),
20328f0f2ac7fcd8f366a78cc51181d065ab93385e46Elliott Hughes    NATIVE_METHOD(Posix, setreuid, "(II)V"),
20336c9b5377550a9649ed1532d1fcdfeba116c74eadElliott Hughes    NATIVE_METHOD(Posix, setsid, "()I"),
2034c63f0d4e80a9fd3bdf99cd438d108b750226736aElliott Hughes    NATIVE_METHOD(Posix, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"),
2035b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    NATIVE_METHOD(Posix, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"),
2036454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    NATIVE_METHOD(Posix, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"),
2037b974666d79ebc392b37ec1ae83aae57ae6331c08Elliott Hughes    NATIVE_METHOD(Posix, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"),
20385d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupReq;)V"),
20395d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, setsockoptGroupSourceReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupSourceReq;)V"),
20405d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"),
20415d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"),
2042396a9c666da353b910b515d12eb1c43adfddb0c8Elliott Hughes    NATIVE_METHOD(Posix, setuid, "(I)V"),
204390246a0ae7117d780e077c9e84cdb73ff5b44af7Jeff Sharkey    NATIVE_METHOD(Posix, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"),
204459e4744d27231f260271dbbca406e0cc39768116Elliott Hughes    NATIVE_METHOD(Posix, shutdown, "(Ljava/io/FileDescriptor;I)V"),
2045454a95f6a28855aa3c88d168b15a45bf315efc99Elliott Hughes    NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
20463218082325b6b8713a8ac15731482e3da86a7df9Elliott Hughes    NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
20475d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
20485d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, statvfs, "(Ljava/lang/String;)Landroid/system/StructStatVfs;"),
2049ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes    NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"),
2050763f8ed6195707d0c30bfae1ca8a3bb886b746ccElliott Hughes    NATIVE_METHOD(Posix, strsignal, "(I)Ljava/lang/String;"),
2051a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes    NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
20526fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes    NATIVE_METHOD(Posix, sysconf, "(I)J"),
2053bb5816aa1626eb2f6263bd21479600b114c8a1bdJohan Redestig    NATIVE_METHOD(Posix, tcdrain, "(Ljava/io/FileDescriptor;)V"),
2054039f7599559fd7e48c354b99dcb94ff391f53349Elliott Hughes    NATIVE_METHOD(Posix, tcsendbreak, "(Ljava/io/FileDescriptor;I)V"),
2055c79d3ef4dcd25f0e264bf957861e2632da93e62dNick Kralevich    NATIVE_METHOD(Posix, umaskImpl, "(I)I"),
20565d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, uname, "()Landroid/system/StructUtsname;"),
20575e8f82f2592498e75ac4685ccd0d31d601d37bdcNeil Fuller    NATIVE_METHOD(Posix, unlink, "(Ljava/lang/String;)V"),
2058895a613aa2aec6aa6d03b29755cf2fea584909adElliott Hughes    NATIVE_METHOD(Posix, unsetenv, "(Ljava/lang/String;)V"),
20595d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughes    NATIVE_METHOD(Posix, waitpid, "(ILandroid/util/MutableInt;I)I"),
20600568a63ba1086a78ffb4cff68dd2eac4f9908e13Elliott Hughes    NATIVE_METHOD(Posix, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
2061bbac92e691de7d570928ddfba639067978e55b06Elliott Hughes    NATIVE_METHOD(Posix, writev, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
2062ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes};
20637cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughesvoid register_libcore_io_Posix(JNIEnv* env) {
20647cd6760f7045d771faae8080a8c6150bf678f679Elliott Hughes    jniRegisterNativeMethods(env, "libcore/io/Posix", gMethods, NELEM(gMethods));
2065ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes}
2066