Merge changes I5e3b216a,Iebf8b87c

* changes:
  Linux: Add proper casts for varargs call.
  Linux: Implement getrlimit
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index 7db7f75..5b9ff47 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -223,6 +223,8 @@
 
   /** @hide */ public static StructPasswd getpwuid(int uid) throws ErrnoException { return Libcore.os.getpwuid(uid); }
 
+  /** @hide */ public static StructRlimit getrlimit(int resource) throws ErrnoException { return Libcore.os.getrlimit(resource); }
+
   /**
    * See <a href="http://man7.org/linux/man-pages/man2/getsockname.2.html">getsockname(2)</a>.
    */
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index 72c5734..3e1f007 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -398,6 +398,7 @@
     public static final int PROT_READ = placeholder();
     public static final int PROT_WRITE = placeholder();
     public static final int R_OK = placeholder();
+    /** @hide */ public static final int RLIMIT_NOFILE = placeholder();
     public static final int RT_SCOPE_HOST = placeholder();
     public static final int RT_SCOPE_LINK = placeholder();
     public static final int RT_SCOPE_NOWHERE = placeholder();
diff --git a/luni/src/main/java/android/system/StructRlimit.java b/luni/src/main/java/android/system/StructRlimit.java
new file mode 100644
index 0000000..6bb05a9
--- /dev/null
+++ b/luni/src/main/java/android/system/StructRlimit.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.system;
+
+import libcore.util.Objects;
+
+/**
+ * Information returned by {@link Os#getrlimit}. Corresponds to C's {@code struct rlimit} from
+ * {@code <sys/resource.h>}.
+ *
+ * @hide
+ */
+public final class StructRlimit {
+  public final long rlim_cur;
+  public final long rlim_max;
+
+  public StructRlimit(long rlim_cur, long rlim_max) {
+    this.rlim_cur = rlim_cur;
+    this.rlim_max = rlim_max;
+  }
+
+  @Override public String toString() {
+    return Objects.toString(this);
+  }
+}
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 55d4d82..3054dc3 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -28,6 +28,7 @@
 import android.system.StructLinger;
 import android.system.StructPasswd;
 import android.system.StructPollfd;
+import android.system.StructRlimit;
 import android.system.StructStat;
 import android.system.StructStatVfs;
 import android.system.StructTimeval;
@@ -98,6 +99,7 @@
     public int getppid() { return os.getppid(); }
     public StructPasswd getpwnam(String name) throws ErrnoException { return os.getpwnam(name); }
     public StructPasswd getpwuid(int uid) throws ErrnoException { return os.getpwuid(uid); }
+    public StructRlimit getrlimit(int resource) throws ErrnoException { return os.getrlimit(resource); }
     public SocketAddress getsockname(FileDescriptor fd) throws ErrnoException { return os.getsockname(fd); }
     public int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptByte(fd, level, option); }
     public InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptInAddr(fd, level, option); }
diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java
index 09adb09..a0931d2 100644
--- a/luni/src/main/java/libcore/io/Linux.java
+++ b/luni/src/main/java/libcore/io/Linux.java
@@ -28,6 +28,7 @@
 import android.system.StructLinger;
 import android.system.StructPasswd;
 import android.system.StructPollfd;
+import android.system.StructRlimit;
 import android.system.StructStat;
 import android.system.StructStatVfs;
 import android.system.StructTimeval;
@@ -89,6 +90,7 @@
     public native int getppid();
     public native StructPasswd getpwnam(String name) throws ErrnoException;
     public native StructPasswd getpwuid(int uid) throws ErrnoException;
+    public native StructRlimit getrlimit(int resource) throws ErrnoException;
     public native SocketAddress getsockname(FileDescriptor fd) throws ErrnoException;
     public native int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException;
     public native InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index 20a84bd..a8809bf 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -28,6 +28,7 @@
 import android.system.StructLinger;
 import android.system.StructPasswd;
 import android.system.StructPollfd;
+import android.system.StructRlimit;
 import android.system.StructStat;
 import android.system.StructStatVfs;
 import android.system.StructTimeval;
@@ -84,6 +85,7 @@
     public int getppid();
     public StructPasswd getpwnam(String name) throws ErrnoException;
     public StructPasswd getpwuid(int uid) throws ErrnoException;
+    public StructRlimit getrlimit(int resource) throws ErrnoException;
     public SocketAddress getsockname(FileDescriptor fd) throws ErrnoException;
     public int getsockoptByte(FileDescriptor fd, int level, int option) throws ErrnoException;
     public InetAddress getsockoptInAddr(FileDescriptor fd, int level, int option) throws ErrnoException;
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index 826fa1e..963439c 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -33,6 +33,7 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
@@ -432,6 +433,7 @@
     initConstant(env, c, "PROT_READ", PROT_READ);
     initConstant(env, c, "PROT_WRITE", PROT_WRITE);
     initConstant(env, c, "R_OK", R_OK);
+    initConstant(env, c, "RLIMIT_NOFILE", RLIMIT_NOFILE);
 // NOTE: The RT_* constants are not preprocessor defines, they're enum
 // members. The best we can do (barring UAPI / kernel version checks) is
 // to hope they exist on all host linuxes we're building on. These
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 989024f..26b7697 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -33,6 +33,7 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
@@ -1315,6 +1316,19 @@
     return Passwd(env).getpwuid(uid);
 }
 
+static jobject Linux_getrlimit(JNIEnv* env, jobject, jint resource) {
+    struct rlimit r;
+    if (throwIfMinusOne(env, "getrlimit", TEMP_FAILURE_RETRY(getrlimit(resource, &r))) == -1) {
+        return nullptr;
+    }
+
+    ScopedLocalRef<jclass> rlimit_class(env, env->FindClass("android/system/StructRlimit"));
+    jmethodID ctor = env->GetMethodID(rlimit_class.get(), "<init>", "(JJ)V");
+    return env->NewObject(rlimit_class.get(), ctor,
+                          static_cast<jlong>(r.rlim_cur),
+                          static_cast<jlong>(r.rlim_max));
+}
+
 static jobject Linux_getsockname(JNIEnv* env, jobject, jobject javaFd) {
   return doGetSockName(env, javaFd, true);
 }
@@ -2421,6 +2435,7 @@
     NATIVE_METHOD(Linux, getppid, "()I"),
     NATIVE_METHOD(Linux, getpwnam, "(Ljava/lang/String;)Landroid/system/StructPasswd;"),
     NATIVE_METHOD(Linux, getpwuid, "(I)Landroid/system/StructPasswd;"),
+    NATIVE_METHOD(Linux, getrlimit, "(I)Landroid/system/StructRlimit;"),
     NATIVE_METHOD(Linux, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
     NATIVE_METHOD(Linux, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
     NATIVE_METHOD(Linux, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 0f47d87..a509c2b 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -20,6 +20,7 @@
 import android.system.NetlinkSocketAddress;
 import android.system.OsConstants;
 import android.system.PacketSocketAddress;
+import android.system.StructRlimit;
 import android.system.StructStat;
 import android.system.StructTimeval;
 import android.system.StructUcred;
@@ -803,4 +804,12 @@
     assertEquals(0, structStat1.st_atim.compareTo(structStat2.st_atim));
   }
 
+  public void test_getrlimit() throws Exception {
+    StructRlimit rlimit = Libcore.os.getrlimit(OsConstants.RLIMIT_NOFILE);
+    // We can't really make any assertions about these values since they might vary from
+    // device to device and even process to process. We do know that they will be greater
+    // than zero, though.
+    assertTrue(rlimit.rlim_cur > 0);
+    assertTrue(rlimit.rlim_max > 0);
+  }
 }
diff --git a/non_openjdk_java_files.mk b/non_openjdk_java_files.mk
index 29f8d0c..7b1d180 100644
--- a/non_openjdk_java_files.mk
+++ b/non_openjdk_java_files.mk
@@ -16,6 +16,7 @@
   luni/src/main/java/android/system/StructLinger.java \
   luni/src/main/java/android/system/StructPasswd.java \
   luni/src/main/java/android/system/StructPollfd.java \
+  luni/src/main/java/android/system/StructRlimit.java \
   luni/src/main/java/android/system/StructStat.java \
   luni/src/main/java/android/system/StructStatVfs.java \
   luni/src/main/java/android/system/StructTimeval.java \