Initial import of OpenJdk files.
Create new libcore/ojluni directory with src/main/java and
src/main/native subdirectiories.
Build ojluni into core-oj jar.
Use openjdk classes from java.awt.font package.
Copy all files from jdk/src/share/classes and jdk/src/solaris/classes
directories in openjdk into libcore/ojluni/src/main/java.
Copy following native files from openjdk to
libcore/ojluni/src/main/native:
jdk/src/solaris/native/java/io/canonicalize_md.c
build/linux-amd64/include/classfile_constants.h
jdk/src/share/native/java/net/DatagramPacket.c
jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c
jdk/src/share/native/java/lang/Double.c
jdk/src/share/native/java/lang/fdlibm/include/fdlibm.h
jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c
jdk/src/solaris/native/java/io/FileDescriptor_md.c
jdk/src/solaris/native/sun/nio/ch/FileDispatcherImpl.c
jdk/src/share/native/java/io/FileInputStream.c
jdk/src/solaris/native/sun/nio/ch/FileKey.c
jdk/src/solaris/native/java/io/FileOutputStream_md.c
jdk/src/solaris/native/java/io/FileSystem_md.c
jdk/src/share/native/java/lang/Float.c
jdk/src/share/native/java/net/Inet4Address.c
jdk/src/solaris/native/java/net/Inet4AddressImpl.c
jdk/src/share/native/java/net/Inet6Address.c
jdk/src/solaris/native/java/net/Inet6AddressImpl.c
jdk/src/share/native/java/net/InetAddress.c
jdk/src/solaris/native/java/net/InetAddressImplFactory.c
jdk/src/share/native/java/io/io_util.c
jdk/src/solaris/native/sun/nio/ch/IOUtil.c
jdk/src/share/native/java/io/io_util.h
jdk/src/solaris/native/java/io/io_util_md.c
jdk/src/solaris/native/java/io/io_util_md.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/java_io_FileDescriptor.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_io_FileInputStream.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_io_FileOutputStream.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_io_FileSystem.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_io_ObjectStreamClass.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_io_UnixFileSystem.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Double.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Float.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Integer.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Long.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Runtime.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Shutdown.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_StrictMath.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_String.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_System.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Thread.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/java_lang_Throwable.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_DatagramPacket.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_Inet4Address.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_Inet4AddressImpl.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_Inet6Address.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_Inet6AddressImpl.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_InetAddress.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_InetAddressImplFactory.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_NetworkInterface.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_PlainDatagramSocketImpl.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_PlainSocketImpl.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_SocketInputStream.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_SocketOptions.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/java_net_SocketOutputStream.h
jdk/src/share/native/java/lang/java_props.h
jdk/src/solaris/native/java/lang/java_props_md.c
jdk/src/share/native/java/util/zip/Adler32.c as java_util_zip_Adler32.c
jdk/src/share/native/java/util/zip/CRC32.c as java_util_zip_CRC32.c
build/linux-amd64/tmp/sun/java.util.zip/zip/CClassHeaders/java_util_zip_CRC32.h
jdk/src/share/native/java/util/zip/Deflater.c as java_util_zip_Deflater.c
build/linux-amd64/tmp/sun/java.util.zip/zip/CClassHeaders/java_util_zip_Deflater.h
jdk/src/share/native/java/util/zip/Inflater.c as java_util_zip_Inflater.c
build/linux-amd64/tmp/sun/java.util.zip/zip/CClassHeaders/java_util_zip_Inflater.h
jdk/src/share/native/java/util/zip/ZipFile.c as java_util_zip_ZipFile.c
build/linux-amd64/tmp/sun/java.util.zip/zip/CClassHeaders/java_util_zip_ZipFile.h
jdk/src/share/native/java/lang/fdlibm/include/jfdlibm.h
jdk/src/share/native/common/jlong.h
jdk/src/solaris/native/common/jlong_md.h
jdk/src/share/native/common/jni_util.c
jdk/src/share/native/common/jni_util.h
jdk/src/solaris/native/common/jni_util_md.c
jdk/src/share/javavm/export/jvm.h
jdk/src/solaris/javavm/export/jvm_md.h
jdk/src/solaris/native/java/net/linux_close.c
jdk/src/share/native/sun/misc/NativeSignalHandler.c
jdk/src/solaris/native/sun/nio/ch/NativeThread.c
jdk/src/share/native/java/net/net_util.c
jdk/src/share/native/java/net/net_util.h
jdk/src/solaris/native/java/net/net_util_md.c
jdk/src/solaris/native/java/net/net_util_md.h
jdk/src/solaris/native/java/net/NetworkInterface.c
jdk/src/share/native/sun/nio/ch/nio.h
jdk/src/solaris/native/sun/nio/ch/nio_util.h
jdk/src/share/native/java/io/ObjectStreamClass.c
jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
jdk/src/solaris/native/java/net/PlainSocketImpl.c
jdk/src/solaris/native/java/lang/ProcessEnvironment_md.c
jdk/src/share/native/java/lang/Runtime.c
jdk/src/share/native/java/lang/Shutdown.c
jdk/src/share/native/sun/misc/Signal.c
jdk/src/solaris/native/java/net/SocketInputStream.c
jdk/src/solaris/native/java/net/SocketOutputStream.c
jdk/src/share/native/java/lang/StrictMath.c
jdk/src/share/native/java/lang/String.c
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/sun_misc_NativeSignalHandler.h
build/linux-amd64/tmp/java/java.lang/java/CClassHeaders/sun_misc_Signal.h
build/linux-amd64/tmp/sun/java.net/net/CClassHeaders/sun_net_spi_DefaultProxySelector.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_FileChannelImpl.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_FileDispatcherImpl.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_FileKey.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_IOStatus.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_IOUtil.h
build/linux-amd64/tmp/java/java.nio/nio/CClassHeaders/sun_nio_ch_NativeThread.h
jdk/src/share/native/java/lang/System.c
jdk/src/share/native/java/lang/Thread.c
jdk/src/share/native/java/lang/Throwable.c
jdk/src/solaris/native/java/io/UnixFileSystem_md.c
jdk/src/solaris/native/java/lang/UNIXProcess_md.c
jdk/src/share/native/java/util/zip/zip_util.c
jdk/src/share/native/java/util/zip/zip_util.h
Change-Id: Ib237df4e1b7b5b4d9f12e74d189e6ec9eed3c31d
diff --git a/ojluni/src/main/native/DatagramPacket.c b/ojluni/src/main/native/DatagramPacket.c
new file mode 100755
index 0000000..01ac9fb
--- /dev/null
+++ b/ojluni/src/main/native/DatagramPacket.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "java_net_DatagramPacket.h"
+#include "net_util.h"
+
+/************************************************************************
+ * DatagramPacket
+ */
+
+jfieldID dp_addressID;
+jfieldID dp_portID;
+jfieldID dp_bufID;
+jfieldID dp_offsetID;
+jfieldID dp_lengthID;
+jfieldID dp_bufLengthID;
+
+/*
+ * Class: java_net_DatagramPacket
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_DatagramPacket_init (JNIEnv *env, jclass cls) {
+ dp_addressID = (*env)->GetFieldID(env, cls, "address",
+ "Ljava/net/InetAddress;");
+ CHECK_NULL(dp_addressID);
+ dp_portID = (*env)->GetFieldID(env, cls, "port", "I");
+ CHECK_NULL(dp_portID);
+ dp_bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
+ CHECK_NULL(dp_bufID);
+ dp_offsetID = (*env)->GetFieldID(env, cls, "offset", "I");
+ CHECK_NULL(dp_offsetID);
+ dp_lengthID = (*env)->GetFieldID(env, cls, "length", "I");
+ CHECK_NULL(dp_lengthID);
+ dp_bufLengthID = (*env)->GetFieldID(env, cls, "bufLength", "I");
+ CHECK_NULL(dp_bufLengthID);
+}
diff --git a/ojluni/src/main/native/DefaultProxySelector.c b/ojluni/src/main/native/DefaultProxySelector.c
new file mode 100755
index 0000000..6883902
--- /dev/null
+++ b/ojluni/src/main/native/DefaultProxySelector.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jvm_md.h"
+#include "jlong.h"
+#include "sun_net_spi_DefaultProxySelector.h"
+#include <dlfcn.h>
+#include <stdio.h>
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/**
+ * These functions are used by the sun.net.spi.DefaultProxySelector class
+ * to access some platform specific settings.
+ * This is the Solaris/Linux Gnome 2.x code using the GConf-2 library.
+ * Everything is loaded dynamically so no hard link with any library exists.
+ * The GConf-2 settings used are:
+ * - /system/http_proxy/use_http_proxy boolean
+ * - /system/http_proxy/use_authentcation boolean
+ * - /system/http_proxy/use_same_proxy boolean
+ * - /system/http_proxy/host string
+ * - /system/http_proxy/authentication_user string
+ * - /system/http_proxy/authentication_password string
+ * - /system/http_proxy/port int
+ * - /system/proxy/socks_host string
+ * - /system/proxy/mode string
+ * - /system/proxy/ftp_host string
+ * - /system/proxy/secure_host string
+ * - /system/proxy/socks_port int
+ * - /system/proxy/ftp_port int
+ * - /system/proxy/secure_port int
+ * - /system/proxy/no_proxy_for list
+ * - /system/proxy/gopher_host string
+ * - /system/proxy/gopher_port int
+ */
+typedef void* gconf_client_get_default_func();
+typedef char* gconf_client_get_string_func(void *, char *, void**);
+typedef int gconf_client_get_int_func(void*, char *, void**);
+typedef int gconf_client_get_bool_func(void*, char *, void**);
+typedef int gconf_init_func(int, char**, void**);
+typedef void g_type_init_func ();
+gconf_client_get_default_func* my_get_default_func = NULL;
+gconf_client_get_string_func* my_get_string_func = NULL;
+gconf_client_get_int_func* my_get_int_func = NULL;
+gconf_client_get_bool_func* my_get_bool_func = NULL;
+gconf_init_func* my_gconf_init_func = NULL;
+g_type_init_func* my_g_type_init_func = NULL;
+
+static jclass proxy_class;
+static jclass isaddr_class;
+static jclass ptype_class;
+static jmethodID isaddr_createUnresolvedID;
+static jmethodID proxy_ctrID;
+static jfieldID pr_no_proxyID;
+static jfieldID ptype_httpID;
+static jfieldID ptype_socksID;
+
+static int gconf_ver = 0;
+static void* gconf_client = NULL;
+
+#define CHECK_NULL(X) { if ((X) == NULL) fprintf (stderr,"JNI errror at line %d\n", __LINE__); }
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_net_spi_DefaultProxySelector_init(JNIEnv *env, jclass clazz) {
+ jclass cls = NULL;
+ CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy"));
+ proxy_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(cls = (*env)->FindClass(env,"java/net/Proxy$Type"));
+ ptype_class = (*env)->NewGlobalRef(env, cls);
+ CHECK_NULL(cls = (*env)->FindClass(env, "java/net/InetSocketAddress"));
+ isaddr_class = (*env)->NewGlobalRef(env, cls);
+ proxy_ctrID = (*env)->GetMethodID(env, proxy_class, "<init>", "(Ljava/net/Proxy$Type;Ljava/net/SocketAddress;)V");
+ pr_no_proxyID = (*env)->GetStaticFieldID(env, proxy_class, "NO_PROXY", "Ljava/net/Proxy;");
+ ptype_httpID = (*env)->GetStaticFieldID(env, ptype_class, "HTTP", "Ljava/net/Proxy$Type;");
+ ptype_socksID = (*env)->GetStaticFieldID(env, ptype_class, "SOCKS", "Ljava/net/Proxy$Type;");
+ isaddr_createUnresolvedID = (*env)->GetStaticMethodID(env, isaddr_class, "createUnresolved", "(Ljava/lang/String;I)Ljava/net/InetSocketAddress;");
+
+ /**
+ * Let's try to load le GConf-2 library
+ */
+ if (dlopen(JNI_LIB_NAME("gconf-2"), RTLD_GLOBAL | RTLD_LAZY) != NULL ||
+ dlopen(VERSIONED_JNI_LIB_NAME("gconf-2", "4"),
+ RTLD_GLOBAL | RTLD_LAZY) != NULL) {
+ gconf_ver = 2;
+ }
+ if (gconf_ver > 0) {
+ /*
+ * Now let's get pointer to the functions we need.
+ */
+ my_g_type_init_func = (g_type_init_func*) dlsym(RTLD_DEFAULT, "g_type_init");
+ my_get_default_func = (gconf_client_get_default_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_default");
+ if (my_g_type_init_func != NULL && my_get_default_func != NULL) {
+ /**
+ * Try to connect to GConf.
+ */
+ (*my_g_type_init_func)();
+ gconf_client = (*my_get_default_func)();
+ if (gconf_client != NULL) {
+ my_get_string_func = (gconf_client_get_string_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_string");
+ my_get_int_func = (gconf_client_get_int_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_int");
+ my_get_bool_func = (gconf_client_get_bool_func*) dlsym(RTLD_DEFAULT, "gconf_client_get_bool");
+ if (my_get_int_func != NULL && my_get_string_func != NULL &&
+ my_get_bool_func != NULL) {
+ /**
+ * We did get all we need. Let's enable the System Proxy Settings.
+ */
+ return JNI_TRUE;
+ }
+ }
+ }
+ }
+ return JNI_FALSE;
+}
+
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: getSystemProxy
+ * Signature: ([Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
+ */
+JNIEXPORT jobject JNICALL
+Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env,
+ jobject this,
+ jstring proto,
+ jstring host)
+{
+ char *phost = NULL;
+ char *mode = NULL;
+ int pport = 0;
+ int use_proxy = 0;
+ int use_same_proxy = 0;
+ const char* urlhost;
+ jobject isa = NULL;
+ jobject proxy = NULL;
+ jobject type_proxy = NULL;
+ jobject no_proxy = NULL;
+ const char *cproto;
+ jboolean isCopy;
+
+ if (gconf_ver > 0) {
+ if (gconf_client == NULL) {
+ (*my_g_type_init_func)();
+ gconf_client = (*my_get_default_func)();
+ }
+ if (gconf_client != NULL) {
+ cproto = (*env)->GetStringUTFChars(env, proto, &isCopy);
+ if (cproto != NULL) {
+ /**
+ * We will have to check protocol by protocol as they do use different
+ * entries.
+ */
+
+ use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL);
+ if (use_same_proxy) {
+ use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL);
+ if (use_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
+ }
+ }
+
+ /**
+ * HTTP:
+ * /system/http_proxy/use_http_proxy (boolean)
+ * /system/http_proxy/host (string)
+ * /system/http_proxy/port (integer)
+ */
+ if (strcasecmp(cproto, "http") == 0) {
+ use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL);
+ if (use_proxy) {
+ if (!use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL);
+ }
+ CHECK_NULL(type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID));
+ }
+ }
+
+ /**
+ * HTTPS:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/secure_host (string)
+ * /system/proxy/secure_port (integer)
+ */
+ if (strcasecmp(cproto, "https") == 0) {
+ mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
+ if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
+ if (!use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL);
+ }
+ use_proxy = (phost != NULL);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+ }
+
+ /**
+ * FTP:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/ftp_host (string)
+ * /system/proxy/ftp_port (integer)
+ */
+ if (strcasecmp(cproto, "ftp") == 0) {
+ mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
+ if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
+ if (!use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL);
+ }
+ use_proxy = (phost != NULL);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+ }
+
+ /**
+ * GOPHER:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/gopher_host (string)
+ * /system/proxy/gopher_port (integer)
+ */
+ if (strcasecmp(cproto, "gopher") == 0) {
+ mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
+ if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
+ if (!use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL);
+ }
+ use_proxy = (phost != NULL);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID);
+ }
+ }
+
+ /**
+ * SOCKS:
+ * /system/proxy/mode (string) [ "manual" means use proxy settings ]
+ * /system/proxy/socks_host (string)
+ * /system/proxy/socks_port (integer)
+ */
+ if (strcasecmp(cproto, "socks") == 0) {
+ mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL);
+ if (mode != NULL && (strcasecmp(mode,"manual") == 0)) {
+ if (!use_same_proxy) {
+ phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL);
+ pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL);
+ }
+ use_proxy = (phost != NULL);
+ if (use_proxy)
+ type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID);
+ }
+ }
+
+ if (isCopy == JNI_TRUE)
+ (*env)->ReleaseStringUTFChars(env, proto, cproto);
+
+ if (use_proxy && (phost != NULL)) {
+ jstring jhost;
+ char *noproxyfor;
+ char *s;
+
+ /**
+ * check for the exclude list (aka "No Proxy For" list).
+ * It's a list of comma separated suffixes (e.g. domain name).
+ */
+ noproxyfor = (*my_get_string_func)(gconf_client, "/system/proxy/no_proxy_for", NULL);
+ if (noproxyfor != NULL) {
+ char *tmpbuf[512];
+
+ s = strtok_r(noproxyfor, ", ", tmpbuf);
+ urlhost = (*env)->GetStringUTFChars(env, host, &isCopy);
+ if (urlhost != NULL) {
+ while (s != NULL && strlen(s) <= strlen(urlhost)) {
+ if (strcasecmp(urlhost+(strlen(urlhost) - strlen(s)), s) == 0) {
+ /**
+ * the URL host name matches with one of the sufixes,
+ * therefore we have to use a direct connection.
+ */
+ use_proxy = 0;
+ break;
+ }
+ s = strtok_r(NULL, ", ", tmpbuf);
+ }
+ if (isCopy == JNI_TRUE)
+ (*env)->ReleaseStringUTFChars(env, host, urlhost);
+ }
+ }
+ if (use_proxy) {
+ jhost = (*env)->NewStringUTF(env, phost);
+ isa = (*env)->CallStaticObjectMethod(env, isaddr_class, isaddr_createUnresolvedID, jhost, pport);
+ proxy = (*env)->NewObject(env, proxy_class, proxy_ctrID, type_proxy, isa);
+ return proxy;
+ }
+ }
+ }
+ }
+ }
+
+ CHECK_NULL(no_proxy = (*env)->GetStaticObjectField(env, proxy_class, pr_no_proxyID));
+ return no_proxy;
+}
diff --git a/ojluni/src/main/native/Double.c b/ojluni/src/main/native/Double.c
new file mode 100755
index 0000000..7715788
--- /dev/null
+++ b/ojluni/src/main/native/Double.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+
+#include "java_lang_Double.h"
+
+/*
+ * Find the double float corresponding to a given bit pattern
+ */
+JNIEXPORT jdouble JNICALL
+Java_java_lang_Double_longBitsToDouble(JNIEnv *env, jclass unused, jlong v)
+{
+ union {
+ jlong l;
+ double d;
+ } u;
+ jlong_to_jdouble_bits(&v);
+ u.l = v;
+ return (jdouble)u.d;
+}
+
+/*
+ * Find the bit pattern corresponding to a given double float, NOT collapsing NaNs
+ */
+JNIEXPORT jlong JNICALL
+Java_java_lang_Double_doubleToRawLongBits(JNIEnv *env, jclass unused, jdouble v)
+{
+ union {
+ jlong l;
+ double d;
+ } u;
+ jdouble_to_jlong_bits(&v);
+ u.d = (double)v;
+ return u.l;
+}
diff --git a/ojluni/src/main/native/FileChannelImpl.c b/ojluni/src/main/native/FileChannelImpl.c
new file mode 100755
index 0000000..8e5c0fd
--- /dev/null
+++ b/ojluni/src/main/native/FileChannelImpl.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jvm_md.h"
+#include "jlong.h"
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "sun_nio_ch_FileChannelImpl.h"
+#include "java_lang_Integer.h"
+#include "nio.h"
+#include "nio_util.h"
+#include <dlfcn.h>
+
+#if defined(__linux__) || defined(__solaris__)
+#include <sys/sendfile.h>
+#elif defined(_ALLBSD_SOURCE)
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#define lseek64 lseek
+#define mmap64 mmap
+#endif
+
+static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)
+{
+ jlong pageSize = sysconf(_SC_PAGESIZE);
+ chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
+ return pageSize;
+}
+
+static jlong
+handle(JNIEnv *env, jlong rv, char *msg)
+{
+ if (rv >= 0)
+ return rv;
+ if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, msg);
+ return IOS_THROWN;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this,
+ jint prot, jlong off, jlong len)
+{
+ void *mapAddress = 0;
+ jobject fdo = (*env)->GetObjectField(env, this, chan_fd);
+ jint fd = fdval(env, fdo);
+ int protections = 0;
+ int flags = 0;
+
+ if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) {
+ protections = PROT_READ;
+ flags = MAP_SHARED;
+ } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) {
+ protections = PROT_WRITE | PROT_READ;
+ flags = MAP_SHARED;
+ } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) {
+ protections = PROT_WRITE | PROT_READ;
+ flags = MAP_PRIVATE;
+ }
+
+ mapAddress = mmap64(
+ 0, /* Let OS decide location */
+ len, /* Number of bytes to map */
+ protections, /* File permissions */
+ flags, /* Changes are shared */
+ fd, /* File descriptor of mapped file */
+ off); /* Offset into file */
+
+ if (mapAddress == MAP_FAILED) {
+ if (errno == ENOMEM) {
+ JNU_ThrowOutOfMemoryError(env, "Map failed");
+ return IOS_THROWN;
+ }
+ return handle(env, -1, "Map failed");
+ }
+
+ return ((jlong) (unsigned long) mapAddress);
+}
+
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this,
+ jlong address, jlong len)
+{
+ void *a = (void *)jlong_to_ptr(address);
+ return handle(env,
+ munmap(a, (size_t)len),
+ "Unmap failed");
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
+ jobject fdo, jlong offset)
+{
+ jint fd = fdval(env, fdo);
+ jlong result = 0;
+
+ if (offset < 0) {
+ result = lseek64(fd, 0, SEEK_CUR);
+ } else {
+ result = lseek64(fd, offset, SEEK_SET);
+ }
+ return handle(env, result, "Position failed");
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)
+{
+ jint fd = fdval(env, fdo);
+ if (fd != -1) {
+ jlong result = close(fd);
+ if (result < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "Close failed");
+ }
+ }
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
+ jint srcFD,
+ jlong position, jlong count,
+ jint dstFD)
+{
+#if defined(__linux__)
+ off64_t offset = (off64_t)position;
+ jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count);
+ if (n < 0) {
+ if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ if ((errno == EINVAL) && ((ssize_t)count >= 0))
+ return IOS_UNSUPPORTED_CASE;
+ if (errno == EINTR) {
+ return IOS_INTERRUPTED;
+ }
+ JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
+ return IOS_THROWN;
+ }
+ return n;
+#elif defined (__solaris__)
+ sendfilevec64_t sfv;
+ size_t numBytes = 0;
+ jlong result;
+
+ sfv.sfv_fd = srcFD;
+ sfv.sfv_flag = 0;
+ sfv.sfv_off = (off64_t)position;
+ sfv.sfv_len = count;
+
+ result = sendfilev64(dstFD, &sfv, 1, &numBytes);
+
+ /* Solaris sendfilev() will return -1 even if some bytes have been
+ * transferred, so we check numBytes first.
+ */
+ if (numBytes > 0)
+ return numBytes;
+ if (result < 0) {
+ if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ if (errno == EOPNOTSUPP)
+ return IOS_UNSUPPORTED_CASE;
+ if ((errno == EINVAL) && ((ssize_t)count >= 0))
+ return IOS_UNSUPPORTED_CASE;
+ if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
+ return IOS_THROWN;
+ }
+ return result;
+#elif defined(__APPLE__)
+ off_t numBytes;
+ int result;
+
+ numBytes = count;
+
+#ifdef __APPLE__
+ result = sendfile(srcFD, dstFD, position, &numBytes, NULL, 0);
+#endif
+
+ if (numBytes > 0)
+ return numBytes;
+
+ if (result == -1) {
+ if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ if (errno == EOPNOTSUPP || errno == ENOTSOCK || errno == ENOTCONN)
+ return IOS_UNSUPPORTED_CASE;
+ if ((errno == EINVAL) && ((ssize_t)count >= 0))
+ return IOS_UNSUPPORTED_CASE;
+ if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
+ return IOS_THROWN;
+ }
+
+ return result;
+#else
+ return IOS_UNSUPPORTED_CASE;
+#endif
+}
diff --git a/ojluni/src/main/native/FileDescriptor_md.c b/ojluni/src/main/native/FileDescriptor_md.c
new file mode 100755
index 0000000..c279ca9
--- /dev/null
+++ b/ojluni/src/main/native/FileDescriptor_md.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+
+#include "java_io_FileDescriptor.h"
+
+/*******************************************************************/
+/* BEGIN JNI ********* BEGIN JNI *********** BEGIN JNI ************/
+/*******************************************************************/
+
+/* field id for jint 'fd' in java.io.FileDescriptor */
+jfieldID IO_fd_fdID;
+
+/**************************************************************
+ * static methods to store field ID's in initializers
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileDescriptor_initIDs(JNIEnv *env, jclass fdClass) {
+ IO_fd_fdID = (*env)->GetFieldID(env, fdClass, "fd", "I");
+}
+
+/**************************************************************
+ * File Descriptor
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileDescriptor_sync(JNIEnv *env, jobject this) {
+ int fd = (*env)->GetIntField(env, this, IO_fd_fdID);
+ if (JVM_Sync(fd) == -1) {
+ JNU_ThrowByName(env, "java/io/SyncFailedException", "sync failed");
+ }
+}
diff --git a/ojluni/src/main/native/FileDispatcherImpl.c b/ojluni/src/main/native/FileDispatcherImpl.c
new file mode 100755
index 0000000..4d987b9
--- /dev/null
+++ b/ojluni/src/main/native/FileDispatcherImpl.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "sun_nio_ch_FileDispatcherImpl.h"
+#include "java_lang_Long.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include "nio.h"
+#include "nio_util.h"
+
+#ifdef _ALLBSD_SOURCE
+#define stat64 stat
+#define flock64 flock
+#define off64_t off_t
+#define F_SETLKW64 F_SETLKW
+#define F_SETLK64 F_SETLK
+
+#define pread64 pread
+#define pwrite64 pwrite
+#define ftruncate64 ftruncate
+#define fstat64 fstat
+
+#define fdatasync fsync
+#endif
+
+static int preCloseFD = -1; /* File descriptor to which we dup other fd's
+ before closing them for real */
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl)
+{
+ int sp[2];
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
+ return;
+ }
+ preCloseFD = sp[0];
+ close(sp[1]);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong address, jint len)
+{
+ jint fd = fdval(env, fdo);
+ void *buf = (void *)jlong_to_ptr(address);
+
+ return convertReturnVal(env, read(fd, buf, len), JNI_TRUE);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo,
+ jlong address, jint len, jlong offset)
+{
+ jint fd = fdval(env, fdo);
+ void *buf = (void *)jlong_to_ptr(address);
+
+ return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong address, jint len)
+{
+ jint fd = fdval(env, fdo);
+ struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+ return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong address, jint len)
+{
+ jint fd = fdval(env, fdo);
+ void *buf = (void *)jlong_to_ptr(address);
+
+ return convertReturnVal(env, write(fd, buf, len), JNI_FALSE);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo,
+ jlong address, jint len, jlong offset)
+{
+ jint fd = fdval(env, fdo);
+ void *buf = (void *)jlong_to_ptr(address);
+
+ return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE);
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz,
+ jobject fdo, jlong address, jint len)
+{
+ jint fd = fdval(env, fdo);
+ struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
+ return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE);
+}
+
+static jlong
+handle(JNIEnv *env, jlong rv, char *msg)
+{
+ if (rv >= 0)
+ return rv;
+ if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, msg);
+ return IOS_THROWN;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
+ jobject fdo, jboolean md)
+{
+ jint fd = fdval(env, fdo);
+ int result = 0;
+
+ if (md == JNI_FALSE) {
+ result = fdatasync(fd);
+ } else {
+ result = fsync(fd);
+ }
+ return handle(env, result, "Force failed");
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this,
+ jobject fdo, jlong size)
+{
+ return handle(env,
+ ftruncate64(fdval(env, fdo), size),
+ "Truncation failed");
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
+{
+ struct stat64 fbuf;
+
+ if (fstat64(fdval(env, fdo), &fbuf) < 0)
+ return handle(env, -1, "Size failed");
+ return fbuf.st_size;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
+ jboolean block, jlong pos, jlong size,
+ jboolean shared)
+{
+ jint fd = fdval(env, fdo);
+ jint lockResult = 0;
+ int cmd = 0;
+ struct flock64 fl;
+
+ fl.l_whence = SEEK_SET;
+ if (size == (jlong)java_lang_Long_MAX_VALUE) {
+ fl.l_len = (off64_t)0;
+ } else {
+ fl.l_len = (off64_t)size;
+ }
+ fl.l_start = (off64_t)pos;
+ if (shared == JNI_TRUE) {
+ fl.l_type = F_RDLCK;
+ } else {
+ fl.l_type = F_WRLCK;
+ }
+ if (block == JNI_TRUE) {
+ cmd = F_SETLKW64;
+ } else {
+ cmd = F_SETLK64;
+ }
+ lockResult = fcntl(fd, cmd, &fl);
+ if (lockResult < 0) {
+ if ((cmd == F_SETLK64) && (errno == EAGAIN || errno == EACCES))
+ return sun_nio_ch_FileDispatcherImpl_NO_LOCK;
+ if (errno == EINTR)
+ return sun_nio_ch_FileDispatcherImpl_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, "Lock failed");
+ }
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this,
+ jobject fdo, jlong pos, jlong size)
+{
+ jint fd = fdval(env, fdo);
+ jint lockResult = 0;
+ struct flock64 fl;
+ int cmd = F_SETLK64;
+
+ fl.l_whence = SEEK_SET;
+ if (size == (jlong)java_lang_Long_MAX_VALUE) {
+ fl.l_len = (off64_t)0;
+ } else {
+ fl.l_len = (off64_t)size;
+ }
+ fl.l_start = (off64_t)pos;
+ fl.l_type = F_UNLCK;
+ lockResult = fcntl(fd, cmd, &fl);
+ if (lockResult < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "Release failed");
+ }
+}
+
+
+static void closeFileDescriptor(JNIEnv *env, int fd) {
+ if (fd != -1) {
+ int result = close(fd);
+ if (result < 0)
+ JNU_ThrowIOExceptionWithLastError(env, "Close failed");
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo)
+{
+ jint fd = fdval(env, fdo);
+ closeFileDescriptor(env, fd);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_preClose0(JNIEnv *env, jclass clazz, jobject fdo)
+{
+ jint fd = fdval(env, fdo);
+ if (preCloseFD >= 0) {
+ if (dup2(preCloseFD, fd) < 0)
+ JNU_ThrowIOExceptionWithLastError(env, "dup2 failed");
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_closeIntFD(JNIEnv *env, jclass clazz, jint fd)
+{
+ closeFileDescriptor(env, fd);
+}
diff --git a/ojluni/src/main/native/FileInputStream.c b/ojluni/src/main/native/FileInputStream.c
new file mode 100755
index 0000000..81fdd32
--- /dev/null
+++ b/ojluni/src/main/native/FileInputStream.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "io_util.h"
+
+#include "jvm.h"
+
+#include "java_io_FileInputStream.h"
+
+#include <fcntl.h>
+#include <limits.h>
+
+#include "io_util_md.h"
+
+/*******************************************************************/
+/* BEGIN JNI ********* BEGIN JNI *********** BEGIN JNI ************/
+/*******************************************************************/
+
+jfieldID fis_fd; /* id for jobject 'fd' in java.io.FileInputStream */
+
+/**************************************************************
+ * static methods to store field ID's in initializers
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) {
+ fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;");
+}
+
+/**************************************************************
+ * Input stream
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {
+ fileOpen(env, this, path, fis_fd, O_RDONLY);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_io_FileInputStream_read0(JNIEnv *env, jobject this) {
+ return readSingle(env, this, fis_fd);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
+ jbyteArray bytes, jint off, jint len) {
+ return readBytes(env, this, bytes, off, len, fis_fd);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_FileInputStream_skip(JNIEnv *env, jobject this, jlong toSkip) {
+ jlong cur = jlong_zero;
+ jlong end = jlong_zero;
+ FD fd = GET_FD(this, fis_fd);
+ if (fd == -1) {
+ JNU_ThrowIOException (env, "Stream Closed");
+ return 0;
+ }
+ if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "Seek error");
+ } else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "Seek error");
+ }
+ return (end - cur);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_io_FileInputStream_available(JNIEnv *env, jobject this) {
+ jlong ret;
+ FD fd = GET_FD(this, fis_fd);
+ if (fd == -1) {
+ JNU_ThrowIOException (env, "Stream Closed");
+ return 0;
+ }
+ if (IO_Available(fd, &ret)) {
+ if (ret > INT_MAX) {
+ ret = (jlong) INT_MAX;
+ }
+ return jlong_to_jint(ret);
+ }
+ JNU_ThrowIOExceptionWithLastError(env, NULL);
+ return 0;
+}
diff --git a/ojluni/src/main/native/FileKey.c b/ojluni/src/main/native/FileKey.c
new file mode 100755
index 0000000..85719b2
--- /dev/null
+++ b/ojluni/src/main/native/FileKey.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "sun_nio_ch_FileKey.h"
+
+#ifdef _ALLBSD_SOURCE
+#define stat64 stat
+
+#define fstat64 fstat
+#endif
+
+static jfieldID key_st_dev; /* id for FileKey.st_dev */
+static jfieldID key_st_ino; /* id for FileKey.st_ino */
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileKey_initIDs(JNIEnv *env, jclass clazz)
+{
+ key_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J");
+ key_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J");
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_FileKey_init(JNIEnv *env, jobject this, jobject fdo)
+{
+ struct stat64 fbuf;
+ int res;
+
+ RESTARTABLE(fstat64(fdval(env, fdo), &fbuf), res);
+ if (res < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "fstat64 failed");
+ } else {
+ (*env)->SetLongField(env, this, key_st_dev, (jlong)fbuf.st_dev);
+ (*env)->SetLongField(env, this, key_st_ino, (jlong)fbuf.st_ino);
+ }
+}
diff --git a/ojluni/src/main/native/FileOutputStream_md.c b/ojluni/src/main/native/FileOutputStream_md.c
new file mode 100755
index 0000000..efd5864
--- /dev/null
+++ b/ojluni/src/main/native/FileOutputStream_md.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+
+#include "io_util.h"
+#include "io_util_md.h"
+#include "java_io_FileOutputStream.h"
+
+#include <fcntl.h>
+
+/*******************************************************************/
+/* BEGIN JNI ********* BEGIN JNI *********** BEGIN JNI ************/
+/*******************************************************************/
+
+jfieldID fos_fd; /* id for jobject 'fd' in java.io.FileOutputStream */
+
+/**************************************************************
+ * static methods to store field ID's in initializers
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) {
+ fos_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;");
+}
+
+/**************************************************************
+ * Output stream
+ */
+
+JNIEXPORT void JNICALL
+Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this,
+ jstring path, jboolean append) {
+ fileOpen(env, this, path, fos_fd,
+ O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC));
+}
+
+JNIEXPORT void JNICALL
+Java_java_io_FileOutputStream_write(JNIEnv *env, jobject this, jint byte, jboolean append) {
+ writeSingle(env, this, byte, append, fos_fd);
+}
+
+JNIEXPORT void JNICALL
+Java_java_io_FileOutputStream_writeBytes(JNIEnv *env,
+ jobject this, jbyteArray bytes, jint off, jint len, jboolean append) {
+ writeBytes(env, this, bytes, off, len, append, fos_fd);
+}
+
+JNIEXPORT void JNICALL
+Java_java_io_FileOutputStream_close0(JNIEnv *env, jobject this) {
+ fileClose(env, this, fos_fd);
+}
diff --git a/ojluni/src/main/native/FileSystem_md.c b/ojluni/src/main/native/FileSystem_md.c
new file mode 100755
index 0000000..af4aaba
--- /dev/null
+++ b/ojluni/src/main/native/FileSystem_md.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "java_io_FileSystem.h"
+
+
+JNIEXPORT jobject JNICALL
+Java_java_io_FileSystem_getFileSystem(JNIEnv *env, jclass ignored)
+{
+ return JNU_NewObjectByName(env, "java/io/UnixFileSystem", "()V");
+}
diff --git a/ojluni/src/main/native/Float.c b/ojluni/src/main/native/Float.c
new file mode 100755
index 0000000..d63c08f
--- /dev/null
+++ b/ojluni/src/main/native/Float.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_lang_Float.h"
+
+/*
+ * Find the float corresponding to a given bit pattern
+ */
+JNIEXPORT jfloat JNICALL
+Java_java_lang_Float_intBitsToFloat(JNIEnv *env, jclass unused, jint v)
+{
+ union {
+ int i;
+ float f;
+ } u;
+ u.i = (long)v;
+ return (jfloat)u.f;
+}
+
+/*
+ * Find the bit pattern corresponding to a given float, NOT collapsing NaNs
+ */
+JNIEXPORT jint JNICALL
+Java_java_lang_Float_floatToRawIntBits(JNIEnv *env, jclass unused, jfloat v)
+{
+ union {
+ int i;
+ float f;
+ } u;
+ u.f = (float)v;
+ return (jint)u.i;
+}
diff --git a/ojluni/src/main/native/IOUtil.c b/ojluni/src/main/native/IOUtil.c
new file mode 100755
index 0000000..faa7e36
--- /dev/null
+++ b/ojluni/src/main/native/IOUtil.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include <sys/resource.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "sun_nio_ch_IOUtil.h"
+#include "java_lang_Integer.h"
+#include "nio.h"
+#include "nio_util.h"
+
+static jfieldID fd_fdID; /* for jint 'fd' in java.io.FileDescriptor */
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz)
+{
+ clazz = (*env)->FindClass(env, "java/io/FileDescriptor");
+ fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I");
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_IOUtil_randomBytes(JNIEnv *env, jclass clazz,
+ jbyteArray randArray)
+{
+ JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", NULL);
+ return JNI_FALSE;
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_IOUtil_fdVal(JNIEnv *env, jclass clazz, jobject fdo)
+{
+ return (*env)->GetIntField(env, fdo, fd_fdID);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val)
+{
+ (*env)->SetIntField(env, fdo, fd_fdID, val);
+}
+
+static int
+configureBlocking(int fd, jboolean blocking)
+{
+ int flags = fcntl(fd, F_GETFL);
+ int newflags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
+
+ return (flags == newflags) ? 0 : fcntl(fd, F_SETFL, newflags);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz,
+ jobject fdo, jboolean blocking)
+{
+ if (configureBlocking(fdval(env, fdo), blocking) < 0)
+ JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed");
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_IOUtil_makePipe(JNIEnv *env, jobject this, jboolean blocking)
+{
+ int fd[2];
+
+ if (pipe(fd) < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "Pipe failed");
+ return 0;
+ }
+ if (blocking == JNI_FALSE) {
+ if ((configureBlocking(fd[0], JNI_FALSE) < 0)
+ || (configureBlocking(fd[1], JNI_FALSE) < 0)) {
+ JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed");
+ close(fd[0]);
+ close(fd[1]);
+ return 0;
+ }
+ }
+ return ((jlong) fd[0] << 32) | (jlong) fd[1];
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
+{
+ char buf[128];
+ int tn = 0;
+
+ for (;;) {
+ int n = read(fd, buf, sizeof(buf));
+ tn += n;
+ if ((n < 0) && (errno != EAGAIN))
+ JNU_ThrowIOExceptionWithLastError(env, "Drain");
+ if (n == (int)sizeof(buf))
+ continue;
+ return (tn > 0) ? JNI_TRUE : JNI_FALSE;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_IOUtil_fdLimit(JNIEnv *env, jclass this)
+{
+ struct rlimit rlp;
+ if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed");
+ return -1;
+ }
+ if (rlp.rlim_max < 0 || rlp.rlim_max > java_lang_Integer_MAX_VALUE) {
+ return java_lang_Integer_MAX_VALUE;
+ } else {
+ return (jint)rlp.rlim_max;
+ }
+}
+
+/* Declared in nio_util.h for use elsewhere in NIO */
+
+jint
+convertReturnVal(JNIEnv *env, jint n, jboolean reading)
+{
+ if (n > 0) /* Number of bytes written */
+ return n;
+ else if (n == 0) {
+ if (reading) {
+ return IOS_EOF; /* EOF is -1 in javaland */
+ } else {
+ return 0;
+ }
+ }
+ else if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ else if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ else {
+ const char *msg = reading ? "Read failed" : "Write failed";
+ JNU_ThrowIOExceptionWithLastError(env, msg);
+ return IOS_THROWN;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_IOUtil_iovMax(JNIEnv *env, jclass this)
+{
+ jlong iov_max = sysconf(_SC_IOV_MAX);
+ if (iov_max == -1)
+ iov_max = 16;
+ return (jint)iov_max;
+}
+
+
+/* Declared in nio_util.h for use elsewhere in NIO */
+
+jlong
+convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading)
+{
+ if (n > 0) /* Number of bytes written */
+ return n;
+ else if (n == 0) {
+ if (reading) {
+ return IOS_EOF; /* EOF is -1 in javaland */
+ } else {
+ return 0;
+ }
+ }
+ else if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ else if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ else {
+ const char *msg = reading ? "Read failed" : "Write failed";
+ JNU_ThrowIOExceptionWithLastError(env, msg);
+ return IOS_THROWN;
+ }
+}
+
+jint
+fdval(JNIEnv *env, jobject fdo)
+{
+ return (*env)->GetIntField(env, fdo, fd_fdID);
+}
diff --git a/ojluni/src/main/native/Inet4Address.c b/ojluni/src/main/native/Inet4Address.c
new file mode 100755
index 0000000..2030471
--- /dev/null
+++ b/ojluni/src/main/native/Inet4Address.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+
+#include "java_net_Inet4Address.h"
+#include "net_util.h"
+
+/************************************************************************
+ * Inet4Address
+ */
+jclass ia4_class;
+jmethodID ia4_ctrID;
+
+/*
+ * Class: java_net_Inet4Address
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_Inet4Address_init(JNIEnv *env, jclass cls) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL(c);
+ ia4_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(ia4_class);
+ ia4_ctrID = (*env)->GetMethodID(env, ia4_class, "<init>", "()V");
+ CHECK_NULL(ia4_ctrID);
+}
diff --git a/ojluni/src/main/native/Inet4AddressImpl.c b/ojluni/src/main/native/Inet4AddressImpl.c
new file mode 100755
index 0000000..1aa2de0
--- /dev/null
+++ b/ojluni/src/main/native/Inet4AddressImpl.c
@@ -0,0 +1,858 @@
+/*
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef _ALLBSD_SOURCE
+#include <unistd.h>
+#include <sys/param.h>
+#endif
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_Inet4AddressImpl.h"
+
+#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
+#define HAS_GLIBC_GETHOSTBY_R 1
+#endif
+
+#if defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R)
+/* Use getaddrinfo(3), which is thread safe */
+/************************************************************************
+ * Inet4AddressImpl
+ */
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Jnet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
+ char hostname[NI_MAXHOST+1];
+
+ hostname[0] = '\0';
+ if (JVM_GetHostName(hostname, NI_MAXHOST)) {
+ /* Something went wrong, maybe networking is not setup? */
+ strcpy(hostname, "localhost");
+ } else {
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+
+ error = getaddrinfo(hostname, NULL, &hints, &res);
+
+ if (error == 0) {
+ /* host is known to name service */
+ error = getnameinfo(res->ai_addr,
+ res->ai_addrlen,
+ hostname,
+ NI_MAXHOST,
+ NULL,
+ 0,
+ NI_NAMEREQD);
+
+ /* if getnameinfo fails hostname is still the value
+ from gethostname */
+
+ freeaddrinfo(res);
+ }
+ }
+ return (*env)->NewStringUTF(env, hostname);
+}
+
+static jclass ni_iacls;
+static jclass ni_ia4cls;
+static jmethodID ni_ia4ctrID;
+static int initialized = 0;
+
+/*
+ * Find an internet address for a given hostname. Note that this
+ * code only works for addresses of type INET. The translation
+ * of %d.%d.%d.%d to an address (int) occurs in java now, so the
+ * String "host" shouldn't *ever* be a %d.%d.%d.%d string
+ *
+ * Class: java_net_Inet4AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[[B
+ */
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_net_Jnet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
+ jstring host) {
+ const char *hostname;
+ jobject name;
+ jobjectArray ret = 0;
+ int retLen = 0;
+
+ int error=0;
+ struct addrinfo hints, *res, *resNew = NULL;
+
+ if (!initialized) {
+ ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ initialized = 1;
+ }
+
+ if (IS_NULL(host)) {
+ JNU_ThrowNullPointerException(env, "host is null");
+ return 0;
+ }
+ hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
+ CHECK_NULL_RETURN(hostname, NULL);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_INET;
+
+ /*
+ * Workaround for Solaris bug 4160367 - if a hostname contains a
+ * white space then 0.0.0.0 is returned
+ */
+ if (isspace((unsigned char)hostname[0])) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
+
+ error = getaddrinfo(hostname, NULL, &hints, &res);
+
+ if (error) {
+ /* report error */
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ } else {
+ int i = 0;
+ struct addrinfo *itr, *last = NULL, *iterator = res;
+ while (iterator != NULL) {
+ int skip = 0;
+ itr = resNew;
+
+ while (itr != NULL) {
+ struct sockaddr_in *addr1, *addr2;
+
+ addr1 = (struct sockaddr_in *)iterator->ai_addr;
+ addr2 = (struct sockaddr_in *)itr->ai_addr;
+ if (addr1->sin_addr.s_addr ==
+ addr2->sin_addr.s_addr) {
+ skip = 1;
+ break;
+ }
+
+ itr = itr->ai_next;
+ }
+
+ if (!skip) {
+ struct addrinfo *next
+ = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+ if (!next) {
+ JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ memcpy(next, iterator, sizeof(struct addrinfo));
+ next->ai_next = NULL;
+ if (resNew == NULL) {
+ resNew = next;
+ } else {
+ last->ai_next = next;
+ }
+ last = next;
+ i++;
+ }
+ iterator = iterator->ai_next;
+ }
+
+ retLen = i;
+ iterator = resNew;
+ i = 0;
+
+ name = (*env)->NewStringUTF(env, hostname);
+ if (IS_NULL(name)) {
+ goto cleanupAndReturn;
+ }
+
+ ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto cleanupAndReturn;
+ }
+
+ while (iterator != NULL) {
+ /* We need 4 bytes to store ipv4 address; */
+ int len = 4;
+
+ jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (IS_NULL(iaObj)) {
+ /* we may have memory to free at the end of this */
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, name);
+ (*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);
+ i++;
+ iterator = iterator->ai_next;
+ }
+ }
+
+cleanupAndReturn:
+ {
+ struct addrinfo *iterator, *tmp;
+ iterator = resNew;
+ while (iterator != NULL) {
+ tmp = iterator;
+ iterator = iterator->ai_next;
+ free(tmp);
+ }
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ }
+
+ freeaddrinfo(res);
+
+ return ret;
+
+}
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getHostByAddr
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Jnet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
+ jbyteArray addrArray) {
+ jstring ret = NULL;
+
+ char host[NI_MAXHOST+1];
+ jfieldID fid;
+ int error = 0;
+ jint family;
+ struct sockaddr *him ;
+ int len = 0;
+ jbyte caddr[4];
+ jint addr;
+
+ struct sockaddr_in him4;
+ struct sockaddr *sa;
+
+ /*
+ * For IPv4 addresses construct a sockaddr_in structure.
+ */
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ memset((char *) &him4, 0, sizeof(him4));
+ him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_family = AF_INET;
+ sa = (struct sockaddr *) &him4;
+ len = sizeof(him4);
+
+ error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
+ NI_NAMEREQD);
+
+ if (!error) {
+ ret = (*env)->NewStringUTF(env, host);
+ }
+
+ if (ret == NULL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
+ }
+
+ return ret;
+
+}
+
+#else /* defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R) */
+
+/* the initial size of our hostent buffers */
+#define HENT_BUF_SIZE 1024
+#define BIG_HENT_BUF_SIZE 10240 /* a jumbo-sized one */
+
+/************************************************************************
+ * Inet4AddressImpl
+ */
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Jnet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
+ char hostname[MAXHOSTNAMELEN+1];
+
+ hostname[0] = '\0';
+ if (JVM_GetHostName(hostname, sizeof(hostname))) {
+ /* Something went wrong, maybe networking is not setup? */
+ strcpy(hostname, "localhost");
+ } else {
+#ifdef __linux__
+ /* On Linux gethostname() says "host.domain.sun.com". On
+ * Solaris gethostname() says "host", so extra work is needed.
+ */
+#else
+ /* Solaris doesn't want to give us a fully qualified domain name.
+ * We do a reverse lookup to try and get one. This works
+ * if DNS occurs before NIS in /etc/resolv.conf, but fails
+ * if NIS comes first (it still gets only a partial name).
+ * We use thread-safe system calls.
+ */
+#endif /* __linux__ */
+ struct hostent res, res2, *hp;
+ // these buffers must be pointer-aligned so they are declared
+ // with pointer type
+ char *buf[HENT_BUF_SIZE/(sizeof (char *))];
+ char *buf2[HENT_BUF_SIZE/(sizeof (char *))];
+ int h_error=0;
+
+ // ensure null-terminated
+ hostname[MAXHOSTNAMELEN] = '\0';
+
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
+#else
+ hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
+#endif
+ if (hp) {
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
+ &res2, (char*)buf2, sizeof(buf2), &hp, &h_error);
+#else
+ hp = gethostbyaddr_r(hp->h_addr, hp->h_length, AF_INET,
+ &res2, (char*)buf2, sizeof(buf2), &h_error);
+#endif
+ if (hp) {
+ /*
+ * If gethostbyaddr_r() found a fully qualified host name,
+ * returns that name. Otherwise, returns the hostname
+ * found by gethostname().
+ */
+ char *p = hp->h_name;
+ if ((strlen(hp->h_name) > strlen(hostname))
+ && (strncmp(hostname, hp->h_name, strlen(hostname)) == 0)
+ && (*(p + strlen(hostname)) == '.'))
+ strcpy(hostname, hp->h_name);
+ }
+ }
+ }
+ return (*env)->NewStringUTF(env, hostname);
+}
+
+static jclass ni_iacls;
+static jclass ni_ia4cls;
+static jmethodID ni_ia4ctrID;
+static int initialized = 0;
+
+/*
+ * Find an internet address for a given hostname. Note that this
+ * code only works for addresses of type INET. The translation
+ * of %d.%d.%d.%d to an address (int) occurs in java now, so the
+ * String "host" shouldn't *ever* be a %d.%d.%d.%d string
+ *
+ * Class: java_net_Inet4AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[[B
+ */
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_net_Jnet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
+ jstring host) {
+ const char *hostname;
+ jobjectArray ret = 0;
+ struct hostent res, *hp = 0;
+ // this buffer must be pointer-aligned so is declared
+ // with pointer type
+ char *buf[HENT_BUF_SIZE/(sizeof (char *))];
+
+ /* temporary buffer, on the off chance we need to expand */
+ char *tmp = NULL;
+ int h_error=0;
+
+ if (!initialized) {
+ ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ initialized = 1;
+ }
+
+ if (IS_NULL(host)) {
+ JNU_ThrowNullPointerException(env, "host is null");
+ return 0;
+ }
+ hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
+ CHECK_NULL_RETURN(hostname, NULL);
+
+#ifdef __solaris__
+ /*
+ * Workaround for Solaris bug 4160367 - if a hostname contains a
+ * white space then 0.0.0.0 is returned
+ */
+ if (isspace((unsigned char)hostname[0])) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
+#endif
+
+ /* Try once, with our static buffer. */
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &hp, &h_error);
+#else
+ hp = gethostbyname_r(hostname, &res, (char*)buf, sizeof(buf), &h_error);
+#endif
+
+ /* With the re-entrant system calls, it's possible that the buffer
+ * we pass to it is not large enough to hold an exceptionally
+ * large DNS entry. This is signaled by errno->ERANGE. We try once
+ * more, with a very big size.
+ */
+ if (hp == NULL && errno == ERANGE) {
+ if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
+ &hp, &h_error);
+#else
+ hp = gethostbyname_r(hostname, &res, tmp, BIG_HENT_BUF_SIZE,
+ &h_error);
+#endif
+ }
+ }
+ if (hp != NULL) {
+ struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
+ int i = 0;
+
+ while (*addrp != (struct in_addr *) 0) {
+ i++;
+ addrp++;
+ }
+
+ ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto cleanupAndReturn;
+ }
+ addrp = (struct in_addr **) hp->h_addr_list;
+ i = 0;
+ while (*addrp) {
+ jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (IS_NULL(iaObj)) {
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ setInetAddress_addr(env, iaObj, ntohl((*addrp)->s_addr));
+ setInetAddress_hostName(env, iaObj, host);
+ (*env)->SetObjectArrayElement(env, ret, i, iaObj);
+ addrp++;
+ i++;
+ }
+ } else {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ (char *)hostname);
+ ret = NULL;
+ }
+
+cleanupAndReturn:
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ if (tmp != NULL) {
+ free(tmp);
+ }
+ return ret;
+}
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getHostByAddr
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Jnet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
+ jbyteArray addrArray) {
+ jstring ret = NULL;
+ jint addr;
+ struct hostent hent, *hp = 0;
+ // this buffer must be pointer-aligned so is declared
+ // with pointer type
+ char *buf[HENT_BUF_SIZE/(sizeof (char *))];
+ int h_error = 0;
+ char *tmp = NULL;
+
+ /*
+ * We are careful here to use the reentrant version of
+ * gethostbyname because at the Java level this routine is not
+ * protected by any synchronization.
+ *
+ * Still keeping the reentrant platform dependent calls temporarily
+ * We should probably conform to one interface later.
+ *
+ */
+ jbyte caddr[4];
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ addr = htonl(addr);
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
+ (char*)buf, sizeof(buf), &hp, &h_error);
+#else
+ hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET, &hent,
+ (char*)buf, sizeof(buf), &h_error);
+#endif
+ /* With the re-entrant system calls, it's possible that the buffer
+ * we pass to it is not large enough to hold an exceptionally
+ * large DNS entry. This is signaled by errno->ERANGE. We try once
+ * more, with a very big size.
+ */
+ if (hp == NULL && errno == ERANGE) {
+ if ((tmp = (char*)malloc(BIG_HENT_BUF_SIZE))) {
+#ifdef HAS_GLIBC_GETHOSTBY_R
+ gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
+ &hent, tmp, BIG_HENT_BUF_SIZE, &hp, &h_error);
+#else
+ hp = gethostbyaddr_r((char *)&addr, sizeof(addr), AF_INET,
+ &hent, tmp, BIG_HENT_BUF_SIZE, &h_error);
+#endif
+ } else {
+ JNU_ThrowOutOfMemoryError(env, "getHostByAddr");
+ }
+ }
+ if (hp == NULL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
+ } else {
+ ret = (*env)->NewStringUTF(env, hp->h_name);
+ }
+ if (tmp) {
+ free(tmp);
+ }
+ return ret;
+}
+
+#endif /* _ALLBSD_SOURCE */
+
+#define SET_NONBLOCKING(fd) { \
+ int flags = fcntl(fd, F_GETFL); \
+ flags |= O_NONBLOCK; \
+ fcntl(fd, F_SETFL, flags); \
+}
+
+/**
+ * ping implementation.
+ * Send a ICMP_ECHO_REQUEST packet every second until either the timeout
+ * expires or a answer is received.
+ * Returns true is an ECHO_REPLY is received, otherwise, false.
+ */
+static jboolean
+ping4(JNIEnv *env, jint fd, struct sockaddr_in* him, jint timeout,
+ struct sockaddr_in* netif, jint ttl) {
+ jint size;
+ jint n, hlen1, icmplen;
+ socklen_t len;
+ char sendbuf[1500];
+ char recvbuf[1500];
+ struct icmp *icmp;
+ struct ip *ip;
+ struct sockaddr_in sa_recv;
+ jchar pid;
+ jint tmout2, seq = 1;
+ struct timeval tv;
+ size_t plen;
+
+ /* icmp_id is a 16 bit data type, therefore down cast the pid */
+ pid = (jchar)getpid();
+ size = 60*1024;
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ /*
+ * sets the ttl (max number of hops)
+ */
+ if (ttl > 0) {
+ setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+ }
+ /*
+ * a specific interface was specified, so let's bind the socket
+ * to that interface to ensure the requests are sent only through it.
+ */
+ if (netif != NULL) {
+ if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
+ NET_ThrowNew(env, errno, "Can't bind socket");
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+ /*
+ * Make the socket non blocking so we can use select
+ */
+ SET_NONBLOCKING(fd);
+ do {
+ /*
+ * create the ICMP request
+ */
+ icmp = (struct icmp *) sendbuf;
+ icmp->icmp_type = ICMP_ECHO;
+ icmp->icmp_code = 0;
+ icmp->icmp_id = htons(pid);
+ icmp->icmp_seq = htons(seq);
+ seq++;
+ gettimeofday(&tv, NULL);
+ memcpy(icmp->icmp_data, &tv, sizeof(tv));
+ plen = ICMP_ADVLENMIN + sizeof(tv);
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = in_cksum((u_short *)icmp, plen);
+ /*
+ * send it
+ */
+ n = sendto(fd, sendbuf, plen, 0, (struct sockaddr *)him,
+ sizeof(struct sockaddr));
+ if (n < 0 && errno != EINPROGRESS ) {
+#ifdef __linux__
+ if (errno != EINVAL && errno != EHOSTUNREACH)
+ /*
+ * On some Linuxes, when bound to the loopback interface, sendto
+ * will fail and errno will be set to EINVAL or EHOSTUNREACH.
+ * When that happens, don't throw an exception, just return false.
+ */
+#endif /*__linux__ */
+ NET_ThrowNew(env, errno, "Can't send ICMP packet");
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ tmout2 = timeout > 1000 ? 1000 : timeout;
+ do {
+ tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
+ if (tmout2 >= 0) {
+ len = sizeof(sa_recv);
+ n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr *)&sa_recv, &len);
+ ip = (struct ip*) recvbuf;
+ hlen1 = (ip->ip_hl) << 2;
+ icmp = (struct icmp *) (recvbuf + hlen1);
+ icmplen = n - hlen1;
+ /*
+ * We did receive something, but is it what we were expecting?
+ * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
+ */
+ if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
+ && (ntohs(icmp->icmp_id) == pid)) {
+ if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
+ close(fd);
+ return JNI_TRUE;
+ }
+
+ if (him->sin_addr.s_addr == 0) {
+ close(fd);
+ return JNI_TRUE;
+ }
+ }
+
+ }
+ } while (tmout2 > 0);
+ timeout -= 1000;
+ } while (timeout >0);
+ close(fd);
+ return JNI_FALSE;
+}
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: isReachable0
+ * Signature: ([bI[bI)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_java_net_Jnet4AddressImpl_isReachable0(JNIEnv *env, jobject this,
+ jbyteArray addrArray,
+ jint timeout,
+ jbyteArray ifArray,
+ jint ttl) {
+ jint addr;
+ jbyte caddr[4];
+ jint fd;
+ struct sockaddr_in him;
+ struct sockaddr_in* netif = NULL;
+ struct sockaddr_in inf;
+ int len = 0;
+ int connect_rv = -1;
+ int sz;
+
+ memset((char *) caddr, 0, sizeof(caddr));
+ memset((char *) &him, 0, sizeof(him));
+ memset((char *) &inf, 0, sizeof(inf));
+ sz = (*env)->GetArrayLength(env, addrArray);
+ if (sz != 4) {
+ return JNI_FALSE;
+ }
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ addr = htonl(addr);
+ him.sin_addr.s_addr = addr;
+ him.sin_family = AF_INET;
+ len = sizeof(him);
+ /*
+ * If a network interface was specified, let's create the address
+ * for it.
+ */
+ if (!(IS_NULL(ifArray))) {
+ memset((char *) caddr, 0, sizeof(caddr));
+ (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ addr = htonl(addr);
+ inf.sin_addr.s_addr = addr;
+ inf.sin_family = AF_INET;
+ inf.sin_port = 0;
+ netif = &inf;
+ }
+
+ /*
+ * Let's try to create a RAW socket to send ICMP packets
+ * This usually requires "root" privileges, so it's likely to fail.
+ */
+ fd = JVM_Socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (fd != -1) {
+ /*
+ * It didn't fail, so we can use ICMP_ECHO requests.
+ */
+ return ping4(env, fd, &him, timeout, netif, ttl);
+ }
+
+ /*
+ * Can't create a raw socket, so let's try a TCP socket
+ */
+ fd = JVM_Socket(AF_INET, SOCK_STREAM, 0);
+ if (fd == JVM_IO_ERR) {
+ /* note: if you run out of fds, you may not be able to load
+ * the exception class, and get a NoClassDefFoundError
+ * instead.
+ */
+ NET_ThrowNew(env, errno, "Can't create socket");
+ return JNI_FALSE;
+ }
+ if (ttl > 0) {
+ setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
+ }
+
+ /*
+ * A network interface was specified, so let's bind to it.
+ */
+ if (netif != NULL) {
+ if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
+ NET_ThrowNew(env, errno, "Can't bind socket");
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+
+ /*
+ * Make the socket non blocking so we can use select/poll.
+ */
+ SET_NONBLOCKING(fd);
+
+ /* no need to use NET_Connect as non-blocking */
+ him.sin_port = htons(7); /* Echo */
+ connect_rv = JVM_Connect(fd, (struct sockaddr *)&him, len);
+
+ /**
+ * connection established or refused immediately, either way it means
+ * we were able to reach the host!
+ */
+ if (connect_rv == 0 || errno == ECONNREFUSED) {
+ close(fd);
+ return JNI_TRUE;
+ } else {
+ int optlen;
+
+ switch (errno) {
+ case ENETUNREACH: /* Network Unreachable */
+ case EAFNOSUPPORT: /* Address Family not supported */
+ case EADDRNOTAVAIL: /* address is not available on the remote machine */
+#ifdef __linux__
+ case EINVAL:
+ case EHOSTUNREACH:
+ /*
+ * On some Linuxes, when bound to the loopback interface, connect
+ * will fail and errno will be set to EINVAL or EHOSTUNREACH.
+ * When that happens, don't throw an exception, just return false.
+ */
+#endif /* __linux__ */
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ if (errno != EINPROGRESS) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "connect failed");
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
+ if (timeout >= 0) {
+ /* has connection been established? */
+ optlen = sizeof(connect_rv);
+ if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
+ &optlen) <0) {
+ connect_rv = errno;
+ }
+ if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
+ close(fd);
+ return JNI_TRUE;
+ }
+ }
+ close(fd);
+ return JNI_FALSE;
+ }
+}
diff --git a/ojluni/src/main/native/Inet6Address.c b/ojluni/src/main/native/Inet6Address.c
new file mode 100755
index 0000000..7b04c67
--- /dev/null
+++ b/ojluni/src/main/native/Inet6Address.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+
+#include "java_net_Inet6Address.h"
+#include "net_util.h"
+
+/************************************************************************
+ * Inet6Address
+ */
+
+jclass ia6_class;
+jfieldID ia6_ipaddressID;
+jfieldID ia6_scopeidID;
+jfieldID ia6_cachedscopeidID;
+jfieldID ia6_scopeidsetID;
+jfieldID ia6_scopeifnameID;
+jfieldID ia6_scopeifnamesetID;
+jmethodID ia6_ctrID;
+
+/*
+ * Class: java_net_Inet6Address
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_Inet6Address_init(JNIEnv *env, jclass cls) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
+ CHECK_NULL(c);
+ ia6_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(ia6_class);
+ ia6_ipaddressID = (*env)->GetFieldID(env, ia6_class, "ipaddress", "[B");
+ CHECK_NULL(ia6_ipaddressID);
+ ia6_scopeidID = (*env)->GetFieldID(env, ia6_class, "scope_id", "I");
+ CHECK_NULL(ia6_scopeidID);
+ ia6_cachedscopeidID = (*env)->GetFieldID(env, ia6_class, "cached_scope_id", "I");
+ CHECK_NULL(ia6_cachedscopeidID);
+ ia6_scopeidsetID = (*env)->GetFieldID(env, ia6_class, "scope_id_set", "Z");
+ CHECK_NULL(ia6_scopeidID);
+ ia6_scopeifnameID = (*env)->GetFieldID(env, ia6_class, "scope_ifname", "Ljava/net/NetworkInterface;");
+ CHECK_NULL(ia6_scopeifnameID);
+ ia6_scopeifnamesetID = (*env)->GetFieldID(env, ia6_class, "scope_ifname_set", "Z");
+ CHECK_NULL(ia6_scopeifnamesetID);
+ ia6_ctrID = (*env)->GetMethodID(env, ia6_class, "<init>", "()V");
+ CHECK_NULL(ia6_ctrID);
+}
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
new file mode 100755
index 0000000..4038504
--- /dev/null
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -0,0 +1,719 @@
+/*
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef _ALLBSD_SOURCE
+#include <unistd.h> /* gethostname */
+#endif
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+#ifndef IPV6_DEFS_H
+#include <netinet/icmp6.h>
+#endif
+
+#include "java_net_Inet4AddressImpl.h"
+#include "java_net_Inet6AddressImpl.h"
+
+/* the initial size of our hostent buffers */
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+
+
+/************************************************************************
+ * Inet6AddressImpl
+ */
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Inet6AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
+ char hostname[NI_MAXHOST+1];
+
+ hostname[0] = '\0';
+ if (JVM_GetHostName(hostname, sizeof(hostname))) {
+ /* Something went wrong, maybe networking is not setup? */
+ strcpy(hostname, "localhost");
+ } else {
+ // ensure null-terminated
+ hostname[NI_MAXHOST] = '\0';
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+ /* On Linux/FreeBSD gethostname() says "host.domain.sun.com". On
+ * Solaris gethostname() says "host", so extra work is needed.
+ */
+#else
+ /* Solaris doesn't want to give us a fully qualified domain name.
+ * We do a reverse lookup to try and get one. This works
+ * if DNS occurs before NIS in /etc/resolv.conf, but fails
+ * if NIS comes first (it still gets only a partial name).
+ * We use thread-safe system calls.
+ */
+#ifdef AF_INET6
+ if (NET_addrtransAvailable()) {
+ struct addrinfo hints, *res;
+ int error;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+
+ error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+
+ if (error == 0) {
+ /* host is known to name service */
+ error = (*getnameinfo_ptr)(res->ai_addr,
+ res->ai_addrlen,
+ hostname,
+ NI_MAXHOST,
+ NULL,
+ 0,
+ NI_NAMEREQD);
+
+ /* if getnameinfo fails hostname is still the value
+ from gethostname */
+
+ (*freeaddrinfo_ptr)(res);
+ }
+ }
+#endif /* AF_INET6 */
+#endif /* __linux__ || _ALLBSD_SOURCE */
+ }
+ return (*env)->NewStringUTF(env, hostname);
+}
+
+static jclass ni_iacls;
+static jclass ni_ia4cls;
+static jclass ni_ia6cls;
+static jmethodID ni_ia4ctrID;
+static jmethodID ni_ia6ctrID;
+static jfieldID ni_ia6ipaddressID;
+static int initialized = 0;
+
+/*
+ * Find an internet address for a given hostname. Note that this
+ * code only works for addresses of type INET. The translation
+ * of %d.%d.%d.%d to an address (int) occurs in java now, so the
+ * String "host" shouldn't *ever* be a %d.%d.%d.%d string
+ *
+ * Class: java_net_Inet6AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[[B
+ */
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
+ jstring host) {
+ const char *hostname;
+ jobjectArray ret = 0;
+ int retLen = 0;
+ jboolean preferIPv6Address;
+
+ int error=0;
+#ifdef AF_INET6
+ struct addrinfo hints, *res, *resNew = NULL;
+#endif /* AF_INET6 */
+
+ if (!initialized) {
+ ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
+ ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
+ ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
+ ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
+ initialized = 1;
+ }
+
+ if (IS_NULL(host)) {
+ JNU_ThrowNullPointerException(env, "host is null");
+ return 0;
+ }
+ hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
+ CHECK_NULL_RETURN(hostname, NULL);
+
+#ifdef AF_INET6
+ if (NET_addrtransAvailable()) {
+ static jfieldID ia_preferIPv6AddressID;
+ if (ia_preferIPv6AddressID == NULL) {
+ jclass c = (*env)->FindClass(env,"java/net/InetAddress");
+ if (c) {
+ ia_preferIPv6AddressID =
+ (*env)->GetStaticFieldID(env, c, "preferIPv6Address", "Z");
+ }
+ if (ia_preferIPv6AddressID == NULL) {
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
+ }
+ /* get the address preference */
+ preferIPv6Address
+ = (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
+
+ /* Try once, with our static buffer. */
+ bzero(&hints, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_UNSPEC;
+
+#ifdef __solaris__
+ /*
+ * Workaround for Solaris bug 4160367 - if a hostname contains a
+ * white space then 0.0.0.0 is returned
+ */
+ if (isspace((unsigned char)hostname[0])) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
+ hostname);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ }
+#endif
+
+ error = (*getaddrinfo_ptr)(hostname, NULL, &hints, &res);
+
+ if (error) {
+ /* report error */
+ ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ return NULL;
+ } else {
+ int i = 0;
+ int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
+ struct addrinfo *itr, *last = NULL, *iterator = res;
+ while (iterator != NULL) {
+ int skip = 0;
+ itr = resNew;
+ while (itr != NULL) {
+ if (iterator->ai_family == itr->ai_family &&
+ iterator->ai_addrlen == itr->ai_addrlen) {
+ if (itr->ai_family == AF_INET) { /* AF_INET */
+ struct sockaddr_in *addr1, *addr2;
+ addr1 = (struct sockaddr_in *)iterator->ai_addr;
+ addr2 = (struct sockaddr_in *)itr->ai_addr;
+ if (addr1->sin_addr.s_addr ==
+ addr2->sin_addr.s_addr) {
+ skip = 1;
+ break;
+ }
+ } else {
+ int t;
+ struct sockaddr_in6 *addr1, *addr2;
+ addr1 = (struct sockaddr_in6 *)iterator->ai_addr;
+ addr2 = (struct sockaddr_in6 *)itr->ai_addr;
+
+ for (t = 0; t < 16; t++) {
+ if (addr1->sin6_addr.s6_addr[t] !=
+ addr2->sin6_addr.s6_addr[t]) {
+ break;
+ }
+ }
+ if (t < 16) {
+ itr = itr->ai_next;
+ continue;
+ } else {
+ skip = 1;
+ break;
+ }
+ }
+ } else if (iterator->ai_family != AF_INET &&
+ iterator->ai_family != AF_INET6) {
+ /* we can't handle other family types */
+ skip = 1;
+ break;
+ }
+ itr = itr->ai_next;
+ }
+
+ if (!skip) {
+ struct addrinfo *next
+ = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+ if (!next) {
+ JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ memcpy(next, iterator, sizeof(struct addrinfo));
+ next->ai_next = NULL;
+ if (resNew == NULL) {
+ resNew = next;
+ } else {
+ last->ai_next = next;
+ }
+ last = next;
+ i++;
+ if (iterator->ai_family == AF_INET) {
+ inetCount ++;
+ } else if (iterator->ai_family == AF_INET6) {
+ inet6Count ++;
+ }
+ }
+ iterator = iterator->ai_next;
+ }
+ retLen = i;
+ iterator = resNew;
+
+ ret = (*env)->NewObjectArray(env, retLen, ni_iacls, NULL);
+
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto cleanupAndReturn;
+ }
+
+ if (preferIPv6Address) {
+ /* AF_INET addresses will be offset by inet6Count */
+ inetIndex = inet6Count;
+ inet6Index = 0;
+ } else {
+ /* AF_INET6 addresses will be offset by inetCount */
+ inetIndex = 0;
+ inet6Index = inetCount;
+ }
+
+ while (iterator != NULL) {
+ if (iterator->ai_family == AF_INET) {
+ jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (IS_NULL(iaObj)) {
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
+ setInetAddress_hostName(env, iaObj, host);
+ (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
+ inetIndex++;
+ } else if (iterator->ai_family == AF_INET6) {
+ jint scope = 0;
+ jbyteArray ipaddress;
+
+ jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
+ if (IS_NULL(iaObj)) {
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ ipaddress = (*env)->NewByteArray(env, 16);
+ if (IS_NULL(ipaddress)) {
+ ret = NULL;
+ goto cleanupAndReturn;
+ }
+ (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
+ (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr));
+#ifdef __linux__
+ if (!kernelIsV22()) {
+ scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
+ }
+#else
+ scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id;
+#endif
+ if (scope != 0) { /* zero is default value, no need to set */
+ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
+ (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+ }
+ (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
+ setInetAddress_hostName(env, iaObj, host);
+ (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
+ inet6Index++;
+ }
+ iterator = iterator->ai_next;
+ }
+ }
+ }
+
+cleanupAndReturn:
+ {
+ struct addrinfo *iterator, *tmp;
+ iterator = resNew;
+ while (iterator != NULL) {
+ tmp = iterator;
+ iterator = iterator->ai_next;
+ free(tmp);
+ }
+ JNU_ReleaseStringPlatformChars(env, host, hostname);
+ }
+
+ if (NET_addrtransAvailable())
+ (*freeaddrinfo_ptr)(res);
+#endif /* AF_INET6 */
+
+ return ret;
+}
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: getHostByAddr
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL
+Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
+ jbyteArray addrArray) {
+
+ jstring ret = NULL;
+
+#ifdef AF_INET6
+ char host[NI_MAXHOST+1];
+ int error = 0;
+ int len = 0;
+ jbyte caddr[16];
+
+ if (NET_addrtransAvailable()) {
+ struct sockaddr_in him4;
+ struct sockaddr_in6 him6;
+ struct sockaddr *sa;
+
+ /*
+ * For IPv4 addresses construct a sockaddr_in structure.
+ */
+ if ((*env)->GetArrayLength(env, addrArray) == 4) {
+ jint addr;
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ memset((void *) &him4, 0, sizeof(him4));
+ him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+ him4.sin_family = AF_INET;
+ sa = (struct sockaddr *) &him4;
+ len = sizeof(him4);
+ } else {
+ /*
+ * For IPv6 address construct a sockaddr_in6 structure.
+ */
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
+ memset((void *) &him6, 0, sizeof(him6));
+ memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+ him6.sin6_family = AF_INET6;
+ sa = (struct sockaddr *) &him6 ;
+ len = sizeof(him6) ;
+ }
+
+ error = (*getnameinfo_ptr)(sa, len, host, NI_MAXHOST, NULL, 0,
+ NI_NAMEREQD);
+
+ if (!error) {
+ ret = (*env)->NewStringUTF(env, host);
+ }
+ }
+#endif /* AF_INET6 */
+
+ if (ret == NULL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
+ }
+
+ return ret;
+}
+
+#define SET_NONBLOCKING(fd) { \
+ int flags = fcntl(fd, F_GETFL); \
+ flags |= O_NONBLOCK; \
+ fcntl(fd, F_SETFL, flags); \
+}
+
+#ifdef AF_INET6
+static jboolean
+ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
+ struct sockaddr_in6* netif, jint ttl) {
+ jint size;
+ jint n;
+ socklen_t len;
+ char sendbuf[1500];
+ unsigned char recvbuf[1500];
+ struct icmp6_hdr *icmp6;
+ struct sockaddr_in6 sa_recv;
+ jbyte *caddr, *recv_caddr;
+ jchar pid;
+ jint tmout2, seq = 1;
+ struct timeval tv;
+ size_t plen;
+
+#ifdef __linux__
+ {
+ int csum_offset;
+ /**
+ * For some strange reason, the linux kernel won't calculate the
+ * checksum of ICMPv6 packets unless you set this socket option
+ */
+ csum_offset = 2;
+ setsockopt(fd, SOL_RAW, IPV6_CHECKSUM, &csum_offset, sizeof(int));
+ }
+#endif
+
+ caddr = (jbyte *)&(him->sin6_addr);
+
+ /* icmp_id is a 16 bit data type, therefore down cast the pid */
+ pid = (jchar)getpid();
+ size = 60*1024;
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ if (ttl > 0) {
+ setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
+ }
+ if (netif != NULL) {
+ if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
+ NET_ThrowNew(env, errno, "Can't bind socket");
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+ SET_NONBLOCKING(fd);
+
+ do {
+ icmp6 = (struct icmp6_hdr *) sendbuf;
+ icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
+ icmp6->icmp6_code = 0;
+ /* let's tag the ECHO packet with our pid so we can identify it */
+ icmp6->icmp6_id = htons(pid);
+ icmp6->icmp6_seq = htons(seq);
+ seq++;
+ icmp6->icmp6_cksum = 0;
+ gettimeofday(&tv, NULL);
+ memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv));
+ plen = sizeof(struct icmp6_hdr) + sizeof(tv);
+ n = sendto(fd, sendbuf, plen, 0, (struct sockaddr*) him, sizeof(struct sockaddr_in6));
+ if (n < 0 && errno != EINPROGRESS) {
+#ifdef __linux__
+ if (errno != EINVAL && errno != EHOSTUNREACH)
+ /*
+ * On some Linuxes, when bound to the loopback interface, sendto
+ * will fail and errno will be set to EINVAL or EHOSTUNREACH.
+ * When that happens, don't throw an exception, just return false.
+ */
+#endif /*__linux__ */
+ NET_ThrowNew(env, errno, "Can't send ICMP packet");
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ tmout2 = timeout > 1000 ? 1000 : timeout;
+ do {
+ tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2);
+
+ if (tmout2 >= 0) {
+ len = sizeof(sa_recv);
+ n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*) &sa_recv, &len);
+ icmp6 = (struct icmp6_hdr *) (recvbuf);
+ recv_caddr = (jbyte *)&(sa_recv.sin6_addr);
+ /*
+ * We did receive something, but is it what we were expecting?
+ * I.E.: An ICMP6_ECHO_REPLY packet with the proper PID and
+ * from the host that we are trying to determine is reachable.
+ */
+ if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
+ (ntohs(icmp6->icmp6_id) == pid)) {
+ if (NET_IsEqual(caddr, recv_caddr)) {
+ close(fd);
+ return JNI_TRUE;
+ }
+ if (NET_IsZeroAddr(caddr)) {
+ close(fd);
+ return JNI_TRUE;
+ }
+ }
+ }
+ } while (tmout2 > 0);
+ timeout -= 1000;
+ } while (timeout > 0);
+ close(fd);
+ return JNI_FALSE;
+}
+#endif /* AF_INET6 */
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: isReachable0
+ * Signature: ([bII[bI)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_java_net_Inet6AddressImpl_isReachable0(JNIEnv *env, jobject this,
+ jbyteArray addrArray,
+ jint scope,
+ jint timeout,
+ jbyteArray ifArray,
+ jint ttl, jint if_scope) {
+#ifdef AF_INET6
+ jbyte caddr[16];
+ jint fd, sz;
+ struct sockaddr_in6 him6;
+ struct sockaddr_in6 inf6;
+ struct sockaddr_in6* netif = NULL;
+ int len = 0;
+ int connect_rv = -1;
+
+ /*
+ * If IPv6 is not enable, then we can't reach an IPv6 address, can we?
+ */
+ if (!ipv6_available()) {
+ return JNI_FALSE;
+ }
+ /*
+ * If it's an IPv4 address, ICMP won't work with IPv4 mapped address,
+ * therefore, let's delegate to the Inet4Address method.
+ */
+ sz = (*env)->GetArrayLength(env, addrArray);
+ if (sz == 4) {
+ return Java_java_net_Inet4AddressImpl_isReachable0(env, this,
+ addrArray,
+ timeout,
+ ifArray, ttl);
+ }
+
+ memset((void *) caddr, 0, 16);
+ memset((void *) &him6, 0, sizeof(him6));
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
+ memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+ him6.sin6_family = AF_INET6;
+#ifdef __linux__
+ if (scope > 0)
+ him6.sin6_scope_id = scope;
+ else
+ him6.sin6_scope_id = getDefaultIPv6Interface( &(him6.sin6_addr));
+ len = sizeof(struct sockaddr_in6);
+#else
+ if (scope > 0)
+ him6.sin6_scope_id = scope;
+ len = sizeof(struct sockaddr_in6);
+#endif
+ /*
+ * If a network interface was specified, let's create the address
+ * for it.
+ */
+ if (!(IS_NULL(ifArray))) {
+ memset((void *) caddr, 0, 16);
+ memset((void *) &inf6, 0, sizeof(inf6));
+ (*env)->GetByteArrayRegion(env, ifArray, 0, 16, caddr);
+ memcpy((void *)&(inf6.sin6_addr), caddr, sizeof(struct in6_addr) );
+ inf6.sin6_family = AF_INET6;
+ inf6.sin6_scope_id = if_scope;
+ netif = &inf6;
+ }
+ /*
+ * If we can create a RAW socket, then when can use the ICMP ECHO_REQUEST
+ * otherwise we'll try a tcp socket to the Echo port (7).
+ * Note that this is empiric, and not connecting could mean it's blocked
+ * or the echo servioe has been disabled.
+ */
+
+ fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+
+ if (fd != -1) { /* Good to go, let's do a ping */
+ return ping6(env, fd, &him6, timeout, netif, ttl);
+ }
+
+ /* No good, let's fall back on TCP */
+ fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0);
+ if (fd == JVM_IO_ERR) {
+ /* note: if you run out of fds, you may not be able to load
+ * the exception class, and get a NoClassDefFoundError
+ * instead.
+ */
+ NET_ThrowNew(env, errno, "Can't create socket");
+ return JNI_FALSE;
+ }
+ if (ttl > 0) {
+ setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
+ }
+
+ /*
+ * A network interface was specified, so let's bind to it.
+ */
+ if (netif != NULL) {
+ if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
+ NET_ThrowNew(env, errno, "Can't bind socket");
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+ SET_NONBLOCKING(fd);
+
+ /* no need to use NET_Connect as non-blocking */
+ him6.sin6_port = htons((short) 7); /* Echo port */
+ connect_rv = JVM_Connect(fd, (struct sockaddr *)&him6, len);
+
+ /**
+ * connection established or refused immediately, either way it means
+ * we were able to reach the host!
+ */
+ if (connect_rv == 0 || errno == ECONNREFUSED) {
+ close(fd);
+ return JNI_TRUE;
+ } else {
+ int optlen;
+
+ switch (errno) {
+ case ENETUNREACH: /* Network Unreachable */
+ case EAFNOSUPPORT: /* Address Family not supported */
+ case EADDRNOTAVAIL: /* address is not available on the remote machine */
+#ifdef __linux__
+ case EINVAL:
+ case EHOSTUNREACH:
+ /*
+ * On some Linuxes, when bound to the loopback interface, connect
+ * will fail and errno will be set to EINVAL or EHOSTUNREACH.
+ * When that happens, don't throw an exception, just return false.
+ */
+#endif /* __linux__ */
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ if (errno != EINPROGRESS) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "connect failed");
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ timeout = NET_Wait(env, fd, NET_WAIT_CONNECT, timeout);
+
+ if (timeout >= 0) {
+ /* has connection been established */
+ optlen = sizeof(connect_rv);
+ if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
+ &optlen) <0) {
+ connect_rv = errno;
+ }
+ if (connect_rv == 0 || ECONNREFUSED) {
+ close(fd);
+ return JNI_TRUE;
+ }
+ }
+ close(fd);
+ return JNI_FALSE;
+ }
+#else /* AF_INET6 */
+ return JNI_FALSE;
+#endif /* AF_INET6 */
+}
diff --git a/ojluni/src/main/native/InetAddress.c b/ojluni/src/main/native/InetAddress.c
new file mode 100755
index 0000000..3111573
--- /dev/null
+++ b/ojluni/src/main/native/InetAddress.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+
+#include "java_net_InetAddress.h"
+#include "net_util.h"
+
+/************************************************************************
+ * InetAddress
+ */
+
+jclass ia_class;
+jclass iac_class;
+jfieldID ia_holderID;
+jfieldID iac_addressID;
+jfieldID iac_familyID;
+jfieldID iac_hostNameID;
+jfieldID ia_preferIPv6AddressID;
+
+/*
+ * Class: java_net_InetAddress
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
+ jclass c = (*env)->FindClass(env,"java/net/InetAddress");
+ CHECK_NULL(c);
+ ia_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(ia_class);
+ c = (*env)->FindClass(env,"java/net/InetAddress$InetAddressHolder");
+ CHECK_NULL(c);
+ iac_class = (*env)->NewGlobalRef(env, c);
+ ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
+ CHECK_NULL(ia_holderID);
+ ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
+ CHECK_NULL(ia_preferIPv6AddressID);
+
+ iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
+ CHECK_NULL(iac_addressID);
+ iac_familyID = (*env)->GetFieldID(env, iac_class, "family", "I");
+ CHECK_NULL(iac_familyID);
+ iac_hostNameID = (*env)->GetFieldID(env, iac_class, "hostName", "Ljava/lang/String;");
+ CHECK_NULL(iac_hostNameID);
+}
diff --git a/ojluni/src/main/native/InetAddressImplFactory.c b/ojluni/src/main/native/InetAddressImplFactory.c
new file mode 100755
index 0000000..feae950
--- /dev/null
+++ b/ojluni/src/main/native/InetAddressImplFactory.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997, 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "java_net_InetAddressImplFactory.h"
+
+#include "net_util.h"
+
+/************************************************************************
+ * InetAddressImplFactory
+ */
+
+/*
+ * Class: java_net_InetAddressImplFactory
+ * Method: isIPv6Supported
+ * Signature: ()I
+ */
+JNIEXPORT jboolean JNICALL
+Java_java_net_InetAddressImplFactory_isIPv6Supported(JNIEnv *env, jclass cls)
+{
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ return JNI_TRUE;
+ } else
+#endif /* AF_INET6 */
+ {
+ return JNI_FALSE;
+ }
+}
diff --git a/ojluni/src/main/native/NativeSignalHandler.c b/ojluni/src/main/native/NativeSignalHandler.c
new file mode 100755
index 0000000..23c7589
--- /dev/null
+++ b/ojluni/src/main/native/NativeSignalHandler.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+
+#include <jni.h>
+#include <jlong.h>
+#include "sun_misc_NativeSignalHandler.h"
+
+typedef void (*sig_handler_t)(jint, void *, void *);
+
+JNIEXPORT void JNICALL
+Java_sun_misc_NativeSignalHandler_handle0(JNIEnv *env, jclass cls, jint sig, jlong f)
+{
+ /* We've lost the siginfo and context */
+ (*(sig_handler_t)jlong_to_ptr(f))(sig, NULL, NULL);
+}
diff --git a/ojluni/src/main/native/NativeThread.c b/ojluni/src/main/native/NativeThread.c
new file mode 100755
index 0000000..79a91a0
--- /dev/null
+++ b/ojluni/src/main/native/NativeThread.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <sys/types.h>
+#include <string.h>
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "sun_nio_ch_NativeThread.h"
+#include "nio_util.h"
+
+
+#ifdef __linux__
+#include <pthread.h>
+#include <sys/signal.h>
+
+/* Also defined in src/solaris/native/java/net/linux_close.c */
+#define INTERRUPT_SIGNAL (__SIGRTMAX - 2)
+
+static void
+nullHandler(int sig)
+{
+}
+
+#endif
+
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_NativeThread_init(JNIEnv *env, jclass cl)
+{
+#ifdef __linux__
+
+ /* Install the null handler for INTERRUPT_SIGNAL. This might overwrite the
+ * handler previously installed by java/net/linux_close.c, but that's okay
+ * since neither handler actually does anything. We install our own
+ * handler here simply out of paranoia; ultimately the two mechanisms
+ * should somehow be unified, perhaps within the VM.
+ */
+
+ sigset_t ss;
+ struct sigaction sa, osa;
+ sa.sa_handler = nullHandler;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(INTERRUPT_SIGNAL, &sa, &osa) < 0)
+ JNU_ThrowIOExceptionWithLastError(env, "sigaction");
+
+#endif
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_NativeThread_current(JNIEnv *env, jclass cl)
+{
+#ifdef __linux__
+ return (long)pthread_self();
+#else
+ return -1;
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_sun_nio_ch_NativeThread_signal(JNIEnv *env, jclass cl, jlong thread)
+{
+#ifdef __linux__
+ if (pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL))
+ JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed");
+#endif
+}
diff --git a/ojluni/src/main/native/NetworkInterface.c b/ojluni/src/main/native/NetworkInterface.c
new file mode 100755
index 0000000..6a31a61
--- /dev/null
+++ b/ojluni/src/main/native/NetworkInterface.c
@@ -0,0 +1,2000 @@
+/*
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+#include <errno.h>
+#include <strings.h>
+#if defined(_ALLBSD_SOURCE) && defined(__OpenBSD__)
+#include <sys/types.h>
+#endif
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+
+#ifdef __solaris__
+#include <sys/dlpi.h>
+#include <fcntl.h>
+#include <stropts.h>
+#include <sys/sockio.h>
+#endif
+
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <bits/ioctls.h>
+#include <sys/utsname.h>
+#include <stdio.h>
+#endif
+
+#ifdef __linux__
+#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
+#endif
+
+#if defined(_ALLBSD_SOURCE)
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/sockio.h>
+#if defined(__APPLE__)
+#include <net/ethernet.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <netinet/in_var.h>
+#include <ifaddrs.h>
+#endif
+#endif
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+typedef struct _netaddr {
+ struct sockaddr *addr;
+ struct sockaddr *brdcast;
+ short mask;
+ int family; /* to make searches simple */
+ struct _netaddr *next;
+} netaddr;
+
+typedef struct _netif {
+ char *name;
+ int index;
+ char virtual;
+ netaddr *addr;
+ struct _netif *childs;
+ struct _netif *next;
+} netif;
+
+/************************************************************************
+ * NetworkInterface
+ */
+
+#include "java_net_NetworkInterface.h"
+
+/************************************************************************
+ * NetworkInterface
+ */
+jclass ni_class;
+jfieldID ni_nameID;
+jfieldID ni_indexID;
+jfieldID ni_descID;
+jfieldID ni_addrsID;
+jfieldID ni_bindsID;
+jfieldID ni_virutalID;
+jfieldID ni_childsID;
+jfieldID ni_parentID;
+jfieldID ni_defaultIndexID;
+jmethodID ni_ctrID;
+
+static jclass ni_iacls;
+static jclass ni_ia4cls;
+static jclass ni_ia6cls;
+static jclass ni_ibcls;
+static jmethodID ni_ia4ctrID;
+static jmethodID ni_ia6ctrID;
+static jmethodID ni_ibctrID;
+static jfieldID ni_ia6ipaddressID;
+static jfieldID ni_ibaddressID;
+static jfieldID ni_ib4broadcastID;
+static jfieldID ni_ib4maskID;
+
+/** Private methods declarations **/
+static jobject createNetworkInterface(JNIEnv *env, netif *ifs);
+static int getFlags0(JNIEnv *env, jstring ifname);
+
+static netif *enumInterfaces(JNIEnv *env);
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
+#endif
+
+static netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix);
+static void freeif(netif *ifs);
+
+static int openSocket(JNIEnv *env, int proto);
+static int openSocketWithFallback(JNIEnv *env, const char *ifname);
+
+
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store);
+static short getSubnet(JNIEnv *env, int sock, const char *ifname);
+static int getIndex(int sock, const char *ifname);
+
+static int getFlags(int sock, const char *ifname, int *flags);
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf);
+static int getMTU(JNIEnv *env, int sock, const char *ifname);
+
+
+
+#ifdef __solaris__
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family);
+static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf);
+
+#ifndef SIOCGLIFHWADDR
+#define SIOCGLIFHWADDR _IOWR('i', 192, struct lifreq)
+#endif
+
+#endif
+
+/******************* Java entry points *****************************/
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) {
+ ni_class = (*env)->FindClass(env,"java/net/NetworkInterface");
+ ni_class = (*env)->NewGlobalRef(env, ni_class);
+ ni_nameID = (*env)->GetFieldID(env, ni_class,"name", "Ljava/lang/String;");
+ ni_indexID = (*env)->GetFieldID(env, ni_class, "index", "I");
+ ni_addrsID = (*env)->GetFieldID(env, ni_class, "addrs", "[Ljava/net/InetAddress;");
+ ni_bindsID = (*env)->GetFieldID(env, ni_class, "bindings", "[Ljava/net/InterfaceAddress;");
+ ni_descID = (*env)->GetFieldID(env, ni_class, "displayName", "Ljava/lang/String;");
+ ni_virutalID = (*env)->GetFieldID(env, ni_class, "virtual", "Z");
+ ni_childsID = (*env)->GetFieldID(env, ni_class, "childs", "[Ljava/net/NetworkInterface;");
+ ni_parentID = (*env)->GetFieldID(env, ni_class, "parent", "Ljava/net/NetworkInterface;");
+ ni_ctrID = (*env)->GetMethodID(env, ni_class, "<init>", "()V");
+
+ ni_iacls = (*env)->FindClass(env, "java/net/InetAddress");
+ ni_iacls = (*env)->NewGlobalRef(env, ni_iacls);
+ ni_ia4cls = (*env)->FindClass(env, "java/net/Inet4Address");
+ ni_ia4cls = (*env)->NewGlobalRef(env, ni_ia4cls);
+ ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address");
+ ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls);
+ ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress");
+ ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls);
+ ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "<init>", "()V");
+ ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "<init>", "()V");
+ ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "<init>", "()V");
+ ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B");
+ ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;");
+ ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;");
+ ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S");
+ ni_defaultIndexID = (*env)->GetStaticFieldID(env, ni_class, "defaultIndex", "I");
+}
+
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByName0
+ * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
+ (JNIEnv *env, jclass cls, jstring name) {
+
+ netif *ifs, *curr;
+ jboolean isCopy;
+ const char* name_utf;
+ jobject obj = NULL;
+
+ ifs = enumInterfaces(env);
+ if (ifs == NULL) {
+ return NULL;
+ }
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ /*
+ * Search the list of interface based on name
+ */
+ curr = ifs;
+ while (curr != NULL) {
+ if (strcmp(name_utf, curr->name) == 0) {
+ break;
+ }
+ curr = curr->next;
+ }
+
+ /* if found create a NetworkInterface */
+ if (curr != NULL) {;
+ obj = createNetworkInterface(env, curr);
+ }
+
+ /* release the UTF string and interface list */
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ freeif(ifs);
+
+ return obj;
+}
+
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByIndex0
+ * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
+ (JNIEnv *env, jclass cls, jint index) {
+
+ netif *ifs, *curr;
+ jobject obj = NULL;
+
+ if (index <= 0) {
+ return NULL;
+ }
+
+ ifs = enumInterfaces(env);
+ if (ifs == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Search the list of interface based on index
+ */
+ curr = ifs;
+ while (curr != NULL) {
+ if (index == curr->index) {
+ break;
+ }
+ curr = curr->next;
+ }
+
+ /* if found create a NetworkInterface */
+ if (curr != NULL) {;
+ obj = createNetworkInterface(env, curr);
+ }
+
+ freeif(ifs);
+ return obj;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByInetAddress0
+ * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
+ (JNIEnv *env, jclass cls, jobject iaObj) {
+
+ netif *ifs, *curr;
+
+#ifdef AF_INET6
+ int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
+#else
+ int family = AF_INET;
+#endif
+
+ jobject obj = NULL;
+ jboolean match = JNI_FALSE;
+
+ ifs = enumInterfaces(env);
+ if (ifs == NULL) {
+ return NULL;
+ }
+
+ curr = ifs;
+ while (curr != NULL) {
+ netaddr *addrP = curr->addr;
+
+ /*
+ * Iterate through each address on the interface
+ */
+ while (addrP != NULL) {
+
+ if (family == addrP->family) {
+ if (family == AF_INET) {
+ int address1 = htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr);
+ int address2 = getInetAddress_addr(env, iaObj);
+
+ if (address1 == address2) {
+ match = JNI_TRUE;
+ break;
+ }
+ }
+
+#ifdef AF_INET6
+ if (family == AF_INET6) {
+ jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr);
+ jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID);
+ jbyte caddr[16];
+ int i;
+
+ (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+ i = 0;
+ while (i < 16) {
+ if (caddr[i] != bytes[i]) {
+ break;
+ }
+ i++;
+ }
+ if (i >= 16) {
+ match = JNI_TRUE;
+ break;
+ }
+ }
+#endif
+
+ }
+
+ if (match) {
+ break;
+ }
+ addrP = addrP->next;
+ }
+
+ if (match) {
+ break;
+ }
+ curr = curr->next;
+ }
+
+ /* if found create a NetworkInterface */
+ if (match) {;
+ obj = createNetworkInterface(env, curr);
+ }
+
+ freeif(ifs);
+ return obj;
+}
+
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getAll
+ * Signature: ()[Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
+ (JNIEnv *env, jclass cls) {
+
+ netif *ifs, *curr;
+ jobjectArray netIFArr;
+ jint arr_index, ifCount;
+
+ ifs = enumInterfaces(env);
+ if (ifs == NULL) {
+ return NULL;
+ }
+
+ /* count the interface */
+ ifCount = 0;
+ curr = ifs;
+ while (curr != NULL) {
+ ifCount++;
+ curr = curr->next;
+ }
+
+ /* allocate a NetworkInterface array */
+ netIFArr = (*env)->NewObjectArray(env, ifCount, cls, NULL);
+ if (netIFArr == NULL) {
+ freeif(ifs);
+ return NULL;
+ }
+
+ /*
+ * Iterate through the interfaces, create a NetworkInterface instance
+ * for each array element and populate the object.
+ */
+ curr = ifs;
+ arr_index = 0;
+ while (curr != NULL) {
+ jobject netifObj;
+
+ netifObj = createNetworkInterface(env, curr);
+ if (netifObj == NULL) {
+ freeif(ifs);
+ return NULL;
+ }
+
+ /* put the NetworkInterface into the array */
+ (*env)->SetObjectArrayElement(env, netIFArr, arr_index++, netifObj);
+
+ curr = curr->next;
+ }
+
+ freeif(ifs);
+ return netIFArr;
+}
+
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isUp0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isP2P0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isLoopback0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: supportsMulticast0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) {
+ int ret = getFlags0(env, name);
+ return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMacAddr0
+ * Signature: ([bLjava/lang/String;I)[b
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) {
+ jint addr;
+ jbyte caddr[4];
+ struct in_addr iaddr;
+ jbyteArray ret = NULL;
+ unsigned char mac[16];
+ int len;
+ int sock;
+ jboolean isCopy;
+ const char* name_utf;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return JNI_FALSE;
+ }
+
+
+ if (!IS_NULL(addrArray)) {
+ (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
+ addr = ((caddr[0]<<24) & 0xff000000);
+ addr |= ((caddr[1] <<16) & 0xff0000);
+ addr |= ((caddr[2] <<8) & 0xff00);
+ addr |= (caddr[3] & 0xff);
+ iaddr.s_addr = htonl(addr);
+ len = getMacAddress(env, sock, name_utf, &iaddr, mac);
+ } else {
+ len = getMacAddress(env, sock, name_utf,NULL, mac);
+ }
+ if (len > 0) {
+ ret = (*env)->NewByteArray(env, len);
+ if (IS_NULL(ret)) {
+ /* we may have memory to free at the end of this */
+ goto fexit;
+ }
+ (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac));
+ }
+ fexit:
+ /* release the UTF string and interface list */
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ close(sock);
+ return ret;
+}
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMTU0
+ * Signature: ([bLjava/lang/String;I)I
+ */
+
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) {
+ jboolean isCopy;
+ int ret = -1;
+ int sock;
+ const char* name_utf;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock =openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return JNI_FALSE;
+ }
+
+ ret = getMTU(env, sock, name_utf);
+
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ close(sock);
+ return ret;
+}
+
+/*** Private methods definitions ****/
+
+static int getFlags0(JNIEnv *env, jstring name) {
+ jboolean isCopy;
+ int ret, sock;
+ const char* name_utf;
+ int flags = 0;
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ if ((sock = openSocketWithFallback(env, name_utf)) < 0) {
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+ return -1;
+ }
+
+ name_utf = (*env)->GetStringUTFChars(env, name, &isCopy);
+
+ ret = getFlags(sock, name_utf, &flags);
+
+ close(sock);
+ (*env)->ReleaseStringUTFChars(env, name, name_utf);
+
+ if (ret < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+ return -1;
+ }
+
+ return flags;
+}
+
+
+
+
+/*
+ * Create a NetworkInterface object, populate the name and index, and
+ * populate the InetAddress array based on the IP addresses for this
+ * interface.
+ */
+jobject createNetworkInterface(JNIEnv *env, netif *ifs) {
+ jobject netifObj;
+ jobject name;
+ jobjectArray addrArr;
+ jobjectArray bindArr;
+ jobjectArray childArr;
+ netaddr *addrs;
+ jint addr_index, addr_count, bind_index;
+ jint child_count, child_index;
+ netaddr *addrP;
+ netif *childP;
+ jobject tmp;
+
+ /*
+ * Create a NetworkInterface object and populate it
+ */
+ netifObj = (*env)->NewObject(env, ni_class, ni_ctrID);
+ name = (*env)->NewStringUTF(env, ifs->name);
+ if (netifObj == NULL || name == NULL) {
+ return NULL;
+ }
+ (*env)->SetObjectField(env, netifObj, ni_nameID, name);
+ (*env)->SetObjectField(env, netifObj, ni_descID, name);
+ (*env)->SetIntField(env, netifObj, ni_indexID, ifs->index);
+ (*env)->SetBooleanField(env, netifObj, ni_virutalID, ifs->virtual ? JNI_TRUE : JNI_FALSE);
+
+ /*
+ * Count the number of address on this interface
+ */
+ addr_count = 0;
+ addrP = ifs->addr;
+ while (addrP != NULL) {
+ addr_count++;
+ addrP = addrP->next;
+ }
+
+ /*
+ * Create the array of InetAddresses
+ */
+ addrArr = (*env)->NewObjectArray(env, addr_count, ni_iacls, NULL);
+ if (addrArr == NULL) {
+ return NULL;
+ }
+
+ bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL);
+ if (bindArr == NULL) {
+ return NULL;
+ }
+ addrP = ifs->addr;
+ addr_index = 0;
+ bind_index = 0;
+ while (addrP != NULL) {
+ jobject iaObj = NULL;
+ jobject ibObj = NULL;
+
+ if (addrP->family == AF_INET) {
+ iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (iaObj) {
+ setInetAddress_addr(env, iaObj, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr));
+ }
+ ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
+ if (ibObj) {
+ (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+ if (addrP->brdcast) {
+ jobject ia2Obj = NULL;
+ ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
+ if (ia2Obj) {
+ setInetAddress_addr(env, ia2Obj, htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr));
+ (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj);
+ (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+ }
+ }
+ (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+ }
+ }
+
+#ifdef AF_INET6
+ if (addrP->family == AF_INET6) {
+ int scope=0;
+ iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID);
+ if (iaObj) {
+ jbyteArray ipaddress = (*env)->NewByteArray(env, 16);
+ if (ipaddress == NULL) {
+ return NULL;
+ }
+ (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
+ (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr));
+
+ scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id;
+
+ if (scope != 0) { /* zero is default value, no need to set */
+ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
+ (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+ (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj);
+ }
+ (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
+ }
+ ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID);
+ if (ibObj) {
+ (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj);
+ (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask);
+ (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj);
+ }
+ }
+#endif
+
+ if (iaObj == NULL) {
+ return NULL;
+ }
+
+ (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
+ addrP = addrP->next;
+ }
+
+ /*
+ * See if there is any virtual interface attached to this one.
+ */
+ child_count = 0;
+ childP = ifs->childs;
+ while (childP) {
+ child_count++;
+ childP = childP->next;
+ }
+
+ childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL);
+ if (childArr == NULL) {
+ return NULL;
+ }
+
+ /*
+ * Create the NetworkInterface instances for the sub-interfaces as
+ * well.
+ */
+ child_index = 0;
+ childP = ifs->childs;
+ while(childP) {
+ tmp = createNetworkInterface(env, childP);
+ if (tmp == NULL) {
+ return NULL;
+ }
+ (*env)->SetObjectField(env, tmp, ni_parentID, netifObj);
+ (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp);
+ childP = childP->next;
+ }
+ (*env)->SetObjectField(env, netifObj, ni_addrsID, addrArr);
+ (*env)->SetObjectField(env, netifObj, ni_bindsID, bindArr);
+ (*env)->SetObjectField(env, netifObj, ni_childsID, childArr);
+
+ /* return the NetworkInterface */
+ return netifObj;
+}
+
+/*
+ * Enumerates all interfaces
+ */
+static netif *enumInterfaces(JNIEnv *env) {
+ netif *ifs;
+ int sock;
+
+ /*
+ * Enumerate IPv4 addresses
+ */
+
+ sock = openSocket(env, AF_INET);
+ if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ return NULL;
+ }
+
+ ifs = enumIPv4Interfaces(env, sock, NULL);
+ close(sock);
+
+ if (ifs == NULL && (*env)->ExceptionOccurred(env)) {
+ return NULL;
+ }
+
+ /* return partial list if exception occure in the middle of process ???*/
+
+ /*
+ * If IPv6 is available then enumerate IPv6 addresses.
+ */
+#ifdef AF_INET6
+
+ /* User can disable ipv6 expicitly by -Djava.net.preferIPv4Stack=true,
+ * so we have to call ipv6_available()
+ */
+ if (ipv6_available()) {
+
+ sock = openSocket(env, AF_INET6);
+ if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+ freeif(ifs);
+ return NULL;
+ }
+
+ ifs = enumIPv6Interfaces(env, sock, ifs);
+ close(sock);
+
+ if ((*env)->ExceptionOccurred(env)) {
+ freeif(ifs);
+ return NULL;
+ }
+
+ }
+#endif
+
+ return ifs;
+}
+
+#define CHECKED_MALLOC3(_pointer,_type,_size) \
+ do{ \
+ _pointer = (_type)malloc( _size ); \
+ if (_pointer == NULL) { \
+ JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); \
+ return ifs; /* return untouched list */ \
+ } \
+ } while(0)
+
+
+/*
+ * Free an interface list (including any attached addresses)
+ */
+void freeif(netif *ifs) {
+ netif *currif = ifs;
+ netif *child = NULL;
+
+ while (currif != NULL) {
+ netaddr *addrP = currif->addr;
+ while (addrP != NULL) {
+ netaddr *next = addrP->next;
+ free(addrP);
+ addrP = next;
+ }
+
+ /*
+ * Don't forget to free the sub-interfaces.
+ */
+ if (currif->childs != NULL) {
+ freeif(currif->childs);
+ }
+
+ ifs = currif->next;
+ free(currif);
+ currif = ifs;
+ }
+}
+
+netif *addif(JNIEnv *env, int sock, const char * if_name,
+ netif *ifs, struct sockaddr* ifr_addrP, int family,
+ short prefix)
+{
+ netif *currif = ifs, *parent;
+ netaddr *addrP;
+
+#ifdef LIFNAMSIZ
+ int ifnam_size = LIFNAMSIZ;
+ char name[LIFNAMSIZ], vname[LIFNAMSIZ];
+#else
+ int ifnam_size = IFNAMSIZ;
+ char name[IFNAMSIZ], vname[IFNAMSIZ];
+#endif
+
+ char *name_colonP;
+ int mask;
+ int isVirtual = 0;
+ int addr_size;
+ int flags = 0;
+
+ /*
+ * If the interface name is a logical interface then we
+ * remove the unit number so that we have the physical
+ * interface (eg: hme0:1 -> hme0). NetworkInterface
+ * currently doesn't have any concept of physical vs.
+ * logical interfaces.
+ */
+ strncpy(name, if_name, ifnam_size);
+ name[ifnam_size - 1] = '\0';
+ *vname = 0;
+
+ /*
+ * Create and populate the netaddr node. If allocation fails
+ * return an un-updated list.
+ */
+ /*Allocate for addr and brdcast at once*/
+
+#ifdef AF_INET6
+ addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
+#else
+ addr_size = sizeof(struct sockaddr_in);
+#endif
+
+ CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size);
+ addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) );
+ memcpy(addrP->addr, ifr_addrP, addr_size);
+
+ addrP->family = family;
+ addrP->brdcast = NULL;
+ addrP->mask = prefix;
+ addrP->next = 0;
+ if (family == AF_INET) {
+ /*
+ * Deal with brodcast addr & subnet mask
+ */
+ struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size);
+ addrP->brdcast = getBroadcast(env, sock, name, brdcast_to );
+
+ if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) {
+ addrP->mask = mask;
+ }
+ }
+
+ /**
+ * Deal with virtual interface with colon notaion e.g. eth0:1
+ */
+ name_colonP = strchr(name, ':');
+ if (name_colonP != NULL) {
+ /**
+ * This is a virtual interface. If we are able to access the parent
+ * we need to create a new entry if it doesn't exist yet *and* update
+ * the 'parent' interface with the new records.
+ */
+ *name_colonP = 0;
+ if (getFlags(sock, name, &flags) < 0 || flags < 0) {
+ // failed to access parent interface do not create parent.
+ // We are a virtual interface with no parent.
+ isVirtual = 1;
+ *name_colonP = ':';
+ }
+ else{
+ // Got access to parent, so create it if necessary.
+ // Save original name to vname and truncate name by ':'
+ memcpy(vname, name, sizeof(vname) );
+ vname[name_colonP - name] = ':';
+ }
+ }
+
+ /*
+ * Check if this is a "new" interface. Use the interface
+ * name for matching because index isn't supported on
+ * Solaris 2.6 & 7.
+ */
+ while (currif != NULL) {
+ if (strcmp(name, currif->name) == 0) {
+ break;
+ }
+ currif = currif->next;
+ }
+
+ /*
+ * If "new" then create an netif structure and
+ * insert it onto the list.
+ */
+ if (currif == NULL) {
+ CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
+ currif->name = (char *) currif+sizeof(netif);
+ strncpy(currif->name, name, ifnam_size);
+ currif->name[ifnam_size - 1] = '\0';
+ currif->index = getIndex(sock, name);
+ currif->addr = NULL;
+ currif->childs = NULL;
+ currif->virtual = isVirtual;
+ currif->next = ifs;
+ ifs = currif;
+ }
+
+ /*
+ * Finally insert the address on the interface
+ */
+ addrP->next = currif->addr;
+ currif->addr = addrP;
+
+ parent = currif;
+
+ /**
+ * Let's deal with the virtual interface now.
+ */
+ if (vname[0]) {
+ netaddr *tmpaddr;
+
+ currif = parent->childs;
+
+ while (currif != NULL) {
+ if (strcmp(vname, currif->name) == 0) {
+ break;
+ }
+ currif = currif->next;
+ }
+
+ if (currif == NULL) {
+ CHECKED_MALLOC3(currif, netif *, sizeof(netif) + ifnam_size);
+ currif->name = (char *) currif + sizeof(netif);
+ strncpy(currif->name, vname, ifnam_size);
+ currif->name[ifnam_size - 1] = '\0';
+ currif->index = getIndex(sock, vname);
+ currif->addr = NULL;
+ /* Need to duplicate the addr entry? */
+ currif->virtual = 1;
+ currif->childs = NULL;
+ currif->next = parent->childs;
+ parent->childs = currif;
+ }
+
+ CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size);
+ memcpy(tmpaddr, addrP, sizeof(netaddr));
+ if (addrP->addr != NULL) {
+ tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ;
+ memcpy(tmpaddr->addr, addrP->addr, addr_size);
+ }
+
+ if (addrP->brdcast != NULL) {
+ tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size);
+ memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size);
+ }
+
+ tmpaddr->next = currif->addr;
+ currif->addr = tmpaddr;
+ }
+
+ return ifs;
+}
+
+/* Open socket for further ioct calls
+ * proto is AF_INET/AF_INET6
+ */
+static int openSocket(JNIEnv *env, int proto){
+ int sock;
+
+ if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) {
+ /*
+ * If EPROTONOSUPPORT is returned it means we don't have
+ * support for this proto so don't throw an exception.
+ */
+ if (errno != EPROTONOSUPPORT) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed");
+ }
+ return -1;
+ }
+
+ return sock;
+}
+
+
+/** Linux **/
+#ifdef __linux__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ int sock;
+ struct ifreq if2;
+
+ if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (errno == EPROTONOSUPPORT){
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+ }
+ else{ // errno is not NOSUPPORT
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+ return -1;
+ }
+ }
+
+ /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
+ of address of an interface */
+
+ return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ return openSocket(env,AF_INET);
+}
+#endif
+
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ struct ifconf ifc;
+ struct ifreq *ifreqP;
+ char *buf;
+ int numifs;
+ unsigned i;
+
+
+ /* need to do a dummy SIOCGIFCONF to determine the buffer size.
+ * SIOCGIFCOUNT doesn't work
+ */
+ ifc.ifc_buf = NULL;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+ return ifs;
+ }
+
+ CHECKED_MALLOC3(buf,char *, ifc.ifc_len);
+
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed");
+ (void) free(buf);
+ return ifs;
+ }
+
+ /*
+ * Iterate through each interface
+ */
+ ifreqP = ifc.ifc_req;
+ for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) {
+ /*
+ * Add to the list
+ */
+ ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0);
+
+ /*
+ * If an exception occurred then free the list
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ free(buf);
+ freeif(ifs);
+ return NULL;
+ }
+ }
+
+ /*
+ * Free socket and buffer
+ */
+ free(buf);
+ return ifs;
+}
+
+
+/*
+ * Enumerates and returns all IPv6 interfaces on Linux
+ */
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ FILE *f;
+ char addr6[40], devname[21];
+ char addr6p[8][5];
+ int plen, scope, dad_status, if_idx;
+ uint8_t ipv6addr[16];
+
+ if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %08x %02x %02x %02x %20s\n",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+ &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
+
+ struct netif *ifs_ptr = NULL;
+ struct netif *last_ptr = NULL;
+ struct sockaddr_in6 addr;
+
+ sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
+ inet_pton(AF_INET6, addr6, ipv6addr);
+
+ memset(&addr, 0, sizeof(struct sockaddr_in6));
+ memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16);
+
+ addr.sin6_scope_id = if_idx;
+
+ ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen);
+
+
+ /*
+ * If an exception occurred then return the list as is.
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ fclose(f);
+ return ifs;
+ }
+ }
+ fclose(f);
+ }
+ return ifs;
+}
+#endif
+
+
+static int getIndex(int sock, const char *name){
+ /*
+ * Try to get the interface index
+ * (Not supported on Solaris 2.6 or 7)
+ */
+ struct ifreq if2;
+ strcpy(if2.ifr_name, name);
+
+ if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
+ return -1;
+ }
+
+ return if2.ifr_ifindex;
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+ struct sockaddr *ret = NULL;
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ /* Let's make sure the interface does have a broadcast address */
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
+ return ret;
+ }
+
+ if (if2.ifr_flags & IFF_BROADCAST) {
+ /* It does, let's retrieve it*/
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
+ return ret;
+ }
+
+ ret = brdcast_store;
+ memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+ }
+
+ return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+ unsigned int mask;
+ short ret;
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+ return -1;
+ }
+
+ mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
+ ret = 0;
+ while (mask) {
+ mask <<= 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+ static struct ifreq ifr;
+ int i;
+
+ strcpy(ifr.ifr_name, ifname);
+ if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed");
+ return -1;
+ }
+
+ memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+
+ /*
+ * All bytes to 0 means no hardware address.
+ */
+
+ for (i = 0; i < IFHWADDRLEN; i++) {
+ if (buf[i] != 0)
+ return IFHWADDRLEN;
+ }
+
+ return -1;
+}
+
+static int getMTU(JNIEnv *env, int sock, const char *ifname) {
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+ return -1;
+ }
+
+ return if2.ifr_mtu;
+}
+
+static int getFlags(int sock, const char *ifname, int *flags) {
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+ return -1;
+ }
+
+ if (sizeof(if2.ifr_flags) == sizeof(short)) {
+ *flags = (if2.ifr_flags & 0xffff);
+ } else {
+ *flags = if2.ifr_flags;
+ }
+ return 0;
+}
+
+#endif
+
+/** Solaris **/
+#ifdef __solaris__
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ int sock, alreadyV6 = 0;
+ struct lifreq if2;
+
+ if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (errno == EPROTONOSUPPORT){
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+
+ alreadyV6=1;
+ }
+ else{ // errno is not NOSUPPORT
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+ return -1;
+ }
+ }
+
+ /**
+ * Solaris requires that we have IPv6 socket to query an
+ * interface without IPv4 address - check it here
+ * POSIX 1 require the kernell to return ENOTTY if the call is
+ * unappropriate for device e.g. NETMASK for device having IPv6
+ * only address but not all devices follows the standart so
+ * fallback on any error. It's not an ecology friendly but more
+ * reliable.
+ */
+
+ if (! alreadyV6 ){
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+ if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+ close(sock);
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+ }
+ }
+
+ return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ return openSocket(env,AF_INET);
+}
+#endif
+
+/*
+ * Enumerates and returns all IPv4 interfaces
+ * (linux verison)
+ */
+
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ return enumIPvXInterfaces(env,sock, ifs, AF_INET);
+}
+
+#ifdef AF_INET6
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ return enumIPvXInterfaces(env,sock, ifs, AF_INET6);
+}
+#endif
+
+/*
+ Enumerates and returns all interfaces on Solaris
+ use the same code for IPv4 and IPv6
+ */
+static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) {
+ struct lifconf ifc;
+ struct lifreq *ifr;
+ int n;
+ char *buf;
+ struct lifnum numifs;
+ unsigned bufsize;
+
+ /*
+ * Get the interface count
+ */
+ numifs.lifn_family = family;
+ numifs.lifn_flags = 0;
+ if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed");
+ return ifs;
+ }
+
+ /*
+ * Enumerate the interface configurations
+ */
+ bufsize = numifs.lifn_count * sizeof (struct lifreq);
+ CHECKED_MALLOC3(buf, char *, bufsize);
+
+ ifc.lifc_family = family;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = bufsize;
+ ifc.lifc_buf = buf;
+ if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed");
+ free(buf);
+ return ifs;
+ }
+
+ /*
+ * Iterate through each interface
+ */
+ ifr = ifc.lifc_req;
+ for (n=0; n<numifs.lifn_count; n++, ifr++) {
+ int index = -1;
+ struct lifreq if2;
+
+ /*
+ * Ignore either IPv4 or IPv6 addresses
+ */
+ if (ifr->lifr_addr.ss_family != family) {
+ continue;
+ }
+
+#ifdef AF_INET6
+ if (ifr->lifr_addr.ss_family == AF_INET6) {
+ struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr);
+ s6->sin6_scope_id = getIndex(sock, ifr->lifr_name);
+ }
+#endif
+
+ /* add to the list */
+ ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen);
+
+ /*
+ * If an exception occurred we return immediately
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ free(buf);
+ return ifs;
+ }
+
+ }
+
+ free(buf);
+ return ifs;
+}
+
+static int getIndex(int sock, const char *name){
+ /*
+ * Try to get the interface index
+ * (Not supported on Solaris 2.6 or 7)
+ */
+ struct lifreq if2;
+ strcpy(if2.lifr_name, name);
+
+ if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) {
+ return -1;
+ }
+
+ return if2.lifr_index;
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+ struct sockaddr *ret = NULL;
+ struct lifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+
+ /* Let's make sure the interface does have a broadcast address */
+ if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed");
+ return ret;
+ }
+
+ if (if2.lifr_flags & IFF_BROADCAST) {
+ /* It does, let's retrieve it*/
+ if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed");
+ return ret;
+ }
+
+ ret = brdcast_store;
+ memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr));
+ }
+
+ return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+ unsigned int mask;
+ short ret;
+ struct lifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+
+ if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed");
+ return -1;
+ }
+
+ mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr);
+ ret = 0;
+
+ while (mask) {
+ mask <<= 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+
+
+#define DEV_PREFIX "/dev/"
+
+/**
+ * Solaris specific DLPI code to get hardware address from a device.
+ * Unfortunately, at least up to Solaris X, you have to have special
+ * privileges (i.e. be root).
+ */
+static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) {
+ char style1dev[MAXPATHLEN];
+ int fd;
+ dl_phys_addr_req_t dlpareq;
+ dl_phys_addr_ack_t *dlpaack;
+ struct strbuf msg;
+ char buf[128];
+ int flags = 0;
+
+ /**
+ * Device is in /dev
+ * e.g.: /dev/bge0
+ */
+ strcpy(style1dev, DEV_PREFIX);
+ strcat(style1dev, ifname);
+ if ((fd = open(style1dev, O_RDWR)) < 0) {
+ /*
+ * Can't open it. We probably are missing the privilege.
+ * We'll have to try something else
+ */
+ return 0;
+ }
+
+ dlpareq.dl_primitive = DL_PHYS_ADDR_REQ;
+ dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR;
+
+ msg.buf = (char *)&dlpareq;
+ msg.len = DL_PHYS_ADDR_REQ_SIZE;
+
+ if (putmsg(fd, &msg, NULL, 0) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed");
+ return -1;
+ }
+
+ dlpaack = (dl_phys_addr_ack_t *)buf;
+
+ msg.buf = (char *)buf;
+ msg.len = 0;
+ msg.maxlen = sizeof (buf);
+ if (getmsg(fd, &msg, NULL, &flags) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed");
+ return -1;
+ }
+
+ if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n");
+ return -1;
+ }
+
+ memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length);
+ return dlpaack->dl_addr_length;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr, unsigned char *buf) {
+ struct arpreq arpreq;
+ struct sockaddr_in* sin;
+ struct sockaddr_in ipAddr;
+ int len, i;
+ struct lifreq lif;
+
+ /* First, try the new (S11) SIOCGLIFHWADDR ioctl(). If that fails
+ * try the old way.
+ */
+ memset(&lif, 0, sizeof(lif));
+ strlcpy(lif.lifr_name, ifname, sizeof(lif.lifr_name));
+
+ if (ioctl(sock, SIOCGLIFHWADDR, &lif) != -1) {
+ struct sockaddr_dl *sp;
+ sp = (struct sockaddr_dl *)&lif.lifr_addr;
+ memcpy(buf, &sp->sdl_data[0], sp->sdl_alen);
+ return sp->sdl_alen;
+ }
+
+ /**
+ * On Solaris we have to use DLPI, but it will only work if we have
+ * privileged access (i.e. root). If that fails, we try a lookup
+ * in the ARP table, which requires an IPv4 address.
+ */
+ if ((len = getMacFromDevice(env, ifname, buf)) == 0) {
+ /*DLPI failed - trying to do arp lookup*/
+
+ if (addr == NULL) {
+ /**
+ * No IPv4 address for that interface, so can't do an ARP lookup.
+ */
+ return -1;
+ }
+
+ len = 6; //???
+
+ sin = (struct sockaddr_in *) &arpreq.arp_pa;
+ memset((char *) &arpreq, 0, sizeof(struct arpreq));
+ ipAddr.sin_port = 0;
+ ipAddr.sin_family = AF_INET;
+ memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr));
+ memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in));
+ arpreq.arp_flags= ATF_PUBL;
+
+ if (ioctl(sock, SIOCGARP, &arpreq) < 0) {
+ return -1;
+ }
+
+ memcpy(buf, &arpreq.arp_ha.sa_data[0], len );
+ }
+
+ /*
+ * All bytes to 0 means no hardware address.
+ */
+
+ for (i = 0; i < len; i++) {
+ if (buf[i] != 0)
+ return len;
+ }
+
+ return -1;
+}
+
+static int getMTU(JNIEnv *env, int sock, const char *ifname) {
+ struct lifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.lifr_name, ifname);
+
+ if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed");
+ return -1;
+ }
+
+ return if2.lifr_mtu;
+}
+
+
+static int getFlags(int sock, const char *ifname, int *flags) {
+ struct lifreq lifr;
+ memset((caddr_t)&lifr, 0, sizeof(lifr));
+ strcpy((caddr_t)&(lifr.lifr_name), ifname);
+
+ if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) {
+ return -1;
+ }
+
+ *flags = lifr.lifr_flags;
+ return 0;
+}
+
+
+#endif
+
+
+/** BSD **/
+#ifdef _ALLBSD_SOURCE
+/* Open socket for further ioct calls, try v4 socket first and
+ * if it falls return v6 socket
+ */
+
+#ifdef AF_INET6
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ int sock;
+ struct ifreq if2;
+
+ if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ if (errno == EPROTONOSUPPORT){
+ if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed");
+ return -1;
+ }
+ }
+ else{ // errno is not NOSUPPORT
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed");
+ return -1;
+ }
+ }
+
+ return sock;
+}
+
+#else
+static int openSocketWithFallback(JNIEnv *env, const char *ifname){
+ return openSocket(env,AF_INET);
+}
+#endif
+
+/*
+ * Enumerates and returns all IPv4 interfaces
+ */
+static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ struct ifaddrs *ifa, *origifa;
+
+ if (getifaddrs(&origifa) != 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+ "getifaddrs() function failed");
+ return ifs;
+ }
+
+ for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
+
+ /*
+ * Skip non-AF_INET entries.
+ */
+ if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+
+ /*
+ * Add to the list.
+ */
+ ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET, 0);
+
+ /*
+ * If an exception occurred then free the list.
+ */
+ if ((*env)->ExceptionOccurred(env)) {
+ freeifaddrs(origifa);
+ freeif(ifs);
+ return NULL;
+ }
+ }
+
+ /*
+ * Free socket and buffer
+ */
+ freeifaddrs(origifa);
+ return ifs;
+}
+
+
+/*
+ * Enumerates and returns all IPv6 interfaces on Linux
+ */
+
+#ifdef AF_INET6
+/*
+ * Determines the prefix on BSD for IPv6 interfaces.
+ */
+static
+int prefix(void *val, int size) {
+ u_char *name = (u_char *)val;
+ int byte, bit, plen = 0;
+
+ for (byte = 0; byte < size; byte++, plen += 8)
+ if (name[byte] != 0xff)
+ break;
+ if (byte == size)
+ return (plen);
+ for (bit = 7; bit != 0; bit--, plen++)
+ if (!(name[byte] & (1 << bit)))
+ break;
+ for (; bit != 0; bit--)
+ if (name[byte] & (1 << bit))
+ return (0);
+ byte++;
+ for (; byte < size; byte++)
+ if (name[byte])
+ return (0);
+ return (plen);
+}
+
+/*
+ * Enumerates and returns all IPv6 interfaces on BSD
+ */
+static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) {
+ struct ifaddrs *ifa, *origifa;
+ struct sockaddr_in6 *sin6;
+ struct in6_ifreq ifr6;
+
+ if (getifaddrs(&origifa) != 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+ "getifaddrs() function failed");
+ return ifs;
+ }
+
+ for (ifa = origifa; ifa != NULL; ifa = ifa->ifa_next) {
+
+ /*
+ * Skip non-AF_INET6 entries.
+ */
+ if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+
+ memset(&ifr6, 0, sizeof(ifr6));
+ strlcpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name));
+ memcpy(&ifr6.ifr_addr, ifa->ifa_addr, MIN(sizeof(ifr6.ifr_addr), ifa->ifa_addr->sa_len));
+
+ if (ioctl(sock, SIOCGIFNETMASK_IN6, (caddr_t)&ifr6) < 0) {
+ NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException",
+ "ioctl SIOCGIFNETMASK_IN6 failed");
+ freeifaddrs(origifa);
+ freeif(ifs);
+ return NULL;
+ }
+
+ /* Add to the list. */
+ sin6 = (struct sockaddr_in6 *)&ifr6.ifr_addr;
+ ifs = addif(env, sock, ifa->ifa_name, ifs, ifa->ifa_addr, AF_INET6,
+ prefix(&sin6->sin6_addr, sizeof(struct in6_addr)));
+
+ /* If an exception occurred then free the list. */
+ if ((*env)->ExceptionOccurred(env)) {
+ freeifaddrs(origifa);
+ freeif(ifs);
+ return NULL;
+ }
+ }
+
+ /*
+ * Free socket and ifaddrs buffer
+ */
+ freeifaddrs(origifa);
+ return ifs;
+}
+#endif
+
+static int getIndex(int sock, const char *name){
+#ifdef __FreeBSD__
+ /*
+ * Try to get the interface index
+ * (Not supported on Solaris 2.6 or 7)
+ */
+ struct ifreq if2;
+ strcpy(if2.ifr_name, name);
+
+ if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) {
+ return -1;
+ }
+
+ return if2.ifr_index;
+#else
+ /*
+ * Try to get the interface index using BSD specific if_nametoindex
+ */
+ int index = if_nametoindex(name);
+ return (index == 0) ? -1 : index;
+#endif
+}
+
+/**
+ * Returns the IPv4 broadcast address of a named interface, if it exists.
+ * Returns 0 if it doesn't have one.
+ */
+static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) {
+ struct sockaddr *ret = NULL;
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ /* Let's make sure the interface does have a broadcast address */
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed");
+ return ret;
+ }
+
+ if (if2.ifr_flags & IFF_BROADCAST) {
+ /* It does, let's retrieve it*/
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed");
+ return ret;
+ }
+
+ ret = brdcast_store;
+ memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr));
+ }
+
+ return ret;
+}
+
+/**
+ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named
+ * interface, if it has one, otherwise return -1.
+ */
+static short getSubnet(JNIEnv *env, int sock, const char *ifname) {
+ unsigned int mask;
+ short ret;
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed");
+ return -1;
+ }
+
+ mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr);
+ ret = 0;
+ while (mask) {
+ mask <<= 1;
+ ret++;
+ }
+
+ return ret;
+}
+
+/**
+ * Get the Hardware address (usually MAC address) for the named interface.
+ * return puts the data in buf, and returns the length, in byte, of the
+ * MAC address. Returns -1 if there is no hardware address on that interface.
+ */
+static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) {
+ struct ifaddrs *ifa0, *ifa;
+ struct sockaddr *saddr;
+ int i;
+
+ /* Grab the interface list */
+ if (!getifaddrs(&ifa0)) {
+ /* Cycle through the interfaces */
+ for (i = 0, ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next, i++) {
+ saddr = ifa->ifa_addr;
+ /* Link layer contains the MAC address */
+ if (saddr->sa_family == AF_LINK && !strcmp(ifname, ifa->ifa_name)) {
+ struct sockaddr_dl *sadl = (struct sockaddr_dl *) saddr;
+ /* Check the address is the correct length */
+ if (sadl->sdl_alen == ETHER_ADDR_LEN) {
+ memcpy(buf, (sadl->sdl_data + sadl->sdl_nlen), ETHER_ADDR_LEN);
+ freeifaddrs(ifa0);
+ return ETHER_ADDR_LEN;
+ }
+ }
+ }
+ freeifaddrs(ifa0);
+ }
+
+ return -1;
+}
+
+static int getMTU(JNIEnv *env, int sock, const char *ifname) {
+ struct ifreq if2;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed");
+ return -1;
+ }
+
+ return if2.ifr_mtu;
+}
+
+static int getFlags(int sock, const char *ifname, int *flags) {
+ struct ifreq if2;
+ int ret = -1;
+
+ memset((char *) &if2, 0, sizeof(if2));
+ strcpy(if2.ifr_name, ifname);
+
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){
+ return -1;
+ }
+
+ if (sizeof(if2.ifr_flags) == sizeof(short)) {
+ *flags = (if2.ifr_flags & 0xffff);
+ } else {
+ *flags = if2.ifr_flags;
+ }
+ return 0;
+}
+
+#endif
diff --git a/ojluni/src/main/native/ObjectStreamClass.c b/ojluni/src/main/native/ObjectStreamClass.c
new file mode 100755
index 0000000..f9e6c57
--- /dev/null
+++ b/ojluni/src/main/native/ObjectStreamClass.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_io_ObjectStreamClass.h"
+
+static jclass noSuchMethodErrCl;
+
+/*
+ * Class: java_io_ObjectStreamClass
+ * Method: initNative
+ * Signature: ()V
+ *
+ * Native code initialization hook.
+ */
+JNIEXPORT void JNICALL
+Java_java_io_ObjectStreamClass_initNative(JNIEnv *env, jclass this)
+{
+ jclass cl = (*env)->FindClass(env, "java/lang/NoSuchMethodError");
+ if (cl == NULL) { /* exception thrown */
+ return;
+ }
+ noSuchMethodErrCl = (*env)->NewGlobalRef(env, cl);
+}
+
+/*
+ * Class: java_io_ObjectStreamClass
+ * Method: hasStaticInitializer
+ * Signature: (Ljava/lang/Class;)Z
+ *
+ * Returns true if the given class defines a <clinit>()V method; returns false
+ * otherwise.
+ */
+JNIEXPORT jboolean JNICALL
+Java_java_io_ObjectStreamClass_hasStaticInitializer(JNIEnv *env, jclass this,
+ jclass clazz)
+{
+ jclass superCl = NULL;
+ jmethodID superClinitId = NULL;
+ jmethodID clinitId =
+ (*env)->GetStaticMethodID(env, clazz, "<clinit>", "()V");
+ if (clinitId == NULL) { /* error thrown */
+ jthrowable th = (*env)->ExceptionOccurred(env);
+ (*env)->ExceptionClear(env); /* normal return */
+ if (!(*env)->IsInstanceOf(env, th, noSuchMethodErrCl)) {
+ (*env)->Throw(env, th);
+ }
+ return JNI_FALSE;
+ }
+
+ /*
+ * Check superclass for static initializer as well--if the same method ID
+ * is returned, then the static initializer is from a superclass.
+ * Empirically, this step appears to be unnecessary in 1.4; however, the
+ * JNI spec makes no guarantee that GetStaticMethodID will not return the
+ * ID for a superclass initializer.
+ */
+
+ if ((superCl = (*env)->GetSuperclass(env, clazz)) == NULL) {
+ return JNI_TRUE;
+ }
+ superClinitId =
+ (*env)->GetStaticMethodID(env, superCl, "<clinit>", "()V");
+ if (superClinitId == NULL) { /* error thrown */
+ jthrowable th = (*env)->ExceptionOccurred(env);
+ (*env)->ExceptionClear(env); /* normal return */
+ if (!(*env)->IsInstanceOf(env, th, noSuchMethodErrCl)) {
+ (*env)->Throw(env, th);
+ }
+ return JNI_TRUE;
+ }
+
+ return (clinitId != superClinitId);
+}
diff --git a/ojluni/src/main/native/PlainDatagramSocketImpl.c b/ojluni/src/main/native/PlainDatagramSocketImpl.c
new file mode 100755
index 0000000..64f0b7b
--- /dev/null
+++ b/ojluni/src/main/native/PlainDatagramSocketImpl.c
@@ -0,0 +1,2465 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __solaris__
+#include <fcntl.h>
+#endif
+#ifdef __linux__
+#include <unistd.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <netinet/ip.h>
+
+#define IPV6_MULTICAST_IF 17
+#ifndef SO_BSDCOMPAT
+#define SO_BSDCOMPAT 14
+#endif
+#endif
+
+#ifndef IPTOS_TOS_MASK
+#define IPTOS_TOS_MASK 0x1e
+#endif
+#ifndef IPTOS_PREC_MASK
+#define IPTOS_PREC_MASK 0xe0
+#endif
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+#include "java_net_PlainDatagramSocketImpl.h"
+#include "java_net_NetworkInterface.h"
+/************************************************************************
+ * PlainDatagramSocketImpl
+ */
+
+static jfieldID IO_fd_fdID;
+
+static jfieldID pdsi_fdID;
+static jfieldID pdsi_timeoutID;
+static jfieldID pdsi_trafficClassID;
+static jfieldID pdsi_localPortID;
+static jfieldID pdsi_connected;
+static jfieldID pdsi_connectedAddress;
+static jfieldID pdsi_connectedPort;
+
+#ifdef __linux__
+static jboolean isOldKernel;
+#endif
+
+#if defined(__linux__) && defined(AF_INET6)
+static jfieldID pdsi_multicastInterfaceID;
+static jfieldID pdsi_loopbackID;
+static jfieldID pdsi_ttlID;
+#endif
+
+extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
+extern int getDefaultScopeID(JNIEnv *env);
+
+/*
+ * Returns a java.lang.Integer based on 'i'
+ */
+static jobject createInteger(JNIEnv *env, int i) {
+ static jclass i_class;
+ static jmethodID i_ctrID;
+
+ if (i_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/lang/Integer");
+ CHECK_NULL_RETURN(c, NULL);
+ i_ctrID = (*env)->GetMethodID(env, c, "<init>", "(I)V");
+ CHECK_NULL_RETURN(i_ctrID, NULL);
+ i_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(i_class, NULL);
+ }
+
+ return ( (*env)->NewObject(env, i_class, i_ctrID, i) );
+}
+
+/*
+ * Returns a java.lang.Boolean based on 'b'
+ */
+static jobject createBoolean(JNIEnv *env, int b) {
+ static jclass b_class;
+ static jmethodID b_ctrID;
+
+ if (b_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/lang/Boolean");
+ CHECK_NULL_RETURN(c, NULL);
+ b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V");
+ CHECK_NULL_RETURN(b_ctrID, NULL);
+ b_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(b_class, NULL);
+ }
+
+ return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) );
+}
+
+
+/*
+ * Returns the fd for a PlainDatagramSocketImpl or -1
+ * if closed.
+ */
+static int getFD(JNIEnv *env, jobject this) {
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ if (fdObj == NULL) {
+ return -1;
+ }
+ return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+}
+
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
+
+#ifdef __linux__
+ struct utsname sysinfo;
+#endif
+ pdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
+ "Ljava/io/FileDescriptor;");
+ CHECK_NULL(pdsi_fdID);
+ pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
+ CHECK_NULL(pdsi_timeoutID);
+ pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
+ CHECK_NULL(pdsi_trafficClassID);
+ pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I");
+ CHECK_NULL(pdsi_localPortID);
+ pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z");
+ CHECK_NULL(pdsi_connected);
+ pdsi_connectedAddress = (*env)->GetFieldID(env, cls, "connectedAddress",
+ "Ljava/net/InetAddress;");
+ CHECK_NULL(pdsi_connectedAddress);
+ pdsi_connectedPort = (*env)->GetFieldID(env, cls, "connectedPort", "I");
+ CHECK_NULL(pdsi_connectedPort);
+
+ IO_fd_fdID = NET_GetFileDescriptorID(env);
+ CHECK_NULL(IO_fd_fdID);
+
+ Java_java_net_InetAddress_init(env, 0);
+ Java_java_net_Inet4Address_init(env, 0);
+ Java_java_net_Inet6Address_init(env, 0);
+ Java_java_net_NetworkInterface_init(env, 0);
+
+#ifdef __linux__
+ /*
+ * We need to determine if this is a 2.2 kernel.
+ */
+ if (uname(&sysinfo) == 0) {
+ sysinfo.release[3] = '\0';
+ isOldKernel = (strcmp(sysinfo.release, "2.2") == 0);
+ } else {
+ /*
+ * uname failed - move to plan B and examine /proc/version
+ * If this fails assume that /proc has changed and that
+ * this must be new /proc format and hence new kernel.
+ */
+ FILE *fP;
+ isOldKernel = JNI_FALSE;
+ if ((fP = fopen("/proc/version", "r")) != NULL) {
+ char ver[25];
+ if (fgets(ver, sizeof(ver), fP) != NULL) {
+ isOldKernel = (strstr(ver, "2.2.") != NULL);
+ }
+ fclose(fP);
+ }
+ }
+
+#ifdef AF_INET6
+ pdsi_multicastInterfaceID = (*env)->GetFieldID(env, cls, "multicastInterface", "I");
+ CHECK_NULL(pdsi_multicastInterfaceID);
+ pdsi_loopbackID = (*env)->GetFieldID(env, cls, "loopbackMode", "Z");
+ CHECK_NULL(pdsi_loopbackID);
+ pdsi_ttlID = (*env)->GetFieldID(env, cls, "ttl", "I");
+ CHECK_NULL(pdsi_ttlID);
+#endif
+
+#endif
+
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: bind
+ * Signature: (ILjava/net/InetAddress;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
+ jint localport, jobject iaObj) {
+ /* fdObj is the FileDescriptor field on this */
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ /* fd is an int field on fdObj */
+ int fd;
+ int len = 0;
+ SOCKADDR him;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+
+ if (IS_NULL(iaObj)) {
+ JNU_ThrowNullPointerException(env, "iaObj is null.");
+ return;
+ }
+
+ /* bind */
+ if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
+ return;
+ }
+ setDefaultScopeID(env, (struct sockaddr *)&him);
+
+ if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
+ if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
+ errno == EPERM || errno == EACCES) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
+ "Bind failed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Bind failed");
+ }
+ return;
+ }
+
+ /* intialize the local port */
+ if (localport == 0) {
+ /* Now that we're a connected socket, let's extract the port number
+ * that the system chose for us and store it in the Socket object.
+ */
+ if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket name");
+ return;
+ }
+
+ localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
+
+ (*env)->SetIntField(env, this, pdsi_localPortID, localport);
+ } else {
+ (*env)->SetIntField(env, this, pdsi_localPortID, localport);
+ }
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: connect0
+ * Signature: (Ljava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_connect0(JNIEnv *env, jobject this,
+ jobject address, jint port) {
+ /* The object's field */
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ /* The fdObj'fd */
+ jint fd;
+ /* The packetAddress address, family and port */
+ SOCKADDR rmtaddr;
+ int len = 0;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (IS_NULL(address)) {
+ JNU_ThrowNullPointerException(env, "address");
+ return;
+ }
+
+ if (NET_InetAddressToSockaddr(env, address, port, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) {
+ return;
+ }
+
+#ifdef __linux__
+ if (isOldKernel) {
+ int t = 0;
+ setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int));
+ } else
+#endif
+ setDefaultScopeID(env, (struct sockaddr *)&rmtaddr);
+ {
+ if (JVM_Connect(fd, (struct sockaddr *)&rmtaddr, len) == -1) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "Connect failed");
+ return;
+ }
+ }
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: disconnect0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_disconnect0(JNIEnv *env, jobject this, jint family) {
+ /* The object's field */
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ /* The fdObj'fd */
+ jint fd;
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+ SOCKADDR addr;
+ int len;
+#endif
+
+ if (IS_NULL(fdObj)) {
+ return;
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+#ifdef __linux__
+ if (isOldKernel) {
+ int t = 1;
+ setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int));
+ } else {
+#endif /* __linux__ */
+ memset(&addr, 0, sizeof(addr));
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&addr;
+ him6->sin6_family = AF_UNSPEC;
+ len = sizeof(struct sockaddr_in6);
+ } else
+#endif
+ {
+ struct sockaddr_in *him4 = (struct sockaddr_in*)&addr;
+ him4->sin_family = AF_UNSPEC;
+ len = sizeof(struct sockaddr_in);
+ }
+ JVM_Connect(fd, (struct sockaddr *)&addr, len);
+
+#ifdef __linux__
+ // After disconnecting a UDP socket, Linux kernel will set
+ // local port to zero if the port number comes from implicit
+ // bind. Successive send/recv on the same socket will fail.
+ // So bind again with former port number here.
+ int localPort = 0;
+ if (JVM_GetSockName(fd, (struct sockaddr *)&addr, &len) == -1) {
+ return;
+ }
+ localPort = NET_GetPortFromSockaddr((struct sockaddr *)&addr);
+ if (localPort == 0) {
+ localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
+#ifdef AF_INET6
+ if (((struct sockaddr*)&addr)->sa_family == AF_INET6) {
+ ((struct sockaddr_in6*)&addr)->sin6_port = htons(localPort);
+ } else
+#endif /* AF_INET6 */
+ {
+ ((struct sockaddr_in*)&addr)->sin_port = htons(localPort);
+ }
+ NET_Bind(fd, (struct sockaddr *)&addr, len);
+ }
+ }
+#endif
+#else
+ JVM_Connect(fd, 0, 0);
+#endif
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: send
+ * Signature: (Ljava/net/DatagramPacket;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_send(JNIEnv *env, jobject this,
+ jobject packet) {
+
+ char BUF[MAX_BUFFER_LEN];
+ char *fullPacket = NULL;
+ int ret, mallocedPacket = JNI_FALSE;
+ /* The object's field */
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint trafficClass = (*env)->GetIntField(env, this, pdsi_trafficClassID);
+
+ jbyteArray packetBuffer;
+ jobject packetAddress;
+ jint packetBufferOffset, packetBufferLen, packetPort;
+ jboolean connected;
+
+ /* The fdObj'fd */
+ jint fd;
+
+ SOCKADDR rmtaddr, *rmtaddrP=&rmtaddr;
+ int len;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (IS_NULL(packet)) {
+ JNU_ThrowNullPointerException(env, "packet");
+ return;
+ }
+
+ connected = (*env)->GetBooleanField(env, this, pdsi_connected);
+
+ packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID);
+ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
+ if (IS_NULL(packetBuffer) || IS_NULL(packetAddress)) {
+ JNU_ThrowNullPointerException(env, "null buffer || null address");
+ return;
+ }
+
+ packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
+ packetBufferLen = (*env)->GetIntField(env, packet, dp_lengthID);
+
+#ifdef __linux__
+ if (connected && !isOldKernel) {
+#else
+ if (connected) {
+#endif
+ /* arg to NET_Sendto () null in this case */
+ len = 0;
+ rmtaddrP = 0;
+ } else {
+ packetPort = (*env)->GetIntField(env, packet, dp_portID);
+ if (NET_InetAddressToSockaddr(env, packetAddress, packetPort, (struct sockaddr *)&rmtaddr, &len, JNI_TRUE) != 0) {
+ return;
+ }
+ }
+ setDefaultScopeID(env, (struct sockaddr *)&rmtaddr);
+
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+ /* When JNI-ifying the JDK's IO routines, we turned
+ * read's and write's of byte arrays of size greater
+ * than 2048 bytes into several operations of size 2048.
+ * This saves a malloc()/memcpy()/free() for big
+ * buffers. This is OK for file IO and TCP, but that
+ * strategy violates the semantics of a datagram protocol.
+ * (one big send) != (several smaller sends). So here
+ * we *must* alloc the buffer. Note it needn't be bigger
+ * than 65,536 (0xFFFF) the max size of an IP packet.
+ * Anything bigger should be truncated anyway.
+ *
+ * We may want to use a smarter allocation scheme at some
+ * point.
+ */
+ if (packetBufferLen > MAX_PACKET_LEN) {
+ packetBufferLen = MAX_PACKET_LEN;
+ }
+ fullPacket = (char *)malloc(packetBufferLen);
+
+ if (!fullPacket) {
+ JNU_ThrowOutOfMemoryError(env, "Send buffer native heap allocation failed");
+ return;
+ } else {
+ mallocedPacket = JNI_TRUE;
+ }
+ } else {
+ fullPacket = &(BUF[0]);
+ }
+
+ (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
+ (jbyte *)fullPacket);
+#ifdef AF_INET6
+ if (trafficClass != 0 && ipv6_available()) {
+ NET_SetTrafficClass((struct sockaddr *)&rmtaddr, trafficClass);
+ }
+#endif /* AF_INET6 */
+
+
+ /*
+ * Send the datagram.
+ *
+ * If we are connected it's possible that sendto will return
+ * ECONNREFUSED indicating that an ICMP port unreachable has
+ * received.
+ */
+ ret = NET_SendTo(fd, fullPacket, packetBufferLen, 0,
+ (struct sockaddr *)rmtaddrP, len);
+
+ if (ret < 0) {
+ switch (ret) {
+ case JVM_IO_ERR :
+ if (errno == ECONNREFUSED) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
+ "ICMP Port Unreachable");
+ } else {
+ NET_ThrowByNameWithLastError(env, "java/io/IOException", "sendto failed");
+ }
+ break;
+
+ case JVM_IO_INTR:
+ JNU_ThrowByName(env, "java/io/InterruptedIOException",
+ "operation interrupted");
+ break;
+ }
+ }
+
+ if (mallocedPacket) {
+ free(fullPacket);
+ }
+ return;
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: peek
+ * Signature: (Ljava/net/InetAddress;)I
+ */
+JNIEXPORT jint JNICALL
+Java_java_net_PlainDatagramSocketImpl_peek(JNIEnv *env, jobject this,
+ jobject addressObj) {
+
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID);
+ jint fd;
+ ssize_t n;
+ SOCKADDR remote_addr;
+ int len;
+ char buf[1];
+ jint family;
+ jobject iaObj;
+ int port;
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ return -1;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (IS_NULL(addressObj)) {
+ JNU_ThrowNullPointerException(env, "Null address in peek()");
+ }
+ if (timeout) {
+ int ret = NET_Timeout(fd, timeout);
+ if (ret == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Peek timed out");
+ return ret;
+ } else if (ret == JVM_IO_ERR) {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");
+ }
+ return ret;
+ } else if (ret == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ return ret; /* WARNING: SHOULD WE REALLY RETURN -2??? */
+ }
+ }
+
+ len = SOCKADDR_LEN;
+ n = NET_RecvFrom(fd, buf, 1, MSG_PEEK,
+ (struct sockaddr *)&remote_addr, &len);
+
+ if (n == JVM_IO_ERR) {
+
+#ifdef __solaris__
+ if (errno == ECONNREFUSED) {
+ int orig_errno = errno;
+ (void) recv(fd, buf, 1, 0);
+ errno = orig_errno;
+ }
+#endif
+ if (errno == ECONNREFUSED) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
+ "ICMP Port Unreachable");
+ } else {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Peek failed");
+ }
+ }
+ return 0;
+ } else if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
+ return 0;
+ }
+
+ iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
+#ifdef AF_INET6
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+#else
+ family = AF_INET;
+#endif
+ if (family == AF_INET) { /* this api can't handle IPV6 addresses */
+ int address = getInetAddress_addr(env, iaObj);
+ setInetAddress_addr(env, addressObj, address);
+ }
+ return port;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_net_PlainDatagramSocketImpl_peekData(JNIEnv *env, jobject this,
+ jobject packet) {
+
+ char BUF[MAX_BUFFER_LEN];
+ char *fullPacket = NULL;
+ int mallocedPacket = JNI_FALSE;
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID);
+
+ jbyteArray packetBuffer;
+ jint packetBufferOffset, packetBufferLen;
+
+ int fd;
+
+ int n;
+ SOCKADDR remote_addr;
+ int len;
+ int port;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ }
+
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (IS_NULL(packet)) {
+ JNU_ThrowNullPointerException(env, "packet");
+ return -1;
+ }
+
+ packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID);
+ if (IS_NULL(packetBuffer)) {
+ JNU_ThrowNullPointerException(env, "packet buffer");
+ return -1;
+ }
+ packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
+ packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID);
+ if (timeout) {
+ int ret = NET_Timeout(fd, timeout);
+ if (ret == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Receive timed out");
+ return -1;
+ } else if (ret == JVM_IO_ERR) {
+#ifdef __linux__
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+ }
+#else
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+#endif
+ return -1;
+ } else if (ret == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ return -1;
+ }
+ }
+
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+
+ /* When JNI-ifying the JDK's IO routines, we turned
+ * read's and write's of byte arrays of size greater
+ * than 2048 bytes into several operations of size 2048.
+ * This saves a malloc()/memcpy()/free() for big
+ * buffers. This is OK for file IO and TCP, but that
+ * strategy violates the semantics of a datagram protocol.
+ * (one big send) != (several smaller sends). So here
+ * we *must* alloc the buffer. Note it needn't be bigger
+ * than 65,536 (0xFFFF) the max size of an IP packet.
+ * anything bigger is truncated anyway.
+ *
+ * We may want to use a smarter allocation scheme at some
+ * point.
+ */
+ if (packetBufferLen > MAX_PACKET_LEN) {
+ packetBufferLen = MAX_PACKET_LEN;
+ }
+ fullPacket = (char *)malloc(packetBufferLen);
+
+ if (!fullPacket) {
+ JNU_ThrowOutOfMemoryError(env, "Peek buffer native heap allocation failed");
+ return -1;
+ } else {
+ mallocedPacket = JNI_TRUE;
+ }
+ } else {
+ fullPacket = &(BUF[0]);
+ }
+
+ len = SOCKADDR_LEN;
+ n = NET_RecvFrom(fd, fullPacket, packetBufferLen, MSG_PEEK,
+ (struct sockaddr *)&remote_addr, &len);
+ /* truncate the data if the packet's length is too small */
+ if (n > packetBufferLen) {
+ n = packetBufferLen;
+ }
+ if (n == JVM_IO_ERR) {
+
+#ifdef __solaris__
+ if (errno == ECONNREFUSED) {
+ int orig_errno = errno;
+ (void) recv(fd, fullPacket, 1, 0);
+ errno = orig_errno;
+ }
+#endif
+ (*env)->SetIntField(env, packet, dp_offsetID, 0);
+ (*env)->SetIntField(env, packet, dp_lengthID, 0);
+ if (errno == ECONNREFUSED) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
+ "ICMP Port Unreachable");
+ } else {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+ }
+ }
+ } else if (n == JVM_IO_INTR) {
+ (*env)->SetIntField(env, packet, dp_offsetID, 0);
+ (*env)->SetIntField(env, packet, dp_lengthID, 0);
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ } else {
+ /*
+ * success - fill in received address...
+ *
+ * REMIND: Fill in an int on the packet, and create inetadd
+ * object in Java, as a performance improvement. Also
+ * construct the inetadd object lazily.
+ */
+
+ jobject packetAddress;
+
+ /*
+ * Check if there is an InetAddress already associated with this
+ * packet. If so we check if it is the same source address. We
+ * can't update any existing InetAddress because it is immutable
+ */
+ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
+ if (packetAddress != NULL) {
+ if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) {
+ /* force a new InetAddress to be created */
+ packetAddress = NULL;
+ }
+ }
+ if (packetAddress == NULL) {
+ packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
+ /* stuff the new Inetaddress in the packet */
+ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
+ } else {
+ /* only get the new port number */
+ port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr);
+ }
+ /* and fill in the data, remote address/port and such */
+ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
+ (jbyte *)fullPacket);
+ (*env)->SetIntField(env, packet, dp_portID, port);
+ (*env)->SetIntField(env, packet, dp_lengthID, n);
+ }
+
+ if (mallocedPacket) {
+ free(fullPacket);
+ }
+ return port;
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: receive
+ * Signature: (Ljava/net/DatagramPacket;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_receive0(JNIEnv *env, jobject this,
+ jobject packet) {
+
+ char BUF[MAX_BUFFER_LEN];
+ char *fullPacket = NULL;
+ int mallocedPacket = JNI_FALSE;
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint timeout = (*env)->GetIntField(env, this, pdsi_timeoutID);
+
+ jbyteArray packetBuffer;
+ jint packetBufferOffset, packetBufferLen;
+
+ int fd;
+
+ int n;
+ SOCKADDR remote_addr;
+ int len;
+ jboolean retry;
+#ifdef __linux__
+ jboolean connected = JNI_FALSE;
+ jobject connectedAddress = NULL;
+ jint connectedPort = 0;
+ jlong prevTime = 0;
+#endif
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (IS_NULL(packet)) {
+ JNU_ThrowNullPointerException(env, "packet");
+ return;
+ }
+
+ packetBuffer = (*env)->GetObjectField(env, packet, dp_bufID);
+ if (IS_NULL(packetBuffer)) {
+ JNU_ThrowNullPointerException(env, "packet buffer");
+ return;
+ }
+ packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
+ packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID);
+
+ if (packetBufferLen > MAX_BUFFER_LEN) {
+
+ /* When JNI-ifying the JDK's IO routines, we turned
+ * read's and write's of byte arrays of size greater
+ * than 2048 bytes into several operations of size 2048.
+ * This saves a malloc()/memcpy()/free() for big
+ * buffers. This is OK for file IO and TCP, but that
+ * strategy violates the semantics of a datagram protocol.
+ * (one big send) != (several smaller sends). So here
+ * we *must* alloc the buffer. Note it needn't be bigger
+ * than 65,536 (0xFFFF) the max size of an IP packet.
+ * anything bigger is truncated anyway.
+ *
+ * We may want to use a smarter allocation scheme at some
+ * point.
+ */
+ if (packetBufferLen > MAX_PACKET_LEN) {
+ packetBufferLen = MAX_PACKET_LEN;
+ }
+ fullPacket = (char *)malloc(packetBufferLen);
+
+ if (!fullPacket) {
+ JNU_ThrowOutOfMemoryError(env, "Receive buffer native heap allocation failed");
+ return;
+ } else {
+ mallocedPacket = JNI_TRUE;
+ }
+ } else {
+ fullPacket = &(BUF[0]);
+ }
+
+#ifdef __linux__
+ /*
+ * On Linux with the 2.2 kernel we simulate connected datagrams by
+ * discarding packets
+ */
+ if (isOldKernel) {
+ connected = (*env)->GetBooleanField(env, this, pdsi_connected);
+ if (connected) {
+ connectedAddress = (*env)->GetObjectField(env, this, pdsi_connectedAddress);
+ connectedPort = (*env)->GetIntField(env, this, pdsi_connectedPort);
+
+ if (timeout) {
+ prevTime = JVM_CurrentTimeMillis(env, 0);
+ }
+ }
+ }
+#endif
+
+ do {
+ retry = JNI_FALSE;
+
+ if (timeout) {
+ int ret = NET_Timeout(fd, timeout);
+ if (ret <= 0) {
+ if (ret == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Receive timed out");
+ } else if (ret == JVM_IO_ERR) {
+#ifdef __linux__
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+ }
+#else
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+#endif
+ } else if (ret == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ }
+
+ if (mallocedPacket) {
+ free(fullPacket);
+ }
+
+ return;
+ }
+ }
+
+ /*
+ * Security Note: For Linux 2.2 with connected datagrams ensure that
+ * you receive into the stack/heap allocated buffer - do not attempt
+ * to receive directly into DatagramPacket's byte array.
+ * (ie: if the virtual machine support pinning don't use
+ * GetByteArrayElements or a JNI critical section and receive
+ * directly into the byte array)
+ */
+ len = SOCKADDR_LEN;
+ n = NET_RecvFrom(fd, fullPacket, packetBufferLen, 0,
+ (struct sockaddr *)&remote_addr, &len);
+ /* truncate the data if the packet's length is too small */
+ if (n > packetBufferLen) {
+ n = packetBufferLen;
+ }
+ if (n == JVM_IO_ERR) {
+ (*env)->SetIntField(env, packet, dp_offsetID, 0);
+ (*env)->SetIntField(env, packet, dp_lengthID, 0);
+ if (errno == ECONNREFUSED) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "PortUnreachableException",
+ "ICMP Port Unreachable");
+ } else {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Receive failed");
+ }
+ }
+ } else if (n == JVM_IO_INTR) {
+ (*env)->SetIntField(env, packet, dp_offsetID, 0);
+ (*env)->SetIntField(env, packet, dp_lengthID, 0);
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ } else {
+ int port;
+ jobject packetAddress;
+
+ /*
+ * If we are connected then we know that the datagram that we have
+ * received is from the address that we are connected too. However
+ * on Linux with 2.2 kernel we have to simulate this behaviour by
+ * discarding any datagrams that aren't from the connected address.
+ */
+#ifdef __linux__
+ if (isOldKernel && connected) {
+
+ if (NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr) != connectedPort ||
+ !NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, connectedAddress)) {
+
+ /*
+ * Discard the datagram as it's not from the connected
+ * address
+ */
+ retry = JNI_TRUE;
+
+ /*
+ * Adjust timeout if necessary to ensure that we adhere to
+ * timeout semantics.
+ */
+ if (timeout) {
+ jlong newTime = JVM_CurrentTimeMillis(env, 0);
+ timeout -= (newTime - prevTime);
+ if (timeout <= 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Receive timed out");
+ if (mallocedPacket) {
+ free(fullPacket);
+ }
+ return;
+ }
+ prevTime = newTime;
+ }
+
+ continue;
+ }
+ }
+#endif
+
+ /*
+ * success - fill in received address...
+ *
+ * REMIND: Fill in an int on the packet, and create inetadd
+ * object in Java, as a performance improvement. Also
+ * construct the inetadd object lazily.
+ */
+
+ /*
+ * Check if there is an InetAddress already associated with this
+ * packet. If so we check if it is the same source address. We
+ * can't update any existing InetAddress because it is immutable
+ */
+ packetAddress = (*env)->GetObjectField(env, packet, dp_addressID);
+ if (packetAddress != NULL) {
+ if (!NET_SockaddrEqualsInetAddress(env, (struct sockaddr *)&remote_addr, packetAddress)) {
+ /* force a new InetAddress to be created */
+ packetAddress = NULL;
+ }
+ }
+ if (packetAddress == NULL) {
+ packetAddress = NET_SockaddrToInetAddress(env, (struct sockaddr *)&remote_addr, &port);
+ /* stuff the new Inetaddress in the packet */
+ (*env)->SetObjectField(env, packet, dp_addressID, packetAddress);
+ } else {
+ /* only get the new port number */
+ port = NET_GetPortFromSockaddr((struct sockaddr *)&remote_addr);
+ }
+ /* and fill in the data, remote address/port and such */
+ (*env)->SetByteArrayRegion(env, packetBuffer, packetBufferOffset, n,
+ (jbyte *)fullPacket);
+ (*env)->SetIntField(env, packet, dp_portID, port);
+ (*env)->SetIntField(env, packet, dp_lengthID, n);
+ }
+
+ } while (retry);
+
+ if (mallocedPacket) {
+ free(fullPacket);
+ }
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: datagramSocketCreate
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
+ jobject this) {
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ int arg, fd, t = 1;
+#ifdef AF_INET6
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+ int domain = AF_INET;
+#endif
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+
+ if ((fd = JVM_Socket(domain, SOCK_DGRAM, 0)) == JVM_IO_ERR) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error creating socket");
+ return;
+ }
+
+#ifdef AF_INET6
+ /* Disable IPV6_V6ONLY to ensure dual-socket support */
+ if (domain == AF_INET6) {
+ arg = 0;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+ sizeof(int)) < 0) {
+ NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+ close(fd);
+ return;
+ }
+ }
+#endif /* AF_INET6 */
+
+#ifdef __APPLE__
+ arg = 65507;
+ if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_SNDBUF,
+ (char *)&arg, sizeof(arg)) < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ strerror(errno));
+ return;
+ }
+ if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_RCVBUF,
+ (char *)&arg, sizeof(arg)) < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ strerror(errno));
+ return;
+ }
+#endif /* __APPLE__ */
+
+ setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
+
+#ifdef __linux__
+ if (isOldKernel) {
+ setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, (char*) &t, sizeof(int));
+ }
+
+#ifdef AF_INET6
+ /*
+ * On Linux for IPv6 sockets we must set the hop limit
+ * to 1 to be compatible with default ttl of 1 for IPv4 sockets.
+ */
+ if (domain == AF_INET6) {
+ int ttl = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
+ sizeof(ttl));
+
+ if (isOldKernel) {
+ (*env)->SetIntField(env, this, pdsi_ttlID, ttl);
+ }
+ }
+#endif
+
+#endif /* __linux__ */
+
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: datagramSocketClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_datagramSocketClose(JNIEnv *env,
+ jobject this) {
+ /*
+ * REMIND: PUT A LOCK AROUND THIS CODE
+ */
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ int fd;
+
+ if (IS_NULL(fdObj)) {
+ return;
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ if (fd == -1) {
+ return;
+ }
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+ NET_SocketClose(fd);
+}
+
+
+/*
+ * Set outgoing multicast interface designated by a NetworkInterface.
+ * Throw exception if failed.
+ */
+static void mcast_set_if_by_if_v4(JNIEnv *env, jobject this, int fd, jobject value) {
+ static jfieldID ni_addrsID;
+ struct in_addr in;
+ jobjectArray addrArray;
+ jsize len;
+ jobject addr;
+ int i;
+
+ if (ni_addrsID == NULL ) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
+ "[Ljava/net/InetAddress;");
+ CHECK_NULL(ni_addrsID);
+ }
+
+ addrArray = (*env)->GetObjectField(env, value, ni_addrsID);
+ len = (*env)->GetArrayLength(env, addrArray);
+
+ /*
+ * Check that there is at least one address bound to this
+ * interface.
+ */
+ if (len < 1) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface");
+ return;
+ }
+
+ /*
+ * We need an ipv4 address here
+ */
+ for (i = 0; i < len; i++) {
+ addr = (*env)->GetObjectArrayElement(env, addrArray, i);
+ if (getInetAddress_family(env, addr) == IPv4) {
+ in.s_addr = htonl(getInetAddress_addr(env, addr));
+ break;
+ }
+ }
+
+ if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (const char*)&in, sizeof(in)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+}
+
+/*
+ * Set outgoing multicast interface designated by a NetworkInterface.
+ * Throw exception if failed.
+ */
+#ifdef AF_INET6
+static void mcast_set_if_by_if_v6(JNIEnv *env, jobject this, int fd, jobject value) {
+ static jfieldID ni_indexID;
+ int index;
+
+ if (ni_indexID == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
+ CHECK_NULL(ni_indexID);
+ }
+ index = (*env)->GetIntField(env, value, ni_indexID);
+
+ if (JVM_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (const char*)&index, sizeof(index)) < 0) {
+ if (errno == EINVAL && index > 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "IPV6_MULTICAST_IF failed (interface has IPv4 "
+ "address only?)");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+ return;
+ }
+
+#ifdef __linux__
+ /*
+ * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socket
+ * option so record index for later retrival.
+ */
+ if (isOldKernel) {
+ (*env)->SetIntField(env, this, pdsi_multicastInterfaceID,
+ (jint)index);
+ }
+#endif
+}
+#endif /* AF_INET6 */
+
+/*
+ * Set outgoing multicast interface designated by an InetAddress.
+ * Throw exception if failed.
+ */
+static void mcast_set_if_by_addr_v4(JNIEnv *env, jobject this, int fd, jobject value) {
+ struct in_addr in;
+
+ in.s_addr = htonl( getInetAddress_addr(env, value) );
+
+ if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (const char*)&in, sizeof(in)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+}
+
+/*
+ * Set outgoing multicast interface designated by an InetAddress.
+ * Throw exception if failed.
+ */
+#ifdef AF_INET6
+static void mcast_set_if_by_addr_v6(JNIEnv *env, jobject this, int fd, jobject value) {
+ static jclass ni_class;
+ if (ni_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ ni_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(ni_class);
+ }
+
+ value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value);
+ if (value == NULL) {
+ if (!(*env)->ExceptionOccurred(env)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "bad argument for IP_MULTICAST_IF"
+ ": address not bound to any interface");
+ }
+ return;
+ }
+
+ mcast_set_if_by_if_v6(env, this, fd, value);
+}
+#endif
+
+/*
+ * Sets the multicast interface.
+ *
+ * SocketOptions.IP_MULTICAST_IF :-
+ * value is a InetAddress
+ * IPv4: set outgoing multicast interface using
+ * IPPROTO_IP/IP_MULTICAST_IF
+ * IPv6: Get the index of the interface to which the
+ * InetAddress is bound
+ * Set outgoing multicast interface using
+ * IPPROTO_IPV6/IPV6_MULTICAST_IF
+ * On Linux 2.2 record interface index as can't
+ * query the multicast interface.
+ *
+ * SockOptions.IF_MULTICAST_IF2 :-
+ * value is a NetworkInterface
+ * IPv4: Obtain IP address bound to network interface
+ * (NetworkInterface.addres[0])
+ * set outgoing multicast interface using
+ * IPPROTO_IP/IP_MULTICAST_IF
+ * IPv6: Obtain NetworkInterface.index
+ * Set outgoing multicast interface using
+ * IPPROTO_IPV6/IPV6_MULTICAST_IF
+ * On Linux 2.2 record interface index as can't
+ * query the multicast interface.
+ *
+ */
+static void setMulticastInterface(JNIEnv *env, jobject this, int fd,
+ jint opt, jobject value)
+{
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
+ /*
+ * value is an InetAddress.
+ */
+#ifdef AF_INET6
+#ifdef __linux__
+ mcast_set_if_by_addr_v4(env, this, fd, value);
+ if (ipv6_available()) {
+ mcast_set_if_by_addr_v6(env, this, fd, value);
+ }
+#else /* __linux__ not defined */
+ if (ipv6_available()) {
+ mcast_set_if_by_addr_v6(env, this, fd, value);
+ } else {
+ mcast_set_if_by_addr_v4(env, this, fd, value);
+ }
+#endif /* __linux__ */
+#else
+ mcast_set_if_by_addr_v4(env, this, fd, value);
+#endif /* AF_INET6 */
+ }
+
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
+ /*
+ * value is a NetworkInterface.
+ */
+#ifdef AF_INET6
+#ifdef __linux__
+ mcast_set_if_by_if_v4(env, this, fd, value);
+ if (ipv6_available()) {
+ mcast_set_if_by_if_v6(env, this, fd, value);
+ }
+#else /* __linux__ not defined */
+ if (ipv6_available()) {
+ mcast_set_if_by_if_v6(env, this, fd, value);
+ } else {
+ mcast_set_if_by_if_v4(env, this, fd, value);
+ }
+#endif /* __linux__ */
+#else
+ mcast_set_if_by_if_v4(env, this, fd, value);
+#endif /* AF_INET6 */
+ }
+}
+
+/*
+ * Enable/disable local loopback of multicast datagrams.
+ */
+static void mcast_set_loop_v4(JNIEnv *env, jobject this, int fd, jobject value) {
+ jclass cls;
+ jfieldID fid;
+ jboolean on;
+ char loopback;
+
+ cls = (*env)->FindClass(env, "java/lang/Boolean");
+ CHECK_NULL(cls);
+ fid = (*env)->GetFieldID(env, cls, "value", "Z");
+ CHECK_NULL(fid);
+
+ on = (*env)->GetBooleanField(env, value, fid);
+ loopback = (!on ? 1 : 0);
+
+ if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const void *)&loopback, sizeof(char)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+ return;
+ }
+}
+
+/*
+ * Enable/disable local loopback of multicast datagrams.
+ */
+#ifdef AF_INET6
+static void mcast_set_loop_v6(JNIEnv *env, jobject this, int fd, jobject value) {
+ jclass cls;
+ jfieldID fid;
+ jboolean on;
+ int loopback;
+
+ cls = (*env)->FindClass(env, "java/lang/Boolean");
+ CHECK_NULL(cls);
+ fid = (*env)->GetFieldID(env, cls, "value", "Z");
+ CHECK_NULL(fid);
+
+ on = (*env)->GetBooleanField(env, value, fid);
+ loopback = (!on ? 1 : 0);
+
+ if (NET_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const void *)&loopback, sizeof(int)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+ return;
+ }
+
+#ifdef __linux__
+ /*
+ * Can't query IPV6_MULTICAST_LOOP on Linux 2.2 kernel so
+ * store it in impl so that we can simulate getsockopt.
+ */
+ if (isOldKernel) {
+ (*env)->SetBooleanField(env, this, pdsi_loopbackID, on);
+ }
+#endif
+}
+#endif /* AF_INET6 */
+
+/*
+ * Sets the multicast loopback mode.
+ */
+static void setMulticastLoopbackMode(JNIEnv *env, jobject this, int fd,
+ jint opt, jobject value) {
+#ifdef AF_INET6
+#ifdef __linux__
+ mcast_set_loop_v4(env, this, fd, value);
+ if (ipv6_available()) {
+ mcast_set_loop_v6(env, this, fd, value);
+ }
+#else /* __linux__ not defined */
+ if (ipv6_available()) {
+ mcast_set_loop_v6(env, this, fd, value);
+ } else {
+ mcast_set_loop_v4(env, this, fd, value);
+ }
+#endif /* __linux__ */
+#else
+ mcast_set_loop_v4(env, this, fd, value);
+#endif /* AF_INET6 */
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: socketSetOption
+ * Signature: (ILjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_socketSetOption(JNIEnv *env,
+ jobject this,
+ jint opt,
+ jobject value) {
+ int fd;
+ int level, optname, optlen;
+ union {
+ int i;
+ char c;
+ } optval;
+
+ /*
+ * Check that socket hasn't been closed
+ */
+ fd = getFD(env, this);
+ if (fd < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+
+ /*
+ * Check argument has been provided
+ */
+ if (IS_NULL(value)) {
+ JNU_ThrowNullPointerException(env, "value argument");
+ return;
+ }
+
+ /*
+ * Setting the multicast interface handled seperately
+ */
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
+ opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
+
+ setMulticastInterface(env, this, fd, opt, value);
+ return;
+ }
+
+ /*
+ * Setting the multicast loopback mode handled separately
+ */
+ if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) {
+ setMulticastLoopbackMode(env, this, fd, opt, value);
+ return;
+ }
+
+ /*
+ * Map the Java level socket option to the platform specific
+ * level and option name.
+ */
+ if (NET_MapSocketOption(opt, &level, &optname)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ return;
+ }
+
+ switch (opt) {
+ case java_net_SocketOptions_SO_SNDBUF :
+ case java_net_SocketOptions_SO_RCVBUF :
+ case java_net_SocketOptions_IP_TOS :
+ {
+ jclass cls;
+ jfieldID fid;
+
+ cls = (*env)->FindClass(env, "java/lang/Integer");
+ CHECK_NULL(cls);
+ fid = (*env)->GetFieldID(env, cls, "value", "I");
+ CHECK_NULL(fid);
+
+ optval.i = (*env)->GetIntField(env, value, fid);
+ optlen = sizeof(optval.i);
+ break;
+ }
+
+ case java_net_SocketOptions_SO_REUSEADDR:
+ case java_net_SocketOptions_SO_BROADCAST:
+ {
+ jclass cls;
+ jfieldID fid;
+ jboolean on;
+
+ cls = (*env)->FindClass(env, "java/lang/Boolean");
+ CHECK_NULL(cls);
+ fid = (*env)->GetFieldID(env, cls, "value", "Z");
+ CHECK_NULL(fid);
+
+ on = (*env)->GetBooleanField(env, value, fid);
+
+ /* SO_REUSEADDR or SO_BROADCAST */
+ optval.i = (on ? 1 : 0);
+ optlen = sizeof(optval.i);
+
+ break;
+ }
+
+ default :
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket option not supported by PlainDatagramSocketImp");
+ break;
+
+ }
+
+ if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
+ return;
+ }
+}
+
+
+/*
+ * Return the multicast interface:
+ *
+ * SocketOptions.IP_MULTICAST_IF
+ * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF
+ * Create InetAddress
+ * IP_MULTICAST_IF returns struct ip_mreqn on 2.2
+ * kernel but struct in_addr on 2.4 kernel
+ * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or
+ * obtain from impl is Linux 2.2 kernel
+ * If index == 0 return InetAddress representing
+ * anyLocalAddress.
+ * If index > 0 query NetworkInterface by index
+ * and returns addrs[0]
+ *
+ * SocketOptions.IP_MULTICAST_IF2
+ * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF
+ * Query NetworkInterface by IP address and
+ * return the NetworkInterface that the address
+ * is bound too.
+ * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF
+ * (except Linux .2 kernel)
+ * Query NetworkInterface by index and
+ * return NetworkInterface.
+ */
+jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) {
+ jboolean isIPV4 = JNI_TRUE;
+
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ isIPV4 = JNI_FALSE;
+ }
+#endif
+
+ /*
+ * IPv4 implementation
+ */
+ if (isIPV4) {
+ static jclass inet4_class;
+ static jmethodID inet4_ctrID;
+
+ static jclass ni_class;
+ static jmethodID ni_ctrID;
+ static jfieldID ni_indexID;
+ static jfieldID ni_addrsID;
+
+ jobjectArray addrArray;
+ jobject addr;
+ jobject ni;
+
+ struct in_addr in;
+ struct in_addr *inP = ∈
+ int len = sizeof(struct in_addr);
+
+#ifdef __linux__
+ struct ip_mreqn mreqn;
+ if (isOldKernel) {
+ inP = (struct in_addr *)&mreqn;
+ len = sizeof(struct ip_mreqn);
+ }
+#endif
+
+ if (JVM_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF,
+ (char *)inP, &len) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return NULL;
+ }
+
+ /*
+ * Construct and populate an Inet4Address
+ */
+ if (inet4_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL_RETURN(c, NULL);
+ inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
+ CHECK_NULL_RETURN(inet4_ctrID, NULL);
+ inet4_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(inet4_class, NULL);
+ }
+ addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0);
+ CHECK_NULL_RETURN(addr, NULL);
+
+#ifdef __linux__
+ setInetAddress_addr(env, addr, (isOldKernel ?
+ ntohl(mreqn.imr_address.s_addr) : ntohl(in.s_addr)));
+#else
+ setInetAddress_addr(env, addr, ntohl(in.s_addr));
+#endif
+
+ /*
+ * For IP_MULTICAST_IF return InetAddress
+ */
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
+ return addr;
+ }
+
+ /*
+ * For IP_MULTICAST_IF2 we get the NetworkInterface for
+ * this address and return it
+ */
+ if (ni_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL_RETURN(c, NULL);
+ ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
+ CHECK_NULL_RETURN(ni_ctrID, NULL);
+ ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
+ CHECK_NULL_RETURN(ni_indexID, NULL);
+ ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
+ "[Ljava/net/InetAddress;");
+ CHECK_NULL_RETURN(ni_addrsID, NULL);
+ ni_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(ni_class, NULL);
+ }
+ ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
+ if (ni) {
+ return ni;
+ }
+
+ /*
+ * The address doesn't appear to be bound at any known
+ * NetworkInterface. Therefore we construct a NetworkInterface
+ * with this address.
+ */
+ ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
+ CHECK_NULL_RETURN(ni, NULL);
+
+ (*env)->SetIntField(env, ni, ni_indexID, -1);
+ addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL);
+ CHECK_NULL_RETURN(addrArray, NULL);
+ (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
+ (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
+ return ni;
+ }
+
+
+#ifdef AF_INET6
+ /*
+ * IPv6 implementation
+ */
+ if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) ||
+ (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) {
+
+ static jclass ni_class;
+ static jmethodID ni_ctrID;
+ static jfieldID ni_indexID;
+ static jfieldID ni_addrsID;
+ static jclass ia_class;
+ static jmethodID ia_anyLocalAddressID;
+
+ int index;
+ int len = sizeof(index);
+
+ jobjectArray addrArray;
+ jobject addr;
+ jobject ni;
+
+#ifdef __linux__
+ /*
+ * Linux 2.2 kernel doesn't support IPV6_MULTICAST_IF socke option
+ * so use cached index.
+ */
+ if (isOldKernel) {
+ index = (*env)->GetIntField(env, this, pdsi_multicastInterfaceID);
+ } else
+#endif
+ {
+ if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (char*)&index, &len) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return NULL;
+ }
+ }
+
+ if (ni_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL_RETURN(c, NULL);
+ ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V");
+ CHECK_NULL_RETURN(ni_ctrID, NULL);
+ ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
+ CHECK_NULL_RETURN(ni_indexID, NULL);
+ ni_addrsID = (*env)->GetFieldID(env, c, "addrs",
+ "[Ljava/net/InetAddress;");
+ CHECK_NULL_RETURN(ni_addrsID, NULL);
+
+ ia_class = (*env)->FindClass(env, "java/net/InetAddress");
+ CHECK_NULL_RETURN(ia_class, NULL);
+ ia_class = (*env)->NewGlobalRef(env, ia_class);
+ CHECK_NULL_RETURN(ia_class, NULL);
+ ia_anyLocalAddressID = (*env)->GetStaticMethodID(env,
+ ia_class,
+ "anyLocalAddress",
+ "()Ljava/net/InetAddress;");
+ CHECK_NULL_RETURN(ia_anyLocalAddressID, NULL);
+ ni_class = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(ni_class, NULL);
+ }
+
+ /*
+ * If multicast to a specific interface then return the
+ * interface (for IF2) or the any address on that interface
+ * (for IF).
+ */
+ if (index > 0) {
+ ni = Java_java_net_NetworkInterface_getByIndex0(env, ni_class,
+ index);
+ if (ni == NULL) {
+ char errmsg[255];
+ sprintf(errmsg,
+ "IPV6_MULTICAST_IF returned index to unrecognized interface: %d",
+ index);
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", errmsg);
+ return NULL;
+ }
+
+ /*
+ * For IP_MULTICAST_IF2 return the NetworkInterface
+ */
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
+ return ni;
+ }
+
+ /*
+ * For IP_MULTICAST_IF return addrs[0]
+ */
+ addrArray = (*env)->GetObjectField(env, ni, ni_addrsID);
+ if ((*env)->GetArrayLength(env, addrArray) < 1) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "IPV6_MULTICAST_IF returned interface without IP bindings");
+ return NULL;
+ }
+
+ addr = (*env)->GetObjectArrayElement(env, addrArray, 0);
+ return addr;
+ }
+
+ /*
+ * Multicast to any address - return anyLocalAddress
+ * or a NetworkInterface with addrs[0] set to anyLocalAddress
+ */
+
+ addr = (*env)->CallStaticObjectMethod(env, ia_class, ia_anyLocalAddressID,
+ NULL);
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF) {
+ return addr;
+ }
+
+ ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0);
+ CHECK_NULL_RETURN(ni, NULL);
+ (*env)->SetIntField(env, ni, ni_indexID, -1);
+ addrArray = (*env)->NewObjectArray(env, 1, ia_class, NULL);
+ CHECK_NULL_RETURN(addrArray, NULL);
+ (*env)->SetObjectArrayElement(env, addrArray, 0, addr);
+ (*env)->SetObjectField(env, ni, ni_addrsID, addrArray);
+ return ni;
+ }
+#endif
+ return NULL;
+}
+
+
+
+/*
+ * Returns relevant info as a jint.
+ *
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: socketGetOption
+ * Signature: (I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL
+Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this,
+ jint opt) {
+ int fd;
+ int level, optname, optlen;
+ union {
+ int i;
+ char c;
+ } optval;
+
+ fd = getFD(env, this);
+ if (fd < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "socket closed");
+ return NULL;
+ }
+
+ /*
+ * Handle IP_MULTICAST_IF seperately
+ */
+ if (opt == java_net_SocketOptions_IP_MULTICAST_IF ||
+ opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
+ return getMulticastInterface(env, this, fd, opt);
+
+ }
+
+ /*
+ * SO_BINDADDR implemented using getsockname
+ */
+ if (opt == java_net_SocketOptions_SO_BINDADDR) {
+ /* find out local IP address */
+ SOCKADDR him;
+ socklen_t len = 0;
+ int port;
+ jobject iaObj;
+
+ len = SOCKADDR_LEN;
+
+ if (getsockname(fd, (struct sockaddr *)&him, &len) == -1) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket name");
+ return NULL;
+ }
+ iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
+
+ return iaObj;
+ }
+
+ /*
+ * Map the Java level socket option to the platform specific
+ * level and option name.
+ */
+ if (NET_MapSocketOption(opt, &level, &optname)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ return NULL;
+ }
+
+ /*
+ * IP_MULTICAST_LOOP socket option isn't available on Linux 2.2
+ * kernel with IPv6 so return value stored in impl.
+ */
+#if defined(AF_INET6) && defined(__linux__)
+ if (isOldKernel && opt == java_net_SocketOptions_IP_MULTICAST_LOOP &&
+ level == IPPROTO_IPV6) {
+ int mode = (int)(*env)->GetBooleanField(env, this, pdsi_loopbackID);
+ return createBoolean(env, mode);
+ }
+#endif
+
+ if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP &&
+ level == IPPROTO_IP) {
+ optlen = sizeof(optval.c);
+ } else {
+ optlen = sizeof(optval.i);
+ }
+
+ if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return NULL;
+ }
+
+ switch (opt) {
+ case java_net_SocketOptions_IP_MULTICAST_LOOP:
+ /* getLoopbackMode() returns true if IP_MULTICAST_LOOP disabled */
+ if (level == IPPROTO_IP) {
+ return createBoolean(env, (int)!optval.c);
+ } else {
+ return createBoolean(env, !optval.i);
+ }
+
+ case java_net_SocketOptions_SO_BROADCAST:
+ case java_net_SocketOptions_SO_REUSEADDR:
+ return createBoolean(env, optval.i);
+
+ case java_net_SocketOptions_SO_SNDBUF:
+ case java_net_SocketOptions_SO_RCVBUF:
+ case java_net_SocketOptions_IP_TOS:
+ return createInteger(env, optval.i);
+
+ }
+
+ /* should never rearch here */
+ return NULL;
+}
+
+/*
+ * Multicast-related calls
+ */
+
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_setTTL(JNIEnv *env, jobject this,
+ jbyte ttl) {
+ jint ittl = ttl;
+ if (ittl < 0) {
+ ittl += 0x100;
+ }
+ Java_java_net_PlainDatagramSocketImpl_setTimeToLive(env, this, ittl);
+}
+
+/*
+ * Set TTL for a socket. Throw exception if failed.
+ */
+static void setTTL(JNIEnv *env, int fd, jint ttl) {
+ char ittl = (char)ttl;
+ if (JVM_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ittl,
+ sizeof(ittl)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+}
+
+/*
+ * Set hops limit for a socket. Throw exception if failed.
+ */
+#ifdef AF_INET6
+static void setHopLimit(JNIEnv *env, int fd, jint ttl) {
+ int ittl = (int)ttl;
+ if (JVM_SetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (char*)&ittl, sizeof(ittl)) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+}
+#endif
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: setTTL
+ * Signature: (B)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_setTimeToLive(JNIEnv *env, jobject this,
+ jint ttl) {
+
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ int fd;
+ /* it is important to cast this to a char, otherwise setsockopt gets confused */
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ /* setsockopt to be correct ttl */
+#ifdef AF_INET6
+#ifdef __linux__
+ setTTL(env, fd, ttl);
+ if (ipv6_available()) {
+ setHopLimit(env, fd, ttl);
+ if (isOldKernel) {
+ (*env)->SetIntField(env, this, pdsi_ttlID, ttl);
+ }
+ }
+#else /* __linux__ not defined */
+ if (ipv6_available()) {
+ setHopLimit(env, fd, ttl);
+ } else {
+ setTTL(env, fd, ttl);
+ }
+#endif /* __linux__ */
+#else
+ setTTL(env, fd, ttl);
+#endif /* AF_INET6 */
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: getTTL
+ * Signature: ()B
+ */
+JNIEXPORT jbyte JNICALL
+Java_java_net_PlainDatagramSocketImpl_getTTL(JNIEnv *env, jobject this) {
+ return (jbyte)Java_java_net_PlainDatagramSocketImpl_getTimeToLive(env, this);
+}
+
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: getTTL
+ * Signature: ()B
+ */
+JNIEXPORT jint JNICALL
+Java_java_net_PlainDatagramSocketImpl_getTimeToLive(JNIEnv *env, jobject this) {
+
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint fd = -1;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ /* getsockopt of ttl */
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ int ttl = 0;
+ int len = sizeof(ttl);
+
+#ifdef __linux__
+ /*
+ * Linux 2.2 kernel doesn't support IPV6_MULTICAST_HOPS socket option
+ */
+ if (isOldKernel) {
+ return (*env)->GetIntField(env, this, pdsi_ttlID);
+ }
+#endif
+
+ if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (char*)&ttl, &len) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return -1;
+ }
+ return (jint)ttl;
+ } else
+#endif /* AF_INET6 */
+ {
+ u_char ttl = 0;
+ int len = sizeof(ttl);
+ if (JVM_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
+ (char*)&ttl, &len) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return -1;
+ }
+ return (jint)ttl;
+ }
+}
+
+
+/*
+ * mcast_join_leave: Join or leave a multicast group.
+ *
+ * For IPv4 sockets use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option
+ * to join/leave multicast group.
+ *
+ * For IPv6 sockets use IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP socket option
+ * to join/leave multicast group. If multicast group is an IPv4 address then
+ * an IPv4-mapped address is used.
+ *
+ * On Linux with IPv6 if we wish to join/leave an IPv4 multicast group then
+ * we must use the IPv4 socket options. This is because the IPv6 socket options
+ * don't support IPv4-mapped addresses. This is true as per 2.2.19 and 2.4.7
+ * kernel releases. In the future it's possible that IP_ADD_MEMBERSHIP
+ * will be updated to return ENOPROTOOPT if uses with an IPv6 socket (Solaris
+ * already does this). Thus to cater for this we first try with the IPv4
+ * socket options and if they fail we use the IPv6 socket options. This
+ * seems a reasonable failsafe solution.
+ */
+static void mcast_join_leave(JNIEnv *env, jobject this,
+ jobject iaObj, jobject niObj,
+ jboolean join) {
+
+ jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
+ jint fd;
+ jint ipv6_join_leave;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (IS_NULL(iaObj)) {
+ JNU_ThrowNullPointerException(env, "iaObj");
+ return;
+ }
+
+ /*
+ * Determine if this is an IPv4 or IPv6 join/leave.
+ */
+#ifdef AF_INET6
+ ipv6_join_leave = ipv6_available();
+
+#ifdef __linux__
+ if (getInetAddress_family(env, iaObj) == IPv4) {
+ ipv6_join_leave = JNI_FALSE;
+ }
+#endif
+
+#else
+ /*
+ * IPv6 not compiled in
+ */
+ ipv6_join_leave = JNI_FALSE;
+#endif
+
+ /*
+ * For IPv4 join use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option
+ *
+ * On Linux if IPv4 or IPv6 use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP
+ */
+ if (!ipv6_join_leave) {
+#ifdef __linux__
+ struct ip_mreqn mname;
+#else
+ struct ip_mreq mname;
+#endif
+ int mname_len;
+
+ /*
+ * joinGroup(InetAddress, NetworkInterface) implementation :-
+ *
+ * Linux/IPv6: use ip_mreqn structure populated with multicast
+ * address and interface index.
+ *
+ * IPv4: use ip_mreq structure populated with multicast
+ * address and first address obtained from
+ * NetworkInterface
+ */
+ if (niObj != NULL) {
+#if defined(__linux__) && defined(AF_INET6)
+ if (ipv6_available()) {
+ static jfieldID ni_indexID;
+
+ if (ni_indexID == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ ni_indexID = (*env)->GetFieldID(env, c, "index", "I");
+ CHECK_NULL(ni_indexID);
+ }
+
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
+ mname.imr_address.s_addr = 0;
+ mname.imr_ifindex = (*env)->GetIntField(env, niObj, ni_indexID);
+ mname_len = sizeof(struct ip_mreqn);
+ } else
+#endif
+ {
+ jobjectArray addrArray = (*env)->GetObjectField(env, niObj, ni_addrsID);
+ jobject addr;
+
+ if ((*env)->GetArrayLength(env, addrArray) < 1) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "bad argument for IP_ADD_MEMBERSHIP: "
+ "No IP addresses bound to interface");
+ return;
+ }
+ addr = (*env)->GetObjectArrayElement(env, addrArray, 0);
+
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
+#ifdef __linux__
+ mname.imr_address.s_addr = htonl(getInetAddress_addr(env, addr));
+#else
+ mname.imr_interface.s_addr = htonl(getInetAddress_addr(env, addr));
+#endif
+ mname_len = sizeof(struct ip_mreq);
+ }
+ }
+
+
+ /*
+ * joinGroup(InetAddress) implementation :-
+ *
+ * Linux/IPv6: use ip_mreqn structure populated with multicast
+ * address and interface index. index obtained
+ * from cached value or IPV6_MULTICAST_IF.
+ *
+ * IPv4: use ip_mreq structure populated with multicast
+ * address and local address obtained from
+ * IP_MULTICAST_IF. On Linux IP_MULTICAST_IF
+ * returns different structure depending on
+ * kernel.
+ */
+
+ if (niObj == NULL) {
+
+#if defined(__linux__) && defined(AF_INET6)
+ if (ipv6_available()) {
+
+ int index;
+ int len = sizeof(index);
+
+ if (isOldKernel) {
+ index = (*env)->GetIntField(env, this, pdsi_multicastInterfaceID);
+ } else {
+ if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (char*)&index, &len) < 0) {
+ NET_ThrowCurrent(env, "getsockopt IPV6_MULTICAST_IF failed");
+ return;
+ }
+ }
+
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
+ mname.imr_address.s_addr = 0 ;
+ mname.imr_ifindex = index;
+ mname_len = sizeof(struct ip_mreqn);
+ } else
+#endif
+ {
+ struct in_addr in;
+ struct in_addr *inP = ∈
+ socklen_t len = sizeof(struct in_addr);
+
+#ifdef __linux__
+ struct ip_mreqn mreqn;
+ if (isOldKernel) {
+ inP = (struct in_addr *)&mreqn;
+ len = sizeof(struct ip_mreqn);
+ }
+#endif
+ if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (char *)inP, &len) < 0) {
+ NET_ThrowCurrent(env, "getsockopt IP_MULTICAST_IF failed");
+ return;
+ }
+
+#ifdef __linux__
+ mname.imr_address.s_addr =
+ (isOldKernel ? mreqn.imr_address.s_addr : in.s_addr);
+
+#else
+ mname.imr_interface.s_addr = in.s_addr;
+#endif
+ mname.imr_multiaddr.s_addr = htonl(getInetAddress_addr(env, iaObj));
+ mname_len = sizeof(struct ip_mreq);
+ }
+ }
+
+
+ /*
+ * Join the multicast group.
+ */
+ if (JVM_SetSockOpt(fd, IPPROTO_IP, (join ? IP_ADD_MEMBERSHIP:IP_DROP_MEMBERSHIP),
+ (char *) &mname, mname_len) < 0) {
+
+ /*
+ * If IP_ADD_MEMBERSHIP returns ENOPROTOOPT on Linux and we've got
+ * IPv6 enabled then it's possible that the kernel has been fixed
+ * so we switch to IPV6_ADD_MEMBERSHIP socket option.
+ * As of 2.4.7 kernel IPV6_ADD_MEMERSHIP can't handle IPv4-mapped
+ * addresses so we have to use IP_ADD_MEMERSHIP for IPv4 multicast
+ * groups. However if the socket is an IPv6 socket then then setsockopt
+ * should reurn ENOPROTOOPT. We assume this will be fixed in Linux
+ * at some stage.
+ */
+#if defined(__linux__) && defined(AF_INET6)
+ if (errno == ENOPROTOOPT) {
+ if (ipv6_available()) {
+ ipv6_join_leave = JNI_TRUE;
+ errno = 0;
+ } else {
+ errno = ENOPROTOOPT; /* errno can be changed by ipv6_available */
+ }
+ }
+#endif
+ if (errno) {
+ if (join) {
+ NET_ThrowCurrent(env, "setsockopt IP_ADD_MEMBERSHIP failed");
+ } else {
+ if (errno == ENOENT)
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Not a member of the multicast group");
+ else
+ NET_ThrowCurrent(env, "setsockopt IP_DROP_MEMBERSHIP failed");
+ }
+ }
+ }
+
+ /*
+ * If we haven't switched to IPv6 socket option then we're done.
+ */
+ if (!ipv6_join_leave) {
+ return;
+ }
+ }
+
+
+ /*
+ * IPv6 join. If it's an IPv4 multicast group then we use an IPv4-mapped
+ * address.
+ */
+#ifdef AF_INET6
+ {
+ struct ipv6_mreq mname6;
+ jbyteArray ipaddress;
+ jbyte caddr[16];
+ jint family;
+ jint address;
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ if (family == AF_INET) { /* will convert to IPv4-mapped address */
+ memset((char *) caddr, 0, 16);
+ address = getInetAddress_addr(env, iaObj);
+
+ caddr[10] = 0xff;
+ caddr[11] = 0xff;
+
+ caddr[12] = ((address >> 24) & 0xff);
+ caddr[13] = ((address >> 16) & 0xff);
+ caddr[14] = ((address >> 8) & 0xff);
+ caddr[15] = (address & 0xff);
+ } else {
+ ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
+ (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+ }
+
+ memcpy((void *)&(mname6.ipv6mr_multiaddr), caddr, sizeof(struct in6_addr));
+ if (IS_NULL(niObj)) {
+ int index;
+ int len = sizeof(index);
+
+#ifdef __linux__
+ /*
+ * 2.2 kernel doens't support IPV6_MULTICAST_IF socket option
+ */
+ if (isOldKernel) {
+ index = (*env)->GetIntField(env, this, pdsi_multicastInterfaceID);
+ } else
+#endif
+ {
+ if (JVM_GetSockOpt(fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ (char*)&index, &len) < 0) {
+ NET_ThrowCurrent(env, "getsockopt IPV6_MULTICAST_IF failed");
+ return;
+ }
+ }
+
+#ifdef __linux__
+ /*
+ * On 2.4.8+ if we join a group with the interface set to 0
+ * then the kernel records the interface it decides. This causes
+ * subsequent leave groups to fail as there is no match. Thus we
+ * pick the interface if there is a matching route.
+ */
+ if (index == 0 && !isOldKernel) {
+ int rt_index = getDefaultIPv6Interface(&(mname6.ipv6mr_multiaddr));
+ if (rt_index > 0) {
+ index = rt_index;
+ }
+ }
+#endif
+#ifdef MACOSX
+ if (family == AF_INET6 && index == 0) {
+ index = getDefaultScopeID(env);
+ }
+#endif
+ mname6.ipv6mr_interface = index;
+ } else {
+ jint idx = (*env)->GetIntField(env, niObj, ni_indexID);
+ mname6.ipv6mr_interface = idx;
+ }
+
+#if defined(_ALLBSD_SOURCE)
+#define ADD_MEMBERSHIP IPV6_JOIN_GROUP
+#define DRP_MEMBERSHIP IPV6_LEAVE_GROUP
+#define S_ADD_MEMBERSHIP "IPV6_JOIN_GROUP"
+#define S_DRP_MEMBERSHIP "IPV6_LEAVE_GROUP"
+#else
+#define ADD_MEMBERSHIP IPV6_ADD_MEMBERSHIP
+#define DRP_MEMBERSHIP IPV6_DROP_MEMBERSHIP
+#define S_ADD_MEMBERSHIP "IPV6_ADD_MEMBERSHIP"
+#define S_DRP_MEMBERSHIP "IPV6_DROP_MEMBERSHIP"
+#endif
+
+ /* Join the multicast group */
+ if (JVM_SetSockOpt(fd, IPPROTO_IPV6, (join ? ADD_MEMBERSHIP : DRP_MEMBERSHIP),
+ (char *) &mname6, sizeof (mname6)) < 0) {
+
+ if (join) {
+ NET_ThrowCurrent(env, "setsockopt " S_ADD_MEMBERSHIP " failed");
+ } else {
+ if (errno == ENOENT) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Not a member of the multicast group");
+ } else {
+ NET_ThrowCurrent(env, "setsockopt " S_DRP_MEMBERSHIP " failed");
+ }
+ }
+ }
+ }
+#endif
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: join
+ * Signature: (Ljava/net/InetAddress;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_join(JNIEnv *env, jobject this,
+ jobject iaObj, jobject niObj)
+{
+ mcast_join_leave(env, this, iaObj, niObj, JNI_TRUE);
+}
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: leave
+ * Signature: (Ljava/net/InetAddress;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainDatagramSocketImpl_leave(JNIEnv *env, jobject this,
+ jobject iaObj, jobject niObj)
+{
+ mcast_join_leave(env, this, iaObj, niObj, JNI_FALSE);
+}
diff --git a/ojluni/src/main/native/PlainSocketImpl.c b/ojluni/src/main/native/PlainSocketImpl.c
new file mode 100755
index 0000000..82616f2
--- /dev/null
+++ b/ojluni/src/main/native/PlainSocketImpl.c
@@ -0,0 +1,1110 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if defined(__linux__) && !defined(USE_SELECT)
+#include <sys/poll.h>
+#endif
+#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
+#include <netinet/in.h>
+#ifdef __linux__
+#include <netinet/ip.h>
+#endif
+#include <netdb.h>
+#include <stdlib.h>
+
+#ifdef __solaris__
+#include <fcntl.h>
+#endif
+#ifdef __linux__
+#include <unistd.h>
+#include <sys/sysctl.h>
+#endif
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+#include "java_net_PlainSocketImpl.h"
+
+/************************************************************************
+ * PlainSocketImpl
+ */
+
+static jfieldID IO_fd_fdID;
+
+jfieldID psi_fdID;
+jfieldID psi_addressID;
+jfieldID psi_ipaddressID;
+jfieldID psi_portID;
+jfieldID psi_localportID;
+jfieldID psi_timeoutID;
+jfieldID psi_trafficClassID;
+jfieldID psi_serverSocketID;
+jfieldID psi_fdLockID;
+jfieldID psi_closePendingID;
+
+extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
+
+/*
+ * file descriptor used for dup2
+ */
+static int marker_fd = -1;
+
+
+#define SET_NONBLOCKING(fd) { \
+ int flags = fcntl(fd, F_GETFL); \
+ flags |= O_NONBLOCK; \
+ fcntl(fd, F_SETFL, flags); \
+}
+
+#define SET_BLOCKING(fd) { \
+ int flags = fcntl(fd, F_GETFL); \
+ flags &= ~O_NONBLOCK; \
+ fcntl(fd, F_SETFL, flags); \
+}
+
+/*
+ * Create the marker file descriptor by establishing a loopback connection
+ * which we shutdown but do not close the fd. The result is an fd that
+ * can be used for read/write.
+ */
+static int getMarkerFD()
+{
+ int sv[2];
+
+#ifdef AF_UNIX
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+ return -1;
+ }
+#else
+ return -1;
+#endif
+
+ /*
+ * Finally shutdown sv[0] (any reads to this fd will get
+ * EOF; any writes will get an error).
+ */
+ JVM_SocketShutdown(sv[0], 2);
+ JVM_SocketClose(sv[1]);
+
+ return sv[0];
+}
+
+/*
+ * Return the file descriptor given a PlainSocketImpl
+ */
+static int getFD(JNIEnv *env, jobject this) {
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ CHECK_NULL_RETURN(fdObj, -1);
+ return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+}
+
+/*
+ * The initroto function is called whenever PlainSocketImpl is
+ * loaded, to cache fieldIds for efficiency. This is called everytime
+ * the Java class is loaded.
+ *
+ * Class: java_net_PlainSocketImpl
+ * Method: initProto
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_initProto(JNIEnv *env, jclass cls) {
+ psi_fdID = (*env)->GetFieldID(env, cls , "fd",
+ "Ljava/io/FileDescriptor;");
+ CHECK_NULL(psi_fdID);
+ psi_addressID = (*env)->GetFieldID(env, cls, "address",
+ "Ljava/net/InetAddress;");
+ CHECK_NULL(psi_addressID);
+ psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
+ CHECK_NULL(psi_portID);
+ psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
+ CHECK_NULL(psi_localportID);
+ psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
+ CHECK_NULL(psi_timeoutID);
+ psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
+ CHECK_NULL(psi_trafficClassID);
+ psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
+ "Ljava/net/ServerSocket;");
+ CHECK_NULL(psi_serverSocketID);
+ psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
+ "Ljava/lang/Object;");
+ CHECK_NULL(psi_fdLockID);
+ psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
+ CHECK_NULL(psi_closePendingID);
+ IO_fd_fdID = NET_GetFileDescriptorID(env);
+ CHECK_NULL(IO_fd_fdID);
+
+ /* Create the marker fd used for dup2 */
+ marker_fd = getMarkerFD();
+}
+
+/* a global reference to the java.net.SocketException class. In
+ * socketCreate, we ensure that this is initialized. This is to
+ * prevent the problem where socketCreate runs out of file
+ * descriptors, and is then unable to load the exception class.
+ */
+static jclass socketExceptionCls;
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketCreate
+ * Signature: (Z)V */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
+ jboolean stream) {
+ jobject fdObj, ssObj;
+ int fd;
+ int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+#ifdef AF_INET6
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+ int domain = AF_INET;
+#endif
+
+ if (socketExceptionCls == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/SocketException");
+ CHECK_NULL(c);
+ socketExceptionCls = (jclass)(*env)->NewGlobalRef(env, c);
+ CHECK_NULL(socketExceptionCls);
+ }
+ fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+
+ if (fdObj == NULL) {
+ (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
+ return;
+ }
+
+ if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
+ /* note: if you run out of fds, you may not be able to load
+ * the exception class, and get a NoClassDefFoundError
+ * instead.
+ */
+ NET_ThrowNew(env, errno, "can't create socket");
+ return;
+ }
+
+#ifdef AF_INET6
+ /* Disable IPV6_V6ONLY to ensure dual-socket support */
+ if (domain == AF_INET6) {
+ int arg = 0;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+ sizeof(int)) < 0) {
+ NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+ close(fd);
+ return;
+ }
+ }
+#endif /* AF_INET6 */
+
+ /*
+ * If this is a server socket then enable SO_REUSEADDR
+ * automatically and set to non blocking.
+ */
+ ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
+ if (ssObj != NULL) {
+ int arg = 1;
+ SET_NONBLOCKING(fd);
+ if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+ sizeof(arg)) < 0) {
+ NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
+ close(fd);
+ return;
+ }
+ }
+
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
+}
+
+/*
+ * inetAddress is the address object passed to the socket connect
+ * call.
+ *
+ * Class: java_net_PlainSocketImpl
+ * Method: socketConnect
+ * Signature: (Ljava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketConnect(JNIEnv *env, jobject this,
+ jobject iaObj, jint port,
+ jint timeout)
+{
+ jint localport = (*env)->GetIntField(env, this, psi_localportID);
+ int len = 0;
+
+ /* fdObj is the FileDescriptor field on this */
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+
+ jclass clazz = (*env)->GetObjectClass(env, this);
+
+ jobject fdLock;
+
+ jint trafficClass = (*env)->GetIntField(env, this, psi_trafficClassID);
+
+ /* fd is an int field on iaObj */
+ jint fd;
+
+ SOCKADDR him;
+ /* The result of the connection */
+ int connect_rv = -1;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (IS_NULL(iaObj)) {
+ JNU_ThrowNullPointerException(env, "inet address argument null.");
+ return;
+ }
+
+ /* connect */
+ if (NET_InetAddressToSockaddr(env, iaObj, port, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
+ return;
+ }
+ setDefaultScopeID(env, (struct sockaddr *)&him);
+
+#ifdef AF_INET6
+ if (trafficClass != 0 && ipv6_available()) {
+ NET_SetTrafficClass((struct sockaddr *)&him, trafficClass);
+ }
+#endif /* AF_INET6 */
+ if (timeout <= 0) {
+ connect_rv = NET_Connect(fd, (struct sockaddr *)&him, len);
+#ifdef __solaris__
+ if (connect_rv == JVM_IO_ERR && errno == EINPROGRESS ) {
+
+ /* This can happen if a blocking connect is interrupted by a signal.
+ * See 6343810.
+ */
+ while (1) {
+#ifndef USE_SELECT
+ {
+ struct pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLOUT;
+
+ connect_rv = NET_Poll(&pfd, 1, -1);
+ }
+#else
+ {
+ fd_set wr, ex;
+
+ FD_ZERO(&wr);
+ FD_SET(fd, &wr);
+ FD_ZERO(&ex);
+ FD_SET(fd, &ex);
+
+ connect_rv = NET_Select(fd+1, 0, &wr, &ex, 0);
+ }
+#endif
+
+ if (connect_rv == JVM_IO_ERR) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ if (connect_rv > 0) {
+ int optlen;
+ /* has connection been established */
+ optlen = sizeof(connect_rv);
+ if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
+ (void*)&connect_rv, &optlen) <0) {
+ connect_rv = errno;
+ }
+
+ if (connect_rv != 0) {
+ /* restore errno */
+ errno = connect_rv;
+ connect_rv = JVM_IO_ERR;
+ }
+ break;
+ }
+ }
+ }
+#endif
+ } else {
+ /*
+ * A timeout was specified. We put the socket into non-blocking
+ * mode, connect, and then wait for the connection to be
+ * established, fail, or timeout.
+ */
+ SET_NONBLOCKING(fd);
+
+ /* no need to use NET_Connect as non-blocking */
+ connect_rv = connect(fd, (struct sockaddr *)&him, len);
+
+ /* connection not established immediately */
+ if (connect_rv != 0) {
+ int optlen;
+ jlong prevTime = JVM_CurrentTimeMillis(env, 0);
+
+ if (errno != EINPROGRESS) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "connect failed");
+ SET_BLOCKING(fd);
+ return;
+ }
+
+ /*
+ * Wait for the connection to be established or a
+ * timeout occurs. poll/select needs to handle EINTR in
+ * case lwp sig handler redirects any process signals to
+ * this thread.
+ */
+ while (1) {
+ jlong newTime;
+#ifndef USE_SELECT
+ {
+ struct pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLOUT;
+
+ errno = 0;
+ connect_rv = NET_Poll(&pfd, 1, timeout);
+ }
+#else
+ {
+ fd_set wr, ex;
+ struct timeval t;
+
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+
+ FD_ZERO(&wr);
+ FD_SET(fd, &wr);
+ FD_ZERO(&ex);
+ FD_SET(fd, &ex);
+
+ errno = 0;
+ connect_rv = NET_Select(fd+1, 0, &wr, &ex, &t);
+ }
+#endif
+
+ if (connect_rv >= 0) {
+ break;
+ }
+ if (errno != EINTR) {
+ break;
+ }
+
+ /*
+ * The poll was interrupted so adjust timeout and
+ * restart
+ */
+ newTime = JVM_CurrentTimeMillis(env, 0);
+ timeout -= (newTime - prevTime);
+ if (timeout <= 0) {
+ connect_rv = 0;
+ break;
+ }
+ prevTime = newTime;
+
+ } /* while */
+
+ if (connect_rv == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "connect timed out");
+
+ /*
+ * Timeout out but connection may still be established.
+ * At the high level it should be closed immediately but
+ * just in case we make the socket blocking again and
+ * shutdown input & output.
+ */
+ SET_BLOCKING(fd);
+ JVM_SocketShutdown(fd, 2);
+ return;
+ }
+
+ /* has connection been established */
+ optlen = sizeof(connect_rv);
+ if (JVM_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, (void*)&connect_rv,
+ &optlen) <0) {
+ connect_rv = errno;
+ }
+ }
+
+ /* make socket blocking again */
+ SET_BLOCKING(fd);
+
+ /* restore errno */
+ if (connect_rv != 0) {
+ errno = connect_rv;
+ connect_rv = JVM_IO_ERR;
+ }
+ }
+
+ /* report the appropriate exception */
+ if (connect_rv < 0) {
+
+#ifdef __linux__
+ /*
+ * Linux/GNU distribution setup /etc/hosts so that
+ * InetAddress.getLocalHost gets back the loopback address
+ * rather than the host address. Thus a socket can be
+ * bound to the loopback address and the connect will
+ * fail with EADDRNOTAVAIL. In addition the Linux kernel
+ * returns the wrong error in this case - it returns EINVAL
+ * instead of EADDRNOTAVAIL. We handle this here so that
+ * a more descriptive exception text is used.
+ */
+ if (connect_rv == JVM_IO_ERR && errno == EINVAL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Invalid argument or cannot assign requested address");
+ return;
+ }
+#endif
+ if (connect_rv == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+#if defined(EPROTO)
+ } else if (errno == EPROTO) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ProtocolException",
+ "Protocol error");
+#endif
+ } else if (errno == ECONNREFUSED) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "Connection refused");
+ } else if (errno == ETIMEDOUT) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
+ "Connection timed out");
+ } else if (errno == EHOSTUNREACH) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
+ "Host unreachable");
+ } else if (errno == EADDRNOTAVAIL) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "NoRouteToHostException",
+ "Address not available");
+ } else if ((errno == EISCONN) || (errno == EBADF)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "connect failed");
+ }
+ return;
+ }
+
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
+
+ /* set the remote peer address and port */
+ (*env)->SetObjectField(env, this, psi_addressID, iaObj);
+ (*env)->SetIntField(env, this, psi_portID, port);
+
+ /*
+ * we need to initialize the local port field if bind was called
+ * previously to the connect (by the client) then localport field
+ * will already be initialized
+ */
+ if (localport == 0) {
+ /* Now that we're a connected socket, let's extract the port number
+ * that the system chose for us and store it in the Socket object.
+ */
+ len = SOCKADDR_LEN;
+ if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket name");
+ } else {
+ localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
+ (*env)->SetIntField(env, this, psi_localportID, localport);
+ }
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketBind
+ * Signature: (Ljava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,
+ jobject iaObj, jint localport) {
+
+ /* fdObj is the FileDescriptor field on this */
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ /* fd is an int field on fdObj */
+ int fd;
+ int len;
+ SOCKADDR him;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (IS_NULL(iaObj)) {
+ JNU_ThrowNullPointerException(env, "iaObj is null.");
+ return;
+ }
+
+ /* bind */
+ if (NET_InetAddressToSockaddr(env, iaObj, localport, (struct sockaddr *)&him, &len, JNI_TRUE) != 0) {
+ return;
+ }
+ setDefaultScopeID(env, (struct sockaddr *)&him);
+
+ if (NET_Bind(fd, (struct sockaddr *)&him, len) < 0) {
+ if (errno == EADDRINUSE || errno == EADDRNOTAVAIL ||
+ errno == EPERM || errno == EACCES) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "BindException",
+ "Bind failed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Bind failed");
+ }
+ return;
+ }
+
+ /* set the address */
+ (*env)->SetObjectField(env, this, psi_addressID, iaObj);
+
+ /* intialize the local port */
+ if (localport == 0) {
+ /* Now that we're a connected socket, let's extract the port number
+ * that the system chose for us and store it in the Socket object.
+ */
+ if (JVM_GetSockName(fd, (struct sockaddr *)&him, &len) == -1) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket name");
+ return;
+ }
+ localport = NET_GetPortFromSockaddr((struct sockaddr *)&him);
+ (*env)->SetIntField(env, this, psi_localportID, localport);
+ } else {
+ (*env)->SetIntField(env, this, psi_localportID, localport);
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketListen
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketListen (JNIEnv *env, jobject this,
+ jint count)
+{
+ /* this FileDescriptor fd field */
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ /* fdObj's int fd field */
+ int fd;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+
+ /*
+ * Workaround for bugid 4101691 in Solaris 2.6. See 4106600.
+ * If listen backlog is Integer.MAX_VALUE then subtract 1.
+ */
+ if (count == 0x7fffffff)
+ count -= 1;
+
+ if (JVM_Listen(fd, count) == JVM_IO_ERR) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Listen failed");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketAccept
+ * Signature: (Ljava/net/SocketImpl;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
+ jobject socket)
+{
+ /* fields on this */
+ int port;
+ jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
+ jlong prevTime = 0;
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+
+ /* the FileDescriptor field on socket */
+ jobject socketFdObj;
+ /* the InetAddress field on socket */
+ jobject socketAddressObj;
+
+ /* the ServerSocket fd int field on fdObj */
+ jint fd;
+
+ /* accepted fd */
+ jint newfd;
+
+ SOCKADDR him;
+ int len;
+
+ len = SOCKADDR_LEN;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (IS_NULL(socket)) {
+ JNU_ThrowNullPointerException(env, "socket is null");
+ return;
+ }
+
+ /*
+ * accept connection but ignore ECONNABORTED indicating that
+ * connection was eagerly accepted by the OS but was reset
+ * before accept() was called.
+ *
+ * If accept timeout in place and timeout is adjusted with
+ * each ECONNABORTED or EWOULDBLOCK to ensure that semantics
+ * of timeout are preserved.
+ */
+ for (;;) {
+ int ret;
+
+ /* first usage pick up current time */
+ if (prevTime == 0 && timeout > 0) {
+ prevTime = JVM_CurrentTimeMillis(env, 0);
+ }
+
+ /* passing a timeout of 0 to poll will return immediately,
+ but in the case of ServerSocket 0 means infinite. */
+ if (timeout <= 0) {
+ ret = NET_Timeout(fd, -1);
+ } else {
+ ret = NET_Timeout(fd, timeout);
+ }
+
+ if (ret == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Accept timed out");
+ return;
+ } else if (ret == JVM_IO_ERR) {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
+ }
+ return;
+ } else if (ret == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ return;
+ }
+
+ newfd = NET_Accept(fd, (struct sockaddr *)&him, (jint*)&len);
+
+ /* connection accepted */
+ if (newfd >= 0) {
+ SET_BLOCKING(newfd);
+ break;
+ }
+
+ /* non (ECONNABORTED or EWOULDBLOCK) error */
+ if (!(errno == ECONNABORTED || errno == EWOULDBLOCK)) {
+ break;
+ }
+
+ /* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
+ if (timeout) {
+ jlong currTime = JVM_CurrentTimeMillis(env, 0);
+ timeout -= (currTime - prevTime);
+
+ if (timeout <= 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Accept timed out");
+ return;
+ }
+ prevTime = currTime;
+ }
+ }
+
+ if (newfd < 0) {
+ if (newfd == -2) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "operation interrupted");
+ } else {
+ if (errno == EINVAL) {
+ errno = EBADF;
+ }
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "Accept failed");
+ }
+ }
+ return;
+ }
+
+ /*
+ * fill up the remote peer port and address in the new socket structure.
+ */
+ socketAddressObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
+ if (socketAddressObj == NULL) {
+ /* should be pending exception */
+ close(newfd);
+ return;
+ }
+
+ /*
+ * Populate SocketImpl.fd.fd
+ */
+ socketFdObj = (*env)->GetObjectField(env, socket, psi_fdID);
+ (*env)->SetIntField(env, socketFdObj, IO_fd_fdID, newfd);
+
+ (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
+ (*env)->SetIntField(env, socket, psi_portID, port);
+ /* also fill up the local port information */
+ port = (*env)->GetIntField(env, this, psi_localportID);
+ (*env)->SetIntField(env, socket, psi_localportID, port);
+}
+
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_java_net_PlainSocketImpl_socketAvailable(JNIEnv *env, jobject this) {
+
+ jint ret = -1;
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ jint fd;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ /* JVM_SocketAvailable returns 0 for failure, 1 for success */
+ if (!JVM_SocketAvailable(fd, &ret)){
+ if (errno == ECONNRESET) {
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException", "");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "ioctl FIONREAD failed");
+ }
+ }
+ return ret;
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketClose0
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketClose0(JNIEnv *env, jobject this,
+ jboolean useDeferredClose) {
+
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ jint fd;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "socket already closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ if (fd != -1) {
+ if (useDeferredClose && marker_fd >= 0) {
+ NET_Dup2(marker_fd, fd);
+ } else {
+ (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+ NET_SocketClose(fd);
+ }
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketShutdown
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketShutdown(JNIEnv *env, jobject this,
+ jint howto)
+{
+
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ jint fd;
+
+ /*
+ * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being
+ * -1 already?
+ */
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "socket already closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ }
+ JVM_SocketShutdown(fd, howto);
+}
+
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketSetOption
+ * Signature: (IZLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,
+ jint cmd, jboolean on,
+ jobject value) {
+ int fd;
+ int level, optname, optlen;
+ union {
+ int i;
+ struct linger ling;
+ } optval;
+
+ /*
+ * Check that socket hasn't been closed
+ */
+ fd = getFD(env, this);
+ if (fd < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return;
+ }
+
+ /*
+ * SO_TIMEOUT is a no-op on Solaris/Linux
+ */
+ if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
+ return;
+ }
+
+ /*
+ * Map the Java level socket option to the platform specific
+ * level and option name.
+ */
+ if (NET_MapSocketOption(cmd, &level, &optname)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ return;
+ }
+
+ switch (cmd) {
+ case java_net_SocketOptions_SO_SNDBUF :
+ case java_net_SocketOptions_SO_RCVBUF :
+ case java_net_SocketOptions_SO_LINGER :
+ case java_net_SocketOptions_IP_TOS :
+ {
+ jclass cls;
+ jfieldID fid;
+
+ cls = (*env)->FindClass(env, "java/lang/Integer");
+ CHECK_NULL(cls);
+ fid = (*env)->GetFieldID(env, cls, "value", "I");
+ CHECK_NULL(fid);
+
+ if (cmd == java_net_SocketOptions_SO_LINGER) {
+ if (on) {
+ optval.ling.l_onoff = 1;
+ optval.ling.l_linger = (*env)->GetIntField(env, value, fid);
+ } else {
+ optval.ling.l_onoff = 0;
+ optval.ling.l_linger = 0;
+ }
+ optlen = sizeof(optval.ling);
+ } else {
+ optval.i = (*env)->GetIntField(env, value, fid);
+ optlen = sizeof(optval.i);
+ }
+
+ break;
+ }
+
+ /* Boolean -> int */
+ default :
+ optval.i = (on ? 1 : 0);
+ optlen = sizeof(optval.i);
+
+ }
+
+ if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
+#ifdef __solaris__
+ if (errno == EINVAL) {
+ // On Solaris setsockopt will set errno to EINVAL if the socket
+ // is closed. The default error message is then confusing
+ char fullMsg[128];
+ jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
+ return;
+ }
+#endif /* __solaris__ */
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error setting socket option");
+ }
+}
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketGetOption
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_java_net_PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
+ jint cmd, jobject iaContainerObj) {
+
+ int fd;
+ int level, optname, optlen;
+ union {
+ int i;
+ struct linger ling;
+ } optval;
+
+ /*
+ * Check that socket hasn't been closed
+ */
+ fd = getFD(env, this);
+ if (fd < 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ }
+
+ /*
+ * SO_BINDADDR isn't a socket option
+ */
+ if (cmd == java_net_SocketOptions_SO_BINDADDR) {
+ SOCKADDR him;
+ socklen_t len = 0;
+ int port;
+ jobject iaObj;
+ jclass iaCntrClass;
+ jfieldID iaFieldID;
+
+ len = SOCKADDR_LEN;
+
+ if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket name");
+ return -1;
+ }
+ iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
+ CHECK_NULL_RETURN(iaObj, -1);
+
+ iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
+ iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
+ CHECK_NULL_RETURN(iaFieldID, -1);
+ (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
+ return 0; /* notice change from before */
+ }
+
+ /*
+ * Map the Java level socket option to the platform specific
+ * level and option name.
+ */
+ if (NET_MapSocketOption(cmd, &level, &optname)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
+ return -1;
+ }
+
+ /*
+ * Args are int except for SO_LINGER
+ */
+ if (cmd == java_net_SocketOptions_SO_LINGER) {
+ optlen = sizeof(optval.ling);
+ } else {
+ optlen = sizeof(optval.i);
+ }
+
+ if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "Error getting socket option");
+ return -1;
+ }
+
+ switch (cmd) {
+ case java_net_SocketOptions_SO_LINGER:
+ return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
+
+ case java_net_SocketOptions_SO_SNDBUF:
+ case java_net_SocketOptions_SO_RCVBUF:
+ case java_net_SocketOptions_IP_TOS:
+ return optval.i;
+
+ default :
+ return (optval.i == 0) ? -1 : 1;
+ }
+}
+
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketSendUrgentData
+ * Signature: (B)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_socketSendUrgentData(JNIEnv *env, jobject this,
+ jint data) {
+ /* The fd field */
+ jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
+ int n, fd;
+ unsigned char d = data & 0xFF;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ /* Bug 4086704 - If the Socket associated with this file descriptor
+ * was closed (sysCloseFD), the the file descriptor is set to -1.
+ */
+ if (fd == -1) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return;
+ }
+
+ }
+ n = JVM_Send(fd, (char *)&d, 1, MSG_OOB);
+ if (n == JVM_IO_ERR) {
+ NET_ThrowByNameWithLastError(env, "java/io/IOException", "Write failed");
+ return;
+ }
+ if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
+ return;
+ }
+}
diff --git a/ojluni/src/main/native/ProcessEnvironment_md.c b/ojluni/src/main/native/ProcessEnvironment_md.c
new file mode 100755
index 0000000..b946663
--- /dev/null
+++ b/ojluni/src/main/native/ProcessEnvironment_md.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "jni.h"
+#include "jni_util.h"
+
+#ifdef __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#endif
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_lang_ProcessEnvironment_environ(JNIEnv *env, jclass ign)
+{
+ /* This is one of the rare times it's more portable to declare an
+ * external symbol explicitly, rather than via a system header.
+ * The declaration is standardized as part of UNIX98, but there is
+ * no standard (not even de-facto) header file where the
+ * declaration is to be found. See:
+ * http://www.opengroup.org/onlinepubs/007908799/xbd/envvar.html */
+#ifndef __APPLE__
+ extern char ** environ; /* environ[i] looks like: VAR=VALUE\0 */
+#endif
+
+ jsize count = 0;
+ jsize i, j;
+ jobjectArray result;
+ jclass byteArrCls = (*env)->FindClass(env, "[B");
+
+ for (i = 0; environ[i]; i++) {
+ /* Ignore corrupted environment variables */
+ if (strchr(environ[i], '=') != NULL)
+ count++;
+ }
+
+ result = (*env)->NewObjectArray(env, 2*count, byteArrCls, 0);
+ if (result == NULL) return NULL;
+
+ for (i = 0, j = 0; environ[i]; i++) {
+ const char * varEnd = strchr(environ[i], '=');
+ /* Ignore corrupted environment variables */
+ if (varEnd != NULL) {
+ jbyteArray var, val;
+ const char * valBeg = varEnd + 1;
+ jsize varLength = varEnd - environ[i];
+ jsize valLength = strlen(valBeg);
+ var = (*env)->NewByteArray(env, varLength);
+ if (var == NULL) return NULL;
+ val = (*env)->NewByteArray(env, valLength);
+ if (val == NULL) return NULL;
+ (*env)->SetByteArrayRegion(env, var, 0, varLength,
+ (jbyte*) environ[i]);
+ (*env)->SetByteArrayRegion(env, val, 0, valLength,
+ (jbyte*) valBeg);
+ (*env)->SetObjectArrayElement(env, result, 2*j , var);
+ (*env)->SetObjectArrayElement(env, result, 2*j+1, val);
+ (*env)->DeleteLocalRef(env, var);
+ (*env)->DeleteLocalRef(env, val);
+ j++;
+ }
+ }
+
+ return result;
+}
diff --git a/ojluni/src/main/native/Runtime.c b/ojluni/src/main/native/Runtime.c
new file mode 100755
index 0000000..dece223
--- /dev/null
+++ b/ojluni/src/main/native/Runtime.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1994, 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Link foreign methods. This first half of this file contains the
+ * machine independent dynamic linking routines.
+ * See "BUILD_PLATFORM"/java/lang/linker_md.c to see
+ * the implementation of this shared dynamic linking
+ * interface.
+ *
+ * NOTE - source in this file is POSIX.1 compliant, host
+ * specific code lives in the platform specific
+ * code tree.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+
+#include "java_lang_Runtime.h"
+
+JNIEXPORT jlong JNICALL
+Java_java_lang_Runtime_freeMemory(JNIEnv *env, jobject this)
+{
+ return JVM_FreeMemory();
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_lang_Runtime_totalMemory(JNIEnv *env, jobject this)
+{
+ return JVM_TotalMemory();
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_lang_Runtime_maxMemory(JNIEnv *env, jobject this)
+{
+ return JVM_MaxMemory();
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_Runtime_gc(JNIEnv *env, jobject this)
+{
+ JVM_GC();
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_Runtime_traceInstructions(JNIEnv *env, jobject this, jboolean on)
+{
+ JVM_TraceInstructions(on);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_Runtime_traceMethodCalls(JNIEnv *env, jobject this, jboolean on)
+{
+ JVM_TraceMethodCalls(on);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_Runtime_runFinalization0(JNIEnv *env, jobject this)
+{
+ jclass cl;
+ jmethodID mid;
+
+ if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))
+ && (mid = (*env)->GetStaticMethodID(env, cl,
+ "runFinalization", "()V"))) {
+ (*env)->CallStaticVoidMethod(env, cl, mid);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_Runtime_availableProcessors(JNIEnv *env, jobject this)
+{
+ return JVM_ActiveProcessorCount();
+}
diff --git a/ojluni/src/main/native/Shutdown.c b/ojluni/src/main/native/Shutdown.c
new file mode 100755
index 0000000..f131a24
--- /dev/null
+++ b/ojluni/src/main/native/Shutdown.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+
+#include "java_lang_Shutdown.h"
+
+
+JNIEXPORT void JNICALL
+Java_java_lang_Shutdown_halt0(JNIEnv *env, jclass ignored, jint code)
+{
+ JVM_Halt(code);
+}
+
+
+JNIEXPORT void JNICALL
+Java_java_lang_Shutdown_runAllFinalizers(JNIEnv *env, jclass ignored)
+{
+ jclass cl;
+ jmethodID mid;
+
+ if ((cl = (*env)->FindClass(env, "java/lang/ref/Finalizer"))
+ && (mid = (*env)->GetStaticMethodID(env, cl,
+ "runAllFinalizers", "()V"))) {
+ (*env)->CallStaticVoidMethod(env, cl, mid);
+ }
+}
diff --git a/ojluni/src/main/native/Signal.c b/ojluni/src/main/native/Signal.c
new file mode 100755
index 0000000..da1bc19
--- /dev/null
+++ b/ojluni/src/main/native/Signal.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+
+#include <jni.h>
+#include <jvm.h>
+#include <jni_util.h>
+#include <jlong.h>
+#include "sun_misc_Signal.h"
+
+JNIEXPORT jint JNICALL
+Java_sun_misc_Signal_findSignal(JNIEnv *env, jclass cls, jstring name)
+{
+ jint res;
+ const char *cname = (*env)->GetStringUTFChars(env, name, 0);
+ if (cname == NULL) {
+ /* out of memory thrown */
+ return 0;
+ }
+ res = JVM_FindSignal(cname);
+ (*env)->ReleaseStringUTFChars(env, name, cname);
+ return res;
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_misc_Signal_handle0(JNIEnv *env, jclass cls, jint sig, jlong handler)
+{
+ return ptr_to_jlong(JVM_RegisterSignal(sig, jlong_to_ptr(handler)));
+}
+
+JNIEXPORT void JNICALL
+Java_sun_misc_Signal_raise0(JNIEnv *env, jclass cls, jint sig)
+{
+ JVM_RaiseSignal(sig);
+}
diff --git a/ojluni/src/main/native/SocketInputStream.c b/ojluni/src/main/native/SocketInputStream.c
new file mode 100755
index 0000000..1e115ce
--- /dev/null
+++ b/ojluni/src/main/native/SocketInputStream.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_SocketInputStream.h"
+
+
+/************************************************************************
+ * SocketInputStream
+ */
+
+static jfieldID IO_fd_fdID;
+
+/*
+ * Class: java_net_SocketInputStream
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) {
+ IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+/*
+ * Class: java_net_SocketInputStream
+ * Method: socketRead0
+ * Signature: (Ljava/io/FileDescriptor;[BIII)I
+ */
+JNIEXPORT jint JNICALL
+Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
+ jobject fdObj, jbyteArray data,
+ jint off, jint len, jint timeout)
+{
+ char BUF[MAX_BUFFER_LEN];
+ char *bufP;
+ jint fd, nread;
+
+ if (IS_NULL(fdObj)) {
+ /* should't this be a NullPointerException? -br */
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ /* Bug 4086704 - If the Socket associated with this file descriptor
+ * was closed (sysCloseFD), the the file descriptor is set to -1.
+ */
+ if (fd == -1) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return -1;
+ }
+ }
+
+ /*
+ * If the read is greater than our stack allocated buffer then
+ * we allocate from the heap (up to a limit)
+ */
+ if (len > MAX_BUFFER_LEN) {
+ if (len > MAX_HEAP_BUFFER_LEN) {
+ len = MAX_HEAP_BUFFER_LEN;
+ }
+ bufP = (char *)malloc((size_t)len);
+ if (bufP == NULL) {
+ bufP = BUF;
+ len = MAX_BUFFER_LEN;
+ }
+ } else {
+ bufP = BUF;
+ }
+
+ if (timeout) {
+ nread = NET_Timeout(fd, timeout);
+ if (nread <= 0) {
+ if (nread == 0) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Read timed out");
+ } else if (nread == JVM_IO_ERR) {
+ if (errno == EBADF) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
+ } else {
+ NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+ "select/poll failed");
+ }
+ } else if (nread == JVM_IO_INTR) {
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "Operation interrupted");
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return -1;
+ }
+ }
+
+ nread = NET_Read(fd, bufP, len);
+
+ if (nread <= 0) {
+ if (nread < 0) {
+
+ switch (errno) {
+ case ECONNRESET:
+ case EPIPE:
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+ "Connection reset");
+ break;
+
+ case EBADF:
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ break;
+
+ case EINTR:
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+ "Operation interrupted");
+ break;
+
+ default:
+ NET_ThrowByNameWithLastError(env,
+ JNU_JAVANETPKG "SocketException", "Read failed");
+ }
+ }
+ } else {
+ (*env)->SetByteArrayRegion(env, data, off, nread, (jbyte *)bufP);
+ }
+
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return nread;
+}
diff --git a/ojluni/src/main/native/SocketOutputStream.c b/ojluni/src/main/native/SocketOutputStream.c
new file mode 100755
index 0000000..d6e01ff
--- /dev/null
+++ b/ojluni/src/main/native/SocketOutputStream.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "jni_util.h"
+#include "jvm.h"
+#include "net_util.h"
+
+#include "java_net_SocketOutputStream.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/*
+ * SocketOutputStream
+ */
+
+static jfieldID IO_fd_fdID;
+
+/*
+ * Class: java_net_SocketOutputStream
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_SocketOutputStream_init(JNIEnv *env, jclass cls) {
+ IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+/*
+ * Class: java_net_SocketOutputStream
+ * Method: socketWrite0
+ * Signature: (Ljava/io/FileDescriptor;[BII)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_SocketOutputStream_socketWrite0(JNIEnv *env, jobject this,
+ jobject fdObj,
+ jbyteArray data,
+ jint off, jint len) {
+ char *bufP;
+ char BUF[MAX_BUFFER_LEN];
+ int buflen;
+ int fd;
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return;
+ } else {
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+ /* Bug 4086704 - If the Socket associated with this file descriptor
+ * was closed (sysCloseFD), the the file descriptor is set to -1.
+ */
+ if (fd == -1) {
+ JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
+ return;
+ }
+
+ }
+
+ if (len <= MAX_BUFFER_LEN) {
+ bufP = BUF;
+ buflen = MAX_BUFFER_LEN;
+ } else {
+ buflen = min(MAX_HEAP_BUFFER_LEN, len);
+ bufP = (char *)malloc((size_t)buflen);
+
+ /* if heap exhausted resort to stack buffer */
+ if (bufP == NULL) {
+ bufP = BUF;
+ buflen = MAX_BUFFER_LEN;
+ }
+ }
+
+ while(len > 0) {
+ int loff = 0;
+ int chunkLen = min(buflen, len);
+ int llen = chunkLen;
+ (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP);
+
+ while(llen > 0) {
+ int n = NET_Send(fd, bufP + loff, llen, 0);
+ if (n > 0) {
+ llen -= n;
+ loff += n;
+ continue;
+ }
+ if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", 0);
+ } else {
+ if (errno == ECONNRESET) {
+ JNU_ThrowByName(env, "sun/net/ConnectionResetException",
+ "Connection reset");
+ } else {
+ NET_ThrowByNameWithLastError(env, "java/net/SocketException",
+ "Write failed");
+ }
+ }
+ if (bufP != BUF) {
+ free(bufP);
+ }
+ return;
+ }
+ len -= chunkLen;
+ off += chunkLen;
+ }
+
+ if (bufP != BUF) {
+ free(bufP);
+ }
+}
diff --git a/ojluni/src/main/native/StrictMath.c b/ojluni/src/main/native/StrictMath.c
new file mode 100755
index 0000000..d7c2007
--- /dev/null
+++ b/ojluni/src/main/native/StrictMath.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "fdlibm.h"
+
+#include "java_lang_StrictMath.h"
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_cos(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jcos((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_sin(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jsin((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_tan(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jtan((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_asin(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jasin((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_acos(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jacos((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_atan(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jatan((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_exp(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jexp((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_log(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jlog((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_log10(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jlog10((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_sqrt(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jsqrt((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_cbrt(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jcbrt((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_atan2(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
+{
+ return (jdouble) jatan2((double)d1, (double)d2);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_pow(JNIEnv *env, jclass unused, jdouble d1, jdouble d2)
+{
+ return (jdouble) jpow((double)d1, (double)d2);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_IEEEremainder(JNIEnv *env, jclass unused,
+ jdouble dividend,
+ jdouble divisor)
+{
+ return (jdouble) jremainder(dividend, divisor);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_cosh(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jcosh((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_sinh(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jsinh((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_tanh(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jtanh((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_hypot(JNIEnv *env, jclass unused, jdouble x, jdouble y)
+{
+ return (jdouble) jhypot((double)x, (double)y);
+}
+
+
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_log1p(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jlog1p((double)d);
+}
+
+JNIEXPORT jdouble JNICALL
+Java_java_lang_StrictMath_expm1(JNIEnv *env, jclass unused, jdouble d)
+{
+ return (jdouble) jexpm1((double)d);
+}
diff --git a/ojluni/src/main/native/String.c b/ojluni/src/main/native/String.c
new file mode 100755
index 0000000..7c8170e
--- /dev/null
+++ b/ojluni/src/main/native/String.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvm.h"
+#include "java_lang_String.h"
+
+JNIEXPORT jobject JNICALL
+Java_java_lang_String_intern(JNIEnv *env, jobject this)
+{
+ return JVM_InternString(env, this);
+}
diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c
new file mode 100755
index 0000000..4051bff
--- /dev/null
+++ b/ojluni/src/main/native/System.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <string.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "java_props.h"
+
+#include "java_lang_System.h"
+
+#define OBJ "Ljava/lang/Object;"
+
+/* Only register the performance-critical methods */
+static JNINativeMethod methods[] = {
+ {"currentTimeMillis", "()J", (void *)&JVM_CurrentTimeMillis},
+ {"nanoTime", "()J", (void *)&JVM_NanoTime},
+ {"arraycopy", "(" OBJ "I" OBJ "II)V", (void *)&JVM_ArrayCopy},
+};
+
+#undef OBJ
+
+JNIEXPORT void JNICALL
+Java_java_lang_System_registerNatives(JNIEnv *env, jclass cls)
+{
+ (*env)->RegisterNatives(env, cls,
+ methods, sizeof(methods)/sizeof(methods[0]));
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_System_identityHashCode(JNIEnv *env, jobject this, jobject x)
+{
+ return JVM_IHashCode(env, x);
+}
+
+#define PUTPROP(props, key, val) \
+ if (1) { \
+ jstring jkey = (*env)->NewStringUTF(env, key); \
+ jstring jval = (*env)->NewStringUTF(env, val); \
+ jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \
+ if ((*env)->ExceptionOccurred(env)) return NULL; \
+ (*env)->DeleteLocalRef(env, jkey); \
+ (*env)->DeleteLocalRef(env, jval); \
+ (*env)->DeleteLocalRef(env, r); \
+ } else ((void) 0)
+
+/* "key" is a char type string with only ASCII character in it.
+ "val" is a nchar (typedefed in java_props.h) type string */
+
+#define PUTPROP_ForPlatformNString(props, key, val) \
+ if (1) { \
+ jstring jkey = (*env)->NewStringUTF(env, key); \
+ jstring jval = GetStringPlatform(env, val); \
+ jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \
+ if ((*env)->ExceptionOccurred(env)) return NULL; \
+ (*env)->DeleteLocalRef(env, jkey); \
+ (*env)->DeleteLocalRef(env, jval); \
+ (*env)->DeleteLocalRef(env, r); \
+ } else ((void) 0)
+#define REMOVEPROP(props, key) \
+ if (1) { \
+ jstring jkey = JNU_NewStringPlatform(env, key); \
+ jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \
+ if ((*env)->ExceptionOccurred(env)) return NULL; \
+ (*env)->DeleteLocalRef(env, jkey); \
+ (*env)->DeleteLocalRef(env, r); \
+ } else ((void) 0)
+#define GETPROP(props, key, jret) \
+ if (1) { \
+ jstring jkey = JNU_NewStringPlatform(env, key); \
+ jret = (*env)->CallObjectMethod(env, props, getPropID, jkey); \
+ if ((*env)->ExceptionOccurred(env)) return NULL; \
+ (*env)->DeleteLocalRef(env, jkey); \
+ } else ((void) 0)
+
+#ifndef VENDOR /* Third party may overwrite this. */
+#define VENDOR "Oracle Corporation"
+#define VENDOR_URL "http://java.oracle.com/"
+#define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/"
+#endif
+
+#define JAVA_MAX_SUPPORTED_VERSION 51
+#define JAVA_MAX_SUPPORTED_MINOR_VERSION 0
+
+#ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */
+ #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed"
+#else
+ #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation"
+#endif
+
+static int fmtdefault; // boolean value
+jobject fillI18nProps(JNIEnv *env, jobject props, char *baseKey,
+ char *platformDispVal, char *platformFmtVal,
+ jmethodID putID, jmethodID getPropID) {
+ jstring jVMBaseVal = NULL;
+
+ GETPROP(props, baseKey, jVMBaseVal);
+ if (jVMBaseVal) {
+ // user specified the base property. there's nothing to do here.
+ (*env)->DeleteLocalRef(env, jVMBaseVal);
+ } else {
+ char buf[64];
+ jstring jVMVal = NULL;
+ const char *baseVal = "";
+
+ /* user.xxx base property */
+ if (fmtdefault) {
+ if (platformFmtVal) {
+ PUTPROP(props, baseKey, platformFmtVal);
+ baseVal = platformFmtVal;
+ }
+ } else {
+ if (platformDispVal) {
+ PUTPROP(props, baseKey, platformDispVal);
+ baseVal = platformDispVal;
+ }
+ }
+
+ /* user.xxx.display property */
+ jio_snprintf(buf, sizeof(buf), "%s.display", baseKey);
+ GETPROP(props, buf, jVMVal);
+ if (jVMVal == NULL) {
+ if (platformDispVal && (strcmp(baseVal, platformDispVal) != 0)) {
+ PUTPROP(props, buf, platformDispVal);
+ }
+ } else {
+ (*env)->DeleteLocalRef(env, jVMVal);
+ }
+
+ /* user.xxx.format property */
+ jio_snprintf(buf, sizeof(buf), "%s.format", baseKey);
+ GETPROP(props, buf, jVMVal);
+ if (jVMVal == NULL) {
+ if (platformFmtVal && (strcmp(baseVal, platformFmtVal) != 0)) {
+ PUTPROP(props, buf, platformFmtVal);
+ }
+ } else {
+ (*env)->DeleteLocalRef(env, jVMVal);
+ }
+ }
+
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL
+Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
+{
+ char buf[128];
+ java_props_t *sprops = GetJavaProperties(env);
+ jmethodID putID = (*env)->GetMethodID(env,
+ (*env)->GetObjectClass(env, props),
+ "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+ jmethodID removeID = (*env)->GetMethodID(env,
+ (*env)->GetObjectClass(env, props),
+ "remove",
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
+ jmethodID getPropID = (*env)->GetMethodID(env,
+ (*env)->GetObjectClass(env, props),
+ "getProperty",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ jobject ret = NULL;
+ jstring jVMVal = NULL;
+
+ if (sprops == NULL || putID == NULL ) return NULL;
+
+ PUTPROP(props, "java.specification.version",
+ JDK_MAJOR_VERSION "." JDK_MINOR_VERSION);
+ PUTPROP(props, "java.specification.name",
+ "Java Platform API Specification");
+ PUTPROP(props, "java.specification.vendor",
+ JAVA_SPECIFICATION_VENDOR);
+
+ PUTPROP(props, "java.version", RELEASE);
+ PUTPROP(props, "java.vendor", VENDOR);
+ PUTPROP(props, "java.vendor.url", VENDOR_URL);
+ PUTPROP(props, "java.vendor.url.bug", VENDOR_URL_BUG);
+
+ jio_snprintf(buf, sizeof(buf), "%d.%d", JAVA_MAX_SUPPORTED_VERSION,
+ JAVA_MAX_SUPPORTED_MINOR_VERSION);
+ PUTPROP(props, "java.class.version", buf);
+
+ if (sprops->awt_toolkit) {
+ PUTPROP(props, "awt.toolkit", sprops->awt_toolkit);
+ }
+
+ /* os properties */
+ PUTPROP(props, "os.name", sprops->os_name);
+ PUTPROP(props, "os.version", sprops->os_version);
+ PUTPROP(props, "os.arch", sprops->os_arch);
+
+ /* file system properties */
+ PUTPROP(props, "file.separator", sprops->file_separator);
+ PUTPROP(props, "path.separator", sprops->path_separator);
+ PUTPROP(props, "line.separator", sprops->line_separator);
+
+ /*
+ * user.language
+ * user.script, user.country, user.variant (if user's environment specifies them)
+ * file.encoding
+ * file.encoding.pkg
+ */
+ PUTPROP(props, "user.language", sprops->language);
+ if (sprops->script) {
+ PUTPROP(props, "user.script", sprops->script);
+ }
+ if (sprops->country) {
+ PUTPROP(props, "user.country", sprops->country);
+ }
+ if (sprops->variant) {
+ PUTPROP(props, "user.variant", sprops->variant);
+ }
+ PUTPROP(props, "file.encoding", sprops->encoding);
+ PUTPROP(props, "sun.jnu.encoding", sprops->sun_jnu_encoding);
+ PUTPROP(props, "file.encoding.pkg", "sun.io");
+ /* unicode_encoding specifies the default endianness */
+ PUTPROP(props, "sun.io.unicode.encoding", sprops->unicode_encoding);
+ PUTPROP(props, "sun.cpu.isalist",
+ (sprops->cpu_isalist ? sprops->cpu_isalist : ""));
+ PUTPROP(props, "sun.cpu.endian", sprops->cpu_endian);
+
+
+#ifdef MACOSX
+ /* Proxy setting properties */
+ if (sprops->httpProxyEnabled) {
+ PUTPROP(props, "http.proxyHost", sprops->httpHost);
+ PUTPROP(props, "http.proxyPort", sprops->httpPort);
+ }
+
+ if (sprops->httpsProxyEnabled) {
+ PUTPROP(props, "https.proxyHost", sprops->httpsHost);
+ PUTPROP(props, "https.proxyPort", sprops->httpsPort);
+ }
+
+ if (sprops->ftpProxyEnabled) {
+ PUTPROP(props, "ftp.proxyHost", sprops->ftpHost);
+ PUTPROP(props, "ftp.proxyPort", sprops->ftpPort);
+ }
+
+ if (sprops->socksProxyEnabled) {
+ PUTPROP(props, "socksProxyHost", sprops->socksHost);
+ PUTPROP(props, "socksProxyPort", sprops->socksPort);
+ }
+
+ if (sprops->gopherProxyEnabled) {
+ // The gopher client is different in that it expects an 'is this set?' flag that the others don't.
+ PUTPROP(props, "gopherProxySet", "true");
+ PUTPROP(props, "gopherProxyHost", sprops->gopherHost);
+ PUTPROP(props, "gopherProxyPort", sprops->gopherPort);
+ } else {
+ PUTPROP(props, "gopherProxySet", "false");
+ }
+
+ // Mac OS X only has a single proxy exception list which applies
+ // to all protocols
+ if (sprops->exceptionList) {
+ PUTPROP(props, "http.nonProxyHosts", sprops->exceptionList);
+ // HTTPS: implementation in jsse.jar uses http.nonProxyHosts
+ PUTPROP(props, "ftp.nonProxyHosts", sprops->exceptionList);
+ PUTPROP(props, "socksNonProxyHosts", sprops->exceptionList);
+ }
+#endif
+
+ /* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!!
+ * !!! I18n properties have not been set up yet !!!
+ */
+
+ /* Printing properties */
+ /* Note: java.awt.printerjob is an implementation private property which
+ * just happens to have a java.* name because it is referenced in
+ * a java.awt class. It is the mechanism by which the implementation
+ * finds the appropriate class in the JRE for the platform.
+ * It is explicitly not designed to be overridden by clients as
+ * a way of replacing the implementation class, and in any case
+ * the mechanism by which the class is loaded is constrained to only
+ * find and load classes that are part of the JRE.
+ * This property may be removed if that mechanism is redesigned
+ */
+ PUTPROP(props, "java.awt.printerjob", sprops->printerJob);
+
+ /* data model */
+ if (sizeof(sprops) == 4) {
+ sprops->data_model = "32";
+ } else if (sizeof(sprops) == 8) {
+ sprops->data_model = "64";
+ } else {
+ sprops->data_model = "unknown";
+ }
+ PUTPROP(props, "sun.arch.data.model", \
+ sprops->data_model);
+
+ /* patch level */
+ PUTPROP(props, "sun.os.patch.level", \
+ sprops->patch_level);
+
+ /* Java2D properties */
+ /* Note: java.awt.graphicsenv is an implementation private property which
+ * just happens to have a java.* name because it is referenced in
+ * a java.awt class. It is the mechanism by which the implementation
+ * finds the appropriate class in the JRE for the platform.
+ * It is explicitly not designed to be overridden by clients as
+ * a way of replacing the implementation class, and in any case
+ * the mechanism by which the class is loaded is constrained to only
+ * find and load classes that are part of the JRE.
+ * This property may be removed if that mechanism is redesigned
+ */
+ PUTPROP(props, "java.awt.graphicsenv", sprops->graphics_env);
+ if (sprops->font_dir != NULL) {
+ PUTPROP_ForPlatformNString(props,
+ "sun.java2d.fontpath", sprops->font_dir);
+ }
+
+ PUTPROP_ForPlatformNString(props, "java.io.tmpdir", sprops->tmp_dir);
+
+ PUTPROP_ForPlatformNString(props, "user.name", sprops->user_name);
+ PUTPROP_ForPlatformNString(props, "user.home", sprops->user_home);
+
+ PUTPROP(props, "user.timezone", sprops->timezone);
+
+ PUTPROP_ForPlatformNString(props, "user.dir", sprops->user_dir);
+
+ /* This is a sun. property as it is currently only set for Gnome and
+ * Windows desktops.
+ */
+ if (sprops->desktop != NULL) {
+ PUTPROP(props, "sun.desktop", sprops->desktop);
+ }
+
+ /*
+ * unset "user.language", "user.script", "user.country", and "user.variant"
+ * in order to tell whether the command line option "-DXXXX=YYYY" is
+ * specified or not. They will be reset in fillI18nProps() below.
+ */
+ REMOVEPROP(props, "user.language");
+ REMOVEPROP(props, "user.script");
+ REMOVEPROP(props, "user.country");
+ REMOVEPROP(props, "user.variant");
+ REMOVEPROP(props, "file.encoding");
+
+ ret = JVM_InitProperties(env, props);
+
+ /* Check the compatibility flag */
+ GETPROP(props, "sun.locale.formatasdefault", jVMVal);
+ if (jVMVal) {
+ const char * val = (*env)->GetStringUTFChars(env, jVMVal, 0);
+ fmtdefault = !strcmp(val, "true");
+ (*env)->ReleaseStringUTFChars(env, jVMVal, val);
+ (*env)->DeleteLocalRef(env, jVMVal);
+ }
+
+ /* reconstruct i18n related properties */
+ fillI18nProps(env, props, "user.language", sprops->display_language,
+ sprops->format_language, putID, getPropID);
+ fillI18nProps(env, props, "user.script",
+ sprops->display_script, sprops->format_script, putID, getPropID);
+ fillI18nProps(env, props, "user.country",
+ sprops->display_country, sprops->format_country, putID, getPropID);
+ fillI18nProps(env, props, "user.variant",
+ sprops->display_variant, sprops->format_variant, putID, getPropID);
+ GETPROP(props, "file.encoding", jVMVal);
+ if (jVMVal == NULL) {
+#ifdef MACOSX
+ /*
+ * Since sun_jnu_encoding is now hard-coded to UTF-8 on Mac, we don't
+ * want to use it to overwrite file.encoding
+ */
+ PUTPROP(props, "file.encoding", sprops->encoding);
+#else
+ if (fmtdefault) {
+ PUTPROP(props, "file.encoding", sprops->encoding);
+ } else {
+ PUTPROP(props, "file.encoding", sprops->sun_jnu_encoding);
+ }
+#endif
+ } else {
+ (*env)->DeleteLocalRef(env, jVMVal);
+ }
+
+ return ret;
+}
+
+/*
+ * The following three functions implement setter methods for
+ * java.lang.System.{in, out, err}. They are natively implemented
+ * because they violate the semantics of the language (i.e. set final
+ * variable).
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_System_setIn0(JNIEnv *env, jclass cla, jobject stream)
+{
+ jfieldID fid =
+ (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;");
+ if (fid == 0)
+ return;
+ (*env)->SetStaticObjectField(env,cla,fid,stream);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
+{
+ jfieldID fid =
+ (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
+ if (fid == 0)
+ return;
+ (*env)->SetStaticObjectField(env,cla,fid,stream);
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_System_setErr0(JNIEnv *env, jclass cla, jobject stream)
+{
+ jfieldID fid =
+ (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;");
+ if (fid == 0)
+ return;
+ (*env)->SetStaticObjectField(env,cla,fid,stream);
+}
+
+static void cpchars(jchar *dst, char *src, int n)
+{
+ int i;
+ for (i = 0; i < n; i++) {
+ dst[i] = src[i];
+ }
+}
+
+JNIEXPORT jstring JNICALL
+Java_java_lang_System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname)
+{
+ int len;
+ int prefix_len = (int) strlen(JNI_LIB_PREFIX);
+ int suffix_len = (int) strlen(JNI_LIB_SUFFIX);
+
+ jchar chars[256];
+ if (libname == NULL) {
+ JNU_ThrowNullPointerException(env, 0);
+ return NULL;
+ }
+ len = (*env)->GetStringLength(env, libname);
+ if (len > 240) {
+ JNU_ThrowIllegalArgumentException(env, "name too long");
+ return NULL;
+ }
+ cpchars(chars, JNI_LIB_PREFIX, prefix_len);
+ (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len);
+ len += prefix_len;
+ cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len);
+ len += suffix_len;
+
+ return (*env)->NewString(env, chars, len);
+}
diff --git a/ojluni/src/main/native/Thread.c b/ojluni/src/main/native/Thread.c
new file mode 100755
index 0000000..cfbc7fd
--- /dev/null
+++ b/ojluni/src/main/native/Thread.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*-
+ * Stuff for dealing with threads.
+ * originally in threadruntime.c, Sun Sep 22 12:09:39 1991
+ */
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_lang_Thread.h"
+
+#define THD "Ljava/lang/Thread;"
+#define OBJ "Ljava/lang/Object;"
+#define STE "Ljava/lang/StackTraceElement;"
+#define STR "Ljava/lang/String;"
+
+#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
+
+static JNINativeMethod methods[] = {
+ {"start0", "()V", (void *)&JVM_StartThread},
+ {"stop0", "(" OBJ ")V", (void *)&JVM_StopThread},
+ {"isAlive", "()Z", (void *)&JVM_IsThreadAlive},
+ {"suspend0", "()V", (void *)&JVM_SuspendThread},
+ {"resume0", "()V", (void *)&JVM_ResumeThread},
+ {"setPriority0", "(I)V", (void *)&JVM_SetThreadPriority},
+ {"yield", "()V", (void *)&JVM_Yield},
+ {"sleep", "(J)V", (void *)&JVM_Sleep},
+ {"currentThread", "()" THD, (void *)&JVM_CurrentThread},
+ {"countStackFrames", "()I", (void *)&JVM_CountStackFrames},
+ {"interrupt0", "()V", (void *)&JVM_Interrupt},
+ {"isInterrupted", "(Z)Z", (void *)&JVM_IsInterrupted},
+ {"holdsLock", "(" OBJ ")Z", (void *)&JVM_HoldsLock},
+ {"getThreads", "()[" THD, (void *)&JVM_GetAllThreads},
+ {"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
+ {"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName},
+};
+
+#undef THD
+#undef OBJ
+#undef STE
+#undef STR
+
+JNIEXPORT void JNICALL
+Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
+{
+ (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
+}
diff --git a/ojluni/src/main/native/Throwable.c b/ojluni/src/main/native/Throwable.c
new file mode 100755
index 0000000..aaf3c26
--- /dev/null
+++ b/ojluni/src/main/native/Throwable.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Implementation of class Throwable
+ *
+ * former classruntime.c, Wed Jun 26 18:43:20 1991
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_lang_Throwable.h"
+
+/*
+ * Fill in the current stack trace in this exception. This is
+ * usually called automatically when the exception is created but it
+ * may also be called explicitly by the user. This routine returns
+ * `this' so you can write 'throw e.fillInStackTrace();'
+ */
+JNIEXPORT jobject JNICALL
+Java_java_lang_Throwable_fillInStackTrace(JNIEnv *env, jobject throwable, int dummy)
+{
+ JVM_FillInStackTrace(env, throwable);
+ return throwable;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_Throwable_getStackTraceDepth(JNIEnv *env, jobject throwable)
+{
+ return JVM_GetStackTraceDepth(env, throwable);
+}
+
+JNIEXPORT jobject JNICALL
+Java_java_lang_Throwable_getStackTraceElement(JNIEnv *env,
+ jobject throwable, jint index)
+{
+ return JVM_GetStackTraceElement(env, throwable, index);
+}
diff --git a/ojluni/src/main/native/UNIXProcess_md.c b/ojluni/src/main/native/UNIXProcess_md.c
new file mode 100755
index 0000000..6904a44
--- /dev/null
+++ b/ojluni/src/main/native/UNIXProcess_md.c
@@ -0,0 +1,965 @@
+/*
+ * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#undef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE 1
+
+#include "jni.h"
+#include "jvm.h"
+#include "jvm_md.h"
+#include "jni_util.h"
+#include "io_util.h"
+
+/*
+ * Platform-specific support for java.lang.Process
+ */
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef _ALLBSD_SOURCE
+#include <sys/wait.h>
+#else
+#include <wait.h>
+#endif
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#ifdef __APPLE__
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
+#endif
+
+/*
+ * There are 3 possible strategies we might use to "fork":
+ *
+ * - fork(2). Very portable and reliable but subject to
+ * failure due to overcommit (see the documentation on
+ * /proc/sys/vm/overcommit_memory in Linux proc(5)).
+ * This is the ancient problem of spurious failure whenever a large
+ * process starts a small subprocess.
+ *
+ * - vfork(). Using this is scary because all relevant man pages
+ * contain dire warnings, e.g. Linux vfork(2). But at least it's
+ * documented in the glibc docs and is standardized by XPG4.
+ * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
+ * On Linux, one might think that vfork() would be implemented using
+ * the clone system call with flag CLONE_VFORK, but in fact vfork is
+ * a separate system call (which is a good sign, suggesting that
+ * vfork will continue to be supported at least on Linux).
+ * Another good sign is that glibc implements posix_spawn using
+ * vfork whenever possible. Note that we cannot use posix_spawn
+ * ourselves because there's no reliable way to close all inherited
+ * file descriptors.
+ *
+ * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is
+ * Linux-specific, but this ought to work - at least the glibc
+ * sources contain code to handle different combinations of CLONE_VM
+ * and CLONE_THREAD. However, when this was implemented, it
+ * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
+ * the simple program
+ * Runtime.getRuntime().exec("/bin/true").waitFor();
+ * with:
+ * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
+ * # Error: pthread_getattr_np failed with errno = 3 (ESRCH)
+ * We believe this is a glibc bug, reported here:
+ * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
+ * but the glibc maintainers closed it as WONTFIX.
+ *
+ * Based on the above analysis, we are currently using vfork() on
+ * Linux and fork() on other Unix systems, but the code to use clone()
+ * remains.
+ */
+
+#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */
+
+#ifndef START_CHILD_USE_CLONE
+ #ifdef __linux__
+ #define START_CHILD_USE_CLONE 1
+ #else
+ #define START_CHILD_USE_CLONE 0
+ #endif
+#endif
+
+/* By default, use vfork() on Linux. */
+#ifndef START_CHILD_USE_VFORK
+ #ifdef __linux__
+ #define START_CHILD_USE_VFORK 1
+ #else
+ #define START_CHILD_USE_VFORK 0
+ #endif
+#endif
+
+#if START_CHILD_USE_CLONE
+#include <sched.h>
+#define START_CHILD_SYSTEM_CALL "clone"
+#elif START_CHILD_USE_VFORK
+#define START_CHILD_SYSTEM_CALL "vfork"
+#else
+#define START_CHILD_SYSTEM_CALL "fork"
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef SA_NOCLDSTOP
+#define SA_NOCLDSTOP 0
+#endif
+
+#ifndef SA_RESTART
+#define SA_RESTART 0
+#endif
+
+#define FAIL_FILENO (STDERR_FILENO + 1)
+
+/* TODO: Refactor. */
+#define RESTARTABLE(_cmd, _result) do { \
+ do { \
+ _result = _cmd; \
+ } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+/* This is one of the rare times it's more portable to declare an
+ * external symbol explicitly, rather than via a system header.
+ * The declaration is standardized as part of UNIX98, but there is
+ * no standard (not even de-facto) header file where the
+ * declaration is to be found. See:
+ * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
+ *
+ * "All identifiers in this volume of IEEE Std 1003.1-2001, except
+ * environ, are defined in at least one of the headers" (!)
+ */
+extern char **environ;
+
+
+static void
+setSIGCHLDHandler(JNIEnv *env)
+{
+ /* There is a subtle difference between having the signal handler
+ * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
+ * termination information for child processes if the signal
+ * handler is SIG_IGN. It must be SIG_DFL.
+ *
+ * We used to set the SIGCHLD handler only on Linux, but it's
+ * safest to set it unconditionally.
+ *
+ * Consider what happens if java's parent process sets the SIGCHLD
+ * handler to SIG_IGN. Normally signal handlers are inherited by
+ * children, but SIGCHLD is a controversial case. Solaris appears
+ * to always reset it to SIG_DFL, but this behavior may be
+ * non-standard-compliant, and we shouldn't rely on it.
+ *
+ * References:
+ * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
+ * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
+ */
+ struct sigaction sa;
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
+ if (sigaction(SIGCHLD, &sa, NULL) < 0)
+ JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
+}
+
+static void*
+xmalloc(JNIEnv *env, size_t size)
+{
+ void *p = malloc(size);
+ if (p == NULL)
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return p;
+}
+
+#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
+
+/**
+ * If PATH is not defined, the OS provides some default value.
+ * Unfortunately, there's no portable way to get this value.
+ * Fortunately, it's only needed if the child has PATH while we do not.
+ */
+static const char*
+defaultPath(void)
+{
+#ifdef __solaris__
+ /* These really are the Solaris defaults! */
+ return (geteuid() == 0 || getuid() == 0) ?
+ "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
+ "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
+#else
+ return ":/bin:/usr/bin"; /* glibc */
+#endif
+}
+
+static const char*
+effectivePath(void)
+{
+ const char *s = getenv("PATH");
+ return (s != NULL) ? s : defaultPath();
+}
+
+static int
+countOccurrences(const char *s, char c)
+{
+ int count;
+ for (count = 0; *s != '\0'; s++)
+ count += (*s == c);
+ return count;
+}
+
+static const char * const *
+splitPath(JNIEnv *env, const char *path)
+{
+ const char *p, *q;
+ char **pathv;
+ int i;
+ int count = countOccurrences(path, ':') + 1;
+
+ pathv = NEW(char*, count+1);
+ pathv[count] = NULL;
+ for (p = path, i = 0; i < count; i++, p = q + 1) {
+ for (q = p; (*q != ':') && (*q != '\0'); q++)
+ ;
+ if (q == p) /* empty PATH component => "." */
+ pathv[i] = "./";
+ else {
+ int addSlash = ((*(q - 1)) != '/');
+ pathv[i] = NEW(char, q - p + addSlash + 1);
+ memcpy(pathv[i], p, q - p);
+ if (addSlash)
+ pathv[i][q - p] = '/';
+ pathv[i][q - p + addSlash] = '\0';
+ }
+ }
+ return (const char * const *) pathv;
+}
+
+/**
+ * Cached value of JVM's effective PATH.
+ * (We don't support putenv("PATH=...") in native code)
+ */
+static const char *parentPath;
+
+/**
+ * Split, canonicalized version of parentPath
+ */
+static const char * const *parentPathv;
+
+static jfieldID field_exitcode;
+
+JNIEXPORT void JNICALL
+Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz)
+{
+ field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I");
+
+ parentPath = effectivePath();
+ parentPathv = splitPath(env, parentPath);
+
+ setSIGCHLDHandler(env);
+}
+
+
+#ifndef WIFEXITED
+#define WIFEXITED(status) (((status)&0xFF) == 0)
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(status) (((status)>>8)&0xFF)
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(status) ((status)&0x7F)
+#endif
+
+/* Block until a child process exits and return its exit code.
+ Note, can only be called once for any given pid. */
+JNIEXPORT jint JNICALL
+Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
+ jobject junk,
+ jint pid)
+{
+ /* We used to use waitid() on Solaris, waitpid() on Linux, but
+ * waitpid() is more standard, so use it on all POSIX platforms. */
+ int status;
+ /* Wait for the child process to exit. This returns immediately if
+ the child has already exited. */
+ while (waitpid(pid, &status, 0) < 0) {
+ switch (errno) {
+ case ECHILD: return 0;
+ case EINTR: break;
+ default: return -1;
+ }
+ }
+
+ if (WIFEXITED(status)) {
+ /*
+ * The child exited normally; get its exit code.
+ */
+ return WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ /* The child exited because of a signal.
+ * The best value to return is 0x80 + signal number,
+ * because that is what all Unix shells do, and because
+ * it allows callers to distinguish between process exit and
+ * process death by signal.
+ * Unfortunately, the historical behavior on Solaris is to return
+ * the signal number, and we preserve this for compatibility. */
+#ifdef __solaris__
+ return WTERMSIG(status);
+#else
+ return 0x80 + WTERMSIG(status);
+#endif
+ } else {
+ /*
+ * Unknown exit code; pass it through.
+ */
+ return status;
+ }
+}
+
+static ssize_t
+restartableWrite(int fd, const void *buf, size_t count)
+{
+ ssize_t result;
+ RESTARTABLE(write(fd, buf, count), result);
+ return result;
+}
+
+static int
+restartableDup2(int fd_from, int fd_to)
+{
+ int err;
+ RESTARTABLE(dup2(fd_from, fd_to), err);
+ return err;
+}
+
+static int
+restartableClose(int fd)
+{
+ int err;
+ RESTARTABLE(close(fd), err);
+ return err;
+}
+
+static int
+closeSafely(int fd)
+{
+ return (fd == -1) ? 0 : restartableClose(fd);
+}
+
+static int
+isAsciiDigit(char c)
+{
+ return c >= '0' && c <= '9';
+}
+
+#ifdef _ALLBSD_SOURCE
+#define FD_DIR "/dev/fd"
+#define dirent64 dirent
+#define readdir64 readdir
+#else
+#define FD_DIR "/proc/self/fd"
+#endif
+
+static int
+closeDescriptors(void)
+{
+ DIR *dp;
+ struct dirent64 *dirp;
+ int from_fd = FAIL_FILENO + 1;
+
+ /* We're trying to close all file descriptors, but opendir() might
+ * itself be implemented using a file descriptor, and we certainly
+ * don't want to close that while it's in use. We assume that if
+ * opendir() is implemented using a file descriptor, then it uses
+ * the lowest numbered file descriptor, just like open(). So we
+ * close a couple explicitly. */
+
+ restartableClose(from_fd); /* for possible use by opendir() */
+ restartableClose(from_fd + 1); /* another one for good luck */
+
+ if ((dp = opendir(FD_DIR)) == NULL)
+ return 0;
+
+ /* We use readdir64 instead of readdir to work around Solaris bug
+ * 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9
+ */
+ while ((dirp = readdir64(dp)) != NULL) {
+ int fd;
+ if (isAsciiDigit(dirp->d_name[0]) &&
+ (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2)
+ restartableClose(fd);
+ }
+
+ closedir(dp);
+
+ return 1;
+}
+
+static int
+moveDescriptor(int fd_from, int fd_to)
+{
+ if (fd_from != fd_to) {
+ if ((restartableDup2(fd_from, fd_to) == -1) ||
+ (restartableClose(fd_from) == -1))
+ return -1;
+ }
+ return 0;
+}
+
+static const char *
+getBytes(JNIEnv *env, jbyteArray arr)
+{
+ return arr == NULL ? NULL :
+ (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
+}
+
+static void
+releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
+{
+ if (parr != NULL)
+ (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
+}
+
+static void
+initVectorFromBlock(const char**vector, const char* block, int count)
+{
+ int i;
+ const char *p;
+ for (i = 0, p = block; i < count; i++) {
+ /* Invariant: p always points to the start of a C string. */
+ vector[i] = p;
+ while (*(p++));
+ }
+ vector[count] = NULL;
+}
+
+static void
+throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
+{
+ static const char * const format = "error=%d, %s";
+ const char *detail = defaultDetail;
+ char *errmsg;
+ jstring s;
+
+ if (errnum != 0) {
+ const char *s = strerror(errnum);
+ if (strcmp(s, "Unknown error") != 0)
+ detail = s;
+ }
+ /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
+ errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
+ sprintf(errmsg, format, errnum, detail);
+ s = JNU_NewStringPlatform(env, errmsg);
+ if (s != NULL) {
+ jobject x = JNU_NewObjectByName(env, "java/io/IOException",
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL)
+ (*env)->Throw(env, x);
+ }
+ free(errmsg);
+}
+
+#ifdef DEBUG_PROCESS
+/* Debugging process code is difficult; where to write debug output? */
+static void
+debugPrint(char *format, ...)
+{
+ FILE *tty = fopen("/dev/tty", "w");
+ va_list ap;
+ va_start(ap, format);
+ vfprintf(tty, format, ap);
+ va_end(ap);
+ fclose(tty);
+}
+#endif /* DEBUG_PROCESS */
+
+/**
+ * Exec FILE as a traditional Bourne shell script (i.e. one without #!).
+ * If we could do it over again, we would probably not support such an ancient
+ * misfeature, but compatibility wins over sanity. The original support for
+ * this was imported accidentally from execvp().
+ */
+static void
+execve_as_traditional_shell_script(const char *file,
+ const char *argv[],
+ const char *const envp[])
+{
+ /* Use the extra word of space provided for us in argv by caller. */
+ const char *argv0 = argv[0];
+ const char *const *end = argv;
+ while (*end != NULL)
+ ++end;
+ memmove(argv+2, argv+1, (end-argv) * sizeof (*end));
+ argv[0] = "/bin/sh";
+ argv[1] = file;
+ execve(argv[0], (char **) argv, (char **) envp);
+ /* Can't even exec /bin/sh? Big trouble, but let's soldier on... */
+ memmove(argv+1, argv+2, (end-argv) * sizeof (*end));
+ argv[0] = argv0;
+}
+
+/**
+ * Like execve(2), except that in case of ENOEXEC, FILE is assumed to
+ * be a shell script and the system default shell is invoked to run it.
+ */
+static void
+execve_with_shell_fallback(const char *file,
+ const char *argv[],
+ const char *const envp[])
+{
+#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK
+ /* shared address space; be very careful. */
+ execve(file, (char **) argv, (char **) envp);
+ if (errno == ENOEXEC)
+ execve_as_traditional_shell_script(file, argv, envp);
+#else
+ /* unshared address space; we can mutate environ. */
+ environ = (char **) envp;
+ execvp(file, (char **) argv);
+#endif
+}
+
+/**
+ * 'execvpe' should have been included in the Unix standards,
+ * and is a GNU extension in glibc 2.10.
+ *
+ * JDK_execvpe is identical to execvp, except that the child environment is
+ * specified via the 3rd argument instead of being inherited from environ.
+ */
+static void
+JDK_execvpe(const char *file,
+ const char *argv[],
+ const char *const envp[])
+{
+ if (envp == NULL || (char **) envp == environ) {
+ execvp(file, (char **) argv);
+ return;
+ }
+
+ if (*file == '\0') {
+ errno = ENOENT;
+ return;
+ }
+
+ if (strchr(file, '/') != NULL) {
+ execve_with_shell_fallback(file, argv, envp);
+ } else {
+ /* We must search PATH (parent's, not child's) */
+ char expanded_file[PATH_MAX];
+ int filelen = strlen(file);
+ int sticky_errno = 0;
+ const char * const * dirs;
+ for (dirs = parentPathv; *dirs; dirs++) {
+ const char * dir = *dirs;
+ int dirlen = strlen(dir);
+ if (filelen + dirlen + 1 >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ continue;
+ }
+ memcpy(expanded_file, dir, dirlen);
+ memcpy(expanded_file + dirlen, file, filelen);
+ expanded_file[dirlen + filelen] = '\0';
+ execve_with_shell_fallback(expanded_file, argv, envp);
+ /* There are 3 responses to various classes of errno:
+ * return immediately, continue (especially for ENOENT),
+ * or continue with "sticky" errno.
+ *
+ * From exec(3):
+ *
+ * If permission is denied for a file (the attempted
+ * execve returned EACCES), these functions will continue
+ * searching the rest of the search path. If no other
+ * file is found, however, they will return with the
+ * global variable errno set to EACCES.
+ */
+ switch (errno) {
+ case EACCES:
+ sticky_errno = errno;
+ /* FALLTHRU */
+ case ENOENT:
+ case ENOTDIR:
+#ifdef ELOOP
+ case ELOOP:
+#endif
+#ifdef ESTALE
+ case ESTALE:
+#endif
+#ifdef ENODEV
+ case ENODEV:
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT:
+#endif
+ break; /* Try other directories in PATH */
+ default:
+ return;
+ }
+ }
+ if (sticky_errno != 0)
+ errno = sticky_errno;
+ }
+}
+
+/*
+ * Reads nbyte bytes from file descriptor fd into buf,
+ * The read operation is retried in case of EINTR or partial reads.
+ *
+ * Returns number of bytes read (normally nbyte, but may be less in
+ * case of EOF). In case of read errors, returns -1 and sets errno.
+ */
+static ssize_t
+readFully(int fd, void *buf, size_t nbyte)
+{
+ ssize_t remaining = nbyte;
+ for (;;) {
+ ssize_t n = read(fd, buf, remaining);
+ if (n == 0) {
+ return nbyte - remaining;
+ } else if (n > 0) {
+ remaining -= n;
+ if (remaining <= 0)
+ return nbyte;
+ /* We were interrupted in the middle of reading the bytes.
+ * Unlikely, but possible. */
+ buf = (void *) (((char *)buf) + n);
+ } else if (errno == EINTR) {
+ /* Strange signals like SIGJVM1 are possible at any time.
+ * See http://www.dreamsongs.com/WorseIsBetter.html */
+ } else {
+ return -1;
+ }
+ }
+}
+
+typedef struct _ChildStuff
+{
+ int in[2];
+ int out[2];
+ int err[2];
+ int fail[2];
+ int fds[3];
+ const char **argv;
+ const char **envv;
+ const char *pdir;
+ jboolean redirectErrorStream;
+#if START_CHILD_USE_CLONE
+ void *clone_stack;
+#endif
+} ChildStuff;
+
+static void
+copyPipe(int from[2], int to[2])
+{
+ to[0] = from[0];
+ to[1] = from[1];
+}
+
+/**
+ * Child process after a successful fork() or clone().
+ * This function must not return, and must be prepared for either all
+ * of its address space to be shared with its parent, or to be a copy.
+ * It must not modify global variables such as "environ".
+ */
+static int
+childProcess(void *arg)
+{
+ const ChildStuff* p = (const ChildStuff*) arg;
+
+ /* Close the parent sides of the pipes.
+ Closing pipe fds here is redundant, since closeDescriptors()
+ would do it anyways, but a little paranoia is a good thing. */
+ if ((closeSafely(p->in[1]) == -1) ||
+ (closeSafely(p->out[0]) == -1) ||
+ (closeSafely(p->err[0]) == -1) ||
+ (closeSafely(p->fail[0]) == -1))
+ goto WhyCantJohnnyExec;
+
+ /* Give the child sides of the pipes the right fileno's. */
+ /* Note: it is possible for in[0] == 0 */
+ if ((moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0],
+ STDIN_FILENO) == -1) ||
+ (moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1],
+ STDOUT_FILENO) == -1))
+ goto WhyCantJohnnyExec;
+
+ if (p->redirectErrorStream) {
+ if ((closeSafely(p->err[1]) == -1) ||
+ (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1))
+ goto WhyCantJohnnyExec;
+ } else {
+ if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2],
+ STDERR_FILENO) == -1)
+ goto WhyCantJohnnyExec;
+ }
+
+ if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1)
+ goto WhyCantJohnnyExec;
+
+ /* close everything */
+ if (closeDescriptors() == 0) { /* failed, close the old way */
+ int max_fd = (int)sysconf(_SC_OPEN_MAX);
+ int fd;
+ for (fd = FAIL_FILENO + 1; fd < max_fd; fd++)
+ if (restartableClose(fd) == -1 && errno != EBADF)
+ goto WhyCantJohnnyExec;
+ }
+
+ /* change to the new working directory */
+ if (p->pdir != NULL && chdir(p->pdir) < 0)
+ goto WhyCantJohnnyExec;
+
+ if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1)
+ goto WhyCantJohnnyExec;
+
+ JDK_execvpe(p->argv[0], p->argv, p->envv);
+
+ WhyCantJohnnyExec:
+ /* We used to go to an awful lot of trouble to predict whether the
+ * child would fail, but there is no reliable way to predict the
+ * success of an operation without *trying* it, and there's no way
+ * to try a chdir or exec in the parent. Instead, all we need is a
+ * way to communicate any failure back to the parent. Easy; we just
+ * send the errno back to the parent over a pipe in case of failure.
+ * The tricky thing is, how do we communicate the *success* of exec?
+ * We use FD_CLOEXEC together with the fact that a read() on a pipe
+ * yields EOF when the write ends (we have two of them!) are closed.
+ */
+ {
+ int errnum = errno;
+ restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum));
+ }
+ restartableClose(FAIL_FILENO);
+ _exit(-1);
+ return 0; /* Suppress warning "no return value from function" */
+}
+
+/**
+ * Start a child process running function childProcess.
+ * This function only returns in the parent.
+ * We are unusually paranoid; use of clone/vfork is
+ * especially likely to tickle gcc/glibc bugs.
+ */
+#ifdef __attribute_noinline__ /* See: sys/cdefs.h */
+__attribute_noinline__
+#endif
+static pid_t
+startChild(ChildStuff *c) {
+#if START_CHILD_USE_CLONE
+#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
+ /*
+ * See clone(2).
+ * Instead of worrying about which direction the stack grows, just
+ * allocate twice as much and start the stack in the middle.
+ */
+ if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
+ /* errno will be set to ENOMEM */
+ return -1;
+ return clone(childProcess,
+ c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
+ CLONE_VFORK | CLONE_VM | SIGCHLD, c);
+#else
+ #if START_CHILD_USE_VFORK
+ /*
+ * We separate the call to vfork into a separate function to make
+ * very sure to keep stack of child from corrupting stack of parent,
+ * as suggested by the scary gcc warning:
+ * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
+ */
+ volatile pid_t resultPid = vfork();
+ #else
+ /*
+ * From Solaris fork(2): In Solaris 10, a call to fork() is
+ * identical to a call to fork1(); only the calling thread is
+ * replicated in the child process. This is the POSIX-specified
+ * behavior for fork().
+ */
+ pid_t resultPid = fork();
+ #endif
+ if (resultPid == 0)
+ childProcess(c);
+ assert(resultPid != 0); /* childProcess never returns */
+ return resultPid;
+#endif /* ! START_CHILD_USE_CLONE */
+}
+
+JNIEXPORT jint JNICALL
+Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
+ jobject process,
+ jbyteArray prog,
+ jbyteArray argBlock, jint argc,
+ jbyteArray envBlock, jint envc,
+ jbyteArray dir,
+ jintArray std_fds,
+ jboolean redirectErrorStream)
+{
+ int errnum;
+ int resultPid = -1;
+ int in[2], out[2], err[2], fail[2];
+ jint *fds = NULL;
+ const char *pprog = NULL;
+ const char *pargBlock = NULL;
+ const char *penvBlock = NULL;
+ ChildStuff *c;
+
+ in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
+
+ if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
+ c->argv = NULL;
+ c->envv = NULL;
+ c->pdir = NULL;
+#if START_CHILD_USE_CLONE
+ c->clone_stack = NULL;
+#endif
+
+ /* Convert prog + argBlock into a char ** argv.
+ * Add one word room for expansion of argv for use by
+ * execve_as_traditional_shell_script.
+ */
+ assert(prog != NULL && argBlock != NULL);
+ if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
+ if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
+ if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
+ c->argv[0] = pprog;
+ initVectorFromBlock(c->argv+1, pargBlock, argc);
+
+ if (envBlock != NULL) {
+ /* Convert envBlock into a char ** envv */
+ if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch;
+ if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
+ initVectorFromBlock(c->envv, penvBlock, envc);
+ }
+
+ if (dir != NULL) {
+ if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
+ }
+
+ assert(std_fds != NULL);
+ fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
+ if (fds == NULL) goto Catch;
+
+ if ((fds[0] == -1 && pipe(in) < 0) ||
+ (fds[1] == -1 && pipe(out) < 0) ||
+ (fds[2] == -1 && pipe(err) < 0) ||
+ (pipe(fail) < 0)) {
+ throwIOException(env, errno, "Bad file descriptor");
+ goto Catch;
+ }
+ c->fds[0] = fds[0];
+ c->fds[1] = fds[1];
+ c->fds[2] = fds[2];
+
+ copyPipe(in, c->in);
+ copyPipe(out, c->out);
+ copyPipe(err, c->err);
+ copyPipe(fail, c->fail);
+
+ c->redirectErrorStream = redirectErrorStream;
+
+ resultPid = startChild(c);
+ assert(resultPid != 0);
+
+ if (resultPid < 0) {
+ throwIOException(env, errno, START_CHILD_SYSTEM_CALL " failed");
+ goto Catch;
+ }
+
+ restartableClose(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */
+
+ switch (readFully(fail[0], &errnum, sizeof(errnum))) {
+ case 0: break; /* Exec succeeded */
+ case sizeof(errnum):
+ waitpid(resultPid, NULL, 0);
+ throwIOException(env, errnum, "Exec failed");
+ goto Catch;
+ default:
+ throwIOException(env, errno, "Read failed");
+ goto Catch;
+ }
+
+ fds[0] = (in [1] != -1) ? in [1] : -1;
+ fds[1] = (out[0] != -1) ? out[0] : -1;
+ fds[2] = (err[0] != -1) ? err[0] : -1;
+
+ Finally:
+#if START_CHILD_USE_CLONE
+ free(c->clone_stack);
+#endif
+
+ /* Always clean up the child's side of the pipes */
+ closeSafely(in [0]);
+ closeSafely(out[1]);
+ closeSafely(err[1]);
+
+ /* Always clean up fail descriptors */
+ closeSafely(fail[0]);
+ closeSafely(fail[1]);
+
+ releaseBytes(env, prog, pprog);
+ releaseBytes(env, argBlock, pargBlock);
+ releaseBytes(env, envBlock, penvBlock);
+ releaseBytes(env, dir, c->pdir);
+
+ free(c->argv);
+ free(c->envv);
+ free(c);
+
+ if (fds != NULL)
+ (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
+
+ return resultPid;
+
+ Catch:
+ /* Clean up the parent's side of the pipes in case of failure only */
+ closeSafely(in [1]);
+ closeSafely(out[0]);
+ closeSafely(err[0]);
+ goto Finally;
+}
+
+JNIEXPORT void JNICALL
+Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid)
+{
+ kill(pid, SIGTERM);
+}
diff --git a/ojluni/src/main/native/UnixFileSystem_md.c b/ojluni/src/main/native/UnixFileSystem_md.c
new file mode 100755
index 0000000..4309ffb
--- /dev/null
+++ b/ojluni/src/main/native/UnixFileSystem_md.c
@@ -0,0 +1,455 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+#include "io_util.h"
+#include "io_util_md.h"
+#include "java_io_FileSystem.h"
+#include "java_io_UnixFileSystem.h"
+
+#if defined(_ALLBSD_SOURCE)
+#define dirent64 dirent
+#define readdir64_r readdir_r
+#define stat64 stat
+#define statvfs64 statvfs
+#endif
+
+/* -- Field IDs -- */
+
+static struct {
+ jfieldID path;
+} ids;
+
+
+JNIEXPORT void JNICALL
+Java_java_io_UnixFileSystem_initIDs(JNIEnv *env, jclass cls)
+{
+ jclass fileClass = (*env)->FindClass(env, "java/io/File");
+ if (!fileClass) return;
+ ids.path = (*env)->GetFieldID(env, fileClass,
+ "path", "Ljava/lang/String;");
+}
+
+/* -- Path operations -- */
+
+extern int canonicalize(char *path, const char *out, int len);
+
+JNIEXPORT jstring JNICALL
+Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
+ jstring pathname)
+{
+ jstring rv = NULL;
+
+ WITH_PLATFORM_STRING(env, pathname, path) {
+ char canonicalPath[JVM_MAXPATHLEN];
+ if (canonicalize(JVM_NativePath((char *)path),
+ canonicalPath, JVM_MAXPATHLEN) < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
+ } else {
+#ifdef MACOSX
+ rv = newStringPlatform(env, canonicalPath);
+#else
+ rv = JNU_NewStringPlatform(env, canonicalPath);
+#endif
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+/* -- Attribute accessors -- */
+
+
+static jboolean
+statMode(const char *path, int *mode)
+{
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ *mode = sb.st_mode;
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+
+JNIEXPORT jint JNICALL
+Java_java_io_UnixFileSystem_getBooleanAttributes0(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jint rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ int mode;
+ if (statMode(path, &mode)) {
+ int fmt = mode & S_IFMT;
+ rv = (jint) (java_io_FileSystem_BA_EXISTS
+ | ((fmt == S_IFREG) ? java_io_FileSystem_BA_REGULAR : 0)
+ | ((fmt == S_IFDIR) ? java_io_FileSystem_BA_DIRECTORY : 0));
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_checkAccess(JNIEnv *env, jobject this,
+ jobject file, jint a)
+{
+ jboolean rv = JNI_FALSE;
+ int mode = 0;
+ switch (a) {
+ case java_io_FileSystem_ACCESS_READ:
+ mode = R_OK;
+ break;
+ case java_io_FileSystem_ACCESS_WRITE:
+ mode = W_OK;
+ break;
+ case java_io_FileSystem_ACCESS_EXECUTE:
+ mode = X_OK;
+ break;
+ default: assert(0);
+ }
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (access(path, mode) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setPermission(JNIEnv *env, jobject this,
+ jobject file,
+ jint access,
+ jboolean enable,
+ jboolean owneronly)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ int amode = 0;
+ int mode;
+ switch (access) {
+ case java_io_FileSystem_ACCESS_READ:
+ if (owneronly)
+ amode = S_IRUSR;
+ else
+ amode = S_IRUSR | S_IRGRP | S_IROTH;
+ break;
+ case java_io_FileSystem_ACCESS_WRITE:
+ if (owneronly)
+ amode = S_IWUSR;
+ else
+ amode = S_IWUSR | S_IWGRP | S_IWOTH;
+ break;
+ case java_io_FileSystem_ACCESS_EXECUTE:
+ if (owneronly)
+ amode = S_IXUSR;
+ else
+ amode = S_IXUSR | S_IXGRP | S_IXOTH;
+ break;
+ default:
+ assert(0);
+ }
+ if (statMode(path, &mode)) {
+ if (enable)
+ mode |= amode;
+ else
+ mode &= ~amode;
+ if (chmod(path, mode) >= 0) {
+ rv = JNI_TRUE;
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jlong rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ rv = 1000 * (jlong)sb.st_mtime;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getLength(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jlong rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ rv = sb.st_size;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+/* -- File operations -- */
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
+ jstring pathname)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_PLATFORM_STRING(env, pathname, path) {
+ int fd;
+ if (!strcmp (path, "/")) {
+ fd = JVM_EEXIST; /* The root directory always exists */
+ } else {
+ fd = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
+ }
+ if (fd < 0) {
+ if (fd != JVM_EEXIST) {
+ JNU_ThrowIOExceptionWithLastError(env, path);
+ }
+ } else {
+ JVM_Close(fd);
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_delete0(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (remove(path) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
+ jobject file)
+{
+ DIR *dir = NULL;
+ struct dirent64 *ptr;
+ struct dirent64 *result;
+ int len, maxlen;
+ jobjectArray rv, old;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ dir = opendir(path);
+ } END_PLATFORM_STRING(env, path);
+ if (dir == NULL) return NULL;
+
+ ptr = malloc(sizeof(struct dirent64) + (PATH_MAX + 1));
+ if (ptr == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+ closedir(dir);
+ return NULL;
+ }
+
+ /* Allocate an initial String array */
+ len = 0;
+ maxlen = 16;
+ rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
+ if (rv == NULL) goto error;
+
+ /* Scan the directory */
+ while ((readdir64_r(dir, ptr, &result) == 0) && (result != NULL)) {
+ jstring name;
+ if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))
+ continue;
+ if (len == maxlen) {
+ old = rv;
+ rv = (*env)->NewObjectArray(env, maxlen <<= 1,
+ JNU_ClassString(env), NULL);
+ if (rv == NULL) goto error;
+ if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
+ (*env)->DeleteLocalRef(env, old);
+ }
+#ifdef MACOSX
+ name = newStringPlatform(env, ptr->d_name);
+#else
+ name = JNU_NewStringPlatform(env, ptr->d_name);
+#endif
+ if (name == NULL) goto error;
+ (*env)->SetObjectArrayElement(env, rv, len++, name);
+ (*env)->DeleteLocalRef(env, name);
+ }
+ closedir(dir);
+ free(ptr);
+
+ /* Copy the final results into an appropriately-sized array */
+ old = rv;
+ rv = (*env)->NewObjectArray(env, len, JNU_ClassString(env), NULL);
+ if (rv == NULL) {
+ return NULL;
+ }
+ if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
+ return NULL;
+ }
+ return rv;
+
+ error:
+ closedir(dir);
+ free(ptr);
+ return NULL;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (mkdir(path, 0777) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
+ jobject from, jobject to)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
+ WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
+ if (rename(fromPath, toPath) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, toPath);
+ } END_PLATFORM_STRING(env, fromPath);
+ return rv;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
+ jobject file, jlong time)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+
+ if (stat64(path, &sb) == 0) {
+ struct timeval tv[2];
+
+ /* Preserve access time */
+ tv[0].tv_sec = sb.st_atime;
+ tv[0].tv_usec = 0;
+
+ /* Change last-modified time */
+ tv[1].tv_sec = time / 1000;
+ tv[1].tv_usec = (time % 1000) * 1000;
+
+ if (utimes(path, tv) == 0)
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setReadOnly(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ int mode;
+ if (statMode(path, &mode)) {
+ if (chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)) >= 0) {
+ rv = JNI_TRUE;
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
+ jobject file, jint t)
+{
+ jlong rv = 0L;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct statvfs64 fsstat;
+ memset(&fsstat, 0, sizeof(fsstat));
+ if (statvfs64(path, &fsstat) == 0) {
+ switch(t) {
+ case java_io_FileSystem_SPACE_TOTAL:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_blocks));
+ break;
+ case java_io_FileSystem_SPACE_FREE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_bfree));
+ break;
+ case java_io_FileSystem_SPACE_USABLE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_bavail));
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
diff --git a/ojluni/src/main/native/canonicalize_md.c b/ojluni/src/main/native/canonicalize_md.c
new file mode 100755
index 0000000..b78cc2d
--- /dev/null
+++ b/ojluni/src/main/native/canonicalize_md.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Pathname canonicalization for Unix file systems
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#if !defined(_ALLBSD_SOURCE)
+#include <alloca.h>
+#endif
+
+
+/* Note: The comments in this file use the terminology
+ defined in the java.io.File class */
+
+
+/* Check the given name sequence to see if it can be further collapsed.
+ Return zero if not, otherwise return the number of names in the sequence. */
+
+static int
+collapsible(char *names)
+{
+ char *p = names;
+ int dots = 0, n = 0;
+
+ while (*p) {
+ if ((p[0] == '.') && ((p[1] == '\0')
+ || (p[1] == '/')
+ || ((p[1] == '.') && ((p[2] == '\0')
+ || (p[2] == '/'))))) {
+ dots = 1;
+ }
+ n++;
+ while (*p) {
+ if (*p == '/') {
+ p++;
+ break;
+ }
+ p++;
+ }
+ }
+ return (dots ? n : 0);
+}
+
+
+/* Split the names in the given name sequence,
+ replacing slashes with nulls and filling in the given index array */
+
+static void
+splitNames(char *names, char **ix)
+{
+ char *p = names;
+ int i = 0;
+
+ while (*p) {
+ ix[i++] = p++;
+ while (*p) {
+ if (*p == '/') {
+ *p++ = '\0';
+ break;
+ }
+ p++;
+ }
+ }
+}
+
+
+/* Join the names in the given name sequence, ignoring names whose index
+ entries have been cleared and replacing nulls with slashes as needed */
+
+static void
+joinNames(char *names, int nc, char **ix)
+{
+ int i;
+ char *p;
+
+ for (i = 0, p = names; i < nc; i++) {
+ if (!ix[i]) continue;
+ if (i > 0) {
+ p[-1] = '/';
+ }
+ if (p == ix[i]) {
+ p += strlen(p) + 1;
+ } else {
+ char *q = ix[i];
+ while ((*p++ = *q++));
+ }
+ }
+ *p = '\0';
+}
+
+
+/* Collapse "." and ".." names in the given path wherever possible.
+ A "." name may always be eliminated; a ".." name may be eliminated if it
+ follows a name that is neither "." nor "..". This is a syntactic operation
+ that performs no filesystem queries, so it should only be used to cleanup
+ after invoking the realpath() procedure. */
+
+static void
+collapse(char *path)
+{
+ char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
+ int nc;
+ char **ix;
+ int i, j;
+ char *p, *q;
+
+ nc = collapsible(names);
+ if (nc < 2) return; /* Nothing to do */
+ ix = (char **)alloca(nc * sizeof(char *));
+ splitNames(names, ix);
+
+ for (i = 0; i < nc; i++) {
+ int dots = 0;
+
+ /* Find next occurrence of "." or ".." */
+ do {
+ char *p = ix[i];
+ if (p[0] == '.') {
+ if (p[1] == '\0') {
+ dots = 1;
+ break;
+ }
+ if ((p[1] == '.') && (p[2] == '\0')) {
+ dots = 2;
+ break;
+ }
+ }
+ i++;
+ } while (i < nc);
+ if (i >= nc) break;
+
+ /* At this point i is the index of either a "." or a "..", so take the
+ appropriate action and then continue the outer loop */
+ if (dots == 1) {
+ /* Remove this instance of "." */
+ ix[i] = 0;
+ }
+ else {
+ /* If there is a preceding name, remove both that name and this
+ instance of ".."; otherwise, leave the ".." as is */
+ for (j = i - 1; j >= 0; j--) {
+ if (ix[j]) break;
+ }
+ if (j < 0) continue;
+ ix[j] = 0;
+ ix[i] = 0;
+ }
+ /* i will be incremented at the top of the loop */
+ }
+
+ joinNames(names, nc, ix);
+}
+
+
+/* Convert a pathname to canonical form. The input path is assumed to contain
+ no duplicate slashes. On Solaris we can use realpath() to do most of the
+ work, though once that's done we still must collapse any remaining "." and
+ ".." names by hand. */
+
+int
+canonicalize(char *original, char *resolved, int len)
+{
+ if (len < PATH_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (strlen(original) > PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* First try realpath() on the entire path */
+ if (realpath(original, resolved)) {
+ /* That worked, so return it */
+ collapse(resolved);
+ return 0;
+ }
+ else {
+ /* Something's bogus in the original path, so remove names from the end
+ until either some subpath works or we run out of names */
+ char *p, *end, *r = NULL;
+ char path[PATH_MAX + 1];
+
+ strncpy(path, original, sizeof(path));
+ if (path[PATH_MAX] != '\0') {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ end = path + strlen(path);
+
+ for (p = end; p > path;) {
+
+ /* Skip last element */
+ while ((--p > path) && (*p != '/'));
+ if (p == path) break;
+
+ /* Try realpath() on this subpath */
+ *p = '\0';
+ r = realpath(path, resolved);
+ *p = (p == end) ? '\0' : '/';
+
+ if (r != NULL) {
+ /* The subpath has a canonical path */
+ break;
+ }
+ else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES) {
+ /* If the lookup of a particular subpath fails because the file
+ does not exist, because it is of the wrong type, or because
+ access is denied, then remove its last name and try again.
+ Other I/O problems cause an error return. */
+ continue;
+ }
+ else {
+ return -1;
+ }
+ }
+
+ if (r != NULL) {
+ /* Append unresolved subpath to resolved subpath */
+ int rn = strlen(r);
+ if (rn + (int)strlen(p) >= len) {
+ /* Buffer overflow */
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ if ((rn > 0) && (r[rn - 1] == '/') && (*p == '/')) {
+ /* Avoid duplicate slashes */
+ p++;
+ }
+ strcpy(r + rn, p);
+ collapse(r);
+ return 0;
+ }
+ else {
+ /* Nothing resolved, so just return the original path */
+ strcpy(resolved, path);
+ collapse(resolved);
+ return 0;
+ }
+ }
+
+}
diff --git a/ojluni/src/main/native/classfile_constants.h b/ojluni/src/main/native/classfile_constants.h
new file mode 100755
index 0000000..861576e
--- /dev/null
+++ b/ojluni/src/main/native/classfile_constants.h
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef CLASSFILE_CONSTANTS_H
+#define CLASSFILE_CONSTANTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Classfile version number for this information */
+#define JVM_CLASSFILE_MAJOR_VERSION 51
+#define JVM_CLASSFILE_MINOR_VERSION 0
+
+/* Flags */
+
+enum {
+ JVM_ACC_PUBLIC = 0x0001,
+ JVM_ACC_PRIVATE = 0x0002,
+ JVM_ACC_PROTECTED = 0x0004,
+ JVM_ACC_STATIC = 0x0008,
+ JVM_ACC_FINAL = 0x0010,
+ JVM_ACC_SYNCHRONIZED = 0x0020,
+ JVM_ACC_SUPER = 0x0020,
+ JVM_ACC_VOLATILE = 0x0040,
+ JVM_ACC_BRIDGE = 0x0040,
+ JVM_ACC_TRANSIENT = 0x0080,
+ JVM_ACC_VARARGS = 0x0080,
+ JVM_ACC_NATIVE = 0x0100,
+ JVM_ACC_INTERFACE = 0x0200,
+ JVM_ACC_ABSTRACT = 0x0400,
+ JVM_ACC_STRICT = 0x0800,
+ JVM_ACC_SYNTHETIC = 0x1000,
+ JVM_ACC_ANNOTATION = 0x2000,
+ JVM_ACC_ENUM = 0x4000
+};
+
+/* Used in newarray instruction. */
+
+enum {
+ JVM_T_BOOLEAN = 4,
+ JVM_T_CHAR = 5,
+ JVM_T_FLOAT = 6,
+ JVM_T_DOUBLE = 7,
+ JVM_T_BYTE = 8,
+ JVM_T_SHORT = 9,
+ JVM_T_INT = 10,
+ JVM_T_LONG = 11
+};
+
+/* Constant Pool Entries */
+
+enum {
+ JVM_CONSTANT_Utf8 = 1,
+ JVM_CONSTANT_Unicode = 2, /* unused */
+ JVM_CONSTANT_Integer = 3,
+ JVM_CONSTANT_Float = 4,
+ JVM_CONSTANT_Long = 5,
+ JVM_CONSTANT_Double = 6,
+ JVM_CONSTANT_Class = 7,
+ JVM_CONSTANT_String = 8,
+ JVM_CONSTANT_Fieldref = 9,
+ JVM_CONSTANT_Methodref = 10,
+ JVM_CONSTANT_InterfaceMethodref = 11,
+ JVM_CONSTANT_NameAndType = 12,
+ JVM_CONSTANT_MethodHandle = 15, // JSR 292
+ JVM_CONSTANT_MethodType = 16, // JSR 292
+ JVM_CONSTANT_InvokeDynamic = 18
+};
+
+/* JVM_CONSTANT_MethodHandle subtypes */
+enum {
+ JVM_REF_getField = 1,
+ JVM_REF_getStatic = 2,
+ JVM_REF_putField = 3,
+ JVM_REF_putStatic = 4,
+ JVM_REF_invokeVirtual = 5,
+ JVM_REF_invokeStatic = 6,
+ JVM_REF_invokeSpecial = 7,
+ JVM_REF_newInvokeSpecial = 8,
+ JVM_REF_invokeInterface = 9
+};
+
+/* StackMapTable type item numbers */
+
+enum {
+ JVM_ITEM_Top = 0,
+ JVM_ITEM_Integer = 1,
+ JVM_ITEM_Float = 2,
+ JVM_ITEM_Double = 3,
+ JVM_ITEM_Long = 4,
+ JVM_ITEM_Null = 5,
+ JVM_ITEM_UninitializedThis = 6,
+ JVM_ITEM_Object = 7,
+ JVM_ITEM_Uninitialized = 8
+};
+
+/* Type signatures */
+
+enum {
+ JVM_SIGNATURE_ARRAY = '[',
+ JVM_SIGNATURE_BYTE = 'B',
+ JVM_SIGNATURE_CHAR = 'C',
+ JVM_SIGNATURE_CLASS = 'L',
+ JVM_SIGNATURE_ENDCLASS = ';',
+ JVM_SIGNATURE_ENUM = 'E',
+ JVM_SIGNATURE_FLOAT = 'F',
+ JVM_SIGNATURE_DOUBLE = 'D',
+ JVM_SIGNATURE_FUNC = '(',
+ JVM_SIGNATURE_ENDFUNC = ')',
+ JVM_SIGNATURE_INT = 'I',
+ JVM_SIGNATURE_LONG = 'J',
+ JVM_SIGNATURE_SHORT = 'S',
+ JVM_SIGNATURE_VOID = 'V',
+ JVM_SIGNATURE_BOOLEAN = 'Z'
+};
+
+/* Opcodes */
+
+enum {
+ JVM_OPC_nop = 0,
+ JVM_OPC_aconst_null = 1,
+ JVM_OPC_iconst_m1 = 2,
+ JVM_OPC_iconst_0 = 3,
+ JVM_OPC_iconst_1 = 4,
+ JVM_OPC_iconst_2 = 5,
+ JVM_OPC_iconst_3 = 6,
+ JVM_OPC_iconst_4 = 7,
+ JVM_OPC_iconst_5 = 8,
+ JVM_OPC_lconst_0 = 9,
+ JVM_OPC_lconst_1 = 10,
+ JVM_OPC_fconst_0 = 11,
+ JVM_OPC_fconst_1 = 12,
+ JVM_OPC_fconst_2 = 13,
+ JVM_OPC_dconst_0 = 14,
+ JVM_OPC_dconst_1 = 15,
+ JVM_OPC_bipush = 16,
+ JVM_OPC_sipush = 17,
+ JVM_OPC_ldc = 18,
+ JVM_OPC_ldc_w = 19,
+ JVM_OPC_ldc2_w = 20,
+ JVM_OPC_iload = 21,
+ JVM_OPC_lload = 22,
+ JVM_OPC_fload = 23,
+ JVM_OPC_dload = 24,
+ JVM_OPC_aload = 25,
+ JVM_OPC_iload_0 = 26,
+ JVM_OPC_iload_1 = 27,
+ JVM_OPC_iload_2 = 28,
+ JVM_OPC_iload_3 = 29,
+ JVM_OPC_lload_0 = 30,
+ JVM_OPC_lload_1 = 31,
+ JVM_OPC_lload_2 = 32,
+ JVM_OPC_lload_3 = 33,
+ JVM_OPC_fload_0 = 34,
+ JVM_OPC_fload_1 = 35,
+ JVM_OPC_fload_2 = 36,
+ JVM_OPC_fload_3 = 37,
+ JVM_OPC_dload_0 = 38,
+ JVM_OPC_dload_1 = 39,
+ JVM_OPC_dload_2 = 40,
+ JVM_OPC_dload_3 = 41,
+ JVM_OPC_aload_0 = 42,
+ JVM_OPC_aload_1 = 43,
+ JVM_OPC_aload_2 = 44,
+ JVM_OPC_aload_3 = 45,
+ JVM_OPC_iaload = 46,
+ JVM_OPC_laload = 47,
+ JVM_OPC_faload = 48,
+ JVM_OPC_daload = 49,
+ JVM_OPC_aaload = 50,
+ JVM_OPC_baload = 51,
+ JVM_OPC_caload = 52,
+ JVM_OPC_saload = 53,
+ JVM_OPC_istore = 54,
+ JVM_OPC_lstore = 55,
+ JVM_OPC_fstore = 56,
+ JVM_OPC_dstore = 57,
+ JVM_OPC_astore = 58,
+ JVM_OPC_istore_0 = 59,
+ JVM_OPC_istore_1 = 60,
+ JVM_OPC_istore_2 = 61,
+ JVM_OPC_istore_3 = 62,
+ JVM_OPC_lstore_0 = 63,
+ JVM_OPC_lstore_1 = 64,
+ JVM_OPC_lstore_2 = 65,
+ JVM_OPC_lstore_3 = 66,
+ JVM_OPC_fstore_0 = 67,
+ JVM_OPC_fstore_1 = 68,
+ JVM_OPC_fstore_2 = 69,
+ JVM_OPC_fstore_3 = 70,
+ JVM_OPC_dstore_0 = 71,
+ JVM_OPC_dstore_1 = 72,
+ JVM_OPC_dstore_2 = 73,
+ JVM_OPC_dstore_3 = 74,
+ JVM_OPC_astore_0 = 75,
+ JVM_OPC_astore_1 = 76,
+ JVM_OPC_astore_2 = 77,
+ JVM_OPC_astore_3 = 78,
+ JVM_OPC_iastore = 79,
+ JVM_OPC_lastore = 80,
+ JVM_OPC_fastore = 81,
+ JVM_OPC_dastore = 82,
+ JVM_OPC_aastore = 83,
+ JVM_OPC_bastore = 84,
+ JVM_OPC_castore = 85,
+ JVM_OPC_sastore = 86,
+ JVM_OPC_pop = 87,
+ JVM_OPC_pop2 = 88,
+ JVM_OPC_dup = 89,
+ JVM_OPC_dup_x1 = 90,
+ JVM_OPC_dup_x2 = 91,
+ JVM_OPC_dup2 = 92,
+ JVM_OPC_dup2_x1 = 93,
+ JVM_OPC_dup2_x2 = 94,
+ JVM_OPC_swap = 95,
+ JVM_OPC_iadd = 96,
+ JVM_OPC_ladd = 97,
+ JVM_OPC_fadd = 98,
+ JVM_OPC_dadd = 99,
+ JVM_OPC_isub = 100,
+ JVM_OPC_lsub = 101,
+ JVM_OPC_fsub = 102,
+ JVM_OPC_dsub = 103,
+ JVM_OPC_imul = 104,
+ JVM_OPC_lmul = 105,
+ JVM_OPC_fmul = 106,
+ JVM_OPC_dmul = 107,
+ JVM_OPC_idiv = 108,
+ JVM_OPC_ldiv = 109,
+ JVM_OPC_fdiv = 110,
+ JVM_OPC_ddiv = 111,
+ JVM_OPC_irem = 112,
+ JVM_OPC_lrem = 113,
+ JVM_OPC_frem = 114,
+ JVM_OPC_drem = 115,
+ JVM_OPC_ineg = 116,
+ JVM_OPC_lneg = 117,
+ JVM_OPC_fneg = 118,
+ JVM_OPC_dneg = 119,
+ JVM_OPC_ishl = 120,
+ JVM_OPC_lshl = 121,
+ JVM_OPC_ishr = 122,
+ JVM_OPC_lshr = 123,
+ JVM_OPC_iushr = 124,
+ JVM_OPC_lushr = 125,
+ JVM_OPC_iand = 126,
+ JVM_OPC_land = 127,
+ JVM_OPC_ior = 128,
+ JVM_OPC_lor = 129,
+ JVM_OPC_ixor = 130,
+ JVM_OPC_lxor = 131,
+ JVM_OPC_iinc = 132,
+ JVM_OPC_i2l = 133,
+ JVM_OPC_i2f = 134,
+ JVM_OPC_i2d = 135,
+ JVM_OPC_l2i = 136,
+ JVM_OPC_l2f = 137,
+ JVM_OPC_l2d = 138,
+ JVM_OPC_f2i = 139,
+ JVM_OPC_f2l = 140,
+ JVM_OPC_f2d = 141,
+ JVM_OPC_d2i = 142,
+ JVM_OPC_d2l = 143,
+ JVM_OPC_d2f = 144,
+ JVM_OPC_i2b = 145,
+ JVM_OPC_i2c = 146,
+ JVM_OPC_i2s = 147,
+ JVM_OPC_lcmp = 148,
+ JVM_OPC_fcmpl = 149,
+ JVM_OPC_fcmpg = 150,
+ JVM_OPC_dcmpl = 151,
+ JVM_OPC_dcmpg = 152,
+ JVM_OPC_ifeq = 153,
+ JVM_OPC_ifne = 154,
+ JVM_OPC_iflt = 155,
+ JVM_OPC_ifge = 156,
+ JVM_OPC_ifgt = 157,
+ JVM_OPC_ifle = 158,
+ JVM_OPC_if_icmpeq = 159,
+ JVM_OPC_if_icmpne = 160,
+ JVM_OPC_if_icmplt = 161,
+ JVM_OPC_if_icmpge = 162,
+ JVM_OPC_if_icmpgt = 163,
+ JVM_OPC_if_icmple = 164,
+ JVM_OPC_if_acmpeq = 165,
+ JVM_OPC_if_acmpne = 166,
+ JVM_OPC_goto = 167,
+ JVM_OPC_jsr = 168,
+ JVM_OPC_ret = 169,
+ JVM_OPC_tableswitch = 170,
+ JVM_OPC_lookupswitch = 171,
+ JVM_OPC_ireturn = 172,
+ JVM_OPC_lreturn = 173,
+ JVM_OPC_freturn = 174,
+ JVM_OPC_dreturn = 175,
+ JVM_OPC_areturn = 176,
+ JVM_OPC_return = 177,
+ JVM_OPC_getstatic = 178,
+ JVM_OPC_putstatic = 179,
+ JVM_OPC_getfield = 180,
+ JVM_OPC_putfield = 181,
+ JVM_OPC_invokevirtual = 182,
+ JVM_OPC_invokespecial = 183,
+ JVM_OPC_invokestatic = 184,
+ JVM_OPC_invokeinterface = 185,
+ JVM_OPC_invokedynamic = 186,
+ JVM_OPC_new = 187,
+ JVM_OPC_newarray = 188,
+ JVM_OPC_anewarray = 189,
+ JVM_OPC_arraylength = 190,
+ JVM_OPC_athrow = 191,
+ JVM_OPC_checkcast = 192,
+ JVM_OPC_instanceof = 193,
+ JVM_OPC_monitorenter = 194,
+ JVM_OPC_monitorexit = 195,
+ JVM_OPC_wide = 196,
+ JVM_OPC_multianewarray = 197,
+ JVM_OPC_ifnull = 198,
+ JVM_OPC_ifnonnull = 199,
+ JVM_OPC_goto_w = 200,
+ JVM_OPC_jsr_w = 201,
+ JVM_OPC_MAX = 201
+};
+
+/* Opcode length initializer, use with something like:
+ * unsigned char opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER;
+ */
+#define JVM_OPCODE_LENGTH_INITIALIZER { \
+ 1, /* nop */ \
+ 1, /* aconst_null */ \
+ 1, /* iconst_m1 */ \
+ 1, /* iconst_0 */ \
+ 1, /* iconst_1 */ \
+ 1, /* iconst_2 */ \
+ 1, /* iconst_3 */ \
+ 1, /* iconst_4 */ \
+ 1, /* iconst_5 */ \
+ 1, /* lconst_0 */ \
+ 1, /* lconst_1 */ \
+ 1, /* fconst_0 */ \
+ 1, /* fconst_1 */ \
+ 1, /* fconst_2 */ \
+ 1, /* dconst_0 */ \
+ 1, /* dconst_1 */ \
+ 2, /* bipush */ \
+ 3, /* sipush */ \
+ 2, /* ldc */ \
+ 3, /* ldc_w */ \
+ 3, /* ldc2_w */ \
+ 2, /* iload */ \
+ 2, /* lload */ \
+ 2, /* fload */ \
+ 2, /* dload */ \
+ 2, /* aload */ \
+ 1, /* iload_0 */ \
+ 1, /* iload_1 */ \
+ 1, /* iload_2 */ \
+ 1, /* iload_3 */ \
+ 1, /* lload_0 */ \
+ 1, /* lload_1 */ \
+ 1, /* lload_2 */ \
+ 1, /* lload_3 */ \
+ 1, /* fload_0 */ \
+ 1, /* fload_1 */ \
+ 1, /* fload_2 */ \
+ 1, /* fload_3 */ \
+ 1, /* dload_0 */ \
+ 1, /* dload_1 */ \
+ 1, /* dload_2 */ \
+ 1, /* dload_3 */ \
+ 1, /* aload_0 */ \
+ 1, /* aload_1 */ \
+ 1, /* aload_2 */ \
+ 1, /* aload_3 */ \
+ 1, /* iaload */ \
+ 1, /* laload */ \
+ 1, /* faload */ \
+ 1, /* daload */ \
+ 1, /* aaload */ \
+ 1, /* baload */ \
+ 1, /* caload */ \
+ 1, /* saload */ \
+ 2, /* istore */ \
+ 2, /* lstore */ \
+ 2, /* fstore */ \
+ 2, /* dstore */ \
+ 2, /* astore */ \
+ 1, /* istore_0 */ \
+ 1, /* istore_1 */ \
+ 1, /* istore_2 */ \
+ 1, /* istore_3 */ \
+ 1, /* lstore_0 */ \
+ 1, /* lstore_1 */ \
+ 1, /* lstore_2 */ \
+ 1, /* lstore_3 */ \
+ 1, /* fstore_0 */ \
+ 1, /* fstore_1 */ \
+ 1, /* fstore_2 */ \
+ 1, /* fstore_3 */ \
+ 1, /* dstore_0 */ \
+ 1, /* dstore_1 */ \
+ 1, /* dstore_2 */ \
+ 1, /* dstore_3 */ \
+ 1, /* astore_0 */ \
+ 1, /* astore_1 */ \
+ 1, /* astore_2 */ \
+ 1, /* astore_3 */ \
+ 1, /* iastore */ \
+ 1, /* lastore */ \
+ 1, /* fastore */ \
+ 1, /* dastore */ \
+ 1, /* aastore */ \
+ 1, /* bastore */ \
+ 1, /* castore */ \
+ 1, /* sastore */ \
+ 1, /* pop */ \
+ 1, /* pop2 */ \
+ 1, /* dup */ \
+ 1, /* dup_x1 */ \
+ 1, /* dup_x2 */ \
+ 1, /* dup2 */ \
+ 1, /* dup2_x1 */ \
+ 1, /* dup2_x2 */ \
+ 1, /* swap */ \
+ 1, /* iadd */ \
+ 1, /* ladd */ \
+ 1, /* fadd */ \
+ 1, /* dadd */ \
+ 1, /* isub */ \
+ 1, /* lsub */ \
+ 1, /* fsub */ \
+ 1, /* dsub */ \
+ 1, /* imul */ \
+ 1, /* lmul */ \
+ 1, /* fmul */ \
+ 1, /* dmul */ \
+ 1, /* idiv */ \
+ 1, /* ldiv */ \
+ 1, /* fdiv */ \
+ 1, /* ddiv */ \
+ 1, /* irem */ \
+ 1, /* lrem */ \
+ 1, /* frem */ \
+ 1, /* drem */ \
+ 1, /* ineg */ \
+ 1, /* lneg */ \
+ 1, /* fneg */ \
+ 1, /* dneg */ \
+ 1, /* ishl */ \
+ 1, /* lshl */ \
+ 1, /* ishr */ \
+ 1, /* lshr */ \
+ 1, /* iushr */ \
+ 1, /* lushr */ \
+ 1, /* iand */ \
+ 1, /* land */ \
+ 1, /* ior */ \
+ 1, /* lor */ \
+ 1, /* ixor */ \
+ 1, /* lxor */ \
+ 3, /* iinc */ \
+ 1, /* i2l */ \
+ 1, /* i2f */ \
+ 1, /* i2d */ \
+ 1, /* l2i */ \
+ 1, /* l2f */ \
+ 1, /* l2d */ \
+ 1, /* f2i */ \
+ 1, /* f2l */ \
+ 1, /* f2d */ \
+ 1, /* d2i */ \
+ 1, /* d2l */ \
+ 1, /* d2f */ \
+ 1, /* i2b */ \
+ 1, /* i2c */ \
+ 1, /* i2s */ \
+ 1, /* lcmp */ \
+ 1, /* fcmpl */ \
+ 1, /* fcmpg */ \
+ 1, /* dcmpl */ \
+ 1, /* dcmpg */ \
+ 3, /* ifeq */ \
+ 3, /* ifne */ \
+ 3, /* iflt */ \
+ 3, /* ifge */ \
+ 3, /* ifgt */ \
+ 3, /* ifle */ \
+ 3, /* if_icmpeq */ \
+ 3, /* if_icmpne */ \
+ 3, /* if_icmplt */ \
+ 3, /* if_icmpge */ \
+ 3, /* if_icmpgt */ \
+ 3, /* if_icmple */ \
+ 3, /* if_acmpeq */ \
+ 3, /* if_acmpne */ \
+ 3, /* goto */ \
+ 3, /* jsr */ \
+ 2, /* ret */ \
+ 99, /* tableswitch */ \
+ 99, /* lookupswitch */ \
+ 1, /* ireturn */ \
+ 1, /* lreturn */ \
+ 1, /* freturn */ \
+ 1, /* dreturn */ \
+ 1, /* areturn */ \
+ 1, /* return */ \
+ 3, /* getstatic */ \
+ 3, /* putstatic */ \
+ 3, /* getfield */ \
+ 3, /* putfield */ \
+ 3, /* invokevirtual */ \
+ 3, /* invokespecial */ \
+ 3, /* invokestatic */ \
+ 5, /* invokeinterface */ \
+ 5, /* invokedynamic */ \
+ 3, /* new */ \
+ 2, /* newarray */ \
+ 3, /* anewarray */ \
+ 1, /* arraylength */ \
+ 1, /* athrow */ \
+ 3, /* checkcast */ \
+ 3, /* instanceof */ \
+ 1, /* monitorenter */ \
+ 1, /* monitorexit */ \
+ 0, /* wide */ \
+ 4, /* multianewarray */ \
+ 3, /* ifnull */ \
+ 3, /* ifnonnull */ \
+ 5, /* goto_w */ \
+ 5 /* jsr_w */ \
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* CLASSFILE_CONSTANTS */
diff --git a/ojluni/src/main/native/fdlibm.h b/ojluni/src/main/native/fdlibm.h
new file mode 100755
index 0000000..c24c781
--- /dev/null
+++ b/ojluni/src/main/native/fdlibm.h
@@ -0,0 +1,239 @@
+
+/*
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifdef _ALLBSD_SOURCE
+#include <machine/endian.h>
+#elif __linux__
+#define __USE_BSD 1
+#include <endian.h>
+#endif
+#include "jfdlibm.h"
+
+#ifdef __NEWVALID /* special setup for Sun test regime */
+#if defined(i386) || defined(i486) || \
+ defined(intel) || defined(x86) || defined(arm) || \
+ defined(i86pc) || defined(_M_IA64) || defined(ia64)
+#define _LITTLE_ENDIAN
+#endif
+#endif
+
+#ifdef _LITTLE_ENDIAN
+#define __HI(x) *(1+(int*)&x)
+#define __LO(x) *(int*)&x
+#define __HIp(x) *(1+(int*)x)
+#define __LOp(x) *(int*)x
+#else
+#define __HI(x) *(int*)&x
+#define __LO(x) *(1+(int*)&x)
+#define __HIp(x) *(int*)x
+#define __LOp(x) *(1+(int*)x)
+#endif
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(p) p
+#else
+#define __P(p) ()
+#endif
+#endif
+
+/*
+ * ANSI/POSIX
+ */
+
+extern int signgam;
+
+#define MAXFLOAT ((float)3.40282346638528860e+38)
+
+enum fdversion {fdlibm_ieee = -1, fdlibm_svid, fdlibm_xopen, fdlibm_posix};
+
+#define _LIB_VERSION_TYPE enum fdversion
+#define _LIB_VERSION _fdlib_version
+
+/* if global variable _LIB_VERSION is not desirable, one may
+ * change the following to be a constant by:
+ * #define _LIB_VERSION_TYPE const enum version
+ * In that case, after one initializes the value _LIB_VERSION (see
+ * s_lib_version.c) during compile time, it cannot be modified
+ * in the middle of a program
+ */
+extern _LIB_VERSION_TYPE _LIB_VERSION;
+
+#define _IEEE_ fdlibm_ieee
+#define _SVID_ fdlibm_svid
+#define _XOPEN_ fdlibm_xopen
+#define _POSIX_ fdlibm_posix
+
+struct exception {
+ int type;
+ char *name;
+ double arg1;
+ double arg2;
+ double retval;
+};
+
+#define HUGE MAXFLOAT
+
+/*
+ * set X_TLOSS = pi*2**52, which is possibly defined in <values.h>
+ * (one may replace the following line by "#include <values.h>")
+ */
+
+#define X_TLOSS 1.41484755040568800000e+16
+
+#define DOMAIN 1
+#define SING 2
+#define OVERFLOW 3
+#define UNDERFLOW 4
+#define TLOSS 5
+#define PLOSS 6
+
+/*
+ * ANSI/POSIX
+ */
+extern double acos __P((double));
+extern double asin __P((double));
+extern double atan __P((double));
+extern double atan2 __P((double, double));
+extern double cos __P((double));
+extern double sin __P((double));
+extern double tan __P((double));
+
+extern double cosh __P((double));
+extern double sinh __P((double));
+extern double tanh __P((double));
+
+extern double exp __P((double));
+extern double frexp __P((double, int *));
+extern double ldexp __P((double, int));
+extern double log __P((double));
+extern double log10 __P((double));
+extern double modf __P((double, double *));
+
+extern double pow __P((double, double));
+extern double sqrt __P((double));
+
+extern double ceil __P((double));
+extern double fabs __P((double));
+extern double floor __P((double));
+extern double fmod __P((double, double));
+
+extern double erf __P((double));
+extern double erfc __P((double));
+extern double gamma __P((double));
+extern double hypot __P((double, double));
+extern int isnan __P((double));
+extern int finite __P((double));
+extern double j0 __P((double));
+extern double j1 __P((double));
+extern double jn __P((int, double));
+extern double lgamma __P((double));
+extern double y0 __P((double));
+extern double y1 __P((double));
+extern double yn __P((int, double));
+
+extern double acosh __P((double));
+extern double asinh __P((double));
+extern double atanh __P((double));
+extern double cbrt __P((double));
+extern double logb __P((double));
+extern double nextafter __P((double, double));
+extern double remainder __P((double, double));
+#ifdef _SCALB_INT
+extern double scalb __P((double, int));
+#else
+extern double scalb __P((double, double));
+#endif
+
+extern int matherr __P((struct exception *));
+
+/*
+ * IEEE Test Vector
+ */
+extern double significand __P((double));
+
+/*
+ * Functions callable from C, intended to support IEEE arithmetic.
+ */
+extern double copysign __P((double, double));
+extern int ilogb __P((double));
+extern double rint __P((double));
+extern double scalbn __P((double, int));
+
+/*
+ * BSD math library entry points
+ */
+extern double expm1 __P((double));
+extern double log1p __P((double));
+
+/*
+ * Reentrant version of gamma & lgamma; passes signgam back by reference
+ * as the second argument; user must allocate space for signgam.
+ */
+#ifdef _REENTRANT
+extern double gamma_r __P((double, int *));
+extern double lgamma_r __P((double, int *));
+#endif /* _REENTRANT */
+
+/* ieee style elementary functions */
+extern double __ieee754_sqrt __P((double));
+extern double __ieee754_acos __P((double));
+extern double __ieee754_acosh __P((double));
+extern double __ieee754_log __P((double));
+extern double __ieee754_atanh __P((double));
+extern double __ieee754_asin __P((double));
+extern double __ieee754_atan2 __P((double,double));
+extern double __ieee754_exp __P((double));
+extern double __ieee754_cosh __P((double));
+extern double __ieee754_fmod __P((double,double));
+extern double __ieee754_pow __P((double,double));
+extern double __ieee754_lgamma_r __P((double,int *));
+extern double __ieee754_gamma_r __P((double,int *));
+extern double __ieee754_lgamma __P((double));
+extern double __ieee754_gamma __P((double));
+extern double __ieee754_log10 __P((double));
+extern double __ieee754_sinh __P((double));
+extern double __ieee754_hypot __P((double,double));
+extern double __ieee754_j0 __P((double));
+extern double __ieee754_j1 __P((double));
+extern double __ieee754_y0 __P((double));
+extern double __ieee754_y1 __P((double));
+extern double __ieee754_jn __P((int,double));
+extern double __ieee754_yn __P((int,double));
+extern double __ieee754_remainder __P((double,double));
+extern int __ieee754_rem_pio2 __P((double,double*));
+#ifdef _SCALB_INT
+extern double __ieee754_scalb __P((double,int));
+#else
+extern double __ieee754_scalb __P((double,double));
+#endif
+
+/* fdlibm kernel function */
+extern double __kernel_standard __P((double,double,int));
+extern double __kernel_sin __P((double,double,int));
+extern double __kernel_cos __P((double,double));
+extern double __kernel_tan __P((double,double,int));
+extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const int*));
diff --git a/ojluni/src/main/native/io_util.c b/ojluni/src/main/native/io_util.c
new file mode 100755
index 0000000..e17652a
--- /dev/null
+++ b/ojluni/src/main/native/io_util.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stddef.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "io_util.h"
+#include "io_util_md.h"
+
+/* IO helper functions */
+
+jint
+readSingle(JNIEnv *env, jobject this, jfieldID fid) {
+ jint nread;
+ char ret;
+ FD fd = GET_FD(this, fid);
+ if (fd == -1) {
+ JNU_ThrowIOException(env, "Stream Closed");
+ return -1;
+ }
+ nread = (jint)IO_Read(fd, &ret, 1);
+ if (nread == 0) { /* EOF */
+ return -1;
+ } else if (nread == JVM_IO_ERR) { /* error */
+ JNU_ThrowIOExceptionWithLastError(env, "Read error");
+ } else if (nread == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
+ }
+ return ret & 0xFF;
+}
+
+/* The maximum size of a stack-allocated buffer.
+ */
+#define BUF_SIZE 8192
+
+/*
+ * Returns true if the array slice defined by the given offset and length
+ * is out of bounds.
+ */
+static int
+outOfBounds(JNIEnv *env, jint off, jint len, jbyteArray array) {
+ return ((off < 0) ||
+ (len < 0) ||
+ // We are very careful to avoid signed integer overflow,
+ // the result of which is undefined in C.
+ ((*env)->GetArrayLength(env, array) - off < len));
+}
+
+jint
+readBytes(JNIEnv *env, jobject this, jbyteArray bytes,
+ jint off, jint len, jfieldID fid)
+{
+ jint nread;
+ char stackBuf[BUF_SIZE];
+ char *buf = NULL;
+ FD fd;
+
+ if (IS_NULL(bytes)) {
+ JNU_ThrowNullPointerException(env, NULL);
+ return -1;
+ }
+
+ if (outOfBounds(env, off, len, bytes)) {
+ JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", NULL);
+ return -1;
+ }
+
+ if (len == 0) {
+ return 0;
+ } else if (len > BUF_SIZE) {
+ buf = malloc(len);
+ if (buf == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return 0;
+ }
+ } else {
+ buf = stackBuf;
+ }
+
+ fd = GET_FD(this, fid);
+ if (fd == -1) {
+ JNU_ThrowIOException(env, "Stream Closed");
+ nread = -1;
+ } else {
+ nread = (jint)IO_Read(fd, buf, len);
+ if (nread > 0) {
+ (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf);
+ } else if (nread == JVM_IO_ERR) {
+ JNU_ThrowIOExceptionWithLastError(env, "Read error");
+ } else if (nread == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
+ } else { /* EOF */
+ nread = -1;
+ }
+ }
+
+ if (buf != stackBuf) {
+ free(buf);
+ }
+ return nread;
+}
+
+void
+writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid) {
+ // Discard the 24 high-order bits of byte. See OutputStream#write(int)
+ char c = (char) byte;
+ jint n;
+ FD fd = GET_FD(this, fid);
+ if (fd == -1) {
+ JNU_ThrowIOException(env, "Stream Closed");
+ return;
+ }
+ if (append == JNI_TRUE) {
+ n = (jint)IO_Append(fd, &c, 1);
+ } else {
+ n = (jint)IO_Write(fd, &c, 1);
+ }
+ if (n == JVM_IO_ERR) {
+ JNU_ThrowIOExceptionWithLastError(env, "Write error");
+ } else if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
+ }
+}
+
+void
+writeBytes(JNIEnv *env, jobject this, jbyteArray bytes,
+ jint off, jint len, jboolean append, jfieldID fid)
+{
+ jint n;
+ char stackBuf[BUF_SIZE];
+ char *buf = NULL;
+ FD fd;
+
+ if (IS_NULL(bytes)) {
+ JNU_ThrowNullPointerException(env, NULL);
+ return;
+ }
+
+ if (outOfBounds(env, off, len, bytes)) {
+ JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", NULL);
+ return;
+ }
+
+ if (len == 0) {
+ return;
+ } else if (len > BUF_SIZE) {
+ buf = malloc(len);
+ if (buf == NULL) {
+ JNU_ThrowOutOfMemoryError(env, NULL);
+ return;
+ }
+ } else {
+ buf = stackBuf;
+ }
+
+ (*env)->GetByteArrayRegion(env, bytes, off, len, (jbyte *)buf);
+
+ if (!(*env)->ExceptionOccurred(env)) {
+ off = 0;
+ while (len > 0) {
+ fd = GET_FD(this, fid);
+ if (fd == -1) {
+ JNU_ThrowIOException(env, "Stream Closed");
+ break;
+ }
+ if (append == JNI_TRUE) {
+ n = (jint)IO_Append(fd, buf+off, len);
+ } else {
+ n = (jint)IO_Write(fd, buf+off, len);
+ }
+ if (n == JVM_IO_ERR) {
+ JNU_ThrowIOExceptionWithLastError(env, "Write error");
+ break;
+ } else if (n == JVM_IO_INTR) {
+ JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
+ break;
+ }
+ off += n;
+ len -= n;
+ }
+ }
+ if (buf != stackBuf) {
+ free(buf);
+ }
+}
+
+void
+throwFileNotFoundException(JNIEnv *env, jstring path)
+{
+ char buf[256];
+ jint n;
+ jobject x;
+ jstring why = NULL;
+
+ n = JVM_GetLastErrorString(buf, sizeof(buf));
+ if (n > 0) {
+ why = JNU_NewStringPlatform(env, buf);
+ }
+ x = JNU_NewObjectByName(env,
+ "java/io/FileNotFoundException",
+ "(Ljava/lang/String;Ljava/lang/String;)V",
+ path, why);
+ if (x != NULL) {
+ (*env)->Throw(env, x);
+ }
+}
diff --git a/ojluni/src/main/native/io_util.h b/ojluni/src/main/native/io_util.h
new file mode 100755
index 0000000..31088a9
--- /dev/null
+++ b/ojluni/src/main/native/io_util.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+
+extern jfieldID IO_fd_fdID;
+extern jfieldID IO_handle_fdID;
+
+#ifdef _ALLBSD_SOURCE
+#include <fcntl.h>
+#ifndef O_SYNC
+#define O_SYNC O_FSYNC
+#endif
+#ifndef O_DSYNC
+#define O_DSYNC O_FSYNC
+#endif
+#elif !defined(O_DSYNC) || !defined(O_SYNC)
+#define O_SYNC (0x0800)
+#define O_DSYNC (0x2000)
+#endif
+
+/*
+ * IO helper functions
+ */
+
+jint readSingle(JNIEnv *env, jobject this, jfieldID fid);
+jint readBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off,
+ jint len, jfieldID fid);
+void writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid);
+void writeBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off,
+ jint len, jboolean append, jfieldID fid);
+void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
+void throwFileNotFoundException(JNIEnv *env, jstring path);
+
+
+/*
+ * Macros for managing platform strings. The typical usage pattern is:
+ *
+ * WITH_PLATFORM_STRING(env, string, var) {
+ * doSomethingWith(var);
+ * } END_PLATFORM_STRING(env, var);
+ *
+ * where env is the prevailing JNIEnv,
+ * string is a JNI reference to a java.lang.String object, and
+ * var is the char * variable that will point to the string,
+ * after being converted into the platform encoding.
+ *
+ * The related macro WITH_FIELD_PLATFORM_STRING first extracts the string from
+ * a given field of a given object:
+ *
+ * WITH_FIELD_PLATFORM_STRING(env, object, id, var) {
+ * doSomethingWith(var);
+ * } END_PLATFORM_STRING(env, var);
+ *
+ * where env is the prevailing JNIEnv,
+ * object is a jobject,
+ * id is the field ID of the String field to be extracted, and
+ * var is the char * variable that will point to the string.
+ *
+ * Uses of these macros may be nested as long as each WITH_.._STRING macro
+ * declares a unique variable.
+ */
+
+#define WITH_PLATFORM_STRING(env, strexp, var) \
+ if (1) { \
+ const char *var; \
+ jstring _##var##str = (strexp); \
+ if (_##var##str == NULL) { \
+ JNU_ThrowNullPointerException((env), NULL); \
+ goto _##var##end; \
+ } \
+ var = JNU_GetStringPlatformChars((env), _##var##str, NULL); \
+ if (var == NULL) goto _##var##end;
+
+#define WITH_FIELD_PLATFORM_STRING(env, object, id, var) \
+ WITH_PLATFORM_STRING(env, \
+ ((object == NULL) \
+ ? NULL \
+ : (*(env))->GetObjectField((env), (object), (id))), \
+ var)
+
+#define END_PLATFORM_STRING(env, var) \
+ JNU_ReleaseStringPlatformChars(env, _##var##str, var); \
+ _##var##end: ; \
+ } else ((void)NULL)
+
+
+/* Macros for transforming Java Strings into native Unicode strings.
+ * Works analogously to WITH_PLATFORM_STRING.
+ */
+
+#define WITH_UNICODE_STRING(env, strexp, var) \
+ if (1) { \
+ const jchar *var; \
+ jstring _##var##str = (strexp); \
+ if (_##var##str == NULL) { \
+ JNU_ThrowNullPointerException((env), NULL); \
+ goto _##var##end; \
+ } \
+ var = (*(env))->GetStringChars((env), _##var##str, NULL); \
+ if (var == NULL) goto _##var##end;
+
+#define END_UNICODE_STRING(env, var) \
+ (*(env))->ReleaseStringChars(env, _##var##str, var); \
+ _##var##end: ; \
+ } else ((void)NULL)
diff --git a/ojluni/src/main/native/io_util_md.c b/ojluni/src/main/native/io_util_md.c
new file mode 100755
index 0000000..646e130
--- /dev/null
+++ b/ojluni/src/main/native/io_util_md.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "io_util.h"
+#include "io_util_md.h"
+#include <string.h>
+
+#ifdef MACOSX
+
+#include <CoreFoundation/CoreFoundation.h>
+
+__private_extern__
+jstring newStringPlatform(JNIEnv *env, const char* str)
+{
+ jstring rv = NULL;
+ CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);
+ if (csref == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "native heap");
+ } else {
+ CFStringAppendCString(csref, str, kCFStringEncodingUTF8);
+ CFStringNormalize(csref, kCFStringNormalizationFormC);
+ int clen = CFStringGetLength(csref);
+ int ulen = (clen + 1) * 2; // utf16 + zero padding
+ char* chars = malloc(ulen);
+ if (chars == NULL) {
+ CFRelease(csref);
+ JNU_ThrowOutOfMemoryError(env, "native heap");
+ } else {
+ if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {
+ rv = (*env)->NewString(env, (jchar*)chars, clen);
+ }
+ free(chars);
+ CFRelease(csref);
+ }
+ }
+ return rv;
+}
+#endif
+
+void
+fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
+{
+ WITH_PLATFORM_STRING(env, path, ps) {
+ FD fd;
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+ /* Remove trailing slashes, since the kernel won't */
+ char *p = (char *)ps + strlen(ps) - 1;
+ while ((p > ps) && (*p == '/'))
+ *p-- = '\0';
+#endif
+ fd = JVM_Open(ps, flags, 0666);
+ if (fd >= 0) {
+ SET_FD(this, fd, fid);
+ } else {
+ throwFileNotFoundException(env, path);
+ }
+ } END_PLATFORM_STRING(env, ps);
+}
+
+
+void
+fileClose(JNIEnv *env, jobject this, jfieldID fid)
+{
+ FD fd = GET_FD(this, fid);
+ if (fd == -1) {
+ return;
+ }
+
+ /* Set the fd to -1 before closing it so that the timing window
+ * of other threads using the wrong fd (closed but recycled fd,
+ * that gets re-opened with some other filename) is reduced.
+ * Practically the chance of its occurance is low, however, we are
+ * taking extra precaution over here.
+ */
+ SET_FD(this, -1, fid);
+
+ /*
+ * Don't close file descriptors 0, 1, or 2. If we close these stream
+ * then a subsequent file open or socket will use them. Instead we
+ * just redirect these file descriptors to /dev/null.
+ */
+ if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {
+ int devnull = open("/dev/null", O_WRONLY);
+ if (devnull < 0) {
+ SET_FD(this, fd, fid); // restore fd
+ JNU_ThrowIOExceptionWithLastError(env, "open /dev/null failed");
+ } else {
+ dup2(devnull, fd);
+ close(devnull);
+ }
+ } else if (JVM_Close(fd) == -1) {
+ JNU_ThrowIOExceptionWithLastError(env, "close failed");
+ }
+}
diff --git a/ojluni/src/main/native/io_util_md.h b/ojluni/src/main/native/io_util_md.h
new file mode 100755
index 0000000..fbf8172
--- /dev/null
+++ b/ojluni/src/main/native/io_util_md.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+
+/*
+ * Macros to use the right data type for file descriptors
+ */
+#define FD jint
+
+/*
+ * Macros to set/get fd from the java.io.FileDescriptor. These
+ * macros rely on having an appropriately defined 'this' object
+ * within the scope in which they're used.
+ * If GetObjectField returns null, SET_FD will stop and GET_FD
+ * will simply return -1 to avoid crashing VM.
+ */
+
+#define SET_FD(this, fd, fid) \
+ if ((*env)->GetObjectField(env, (this), (fid)) != NULL) \
+ (*env)->SetIntField(env, (*env)->GetObjectField(env, (this), (fid)),IO_fd_fdID, (fd))
+
+#define GET_FD(this, fid) \
+ (*env)->GetObjectField(env, (this), (fid)) == NULL ? \
+ -1 : (*env)->GetIntField(env, (*env)->GetObjectField(env, (this), (fid)), IO_fd_fdID)
+
+/*
+ * Macros to set/get fd when inside java.io.FileDescriptor
+ */
+#define THIS_FD(obj) (*env)->GetIntField(env, obj, IO_fd_fdID)
+
+/*
+ * Route the routines through VM
+ */
+#define IO_Append JVM_Write
+#define IO_Write JVM_Write
+#define IO_Sync JVM_Sync
+#define IO_Read JVM_Read
+#define IO_Lseek JVM_Lseek
+#define IO_Available JVM_Available
+#define IO_SetLength JVM_SetLength
+
+/*
+ * On Solaris, the handle field is unused
+ */
+#define SET_HANDLE(fd) return (jlong)-1
+
+/*
+ * IO helper function(s)
+ */
+void fileClose(JNIEnv *env, jobject this, jfieldID fid);
+
+#ifdef MACOSX
+jstring newStringPlatform(JNIEnv *env, const char* str);
+#endif
diff --git a/ojluni/src/main/native/java_io_FileDescriptor.h b/ojluni/src/main/native/java_io_FileDescriptor.h
new file mode 100755
index 0000000..1a776e3
--- /dev/null
+++ b/ojluni/src/main/native/java_io_FileDescriptor.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_FileDescriptor */
+
+#ifndef _Included_java_io_FileDescriptor
+#define _Included_java_io_FileDescriptor
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_io_FileDescriptor
+ * Method: sync
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileDescriptor_sync
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_io_FileDescriptor
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileDescriptor_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_io_FileInputStream.h b/ojluni/src/main/native/java_io_FileInputStream.h
new file mode 100755
index 0000000..4dae98a
--- /dev/null
+++ b/ojluni/src/main/native/java_io_FileInputStream.h
@@ -0,0 +1,71 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_FileInputStream */
+
+#ifndef _Included_java_io_FileInputStream
+#define _Included_java_io_FileInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_io_FileInputStream_MAX_SKIP_BUFFER_SIZE
+#define java_io_FileInputStream_MAX_SKIP_BUFFER_SIZE 2048L
+/*
+ * Class: java_io_FileInputStream
+ * Method: open
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileInputStream_open
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: read0
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_io_FileInputStream_read0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: readBytes
+ * Signature: ([BII)I
+ */
+JNIEXPORT jint JNICALL Java_java_io_FileInputStream_readBytes
+ (JNIEnv *, jobject, jbyteArray, jint, jint);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: skip
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_io_FileInputStream_skip
+ (JNIEnv *, jobject, jlong);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: available
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_io_FileInputStream_available
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileInputStream_initIDs
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_io_FileInputStream
+ * Method: close0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileInputStream_close0
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_io_FileOutputStream.h b/ojluni/src/main/native/java_io_FileOutputStream.h
new file mode 100755
index 0000000..9741a28
--- /dev/null
+++ b/ojluni/src/main/native/java_io_FileOutputStream.h
@@ -0,0 +1,53 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_FileOutputStream */
+
+#ifndef _Included_java_io_FileOutputStream
+#define _Included_java_io_FileOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_io_FileOutputStream
+ * Method: open
+ * Signature: (Ljava/lang/String;Z)V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileOutputStream_open
+ (JNIEnv *, jobject, jstring, jboolean);
+
+/*
+ * Class: java_io_FileOutputStream
+ * Method: write
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileOutputStream_write
+ (JNIEnv *, jobject, jint, jboolean);
+
+/*
+ * Class: java_io_FileOutputStream
+ * Method: writeBytes
+ * Signature: ([BIIZ)V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileOutputStream_writeBytes
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jboolean);
+
+/*
+ * Class: java_io_FileOutputStream
+ * Method: close0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileOutputStream_close0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_io_FileOutputStream
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_FileOutputStream_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_io_FileSystem.h b/ojluni/src/main/native/java_io_FileSystem.h
new file mode 100755
index 0000000..0a2105d
--- /dev/null
+++ b/ojluni/src/main/native/java_io_FileSystem.h
@@ -0,0 +1,41 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_FileSystem */
+
+#ifndef _Included_java_io_FileSystem
+#define _Included_java_io_FileSystem
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_io_FileSystem_BA_EXISTS
+#define java_io_FileSystem_BA_EXISTS 1L
+#undef java_io_FileSystem_BA_REGULAR
+#define java_io_FileSystem_BA_REGULAR 2L
+#undef java_io_FileSystem_BA_DIRECTORY
+#define java_io_FileSystem_BA_DIRECTORY 4L
+#undef java_io_FileSystem_BA_HIDDEN
+#define java_io_FileSystem_BA_HIDDEN 8L
+#undef java_io_FileSystem_ACCESS_READ
+#define java_io_FileSystem_ACCESS_READ 4L
+#undef java_io_FileSystem_ACCESS_WRITE
+#define java_io_FileSystem_ACCESS_WRITE 2L
+#undef java_io_FileSystem_ACCESS_EXECUTE
+#define java_io_FileSystem_ACCESS_EXECUTE 1L
+#undef java_io_FileSystem_SPACE_TOTAL
+#define java_io_FileSystem_SPACE_TOTAL 0L
+#undef java_io_FileSystem_SPACE_FREE
+#define java_io_FileSystem_SPACE_FREE 1L
+#undef java_io_FileSystem_SPACE_USABLE
+#define java_io_FileSystem_SPACE_USABLE 2L
+/*
+ * Class: java_io_FileSystem
+ * Method: getFileSystem
+ * Signature: ()Ljava/io/FileSystem;
+ */
+JNIEXPORT jobject JNICALL Java_java_io_FileSystem_getFileSystem
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_io_ObjectStreamClass.h b/ojluni/src/main/native/java_io_ObjectStreamClass.h
new file mode 100755
index 0000000..4e757c3
--- /dev/null
+++ b/ojluni/src/main/native/java_io_ObjectStreamClass.h
@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_ObjectStreamClass */
+
+#ifndef _Included_java_io_ObjectStreamClass
+#define _Included_java_io_ObjectStreamClass
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_io_ObjectStreamClass_serialVersionUID
+#define java_io_ObjectStreamClass_serialVersionUID -6120832682080437368LL
+/*
+ * Class: java_io_ObjectStreamClass
+ * Method: initNative
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_ObjectStreamClass_initNative
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_io_ObjectStreamClass
+ * Method: hasStaticInitializer
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_ObjectStreamClass_hasStaticInitializer
+ (JNIEnv *, jclass, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_io_UnixFileSystem.h b/ojluni/src/main/native/java_io_UnixFileSystem.h
new file mode 100755
index 0000000..249fa79
--- /dev/null
+++ b/ojluni/src/main/native/java_io_UnixFileSystem.h
@@ -0,0 +1,153 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_io_UnixFileSystem */
+
+#ifndef _Included_java_io_UnixFileSystem
+#define _Included_java_io_UnixFileSystem
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_io_UnixFileSystem_BA_EXISTS
+#define java_io_UnixFileSystem_BA_EXISTS 1L
+#undef java_io_UnixFileSystem_BA_REGULAR
+#define java_io_UnixFileSystem_BA_REGULAR 2L
+#undef java_io_UnixFileSystem_BA_DIRECTORY
+#define java_io_UnixFileSystem_BA_DIRECTORY 4L
+#undef java_io_UnixFileSystem_BA_HIDDEN
+#define java_io_UnixFileSystem_BA_HIDDEN 8L
+#undef java_io_UnixFileSystem_ACCESS_READ
+#define java_io_UnixFileSystem_ACCESS_READ 4L
+#undef java_io_UnixFileSystem_ACCESS_WRITE
+#define java_io_UnixFileSystem_ACCESS_WRITE 2L
+#undef java_io_UnixFileSystem_ACCESS_EXECUTE
+#define java_io_UnixFileSystem_ACCESS_EXECUTE 1L
+#undef java_io_UnixFileSystem_SPACE_TOTAL
+#define java_io_UnixFileSystem_SPACE_TOTAL 0L
+#undef java_io_UnixFileSystem_SPACE_FREE
+#define java_io_UnixFileSystem_SPACE_FREE 1L
+#undef java_io_UnixFileSystem_SPACE_USABLE
+#define java_io_UnixFileSystem_SPACE_USABLE 2L
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: canonicalize0
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_io_UnixFileSystem_canonicalize0
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: getBooleanAttributes0
+ * Signature: (Ljava/io/File;)I
+ */
+JNIEXPORT jint JNICALL Java_java_io_UnixFileSystem_getBooleanAttributes0
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: checkAccess
+ * Signature: (Ljava/io/File;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_checkAccess
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: getLastModifiedTime
+ * Signature: (Ljava/io/File;)J
+ */
+JNIEXPORT jlong JNICALL Java_java_io_UnixFileSystem_getLastModifiedTime
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: getLength
+ * Signature: (Ljava/io/File;)J
+ */
+JNIEXPORT jlong JNICALL Java_java_io_UnixFileSystem_getLength
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: setPermission
+ * Signature: (Ljava/io/File;IZZ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_setPermission
+ (JNIEnv *, jobject, jobject, jint, jboolean, jboolean);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: createFileExclusively
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_createFileExclusively
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: delete0
+ * Signature: (Ljava/io/File;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_delete0
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: list
+ * Signature: (Ljava/io/File;)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_io_UnixFileSystem_list
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: createDirectory
+ * Signature: (Ljava/io/File;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_createDirectory
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: rename0
+ * Signature: (Ljava/io/File;Ljava/io/File;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_rename0
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: setLastModifiedTime
+ * Signature: (Ljava/io/File;J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_setLastModifiedTime
+ (JNIEnv *, jobject, jobject, jlong);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: setReadOnly
+ * Signature: (Ljava/io/File;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_io_UnixFileSystem_setReadOnly
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: getSpace
+ * Signature: (Ljava/io/File;I)J
+ */
+JNIEXPORT jlong JNICALL Java_java_io_UnixFileSystem_getSpace
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: java_io_UnixFileSystem
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_io_UnixFileSystem_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Double.h b/ojluni/src/main/native/java_lang_Double.h
new file mode 100755
index 0000000..37ae67f
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Double.h
@@ -0,0 +1,51 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Double */
+
+#ifndef _Included_java_lang_Double
+#define _Included_java_lang_Double
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Double_serialVersionUID
+#define java_lang_Double_serialVersionUID -8742448824652078965LL
+#undef java_lang_Double_POSITIVE_INFINITY
+#define java_lang_Double_POSITIVE_INFINITY InfD
+#undef java_lang_Double_NEGATIVE_INFINITY
+#define java_lang_Double_NEGATIVE_INFINITY -InfD
+#undef java_lang_Double_NaN
+#define java_lang_Double_NaN NaN
+#undef java_lang_Double_MAX_VALUE
+#define java_lang_Double_MAX_VALUE 1.7976931348623157E308
+#undef java_lang_Double_MIN_NORMAL
+#define java_lang_Double_MIN_NORMAL 2.2250738585072014E-308
+#undef java_lang_Double_MIN_VALUE
+#define java_lang_Double_MIN_VALUE 4.9E-324
+#undef java_lang_Double_MAX_EXPONENT
+#define java_lang_Double_MAX_EXPONENT 1023L
+#undef java_lang_Double_MIN_EXPONENT
+#define java_lang_Double_MIN_EXPONENT -1022L
+#undef java_lang_Double_SIZE
+#define java_lang_Double_SIZE 64L
+#undef java_lang_Double_serialVersionUID
+#define java_lang_Double_serialVersionUID -9172774392245257468LL
+/*
+ * Class: java_lang_Double
+ * Method: doubleToRawLongBits
+ * Signature: (D)J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Double_doubleToRawLongBits
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_Double
+ * Method: longBitsToDouble
+ * Signature: (J)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Double_longBitsToDouble
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Float.h b/ojluni/src/main/native/java_lang_Float.h
new file mode 100755
index 0000000..5e77a7d
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Float.h
@@ -0,0 +1,51 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Float */
+
+#ifndef _Included_java_lang_Float
+#define _Included_java_lang_Float
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Float_serialVersionUID
+#define java_lang_Float_serialVersionUID -8742448824652078965LL
+#undef java_lang_Float_POSITIVE_INFINITY
+#define java_lang_Float_POSITIVE_INFINITY Inff
+#undef java_lang_Float_NEGATIVE_INFINITY
+#define java_lang_Float_NEGATIVE_INFINITY -Inff
+#undef java_lang_Float_NaN
+#define java_lang_Float_NaN NaNf
+#undef java_lang_Float_MAX_VALUE
+#define java_lang_Float_MAX_VALUE 3.4028235E38f
+#undef java_lang_Float_MIN_NORMAL
+#define java_lang_Float_MIN_NORMAL 1.17549435E-38f
+#undef java_lang_Float_MIN_VALUE
+#define java_lang_Float_MIN_VALUE 1.4E-45f
+#undef java_lang_Float_MAX_EXPONENT
+#define java_lang_Float_MAX_EXPONENT 127L
+#undef java_lang_Float_MIN_EXPONENT
+#define java_lang_Float_MIN_EXPONENT -126L
+#undef java_lang_Float_SIZE
+#define java_lang_Float_SIZE 32L
+#undef java_lang_Float_serialVersionUID
+#define java_lang_Float_serialVersionUID -2671257302660747028LL
+/*
+ * Class: java_lang_Float
+ * Method: floatToRawIntBits
+ * Signature: (F)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Float_floatToRawIntBits
+ (JNIEnv *, jclass, jfloat);
+
+/*
+ * Class: java_lang_Float
+ * Method: intBitsToFloat
+ * Signature: (I)F
+ */
+JNIEXPORT jfloat JNICALL Java_java_lang_Float_intBitsToFloat
+ (JNIEnv *, jclass, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Integer.h b/ojluni/src/main/native/java_lang_Integer.h
new file mode 100755
index 0000000..94c8788
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Integer.h
@@ -0,0 +1,23 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Integer */
+
+#ifndef _Included_java_lang_Integer
+#define _Included_java_lang_Integer
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Integer_serialVersionUID
+#define java_lang_Integer_serialVersionUID -8742448824652078965LL
+#undef java_lang_Integer_MIN_VALUE
+#define java_lang_Integer_MIN_VALUE -2147483648L
+#undef java_lang_Integer_MAX_VALUE
+#define java_lang_Integer_MAX_VALUE 2147483647L
+#undef java_lang_Integer_SIZE
+#define java_lang_Integer_SIZE 32L
+#undef java_lang_Integer_serialVersionUID
+#define java_lang_Integer_serialVersionUID 1360826667806852920LL
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Long.h b/ojluni/src/main/native/java_lang_Long.h
new file mode 100755
index 0000000..a0953b3
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Long.h
@@ -0,0 +1,23 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Long */
+
+#ifndef _Included_java_lang_Long
+#define _Included_java_lang_Long
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Long_serialVersionUID
+#define java_lang_Long_serialVersionUID -8742448824652078965LL
+#undef java_lang_Long_MIN_VALUE
+#define java_lang_Long_MIN_VALUE -9223372036854775808LL
+#undef java_lang_Long_MAX_VALUE
+#define java_lang_Long_MAX_VALUE 9223372036854775807LL
+#undef java_lang_Long_SIZE
+#define java_lang_Long_SIZE 64L
+#undef java_lang_Long_serialVersionUID
+#define java_lang_Long_serialVersionUID 4290774380558885855LL
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Runtime.h b/ojluni/src/main/native/java_lang_Runtime.h
new file mode 100755
index 0000000..2ba3dac
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Runtime.h
@@ -0,0 +1,77 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Runtime */
+
+#ifndef _Included_java_lang_Runtime
+#define _Included_java_lang_Runtime
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_lang_Runtime
+ * Method: availableProcessors
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Runtime_availableProcessors
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: freeMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Runtime_freeMemory
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: totalMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Runtime_totalMemory
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: maxMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Runtime_maxMemory
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: gc
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_gc
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: runFinalization0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_runFinalization0
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: traceInstructions
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_traceInstructions
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: java_lang_Runtime
+ * Method: traceMethodCalls
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_traceMethodCalls
+ (JNIEnv *, jobject, jboolean);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Shutdown.h b/ojluni/src/main/native/java_lang_Shutdown.h
new file mode 100755
index 0000000..33a3592
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Shutdown.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Shutdown */
+
+#ifndef _Included_java_lang_Shutdown
+#define _Included_java_lang_Shutdown
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Shutdown_RUNNING
+#define java_lang_Shutdown_RUNNING 0L
+#undef java_lang_Shutdown_HOOKS
+#define java_lang_Shutdown_HOOKS 1L
+#undef java_lang_Shutdown_FINALIZERS
+#define java_lang_Shutdown_FINALIZERS 2L
+#undef java_lang_Shutdown_MAX_SYSTEM_HOOKS
+#define java_lang_Shutdown_MAX_SYSTEM_HOOKS 10L
+/*
+ * Class: java_lang_Shutdown
+ * Method: halt0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Shutdown_halt0
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: java_lang_Shutdown
+ * Method: runAllFinalizers
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Shutdown_runAllFinalizers
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_StrictMath.h b/ojluni/src/main/native/java_lang_StrictMath.h
new file mode 100755
index 0000000..0756f83
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_StrictMath.h
@@ -0,0 +1,177 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_StrictMath */
+
+#ifndef _Included_java_lang_StrictMath
+#define _Included_java_lang_StrictMath
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_StrictMath_E
+#define java_lang_StrictMath_E 2.718281828459045
+#undef java_lang_StrictMath_PI
+#define java_lang_StrictMath_PI 3.141592653589793
+/*
+ * Class: java_lang_StrictMath
+ * Method: sin
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_sin
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: cos
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_cos
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: tan
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_tan
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: asin
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_asin
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: acos
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_acos
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: atan
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_atan
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: exp
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_exp
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: log
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_log
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: log10
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_log10
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: sqrt
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_sqrt
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: cbrt
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_cbrt
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: IEEEremainder
+ * Signature: (DD)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_IEEEremainder
+ (JNIEnv *, jclass, jdouble, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: atan2
+ * Signature: (DD)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_atan2
+ (JNIEnv *, jclass, jdouble, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: pow
+ * Signature: (DD)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_pow
+ (JNIEnv *, jclass, jdouble, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: sinh
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_sinh
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: cosh
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_cosh
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: tanh
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_tanh
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: hypot
+ * Signature: (DD)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_hypot
+ (JNIEnv *, jclass, jdouble, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: expm1
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_expm1
+ (JNIEnv *, jclass, jdouble);
+
+/*
+ * Class: java_lang_StrictMath
+ * Method: log1p
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_StrictMath_log1p
+ (JNIEnv *, jclass, jdouble);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_String.h b/ojluni/src/main/native/java_lang_String.h
new file mode 100755
index 0000000..d398a14
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_String.h
@@ -0,0 +1,23 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_String */
+
+#ifndef _Included_java_lang_String
+#define _Included_java_lang_String
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_String_serialVersionUID
+#define java_lang_String_serialVersionUID -6849794470754667710LL
+/*
+ * Class: java_lang_String
+ * Method: intern
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_String_intern
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_System.h b/ojluni/src/main/native/java_lang_System.h
new file mode 100755
index 0000000..9e2e7c3
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_System.h
@@ -0,0 +1,93 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_System */
+
+#ifndef _Included_java_lang_System
+#define _Included_java_lang_System
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_lang_System
+ * Method: registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_registerNatives
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_System
+ * Method: setIn0
+ * Signature: (Ljava/io/InputStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_setIn0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_System
+ * Method: setOut0
+ * Signature: (Ljava/io/PrintStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_setOut0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_System
+ * Method: setErr0
+ * Signature: (Ljava/io/PrintStream;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_setErr0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_System
+ * Method: currentTimeMillis
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_System_currentTimeMillis
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_System
+ * Method: nanoTime
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_System_nanoTime
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_System
+ * Method: arraycopy
+ * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_arraycopy
+ (JNIEnv *, jclass, jobject, jint, jobject, jint, jint);
+
+/*
+ * Class: java_lang_System
+ * Method: identityHashCode
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_System_identityHashCode
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_System
+ * Method: initProperties
+ * Signature: (Ljava/util/Properties;)Ljava/util/Properties;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_System_initProperties
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_System
+ * Method: mapLibraryName
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_System_mapLibraryName
+ (JNIEnv *, jclass, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Thread.h b/ojluni/src/main/native/java_lang_Thread.h
new file mode 100755
index 0000000..e2778f6
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Thread.h
@@ -0,0 +1,155 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Thread */
+
+#ifndef _Included_java_lang_Thread
+#define _Included_java_lang_Thread
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Thread_MIN_PRIORITY
+#define java_lang_Thread_MIN_PRIORITY 1L
+#undef java_lang_Thread_NORM_PRIORITY
+#define java_lang_Thread_NORM_PRIORITY 5L
+#undef java_lang_Thread_MAX_PRIORITY
+#define java_lang_Thread_MAX_PRIORITY 10L
+/*
+ * Class: java_lang_Thread
+ * Method: registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_registerNatives
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_Thread
+ * Method: currentThread
+ * Signature: ()Ljava/lang/Thread;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_Thread_currentThread
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_Thread
+ * Method: yield
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_yield
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_Thread
+ * Method: sleep
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_sleep
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_lang_Thread
+ * Method: start0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_start0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: isInterrupted
+ * Signature: (Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Thread_isInterrupted
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: java_lang_Thread
+ * Method: isAlive
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Thread_isAlive
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: countStackFrames
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Thread_countStackFrames
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: holdsLock
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Thread_holdsLock
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: dumpThreads
+ * Signature: ([Ljava/lang/Thread;)[[Ljava/lang/StackTraceElement;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_Thread_dumpThreads
+ (JNIEnv *, jclass, jobjectArray);
+
+/*
+ * Class: java_lang_Thread
+ * Method: getThreads
+ * Signature: ()[Ljava/lang/Thread;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_Thread_getThreads
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_lang_Thread
+ * Method: setPriority0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_setPriority0
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_lang_Thread
+ * Method: stop0
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_stop0
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: suspend0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_suspend0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: resume0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_resume0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: interrupt0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_interrupt0
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Thread
+ * Method: setNativeName
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_setNativeName
+ (JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_lang_Throwable.h b/ojluni/src/main/native/java_lang_Throwable.h
new file mode 100755
index 0000000..fd93e9f
--- /dev/null
+++ b/ojluni/src/main/native/java_lang_Throwable.h
@@ -0,0 +1,39 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_lang_Throwable */
+
+#ifndef _Included_java_lang_Throwable
+#define _Included_java_lang_Throwable
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_lang_Throwable_serialVersionUID
+#define java_lang_Throwable_serialVersionUID -3042686055658047285LL
+/*
+ * Class: java_lang_Throwable
+ * Method: fillInStackTrace
+ * Signature: (I)Ljava/lang/Throwable;
+ */
+JNIEXPORT jthrowable JNICALL Java_java_lang_Throwable_fillInStackTrace
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_lang_Throwable
+ * Method: getStackTraceDepth
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Throwable_getStackTraceDepth
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_lang_Throwable
+ * Method: getStackTraceElement
+ * Signature: (I)Ljava/lang/StackTraceElement;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_Throwable_getStackTraceElement
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_DatagramPacket.h b/ojluni/src/main/native/java_net_DatagramPacket.h
new file mode 100755
index 0000000..456b353
--- /dev/null
+++ b/ojluni/src/main/native/java_net_DatagramPacket.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_DatagramPacket */
+
+#ifndef _Included_java_net_DatagramPacket
+#define _Included_java_net_DatagramPacket
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_DatagramPacket
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_DatagramPacket_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_Inet4Address.h b/ojluni/src/main/native/java_net_Inet4Address.h
new file mode 100755
index 0000000..9a618a5
--- /dev/null
+++ b/ojluni/src/main/native/java_net_Inet4Address.h
@@ -0,0 +1,35 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_Inet4Address */
+
+#ifndef _Included_java_net_Inet4Address
+#define _Included_java_net_Inet4Address
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_Inet4Address_IPv4
+#define java_net_Inet4Address_IPv4 1L
+#undef java_net_Inet4Address_IPv6
+#define java_net_Inet4Address_IPv6 2L
+#undef java_net_Inet4Address_serialVersionUID
+#define java_net_Inet4Address_serialVersionUID 3286316764910316507LL
+#undef java_net_Inet4Address_maxCacheTime
+#define java_net_Inet4Address_maxCacheTime 5000LL
+#undef java_net_Inet4Address_INADDRSZ
+#define java_net_Inet4Address_INADDRSZ 4L
+#undef java_net_Inet4Address_serialVersionUID
+#define java_net_Inet4Address_serialVersionUID 3286316764910316507LL
+#undef java_net_Inet4Address_loopback
+#define java_net_Inet4Address_loopback 2130706433L
+/*
+ * Class: java_net_Inet4Address
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_Inet4Address_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_Inet4AddressImpl.h b/ojluni/src/main/native/java_net_Inet4AddressImpl.h
new file mode 100755
index 0000000..fbf88af
--- /dev/null
+++ b/ojluni/src/main/native/java_net_Inet4AddressImpl.h
@@ -0,0 +1,45 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_Inet4AddressImpl */
+
+#ifndef _Included_java_net_Inet4AddressImpl
+#define _Included_java_net_Inet4AddressImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_net_Inet4AddressImpl_getLocalHostName
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[Ljava/net/InetAddress;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_net_Inet4AddressImpl_lookupAllHostAddr
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: getHostByAddr
+ * Signature: ([B)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_net_Inet4AddressImpl_getHostByAddr
+ (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class: java_net_Inet4AddressImpl
+ * Method: isReachable0
+ * Signature: ([BI[BI)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_Inet4AddressImpl_isReachable0
+ (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_Inet6Address.h b/ojluni/src/main/native/java_net_Inet6Address.h
new file mode 100755
index 0000000..3936063
--- /dev/null
+++ b/ojluni/src/main/native/java_net_Inet6Address.h
@@ -0,0 +1,35 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_Inet6Address */
+
+#ifndef _Included_java_net_Inet6Address
+#define _Included_java_net_Inet6Address
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_Inet6Address_IPv4
+#define java_net_Inet6Address_IPv4 1L
+#undef java_net_Inet6Address_IPv6
+#define java_net_Inet6Address_IPv6 2L
+#undef java_net_Inet6Address_serialVersionUID
+#define java_net_Inet6Address_serialVersionUID 3286316764910316507LL
+#undef java_net_Inet6Address_maxCacheTime
+#define java_net_Inet6Address_maxCacheTime 5000LL
+#undef java_net_Inet6Address_INADDRSZ
+#define java_net_Inet6Address_INADDRSZ 16L
+#undef java_net_Inet6Address_serialVersionUID
+#define java_net_Inet6Address_serialVersionUID 6880410070516793377LL
+#undef java_net_Inet6Address_INT16SZ
+#define java_net_Inet6Address_INT16SZ 2L
+/*
+ * Class: java_net_Inet6Address
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_Inet6Address_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_Inet6AddressImpl.h b/ojluni/src/main/native/java_net_Inet6AddressImpl.h
new file mode 100755
index 0000000..ab5f1d0
--- /dev/null
+++ b/ojluni/src/main/native/java_net_Inet6AddressImpl.h
@@ -0,0 +1,45 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_Inet6AddressImpl */
+
+#ifndef _Included_java_net_Inet6AddressImpl
+#define _Included_java_net_Inet6AddressImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: getLocalHostName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_net_Inet6AddressImpl_getLocalHostName
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: lookupAllHostAddr
+ * Signature: (Ljava/lang/String;)[Ljava/net/InetAddress;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_net_Inet6AddressImpl_lookupAllHostAddr
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: getHostByAddr
+ * Signature: ([B)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_net_Inet6AddressImpl_getHostByAddr
+ (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class: java_net_Inet6AddressImpl
+ * Method: isReachable0
+ * Signature: ([BII[BII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_Inet6AddressImpl_isReachable0
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jbyteArray, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_InetAddress.h b/ojluni/src/main/native/java_net_InetAddress.h
new file mode 100755
index 0000000..8125ff1
--- /dev/null
+++ b/ojluni/src/main/native/java_net_InetAddress.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_InetAddress */
+
+#ifndef _Included_java_net_InetAddress
+#define _Included_java_net_InetAddress
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_InetAddress_IPv4
+#define java_net_InetAddress_IPv4 1L
+#undef java_net_InetAddress_IPv6
+#define java_net_InetAddress_IPv6 2L
+#undef java_net_InetAddress_serialVersionUID
+#define java_net_InetAddress_serialVersionUID 3286316764910316507LL
+#undef java_net_InetAddress_maxCacheTime
+#define java_net_InetAddress_maxCacheTime 5000LL
+/*
+ * Class: java_net_InetAddress
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_InetAddress_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_InetAddressImplFactory.h b/ojluni/src/main/native/java_net_InetAddressImplFactory.h
new file mode 100755
index 0000000..4c96086
--- /dev/null
+++ b/ojluni/src/main/native/java_net_InetAddressImplFactory.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_InetAddressImplFactory */
+
+#ifndef _Included_java_net_InetAddressImplFactory
+#define _Included_java_net_InetAddressImplFactory
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_InetAddressImplFactory
+ * Method: isIPv6Supported
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_InetAddressImplFactory_isIPv6Supported
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_NetworkInterface.h b/ojluni/src/main/native/java_net_NetworkInterface.h
new file mode 100755
index 0000000..2a9c0b7
--- /dev/null
+++ b/ojluni/src/main/native/java_net_NetworkInterface.h
@@ -0,0 +1,101 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_NetworkInterface */
+
+#ifndef _Included_java_net_NetworkInterface
+#define _Included_java_net_NetworkInterface
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getAll
+ * Signature: ()[Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_net_NetworkInterface_getAll
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByName0
+ * Signature: (Ljava/lang/String;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByIndex0
+ * Signature: (I)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getByInetAddress0
+ * Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isUp0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isLoopback0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: supportsMulticast0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: isP2P0
+ * Signature: (Ljava/lang/String;I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMacAddr0
+ * Signature: ([BLjava/lang/String;I)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0
+ (JNIEnv *, jclass, jbyteArray, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: getMTU0
+ * Signature: (Ljava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: java_net_NetworkInterface
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_PlainDatagramSocketImpl.h b/ojluni/src/main/native/java_net_PlainDatagramSocketImpl.h
new file mode 100755
index 0000000..50719c4
--- /dev/null
+++ b/ojluni/src/main/native/java_net_PlainDatagramSocketImpl.h
@@ -0,0 +1,157 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_PlainDatagramSocketImpl */
+
+#ifndef _Included_java_net_PlainDatagramSocketImpl
+#define _Included_java_net_PlainDatagramSocketImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: bind0
+ * Signature: (ILjava/net/InetAddress;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_bind0
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: send
+ * Signature: (Ljava/net/DatagramPacket;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_send
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: peek
+ * Signature: (Ljava/net/InetAddress;)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_peek
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: peekData
+ * Signature: (Ljava/net/DatagramPacket;)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_peekData
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: receive0
+ * Signature: (Ljava/net/DatagramPacket;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_receive0
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: setTimeToLive
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_setTimeToLive
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: getTimeToLive
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainDatagramSocketImpl_getTimeToLive
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: setTTL
+ * Signature: (B)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_setTTL
+ (JNIEnv *, jobject, jbyte);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: getTTL
+ * Signature: ()B
+ */
+JNIEXPORT jbyte JNICALL Java_java_net_PlainDatagramSocketImpl_getTTL
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: join
+ * Signature: (Ljava/net/InetAddress;Ljava/net/NetworkInterface;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_join
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: leave
+ * Signature: (Ljava/net/InetAddress;Ljava/net/NetworkInterface;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_leave
+ (JNIEnv *, jobject, jobject, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: datagramSocketCreate
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: datagramSocketClose
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_datagramSocketClose
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: socketSetOption
+ * Signature: (ILjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_socketSetOption
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: socketGetOption
+ * Signature: (I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_net_PlainDatagramSocketImpl_socketGetOption
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: connect0
+ * Signature: (Ljava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_connect0
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: disconnect0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_disconnect0
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_net_PlainDatagramSocketImpl
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainDatagramSocketImpl_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_PlainSocketImpl.h b/ojluni/src/main/native/java_net_PlainSocketImpl.h
new file mode 100755
index 0000000..9afa226
--- /dev/null
+++ b/ojluni/src/main/native/java_net_PlainSocketImpl.h
@@ -0,0 +1,113 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_PlainSocketImpl */
+
+#ifndef _Included_java_net_PlainSocketImpl
+#define _Included_java_net_PlainSocketImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_PlainSocketImpl_SHUT_RD
+#define java_net_PlainSocketImpl_SHUT_RD 0L
+#undef java_net_PlainSocketImpl_SHUT_WR
+#define java_net_PlainSocketImpl_SHUT_WR 1L
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketCreate
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketCreate
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketConnect
+ * Signature: (Ljava/net/InetAddress;II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketConnect
+ (JNIEnv *, jobject, jobject, jint, jint);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketBind
+ * Signature: (Ljava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketBind
+ (JNIEnv *, jobject, jobject, jint);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketListen
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketListen
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketAccept
+ * Signature: (Ljava/net/SocketImpl;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketAccept
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_socketAvailable
+ (JNIEnv *, jobject);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketClose0
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketClose0
+ (JNIEnv *, jobject, jboolean);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketShutdown
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketShutdown
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: initProto
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_initProto
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketSetOption
+ * Signature: (IZLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketSetOption
+ (JNIEnv *, jobject, jint, jboolean, jobject);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketGetOption
+ * Signature: (ILjava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_socketGetOption
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: java_net_PlainSocketImpl
+ * Method: socketSendUrgentData
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_socketSendUrgentData
+ (JNIEnv *, jobject, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_SocketInputStream.h b/ojluni/src/main/native/java_net_SocketInputStream.h
new file mode 100755
index 0000000..47ce360
--- /dev/null
+++ b/ojluni/src/main/native/java_net_SocketInputStream.h
@@ -0,0 +1,31 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_SocketInputStream */
+
+#ifndef _Included_java_net_SocketInputStream
+#define _Included_java_net_SocketInputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_SocketInputStream_MAX_SKIP_BUFFER_SIZE
+#define java_net_SocketInputStream_MAX_SKIP_BUFFER_SIZE 2048L
+/*
+ * Class: java_net_SocketInputStream
+ * Method: socketRead0
+ * Signature: (Ljava/io/FileDescriptor;[BIII)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_SocketInputStream_socketRead0
+ (JNIEnv *, jobject, jobject, jbyteArray, jint, jint, jint);
+
+/*
+ * Class: java_net_SocketInputStream
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_SocketInputStream_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_SocketOptions.h b/ojluni/src/main/native/java_net_SocketOptions.h
new file mode 100755
index 0000000..f744fc3
--- /dev/null
+++ b/ojluni/src/main/native/java_net_SocketOptions.h
@@ -0,0 +1,41 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_SocketOptions */
+
+#ifndef _Included_java_net_SocketOptions
+#define _Included_java_net_SocketOptions
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_net_SocketOptions_TCP_NODELAY
+#define java_net_SocketOptions_TCP_NODELAY 1L
+#undef java_net_SocketOptions_SO_BINDADDR
+#define java_net_SocketOptions_SO_BINDADDR 15L
+#undef java_net_SocketOptions_SO_REUSEADDR
+#define java_net_SocketOptions_SO_REUSEADDR 4L
+#undef java_net_SocketOptions_SO_BROADCAST
+#define java_net_SocketOptions_SO_BROADCAST 32L
+#undef java_net_SocketOptions_IP_MULTICAST_IF
+#define java_net_SocketOptions_IP_MULTICAST_IF 16L
+#undef java_net_SocketOptions_IP_MULTICAST_IF2
+#define java_net_SocketOptions_IP_MULTICAST_IF2 31L
+#undef java_net_SocketOptions_IP_MULTICAST_LOOP
+#define java_net_SocketOptions_IP_MULTICAST_LOOP 18L
+#undef java_net_SocketOptions_IP_TOS
+#define java_net_SocketOptions_IP_TOS 3L
+#undef java_net_SocketOptions_SO_LINGER
+#define java_net_SocketOptions_SO_LINGER 128L
+#undef java_net_SocketOptions_SO_TIMEOUT
+#define java_net_SocketOptions_SO_TIMEOUT 4102L
+#undef java_net_SocketOptions_SO_SNDBUF
+#define java_net_SocketOptions_SO_SNDBUF 4097L
+#undef java_net_SocketOptions_SO_RCVBUF
+#define java_net_SocketOptions_SO_RCVBUF 4098L
+#undef java_net_SocketOptions_SO_KEEPALIVE
+#define java_net_SocketOptions_SO_KEEPALIVE 8L
+#undef java_net_SocketOptions_SO_OOBINLINE
+#define java_net_SocketOptions_SO_OOBINLINE 4099L
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_net_SocketOutputStream.h b/ojluni/src/main/native/java_net_SocketOutputStream.h
new file mode 100755
index 0000000..2fa8d94
--- /dev/null
+++ b/ojluni/src/main/native/java_net_SocketOutputStream.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_net_SocketOutputStream */
+
+#ifndef _Included_java_net_SocketOutputStream
+#define _Included_java_net_SocketOutputStream
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_net_SocketOutputStream
+ * Method: socketWrite0
+ * Signature: (Ljava/io/FileDescriptor;[BII)V
+ */
+JNIEXPORT void JNICALL Java_java_net_SocketOutputStream_socketWrite0
+ (JNIEnv *, jobject, jobject, jbyteArray, jint, jint);
+
+/*
+ * Class: java_net_SocketOutputStream
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_SocketOutputStream_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_props.h b/ojluni/src/main/native/java_props.h
new file mode 100755
index 0000000..de1947168
--- /dev/null
+++ b/ojluni/src/main/native/java_props.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVA_PROPS_H
+#define _JAVA_PROPS_H
+
+#include <jni_util.h>
+
+/* The preferred native type for storing text on the current OS */
+#ifdef WIN32
+#include <tchar.h>
+typedef WCHAR nchar;
+#else
+typedef char nchar;
+#endif
+
+typedef struct {
+ char *os_name;
+ char *os_version;
+ char *os_arch;
+
+ nchar *tmp_dir;
+ nchar *font_dir;
+ nchar *user_dir;
+
+ char *file_separator;
+ char *path_separator;
+ char *line_separator;
+
+ nchar *user_name;
+ nchar *user_home;
+
+ char *language;
+ char *format_language;
+ char *display_language;
+ char *script;
+ char *format_script;
+ char *display_script;
+ char *country;
+ char *format_country;
+ char *display_country;
+ char *variant;
+ char *format_variant;
+ char *display_variant;
+ char *encoding;
+ char *sun_jnu_encoding;
+ char *timezone;
+
+ char *printerJob;
+ char *graphics_env;
+ char *awt_toolkit;
+
+ char *unicode_encoding; /* The default endianness of unicode
+ i.e. UnicodeBig or UnicodeLittle */
+
+ const char *cpu_isalist; /* list of supported instruction sets */
+
+ char *cpu_endian; /* endianness of platform */
+
+ char *data_model; /* 32 or 64 bit data model */
+
+ char *patch_level; /* patches/service packs installed */
+
+ char *desktop; /* Desktop name. */
+
+#ifdef MACOSX
+ // These are for proxy-related information.
+ // Note that if these platform-specific extensions get out of hand we should make a new
+ // structure for them and #include it here.
+ int httpProxyEnabled;
+ char *httpHost;
+ char *httpPort;
+
+ int httpsProxyEnabled;
+ char *httpsHost;
+ char *httpsPort;
+
+ int ftpProxyEnabled;
+ char *ftpHost;
+ char *ftpPort;
+
+ int socksProxyEnabled;
+ char *socksHost;
+ char *socksPort;
+
+ int gopherProxyEnabled;
+ char *gopherHost;
+ char *gopherPort;
+
+ char *exceptionList;
+#endif
+
+} java_props_t;
+
+java_props_t *GetJavaProperties(JNIEnv *env);
+jstring GetStringPlatform(JNIEnv *env, nchar* str);
+
+#endif /* _JAVA_PROPS_H */
diff --git a/ojluni/src/main/native/java_props_md.c b/ojluni/src/main/native/java_props_md.c
new file mode 100755
index 0000000..3a2d6e0
--- /dev/null
+++ b/ojluni/src/main/native/java_props_md.c
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+#include <stdio.h>
+#include <ctype.h>
+#endif
+#include <pwd.h>
+#include <locale.h>
+#ifndef ARCHPROPNAME
+#error "The macro ARCHPROPNAME has not been defined"
+#endif
+#include <sys/utsname.h> /* For os_name and os_version */
+#include <langinfo.h> /* For nl_langinfo */
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <time.h>
+#include <errno.h>
+
+#ifdef MACOSX
+#include "java_props_macosx.h"
+#endif
+
+#if defined(_ALLBSD_SOURCE)
+#if !defined(P_tmpdir)
+#include <paths.h>
+#define P_tmpdir _PATH_VARTMP
+#endif
+#endif
+
+#include "locale_str.h"
+#include "java_props.h"
+
+#if !defined(_ALLBSD_SOURCE)
+#ifdef __linux__
+ #ifndef CODESET
+ #define CODESET _NL_CTYPE_CODESET_NAME
+ #endif
+#else
+#ifdef ALT_CODESET_KEY
+#define CODESET ALT_CODESET_KEY
+#endif
+#endif
+#endif /* !_ALLBSD_SOURCE */
+
+#ifdef JAVASE_EMBEDDED
+#include <dlfcn.h>
+#include <sys/stat.h>
+#endif
+
+/* Take an array of string pairs (map of key->value) and a string (key).
+ * Examine each pair in the map to see if the first string (key) matches the
+ * string. If so, store the second string of the pair (value) in the value and
+ * return 1. Otherwise do nothing and return 0. The end of the map is
+ * indicated by an empty string at the start of a pair (key of "").
+ */
+static int
+mapLookup(char* map[], const char* key, char** value) {
+ int i;
+ for (i = 0; strcmp(map[i], ""); i += 2){
+ if (!strcmp(key, map[i])){
+ *value = map[i + 1];
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* This function sets an environment variable using envstring.
+ * The format of envstring is "name=value".
+ * If the name has already existed, it will append value to the name.
+ */
+static void
+setPathEnvironment(char *envstring)
+{
+ char name[20], *value, *current;
+
+ value = strchr(envstring, '='); /* locate name and value separator */
+
+ if (! value)
+ return; /* not a valid environment setting */
+
+ /* copy first part as environment name */
+ strncpy(name, envstring, value - envstring);
+ name[value-envstring] = '\0';
+
+ value++; /* set value point to value of the envstring */
+
+ current = getenv(name);
+ if (current) {
+ if (! strstr(current, value)) {
+ /* value is not found in current environment, append it */
+ char *temp = malloc(strlen(envstring) + strlen(current) + 2);
+ strcpy(temp, name);
+ strcat(temp, "=");
+ strcat(temp, current);
+ strcat(temp, ":");
+ strcat(temp, value);
+ putenv(temp);
+ }
+ /* else the value has already been set, do nothing */
+ }
+ else {
+ /* environment variable is not found */
+ putenv(envstring);
+ }
+}
+
+#ifndef P_tmpdir
+#define P_tmpdir "/var/tmp"
+#endif
+
+static int ParseLocale(int cat, char ** std_language, char ** std_script,
+ char ** std_country, char ** std_variant, char ** std_encoding) {
+ char temp[64];
+ char *language = NULL, *country = NULL, *variant = NULL,
+ *encoding = NULL;
+ char *p, encoding_variant[64];
+ char *lc;
+
+ /* Query the locale set for the category */
+
+#ifdef MACOSX
+ lc = setupMacOSXLocale(cat); // malloc'd memory, need to free
+#else
+ lc = setlocale(cat, NULL);
+#endif
+
+#ifndef __linux__
+ if (lc == NULL) {
+ return 0;
+ }
+
+ if (cat == LC_CTYPE) {
+ /*
+ * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
+ * locales. Since we don't depend on the libc @euro behavior,
+ * we just remove the qualifier.
+ * On Linux, the bug doesn't occur; on the other hand, @euro
+ * is needed there because it's a shortcut that also determines
+ * the encoding - without it, we wouldn't get ISO-8859-15.
+ * Therefore, this code section is Solaris-specific.
+ */
+ lc = strdup(lc); /* keep a copy, setlocale trashes original. */
+ strcpy(temp, lc);
+ p = strstr(temp, "@euro");
+ if (p != NULL) {
+ *p = '\0';
+ setlocale(LC_ALL, temp);
+ }
+ }
+#else
+ if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
+ lc = "en_US";
+ }
+#endif
+
+ /*
+ * locale string format in Solaris is
+ * <language name>_<country name>.<encoding name>@<variant name>
+ * <country name>, <encoding name>, and <variant name> are optional.
+ */
+
+ strcpy(temp, lc);
+#ifdef MACOSX
+ free(lc); // malloced memory
+#endif
+ /* Parse the language, country, encoding, and variant from the
+ * locale. Any of the elements may be missing, but they must occur
+ * in the order language_country.encoding@variant, and must be
+ * preceded by their delimiter (except for language).
+ *
+ * If the locale name (without .encoding@variant, if any) matches
+ * any of the names in the locale_aliases list, map it to the
+ * corresponding full locale name. Most of the entries in the
+ * locale_aliases list are locales that include a language name but
+ * no country name, and this facility is used to map each language
+ * to a default country if that's possible. It's also used to map
+ * the Solaris locale aliases to their proper Java locale IDs.
+ */
+ if ((p = strchr(temp, '.')) != NULL) {
+ strcpy(encoding_variant, p); /* Copy the leading '.' */
+ *p = '\0';
+ } else if ((p = strchr(temp, '@')) != NULL) {
+ strcpy(encoding_variant, p); /* Copy the leading '@' */
+ *p = '\0';
+ } else {
+ *encoding_variant = '\0';
+ }
+
+ if (mapLookup(locale_aliases, temp, &p)) {
+ strcpy(temp, p);
+ // check the "encoding_variant" again, if any.
+ if ((p = strchr(temp, '.')) != NULL) {
+ strcpy(encoding_variant, p); /* Copy the leading '.' */
+ *p = '\0';
+ } else if ((p = strchr(temp, '@')) != NULL) {
+ strcpy(encoding_variant, p); /* Copy the leading '@' */
+ *p = '\0';
+ }
+ }
+
+ language = temp;
+ if ((country = strchr(temp, '_')) != NULL) {
+ *country++ = '\0';
+ }
+
+ p = encoding_variant;
+ if ((encoding = strchr(p, '.')) != NULL) {
+ p[encoding++ - p] = '\0';
+ p = encoding;
+ }
+ if ((variant = strchr(p, '@')) != NULL) {
+ p[variant++ - p] = '\0';
+ }
+
+ /* Normalize the language name */
+ if (std_language != NULL) {
+ *std_language = "en";
+ if (language != NULL && mapLookup(language_names, language, std_language) == 0) {
+ *std_language = malloc(strlen(language)+1);
+ strcpy(*std_language, language);
+ }
+ }
+
+ /* Normalize the country name */
+ if (std_country != NULL && country != NULL) {
+ if (mapLookup(country_names, country, std_country) == 0) {
+ *std_country = malloc(strlen(country)+1);
+ strcpy(*std_country, country);
+ }
+ }
+
+ /* Normalize the script and variant name. Note that we only use
+ * variants listed in the mapping array; others are ignored.
+ */
+ if (variant != NULL) {
+ if (std_script != NULL) {
+ mapLookup(script_names, variant, std_script);
+ }
+
+ if (std_variant != NULL) {
+ mapLookup(variant_names, variant, std_variant);
+ }
+ }
+
+ /* Normalize the encoding name. Note that we IGNORE the string
+ * 'encoding' extracted from the locale name above. Instead, we use the
+ * more reliable method of calling nl_langinfo(CODESET). This function
+ * returns an empty string if no encoding is set for the given locale
+ * (e.g., the C or POSIX locales); we use the default ISO 8859-1
+ * converter for such locales.
+ */
+ if (std_encoding != NULL) {
+ /* OK, not so reliable - nl_langinfo() gives wrong answers on
+ * Euro locales, in particular. */
+ if (strcmp(p, "ISO8859-15") == 0)
+ p = "ISO8859-15";
+ else
+ p = nl_langinfo(CODESET);
+
+ /* Convert the bare "646" used on Solaris to a proper IANA name */
+ if (strcmp(p, "646") == 0)
+ p = "ISO646-US";
+
+ /* return same result nl_langinfo would return for en_UK,
+ * in order to use optimizations. */
+ *std_encoding = (*p != '\0') ? p : "ISO8859-1";
+
+#ifdef __linux__
+ /*
+ * Remap the encoding string to a different value for japanese
+ * locales on linux so that customized converters are used instead
+ * of the default converter for "EUC-JP". The customized converters
+ * omit support for the JIS0212 encoding which is not supported by
+ * the variant of "EUC-JP" encoding used on linux
+ */
+ if (strcmp(p, "EUC-JP") == 0) {
+ *std_encoding = "EUC-JP-LINUX";
+ }
+#else
+ if (strcmp(p,"eucJP") == 0) {
+ /* For Solaris use customized vendor defined character
+ * customized EUC-JP converter
+ */
+ *std_encoding = "eucJP-open";
+ } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
+ /*
+ * Remap the encoding string to Big5_Solaris which augments
+ * the default converter for Solaris Big5 locales to include
+ * seven additional ideographic characters beyond those included
+ * in the Java "Big5" converter.
+ */
+ *std_encoding = "Big5_Solaris";
+ } else if (strcmp(p, "Big5-HKSCS") == 0) {
+ /*
+ * Solaris uses HKSCS2001
+ */
+ *std_encoding = "Big5-HKSCS-2001";
+ }
+#endif
+ }
+
+ return 1;
+}
+
+#ifdef JAVASE_EMBEDDED
+/* Determine the default embedded toolkit based on whether lib/xawt/
+ * exists in the JRE. This can still be overridden by -Dawt.toolkit=XXX
+ */
+static char* getEmbeddedToolkit() {
+ Dl_info dlinfo;
+ char buf[MAXPATHLEN];
+ int32_t len;
+ char *p;
+ struct stat statbuf;
+
+ /* Get address of this library and the directory containing it. */
+ dladdr((void *)getEmbeddedToolkit, &dlinfo);
+ realpath((char *)dlinfo.dli_fname, buf);
+ len = strlen(buf);
+ p = strrchr(buf, '/');
+ /* Default AWT Toolkit on Linux and Solaris is XAWT. */
+ strncpy(p, "/xawt/", MAXPATHLEN-len-1);
+ /* Check if it exists */
+ if (stat(buf, &statbuf) == -1 && errno == ENOENT) {
+ /* No - this is a reduced-headless-jre so use special HToolkit */
+ return "sun.awt.HToolkit";
+ }
+ else {
+ /* Yes - this is a headful JRE so fallback to SE defaults */
+ return NULL;
+ }
+}
+#endif
+
+/* This function gets called very early, before VM_CALLS are setup.
+ * Do not use any of the VM_CALLS entries!!!
+ */
+java_props_t *
+GetJavaProperties(JNIEnv *env)
+{
+ static java_props_t sprops;
+ char *v; /* tmp var */
+
+ if (sprops.user_dir) {
+ return &sprops;
+ }
+
+ /* tmp dir */
+ sprops.tmp_dir = P_tmpdir;
+#ifdef MACOSX
+ /* darwin has a per-user temp dir */
+ static char tmp_path[PATH_MAX];
+ int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, tmp_path, PATH_MAX);
+ if (pathSize > 0 && pathSize <= PATH_MAX) {
+ sprops.tmp_dir = tmp_path;
+ }
+#endif /* MACOSX */
+
+ /* Printing properties */
+#ifdef MACOSX
+ sprops.printerJob = "sun.lwawt.macosx.CPrinterJob";
+#else
+ sprops.printerJob = "sun.print.PSPrinterJob";
+#endif
+
+ /* patches/service packs installed */
+ sprops.patch_level = "unknown";
+
+ /* Java 2D properties */
+#ifdef MACOSX
+ PreferredToolkit prefToolkit = getPreferredToolkit();
+ switch (prefToolkit) {
+ case CToolkit:
+ case HToolkit:
+ sprops.graphics_env = "sun.awt.CGraphicsEnvironment";
+ break;
+ case XToolkit:
+#endif
+ sprops.graphics_env = "sun.awt.X11GraphicsEnvironment";
+#ifdef MACOSX
+ break;
+ }
+#endif
+ /* AWT properties */
+#ifdef JAVASE_EMBEDDED
+ sprops.awt_toolkit = getEmbeddedToolkit();
+ if (sprops.awt_toolkit == NULL) // default as below
+#endif
+#ifdef MACOSX
+ switch (prefToolkit) {
+ case CToolkit:
+ sprops.awt_toolkit = "sun.lwawt.macosx.LWCToolkit";
+ break;
+ case XToolkit:
+#endif
+ sprops.awt_toolkit = "sun.awt.X11.XToolkit";
+#ifdef MACOSX
+ break;
+ default:
+ sprops.awt_toolkit = "sun.awt.HToolkit";
+ break;
+ }
+#endif
+
+ /* This is used only for debugging of font problems. */
+ v = getenv("JAVA2D_FONTPATH");
+ sprops.font_dir = v ? v : NULL;
+
+#ifdef SI_ISALIST
+ /* supported instruction sets */
+ {
+ char list[258];
+ sysinfo(SI_ISALIST, list, sizeof(list));
+ sprops.cpu_isalist = strdup(list);
+ }
+#else
+ sprops.cpu_isalist = NULL;
+#endif
+
+ /* endianness of platform */
+ {
+ unsigned int endianTest = 0xff000000;
+ if (((char*)(&endianTest))[0] != 0)
+ sprops.cpu_endian = "big";
+ else
+ sprops.cpu_endian = "little";
+ }
+
+ /* os properties */
+ {
+#ifdef MACOSX
+ setOSNameAndVersion(&sprops);
+#else
+ struct utsname name;
+ uname(&name);
+ sprops.os_name = strdup(name.sysname);
+ sprops.os_version = strdup(name.release);
+#endif
+
+ sprops.os_arch = ARCHPROPNAME;
+
+ if (getenv("GNOME_DESKTOP_SESSION_ID") != NULL) {
+ sprops.desktop = "gnome";
+ }
+ else {
+ sprops.desktop = NULL;
+ }
+ }
+
+ /* Determine the language, country, variant, and encoding from the host,
+ * and store these in the user.language, user.country, user.variant and
+ * file.encoding system properties. */
+ setlocale(LC_ALL, "");
+ if (ParseLocale(LC_CTYPE,
+ &(sprops.format_language),
+ &(sprops.format_script),
+ &(sprops.format_country),
+ &(sprops.format_variant),
+ &(sprops.encoding))) {
+ ParseLocale(LC_MESSAGES,
+ &(sprops.language),
+ &(sprops.script),
+ &(sprops.country),
+ &(sprops.variant),
+ NULL);
+ } else {
+ sprops.language = "en";
+ sprops.encoding = "ISO8859-1";
+ }
+ sprops.display_language = sprops.language;
+ sprops.display_script = sprops.script;
+ sprops.display_country = sprops.country;
+ sprops.display_variant = sprops.variant;
+
+#ifdef MACOSX
+ sprops.sun_jnu_encoding = "UTF-8";
+#else
+ sprops.sun_jnu_encoding = sprops.encoding;
+#endif
+
+#ifdef _ALLBSD_SOURCE
+#if BYTE_ORDER == _LITTLE_ENDIAN
+ sprops.unicode_encoding = "UnicodeLittle";
+ #else
+ sprops.unicode_encoding = "UnicodeBig";
+ #endif
+#else /* !_ALLBSD_SOURCE */
+#ifdef __linux__
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ sprops.unicode_encoding = "UnicodeLittle";
+#else
+ sprops.unicode_encoding = "UnicodeBig";
+#endif
+#else
+ sprops.unicode_encoding = "UnicodeBig";
+#endif
+#endif /* _ALLBSD_SOURCE */
+
+ /* user properties */
+ {
+ struct passwd *pwent = getpwuid(getuid());
+ sprops.user_name = pwent ? strdup(pwent->pw_name) : "?";
+ sprops.user_home = pwent ? strdup(pwent->pw_dir) : "?";
+ }
+
+ /* User TIMEZONE */
+ {
+ /*
+ * We defer setting up timezone until it's actually necessary.
+ * Refer to TimeZone.getDefault(). However, the system
+ * property is necessary to be able to be set by the command
+ * line interface -D. Here temporarily set a null string to
+ * timezone.
+ */
+ tzset(); /* for compatibility */
+ sprops.timezone = "";
+ }
+
+ /* Current directory */
+ {
+ char buf[MAXPATHLEN];
+ errno = 0;
+ if (getcwd(buf, sizeof(buf)) == NULL)
+ JNU_ThrowByName(env, "java/lang/Error",
+ "Properties init: Could not determine current working directory.");
+ else
+ sprops.user_dir = strdup(buf);
+ }
+
+ sprops.file_separator = "/";
+ sprops.path_separator = ":";
+ sprops.line_separator = "\n";
+
+#if !defined(_ALLBSD_SOURCE)
+ /* Append CDE message and resource search path to NLSPATH and
+ * XFILESEARCHPATH, in order to pick localized message for
+ * FileSelectionDialog window (Bug 4173641).
+ */
+ setPathEnvironment("NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat");
+ setPathEnvironment("XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt");
+#endif
+
+
+#ifdef MACOSX
+ setProxyProperties(&sprops);
+#endif
+
+ return &sprops;
+}
+
+jstring
+GetStringPlatform(JNIEnv *env, nchar* cstr)
+{
+ return JNU_NewStringPlatform(env, cstr);
+}
diff --git a/ojluni/src/main/native/java_util_zip_Adler32.c b/ojluni/src/main/native/java_util_zip_Adler32.c
new file mode 100755
index 0000000..87f265d
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_Adler32.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native method support for java.util.zip.Adler32
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include <zlib.h>
+
+#include "java_util_zip_Adler32.h"
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Adler32_update(JNIEnv *env, jclass cls, jint adler, jint b)
+{
+ Bytef buf[1];
+
+ buf[0] = (Bytef)b;
+ return adler32(adler, buf, 1);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Adler32_updateBytes(JNIEnv *env, jclass cls, jint adler,
+ jarray b, jint off, jint len)
+{
+ Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (buf) {
+ adler = adler32(adler, buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ }
+ return adler;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Adler32_updateByteBuffer(JNIEnv *env, jclass cls, jint adler,
+ jlong address, jint off, jint len)
+{
+ Bytef *buf = (Bytef *)jlong_to_ptr(address);
+ if (buf) {
+ adler = adler32(adler, buf + off, len);
+ }
+ return adler;
+}
diff --git a/ojluni/src/main/native/java_util_zip_CRC32.c b/ojluni/src/main/native/java_util_zip_CRC32.c
new file mode 100755
index 0000000..689b34b
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_CRC32.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native method support for java.util.zip.CRC32
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include <zlib.h>
+
+#include "java_util_zip_CRC32.h"
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_CRC32_update(JNIEnv *env, jclass cls, jint crc, jint b)
+{
+ Bytef buf[1];
+
+ buf[0] = (Bytef)b;
+ return crc32(crc, buf, 1);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_CRC32_updateBytes(JNIEnv *env, jclass cls, jint crc,
+ jarray b, jint off, jint len)
+{
+ Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (buf) {
+ crc = crc32(crc, buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ }
+ return crc;
+}
+
+JNIEXPORT jint ZIP_CRC32(jint crc, const jbyte *buf, jint len)
+{
+ return crc32(crc, (Bytef*)buf, len);
+}
diff --git a/ojluni/src/main/native/java_util_zip_CRC32.h b/ojluni/src/main/native/java_util_zip_CRC32.h
new file mode 100755
index 0000000..73ea19f
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_CRC32.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_util_zip_CRC32 */
+
+#ifndef _Included_java_util_zip_CRC32
+#define _Included_java_util_zip_CRC32
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_util_zip_CRC32
+ * Method: update
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_CRC32_update
+ (JNIEnv *, jclass, jint, jint);
+
+/*
+ * Class: java_util_zip_CRC32
+ * Method: updateBytes
+ * Signature: (I[BII)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_CRC32_updateBytes
+ (JNIEnv *, jclass, jint, jbyteArray, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_util_zip_Deflater.c b/ojluni/src/main/native/java_util_zip_Deflater.c
new file mode 100755
index 0000000..dbf5ea4
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_Deflater.c
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native method support for java.util.zip.Deflater
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "jlong.h"
+#include "jni.h"
+#include "jni_util.h"
+#include <zlib.h>
+
+#include "java_util_zip_Deflater.h"
+
+#define DEF_MEM_LEVEL 8
+
+static jfieldID levelID;
+static jfieldID strategyID;
+static jfieldID setParamsID;
+static jfieldID finishID;
+static jfieldID finishedID;
+static jfieldID bufID, offID, lenID;
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_initIDs(JNIEnv *env, jclass cls)
+{
+ levelID = (*env)->GetFieldID(env, cls, "level", "I");
+ strategyID = (*env)->GetFieldID(env, cls, "strategy", "I");
+ setParamsID = (*env)->GetFieldID(env, cls, "setParams", "Z");
+ finishID = (*env)->GetFieldID(env, cls, "finish", "Z");
+ finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
+ bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
+ offID = (*env)->GetFieldID(env, cls, "off", "I");
+ lenID = (*env)->GetFieldID(env, cls, "len", "I");
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level,
+ jint strategy, jboolean nowrap)
+{
+ z_stream *strm = calloc(1, sizeof(z_stream));
+
+ if (strm == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return jlong_zero;
+ } else {
+ char *msg;
+ switch (deflateInit2(strm, level, Z_DEFLATED,
+ nowrap ? -MAX_WBITS : MAX_WBITS,
+ DEF_MEM_LEVEL, strategy)) {
+ case Z_OK:
+ return ptr_to_jlong(strm);
+ case Z_MEM_ERROR:
+ free(strm);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return jlong_zero;
+ case Z_STREAM_ERROR:
+ free(strm);
+ JNU_ThrowIllegalArgumentException(env, 0);
+ return jlong_zero;
+ default:
+ msg = strm->msg;
+ free(strm);
+ JNU_ThrowInternalError(env, msg);
+ return jlong_zero;
+ }
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+ jarray b, jint off, jint len)
+{
+ Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ int res;
+ if (buf == 0) {/* out of memory */
+ return;
+ }
+ res = deflateSetDictionary((z_stream *)jlong_to_ptr(addr), buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ switch (res) {
+ case Z_OK:
+ break;
+ case Z_STREAM_ERROR:
+ JNU_ThrowIllegalArgumentException(env, 0);
+ break;
+ default:
+ JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg);
+ break;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Deflater_deflateBytes(JNIEnv *env, jobject this, jlong addr,
+ jarray b, jint off, jint len, jint flush)
+{
+ z_stream *strm = jlong_to_ptr(addr);
+
+ jarray this_buf = (*env)->GetObjectField(env, this, bufID);
+ jint this_off = (*env)->GetIntField(env, this, offID);
+ jint this_len = (*env)->GetIntField(env, this, lenID);
+ jbyte *in_buf;
+ jbyte *out_buf;
+ int res;
+ if ((*env)->GetBooleanField(env, this, setParamsID)) {
+ int level = (*env)->GetIntField(env, this, levelID);
+ int strategy = (*env)->GetIntField(env, this, strategyID);
+ in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
+ if (in_buf == NULL) {
+ // Throw OOME only when length is not zero
+ if (this_len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (out_buf == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+ if (len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+
+ strm->next_in = (Bytef *) (in_buf + this_off);
+ strm->next_out = (Bytef *) (out_buf + off);
+ strm->avail_in = this_len;
+ strm->avail_out = len;
+ res = deflateParams(strm, level, strategy);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+
+ switch (res) {
+ case Z_OK:
+ (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
+ this_off += this_len - strm->avail_in;
+ (*env)->SetIntField(env, this, offID, this_off);
+ (*env)->SetIntField(env, this, lenID, strm->avail_in);
+ return len - strm->avail_out;
+ case Z_BUF_ERROR:
+ (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
+ return 0;
+ default:
+ JNU_ThrowInternalError(env, strm->msg);
+ return 0;
+ }
+ } else {
+ jboolean finish = (*env)->GetBooleanField(env, this, finishID);
+ in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
+ if (in_buf == NULL) {
+ if (this_len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (out_buf == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+ if (len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+
+ return 0;
+ }
+
+ strm->next_in = (Bytef *) (in_buf + this_off);
+ strm->next_out = (Bytef *) (out_buf + off);
+ strm->avail_in = this_len;
+ strm->avail_out = len;
+ res = deflate(strm, finish ? Z_FINISH : flush);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+
+ switch (res) {
+ case Z_STREAM_END:
+ (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+ /* fall through */
+ case Z_OK:
+ this_off += this_len - strm->avail_in;
+ (*env)->SetIntField(env, this, offID, this_off);
+ (*env)->SetIntField(env, this, lenID, strm->avail_in);
+ return len - strm->avail_out;
+ case Z_BUF_ERROR:
+ return 0;
+ default:
+ JNU_ThrowInternalError(env, strm->msg);
+ return 0;
+ }
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Deflater_getAdler(JNIEnv *env, jclass cls, jlong addr)
+{
+ return ((z_stream *)jlong_to_ptr(addr))->adler;
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_reset(JNIEnv *env, jclass cls, jlong addr)
+{
+ if (deflateReset((z_stream *)jlong_to_ptr(addr)) != Z_OK) {
+ JNU_ThrowInternalError(env, 0);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_end(JNIEnv *env, jclass cls, jlong addr)
+{
+ if (deflateEnd((z_stream *)jlong_to_ptr(addr)) == Z_STREAM_ERROR) {
+ JNU_ThrowInternalError(env, 0);
+ } else {
+ free((z_stream *)jlong_to_ptr(addr));
+ }
+}
diff --git a/ojluni/src/main/native/java_util_zip_Deflater.h b/ojluni/src/main/native/java_util_zip_Deflater.h
new file mode 100755
index 0000000..a07f810
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_Deflater.h
@@ -0,0 +1,91 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_util_zip_Deflater */
+
+#ifndef _Included_java_util_zip_Deflater
+#define _Included_java_util_zip_Deflater
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_util_zip_Deflater_DEFLATED
+#define java_util_zip_Deflater_DEFLATED 8L
+#undef java_util_zip_Deflater_NO_COMPRESSION
+#define java_util_zip_Deflater_NO_COMPRESSION 0L
+#undef java_util_zip_Deflater_BEST_SPEED
+#define java_util_zip_Deflater_BEST_SPEED 1L
+#undef java_util_zip_Deflater_BEST_COMPRESSION
+#define java_util_zip_Deflater_BEST_COMPRESSION 9L
+#undef java_util_zip_Deflater_DEFAULT_COMPRESSION
+#define java_util_zip_Deflater_DEFAULT_COMPRESSION -1L
+#undef java_util_zip_Deflater_FILTERED
+#define java_util_zip_Deflater_FILTERED 1L
+#undef java_util_zip_Deflater_HUFFMAN_ONLY
+#define java_util_zip_Deflater_HUFFMAN_ONLY 2L
+#undef java_util_zip_Deflater_DEFAULT_STRATEGY
+#define java_util_zip_Deflater_DEFAULT_STRATEGY 0L
+#undef java_util_zip_Deflater_NO_FLUSH
+#define java_util_zip_Deflater_NO_FLUSH 0L
+#undef java_util_zip_Deflater_SYNC_FLUSH
+#define java_util_zip_Deflater_SYNC_FLUSH 2L
+#undef java_util_zip_Deflater_FULL_FLUSH
+#define java_util_zip_Deflater_FULL_FLUSH 3L
+/*
+ * Class: java_util_zip_Deflater
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Deflater_initIDs
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: init
+ * Signature: (IIZ)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_Deflater_init
+ (JNIEnv *, jclass, jint, jint, jboolean);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: setDictionary
+ * Signature: (J[BII)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Deflater_setDictionary
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jint);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: deflateBytes
+ * Signature: (J[BIII)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_Deflater_deflateBytes
+ (JNIEnv *, jobject, jlong, jbyteArray, jint, jint, jint);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: getAdler
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_Deflater_getAdler
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: reset
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Deflater_reset
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_Deflater
+ * Method: end
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Deflater_end
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_util_zip_Inflater.c b/ojluni/src/main/native/java_util_zip_Inflater.c
new file mode 100755
index 0000000..062a892
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_Inflater.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native method support for java.util.zip.Inflater
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include "jlong.h"
+#include "jni.h"
+#include "jvm.h"
+#include "jni_util.h"
+#include <zlib.h>
+#include "java_util_zip_Inflater.h"
+
+#define ThrowDataFormatException(env, msg) \
+ JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg)
+
+static jfieldID needDictID;
+static jfieldID finishedID;
+static jfieldID bufID, offID, lenID;
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls)
+{
+ needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z");
+ finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
+ bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
+ offID = (*env)->GetFieldID(env, cls, "off", "I");
+ lenID = (*env)->GetFieldID(env, cls, "len", "I");
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_init(JNIEnv *env, jclass cls, jboolean nowrap)
+{
+ z_stream *strm = calloc(1, sizeof(z_stream));
+
+ if (strm == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return jlong_zero;
+ } else {
+ char *msg;
+ switch (inflateInit2(strm, nowrap ? -MAX_WBITS : MAX_WBITS)) {
+ case Z_OK:
+ return ptr_to_jlong(strm);
+ case Z_MEM_ERROR:
+ free(strm);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return jlong_zero;
+ default:
+ msg = strm->msg;
+ free(strm);
+ JNU_ThrowInternalError(env, msg);
+ return jlong_zero;
+ }
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+ jarray b, jint off, jint len)
+{
+ Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ int res;
+ if (buf == 0) /* out of memory */
+ return;
+ res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+ switch (res) {
+ case Z_OK:
+ break;
+ case Z_STREAM_ERROR:
+ case Z_DATA_ERROR:
+ JNU_ThrowIllegalArgumentException(env, ((z_stream *)jlong_to_ptr(addr))->msg);
+ break;
+ default:
+ JNU_ThrowInternalError(env, ((z_stream *)jlong_to_ptr(addr))->msg);
+ break;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr,
+ jarray b, jint off, jint len)
+{
+ z_stream *strm = jlong_to_ptr(addr);
+ jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID);
+ jint this_off = (*env)->GetIntField(env, this, offID);
+ jint this_len = (*env)->GetIntField(env, this, lenID);
+
+ jbyte *in_buf;
+ jbyte *out_buf;
+ int ret;
+
+ in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
+ if (in_buf == NULL) {
+ if (this_len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+ if (out_buf == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+ if (len != 0)
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ strm->next_in = (Bytef *) (in_buf + this_off);
+ strm->next_out = (Bytef *) (out_buf + off);
+ strm->avail_in = this_len;
+ strm->avail_out = len;
+ ret = inflate(strm, Z_PARTIAL_FLUSH);
+ (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
+ (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+
+ switch (ret) {
+ case Z_STREAM_END:
+ (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+ /* fall through */
+ case Z_OK:
+ this_off += this_len - strm->avail_in;
+ (*env)->SetIntField(env, this, offID, this_off);
+ (*env)->SetIntField(env, this, lenID, strm->avail_in);
+ return len - strm->avail_out;
+ case Z_NEED_DICT:
+ (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE);
+ /* Might have consumed some input here! */
+ this_off += this_len - strm->avail_in;
+ (*env)->SetIntField(env, this, offID, this_off);
+ (*env)->SetIntField(env, this, lenID, strm->avail_in);
+ return 0;
+ case Z_BUF_ERROR:
+ return 0;
+ case Z_DATA_ERROR:
+ ThrowDataFormatException(env, strm->msg);
+ return 0;
+ case Z_MEM_ERROR:
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ default:
+ JNU_ThrowInternalError(env, strm->msg);
+ return 0;
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_Inflater_getAdler(JNIEnv *env, jclass cls, jlong addr)
+{
+ return ((z_stream *)jlong_to_ptr(addr))->adler;
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_reset(JNIEnv *env, jclass cls, jlong addr)
+{
+ if (inflateReset(jlong_to_ptr(addr)) != Z_OK) {
+ JNU_ThrowInternalError(env, 0);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_end(JNIEnv *env, jclass cls, jlong addr)
+{
+ if (inflateEnd(jlong_to_ptr(addr)) == Z_STREAM_ERROR) {
+ JNU_ThrowInternalError(env, 0);
+ } else {
+ free(jlong_to_ptr(addr));
+ }
+}
diff --git a/ojluni/src/main/native/java_util_zip_Inflater.h b/ojluni/src/main/native/java_util_zip_Inflater.h
new file mode 100755
index 0000000..0fcec49
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_Inflater.h
@@ -0,0 +1,69 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_util_zip_Inflater */
+
+#ifndef _Included_java_util_zip_Inflater
+#define _Included_java_util_zip_Inflater
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: java_util_zip_Inflater
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Inflater_initIDs
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: init
+ * Signature: (Z)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_Inflater_init
+ (JNIEnv *, jclass, jboolean);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: setDictionary
+ * Signature: (J[BII)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Inflater_setDictionary
+ (JNIEnv *, jclass, jlong, jbyteArray, jint, jint);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: inflateBytes
+ * Signature: (J[BII)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_Inflater_inflateBytes
+ (JNIEnv *, jobject, jlong, jbyteArray, jint, jint);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: getAdler
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_Inflater_getAdler
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: reset
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Inflater_reset
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_Inflater
+ * Method: end
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_Inflater_end
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.c b/ojluni/src/main/native/java_util_zip_ZipFile.c
new file mode 100755
index 0000000..30fbfdd
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_ZipFile.c
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Native method support for java.util.zip.ZipFile
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <assert.h>
+#include "jlong.h"
+#include "jvm.h"
+#include "jni.h"
+#include "jni_util.h"
+#include "zip_util.h"
+#ifdef WIN32
+#include "io_util_md.h"
+#else
+#include "io_util.h"
+#endif
+
+#include "java_util_zip_ZipFile.h"
+#include "java_util_jar_JarFile.h"
+
+#define DEFLATED 8
+#define STORED 0
+
+static jfieldID jzfileID;
+
+static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ;
+static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE;
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls)
+{
+ jzfileID = (*env)->GetFieldID(env, cls, "jzfile", "J");
+ assert(jzfileID != 0);
+}
+
+static void
+ThrowZipException(JNIEnv *env, const char *msg)
+{
+ jstring s = NULL;
+ jobject x;
+
+ if (msg != NULL) {
+ s = JNU_NewStringPlatform(env, msg);
+ }
+ x = JNU_NewObjectByName(env,
+ "java/util/zip/ZipException",
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL) {
+ (*env)->Throw(env, x);
+ }
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name,
+ jint mode, jlong lastModified,
+ jboolean usemmap)
+{
+ const char *path = JNU_GetStringPlatformChars(env, name, 0);
+ char *msg = 0;
+ jlong result = 0;
+ int flag = 0;
+ jzfile *zip = 0;
+
+ if (mode & OPEN_READ) flag |= O_RDONLY;
+ if (mode & OPEN_DELETE) flag |= JVM_O_DELETE;
+
+ if (path != 0) {
+ zip = ZIP_Get_From_Cache(path, &msg, lastModified);
+ if (zip == 0 && msg == 0) {
+ ZFILE zfd = 0;
+#ifdef WIN32
+ zfd = winFileHandleOpen(env, name, flag);
+ if (zfd == -1) {
+ /* Exception already pending. */
+ goto finally;
+ }
+#else
+ zfd = JVM_Open(path, flag, 0);
+ if (zfd < 0) {
+ throwFileNotFoundException(env, name);
+ goto finally;
+ }
+#endif
+ zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap);
+ }
+
+ if (zip != 0) {
+ result = ptr_to_jlong(zip);
+ } else if (msg != 0) {
+ ThrowZipException(env, msg);
+ free(msg);
+ } else if (errno == ENOMEM) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ } else {
+ ThrowZipException(env, "error in opening zip file");
+ }
+finally:
+ JNU_ReleaseStringPlatformChars(env, name, path);
+ }
+ return result;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+
+ return zip->total;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+
+ return zip->locsig;
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
+{
+ ZIP_Close(jlong_to_ptr(zfile));
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
+ jbyteArray name, jboolean addSlash)
+{
+#define MAXNAME 1024
+ jzfile *zip = jlong_to_ptr(zfile);
+ jsize ulen = (*env)->GetArrayLength(env, name);
+ char buf[MAXNAME+2], *path;
+ jzentry *ze;
+
+ if (ulen > MAXNAME) {
+ path = malloc(ulen + 2);
+ if (path == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ } else {
+ path = buf;
+ }
+ (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
+ path[ulen] = '\0';
+ if (addSlash == JNI_FALSE) {
+ ze = ZIP_GetEntry(zip, path, 0);
+ } else {
+ ze = ZIP_GetEntry(zip, path, (jint)ulen);
+ }
+ if (path != buf) {
+ free(path);
+ }
+ return ptr_to_jlong(ze);
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_ZipFile_freeEntry(JNIEnv *env, jclass cls, jlong zfile,
+ jlong zentry)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+ jzentry *ze = jlong_to_ptr(zentry);
+ ZIP_FreeEntry(zip, ze);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
+ jint n)
+{
+ jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
+ return ptr_to_jlong(ze);
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return ze->csize != 0 ? DEFLATED : STORED;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return ze->flag;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return ze->csize != 0 ? ze->csize : ze->size;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return ze->size;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return (jlong)ze->time & 0xffffffffUL;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ return (jlong)ze->crc & 0xffffffffUL;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_java_util_zip_ZipFile_getCommentBytes(JNIEnv *env,
+ jclass cls,
+ jlong zfile)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+ jbyteArray jba = NULL;
+
+ if (zip->comment != NULL) {
+ if ((jba = (*env)->NewByteArray(env, zip->clen)) == NULL)
+ return NULL;
+ (*env)->SetByteArrayRegion(env, jba, 0, zip->clen, (jbyte*)zip->comment);
+ }
+ return jba;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env,
+ jclass cls,
+ jlong zentry, jint type)
+{
+ jzentry *ze = jlong_to_ptr(zentry);
+ int len = 0;
+ jbyteArray jba = NULL;
+ switch (type) {
+ case java_util_zip_ZipFile_JZENTRY_NAME:
+ if (ze->name != 0) {
+ len = (int)strlen(ze->name);
+ if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
+ }
+ break;
+ case java_util_zip_ZipFile_JZENTRY_EXTRA:
+ if (ze->extra != 0) {
+ unsigned char *bp = (unsigned char *)&ze->extra[0];
+ len = (bp[0] | (bp[1] << 8));
+ if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
+ }
+ break;
+ case java_util_zip_ZipFile_JZENTRY_COMMENT:
+ if (ze->comment != 0) {
+ len = (int)strlen(ze->comment);
+ if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
+ break;
+ (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
+ }
+ break;
+ }
+ return jba;
+}
+
+JNIEXPORT jint JNICALL
+Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
+ jlong zentry, jlong pos, jbyteArray bytes,
+ jint off, jint len)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+ char *msg;
+
+#define BUFSIZE 8192
+ /* copy via tmp stack buffer: */
+ jbyte buf[BUFSIZE];
+
+ if (len > BUFSIZE) {
+ len = BUFSIZE;
+ }
+
+ ZIP_Lock(zip);
+ len = ZIP_Read(zip, jlong_to_ptr(zentry), pos, buf, len);
+ msg = zip->msg;
+ ZIP_Unlock(zip);
+ if (len != -1) {
+ (*env)->SetByteArrayRegion(env, bytes, off, len, buf);
+ }
+
+ if (len == -1) {
+ if (msg != 0) {
+ ThrowZipException(env, msg);
+ } else {
+ char errmsg[128];
+ sprintf(errmsg, "errno: %d, error: %s\n",
+ errno, "Error reading ZIP file");
+ JNU_ThrowIOExceptionWithLastError(env, errmsg);
+ }
+ }
+
+ return len;
+}
+
+/*
+ * Returns an array of strings representing the names of all entries
+ * that begin with "META-INF/" (case ignored). This native method is
+ * used in JarFile as an optimization when looking up manifest and
+ * signature file entries. Returns null if no entries were found.
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_java_util_jar_JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj)
+{
+ jlong zfile = (*env)->GetLongField(env, obj, jzfileID);
+ jzfile *zip;
+ int i, count;
+ jobjectArray result = 0;
+
+ if (zfile == 0) {
+ JNU_ThrowByName(env,
+ "java/lang/IllegalStateException", "zip file closed");
+ return NULL;
+ }
+ zip = jlong_to_ptr(zfile);
+
+ /* count the number of valid ZIP metanames */
+ count = 0;
+ if (zip->metanames != 0) {
+ for (i = 0; i < zip->metacount; i++) {
+ if (zip->metanames[i] != 0) {
+ count++;
+ }
+ }
+ }
+
+ /* If some names were found then build array of java strings */
+ if (count > 0) {
+ jclass cls = (*env)->FindClass(env, "java/lang/String");
+ result = (*env)->NewObjectArray(env, count, cls, 0);
+ if (result != 0) {
+ for (i = 0; i < count; i++) {
+ jstring str = (*env)->NewStringUTF(env, zip->metanames[i]);
+ if (str == 0) {
+ break;
+ }
+ (*env)->SetObjectArrayElement(env, result, i, str);
+ (*env)->DeleteLocalRef(env, str);
+ }
+ }
+ }
+ return result;
+}
+
+JNIEXPORT jstring JNICALL
+Java_java_util_zip_ZipFile_getZipMessage(JNIEnv *env, jclass cls, jlong zfile)
+{
+ jzfile *zip = jlong_to_ptr(zfile);
+ char *msg = zip->msg;
+ if (msg == NULL) {
+ return NULL;
+ }
+ return JNU_NewStringPlatform(env, msg);
+}
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.h b/ojluni/src/main/native/java_util_zip_ZipFile.h
new file mode 100755
index 0000000..d58b4f0
--- /dev/null
+++ b/ojluni/src/main/native/java_util_zip_ZipFile.h
@@ -0,0 +1,171 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class java_util_zip_ZipFile */
+
+#ifndef _Included_java_util_zip_ZipFile
+#define _Included_java_util_zip_ZipFile
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef java_util_zip_ZipFile_STORED
+#define java_util_zip_ZipFile_STORED 0L
+#undef java_util_zip_ZipFile_DEFLATED
+#define java_util_zip_ZipFile_DEFLATED 8L
+#undef java_util_zip_ZipFile_OPEN_READ
+#define java_util_zip_ZipFile_OPEN_READ 1L
+#undef java_util_zip_ZipFile_OPEN_DELETE
+#define java_util_zip_ZipFile_OPEN_DELETE 4L
+#undef java_util_zip_ZipFile_JZENTRY_NAME
+#define java_util_zip_ZipFile_JZENTRY_NAME 0L
+#undef java_util_zip_ZipFile_JZENTRY_EXTRA
+#define java_util_zip_ZipFile_JZENTRY_EXTRA 1L
+#undef java_util_zip_ZipFile_JZENTRY_COMMENT
+#define java_util_zip_ZipFile_JZENTRY_COMMENT 2L
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_ZipFile_initIDs
+ (JNIEnv *, jclass);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntry
+ * Signature: (J[BZ)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getEntry
+ (JNIEnv *, jclass, jlong, jbyteArray, jboolean);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: freeEntry
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_ZipFile_freeEntry
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getNextEntry
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getNextEntry
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_util_zip_ZipFile_close
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: open
+ * Signature: (Ljava/lang/String;IJZ)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_open
+ (JNIEnv *, jclass, jstring, jint, jlong, jboolean);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getTotal
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_ZipFile_getTotal
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: startsWithLOC
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_util_zip_ZipFile_startsWithLOC
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: read
+ * Signature: (JJJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_ZipFile_read
+ (JNIEnv *, jclass, jlong, jlong, jlong, jbyteArray, jint, jint);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryTime
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getEntryTime
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryCrc
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getEntryCrc
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryCSize
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getEntryCSize
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntrySize
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_java_util_zip_ZipFile_getEntrySize
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryMethod
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_ZipFile_getEntryMethod
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryFlag
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_java_util_zip_ZipFile_getEntryFlag
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getCommentBytes
+ * Signature: (J)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_util_zip_ZipFile_getCommentBytes
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getEntryBytes
+ * Signature: (JI)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_java_util_zip_ZipFile_getEntryBytes
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: java_util_zip_ZipFile
+ * Method: getZipMessage
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_util_zip_ZipFile_getZipMessage
+ (JNIEnv *, jclass, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/jfdlibm.h b/ojluni/src/main/native/jfdlibm.h
new file mode 100755
index 0000000..4525f4b
--- /dev/null
+++ b/ojluni/src/main/native/jfdlibm.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JFDLIBM_H
+#define _JFDLIBM_H
+
+#define _IEEE_LIBM
+
+/*
+ * In order to resolve the conflict between fdlibm and compilers
+ * (such as keywords and built-in functions), the following
+ * function names have to be re-mapped.
+ */
+
+#define huge HUGE_NUMBER
+#define acos jacos
+#define asin jasin
+#define atan jatan
+#define atan2 jatan2
+#define cos jcos
+#define exp jexp
+#define log jlog
+#define log10 jlog10
+#define pow jpow
+#define sin jsin
+#define sqrt jsqrt
+#define cbrt jcbrt
+#define tan jtan
+#define floor jfloor
+#define ceil jceil
+#define cosh jcosh
+#define fmod jmod
+#define log10 jlog10
+#define sinh jsinh
+#define fabs jfabs
+#define tanh jtanh
+#define remainder jremainder
+#define hypot jhypot
+#define log1p jlog1p
+#define expm1 jexpm1
+
+#if defined(__linux__) || defined(_ALLBSD_SOURCE)
+#define __ieee754_sqrt __j__ieee754_sqrt
+#define __ieee754_acos __j__ieee754_acos
+#define __ieee754_acosh __j__ieee754_acosh
+#define __ieee754_log __j__ieee754_log
+#define __ieee754_atanh __j__ieee754_atanh
+#define __ieee754_asin __j__ieee754_asin
+#define __ieee754_atan2 __j__ieee754_atan2
+#define __ieee754_exp __j__ieee754_exp
+#define __ieee754_cosh __j__ieee754_cosh
+#define __ieee754_fmod __j__ieee754_fmod
+#define __ieee754_pow __j__ieee754_pow
+#define __ieee754_lgamma_r __j__ieee754_lgamma_r
+#define __ieee754_gamma_r __j__ieee754_gamma_r
+#define __ieee754_lgamma __j__ieee754_lgamma
+#define __ieee754_gamma __j__ieee754_gamma
+#define __ieee754_log10 __j__ieee754_log10
+#define __ieee754_sinh __j__ieee754_sinh
+#define __ieee754_hypot __j__ieee754_hypot
+#define __ieee754_j0 __j__ieee754_j0
+#define __ieee754_j1 __j__ieee754_j1
+#define __ieee754_y0 __j__ieee754_y0
+#define __ieee754_y1 __j__ieee754_y1
+#define __ieee754_jn __j__ieee754_jn
+#define __ieee754_yn __j__ieee754_yn
+#define __ieee754_remainder __j__ieee754_remainder
+#define __ieee754_rem_pio2 __j__ieee754_rem_pio2
+#define __ieee754_scalb __j__ieee754_scalb
+#define __kernel_standard __j__kernel_standard
+#define __kernel_sin __j__kernel_sin
+#define __kernel_cos __j__kernel_cos
+#define __kernel_tan __j__kernel_tan
+#define __kernel_rem_pio2 __j__kernel_rem_pio2
+#define __ieee754_log1p __j__ieee754_log1p
+#define __ieee754_expm1 __j__ieee754_expm1
+#endif
+#endif/*_JFDLIBM_H*/
diff --git a/ojluni/src/main/native/jlong.h b/ojluni/src/main/native/jlong.h
new file mode 100755
index 0000000..40fd9f1
--- /dev/null
+++ b/ojluni/src/main/native/jlong.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JLONG_H_
+#define _JLONG_H_
+
+#include "jlong_md.h"
+
+#endif
diff --git a/ojluni/src/main/native/jlong_md.h b/ojluni/src/main/native/jlong_md.h
new file mode 100755
index 0000000..97b08e6
--- /dev/null
+++ b/ojluni/src/main/native/jlong_md.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _SOLARIS_JLONG_MD_H_
+#define _SOLARIS_JLONG_MD_H_
+
+/* Make sure ptrdiff_t is defined */
+#include <stddef.h>
+#include <stdint.h> /* For uintptr_t */
+
+#define jlong_high(a) ((jint)((a)>>32))
+#define jlong_low(a) ((jint)(a))
+#define jlong_add(a, b) ((a) + (b))
+#define jlong_and(a, b) ((a) & (b))
+#define jlong_div(a, b) ((a) / (b))
+#define jlong_mul(a, b) ((a) * (b))
+#define jlong_neg(a) (-(a))
+#define jlong_not(a) (~(a))
+#define jlong_or(a, b) ((a) | (b))
+#define jlong_shl(a, n) ((a) << (n))
+#define jlong_shr(a, n) ((a) >> (n))
+#define jlong_sub(a, b) ((a) - (b))
+#define jlong_xor(a, b) ((a) ^ (b))
+#define jlong_rem(a,b) ((a) % (b))
+
+/* comparison operators */
+#define jlong_ltz(ll) ((ll)<0)
+#define jlong_gez(ll) ((ll)>=0)
+#define jlong_gtz(ll) ((ll)>0)
+#define jlong_eqz(a) ((a) == 0)
+#define jlong_eq(a, b) ((a) == (b))
+#define jlong_ne(a,b) ((a) != (b))
+#define jlong_ge(a,b) ((a) >= (b))
+#define jlong_le(a,b) ((a) <= (b))
+#define jlong_lt(a,b) ((a) < (b))
+#define jlong_gt(a,b) ((a) > (b))
+
+#define jlong_zero ((jlong) 0)
+#define jlong_one ((jlong) 1)
+#define jlong_minus_one ((jlong) -1)
+
+/* For static variables initialized to zero */
+#define jlong_zero_init ((jlong) 0L)
+
+#ifdef _LP64
+#define jlong_to_ptr(a) ((void*)(a))
+#define ptr_to_jlong(a) ((jlong)(a))
+#else
+#define jlong_to_ptr(a) ((void*)(int)(a))
+#define ptr_to_jlong(a) ((jlong)(int)(a))
+#endif
+
+#define jint_to_jlong(a) ((jlong)(a))
+#define jlong_to_jint(a) ((jint)(a))
+
+/* Useful on machines where jlong and jdouble have different endianness. */
+#define jlong_to_jdouble_bits(a)
+#define jdouble_to_jlong_bits(a)
+
+#define jlong_to_int(a) ((int)(a))
+#define int_to_jlong(a) ((jlong)(a))
+#define jlong_to_uint(a) ((unsigned int)(a))
+#define uint_to_jlong(a) ((jlong)(a))
+#define jlong_to_ptrdiff(a) ((ptrdiff_t)(a))
+#define ptrdiff_to_jlong(a) ((jlong)(a))
+#define jlong_to_size(a) ((size_t)(a))
+#define size_to_jlong(a) ((jlong)(a))
+#define long_to_jlong(a) ((jlong)(a))
+
+#endif /* !_SOLARIS_JLONG_MD_H_ */
diff --git a/ojluni/src/main/native/jni_util.c b/ojluni/src/main/native/jni_util.c
new file mode 100755
index 0000000..3ef707f
--- /dev/null
+++ b/ojluni/src/main/native/jni_util.c
@@ -0,0 +1,1322 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "jvm.h"
+#include "jni.h"
+#include "jni_util.h"
+
+/* Due to a bug in the win32 C runtime library strings
+ * such as "z:" need to be appended with a "." so we
+ * must allocate at least 4 bytes to allow room for
+ * this expansion. See 4235353 for details.
+ */
+#define MALLOC_MIN4(len) ((char *)malloc((len) + 1 < 4 ? 4 : (len) + 1))
+
+/**
+ * Throw a Java exception by name. Similar to SignalError.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg)
+{
+ jclass cls = (*env)->FindClass(env, name);
+
+ if (cls != 0) /* Otherwise an exception has already been thrown */
+ (*env)->ThrowNew(env, cls, msg);
+}
+
+/* JNU_Throw common exceptions */
+
+JNIEXPORT void JNICALL
+JNU_ThrowNullPointerException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NullPointerException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/ArrayIndexOutOfBoundsException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/OutOfMemoryError", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/IllegalArgumentException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/IllegalAccessError", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/IllegalAccessException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowInternalError(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/InternalError", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NoSuchFieldException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NoSuchMethodException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/ClassNotFoundException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NumberFormatException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowIOException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/io/IOException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NoSuchFieldError", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/NoSuchMethodError", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/StringIndexOutOfBoundsException", msg);
+}
+
+JNIEXPORT void JNICALL
+JNU_ThrowInstantiationException(JNIEnv *env, const char *msg)
+{
+ JNU_ThrowByName(env, "java/lang/InstantiationException", msg);
+}
+
+
+/* Throw an exception by name, using the string returned by
+ * JVM_LastErrorString for the detail string. If the last-error
+ * string is NULL, use the given default detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+ const char *defaultDetail)
+{
+ char buf[256];
+ int n = JVM_GetLastErrorString(buf, sizeof(buf));
+
+ if (n > 0) {
+ jstring s = JNU_NewStringPlatform(env, buf);
+ if (s != NULL) {
+ jobject x = JNU_NewObjectByName(env, name,
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL) {
+ (*env)->Throw(env, x);
+ }
+ }
+ }
+ if (!(*env)->ExceptionOccurred(env)) {
+ JNU_ThrowByName(env, name, defaultDetail);
+ }
+}
+
+/* Throw an IOException, using the last-error string for the detail
+ * string. If the last-error string is NULL, use the given default
+ * detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail)
+{
+ JNU_ThrowByNameWithLastError(env, "java/io/IOException", defaultDetail);
+}
+
+
+JNIEXPORT jvalue JNICALL
+JNU_CallStaticMethodByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *class_name,
+ const char *name,
+ const char *signature,
+ ...)
+{
+ jclass clazz;
+ jmethodID mid;
+ va_list args;
+ jvalue result;
+ const char *p = signature;
+
+ /* find out the return type */
+ while (*p && *p != ')')
+ p++;
+ p++;
+
+ result.i = 0;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ clazz = (*env)->FindClass(env, class_name);
+ if (clazz == 0)
+ goto done2;
+ mid = (*env)->GetStaticMethodID(env, clazz, name, signature);
+ if (mid == 0)
+ goto done1;
+ va_start(args, signature);
+ switch (*p) {
+ case 'V':
+ (*env)->CallStaticVoidMethodV(env, clazz, mid, args);
+ break;
+ case '[':
+ case 'L':
+ result.l = (*env)->CallStaticObjectMethodV(env, clazz, mid, args);
+ break;
+ case 'Z':
+ result.z = (*env)->CallStaticBooleanMethodV(env, clazz, mid, args);
+ break;
+ case 'B':
+ result.b = (*env)->CallStaticByteMethodV(env, clazz, mid, args);
+ break;
+ case 'C':
+ result.c = (*env)->CallStaticCharMethodV(env, clazz, mid, args);
+ break;
+ case 'S':
+ result.s = (*env)->CallStaticShortMethodV(env, clazz, mid, args);
+ break;
+ case 'I':
+ result.i = (*env)->CallStaticIntMethodV(env, clazz, mid, args);
+ break;
+ case 'J':
+ result.j = (*env)->CallStaticLongMethodV(env, clazz, mid, args);
+ break;
+ case 'F':
+ result.f = (*env)->CallStaticFloatMethodV(env, clazz, mid, args);
+ break;
+ case 'D':
+ result.d = (*env)->CallStaticDoubleMethodV(env, clazz, mid, args);
+ break;
+ default:
+ (*env)->FatalError(env, "JNU_CallStaticMethodByName: illegal signature");
+ }
+ va_end(args);
+
+ done1:
+ (*env)->DeleteLocalRef(env, clazz);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+ return result;
+}
+
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature,
+ ...)
+{
+ jvalue result;
+ va_list args;
+
+ va_start(args, signature);
+ result = JNU_CallMethodByNameV(env, hasException, obj, name, signature,
+ args);
+ va_end(args);
+
+ return result;
+}
+
+
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByNameV(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature,
+ va_list args)
+{
+ jclass clazz;
+ jmethodID mid;
+ jvalue result;
+ const char *p = signature;
+
+ /* find out the return type */
+ while (*p && *p != ')')
+ p++;
+ p++;
+
+ result.i = 0;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ clazz = (*env)->GetObjectClass(env, obj);
+ mid = (*env)->GetMethodID(env, clazz, name, signature);
+ if (mid == 0)
+ goto done1;
+
+ switch (*p) {
+ case 'V':
+ (*env)->CallVoidMethodV(env, obj, mid, args);
+ break;
+ case '[':
+ case 'L':
+ result.l = (*env)->CallObjectMethodV(env, obj, mid, args);
+ break;
+ case 'Z':
+ result.z = (*env)->CallBooleanMethodV(env, obj, mid, args);
+ break;
+ case 'B':
+ result.b = (*env)->CallByteMethodV(env, obj, mid, args);
+ break;
+ case 'C':
+ result.c = (*env)->CallCharMethodV(env, obj, mid, args);
+ break;
+ case 'S':
+ result.s = (*env)->CallShortMethodV(env, obj, mid, args);
+ break;
+ case 'I':
+ result.i = (*env)->CallIntMethodV(env, obj, mid, args);
+ break;
+ case 'J':
+ result.j = (*env)->CallLongMethodV(env, obj, mid, args);
+ break;
+ case 'F':
+ result.f = (*env)->CallFloatMethodV(env, obj, mid, args);
+ break;
+ case 'D':
+ result.d = (*env)->CallDoubleMethodV(env, obj, mid, args);
+ break;
+ default:
+ (*env)->FatalError(env, "JNU_CallMethodByNameV: illegal signature");
+ }
+ done1:
+ (*env)->DeleteLocalRef(env, clazz);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+ return result;
+}
+
+JNIEXPORT jobject JNICALL
+JNU_NewObjectByName(JNIEnv *env, const char *class_name,
+ const char *constructor_sig, ...)
+{
+ jobject obj = NULL;
+
+ jclass cls = 0;
+ jmethodID cls_initMID;
+ va_list args;
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+ goto done;
+
+ cls = (*env)->FindClass(env, class_name);
+ if (cls == 0) {
+ goto done;
+ }
+ cls_initMID = (*env)->GetMethodID(env, cls,
+ "<init>", constructor_sig);
+ if (cls_initMID == NULL) {
+ goto done;
+ }
+ va_start(args, constructor_sig);
+ obj = (*env)->NewObjectV(env, cls, cls_initMID, args);
+ va_end(args);
+
+ done:
+ (*env)->DeleteLocalRef(env, cls);
+ return obj;
+}
+
+/* Optimized for char set ISO_8559_1 */
+static jstring
+newString8859_1(JNIEnv *env, const char *str)
+{
+ int len = (int)strlen(str);
+ jchar buf[512];
+ jchar *str1;
+ jstring result;
+ int i;
+
+ if (len > 512) {
+ str1 = (jchar *)malloc(len * sizeof(jchar));
+ if (str1 == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ } else
+ str1 = buf;
+
+ for (i=0;i<len;i++)
+ str1[i] = (unsigned char)str[i];
+ result = (*env)->NewString(env, str1, len);
+ if (str1 != buf)
+ free(str1);
+ return result;
+}
+
+static const char*
+getString8859_1Chars(JNIEnv *env, jstring jstr)
+{
+ int i;
+ char *result;
+ jint len = (*env)->GetStringLength(env, jstr);
+ const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
+ if (str == 0) {
+ return 0;
+ }
+
+ result = MALLOC_MIN4(len);
+ if (result == 0) {
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+
+ for (i=0; i<len; i++) {
+ jchar unicode = str[i];
+ if (unicode <= 0x00ff)
+ result[i] = (char)unicode;
+ else
+ result[i] = '?';
+ }
+
+ result[len] = 0;
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ return result;
+}
+
+
+/* Optimized for char set ISO646-US (us-ascii) */
+static jstring
+newString646_US(JNIEnv *env, const char *str)
+{
+ int len = strlen(str);
+ jchar buf[512];
+ jchar *str1;
+ jstring result;
+ int i;
+
+ if (len > 512) {
+ str1 = (jchar *)malloc(len * sizeof(jchar));
+ if (str1 == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ } else
+ str1 = buf;
+
+ for (i=0; i<len; i++) {
+ unsigned char c = (unsigned char)str[i];
+ if (c <= 0x7f)
+ str1[i] = c;
+ else
+ str1[i] = '?';
+ }
+
+ result = (*env)->NewString(env, str1, len);
+ if (str1 != buf)
+ free(str1);
+ return result;
+}
+
+static const char*
+getString646_USChars(JNIEnv *env, jstring jstr)
+{
+ int i;
+ char *result;
+ jint len = (*env)->GetStringLength(env, jstr);
+ const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
+ if (str == 0) {
+ return 0;
+ }
+
+ result = MALLOC_MIN4(len);
+ if (result == 0) {
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+
+ for (i=0; i<len; i++) {
+ jchar unicode = str[i];
+ if (unicode <= 0x007f )
+ result[i] = (char)unicode;
+ else
+ result[i] = '?';
+ }
+
+ result[len] = 0;
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ return result;
+}
+
+/* enumeration of c1 row from Cp1252 */
+static int cp1252c1chars[32] = {
+ 0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,
+ 0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD,
+ 0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,
+ 0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
+};
+
+/* Optimized for char set Cp1252 */
+static jstring
+newStringCp1252(JNIEnv *env, const char *str)
+{
+ int len = (int) strlen(str);
+ jchar buf[512];
+ jchar *str1;
+ jstring result;
+ int i;
+ if (len > 512) {
+ str1 = (jchar *)malloc(len * sizeof(jchar));
+ if (str1 == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+ } else
+ str1 = buf;
+
+ for (i=0; i<len; i++) {
+ unsigned char c = (unsigned char)str[i];
+ if ((c >= 0x80) && (c <= 0x9f))
+ str1[i] = cp1252c1chars[c-128];
+ else
+ str1[i] = c;
+ }
+
+ result = (*env)->NewString(env, str1, len);
+ if (str1 != buf)
+ free(str1);
+ return result;
+}
+
+static const char*
+getStringCp1252Chars(JNIEnv *env, jstring jstr)
+{
+ int i;
+ char *result;
+ jint len = (*env)->GetStringLength(env, jstr);
+ const jchar *str = (*env)->GetStringCritical(env, jstr, 0);
+ if (str == 0) {
+ return 0;
+ }
+
+ result = MALLOC_MIN4(len);
+ if (result == 0) {
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ JNU_ThrowOutOfMemoryError(env, 0);
+ return 0;
+ }
+
+ for (i=0; i<len; i++) {
+ jchar c = str[i];
+ if (c < 256)
+ result[i] = (char)c;
+ else switch(c) {
+ case 0x20AC: result[i] = (char)0x80; break;
+ case 0x201A: result[i] = (char)0x82; break;
+ case 0x0192: result[i] = (char)0x83; break;
+ case 0x201E: result[i] = (char)0x84; break;
+ case 0x2026: result[i] = (char)0x85; break;
+ case 0x2020: result[i] = (char)0x86; break;
+ case 0x2021: result[i] = (char)0x87; break;
+ case 0x02C6: result[i] = (char)0x88; break;
+ case 0x2030: result[i] = (char)0x89; break;
+ case 0x0160: result[i] = (char)0x8A; break;
+ case 0x2039: result[i] = (char)0x8B; break;
+ case 0x0152: result[i] = (char)0x8C; break;
+ case 0x017D: result[i] = (char)0x8E; break;
+ case 0x2018: result[i] = (char)0x91; break;
+ case 0x2019: result[i] = (char)0x92; break;
+ case 0x201C: result[i] = (char)0x93; break;
+ case 0x201D: result[i] = (char)0x94; break;
+ case 0x2022: result[i] = (char)0x95; break;
+ case 0x2013: result[i] = (char)0x96; break;
+ case 0x2014: result[i] = (char)0x97; break;
+ case 0x02DC: result[i] = (char)0x98; break;
+ case 0x2122: result[i] = (char)0x99; break;
+ case 0x0161: result[i] = (char)0x9A; break;
+ case 0x203A: result[i] = (char)0x9B; break;
+ case 0x0153: result[i] = (char)0x9C; break;
+ case 0x017E: result[i] = (char)0x9E; break;
+ case 0x0178: result[i] = (char)0x9F; break;
+ default: result[i] = '?'; break;
+ }
+ }
+
+ result[len] = 0;
+ (*env)->ReleaseStringCritical(env, jstr, str);
+ return result;
+}
+
+static int fastEncoding = NO_ENCODING_YET;
+static jstring jnuEncoding = NULL;
+
+/* Cached method IDs */
+static jmethodID String_init_ID; /* String(byte[], enc) */
+static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
+
+int getFastEncoding() {
+ return fastEncoding;
+}
+
+/* Initialize the fast encoding. If the "sun.jnu.encoding" property
+ * has not yet been set, we leave fastEncoding == NO_ENCODING_YET.
+ */
+void
+initializeEncoding(JNIEnv *env)
+{
+ jstring propname = 0;
+ jstring enc = 0;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ return;
+
+ propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
+ if (propname) {
+ jboolean exc;
+ enc = JNU_CallStaticMethodByName
+ (env,
+ &exc,
+ "java/lang/System",
+ "getProperty",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ propname).l;
+ if (!exc) {
+ if (enc) {
+ const char* encname = (*env)->GetStringUTFChars(env, enc, 0);
+ if (encname) {
+ /*
+ * On Solaris with nl_langinfo() called in GetJavaProperties():
+ *
+ * locale undefined -> NULL -> hardcoded default
+ * "C" locale -> "" -> hardcoded default (on 2.6)
+ * "C" locale -> "ISO646-US" (on Sol 7/8)
+ * "en_US" locale -> "ISO8859-1"
+ * "en_GB" locale -> "ISO8859-1" (on Sol 7/8)
+ * "en_UK" locale -> "ISO8859-1" (on 2.6)
+ */
+ if ((strcmp(encname, "8859_1") == 0) ||
+ (strcmp(encname, "ISO8859-1") == 0) ||
+ (strcmp(encname, "ISO8859_1") == 0))
+ fastEncoding = FAST_8859_1;
+ else if (strcmp(encname, "ISO646-US") == 0)
+ fastEncoding = FAST_646_US;
+ else if (strcmp(encname, "Cp1252") == 0 ||
+ /* This is a temporary fix until we move */
+ /* to wide character versions of all Windows */
+ /* calls. */
+ strcmp(encname, "utf-16le") == 0)
+ fastEncoding = FAST_CP1252;
+ else {
+ fastEncoding = NO_FAST_ENCODING;
+ jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
+ }
+ (*env)->ReleaseStringUTFChars(env, enc, encname);
+ }
+ }
+ } else {
+ (*env)->ExceptionClear(env);
+ }
+ } else {
+ (*env)->ExceptionClear(env);
+ }
+ (*env)->DeleteLocalRef(env, propname);
+ (*env)->DeleteLocalRef(env, enc);
+
+ /* Initialize method-id cache */
+ String_getBytes_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+ "getBytes", "(Ljava/lang/String;)[B");
+ String_init_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+ "<init>", "([BLjava/lang/String;)V");
+}
+
+static jboolean isJNUEncodingSupported = JNI_FALSE;
+static jboolean jnuEncodingSupported(JNIEnv *env) {
+ jboolean exe;
+ if (isJNUEncodingSupported == JNI_TRUE) {
+ return JNI_TRUE;
+ }
+ isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
+ env, &exe,
+ "java/nio/charset/Charset",
+ "isSupported",
+ "(Ljava/lang/String;)Z",
+ jnuEncoding).z;
+ return isJNUEncodingSupported;
+}
+
+
+JNIEXPORT jstring
+NewStringPlatform(JNIEnv *env, const char *str)
+{
+ return JNU_NewStringPlatform(env, str);
+}
+
+JNIEXPORT jstring JNICALL
+JNU_NewStringPlatform(JNIEnv *env, const char *str)
+{
+ jstring result;
+ result = nativeNewStringPlatform(env, str);
+ if (result == NULL) {
+ jbyteArray hab = 0;
+ int len;
+
+ if (fastEncoding == NO_ENCODING_YET)
+ initializeEncoding(env);
+
+ if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
+ return newString8859_1(env, str);
+ if (fastEncoding == FAST_646_US)
+ return newString646_US(env, str);
+ if (fastEncoding == FAST_CP1252)
+ return newStringCp1252(env, str);
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+ return NULL;
+
+ len = (int)strlen(str);
+ hab = (*env)->NewByteArray(env, len);
+ if (hab != 0) {
+ (*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
+ if (jnuEncodingSupported(env)) {
+ result = (*env)->NewObject(env, JNU_ClassString(env),
+ String_init_ID, hab, jnuEncoding);
+ } else {
+ /*If the encoding specified in sun.jnu.encoding is not endorsed
+ by "Charset.isSupported" we have to fall back to use String(byte[])
+ explicitly here without specifying the encoding name, in which the
+ StringCoding class will pickup the iso-8859-1 as the fallback
+ converter for us.
+ */
+ jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+ "<init>", "([B)V");
+ result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
+ }
+ (*env)->DeleteLocalRef(env, hab);
+ return result;
+ }
+ }
+ return NULL;
+}
+
+JNIEXPORT const char *
+GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
+{
+ return JNU_GetStringPlatformChars(env, jstr, isCopy);
+}
+
+JNIEXPORT const char * JNICALL
+JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
+{
+ char *result = nativeGetStringPlatformChars(env, jstr, isCopy);
+ if (result == NULL) {
+
+ jbyteArray hab = 0;
+
+ if (isCopy)
+ *isCopy = JNI_TRUE;
+
+ if (fastEncoding == NO_ENCODING_YET)
+ initializeEncoding(env);
+
+ if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
+ return getString8859_1Chars(env, jstr);
+ if (fastEncoding == FAST_646_US)
+ return getString646_USChars(env, jstr);
+ if (fastEncoding == FAST_CP1252)
+ return getStringCp1252Chars(env, jstr);
+
+ if ((*env)->EnsureLocalCapacity(env, 2) < 0)
+ return 0;
+
+ if (jnuEncodingSupported(env)) {
+ hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
+ } else {
+ jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+ "getBytes", "()[B");
+ hab = (*env)->CallObjectMethod(env, jstr, mid);
+ }
+
+ if (!(*env)->ExceptionCheck(env)) {
+ jint len = (*env)->GetArrayLength(env, hab);
+ result = MALLOC_MIN4(len);
+ if (result == 0) {
+ JNU_ThrowOutOfMemoryError(env, 0);
+ (*env)->DeleteLocalRef(env, hab);
+ return 0;
+ }
+ (*env)->GetByteArrayRegion(env, hab, 0, len, (jbyte *)result);
+ result[len] = 0; /* NULL-terminate */
+ }
+
+ (*env)->DeleteLocalRef(env, hab);
+ }
+ return result;
+}
+
+JNIEXPORT void JNICALL
+JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
+{
+ free((void *)str);
+}
+
+/*
+ * Export the platform dependent path canonicalization so that
+ * VM can find it when loading system classes.
+ *
+ */
+extern int canonicalize(char *path, const char *out, int len);
+
+JNIEXPORT int
+Canonicalize(JNIEnv *env, char *orig, char *out, int len)
+{
+ /* canonicalize an already natived path */
+ return canonicalize(orig, out, len);
+}
+
+JNIEXPORT jclass JNICALL
+JNU_ClassString(JNIEnv *env)
+{
+ static jclass cls = 0;
+ if (cls == 0) {
+ jclass c;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return 0;
+ c = (*env)->FindClass(env, "java/lang/String");
+ cls = (*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return cls;
+}
+
+JNIEXPORT jclass JNICALL
+JNU_ClassClass(JNIEnv *env)
+{
+ static jclass cls = 0;
+ if (cls == 0) {
+ jclass c;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return 0;
+ c = (*env)->FindClass(env, "java/lang/Class");
+ cls = (*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return cls;
+}
+
+JNIEXPORT jclass JNICALL
+JNU_ClassObject(JNIEnv *env)
+{
+ static jclass cls = 0;
+ if (cls == 0) {
+ jclass c;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return 0;
+ c = (*env)->FindClass(env, "java/lang/Object");
+ cls = (*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return cls;
+}
+
+JNIEXPORT jclass JNICALL
+JNU_ClassThrowable(JNIEnv *env)
+{
+ static jclass cls = 0;
+ if (cls == 0) {
+ jclass c;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return 0;
+ c = (*env)->FindClass(env, "java/lang/Throwable");
+ cls = (*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ return cls;
+}
+
+JNIEXPORT jint JNICALL
+JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
+ jint count)
+{
+ int i;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return -1;
+ for (i=0; i<count; i++) {
+ jstring p = (*env)->GetObjectArrayElement(env, src, i);
+ (*env)->SetObjectArrayElement(env, dst, i, p);
+ (*env)->DeleteLocalRef(env, p);
+ }
+ return 0;
+}
+
+JNIEXPORT void * JNICALL
+JNU_GetEnv(JavaVM *vm, jint version)
+{
+ void *env;
+ (*vm)->GetEnv(vm, &env, version);
+ return env;
+}
+
+JNIEXPORT jint JNICALL
+JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char* classname)
+{
+ jclass cls;
+ if ((*env)->EnsureLocalCapacity(env, 1) < 0)
+ return JNI_ERR;
+ cls = (*env)->FindClass(env, classname);
+ if (cls != NULL) {
+ jint result = (*env)->IsInstanceOf(env, object, cls);
+ (*env)->DeleteLocalRef(env, cls);
+ return result;
+ }
+ return JNI_ERR;
+}
+
+JNIEXPORT jboolean JNICALL
+JNU_Equals(JNIEnv *env, jobject object1, jobject object2)
+{
+ static jmethodID mid = NULL;
+ if (mid == NULL) {
+ mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals",
+ "(Ljava/lang/Object;)Z");
+ }
+ return (*env)->CallBooleanMethod(env, object1, mid, object2);
+}
+
+
+/************************************************************************
+ * Thread calls
+ */
+
+static jmethodID Object_waitMID;
+static jmethodID Object_notifyMID;
+static jmethodID Object_notifyAllMID;
+
+JNIEXPORT void JNICALL
+JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout)
+{
+ if (object == NULL) {
+ JNU_ThrowNullPointerException(env, "JNU_MonitorWait argument");
+ return;
+ }
+ if (Object_waitMID == NULL) {
+ jclass cls = JNU_ClassObject(env);
+ if (cls == NULL) {
+ return;
+ }
+ Object_waitMID = (*env)->GetMethodID(env, cls, "wait", "(J)V");
+ if (Object_waitMID == NULL) {
+ return;
+ }
+ }
+ (*env)->CallVoidMethod(env, object, Object_waitMID, timeout);
+}
+
+JNIEXPORT void JNICALL
+JNU_Notify(JNIEnv *env, jobject object)
+{
+ if (object == NULL) {
+ JNU_ThrowNullPointerException(env, "JNU_Notify argument");
+ return;
+ }
+ if (Object_notifyMID == NULL) {
+ jclass cls = JNU_ClassObject(env);
+ if (cls == NULL) {
+ return;
+ }
+ Object_notifyMID = (*env)->GetMethodID(env, cls, "notify", "()V");
+ if (Object_notifyMID == NULL) {
+ return;
+ }
+ }
+ (*env)->CallVoidMethod(env, object, Object_notifyMID);
+}
+
+JNIEXPORT void JNICALL
+JNU_NotifyAll(JNIEnv *env, jobject object)
+{
+ if (object == NULL) {
+ JNU_ThrowNullPointerException(env, "JNU_NotifyAll argument");
+ return;
+ }
+ if (Object_notifyAllMID == NULL) {
+ jclass cls = JNU_ClassObject(env);
+ if (cls == NULL) {
+ return;
+ }
+ Object_notifyAllMID = (*env)->GetMethodID(env, cls,"notifyAll", "()V");
+ if (Object_notifyAllMID == NULL) {
+ return;
+ }
+ }
+ (*env)->CallVoidMethod(env, object, Object_notifyAllMID);
+}
+
+
+/************************************************************************
+ * Debugging utilities
+ */
+
+JNIEXPORT void JNICALL
+JNU_PrintString(JNIEnv *env, char *hdr, jstring string)
+{
+ if (string == NULL) {
+ fprintf(stderr, "%s: is NULL\n", hdr);
+ } else {
+ const char *stringPtr = JNU_GetStringPlatformChars(env, string, 0);
+ if (stringPtr == 0)
+ return;
+ fprintf(stderr, "%s: %s\n", hdr, stringPtr);
+ JNU_ReleaseStringPlatformChars(env, string, stringPtr);
+ }
+}
+
+JNIEXPORT void JNICALL
+JNU_PrintClass(JNIEnv *env, char* hdr, jobject object)
+{
+ if (object == NULL) {
+ fprintf(stderr, "%s: object is NULL\n", hdr);
+ return;
+ } else {
+ jclass cls = (*env)->GetObjectClass(env, object);
+ jstring clsName = JNU_ToString(env, cls);
+ JNU_PrintString(env, hdr, clsName);
+ (*env)->DeleteLocalRef(env, cls);
+ (*env)->DeleteLocalRef(env, clsName);
+ }
+}
+
+JNIEXPORT jstring JNICALL
+JNU_ToString(JNIEnv *env, jobject object)
+{
+ if (object == NULL) {
+ return (*env)->NewStringUTF(env, "NULL");
+ } else {
+ return (jstring)JNU_CallMethodByName(env,
+ NULL,
+ object,
+ "toString",
+ "()Ljava/lang/String;").l;
+ }
+}
+
+JNIEXPORT jvalue JNICALL
+JNU_GetFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature)
+{
+ jclass cls;
+ jfieldID fid;
+ jvalue result;
+
+ result.i = 0;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ cls = (*env)->GetObjectClass(env, obj);
+ fid = (*env)->GetFieldID(env, cls, name, signature);
+ if (fid == 0)
+ goto done1;
+
+ switch (*signature) {
+ case '[':
+ case 'L':
+ result.l = (*env)->GetObjectField(env, obj, fid);
+ break;
+ case 'Z':
+ result.z = (*env)->GetBooleanField(env, obj, fid);
+ break;
+ case 'B':
+ result.b = (*env)->GetByteField(env, obj, fid);
+ break;
+ case 'C':
+ result.c = (*env)->GetCharField(env, obj, fid);
+ break;
+ case 'S':
+ result.s = (*env)->GetShortField(env, obj, fid);
+ break;
+ case 'I':
+ result.i = (*env)->GetIntField(env, obj, fid);
+ break;
+ case 'J':
+ result.j = (*env)->GetLongField(env, obj, fid);
+ break;
+ case 'F':
+ result.f = (*env)->GetFloatField(env, obj, fid);
+ break;
+ case 'D':
+ result.d = (*env)->GetDoubleField(env, obj, fid);
+ break;
+
+ default:
+ (*env)->FatalError(env, "JNU_GetFieldByName: illegal signature");
+ }
+
+ done1:
+ (*env)->DeleteLocalRef(env, cls);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+ return result;
+}
+
+JNIEXPORT void JNICALL
+JNU_SetFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature,
+ ...)
+{
+ jclass cls;
+ jfieldID fid;
+ va_list args;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ cls = (*env)->GetObjectClass(env, obj);
+ fid = (*env)->GetFieldID(env, cls, name, signature);
+ if (fid == 0)
+ goto done1;
+
+ va_start(args, signature);
+ switch (*signature) {
+ case '[':
+ case 'L':
+ (*env)->SetObjectField(env, obj, fid, va_arg(args, jobject));
+ break;
+ case 'Z':
+ (*env)->SetBooleanField(env, obj, fid, (jboolean)va_arg(args, int));
+ break;
+ case 'B':
+ (*env)->SetByteField(env, obj, fid, (jbyte)va_arg(args, int));
+ break;
+ case 'C':
+ (*env)->SetCharField(env, obj, fid, (jchar)va_arg(args, int));
+ break;
+ case 'S':
+ (*env)->SetShortField(env, obj, fid, (jshort)va_arg(args, int));
+ break;
+ case 'I':
+ (*env)->SetIntField(env, obj, fid, va_arg(args, jint));
+ break;
+ case 'J':
+ (*env)->SetLongField(env, obj, fid, va_arg(args, jlong));
+ break;
+ case 'F':
+ (*env)->SetFloatField(env, obj, fid, (jfloat)va_arg(args, jdouble));
+ break;
+ case 'D':
+ (*env)->SetDoubleField(env, obj, fid, va_arg(args, jdouble));
+ break;
+
+ default:
+ (*env)->FatalError(env, "JNU_SetFieldByName: illegal signature");
+ }
+ va_end(args);
+
+ done1:
+ (*env)->DeleteLocalRef(env, cls);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+}
+
+JNIEXPORT jvalue JNICALL
+JNU_GetStaticFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *classname,
+ const char *name,
+ const char *signature)
+{
+ jclass cls;
+ jfieldID fid;
+ jvalue result;
+
+ result.i = 0;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ cls = (*env)->FindClass(env, classname);
+ if (cls == 0)
+ goto done2;
+
+ fid = (*env)->GetStaticFieldID(env, cls, name, signature);
+ if (fid == 0)
+ goto done1;
+
+ switch (*signature) {
+ case '[':
+ case 'L':
+ result.l = (*env)->GetStaticObjectField(env, cls, fid);
+ break;
+ case 'Z':
+ result.z = (*env)->GetStaticBooleanField(env, cls, fid);
+ break;
+ case 'B':
+ result.b = (*env)->GetStaticByteField(env, cls, fid);
+ break;
+ case 'C':
+ result.c = (*env)->GetStaticCharField(env, cls, fid);
+ break;
+ case 'S':
+ result.s = (*env)->GetStaticShortField(env, cls, fid);
+ break;
+ case 'I':
+ result.i = (*env)->GetStaticIntField(env, cls, fid);
+ break;
+ case 'J':
+ result.j = (*env)->GetStaticLongField(env, cls, fid);
+ break;
+ case 'F':
+ result.f = (*env)->GetStaticFloatField(env, cls, fid);
+ break;
+ case 'D':
+ result.d = (*env)->GetStaticDoubleField(env, cls, fid);
+ break;
+
+ default:
+ (*env)->FatalError(env, "JNU_GetStaticFieldByName: illegal signature");
+ }
+
+ done1:
+ (*env)->DeleteLocalRef(env, cls);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+ return result;
+}
+
+JNIEXPORT void JNICALL
+JNU_SetStaticFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *classname,
+ const char *name,
+ const char *signature,
+ ...)
+{
+ jclass cls;
+ jfieldID fid;
+ va_list args;
+
+ if ((*env)->EnsureLocalCapacity(env, 3) < 0)
+ goto done2;
+
+ cls = (*env)->FindClass(env, classname);
+ if (cls == 0)
+ goto done2;
+
+ fid = (*env)->GetStaticFieldID(env, cls, name, signature);
+ if (fid == 0)
+ goto done1;
+
+ va_start(args, signature);
+ switch (*signature) {
+ case '[':
+ case 'L':
+ (*env)->SetStaticObjectField(env, cls, fid, va_arg(args, jobject));
+ break;
+ case 'Z':
+ (*env)->SetStaticBooleanField(env, cls, fid, (jboolean)va_arg(args, int));
+ break;
+ case 'B':
+ (*env)->SetStaticByteField(env, cls, fid, (jbyte)va_arg(args, int));
+ break;
+ case 'C':
+ (*env)->SetStaticCharField(env, cls, fid, (jchar)va_arg(args, int));
+ break;
+ case 'S':
+ (*env)->SetStaticShortField(env, cls, fid, (jshort)va_arg(args, int));
+ break;
+ case 'I':
+ (*env)->SetStaticIntField(env, cls, fid, va_arg(args, jint));
+ break;
+ case 'J':
+ (*env)->SetStaticLongField(env, cls, fid, va_arg(args, jlong));
+ break;
+ case 'F':
+ (*env)->SetStaticFloatField(env, cls, fid, (jfloat)va_arg(args, jdouble));
+ break;
+ case 'D':
+ (*env)->SetStaticDoubleField(env, cls, fid, va_arg(args, jdouble));
+ break;
+
+ default:
+ (*env)->FatalError(env, "JNU_SetStaticFieldByName: illegal signature");
+ }
+ va_end(args);
+
+ done1:
+ (*env)->DeleteLocalRef(env, cls);
+ done2:
+ if (hasException) {
+ *hasException = (*env)->ExceptionCheck(env);
+ }
+}
diff --git a/ojluni/src/main/native/jni_util.h b/ojluni/src/main/native/jni_util.h
new file mode 100755
index 0000000..55dd0fa
--- /dev/null
+++ b/ojluni/src/main/native/jni_util.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef JNI_UTIL_H
+#define JNI_UTIL_H
+
+#include "jni.h"
+#include "jlong.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains utility functions that can be implemented in pure JNI.
+ *
+ * Caution: Callers of functions declared in this file should be
+ * particularly aware of the fact that these functions are convenience
+ * functions, and as such are often compound operations, each one of
+ * which may throw an exception. Therefore, the functions this file
+ * will often return silently if an exception has occured, and callers
+ * must check for exception themselves.
+ */
+
+/* Throw a Java exception by name. Similar to SignalError. */
+JNIEXPORT void JNICALL
+JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg);
+
+/* Throw common exceptions */
+JNIEXPORT void JNICALL
+JNU_ThrowNullPointerException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowArrayIndexOutOfBoundsException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowOutOfMemoryError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalArgumentException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIllegalAccessException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowInternalError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowIOException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowClassNotFoundException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNumberFormatException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchFieldError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowNoSuchMethodError(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowStringIndexOutOfBoundsException(JNIEnv *env, const char *msg);
+
+JNIEXPORT void JNICALL
+JNU_ThrowInstantiationException(JNIEnv *env, const char *msg);
+
+/* Throw an exception by name, using the string returned by
+ * JVM_LastErrorString for the detail string. If the last-error
+ * string is NULL, use the given default detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+ const char *defaultMessage);
+
+/* Throw an IOException, using the last-error string for the detail
+ * string. If the last-error string is NULL, use the given default
+ * detail string.
+ */
+JNIEXPORT void JNICALL
+JNU_ThrowIOExceptionWithLastError(JNIEnv *env, const char *defaultDetail);
+
+/* Convert between Java strings and i18n C strings */
+JNIEXPORT jstring
+NewStringPlatform(JNIEnv *env, const char *str);
+
+JNIEXPORT const char *
+GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+JNIEXPORT jstring JNICALL
+JNU_NewStringPlatform(JNIEnv *env, const char *str);
+
+JNIEXPORT const char * JNICALL
+JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+JNIEXPORT void JNICALL
+JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str);
+
+/* Class constants */
+JNIEXPORT jclass JNICALL
+JNU_ClassString(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassClass(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassObject(JNIEnv *env);
+
+JNIEXPORT jclass JNICALL
+JNU_ClassThrowable(JNIEnv *env);
+
+/* Copy count number of arguments from src to dst. Array bounds
+ * and ArrayStoreException are checked.
+ */
+JNIEXPORT jint JNICALL
+JNU_CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
+ jint count);
+
+/* Invoke a object-returning static method, based on class name,
+ * method name, and signature string.
+ *
+ * The caller should check for exceptions by setting hasException
+ * argument. If the caller is not interested in whether an exception
+ * has occurred, pass in NULL.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_CallStaticMethodByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *class_name,
+ const char *name,
+ const char *signature,
+ ...);
+
+/* Invoke an instance method by name.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature,
+ ...);
+
+JNIEXPORT jvalue JNICALL
+JNU_CallMethodByNameV(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *signature,
+ va_list args);
+
+/* Construct a new object of class, specifying the class by name,
+ * and specififying which constructor to run and what arguments to
+ * pass to it.
+ *
+ * The method will return an initialized instance if successful.
+ * It will return NULL if an error has occured (for example if
+ * it ran out of memory) and the appropriate Java exception will
+ * have been thrown.
+ */
+JNIEXPORT jobject JNICALL
+JNU_NewObjectByName(JNIEnv *env, const char *class_name,
+ const char *constructor_sig, ...);
+
+/* returns:
+ * 0: object is not an instance of the class named by classname.
+ * 1: object is an instance of the class named by classname.
+ * -1: the class named by classname cannot be found. An exception
+ * has been thrown.
+ */
+JNIEXPORT jint JNICALL
+JNU_IsInstanceOfByName(JNIEnv *env, jobject object, char *classname);
+
+
+/* Get or set class and instance fields.
+ * Note that set functions take a variable number of arguments,
+ * but only one argument of the appropriate type can be passed.
+ * For example, to set an integer field i to 100:
+ *
+ * JNU_SetFieldByName(env, &exc, obj, "i", "I", 100);
+ *
+ * To set a float field f to 12.3:
+ *
+ * JNU_SetFieldByName(env, &exc, obj, "f", "F", 12.3);
+ *
+ * The caller should check for exceptions by setting hasException
+ * argument. If the caller is not interested in whether an exception
+ * has occurred, pass in NULL.
+ */
+JNIEXPORT jvalue JNICALL
+JNU_GetFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *sig);
+JNIEXPORT void JNICALL
+JNU_SetFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ jobject obj,
+ const char *name,
+ const char *sig,
+ ...);
+
+JNIEXPORT jvalue JNICALL
+JNU_GetStaticFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *classname,
+ const char *name,
+ const char *sig);
+JNIEXPORT void JNICALL
+JNU_SetStaticFieldByName(JNIEnv *env,
+ jboolean *hasException,
+ const char *classname,
+ const char *name,
+ const char *sig,
+ ...);
+
+
+/*
+ * Calls the .equals method.
+ */
+JNIEXPORT jboolean JNICALL
+JNU_Equals(JNIEnv *env, jobject object1, jobject object2);
+
+
+/************************************************************************
+ * Thread calls
+ *
+ * Convenience thread-related calls on the java.lang.Object class.
+ */
+
+JNIEXPORT void JNICALL
+JNU_MonitorWait(JNIEnv *env, jobject object, jlong timeout);
+
+JNIEXPORT void JNICALL
+JNU_Notify(JNIEnv *env, jobject object);
+
+JNIEXPORT void JNICALL
+JNU_NotifyAll(JNIEnv *env, jobject object);
+
+
+/************************************************************************
+ * Miscellaneous utilities used by the class libraries
+ */
+
+#define IS_NULL(obj) ((obj) == NULL)
+#define JNU_IsNull(env,obj) ((obj) == NULL)
+
+
+/************************************************************************
+ * Debugging utilities
+ */
+
+JNIEXPORT void JNICALL
+JNU_PrintString(JNIEnv *env, char *hdr, jstring string);
+
+JNIEXPORT void JNICALL
+JNU_PrintClass(JNIEnv *env, char *hdr, jobject object);
+
+JNIEXPORT jstring JNICALL
+JNU_ToString(JNIEnv *env, jobject object);
+
+/*
+ * Package shorthand for use by native libraries
+ */
+#define JNU_JAVAPKG "java/lang/"
+#define JNU_JAVAIOPKG "java/io/"
+#define JNU_JAVANETPKG "java/net/"
+
+/*
+ * Check if the current thread is attached to the VM, and returns
+ * the JNIEnv of the specified version if the thread is attached.
+ *
+ * If the current thread is not attached, this function returns 0.
+ *
+ * If the current thread is attached, this function returns the
+ * JNI environment, or returns (void *)JNI_ERR if the specified
+ * version is not supported.
+ */
+JNIEXPORT void * JNICALL
+JNU_GetEnv(JavaVM *vm, jint version);
+
+/*
+ * Warning free access to pointers stored in Java long fields.
+ */
+#define JNU_GetLongFieldAsPtr(env,obj,id) \
+ (jlong_to_ptr((*(env))->GetLongField((env),(obj),(id))))
+#define JNU_SetLongFieldFromPtr(env,obj,id,val) \
+ (*(env))->SetLongField((env),(obj),(id),ptr_to_jlong(val))
+
+/*
+ * Internal use only.
+ */
+enum {
+ NO_ENCODING_YET = 0, /* "sun.jnu.encoding" not yet set */
+ NO_FAST_ENCODING, /* Platform encoding is not fast */
+ FAST_8859_1, /* ISO-8859-1 */
+ FAST_CP1252, /* MS-DOS Cp1252 */
+ FAST_646_US /* US-ASCII : ISO646-US */
+};
+
+jstring nativeNewStringPlatform(JNIEnv *env, const char *str);
+
+char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);
+
+int getFastEncoding();
+
+void initializeEncoding();
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* JNI_UTIL_H */
diff --git a/ojluni/src/main/native/jni_util_md.c b/ojluni/src/main/native/jni_util_md.c
new file mode 100755
index 0000000..dc9fb99
--- /dev/null
+++ b/ojluni/src/main/native/jni_util_md.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+
+jstring nativeNewStringPlatform(JNIEnv *env, const char *str) {
+ return NULL;
+}
+
+char* nativeGetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy) {
+ return NULL;
+}
diff --git a/ojluni/src/main/native/jvm.h b/ojluni/src/main/native/jvm.h
new file mode 100755
index 0000000..f298cca
--- /dev/null
+++ b/ojluni/src/main/native/jvm.h
@@ -0,0 +1,1486 @@
+/*
+ * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVASOFT_JVM_H_
+#define _JAVASOFT_JVM_H_
+
+#include <sys/stat.h>
+
+#include "jni.h"
+#include "jvm_md.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file contains additional functions exported from the VM.
+ * These functions are complementary to the standard JNI support.
+ * There are three parts to this file:
+ *
+ * First, this file contains the VM-related functions needed by native
+ * libraries in the standard Java API. For example, the java.lang.Object
+ * class needs VM-level functions that wait for and notify monitors.
+ *
+ * Second, this file contains the functions and constant definitions
+ * needed by the byte code verifier and class file format checker.
+ * These functions allow the verifier and format checker to be written
+ * in a VM-independent way.
+ *
+ * Third, this file contains various I/O and nerwork operations needed
+ * by the standard Java I/O and network APIs.
+ */
+
+/*
+ * Bump the version number when either of the following happens:
+ *
+ * 1. There is a change in JVM_* functions.
+ *
+ * 2. There is a change in the contract between VM and Java classes.
+ * For example, if the VM relies on a new private field in Thread
+ * class.
+ */
+
+#define JVM_INTERFACE_VERSION 4
+
+JNIEXPORT jint JNICALL
+JVM_GetInterfaceVersion(void);
+
+/*************************************************************************
+ PART 1: Functions for Native Libraries
+ ************************************************************************/
+/*
+ * java.lang.Object
+ */
+JNIEXPORT jint JNICALL
+JVM_IHashCode(JNIEnv *env, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms);
+
+JNIEXPORT void JNICALL
+JVM_MonitorNotify(JNIEnv *env, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_MonitorNotifyAll(JNIEnv *env, jobject obj);
+
+JNIEXPORT jobject JNICALL
+JVM_Clone(JNIEnv *env, jobject obj);
+
+/*
+ * java.lang.String
+ */
+JNIEXPORT jstring JNICALL
+JVM_InternString(JNIEnv *env, jstring str);
+
+/*
+ * java.lang.System
+ */
+JNIEXPORT jlong JNICALL
+JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
+
+JNIEXPORT jlong JNICALL
+JVM_NanoTime(JNIEnv *env, jclass ignored);
+
+JNIEXPORT void JNICALL
+JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
+ jobject dst, jint dst_pos, jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_InitProperties(JNIEnv *env, jobject p);
+
+/*
+ * java.io.File
+ */
+JNIEXPORT void JNICALL
+JVM_OnExit(void (*func)(void));
+
+/*
+ * java.lang.Runtime
+ */
+JNIEXPORT void JNICALL
+JVM_Exit(jint code);
+
+JNIEXPORT void JNICALL
+JVM_Halt(jint code);
+
+JNIEXPORT void JNICALL
+JVM_GC(void);
+
+/* Returns the number of real-time milliseconds that have elapsed since the
+ * least-recently-inspected heap object was last inspected by the garbage
+ * collector.
+ *
+ * For simple stop-the-world collectors this value is just the time
+ * since the most recent collection. For generational collectors it is the
+ * time since the oldest generation was most recently collected. Other
+ * collectors are free to return a pessimistic estimate of the elapsed time, or
+ * simply the time since the last full collection was performed.
+ *
+ * Note that in the presence of reference objects, a given object that is no
+ * longer strongly reachable may have to be inspected multiple times before it
+ * can be reclaimed.
+ */
+JNIEXPORT jlong JNICALL
+JVM_MaxObjectInspectionAge(void);
+
+JNIEXPORT void JNICALL
+JVM_TraceInstructions(jboolean on);
+
+JNIEXPORT void JNICALL
+JVM_TraceMethodCalls(jboolean on);
+
+JNIEXPORT jlong JNICALL
+JVM_TotalMemory(void);
+
+JNIEXPORT jlong JNICALL
+JVM_FreeMemory(void);
+
+JNIEXPORT jlong JNICALL
+JVM_MaxMemory(void);
+
+JNIEXPORT jint JNICALL
+JVM_ActiveProcessorCount(void);
+
+JNIEXPORT void * JNICALL
+JVM_LoadLibrary(const char *name);
+
+JNIEXPORT void JNICALL
+JVM_UnloadLibrary(void * handle);
+
+JNIEXPORT void * JNICALL
+JVM_FindLibraryEntry(void *handle, const char *name);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsSupportedJNIVersion(jint version);
+
+/*
+ * java.lang.Float and java.lang.Double
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsNaN(jdouble d);
+
+/*
+ * java.lang.Throwable
+ */
+JNIEXPORT void JNICALL
+JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
+
+JNIEXPORT void JNICALL
+JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable);
+
+JNIEXPORT jint JNICALL
+JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable);
+
+JNIEXPORT jobject JNICALL
+JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index);
+
+/*
+ * java.lang.Compiler
+ */
+JNIEXPORT void JNICALL
+JVM_InitializeCompiler (JNIEnv *env, jclass compCls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsSilentCompiler(JNIEnv *env, jclass compCls);
+
+JNIEXPORT jboolean JNICALL
+JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname);
+
+JNIEXPORT jobject JNICALL
+JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg);
+
+JNIEXPORT void JNICALL
+JVM_EnableCompiler(JNIEnv *env, jclass compCls);
+
+JNIEXPORT void JNICALL
+JVM_DisableCompiler(JNIEnv *env, jclass compCls);
+
+/*
+ * java.lang.Thread
+ */
+JNIEXPORT void JNICALL
+JVM_StartThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsThreadAlive(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_SuspendThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_ResumeThread(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
+
+JNIEXPORT void JNICALL
+JVM_Yield(JNIEnv *env, jclass threadClass);
+
+JNIEXPORT void JNICALL
+JVM_Sleep(JNIEnv *env, jclass threadClass, jlong millis);
+
+JNIEXPORT jobject JNICALL
+JVM_CurrentThread(JNIEnv *env, jclass threadClass);
+
+JNIEXPORT jint JNICALL
+JVM_CountStackFrames(JNIEnv *env, jobject thread);
+
+JNIEXPORT void JNICALL
+JVM_Interrupt(JNIEnv *env, jobject thread);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsInterrupted(JNIEnv *env, jobject thread, jboolean clearInterrupted);
+
+JNIEXPORT jboolean JNICALL
+JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj);
+
+JNIEXPORT void JNICALL
+JVM_DumpAllStacks(JNIEnv *env, jclass unused);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetAllThreads(JNIEnv *env, jclass dummy);
+
+JNIEXPORT void JNICALL
+JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name);
+
+/* getStackTrace() and getAllStackTraces() method */
+JNIEXPORT jobjectArray JNICALL
+JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
+
+/*
+ * java.lang.SecurityManager
+ */
+JNIEXPORT jclass JNICALL
+JVM_CurrentLoadedClass(JNIEnv *env);
+
+JNIEXPORT jobject JNICALL
+JVM_CurrentClassLoader(JNIEnv *env);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassContext(JNIEnv *env);
+
+JNIEXPORT jint JNICALL
+JVM_ClassDepth(JNIEnv *env, jstring name);
+
+JNIEXPORT jint JNICALL
+JVM_ClassLoaderDepth(JNIEnv *env);
+
+/*
+ * java.lang.Package
+ */
+JNIEXPORT jstring JNICALL
+JVM_GetSystemPackage(JNIEnv *env, jstring name);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetSystemPackages(JNIEnv *env);
+
+/*
+ * java.io.ObjectInputStream
+ */
+JNIEXPORT jobject JNICALL
+JVM_AllocateNewObject(JNIEnv *env, jobject obj, jclass currClass,
+ jclass initClass);
+
+JNIEXPORT jobject JNICALL
+JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass,
+ jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_LatestUserDefinedLoader(JNIEnv *env);
+
+/*
+ * This function has been deprecated and should not be considered
+ * part of the specified JVM interface.
+ */
+JNIEXPORT jclass JNICALL
+JVM_LoadClass0(JNIEnv *env, jobject obj, jclass currClass,
+ jstring currClassName);
+
+/*
+ * java.lang.reflect.Array
+ */
+JNIEXPORT jint JNICALL
+JVM_GetArrayLength(JNIEnv *env, jobject arr);
+
+JNIEXPORT jobject JNICALL
+JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index);
+
+JNIEXPORT jvalue JNICALL
+JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode);
+
+JNIEXPORT void JNICALL
+JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val);
+
+JNIEXPORT void JNICALL
+JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
+ unsigned char vCode);
+
+JNIEXPORT jobject JNICALL
+JVM_NewArray(JNIEnv *env, jclass eltClass, jint length);
+
+JNIEXPORT jobject JNICALL
+JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
+
+/*
+ * java.lang.Class and java.lang.ClassLoader
+ */
+/*
+ * Returns the class in which the code invoking the native method
+ * belongs.
+ *
+ * Note that in JDK 1.1, native methods did not create a frame.
+ * In 1.2, they do. Therefore native methods like Class.forName
+ * can no longer look at the current frame for the caller class.
+ */
+JNIEXPORT jclass JNICALL
+JVM_GetCallerClass(JNIEnv *env, int n);
+
+/*
+ * Find primitive classes
+ * utf: class name
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
+
+/*
+ * Link the class
+ */
+JNIEXPORT void JNICALL
+JVM_ResolveClass(JNIEnv *env, jclass cls);
+
+/*
+ * Find a class from a boot class loader. Returns NULL if class not found.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
+
+/*
+ * Find a class from a given class loader. Throw ClassNotFoundException
+ * or NoClassDefFoundError depending on the value of the last
+ * argument.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
+ jobject loader, jboolean throwError);
+
+/*
+ * Find a class from a given class.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
+ jclass from);
+
+/* Find a loaded class cached by the VM */
+JNIEXPORT jclass JNICALL
+JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name);
+
+/* Define a class */
+JNIEXPORT jclass JNICALL
+JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
+ jsize len, jobject pd);
+
+/* Define a class with a source (added in JDK1.5) */
+JNIEXPORT jclass JNICALL
+JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
+ const jbyte *buf, jsize len, jobject pd,
+ const char *source);
+
+/*
+ * Reflection support functions
+ */
+
+JNIEXPORT jstring JNICALL
+JVM_GetClassName(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassInterfaces(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobject JNICALL
+JVM_GetClassLoader(JNIEnv *env, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsInterface(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassSigners(JNIEnv *env, jclass cls);
+
+JNIEXPORT void JNICALL
+JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers);
+
+JNIEXPORT jobject JNICALL
+JVM_GetProtectionDomain(JNIEnv *env, jclass cls);
+
+JNIEXPORT void JNICALL
+JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsArrayClass(JNIEnv *env, jclass cls);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
+
+JNIEXPORT jclass JNICALL
+JVM_GetComponentType(JNIEnv *env, jclass cls);
+
+JNIEXPORT jint JNICALL
+JVM_GetClassModifiers(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass);
+
+JNIEXPORT jclass JNICALL
+JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass);
+
+/* Generics support (JDK 1.5) */
+JNIEXPORT jstring JNICALL
+JVM_GetClassSignature(JNIEnv *env, jclass cls);
+
+/* Annotations support (JDK 1.5) */
+JNIEXPORT jbyteArray JNICALL
+JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
+
+/*
+ * New (JDK 1.4) reflection implementation
+ */
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
+
+/* Differs from JVM_GetClassModifiers in treatment of inner classes.
+ This returns the access flags for the class as specified in the
+ class file rather than searching the InnerClasses attribute (if
+ present) to find the source-level access flags. Only the values of
+ the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
+ valid. */
+JNIEXPORT jint JNICALL
+JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
+
+/* The following two reflection routines are still needed due to startup time issues */
+/*
+ * java.lang.reflect.Method
+ */
+JNIEXPORT jobject JNICALL
+JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
+
+/*
+ * java.lang.reflect.Constructor
+ */
+JNIEXPORT jobject JNICALL
+JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
+
+/*
+ * Constant pool access; currently used to implement reflective access to annotations (JDK 1.5)
+ */
+
+JNIEXPORT jobject JNICALL
+JVM_GetClassConstantPool(JNIEnv *env, jclass cls);
+
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
+(JNIEnv *env, jobject unused, jobject jcpool);
+
+JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
+(JNIEnv *env, jobject unused, jobject jcpool, jint index);
+
+/*
+ * java.security.*
+ */
+
+JNIEXPORT jobject JNICALL
+JVM_DoPrivileged(JNIEnv *env, jclass cls,
+ jobject action, jobject context, jboolean wrapException);
+
+JNIEXPORT jobject JNICALL
+JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls);
+
+JNIEXPORT jobject JNICALL
+JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls);
+
+/*
+ * Signal support, used to implement the shutdown sequence. Every VM must
+ * support JVM_SIGINT and JVM_SIGTERM, raising the former for user interrupts
+ * (^C) and the latter for external termination (kill, system shutdown, etc.).
+ * Other platform-dependent signal values may also be supported.
+ */
+
+JNIEXPORT void * JNICALL
+JVM_RegisterSignal(jint sig, void *handler);
+
+JNIEXPORT jboolean JNICALL
+JVM_RaiseSignal(jint sig);
+
+JNIEXPORT jint JNICALL
+JVM_FindSignal(const char *name);
+
+/*
+ * Retrieve the assertion directives for the specified class.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls);
+
+/*
+ * Retrieve the assertion directives from the VM.
+ */
+JNIEXPORT jobject JNICALL
+JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
+
+/*
+ * java.util.concurrent.AtomicLong
+ */
+JNIEXPORT jboolean JNICALL
+JVM_SupportsCX8(void);
+
+/*
+ * com.sun.dtrace.jsdt support
+ */
+
+#define JVM_TRACING_DTRACE_VERSION 1
+
+/*
+ * Structure to pass one probe description to JVM
+ */
+typedef struct {
+ jmethodID method;
+ jstring function;
+ jstring name;
+ void* reserved[4]; // for future use
+} JVM_DTraceProbe;
+
+/**
+ * Encapsulates the stability ratings for a DTrace provider field
+ */
+typedef struct {
+ jint nameStability;
+ jint dataStability;
+ jint dependencyClass;
+} JVM_DTraceInterfaceAttributes;
+
+/*
+ * Structure to pass one provider description to JVM
+ */
+typedef struct {
+ jstring name;
+ JVM_DTraceProbe* probes;
+ jint probe_count;
+ JVM_DTraceInterfaceAttributes providerAttributes;
+ JVM_DTraceInterfaceAttributes moduleAttributes;
+ JVM_DTraceInterfaceAttributes functionAttributes;
+ JVM_DTraceInterfaceAttributes nameAttributes;
+ JVM_DTraceInterfaceAttributes argsAttributes;
+ void* reserved[4]; // for future use
+} JVM_DTraceProvider;
+
+/*
+ * Get the version number the JVM was built with
+ */
+JNIEXPORT jint JNICALL
+JVM_DTraceGetVersion(JNIEnv* env);
+
+/*
+ * Register new probe with given signature, return global handle
+ *
+ * The version passed in is the version that the library code was
+ * built with.
+ */
+JNIEXPORT jlong JNICALL
+JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name,
+ jint providers_count, JVM_DTraceProvider* providers);
+
+/*
+ * Check JSDT probe
+ */
+JNIEXPORT jboolean JNICALL
+JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method);
+
+/*
+ * Destroy custom DOF
+ */
+JNIEXPORT void JNICALL
+JVM_DTraceDispose(JNIEnv* env, jlong activation_handle);
+
+/*
+ * Check to see if DTrace is supported by OS
+ */
+JNIEXPORT jboolean JNICALL
+JVM_DTraceIsSupported(JNIEnv* env);
+
+/*************************************************************************
+ PART 2: Support for the Verifier and Class File Format Checker
+ ************************************************************************/
+/*
+ * Return the class name in UTF format. The result is valid
+ * until JVM_ReleaseUTf is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetClassNameUTF(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the constant pool types in the buffer provided by "types."
+ */
+JNIEXPORT void JNICALL
+JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types);
+
+/*
+ * Returns the number of Constant Pool entries.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the number of *declared* fields or methods.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetClassFieldsCount(JNIEnv *env, jclass cb);
+
+JNIEXPORT jint JNICALL
+JVM_GetClassMethodsCount(JNIEnv *env, jclass cb);
+
+/*
+ * Returns the CP indexes of exceptions raised by a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
+ unsigned short *exceptions);
+/*
+ * Returns the number of exceptions raised by a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index);
+
+/*
+ * Returns the byte code sequence of a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
+ unsigned char *code);
+
+/*
+ * Returns the length of the byte code sequence of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index);
+
+/*
+ * A structure used to a capture exception table entry in a Java method.
+ */
+typedef struct {
+ jint start_pc;
+ jint end_pc;
+ jint handler_pc;
+ jint catchType;
+} JVM_ExceptionTableEntryType;
+
+/*
+ * Returns the exception table entry at entry_index of a given method.
+ * Places the result in the given buffer.
+ *
+ * The method is identified by method_index.
+ */
+JNIEXPORT void JNICALL
+JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
+ jint entry_index,
+ JVM_ExceptionTableEntryType *entry);
+
+/*
+ * Returns the length of the exception table of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the modifiers of a given field.
+ * The field is identified by field_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the modifiers of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the number of local variables of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the number of arguments (including this pointer) of a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the maximum amount of stack (in words) used by a given method.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Is a given method a constructor.
+ * The method is identified by method_index.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
+
+/*
+ * Returns the name of a given method in UTF format.
+ * The result remains valid until JVM_ReleaseUTF is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of a given method in UTF format.
+ * The result remains valid until JVM_ReleaseUTF is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the name of the field refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the name of the method refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of the method refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the signature of the field refered to at a given constant pool
+ * index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The constant pool entry must refer to a CONSTANT_Fieldref.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the class name refered to at a given constant pool index.
+ *
+ * The constant pool entry must refer to CONSTANT_Methodref or
+ * CONSTANT_InterfaceMethodref.
+ *
+ * The result is in UTF format and remains valid until JVM_ReleaseUTF
+ * is called.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ */
+JNIEXPORT const char * JNICALL
+JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index);
+
+/*
+ * Returns the modifiers of a field in calledClass. The field is
+ * referred to in class cb at constant pool entry index.
+ *
+ * The caller must treat the string as a constant and not modify it
+ * in any way.
+ *
+ * Returns -1 if the field does not exist in calledClass.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
+
+/*
+ * Returns the modifiers of a method in calledClass. The method is
+ * referred to in class cb at constant pool entry index.
+ *
+ * Returns -1 if the method does not exist in calledClass.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
+
+/*
+ * Releases the UTF string obtained from the VM.
+ */
+JNIEXPORT void JNICALL
+JVM_ReleaseUTF(const char *utf);
+
+/*
+ * Compare if two classes are in the same package.
+ */
+JNIEXPORT jboolean JNICALL
+JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
+
+/* Get classfile constants */
+#include "classfile_constants.h"
+
+/*
+ * A function defined by the byte-code verifier and called by the VM.
+ * This is not a function implemented in the VM.
+ *
+ * Returns JNI_FALSE if verification fails. A detailed error message
+ * will be places in msg_buf, whose length is specified by buf_len.
+ */
+typedef jboolean (*verifier_fn_t)(JNIEnv *env,
+ jclass cb,
+ char * msg_buf,
+ jint buf_len);
+
+
+/*
+ * Support for a VM-independent class format checker.
+ */
+typedef struct {
+ unsigned long code; /* byte code */
+ unsigned long excs; /* exceptions */
+ unsigned long etab; /* catch table */
+ unsigned long lnum; /* line number */
+ unsigned long lvar; /* local vars */
+} method_size_info;
+
+typedef struct {
+ unsigned int constants; /* constant pool */
+ unsigned int fields;
+ unsigned int methods;
+ unsigned int interfaces;
+ unsigned int fields2; /* number of static 2-word fields */
+ unsigned int innerclasses; /* # of records in InnerClasses attr */
+
+ method_size_info clinit; /* memory used in clinit */
+ method_size_info main; /* used everywhere else */
+} class_size_info;
+
+/*
+ * Functions defined in libjava.so to perform string conversions.
+ *
+ */
+
+typedef jstring (*to_java_string_fn_t)(JNIEnv *env, char *str);
+
+typedef char *(*to_c_string_fn_t)(JNIEnv *env, jstring s, jboolean *b);
+
+/* This is the function defined in libjava.so that performs class
+ * format checks. This functions fills in size information about
+ * the class file and returns:
+ *
+ * 0: good
+ * -1: out of memory
+ * -2: bad format
+ * -3: unsupported version
+ * -4: bad class name
+ */
+
+typedef jint (*check_format_fn_t)(char *class_name,
+ unsigned char *data,
+ unsigned int data_size,
+ class_size_info *class_size,
+ char *message_buffer,
+ jint buffer_length,
+ jboolean measure_only,
+ jboolean check_relaxed);
+
+#define JVM_RECOGNIZED_CLASS_MODIFIERS (JVM_ACC_PUBLIC | \
+ JVM_ACC_FINAL | \
+ JVM_ACC_SUPER | \
+ JVM_ACC_INTERFACE | \
+ JVM_ACC_ABSTRACT | \
+ JVM_ACC_ANNOTATION | \
+ JVM_ACC_ENUM | \
+ JVM_ACC_SYNTHETIC)
+
+#define JVM_RECOGNIZED_FIELD_MODIFIERS (JVM_ACC_PUBLIC | \
+ JVM_ACC_PRIVATE | \
+ JVM_ACC_PROTECTED | \
+ JVM_ACC_STATIC | \
+ JVM_ACC_FINAL | \
+ JVM_ACC_VOLATILE | \
+ JVM_ACC_TRANSIENT | \
+ JVM_ACC_ENUM | \
+ JVM_ACC_SYNTHETIC)
+
+#define JVM_RECOGNIZED_METHOD_MODIFIERS (JVM_ACC_PUBLIC | \
+ JVM_ACC_PRIVATE | \
+ JVM_ACC_PROTECTED | \
+ JVM_ACC_STATIC | \
+ JVM_ACC_FINAL | \
+ JVM_ACC_SYNCHRONIZED | \
+ JVM_ACC_BRIDGE | \
+ JVM_ACC_VARARGS | \
+ JVM_ACC_NATIVE | \
+ JVM_ACC_ABSTRACT | \
+ JVM_ACC_STRICT | \
+ JVM_ACC_SYNTHETIC)
+
+/*
+ * This is the function defined in libjava.so to perform path
+ * canonicalization. VM call this function before opening jar files
+ * to load system classes.
+ *
+ */
+
+typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
+
+/*************************************************************************
+ PART 3: I/O and Network Support
+ ************************************************************************/
+
+/* Note that the JVM IO functions are expected to return JVM_IO_ERR
+ * when there is any kind of error. The caller can then use the
+ * platform specific support (e.g., errno) to get the detailed
+ * error info. The JVM_GetLastErrorString procedure may also be used
+ * to obtain a descriptive error string.
+ */
+#define JVM_IO_ERR (-1)
+
+/* For interruptible IO. Returning JVM_IO_INTR indicates that an IO
+ * operation has been disrupted by Thread.interrupt. There are a
+ * number of technical difficulties related to interruptible IO that
+ * need to be solved. For example, most existing programs do not handle
+ * InterruptedIOExceptions specially, they simply treat those as any
+ * IOExceptions, which typically indicate fatal errors.
+ *
+ * There are also two modes of operation for interruptible IO. In the
+ * resumption mode, an interrupted IO operation is guaranteed not to
+ * have any side-effects, and can be restarted. In the termination mode,
+ * an interrupted IO operation corrupts the underlying IO stream, so
+ * that the only reasonable operation on an interrupted stream is to
+ * close that stream. The resumption mode seems to be impossible to
+ * implement on Win32 and Solaris. Implementing the termination mode is
+ * easier, but it's not clear that's the right semantics.
+ *
+ * Interruptible IO is not supported on Win32.It can be enabled/disabled
+ * using a compile-time flag on Solaris. Third-party JVM ports do not
+ * need to implement interruptible IO.
+ */
+#define JVM_IO_INTR (-2)
+
+/* Write a string into the given buffer, in the platform's local encoding,
+ * that describes the most recent system-level error to occur in this thread.
+ * Return the length of the string or zero if no error occurred.
+ */
+JNIEXPORT jint JNICALL
+JVM_GetLastErrorString(char *buf, int len);
+
+/*
+ * Convert a pathname into native format. This function does syntactic
+ * cleanup, such as removing redundant separator characters. It modifies
+ * the given pathname string in place.
+ */
+JNIEXPORT char * JNICALL
+JVM_NativePath(char *);
+
+/*
+ * JVM I/O error codes
+ */
+#define JVM_EEXIST -100
+
+/*
+ * Open a file descriptor. This function returns a negative error code
+ * on error, and a non-negative integer that is the file descriptor on
+ * success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Open(const char *fname, jint flags, jint mode);
+
+/*
+ * Close a file descriptor. This function returns -1 on error, and 0
+ * on success.
+ *
+ * fd the file descriptor to close.
+ */
+JNIEXPORT jint JNICALL
+JVM_Close(jint fd);
+
+/*
+ * Read data from a file decriptor into a char array.
+ *
+ * fd the file descriptor to read from.
+ * buf the buffer where to put the read data.
+ * nbytes the number of bytes to read.
+ *
+ * This function returns -1 on error, and 0 on success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Read(jint fd, char *buf, jint nbytes);
+
+/*
+ * Write data from a char array to a file decriptor.
+ *
+ * fd the file descriptor to read from.
+ * buf the buffer from which to fetch the data.
+ * nbytes the number of bytes to write.
+ *
+ * This function returns -1 on error, and 0 on success.
+ */
+JNIEXPORT jint JNICALL
+JVM_Write(jint fd, char *buf, jint nbytes);
+
+/*
+ * Returns the number of bytes available for reading from a given file
+ * descriptor
+ */
+JNIEXPORT jint JNICALL
+JVM_Available(jint fd, jlong *pbytes);
+
+/*
+ * Move the file descriptor pointer from whence by offset.
+ *
+ * fd the file descriptor to move.
+ * offset the number of bytes to move it by.
+ * whence the start from where to move it.
+ *
+ * This function returns the resulting pointer location.
+ */
+JNIEXPORT jlong JNICALL
+JVM_Lseek(jint fd, jlong offset, jint whence);
+
+/*
+ * Set the length of the file associated with the given descriptor to the given
+ * length. If the new length is longer than the current length then the file
+ * is extended; the contents of the extended portion are not defined. The
+ * value of the file pointer is undefined after this procedure returns.
+ */
+JNIEXPORT jint JNICALL
+JVM_SetLength(jint fd, jlong length);
+
+/*
+ * Synchronize the file descriptor's in memory state with that of the
+ * physical device. Return of -1 is an error, 0 is OK.
+ */
+JNIEXPORT jint JNICALL
+JVM_Sync(jint fd);
+
+/*
+ * Networking library support
+ */
+
+JNIEXPORT jint JNICALL
+JVM_InitializeSocketLibrary(void);
+
+struct sockaddr;
+
+JNIEXPORT jint JNICALL
+JVM_Socket(jint domain, jint type, jint protocol);
+
+JNIEXPORT jint JNICALL
+JVM_SocketClose(jint fd);
+
+JNIEXPORT jint JNICALL
+JVM_SocketShutdown(jint fd, jint howto);
+
+JNIEXPORT jint JNICALL
+JVM_Recv(jint fd, char *buf, jint nBytes, jint flags);
+
+JNIEXPORT jint JNICALL
+JVM_Send(jint fd, char *buf, jint nBytes, jint flags);
+
+JNIEXPORT jint JNICALL
+JVM_Timeout(int fd, long timeout);
+
+JNIEXPORT jint JNICALL
+JVM_Listen(jint fd, jint count);
+
+JNIEXPORT jint JNICALL
+JVM_Connect(jint fd, struct sockaddr *him, jint len);
+
+JNIEXPORT jint JNICALL
+JVM_Bind(jint fd, struct sockaddr *him, jint len);
+
+JNIEXPORT jint JNICALL
+JVM_Accept(jint fd, struct sockaddr *him, jint *len);
+
+JNIEXPORT jint JNICALL
+JVM_RecvFrom(jint fd, char *buf, int nBytes,
+ int flags, struct sockaddr *from, int *fromlen);
+
+JNIEXPORT jint JNICALL
+JVM_SendTo(jint fd, char *buf, int len,
+ int flags, struct sockaddr *to, int tolen);
+
+JNIEXPORT jint JNICALL
+JVM_SocketAvailable(jint fd, jint *result);
+
+
+JNIEXPORT jint JNICALL
+JVM_GetSockName(jint fd, struct sockaddr *him, int *len);
+
+JNIEXPORT jint JNICALL
+JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen);
+
+JNIEXPORT jint JNICALL
+JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen);
+
+JNIEXPORT int JNICALL
+JVM_GetHostName(char* name, int namelen);
+
+/*
+ * The standard printing functions supported by the Java VM. (Should they
+ * be renamed to JVM_* in the future?
+ */
+
+/*
+ * BE CAREFUL! The following functions do not implement the
+ * full feature set of standard C printf formats.
+ */
+int
+jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
+
+int
+jio_snprintf(char *str, size_t count, const char *fmt, ...);
+
+int
+jio_fprintf(FILE *, const char *fmt, ...);
+
+int
+jio_vfprintf(FILE *, const char *fmt, va_list args);
+
+
+JNIEXPORT void * JNICALL
+JVM_RawMonitorCreate(void);
+
+JNIEXPORT void JNICALL
+JVM_RawMonitorDestroy(void *mon);
+
+JNIEXPORT jint JNICALL
+JVM_RawMonitorEnter(void *mon);
+
+JNIEXPORT void JNICALL
+JVM_RawMonitorExit(void *mon);
+
+/*
+ * java.lang.management support
+ */
+JNIEXPORT void* JNICALL
+JVM_GetManagement(jint version);
+
+/*
+ * com.sun.tools.attach.VirtualMachine support
+ *
+ * Initialize the agent properties with the properties maintained in the VM.
+ */
+JNIEXPORT jobject JNICALL
+JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
+
+/* Generics reflection support.
+ *
+ * Returns information about the given class's EnclosingMethod
+ * attribute, if present, or null if the class had no enclosing
+ * method.
+ *
+ * If non-null, the returned array contains three elements. Element 0
+ * is the java.lang.Class of which the enclosing method is a member,
+ * and elements 1 and 2 are the java.lang.Strings for the enclosing
+ * method's name and descriptor, respectively.
+ */
+JNIEXPORT jobjectArray JNICALL
+JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
+
+/*
+ * Java thread state support
+ */
+enum {
+ JAVA_THREAD_STATE_NEW = 0,
+ JAVA_THREAD_STATE_RUNNABLE = 1,
+ JAVA_THREAD_STATE_BLOCKED = 2,
+ JAVA_THREAD_STATE_WAITING = 3,
+ JAVA_THREAD_STATE_TIMED_WAITING = 4,
+ JAVA_THREAD_STATE_TERMINATED = 5,
+ JAVA_THREAD_STATE_COUNT = 6
+};
+
+/*
+ * Returns an array of the threadStatus values representing the
+ * given Java thread state. Returns NULL if the VM version is
+ * incompatible with the JDK or doesn't support the given
+ * Java thread state.
+ */
+JNIEXPORT jintArray JNICALL
+JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState);
+
+/*
+ * Returns an array of the substate names representing the
+ * given Java thread state. Returns NULL if the VM version is
+ * incompatible with the JDK or the VM doesn't support
+ * the given Java thread state.
+ * values must be the jintArray returned from JVM_GetThreadStateValues
+ * and javaThreadState.
+ */
+JNIEXPORT jobjectArray JNICALL
+JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values);
+
+/* =========================================================================
+ * The following defines a private JVM interface that the JDK can query
+ * for the JVM version and capabilities. sun.misc.Version defines
+ * the methods for getting the VM version and its capabilities.
+ *
+ * When a new bit is added, the following should be updated to provide
+ * access to the new capability:
+ * HS: JVM_GetVersionInfo and Abstract_VM_Version class
+ * SDK: Version class
+ *
+ * Similary, a private JDK interface JDK_GetVersionInfo0 is defined for
+ * JVM to query for the JDK version and capabilities.
+ *
+ * When a new bit is added, the following should be updated to provide
+ * access to the new capability:
+ * HS: JDK_Version class
+ * SDK: JDK_GetVersionInfo0
+ *
+ * ==========================================================================
+ */
+typedef struct {
+ /* Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx */
+ unsigned int jvm_version; /* Consists of major, minor, micro (n.n.n) */
+ /* and build number (xx) */
+ unsigned int update_version : 8; /* Update release version (uu) */
+ unsigned int special_update_version : 8; /* Special update release version (c)*/
+ unsigned int reserved1 : 16;
+ unsigned int reserved2;
+
+ /* The following bits represents JVM supports that JDK has dependency on.
+ * JDK can use these bits to determine which JVM version
+ * and support it has to maintain runtime compatibility.
+ *
+ * When a new bit is added in a minor or update release, make sure
+ * the new bit is also added in the main/baseline.
+ */
+ unsigned int is_attach_supported : 1;
+ unsigned int is_kernel_jvm : 1;
+ unsigned int : 30;
+ unsigned int : 32;
+ unsigned int : 32;
+} jvm_version_info;
+
+#define JVM_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
+#define JVM_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
+#define JVM_VERSION_MICRO(version) ((version & 0x0000FF00) >> 8)
+
+/* Build number is available only for RE builds.
+ * It will be zero for internal builds.
+ */
+#define JVM_VERSION_BUILD(version) ((version & 0x000000FF))
+
+JNIEXPORT void JNICALL
+JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size);
+
+typedef struct {
+ // Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx
+ unsigned int jdk_version; /* Consists of major, minor, micro (n.n.n) */
+ /* and build number (xx) */
+ unsigned int update_version : 8; /* Update release version (uu) */
+ unsigned int special_update_version : 8; /* Special update release version (c)*/
+ unsigned int reserved1 : 16;
+ unsigned int reserved2;
+
+ /* The following bits represents new JDK supports that VM has dependency on.
+ * VM implementation can use these bits to determine which JDK version
+ * and support it has to maintain runtime compatibility.
+ *
+ * When a new bit is added in a minor or update release, make sure
+ * the new bit is also added in the main/baseline.
+ */
+ unsigned int thread_park_blocker : 1;
+ unsigned int post_vm_init_hook_enabled : 1;
+ unsigned int : 30;
+ unsigned int : 32;
+ unsigned int : 32;
+} jdk_version_info;
+
+#define JDK_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
+#define JDK_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
+#define JDK_VERSION_MICRO(version) ((version & 0x0000FF00) >> 8)
+
+/* Build number is available only for RE build (i.e. JDK_BUILD_NUMBER is set to bNN)
+ * It will be zero for internal builds.
+ */
+#define JDK_VERSION_BUILD(version) ((version & 0x000000FF))
+
+/*
+ * This is the function JDK_GetVersionInfo0 defined in libjava.so
+ * that is dynamically looked up by JVM.
+ */
+typedef void (*jdk_version_info_fn_t)(jdk_version_info* info, size_t info_size);
+
+/*
+ * This structure is used by the launcher to get the default thread
+ * stack size from the VM using JNI_GetDefaultJavaVMInitArgs() with a
+ * version of 1.1. As it is not supported otherwise, it has been removed
+ * from jni.h
+ */
+typedef struct JDK1_1InitArgs {
+ jint version;
+
+ char **properties;
+ jint checkSource;
+ jint nativeStackSize;
+ jint javaStackSize;
+ jint minHeapSize;
+ jint maxHeapSize;
+ jint verifyMode;
+ char *classpath;
+
+ jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
+ void (JNICALL *exit)(jint code);
+ void (JNICALL *abort)(void);
+
+ jint enableClassGC;
+ jint enableVerboseGC;
+ jint disableAsyncGC;
+ jint verbose;
+ jboolean debugging;
+ jint debugPort;
+} JDK1_1InitArgs;
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+
+#endif /* __cplusplus */
+
+#endif /* !_JAVASOFT_JVM_H_ */
diff --git a/ojluni/src/main/native/jvm_md.h b/ojluni/src/main/native/jvm_md.h
new file mode 100755
index 0000000..390e89c
--- /dev/null
+++ b/ojluni/src/main/native/jvm_md.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _JAVASOFT_JVM_MD_H_
+#define _JAVASOFT_JVM_MD_H_
+
+/*
+ * This file is currently collecting system-specific dregs for the
+ * JNI conversion, which should be sorted out later.
+ */
+
+#include <dirent.h> /* For DIR */
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <unistd.h> /* For F_OK, R_OK, W_OK */
+#include <stddef.h> /* For ptrdiff_t */
+#include <stdint.h> /* For uintptr_t */
+
+#define JNI_ONLOAD_SYMBOLS {"JNI_OnLoad"}
+#define JNI_ONUNLOAD_SYMBOLS {"JNI_OnUnload"}
+
+#define JNI_LIB_PREFIX "lib"
+#ifdef __APPLE__
+#define JNI_LIB_SUFFIX ".dylib"
+#define VERSIONED_JNI_LIB_NAME(NAME, VERSION) JNI_LIB_PREFIX NAME "." VERSION JNI_LIB_SUFFIX
+#else
+#define JNI_LIB_SUFFIX ".so"
+#define VERSIONED_JNI_LIB_NAME(NAME, VERSION) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX "." VERSION
+#endif
+#define JNI_LIB_NAME(NAME) JNI_LIB_PREFIX NAME JNI_LIB_SUFFIX
+
+#define JVM_MAXPATHLEN MAXPATHLEN
+
+#define JVM_R_OK R_OK
+#define JVM_W_OK W_OK
+#define JVM_X_OK X_OK
+#define JVM_F_OK F_OK
+
+/*
+ * File I/O
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/signal.h>
+
+/* O Flags */
+
+#define JVM_O_RDONLY O_RDONLY
+#define JVM_O_WRONLY O_WRONLY
+#define JVM_O_RDWR O_RDWR
+#define JVM_O_O_APPEND O_APPEND
+#define JVM_O_EXCL O_EXCL
+#define JVM_O_CREAT O_CREAT
+#define JVM_O_DELETE 0x10000
+
+/* Signals */
+
+#define JVM_SIGINT SIGINT
+#define JVM_SIGTERM SIGTERM
+
+
+#endif /* !_JAVASOFT_JVM_MD_H_ */
diff --git a/ojluni/src/main/native/linux_close.c b/ojluni/src/main/native/linux_close.c
new file mode 100755
index 0000000..5665e85
--- /dev/null
+++ b/ojluni/src/main/native/linux_close.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/poll.h>
+
+/*
+ * Stack allocated by thread when doing blocking operation
+ */
+typedef struct threadEntry {
+ pthread_t thr; /* this thread */
+ struct threadEntry *next; /* next thread */
+ int intr; /* interrupted */
+} threadEntry_t;
+
+/*
+ * Heap allocated during initialized - one entry per fd
+ */
+typedef struct {
+ pthread_mutex_t lock; /* fd lock */
+ threadEntry_t *threads; /* threads blocked on fd */
+} fdEntry_t;
+
+/*
+ * Signal to unblock thread
+ */
+static int sigWakeup = (__SIGRTMAX - 2);
+
+/*
+ * The fd table and the number of file descriptors
+ */
+static fdEntry_t *fdTable;
+static int fdCount;
+
+/*
+ * Null signal handler
+ */
+static void sig_wakeup(int sig) {
+}
+
+/*
+ * Initialization routine (executed when library is loaded)
+ * Allocate fd tables and sets up signal handler.
+ */
+static void __attribute((constructor)) init() {
+ struct rlimit nbr_files;
+ sigset_t sigset;
+ struct sigaction sa;
+
+ /*
+ * Allocate table based on the maximum number of
+ * file descriptors.
+ */
+ getrlimit(RLIMIT_NOFILE, &nbr_files);
+ fdCount = nbr_files.rlim_max;
+ fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t));
+ if (fdTable == NULL) {
+ fprintf(stderr, "library initialization failed - "
+ "unable to allocate file descriptor table - out of memory");
+ abort();
+ }
+
+ /*
+ * Setup the signal handler
+ */
+ sa.sa_handler = sig_wakeup;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(sigWakeup, &sa, NULL);
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, sigWakeup);
+ sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+}
+
+/*
+ * Return the fd table for this fd or NULL is fd out
+ * of range.
+ */
+static inline fdEntry_t *getFdEntry(int fd)
+{
+ if (fd < 0 || fd >= fdCount) {
+ return NULL;
+ }
+ return &fdTable[fd];
+}
+
+/*
+ * Start a blocking operation :-
+ * Insert thread onto thread list for the fd.
+ */
+static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ self->thr = pthread_self();
+ self->intr = 0;
+
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ self->next = fdEntry->threads;
+ fdEntry->threads = self;
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+}
+
+/*
+ * End a blocking operation :-
+ * Remove thread from thread list for the fd
+ * If fd has been interrupted then set errno to EBADF
+ */
+static inline void endOp
+ (fdEntry_t *fdEntry, threadEntry_t *self)
+{
+ int orig_errno = errno;
+ pthread_mutex_lock(&(fdEntry->lock));
+ {
+ threadEntry_t *curr, *prev=NULL;
+ curr = fdEntry->threads;
+ while (curr != NULL) {
+ if (curr == self) {
+ if (curr->intr) {
+ orig_errno = EBADF;
+ }
+ if (prev == NULL) {
+ fdEntry->threads = curr->next;
+ } else {
+ prev->next = curr->next;
+ }
+ break;
+ }
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+}
+
+/*
+ * Close or dup2 a file descriptor ensuring that all threads blocked on
+ * the file descriptor are notified via a wakeup signal.
+ *
+ * fd1 < 0 => close(fd2)
+ * fd1 >= 0 => dup2(fd1, fd2)
+ *
+ * Returns -1 with errno set if operation fails.
+ */
+static int closefd(int fd1, int fd2) {
+ int rv, orig_errno;
+ fdEntry_t *fdEntry = getFdEntry(fd2);
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Lock the fd to hold-off additional I/O on this fd.
+ */
+ pthread_mutex_lock(&(fdEntry->lock));
+
+ {
+ /*
+ * Send a wakeup signal to all threads blocked on this
+ * file descriptor.
+ */
+ threadEntry_t *curr = fdEntry->threads;
+ while (curr != NULL) {
+ curr->intr = 1;
+ pthread_kill( curr->thr, sigWakeup );
+ curr = curr->next;
+ }
+
+ /*
+ * And close/dup the file descriptor
+ * (restart if interrupted by signal)
+ */
+ do {
+ if (fd1 < 0) {
+ rv = close(fd2);
+ } else {
+ rv = dup2(fd1, fd2);
+ }
+ } while (rv == -1 && errno == EINTR);
+
+ }
+
+ /*
+ * Unlock without destroying errno
+ */
+ orig_errno = errno;
+ pthread_mutex_unlock(&(fdEntry->lock));
+ errno = orig_errno;
+
+ return rv;
+}
+
+/*
+ * Wrapper for dup2 - same semantics as dup2 system call except
+ * that any threads blocked in an I/O system call on fd2 will be
+ * preempted and return -1/EBADF;
+ */
+int NET_Dup2(int fd, int fd2) {
+ if (fd < 0) {
+ errno = EBADF;
+ return -1;
+ }
+ return closefd(fd, fd2);
+}
+
+/*
+ * Wrapper for close - same semantics as close system call
+ * except that any threads blocked in an I/O on fd will be
+ * preempted and the I/O system call will return -1/EBADF.
+ */
+int NET_SocketClose(int fd) {
+ return closefd(-1, fd);
+}
+
+/************** Basic I/O operations here ***************/
+
+/*
+ * Macro to perform a blocking IO operation. Restarts
+ * automatically if interrupted by signal (other than
+ * our wakeup signal)
+ */
+#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \
+ int ret; \
+ threadEntry_t self; \
+ fdEntry_t *fdEntry = getFdEntry(FD); \
+ if (fdEntry == NULL) { \
+ errno = EBADF; \
+ return -1; \
+ } \
+ do { \
+ startOp(fdEntry, &self); \
+ ret = FUNC; \
+ endOp(fdEntry, &self); \
+ } while (ret == -1 && errno == EINTR); \
+ return ret; \
+}
+
+int NET_Read(int s, void* buf, size_t len) {
+ BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
+}
+
+int NET_ReadV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
+}
+
+int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen) {
+ socklen_t socklen = *fromlen;
+ BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) );
+ *fromlen = socklen;
+}
+
+int NET_Send(int s, void *msg, int len, unsigned int flags) {
+ BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) );
+}
+
+int NET_WriteV(int s, const struct iovec * vector, int count) {
+ BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) );
+}
+
+int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen) {
+ BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) );
+}
+
+int NET_Accept(int s, struct sockaddr *addr, int *addrlen) {
+ socklen_t socklen = *addrlen;
+ BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) );
+ *addrlen = socklen;
+}
+
+int NET_Connect(int s, struct sockaddr *addr, int addrlen) {
+ BLOCKING_IO_RETURN_INT( s, connect(s, addr, addrlen) );
+}
+
+#ifndef USE_SELECT
+int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
+ BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) );
+}
+#else
+int NET_Select(int s, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout) {
+ BLOCKING_IO_RETURN_INT( s-1,
+ select(s, readfds, writefds, exceptfds, timeout) );
+}
+#endif
+
+/*
+ * Wrapper for poll(s, timeout).
+ * Auto restarts with adjusted timeout if interrupted by
+ * signal other than our wakeup signal.
+ */
+int NET_Timeout(int s, long timeout) {
+ long prevtime = 0, newtime;
+ struct timeval t;
+ fdEntry_t *fdEntry = getFdEntry(s);
+
+ /*
+ * Check that fd hasn't been closed.
+ */
+ if (fdEntry == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ /*
+ * Pick up current time as may need to adjust timeout
+ */
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ }
+
+ for(;;) {
+ struct pollfd pfd;
+ int rv;
+ threadEntry_t self;
+
+ /*
+ * Poll the fd. If interrupted by our wakeup signal
+ * errno will be set to EBADF.
+ */
+ pfd.fd = s;
+ pfd.events = POLLIN | POLLERR;
+
+ startOp(fdEntry, &self);
+ rv = poll(&pfd, 1, timeout);
+ endOp(fdEntry, &self);
+
+ /*
+ * If interrupted then adjust timeout. If timeout
+ * has expired return 0 (indicating timeout expired).
+ */
+ if (rv < 0 && errno == EINTR) {
+ if (timeout > 0) {
+ gettimeofday(&t, NULL);
+ newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
+ timeout -= newtime - prevtime;
+ if (timeout <= 0) {
+ return 0;
+ }
+ prevtime = newtime;
+ }
+ } else {
+ return rv;
+ }
+
+ }
+}
diff --git a/ojluni/src/main/native/net_util.c b/ojluni/src/main/native/net_util.c
new file mode 100755
index 0000000..2f99a34
--- /dev/null
+++ b/ojluni/src/main/native/net_util.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+int IPv6_supported() ;
+
+static int IPv6_available;
+
+JNIEXPORT jint JNICALL ipv6_available()
+{
+ return IPv6_available ;
+}
+
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+ jclass iCls;
+ jmethodID mid;
+ jstring s;
+ jint preferIPv4Stack;
+
+ if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2) == JNI_OK) {
+ if (JVM_InitializeSocketLibrary() < 0) {
+ JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError",
+ "failed to initialize net library.");
+ return JNI_VERSION_1_2;
+ }
+ }
+ iCls = (*env)->FindClass(env, "java/lang/Boolean");
+ CHECK_NULL_RETURN(iCls, JNI_VERSION_1_2);
+ mid = (*env)->GetStaticMethodID(env, iCls, "getBoolean", "(Ljava/lang/String;)Z");
+ CHECK_NULL_RETURN(mid, JNI_VERSION_1_2);
+ s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack");
+ CHECK_NULL_RETURN(s, JNI_VERSION_1_2);
+ preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s);
+
+ /*
+ Since we have initialized and loaded the Socket library we will
+ check now to whether we have IPv6 on this platform and if the
+ supporting socket APIs are available
+ */
+ IPv6_available = IPv6_supported() & (!preferIPv4Stack);
+ initLocalAddrTable ();
+ parseExclusiveBindProperty(env);
+
+ return JNI_VERSION_1_2;
+}
+
+static int initialized = 0;
+
+static void initInetAddrs(JNIEnv *env) {
+ if (!initialized) {
+ Java_java_net_InetAddress_init(env, 0);
+ Java_java_net_Inet4Address_init(env, 0);
+ Java_java_net_Inet6Address_init(env, 0);
+ initialized = 1;
+ }
+}
+
+/* The address, and family fields used to be in InetAddress
+ * but are now in an implementation object. So, there is an extra
+ * level of indirection to access them now.
+ */
+
+extern jclass iac_class;
+extern jfieldID ia_holderID;
+extern jfieldID iac_addressID;
+extern jfieldID iac_familyID;
+
+void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
+ jobject holder;
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetIntField(env, holder, iac_addressID, address);
+}
+
+void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
+ jobject holder;
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetIntField(env, holder, iac_familyID, family);
+}
+
+void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
+ jobject holder;
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ (*env)->SetObjectField(env, holder, iac_hostNameID, host);
+}
+
+int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetIntField(env, holder, iac_addressID);
+}
+
+int getInetAddress_family(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetIntField(env, holder, iac_familyID);
+}
+
+jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
+ jobject holder;
+ initInetAddrs(env);
+ holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
+ return (*env)->GetObjectField(env, holder, iac_hostNameID);
+}
+
+JNIEXPORT jobject JNICALL
+NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
+ jobject iaObj;
+ initInetAddrs(env);
+#ifdef AF_INET6
+ if (him->sa_family == AF_INET6) {
+ jbyteArray ipaddress;
+#ifdef WIN32
+ struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+#else
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+#endif
+ jbyte *caddr = (jbyte *)&(him6->sin6_addr);
+ if (NET_IsIPv4Mapped(caddr)) {
+ int address;
+ static jclass inet4Cls = 0;
+ if (inet4Cls == 0) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL_RETURN(c, NULL);
+ inet4Cls = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(inet4Cls, NULL);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
+ CHECK_NULL_RETURN(iaObj, NULL);
+ address = NET_IPv4MappedToIPv4(caddr);
+ setInetAddress_addr(env, iaObj, address);
+ setInetAddress_family(env, iaObj, IPv4);
+ } else {
+ static jclass inet6Cls = 0;
+ jint scope;
+ if (inet6Cls == 0) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet6Address");
+ CHECK_NULL_RETURN(c, NULL);
+ inet6Cls = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(inet6Cls, NULL);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID);
+ CHECK_NULL_RETURN(iaObj, NULL);
+ ipaddress = (*env)->NewByteArray(env, 16);
+ CHECK_NULL_RETURN(ipaddress, NULL);
+ (*env)->SetByteArrayRegion(env, ipaddress, 0, 16,
+ (jbyte *)&(him6->sin6_addr));
+
+ (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
+
+ setInetAddress_family(env, iaObj, IPv6);
+ scope = getScopeID(him);
+ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
+ if (scope > 0)
+ (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
+ }
+ *port = ntohs(him6->sin6_port);
+ } else
+#endif /* AF_INET6 */
+ {
+ struct sockaddr_in *him4 = (struct sockaddr_in *)him;
+ static jclass inet4Cls = 0;
+
+ if (inet4Cls == 0) {
+ jclass c = (*env)->FindClass(env, "java/net/Inet4Address");
+ CHECK_NULL_RETURN(c, NULL);
+ inet4Cls = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL_RETURN(inet4Cls, NULL);
+ (*env)->DeleteLocalRef(env, c);
+ }
+ iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
+ CHECK_NULL_RETURN(iaObj, NULL);
+ setInetAddress_family(env, iaObj, IPv4);
+ setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
+ *port = ntohs(him4->sin_port);
+ }
+ return iaObj;
+}
+
+JNIEXPORT jint JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
+{
+ jint family = AF_INET;
+
+#ifdef AF_INET6
+ family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+ if (him->sa_family == AF_INET6) {
+#ifdef WIN32
+ struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+#else
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+#endif
+ jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
+ if (NET_IsIPv4Mapped(caddrNew)) {
+ int addrNew;
+ int addrCur;
+ if (family == AF_INET6) {
+ return JNI_FALSE;
+ }
+ addrNew = NET_IPv4MappedToIPv4(caddrNew);
+ addrCur = getInetAddress_addr(env, iaObj);
+ if (addrNew == addrCur) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+ } else {
+ jbyteArray ipaddress;
+ jbyte caddrCur[16];
+ int scope;
+
+ if (family == AF_INET) {
+ return JNI_FALSE;
+ }
+ ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
+ scope = (*env)->GetIntField(env, iaObj, ia6_scopeidID);
+ (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddrCur);
+ if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+ }
+ } else
+#endif /* AF_INET6 */
+ {
+ struct sockaddr_in *him4 = (struct sockaddr_in *)him;
+ int addrNew, addrCur;
+ if (family != AF_INET) {
+ return JNI_FALSE;
+ }
+ addrNew = ntohl(him4->sin_addr.s_addr);
+ addrCur = getInetAddress_addr(env, iaObj);
+ if (addrNew == addrCur) {
+ return JNI_TRUE;
+ } else {
+ return JNI_FALSE;
+ }
+ }
+}
+
+unsigned short
+in_cksum(unsigned short *addr, int len) {
+ int nleft = len;
+ int sum = 0;
+ unsigned short *w = addr;
+ unsigned short answer = 0;
+ while(nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ if (nleft == 1) {
+ *(unsigned char *) (&answer) = *(unsigned char *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+ return (answer);
+}
diff --git a/ojluni/src/main/native/net_util.h b/ojluni/src/main/native/net_util.h
new file mode 100755
index 0000000..604c83d
--- /dev/null
+++ b/ojluni/src/main/native/net_util.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NET_UTILS_H
+#define NET_UTILS_H
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util_md.h"
+
+/************************************************************************
+ * Macros and misc constants
+ */
+
+#define MAX_PACKET_LEN 65536
+
+#define IPv4 1
+#define IPv6 2
+
+#define NET_ERROR(env, ex, msg) \
+{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg) }
+
+#define CHECK_NULL(x) if ((x) == NULL) return;
+#define CHECK_NULL_RETURN(x, y) if ((x) == NULL) return y;
+
+/************************************************************************
+ * Cached field IDs
+ *
+ * The naming convention for field IDs is
+ * <class abbrv>_<fieldName>ID
+ * i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID.
+ */
+extern jclass ia_class;
+extern jfieldID iac_addressID;
+extern jfieldID iac_familyID;
+extern jfieldID iac_hostNameID;
+extern jfieldID ia_preferIPv6AddressID;
+
+extern void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address);
+extern void setInetAddress_family(JNIEnv *env, jobject iaObj, int family);
+extern void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject h);
+extern int getInetAddress_addr(JNIEnv *env, jobject iaObj);
+extern int getInetAddress_family(JNIEnv *env, jobject iaObj);
+extern jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj);
+
+extern jclass ia4_class;
+extern jmethodID ia4_ctrID;
+
+/* NetworkInterface fields */
+extern jclass ni_class;
+extern jfieldID ni_nameID;
+extern jfieldID ni_indexID;
+extern jfieldID ni_addrsID;
+extern jfieldID ni_descID;
+extern jmethodID ni_ctrID;
+
+/* PlainSocketImpl fields */
+extern jfieldID psi_timeoutID;
+extern jfieldID psi_fdID;
+extern jfieldID psi_addressID;
+extern jfieldID psi_portID;
+extern jfieldID psi_localportID;
+
+/* DatagramPacket fields */
+extern jfieldID dp_addressID;
+extern jfieldID dp_portID;
+extern jfieldID dp_bufID;
+extern jfieldID dp_offsetID;
+extern jfieldID dp_lengthID;
+extern jfieldID dp_bufLengthID;
+
+/* Inet6Address fields */
+extern jclass ia6_class;
+extern jfieldID ia6_ipaddressID;
+extern jfieldID ia6_scopeidID;
+extern jfieldID ia6_cachedscopeidID;
+extern jfieldID ia6_scopeidsetID;
+extern jfieldID ia6_scopeifnameID;
+extern jfieldID ia6_scopeifnamesetID;
+extern jmethodID ia6_ctrID;
+
+/************************************************************************
+ * Utilities
+ */
+JNIEXPORT void JNICALL Java_java_net_InetAddress_init(JNIEnv *env, jclass cls);
+JNIEXPORT void JNICALL Java_java_net_Inet4Address_init(JNIEnv *env, jclass cls);
+JNIEXPORT void JNICALL Java_java_net_Inet6Address_init(JNIEnv *env, jclass cls);
+JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls);
+
+JNIEXPORT void JNICALL NET_ThrowNew(JNIEnv *env, int errorNum, char *msg);
+int NET_GetError();
+
+void NET_ThrowCurrent(JNIEnv *env, char *msg);
+
+jfieldID NET_GetFileDescriptorID(JNIEnv *env);
+
+JNIEXPORT jint JNICALL ipv6_available();
+
+void
+NET_AllocSockaddr(struct sockaddr **him, int *len);
+
+JNIEXPORT int JNICALL
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress);
+
+JNIEXPORT jobject JNICALL
+NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
+
+void initLocalAddrTable ();
+void parseExclusiveBindProperty(JNIEnv *env);
+
+void
+NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+
+JNIEXPORT jint JNICALL
+NET_GetPortFromSockaddr(struct sockaddr *him);
+
+JNIEXPORT jint JNICALL
+NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
+
+int
+NET_IsIPv4Mapped(jbyte* caddr);
+
+int
+NET_IPv4MappedToIPv4(jbyte* caddr);
+
+int
+NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
+
+int
+NET_IsZeroAddr(jbyte* caddr);
+
+/* Socket operations
+ *
+ * These work just like the JVM_* procedures, except that they may do some
+ * platform-specific pre/post processing of the arguments and/or results.
+ */
+
+JNIEXPORT int JNICALL
+NET_GetSockOpt(int fd, int level, int opt, void *result, int *len);
+
+JNIEXPORT int JNICALL
+NET_SetSockOpt(int fd, int level, int opt, const void *arg, int len);
+
+JNIEXPORT int JNICALL
+NET_Bind(int fd, struct sockaddr *him, int len);
+
+JNIEXPORT int JNICALL
+NET_MapSocketOption(jint cmd, int *level, int *optname);
+
+JNIEXPORT int JNICALL
+NET_MapSocketOptionV6(jint cmd, int *level, int *optname);
+
+int getScopeID (struct sockaddr *);
+
+int cmpScopeID (unsigned int, struct sockaddr *);
+
+unsigned short in_cksum(unsigned short *addr, int len);
+#endif /* NET_UTILS_H */
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
new file mode 100755
index 0000000..84b3156
--- /dev/null
+++ b/ojluni/src/main/native/net_util_md.c
@@ -0,0 +1,1697 @@
+/*
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
+#include <netinet/in.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+#ifndef _ALLBSD_SOURCE
+#include <values.h>
+#else
+#include <limits.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#ifndef MAXINT
+#define MAXINT INT_MAX
+#endif
+#endif
+
+#ifdef __solaris__
+#include <sys/sockio.h>
+#include <stropts.h>
+#include <inet/nd.h>
+#endif
+
+#ifdef __linux__
+#include <arpa/inet.h>
+#include <net/route.h>
+#include <sys/utsname.h>
+
+#ifndef IPV6_FLOWINFO_SEND
+#define IPV6_FLOWINFO_SEND 33
+#endif
+
+#endif
+
+#include "jni_util.h"
+#include "jvm.h"
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+
+/* needed from libsocket on Solaris 8 */
+
+getaddrinfo_f getaddrinfo_ptr = NULL;
+freeaddrinfo_f freeaddrinfo_ptr = NULL;
+gai_strerror_f gai_strerror_ptr = NULL;
+getnameinfo_f getnameinfo_ptr = NULL;
+
+/*
+ * EXCLBIND socket options only on Solaris
+ */
+#if defined(__solaris__) && !defined(TCP_EXCLBIND)
+#define TCP_EXCLBIND 0x21
+#endif
+#if defined(__solaris__) && !defined(UDP_EXCLBIND)
+#define UDP_EXCLBIND 0x0101
+#endif
+
+void setDefaultScopeID(JNIEnv *env, struct sockaddr *him)
+{
+#ifdef MACOSX
+ static jclass ni_class = NULL;
+ static jfieldID ni_defaultIndexID;
+ if (ni_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ c = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(c);
+ ni_defaultIndexID = (*env)->GetStaticFieldID(
+ env, c, "defaultIndex", "I");
+ ni_class = c;
+ }
+ int defaultIndex;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)him;
+ if (sin6->sin6_family == AF_INET6 && (sin6->sin6_scope_id == 0)) {
+ defaultIndex = (*env)->GetStaticIntField(env, ni_class,
+ ni_defaultIndexID);
+ sin6->sin6_scope_id = defaultIndex;
+ }
+#endif
+}
+
+int getDefaultScopeID(JNIEnv *env) {
+ static jclass ni_class = NULL;
+ static jfieldID ni_defaultIndexID;
+ if (ni_class == NULL) {
+ jclass c = (*env)->FindClass(env, "java/net/NetworkInterface");
+ CHECK_NULL(c);
+ c = (*env)->NewGlobalRef(env, c);
+ CHECK_NULL(c);
+ ni_defaultIndexID = (*env)->GetStaticFieldID(
+ env, c, "defaultIndex", "I");
+ ni_class = c;
+ }
+ int defaultIndex = 0;
+ defaultIndex = (*env)->GetStaticIntField(env, ni_class,
+ ni_defaultIndexID);
+ return defaultIndex;
+}
+
+#ifdef __solaris__
+static int init_tcp_max_buf, init_udp_max_buf;
+static int tcp_max_buf;
+static int udp_max_buf;
+static int useExclBind = 0;
+
+/*
+ * Get the specified parameter from the specified driver. The value
+ * of the parameter is assumed to be an 'int'. If the parameter
+ * cannot be obtained return -1
+ */
+static int
+getParam(char *driver, char *param)
+{
+ struct strioctl stri;
+ char buf [64];
+ int s;
+ int value;
+
+ s = open (driver, O_RDWR);
+ if (s < 0) {
+ return -1;
+ }
+ strncpy (buf, param, sizeof(buf));
+ stri.ic_cmd = ND_GET;
+ stri.ic_timout = 0;
+ stri.ic_dp = buf;
+ stri.ic_len = sizeof(buf);
+ if (ioctl (s, I_STR, &stri) < 0) {
+ value = -1;
+ } else {
+ value = atoi(buf);
+ }
+ close (s);
+ return value;
+}
+
+/*
+ * Iterative way to find the max value that SO_SNDBUF or SO_RCVBUF
+ * for Solaris versions that do not support the ioctl() in getParam().
+ * Ugly, but only called once (for each sotype).
+ *
+ * As an optimisation, we make a guess using the default values for Solaris
+ * assuming they haven't been modified with ndd.
+ */
+
+#define MAX_TCP_GUESS 1024 * 1024
+#define MAX_UDP_GUESS 2 * 1024 * 1024
+
+#define FAIL_IF_NOT_ENOBUFS if (errno != ENOBUFS) return -1
+
+static int findMaxBuf(int fd, int opt, int sotype) {
+ int a = 0;
+ int b = MAXINT;
+ int initial_guess;
+ int limit = -1;
+
+ if (sotype == SOCK_DGRAM) {
+ initial_guess = MAX_UDP_GUESS;
+ } else {
+ initial_guess = MAX_TCP_GUESS;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess, sizeof(int)) == 0) {
+ initial_guess++;
+ if (setsockopt(fd, SOL_SOCKET, opt, &initial_guess,sizeof(int)) < 0) {
+ FAIL_IF_NOT_ENOBUFS;
+ return initial_guess - 1;
+ }
+ a = initial_guess;
+ } else {
+ FAIL_IF_NOT_ENOBUFS;
+ b = initial_guess - 1;
+ }
+ do {
+ int mid = a + (b-a)/2;
+ if (setsockopt(fd, SOL_SOCKET, opt, &mid, sizeof(int)) == 0) {
+ limit = mid;
+ a = mid + 1;
+ } else {
+ FAIL_IF_NOT_ENOBUFS;
+ b = mid - 1;
+ }
+ } while (b >= a);
+
+ return limit;
+}
+#endif
+
+#ifdef __linux__
+static int kernelV22 = 0;
+static int vinit = 0;
+
+int kernelIsV22 () {
+ if (!vinit) {
+ struct utsname sysinfo;
+ if (uname(&sysinfo) == 0) {
+ sysinfo.release[3] = '\0';
+ if (strcmp(sysinfo.release, "2.2") == 0) {
+ kernelV22 = JNI_TRUE;
+ }
+ }
+ vinit = 1;
+ }
+ return kernelV22;
+}
+
+static int kernelV24 = 0;
+static int vinit24 = 0;
+
+int kernelIsV24 () {
+ if (!vinit24) {
+ struct utsname sysinfo;
+ if (uname(&sysinfo) == 0) {
+ sysinfo.release[3] = '\0';
+ if (strcmp(sysinfo.release, "2.4") == 0) {
+ kernelV24 = JNI_TRUE;
+ }
+ }
+ vinit24 = 1;
+ }
+ return kernelV24;
+}
+
+int getScopeID (struct sockaddr *him) {
+ struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
+ if (kernelIsV22()) {
+ return 0;
+ }
+ return hext->sin6_scope_id;
+}
+
+int cmpScopeID (unsigned int scope, struct sockaddr *him) {
+ struct sockaddr_in6 *hext = (struct sockaddr_in6 *)him;
+ if (kernelIsV22()) {
+ return 1; /* scope is ignored for comparison in 2.2 kernel */
+ }
+ return hext->sin6_scope_id == scope;
+}
+
+#else
+
+int getScopeID (struct sockaddr *him) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+ return him6->sin6_scope_id;
+}
+
+int cmpScopeID (unsigned int scope, struct sockaddr *him) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+ return him6->sin6_scope_id == scope;
+}
+
+#endif
+
+
+void
+NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+ const char *defaultDetail) {
+ char errmsg[255];
+ sprintf(errmsg, "errno: %d, error: %s\n", errno, defaultDetail);
+ JNU_ThrowByNameWithLastError(env, name, errmsg);
+}
+
+void
+NET_ThrowCurrent(JNIEnv *env, char *msg) {
+ NET_ThrowNew(env, errno, msg);
+}
+
+void
+NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {
+ char fullMsg[512];
+ if (!msg) {
+ msg = "no further information";
+ }
+ switch(errorNumber) {
+ case EBADF:
+ jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
+ break;
+ case EINTR:
+ JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);
+ break;
+ default:
+ errno = errorNumber;
+ JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);
+ break;
+ }
+}
+
+
+jfieldID
+NET_GetFileDescriptorID(JNIEnv *env)
+{
+ jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");
+ CHECK_NULL_RETURN(cls, NULL);
+ return (*env)->GetFieldID(env, cls, "fd", "I");
+}
+
+#if defined(DONT_ENABLE_IPV6)
+jint IPv6_supported()
+{
+ return JNI_FALSE;
+}
+
+#else /* !DONT_ENABLE_IPV6 */
+
+jint IPv6_supported()
+{
+#ifndef AF_INET6
+ return JNI_FALSE;
+#endif
+
+#ifdef AF_INET6
+ int fd;
+ void *ipv6_fn;
+ SOCKADDR sa;
+ socklen_t sa_len = sizeof(sa);
+
+ fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;
+ if (fd < 0) {
+ /*
+ * TODO: We really cant tell since it may be an unrelated error
+ * for now we will assume that AF_INET6 is not available
+ */
+ return JNI_FALSE;
+ }
+
+ /*
+ * If fd 0 is a socket it means we've been launched from inetd or
+ * xinetd. If it's a socket then check the family - if it's an
+ * IPv4 socket then we need to disable IPv6.
+ */
+ if (getsockname(0, (struct sockaddr *)&sa, &sa_len) == 0) {
+ struct sockaddr *saP = (struct sockaddr *)&sa;
+ if (saP->sa_family != AF_INET6) {
+ return JNI_FALSE;
+ }
+ }
+
+ /**
+ * Linux - check if any interface has an IPv6 address.
+ * Don't need to parse the line - we just need an indication.
+ */
+#ifdef __linux__
+ {
+ FILE *fP = fopen("/proc/net/if_inet6", "r");
+ char buf[255];
+ char *bufP;
+
+ if (fP == NULL) {
+ close(fd);
+ return JNI_FALSE;
+ }
+ bufP = fgets(buf, sizeof(buf), fP);
+ fclose(fP);
+ if (bufP == NULL) {
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+#endif
+
+ /**
+ * On Solaris 8 it's possible to create INET6 sockets even
+ * though IPv6 is not enabled on all interfaces. Thus we
+ * query the number of IPv6 addresses to verify that IPv6
+ * has been configured on at least one interface.
+ *
+ * On Linux it doesn't matter - if IPv6 is built-in the
+ * kernel then IPv6 addresses will be bound automatically
+ * to all interfaces.
+ */
+#ifdef __solaris__
+
+#ifdef SIOCGLIFNUM
+ {
+ struct lifnum numifs;
+
+ numifs.lifn_family = AF_INET6;
+ numifs.lifn_flags = 0;
+ if (ioctl(fd, SIOCGLIFNUM, (char *)&numifs) < 0) {
+ /**
+ * SIOCGLIFNUM failed - assume IPv6 not configured
+ */
+ close(fd);
+ return JNI_FALSE;
+ }
+ /**
+ * If no IPv6 addresses then return false. If count > 0
+ * it's possible that all IPv6 addresses are "down" but
+ * that's okay as they may be brought "up" while the
+ * VM is running.
+ */
+ if (numifs.lifn_count == 0) {
+ close(fd);
+ return JNI_FALSE;
+ }
+ }
+#else
+ /* SIOCGLIFNUM not defined in build environment ??? */
+ close(fd);
+ return JNI_FALSE;
+#endif
+
+#endif /* __solaris */
+
+ /*
+ * OK we may have the stack available in the kernel,
+ * we should also check if the APIs are available.
+ */
+ ipv6_fn = JVM_FindLibraryEntry(RTLD_DEFAULT, "inet_pton");
+ if (ipv6_fn == NULL ) {
+ close(fd);
+ return JNI_FALSE;
+ }
+
+ /*
+ * We've got the library, let's get the pointers to some
+ * IPV6 specific functions. We have to do that because, at least
+ * on Solaris we may build on a system without IPV6 networking
+ * libraries, therefore we can't have a hard link to these
+ * functions.
+ */
+ getaddrinfo_ptr = (getaddrinfo_f)
+ JVM_FindLibraryEntry(RTLD_DEFAULT, "getaddrinfo");
+
+ freeaddrinfo_ptr = (freeaddrinfo_f)
+ JVM_FindLibraryEntry(RTLD_DEFAULT, "freeaddrinfo");
+
+ gai_strerror_ptr = (gai_strerror_f)
+ JVM_FindLibraryEntry(RTLD_DEFAULT, "gai_strerror");
+
+ getnameinfo_ptr = (getnameinfo_f)
+ JVM_FindLibraryEntry(RTLD_DEFAULT, "getnameinfo");
+
+ if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {
+ /* We need all 3 of them */
+ getaddrinfo_ptr = NULL;
+ }
+
+ close(fd);
+ return JNI_TRUE;
+#endif /* AF_INET6 */
+}
+#endif /* DONT_ENABLE_IPV6 */
+
+void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+ const char* hostname,
+ int gai_error)
+{
+ int size;
+ char *buf;
+ const char *format = "%s: %s";
+ const char *error_string =
+ (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
+ if (error_string == NULL)
+ error_string = "unknown error";
+
+ size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
+ buf = (char *) malloc(size);
+ if (buf) {
+ jstring s;
+ sprintf(buf, format, hostname, error_string);
+ s = JNU_NewStringPlatform(env, buf);
+ if (s != NULL) {
+ jobject x = JNU_NewObjectByName(env,
+ "java/net/UnknownHostException",
+ "(Ljava/lang/String;)V", s);
+ if (x != NULL)
+ (*env)->Throw(env, x);
+ }
+ free(buf);
+ }
+}
+
+void
+NET_AllocSockaddr(struct sockaddr **him, int *len) {
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));
+ *him = (struct sockaddr*)him6;
+ *len = sizeof(struct sockaddr_in6);
+ } else
+#endif /* AF_INET6 */
+ {
+ struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
+ *him = (struct sockaddr*)him4;
+ *len = sizeof(struct sockaddr_in);
+ }
+}
+
+#if defined(__linux__) && defined(AF_INET6)
+
+
+/* following code creates a list of addresses from the kernel
+ * routing table that are routed via the loopback address.
+ * We check all destination addresses against this table
+ * and override the scope_id field to use the relevant value for "lo"
+ * in order to work-around the Linux bug that prevents packets destined
+ * for certain local addresses from being sent via a physical interface.
+ */
+
+struct loopback_route {
+ struct in6_addr addr; /* destination address */
+ int plen; /* prefix length */
+};
+
+static struct loopback_route *loRoutes = 0;
+static int nRoutes = 0; /* number of routes */
+static int loRoutes_size = 16; /* initial size */
+static int lo_scope_id = 0;
+
+static void initLoopbackRoutes();
+
+void printAddr (struct in6_addr *addr) {
+ int i;
+ for (i=0; i<16; i++) {
+ printf ("%02x", addr->s6_addr[i]);
+ }
+ printf ("\n");
+}
+
+static jboolean needsLoopbackRoute (struct in6_addr* dest_addr) {
+ int byte_count;
+ int extra_bits, i;
+ struct loopback_route *ptr;
+
+ if (loRoutes == 0) {
+ initLoopbackRoutes();
+ }
+
+ for (ptr = loRoutes, i=0; i<nRoutes; i++, ptr++) {
+ struct in6_addr *target_addr=&ptr->addr;
+ int dest_plen = ptr->plen;
+ byte_count = dest_plen >> 3;
+ extra_bits = dest_plen & 0x3;
+
+ if (byte_count > 0) {
+ if (memcmp(target_addr, dest_addr, byte_count)) {
+ continue; /* no match */
+ }
+ }
+
+ if (extra_bits > 0) {
+ unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
+ unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
+ unsigned char mask = 0xff << (8 - extra_bits);
+ if ((c1 & mask) != (c2 & mask)) {
+ continue;
+ }
+ }
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+
+static void initLoopbackRoutes() {
+ FILE *f;
+ char srcp[8][5];
+ char hopp[8][5];
+ int dest_plen, src_plen, use, refcnt, metric;
+ unsigned long flags;
+ char dest_str[40];
+ struct in6_addr dest_addr;
+ char device[16];
+
+ if (loRoutes != 0) {
+ free (loRoutes);
+ }
+ loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));
+ if (loRoutes == 0) {
+ return;
+ }
+ /*
+ * Scan /proc/net/ipv6_route looking for a matching
+ * route.
+ */
+ if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
+ return ;
+ }
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
+ "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
+ "%4s%4s%4s%4s%4s%4s%4s%4s "
+ "%08x %08x %08x %08lx %8s",
+ dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
+ &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
+ &dest_plen,
+ srcp[0], srcp[1], srcp[2], srcp[3],
+ srcp[4], srcp[5], srcp[6], srcp[7],
+ &src_plen,
+ hopp[0], hopp[1], hopp[2], hopp[3],
+ hopp[4], hopp[5], hopp[6], hopp[7],
+ &metric, &use, &refcnt, &flags, device) == 31) {
+
+ /*
+ * Some routes should be ignored
+ */
+ if ( (dest_plen < 0 || dest_plen > 128) ||
+ (src_plen != 0) ||
+ (flags & (RTF_POLICY | RTF_FLOW)) ||
+ ((flags & RTF_REJECT) && dest_plen == 0) ) {
+ continue;
+ }
+
+ /*
+ * Convert the destination address
+ */
+ dest_str[4] = ':';
+ dest_str[9] = ':';
+ dest_str[14] = ':';
+ dest_str[19] = ':';
+ dest_str[24] = ':';
+ dest_str[29] = ':';
+ dest_str[34] = ':';
+ dest_str[39] = '\0';
+
+ if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
+ /* not an Ipv6 address */
+ continue;
+ }
+ if (strcmp(device, "lo") != 0) {
+ /* Not a loopback route */
+ continue;
+ } else {
+ if (nRoutes == loRoutes_size) {
+ loRoutes = realloc (loRoutes, loRoutes_size *
+ sizeof (struct loopback_route) * 2);
+ if (loRoutes == 0) {
+ return ;
+ }
+ loRoutes_size *= 2;
+ }
+ memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));
+ loRoutes[nRoutes].plen = dest_plen;
+ nRoutes ++;
+ }
+ }
+
+ fclose (f);
+ {
+ /* now find the scope_id for "lo" */
+
+ char devname[21];
+ char addr6p[8][5];
+ int plen, scope, dad_status, if_idx;
+
+ if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+ addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+ &if_idx, &plen, &scope, &dad_status, devname) == 13) {
+
+ if (strcmp(devname, "lo") == 0) {
+ /*
+ * Found - so just return the index
+ */
+ fclose(f);
+ lo_scope_id = if_idx;
+ return;
+ }
+ }
+ fclose(f);
+ }
+ }
+}
+
+/*
+ * Following is used for binding to local addresses. Equivalent
+ * to code above, for bind().
+ */
+
+struct localinterface {
+ int index;
+ char localaddr [16];
+};
+
+static struct localinterface *localifs = 0;
+static int localifsSize = 0; /* size of array */
+static int nifs = 0; /* number of entries used in array */
+
+/* not thread safe: make sure called once from one thread */
+
+static void initLocalIfs () {
+ FILE *f;
+ unsigned char staddr [16];
+ char ifname [33];
+ struct localinterface *lif=0;
+ int index, x1, x2, x3;
+ unsigned int u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,ua,ub,uc,ud,ue,uf;
+
+ if ((f = fopen("/proc/net/if_inet6", "r")) == NULL) {
+ return ;
+ }
+ while (fscanf (f, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x "
+ "%d %x %x %x %32s",&u0,&u1,&u2,&u3,&u4,&u5,&u6,&u7,
+ &u8,&u9,&ua,&ub,&uc,&ud,&ue,&uf,
+ &index, &x1, &x2, &x3, ifname) == 21) {
+ staddr[0] = (unsigned char)u0;
+ staddr[1] = (unsigned char)u1;
+ staddr[2] = (unsigned char)u2;
+ staddr[3] = (unsigned char)u3;
+ staddr[4] = (unsigned char)u4;
+ staddr[5] = (unsigned char)u5;
+ staddr[6] = (unsigned char)u6;
+ staddr[7] = (unsigned char)u7;
+ staddr[8] = (unsigned char)u8;
+ staddr[9] = (unsigned char)u9;
+ staddr[10] = (unsigned char)ua;
+ staddr[11] = (unsigned char)ub;
+ staddr[12] = (unsigned char)uc;
+ staddr[13] = (unsigned char)ud;
+ staddr[14] = (unsigned char)ue;
+ staddr[15] = (unsigned char)uf;
+ nifs ++;
+ if (nifs > localifsSize) {
+ localifs = (struct localinterface *) realloc (
+ localifs, sizeof (struct localinterface)* (localifsSize+5));
+ if (localifs == 0) {
+ nifs = 0;
+ fclose (f);
+ return;
+ }
+ lif = localifs + localifsSize;
+ localifsSize += 5;
+ } else {
+ lif ++;
+ }
+ memcpy (lif->localaddr, staddr, 16);
+ lif->index = index;
+ }
+ fclose (f);
+}
+
+/* return the scope_id (interface index) of the
+ * interface corresponding to the given address
+ * returns 0 if no match found
+ */
+
+static int getLocalScopeID (char *addr) {
+ struct localinterface *lif;
+ int i;
+ if (localifs == 0) {
+ initLocalIfs();
+ }
+ for (i=0, lif=localifs; i<nifs; i++, lif++) {
+ if (memcmp (addr, lif->localaddr, 16) == 0) {
+ return lif->index;
+ }
+ }
+ return 0;
+}
+
+void initLocalAddrTable () {
+ initLoopbackRoutes();
+ initLocalIfs();
+}
+
+#else
+
+void initLocalAddrTable () {}
+
+#endif
+
+void parseExclusiveBindProperty(JNIEnv *env) {
+#ifdef __solaris__
+ jstring s, flagSet;
+ jclass iCls;
+ jmethodID mid;
+
+ s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
+ CHECK_NULL(s);
+ iCls = (*env)->FindClass(env, "java/lang/System");
+ CHECK_NULL(iCls);
+ mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
+ "(Ljava/lang/String;)Ljava/lang/String;");
+ CHECK_NULL(mid);
+ flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
+ if (flagSet != NULL) {
+ useExclBind = 1;
+ }
+#endif
+}
+/* In the case of an IPv4 Inetaddress this method will return an
+ * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
+ * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
+*/
+JNIEXPORT int JNICALL
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him,
+ int *len, jboolean v4MappedAddress) {
+ jint family;
+ family = getInetAddress_family(env, iaObj);
+#ifdef AF_INET6
+ /* needs work. 1. family 2. clean up him6 etc deallocate memory */
+ if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+ jbyteArray ipaddress;
+ jbyte caddr[16];
+ jint address;
+
+
+ if (family == IPv4) { /* will convert to IPv4-mapped address */
+ memset((char *) caddr, 0, 16);
+ address = getInetAddress_addr(env, iaObj);
+ if (address == INADDR_ANY) {
+ /* we would always prefer IPv6 wildcard address
+ caddr[10] = 0xff;
+ caddr[11] = 0xff; */
+ } else {
+ caddr[10] = 0xff;
+ caddr[11] = 0xff;
+ caddr[12] = ((address >> 24) & 0xff);
+ caddr[13] = ((address >> 16) & 0xff);
+ caddr[14] = ((address >> 8) & 0xff);
+ caddr[15] = (address & 0xff);
+ }
+ } else {
+ ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID);
+ (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr);
+ }
+ memset((char *)him6, 0, sizeof(struct sockaddr_in6));
+ him6->sin6_port = htons(port);
+ memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
+ him6->sin6_family = AF_INET6;
+ *len = sizeof(struct sockaddr_in6) ;
+
+#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
+// XXXBSD: should we do something with scope id here ? see below linux comment
+/* MMM: Come back to this! */
+#endif
+
+ /*
+ * On Linux if we are connecting to a link-local address
+ * we need to specify the interface in the scope_id (2.4 kernel only)
+ *
+ * If the scope was cached the we use the cached value. If not cached but
+ * specified in the Inet6Address we use that, but we first check if the
+ * address needs to be routed via the loopback interface. In this case,
+ * we override the specified value with that of the loopback interface.
+ * If no cached value exists and no value was specified by user, then
+ * we try to determine a value ffrom the routing table. In all these
+ * cases the used value is cached for further use.
+ */
+#ifdef __linux__
+ if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
+ int cached_scope_id = 0, scope_id = 0;
+ int old_kernel = kernelIsV22();
+
+ if (ia6_cachedscopeidID && !old_kernel) {
+ cached_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
+ /* if cached value exists then use it. Otherwise, check
+ * if scope is set in the address.
+ */
+ if (!cached_scope_id) {
+ if (ia6_scopeidID) {
+ scope_id = (int)(*env)->GetIntField(env,iaObj,ia6_scopeidID);
+ }
+ if (scope_id != 0) {
+ /* check user-specified value for loopback case
+ * that needs to be overridden
+ */
+ if (kernelIsV24() && needsLoopbackRoute (&him6->sin6_addr)) {
+ cached_scope_id = lo_scope_id;
+ (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
+ }
+ } else {
+ /*
+ * Otherwise consult the IPv6 routing tables to
+ * try determine the appropriate interface.
+ */
+ if (kernelIsV24()) {
+ cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
+ } else {
+ cached_scope_id = getLocalScopeID( (char *)&(him6->sin6_addr) );
+ if (cached_scope_id == 0) {
+ cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
+ }
+ }
+ (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
+ }
+ }
+ }
+
+ /*
+ * If we have a scope_id use the extended form
+ * of sockaddr_in6.
+ */
+
+ if (!old_kernel) {
+ struct sockaddr_in6 *him6 =
+ (struct sockaddr_in6 *)him;
+ him6->sin6_scope_id = cached_scope_id != 0 ?
+ cached_scope_id : scope_id;
+ *len = sizeof(struct sockaddr_in6);
+ }
+ }
+#else
+ /* handle scope_id for solaris */
+
+ if (family != IPv4) {
+ if (ia6_scopeidID) {
+ him6->sin6_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID);
+ }
+ }
+#endif
+ } else
+#endif /* AF_INET6 */
+ {
+ struct sockaddr_in *him4 = (struct sockaddr_in*)him;
+ jint address;
+ if (family == IPv6) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
+ return -1;
+ }
+ memset((char *) him4, 0, sizeof(struct sockaddr_in));
+ address = getInetAddress_addr(env, iaObj);
+ him4->sin_port = htons((short) port);
+ him4->sin_addr.s_addr = (uint32_t) htonl(address);
+ him4->sin_family = AF_INET;
+ *len = sizeof(struct sockaddr_in);
+ }
+ return 0;
+}
+
+void
+NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
+#ifdef AF_INET6
+ if (him->sa_family == AF_INET6) {
+ struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
+ him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
+ }
+#endif /* AF_INET6 */
+}
+
+JNIEXPORT jint JNICALL
+NET_GetPortFromSockaddr(struct sockaddr *him) {
+#ifdef AF_INET6
+ if (him->sa_family == AF_INET6) {
+ return ntohs(((struct sockaddr_in6*)him)->sin6_port);
+
+ } else
+#endif /* AF_INET6 */
+ {
+ return ntohs(((struct sockaddr_in*)him)->sin_port);
+ }
+}
+
+int
+NET_IsIPv4Mapped(jbyte* caddr) {
+ int i;
+ for (i = 0; i < 10; i++) {
+ if (caddr[i] != 0x00) {
+ return 0; /* false */
+ }
+ }
+
+ if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) {
+ return 1; /* true */
+ }
+ return 0; /* false */
+}
+
+int
+NET_IPv4MappedToIPv4(jbyte* caddr) {
+ return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8)
+ | (caddr[15] & 0xff);
+}
+
+int
+NET_IsEqual(jbyte* caddr1, jbyte* caddr2) {
+ int i;
+ for (i = 0; i < 16; i++) {
+ if (caddr1[i] != caddr2[i]) {
+ return 0; /* false */
+ }
+ }
+ return 1;
+}
+
+jboolean NET_addrtransAvailable() {
+ return (jboolean)(getaddrinfo_ptr != NULL);
+}
+
+int NET_IsZeroAddr(jbyte* caddr) {
+ int i;
+ for (i = 0; i < 16; i++) {
+ if (caddr[i] != 0) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/*
+ * Map the Java level socket option to the platform specific
+ * level and option name.
+ */
+int
+NET_MapSocketOption(jint cmd, int *level, int *optname) {
+ static struct {
+ jint cmd;
+ int level;
+ int optname;
+ } const opts[] = {
+ { java_net_SocketOptions_TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY },
+ { java_net_SocketOptions_SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE },
+ { java_net_SocketOptions_SO_LINGER, SOL_SOCKET, SO_LINGER },
+ { java_net_SocketOptions_SO_SNDBUF, SOL_SOCKET, SO_SNDBUF },
+ { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF },
+ { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE },
+ { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR },
+ { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST },
+ { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS },
+ { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF },
+ { java_net_SocketOptions_IP_MULTICAST_IF2, IPPROTO_IP, IP_MULTICAST_IF },
+ { java_net_SocketOptions_IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP },
+ };
+
+ int i;
+
+ /*
+ * Different multicast options if IPv6 is enabled
+ */
+#ifdef AF_INET6
+ if (ipv6_available()) {
+ switch (cmd) {
+ case java_net_SocketOptions_IP_MULTICAST_IF:
+ case java_net_SocketOptions_IP_MULTICAST_IF2:
+ *level = IPPROTO_IPV6;
+ *optname = IPV6_MULTICAST_IF;
+ return 0;
+
+ case java_net_SocketOptions_IP_MULTICAST_LOOP:
+ *level = IPPROTO_IPV6;
+ *optname = IPV6_MULTICAST_LOOP;
+ return 0;
+ }
+ }
+#endif
+
+ /*
+ * Map the Java level option to the native level
+ */
+ for (i=0; i<(int)(sizeof(opts) / sizeof(opts[0])); i++) {
+ if (cmd == opts[i].cmd) {
+ *level = opts[i].level;
+ *optname = opts[i].optname;
+ return 0;
+ }
+ }
+
+ /* not found */
+ return -1;
+}
+
+/*
+ * Determine the default interface for an IPv6 address.
+ *
+ * 1. Scans /proc/net/ipv6_route for a matching route
+ * (eg: fe80::/10 or a route for the specific address).
+ * This will tell us the interface to use (eg: "eth0").
+ *
+ * 2. Lookup /proc/net/if_inet6 to map the interface
+ * name to an interface index.
+ *
+ * Returns :-
+ * -1 if error
+ * 0 if no matching interface
+ * >1 interface index to use for the link-local address.
+ */
+#if defined(__linux__) && defined(AF_INET6)
+int getDefaultIPv6Interface(struct in6_addr *target_addr) {
+ FILE *f;
+ char srcp[8][5];
+ char hopp[8][5];
+ int dest_plen, src_plen, use, refcnt, metric;
+ unsigned long flags;
+ char dest_str[40];
+ struct in6_addr dest_addr;
+ char device[16];
+ jboolean match = JNI_FALSE;
+
+ /*
+ * Scan /proc/net/ipv6_route looking for a matching
+ * route.
+ */
+ if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {
+ return -1;
+ }
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
+ "%4s%4s%4s%4s%4s%4s%4s%4s %02x "
+ "%4s%4s%4s%4s%4s%4s%4s%4s "
+ "%08x %08x %08x %08lx %8s",
+ dest_str, &dest_str[5], &dest_str[10], &dest_str[15],
+ &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],
+ &dest_plen,
+ srcp[0], srcp[1], srcp[2], srcp[3],
+ srcp[4], srcp[5], srcp[6], srcp[7],
+ &src_plen,
+ hopp[0], hopp[1], hopp[2], hopp[3],
+ hopp[4], hopp[5], hopp[6], hopp[7],
+ &metric, &use, &refcnt, &flags, device) == 31) {
+
+ /*
+ * Some routes should be ignored
+ */
+ if ( (dest_plen < 0 || dest_plen > 128) ||
+ (src_plen != 0) ||
+ (flags & (RTF_POLICY | RTF_FLOW)) ||
+ ((flags & RTF_REJECT) && dest_plen == 0) ) {
+ continue;
+ }
+
+ /*
+ * Convert the destination address
+ */
+ dest_str[4] = ':';
+ dest_str[9] = ':';
+ dest_str[14] = ':';
+ dest_str[19] = ':';
+ dest_str[24] = ':';
+ dest_str[29] = ':';
+ dest_str[34] = ':';
+ dest_str[39] = '\0';
+
+ if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {
+ /* not an Ipv6 address */
+ continue;
+ } else {
+ /*
+ * The prefix len (dest_plen) indicates the number of bits we
+ * need to match on.
+ *
+ * dest_plen / 8 => number of bytes to match
+ * dest_plen % 8 => number of additional bits to match
+ *
+ * eg: fe80::/10 => match 1 byte + 2 additional bits in the
+ * the next byte.
+ */
+ int byte_count = dest_plen >> 3;
+ int extra_bits = dest_plen & 0x3;
+
+ if (byte_count > 0) {
+ if (memcmp(target_addr, &dest_addr, byte_count)) {
+ continue; /* no match */
+ }
+ }
+
+ if (extra_bits > 0) {
+ unsigned char c1 = ((unsigned char *)target_addr)[byte_count];
+ unsigned char c2 = ((unsigned char *)&dest_addr)[byte_count];
+ unsigned char mask = 0xff << (8 - extra_bits);
+ if ((c1 & mask) != (c2 & mask)) {
+ continue;
+ }
+ }
+
+ /*
+ * We have a match
+ */
+ match = JNI_TRUE;
+ break;
+ }
+ }
+ fclose(f);
+
+ /*
+ * If there's a match then we lookup the interface
+ * index.
+ */
+ if (match) {
+ char devname[21];
+ char addr6p[8][5];
+ int plen, scope, dad_status, if_idx;
+
+ if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {
+ while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
+ addr6p[0], addr6p[1], addr6p[2], addr6p[3],
+ addr6p[4], addr6p[5], addr6p[6], addr6p[7],
+ &if_idx, &plen, &scope, &dad_status, devname) == 13) {
+
+ if (strcmp(devname, device) == 0) {
+ /*
+ * Found - so just return the index
+ */
+ fclose(f);
+ return if_idx;
+ }
+ }
+ fclose(f);
+ } else {
+ /*
+ * Couldn't open /proc/net/if_inet6
+ */
+ return -1;
+ }
+ }
+
+ /*
+ * If we get here it means we didn't there wasn't any
+ * route or we couldn't get the index of the interface.
+ */
+ return 0;
+}
+#endif
+
+
+/*
+ * Wrapper for getsockopt system routine - does any necessary
+ * pre/post processing to deal with OS specific oddies :-
+ *
+ * IP_TOS is a no-op with IPv6 sockets as it's setup when
+ * the connection is established.
+ *
+ * On Linux the SO_SNDBUF/SO_RCVBUF values must be post-processed
+ * to compensate for an incorrect value returned by the kernel.
+ */
+int
+NET_GetSockOpt(int fd, int level, int opt, void *result,
+ int *len)
+{
+ int rv;
+
+#ifdef AF_INET6
+ if ((level == IPPROTO_IP) && (opt == IP_TOS)) {
+ if (ipv6_available()) {
+
+ /*
+ * For IPv6 socket option implemented at Java-level
+ * so return -1.
+ */
+ int *tc = (int *)result;
+ *tc = -1;
+ return 0;
+ }
+ }
+#endif
+
+#ifdef __solaris__
+ rv = getsockopt(fd, level, opt, result, len);
+#else
+ {
+ socklen_t socklen = *len;
+ rv = getsockopt(fd, level, opt, result, &socklen);
+ *len = socklen;
+ }
+#endif
+
+ if (rv < 0) {
+ return rv;
+ }
+
+#ifdef __linux__
+ /*
+ * On Linux SO_SNDBUF/SO_RCVBUF aren't symmetric. This
+ * stems from additional socket structures in the send
+ * and receive buffers.
+ */
+ if ((level == SOL_SOCKET) && ((opt == SO_SNDBUF)
+ || (opt == SO_RCVBUF))) {
+ int n = *((int *)result);
+ n /= 2;
+ *((int *)result) = n;
+ }
+#endif
+
+/* Workaround for Mac OS treating linger value as
+ * signed integer
+ */
+#ifdef MACOSX
+ if (level == SOL_SOCKET && opt == SO_LINGER) {
+ struct linger* to_cast = (struct linger*)result;
+ to_cast->l_linger = (unsigned short)to_cast->l_linger;
+ }
+#endif
+ return rv;
+}
+
+/*
+ * Wrapper for setsockopt system routine - performs any
+ * necessary pre/post processing to deal with OS specific
+ * issue :-
+ *
+ * On Solaris need to limit the suggested value for SO_SNDBUF
+ * and SO_RCVBUF to the kernel configured limit
+ *
+ * For IP_TOS socket option need to mask off bits as this
+ * aren't automatically masked by the kernel and results in
+ * an error. In addition IP_TOS is a noop with IPv6 as it
+ * should be setup as connection time.
+ */
+int
+NET_SetSockOpt(int fd, int level, int opt, const void *arg,
+ int len)
+{
+#ifndef IPTOS_TOS_MASK
+#define IPTOS_TOS_MASK 0x1e
+#endif
+#ifndef IPTOS_PREC_MASK
+#define IPTOS_PREC_MASK 0xe0
+#endif
+
+#if defined(_ALLBSD_SOURCE)
+#if defined(KIPC_MAXSOCKBUF)
+ int mib[3];
+ size_t rlen;
+#endif
+
+ int *bufsize;
+
+#ifdef __APPLE__
+ static int maxsockbuf = -1;
+#else
+ static long maxsockbuf = -1;
+#endif
+
+ int addopt;
+ struct linger *ling;
+#endif
+
+ /*
+ * IPPROTO/IP_TOS :-
+ * 1. IPv6 on Solaris/Mac OS: no-op and will be set
+ * in flowinfo field when connecting TCP socket,
+ * or sending UDP packet.
+ * 2. IPv6 on Linux: By default Linux ignores flowinfo
+ * field so enable IPV6_FLOWINFO_SEND so that flowinfo
+ * will be examined.
+ * 3. IPv4: set socket option based on ToS and Precedence
+ * fields (otherwise get invalid argument)
+ */
+ if (level == IPPROTO_IP && opt == IP_TOS) {
+ int *iptos;
+
+#if defined(AF_INET6) && (defined(__solaris__) || defined(MACOSX))
+ if (ipv6_available()) {
+ return 0;
+ }
+#endif
+
+#if defined(AF_INET6) && defined(__linux__)
+ if (ipv6_available()) {
+ int optval = 1;
+ return setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
+ (void *)&optval, sizeof(optval));
+ }
+#endif
+
+ iptos = (int *)arg;
+ *iptos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
+ }
+
+ /*
+ * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
+ * the value when it exceeds the system limit.
+ */
+#ifdef __solaris__
+ if (level == SOL_SOCKET) {
+ if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
+ int sotype=0, arglen;
+ int *bufsize, maxbuf;
+ int ret;
+
+ /* Attempt with the original size */
+ ret = setsockopt(fd, level, opt, arg, len);
+ if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
+ return ret;
+
+ /* Exceeded system limit so clamp and retry */
+
+ arglen = sizeof(sotype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype,
+ &arglen) < 0) {
+ return -1;
+ }
+
+ /*
+ * We try to get tcp_maxbuf (and udp_max_buf) using
+ * an ioctl() that isn't available on all versions of Solaris.
+ * If that fails, we use the search algorithm in findMaxBuf()
+ */
+ if (!init_tcp_max_buf && sotype == SOCK_STREAM) {
+ tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf");
+ if (tcp_max_buf == -1) {
+ tcp_max_buf = findMaxBuf(fd, opt, SOCK_STREAM);
+ if (tcp_max_buf == -1) {
+ return -1;
+ }
+ }
+ init_tcp_max_buf = 1;
+ } else if (!init_udp_max_buf && sotype == SOCK_DGRAM) {
+ udp_max_buf = getParam("/dev/udp", "udp_max_buf");
+ if (udp_max_buf == -1) {
+ udp_max_buf = findMaxBuf(fd, opt, SOCK_DGRAM);
+ if (udp_max_buf == -1) {
+ return -1;
+ }
+ }
+ init_udp_max_buf = 1;
+ }
+
+ maxbuf = (sotype == SOCK_STREAM) ? tcp_max_buf : udp_max_buf;
+ bufsize = (int *)arg;
+ if (*bufsize > maxbuf) {
+ *bufsize = maxbuf;
+ }
+ }
+ }
+#endif
+
+ /*
+ * On Linux the receive buffer is used for both socket
+ * structures and the the packet payload. The implication
+ * is that if SO_RCVBUF is too small then small packets
+ * must be discard.
+ */
+#ifdef __linux__
+ if (level == SOL_SOCKET && opt == SO_RCVBUF) {
+ int *bufsize = (int *)arg;
+ if (*bufsize < 1024) {
+ *bufsize = 1024;
+ }
+ }
+#endif
+
+#if defined(_ALLBSD_SOURCE)
+ /*
+ * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On FreeBSD need to
+ * ensure that value is <= kern.ipc.maxsockbuf as otherwise we get
+ * an ENOBUFS error.
+ */
+ if (level == SOL_SOCKET) {
+ if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
+#ifdef KIPC_MAXSOCKBUF
+ if (maxsockbuf == -1) {
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_IPC;
+ mib[2] = KIPC_MAXSOCKBUF;
+ rlen = sizeof(maxsockbuf);
+ if (sysctl(mib, 3, &maxsockbuf, &rlen, NULL, 0) == -1)
+ maxsockbuf = 1024;
+
+#if 1
+ /* XXXBSD: This is a hack to workaround mb_max/mb_max_adj
+ problem. It should be removed when kern.ipc.maxsockbuf
+ will be real value. */
+ maxsockbuf = (maxsockbuf/5)*4;
+#endif
+ }
+#elif defined(__OpenBSD__)
+ maxsockbuf = SB_MAX;
+#else
+ maxsockbuf = 64 * 1024; /* XXX: NetBSD */
+#endif
+
+ bufsize = (int *)arg;
+ if (*bufsize > maxsockbuf) {
+ *bufsize = maxsockbuf;
+ }
+
+ if (opt == SO_RCVBUF && *bufsize < 1024) {
+ *bufsize = 1024;
+ }
+
+ }
+ }
+
+ /*
+ * On Solaris, SO_REUSEADDR will allow multiple datagram
+ * sockets to bind to the same port. The network jck tests
+ * for this "feature", so we need to emulate it by turning on
+ * SO_REUSEPORT as well for that combination.
+ */
+ if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
+ int sotype;
+ socklen_t arglen;
+
+ arglen = sizeof(sotype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
+ return -1;
+ }
+
+ if (sotype == SOCK_DGRAM) {
+ addopt = SO_REUSEPORT;
+ setsockopt(fd, level, addopt, arg, len);
+ }
+ }
+
+#endif
+
+ return setsockopt(fd, level, opt, arg, len);
+}
+
+/*
+ * Wrapper for bind system call - performs any necessary pre/post
+ * processing to deal with OS specific issues :-
+ *
+ * Linux allows a socket to bind to 127.0.0.255 which must be
+ * caught.
+ *
+ * On Solaris with IPv6 enabled we must use an exclusive
+ * bind to guaranteed a unique port number across the IPv4 and
+ * IPv6 port spaces.
+ *
+ */
+int
+NET_Bind(int fd, struct sockaddr *him, int len)
+{
+#if defined(__solaris__) && defined(AF_INET6)
+ int level = -1;
+ int exclbind = -1;
+#endif
+ int rv;
+
+#ifdef __linux__
+ /*
+ * ## get bugId for this issue - goes back to 1.2.2 port ##
+ * ## When IPv6 is enabled this will be an IPv4-mapped
+ * ## with family set to AF_INET6
+ */
+ if (him->sa_family == AF_INET) {
+ struct sockaddr_in *sa = (struct sockaddr_in *)him;
+ if ((ntohl(sa->sin_addr.s_addr) & 0x7f0000ff) == 0x7f0000ff) {
+ errno = EADDRNOTAVAIL;
+ return -1;
+ }
+ }
+#endif
+
+#if defined(__solaris__) && defined(AF_INET6)
+ /*
+ * Solaris has seperate IPv4 and IPv6 port spaces so we
+ * use an exclusive bind when SO_REUSEADDR is not used to
+ * give the illusion of a unified port space.
+ * This also avoids problems with IPv6 sockets connecting
+ * to IPv4 mapped addresses whereby the socket conversion
+ * results in a late bind that fails because the
+ * corresponding IPv4 port is in use.
+ */
+ if (ipv6_available()) {
+ int arg, len;
+
+ len = sizeof(arg);
+ if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&arg, &len) == 0) {
+ if (useExclBind || arg == 0) {
+ /*
+ * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
+ * property is true so enable TCP_EXCLBIND or
+ * UDP_EXCLBIND
+ */
+ len = sizeof(arg);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&arg,
+ &len) == 0) {
+ if (arg == SOCK_STREAM) {
+ level = IPPROTO_TCP;
+ exclbind = TCP_EXCLBIND;
+ } else {
+ level = IPPROTO_UDP;
+ exclbind = UDP_EXCLBIND;
+ }
+ }
+
+ arg = 1;
+ setsockopt(fd, level, exclbind, (char *)&arg,
+ sizeof(arg));
+ }
+ }
+ }
+
+#endif
+
+ rv = bind(fd, him, len);
+
+#if defined(__solaris__) && defined(AF_INET6)
+ if (rv < 0) {
+ int en = errno;
+ /* Restore *_EXCLBIND if the bind fails */
+ if (exclbind != -1) {
+ int arg = 0;
+ setsockopt(fd, level, exclbind, (char *)&arg,
+ sizeof(arg));
+ }
+ errno = en;
+ }
+#endif
+
+ return rv;
+}
+
+/**
+ * Wrapper for select/poll with timeout on a single file descriptor.
+ *
+ * flags (defined in net_util_md.h can be any combination of
+ * NET_WAIT_READ, NET_WAIT_WRITE & NET_WAIT_CONNECT.
+ *
+ * The function will return when either the socket is ready for one
+ * of the specified operation or the timeout expired.
+ *
+ * It returns the time left from the timeout (possibly 0), or -1 if it expired.
+ */
+
+jint
+NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
+{
+ jlong prevTime = JVM_CurrentTimeMillis(env, 0);
+ jint read_rv;
+
+ while (1) {
+ jlong newTime;
+#ifndef USE_SELECT
+ {
+ struct pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = 0;
+ if (flags & NET_WAIT_READ)
+ pfd.events |= POLLIN;
+ if (flags & NET_WAIT_WRITE)
+ pfd.events |= POLLOUT;
+ if (flags & NET_WAIT_CONNECT)
+ pfd.events |= POLLOUT;
+
+ errno = 0;
+ read_rv = NET_Poll(&pfd, 1, timeout);
+ }
+#else
+ {
+ fd_set rd, wr, ex;
+ struct timeval t;
+
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+ if (flags & NET_WAIT_READ) {
+ FD_SET(fd, &rd);
+ }
+ if (flags & NET_WAIT_WRITE) {
+ FD_SET(fd, &wr);
+ }
+ if (flags & NET_WAIT_CONNECT) {
+ FD_SET(fd, &wr);
+ FD_SET(fd, &ex);
+ }
+
+ errno = 0;
+ read_rv = NET_Select(fd+1, &rd, &wr, &ex, &t);
+ }
+#endif
+
+ newTime = JVM_CurrentTimeMillis(env, 0);
+ timeout -= (newTime - prevTime);
+ if (timeout <= 0) {
+ return read_rv > 0 ? 0 : -1;
+ }
+ newTime = prevTime;
+
+ if (read_rv > 0) {
+ break;
+ }
+
+
+ } /* while */
+
+ return timeout;
+}
diff --git a/ojluni/src/main/native/net_util_md.h b/ojluni/src/main/native/net_util_md.h
new file mode 100755
index 0000000..c72a07b
--- /dev/null
+++ b/ojluni/src/main/native/net_util_md.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NET_UTILS_MD_H
+#define NET_UTILS_MD_H
+
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#ifndef USE_SELECT
+#include <sys/poll.h>
+#endif
+
+
+#if defined(__linux__) || defined(MACOSX)
+extern int NET_Timeout(int s, long timeout);
+extern int NET_Read(int s, void* buf, size_t len);
+extern int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen);
+extern int NET_ReadV(int s, const struct iovec * vector, int count);
+extern int NET_Send(int s, void *msg, int len, unsigned int flags);
+extern int NET_SendTo(int s, const void *msg, int len, unsigned int
+ flags, const struct sockaddr *to, int tolen);
+extern int NET_Writev(int s, const struct iovec * vector, int count);
+extern int NET_Connect(int s, struct sockaddr *addr, int addrlen);
+extern int NET_Accept(int s, struct sockaddr *addr, int *addrlen);
+extern int NET_SocketClose(int s);
+extern int NET_Dup2(int oldfd, int newfd);
+
+#ifdef USE_SELECT
+extern int NET_Select(int s, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout);
+#else
+extern int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
+#endif
+
+#else
+
+#define NET_Timeout JVM_Timeout
+#define NET_Read JVM_Read
+#define NET_RecvFrom JVM_RecvFrom
+#define NET_ReadV readv
+#define NET_Send JVM_Send
+#define NET_SendTo JVM_SendTo
+#define NET_WriteV writev
+#define NET_Connect JVM_Connect
+#define NET_Accept JVM_Accept
+#define NET_SocketClose JVM_SocketClose
+#define NET_Dup2 dup2
+#define NET_Select select
+#define NET_Poll poll
+
+#endif
+
+#if defined(__linux__) && defined(AF_INET6)
+int getDefaultIPv6Interface(struct in6_addr *target_addr);
+#endif
+
+
+/* needed from libsocket on Solaris 8 */
+
+typedef int (*getaddrinfo_f)(const char *nodename, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res);
+
+typedef void (*freeaddrinfo_f)(struct addrinfo *);
+
+typedef const char * (*gai_strerror_f)(int ecode);
+
+typedef int (*getnameinfo_f)(const struct sockaddr *, size_t,
+ char *, size_t, char *, size_t, int);
+
+extern getaddrinfo_f getaddrinfo_ptr;
+extern freeaddrinfo_f freeaddrinfo_ptr;
+extern getnameinfo_f getnameinfo_ptr;
+
+void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
+ const char* hostname,
+ int gai_error);
+
+/* do we have address translation support */
+
+extern jboolean NET_addrtransAvailable();
+
+#define NET_WAIT_READ 0x01
+#define NET_WAIT_WRITE 0x02
+#define NET_WAIT_CONNECT 0x04
+
+extern jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
+
+/************************************************************************
+ * Macros and constants
+ */
+
+/*
+ * On 64-bit JDKs we use a much larger stack and heap buffer.
+ */
+#ifdef _LP64
+#define MAX_BUFFER_LEN 65536
+#define MAX_HEAP_BUFFER_LEN 131072
+#else
+#define MAX_BUFFER_LEN 8192
+#define MAX_HEAP_BUFFER_LEN 65536
+#endif
+
+#ifdef AF_INET6
+
+#define SOCKADDR union { \
+ struct sockaddr_in him4; \
+ struct sockaddr_in6 him6; \
+ }
+
+#define SOCKADDR_LEN (ipv6_available() ? sizeof(SOCKADDR) : \
+ sizeof(struct sockaddr_in))
+
+#else
+
+#define SOCKADDR union { struct sockaddr_in him4; }
+#define SOCKADDR_LEN sizeof(SOCKADDR)
+
+#endif
+
+/************************************************************************
+ * Utilities
+ */
+#ifdef __linux__
+extern int kernelIsV22();
+extern int kernelIsV24();
+#endif
+
+void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
+ const char *defaultDetail);
+
+
+#endif /* NET_UTILS_MD_H */
diff --git a/ojluni/src/main/native/nio.h b/ojluni/src/main/native/nio.h
new file mode 100755
index 0000000..738c6b3
--- /dev/null
+++ b/ojluni/src/main/native/nio.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "sun_nio_ch_IOStatus.h"
+
+#define IOS_EOF (sun_nio_ch_IOStatus_EOF)
+#define IOS_UNAVAILABLE (sun_nio_ch_IOStatus_UNAVAILABLE)
+#define IOS_INTERRUPTED (sun_nio_ch_IOStatus_INTERRUPTED)
+#define IOS_UNSUPPORTED (sun_nio_ch_IOStatus_UNSUPPORTED)
+#define IOS_THROWN (sun_nio_ch_IOStatus_THROWN)
+#define IOS_UNSUPPORTED_CASE (sun_nio_ch_IOStatus_UNSUPPORTED_CASE)
diff --git a/ojluni/src/main/native/nio_util.h b/ojluni/src/main/native/nio_util.h
new file mode 100755
index 0000000..441ea20
--- /dev/null
+++ b/ojluni/src/main/native/nio_util.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include <errno.h>
+#include <sys/types.h>
+
+#define RESTARTABLE(_cmd, _result) do { \
+ do { \
+ _result = _cmd; \
+ } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+
+/* NIO utility procedures */
+
+
+/* Defined in IOUtil.c */
+
+jint fdval(JNIEnv *env, jobject fdo);
+
+jint convertReturnVal(JNIEnv *env, jint n, jboolean reading);
+jlong convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading);
+
+
+/* Defined in Net.c */
+
+jint handleSocketError(JNIEnv *env, jint errorValue);
diff --git a/ojluni/src/main/native/sun_misc_NativeSignalHandler.h b/ojluni/src/main/native/sun_misc_NativeSignalHandler.h
new file mode 100755
index 0000000..266c578
--- /dev/null
+++ b/ojluni/src/main/native/sun_misc_NativeSignalHandler.h
@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_misc_NativeSignalHandler */
+
+#ifndef _Included_sun_misc_NativeSignalHandler
+#define _Included_sun_misc_NativeSignalHandler
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_misc_NativeSignalHandler
+ * Method: handle0
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_NativeSignalHandler_handle0
+ (JNIEnv *, jclass, jint, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_misc_Signal.h b/ojluni/src/main/native/sun_misc_Signal.h
new file mode 100755
index 0000000..7196773
--- /dev/null
+++ b/ojluni/src/main/native/sun_misc_Signal.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_misc_Signal */
+
+#ifndef _Included_sun_misc_Signal
+#define _Included_sun_misc_Signal
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_misc_Signal
+ * Method: findSignal
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Signal_findSignal
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: sun_misc_Signal
+ * Method: handle0
+ * Signature: (IJ)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Signal_handle0
+ (JNIEnv *, jclass, jint, jlong);
+
+/*
+ * Class: sun_misc_Signal
+ * Method: raise0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Signal_raise0
+ (JNIEnv *, jclass, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_net_spi_DefaultProxySelector.h b/ojluni/src/main/native/sun_net_spi_DefaultProxySelector.h
new file mode 100755
index 0000000..eb1d0b9
--- /dev/null
+++ b/ojluni/src/main/native/sun_net_spi_DefaultProxySelector.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_net_spi_DefaultProxySelector */
+
+#ifndef _Included_sun_net_spi_DefaultProxySelector
+#define _Included_sun_net_spi_DefaultProxySelector
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: init
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_net_spi_DefaultProxySelector_init
+ (JNIEnv *, jclass);
+
+/*
+ * Class: sun_net_spi_DefaultProxySelector
+ * Method: getSystemProxy
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;
+ */
+JNIEXPORT jobject JNICALL Java_sun_net_spi_DefaultProxySelector_getSystemProxy
+ (JNIEnv *, jobject, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_FileChannelImpl.h b/ojluni/src/main/native/sun_nio_ch_FileChannelImpl.h
new file mode 100755
index 0000000..a8a053c
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_FileChannelImpl.h
@@ -0,0 +1,63 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_FileChannelImpl */
+
+#ifndef _Included_sun_nio_ch_FileChannelImpl
+#define _Included_sun_nio_ch_FileChannelImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef sun_nio_ch_FileChannelImpl_MAPPED_TRANSFER_SIZE
+#define sun_nio_ch_FileChannelImpl_MAPPED_TRANSFER_SIZE 8388608LL
+#undef sun_nio_ch_FileChannelImpl_TRANSFER_SIZE
+#define sun_nio_ch_FileChannelImpl_TRANSFER_SIZE 8192L
+#undef sun_nio_ch_FileChannelImpl_MAP_RO
+#define sun_nio_ch_FileChannelImpl_MAP_RO 0L
+#undef sun_nio_ch_FileChannelImpl_MAP_RW
+#define sun_nio_ch_FileChannelImpl_MAP_RW 1L
+#undef sun_nio_ch_FileChannelImpl_MAP_PV
+#define sun_nio_ch_FileChannelImpl_MAP_PV 2L
+/*
+ * Class: sun_nio_ch_FileChannelImpl
+ * Method: map0
+ * Signature: (IJJ)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_map0
+ (JNIEnv *, jobject, jint, jlong, jlong);
+
+/*
+ * Class: sun_nio_ch_FileChannelImpl
+ * Method: unmap0
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileChannelImpl_unmap0
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: sun_nio_ch_FileChannelImpl
+ * Method: transferTo0
+ * Signature: (IJJI)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_transferTo0
+ (JNIEnv *, jobject, jint, jlong, jlong, jint);
+
+/*
+ * Class: sun_nio_ch_FileChannelImpl
+ * Method: position0
+ * Signature: (Ljava/io/FileDescriptor;J)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_position0
+ (JNIEnv *, jobject, jobject, jlong);
+
+/*
+ * Class: sun_nio_ch_FileChannelImpl
+ * Method: initIDs
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_FileDispatcherImpl.h b/ojluni/src/main/native/sun_nio_ch_FileDispatcherImpl.h
new file mode 100755
index 0000000..df42fc1
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_FileDispatcherImpl.h
@@ -0,0 +1,141 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_FileDispatcherImpl */
+
+#ifndef _Included_sun_nio_ch_FileDispatcherImpl
+#define _Included_sun_nio_ch_FileDispatcherImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef sun_nio_ch_FileDispatcherImpl_NO_LOCK
+#define sun_nio_ch_FileDispatcherImpl_NO_LOCK -1L
+#undef sun_nio_ch_FileDispatcherImpl_LOCKED
+#define sun_nio_ch_FileDispatcherImpl_LOCKED 0L
+#undef sun_nio_ch_FileDispatcherImpl_RET_EX_LOCK
+#define sun_nio_ch_FileDispatcherImpl_RET_EX_LOCK 1L
+#undef sun_nio_ch_FileDispatcherImpl_INTERRUPTED
+#define sun_nio_ch_FileDispatcherImpl_INTERRUPTED 2L
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: read0
+ * Signature: (Ljava/io/FileDescriptor;JI)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_read0
+ (JNIEnv *, jclass, jobject, jlong, jint);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: pread0
+ * Signature: (Ljava/io/FileDescriptor;JIJ)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_pread0
+ (JNIEnv *, jclass, jobject, jlong, jint, jlong);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: readv0
+ * Signature: (Ljava/io/FileDescriptor;JI)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_readv0
+ (JNIEnv *, jclass, jobject, jlong, jint);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: write0
+ * Signature: (Ljava/io/FileDescriptor;JI)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_write0
+ (JNIEnv *, jclass, jobject, jlong, jint);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: pwrite0
+ * Signature: (Ljava/io/FileDescriptor;JIJ)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_pwrite0
+ (JNIEnv *, jclass, jobject, jlong, jint, jlong);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: writev0
+ * Signature: (Ljava/io/FileDescriptor;JI)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_writev0
+ (JNIEnv *, jclass, jobject, jlong, jint);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: force0
+ * Signature: (Ljava/io/FileDescriptor;Z)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_force0
+ (JNIEnv *, jclass, jobject, jboolean);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: truncate0
+ * Signature: (Ljava/io/FileDescriptor;J)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_truncate0
+ (JNIEnv *, jclass, jobject, jlong);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: size0
+ * Signature: (Ljava/io/FileDescriptor;)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileDispatcherImpl_size0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: lock0
+ * Signature: (Ljava/io/FileDescriptor;ZJJZ)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_FileDispatcherImpl_lock0
+ (JNIEnv *, jclass, jobject, jboolean, jlong, jlong, jboolean);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: release0
+ * Signature: (Ljava/io/FileDescriptor;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_release0
+ (JNIEnv *, jclass, jobject, jlong, jlong);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: close0
+ * Signature: (Ljava/io/FileDescriptor;)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_close0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: preClose0
+ * Signature: (Ljava/io/FileDescriptor;)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_preClose0
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: closeIntFD
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_closeIntFD
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: sun_nio_ch_FileDispatcherImpl
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileDispatcherImpl_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_FileKey.h b/ojluni/src/main/native/sun_nio_ch_FileKey.h
new file mode 100755
index 0000000..58f0659
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_FileKey.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_FileKey */
+
+#ifndef _Included_sun_nio_ch_FileKey
+#define _Included_sun_nio_ch_FileKey
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_nio_ch_FileKey
+ * Method: init
+ * Signature: (Ljava/io/FileDescriptor;)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileKey_init
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: sun_nio_ch_FileKey
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_FileKey_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_IOStatus.h b/ojluni/src/main/native/sun_nio_ch_IOStatus.h
new file mode 100755
index 0000000..0c2a02a
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_IOStatus.h
@@ -0,0 +1,25 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_IOStatus */
+
+#ifndef _Included_sun_nio_ch_IOStatus
+#define _Included_sun_nio_ch_IOStatus
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef sun_nio_ch_IOStatus_EOF
+#define sun_nio_ch_IOStatus_EOF -1L
+#undef sun_nio_ch_IOStatus_UNAVAILABLE
+#define sun_nio_ch_IOStatus_UNAVAILABLE -2L
+#undef sun_nio_ch_IOStatus_INTERRUPTED
+#define sun_nio_ch_IOStatus_INTERRUPTED -3L
+#undef sun_nio_ch_IOStatus_UNSUPPORTED
+#define sun_nio_ch_IOStatus_UNSUPPORTED -4L
+#undef sun_nio_ch_IOStatus_THROWN
+#define sun_nio_ch_IOStatus_THROWN -5L
+#undef sun_nio_ch_IOStatus_UNSUPPORTED_CASE
+#define sun_nio_ch_IOStatus_UNSUPPORTED_CASE -6L
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_IOUtil.h b/ojluni/src/main/native/sun_nio_ch_IOUtil.h
new file mode 100755
index 0000000..9eb2c99
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_IOUtil.h
@@ -0,0 +1,85 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_IOUtil */
+
+#ifndef _Included_sun_nio_ch_IOUtil
+#define _Included_sun_nio_ch_IOUtil
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: randomBytes
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_nio_ch_IOUtil_randomBytes
+ (JNIEnv *, jclass, jbyteArray);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: makePipe
+ * Signature: (Z)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_IOUtil_makePipe
+ (JNIEnv *, jclass, jboolean);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: drain
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_nio_ch_IOUtil_drain
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: configureBlocking
+ * Signature: (Ljava/io/FileDescriptor;Z)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_IOUtil_configureBlocking
+ (JNIEnv *, jclass, jobject, jboolean);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: fdVal
+ * Signature: (Ljava/io/FileDescriptor;)I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_IOUtil_fdVal
+ (JNIEnv *, jclass, jobject);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: setfdVal
+ * Signature: (Ljava/io/FileDescriptor;I)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_IOUtil_setfdVal
+ (JNIEnv *, jclass, jobject, jint);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: iovMax
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_IOUtil_iovMax
+ (JNIEnv *, jclass);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: fdLimit
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_sun_nio_ch_IOUtil_fdLimit
+ (JNIEnv *, jclass);
+
+/*
+ * Class: sun_nio_ch_IOUtil
+ * Method: initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_IOUtil_initIDs
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/sun_nio_ch_NativeThread.h b/ojluni/src/main/native/sun_nio_ch_NativeThread.h
new file mode 100755
index 0000000..00d16c0
--- /dev/null
+++ b/ojluni/src/main/native/sun_nio_ch_NativeThread.h
@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class sun_nio_ch_NativeThread */
+
+#ifndef _Included_sun_nio_ch_NativeThread
+#define _Included_sun_nio_ch_NativeThread
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: sun_nio_ch_NativeThread
+ * Method: current
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_sun_nio_ch_NativeThread_current
+ (JNIEnv *, jclass);
+
+/*
+ * Class: sun_nio_ch_NativeThread
+ * Method: signal
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_NativeThread_signal
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: sun_nio_ch_NativeThread
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_nio_ch_NativeThread_init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/ojluni/src/main/native/zip_util.c b/ojluni/src/main/native/zip_util.c
new file mode 100755
index 0000000..00c231b
--- /dev/null
+++ b/ojluni/src/main/native/zip_util.c
@@ -0,0 +1,1462 @@
+/*
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Support for reading ZIP/JAR files.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+#include "io_util.h"
+#include "io_util_md.h"
+#include "zip_util.h"
+#include <zlib.h>
+
+#ifdef _ALLBSD_SOURCE
+#define off64_t off_t
+#define mmap64 mmap
+#endif
+
+/* USE_MMAP means mmap the CEN & ENDHDR part of the zip file. */
+#ifdef USE_MMAP
+#include <sys/mman.h>
+#endif
+
+#define MAXREFS 0xFFFF /* max number of open zip file references */
+
+#define MCREATE() JVM_RawMonitorCreate()
+#define MLOCK(lock) JVM_RawMonitorEnter(lock)
+#define MUNLOCK(lock) JVM_RawMonitorExit(lock)
+#define MDESTROY(lock) JVM_RawMonitorDestroy(lock)
+
+#define CENSIZE(cen) (CENHDR + CENNAM(cen) + CENEXT(cen) + CENCOM(cen))
+
+static jzfile *zfiles = 0; /* currently open zip files */
+static void *zfiles_lock = 0;
+
+static void freeCEN(jzfile *);
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+static jint INITIAL_META_COUNT = 2; /* initial number of entries in meta name array */
+
+/*
+ * The ZFILE_* functions exist to provide some platform-independence with
+ * respect to file access needs.
+ */
+
+/*
+ * Opens the named file for reading, returning a ZFILE.
+ *
+ * Compare this with winFileHandleOpen in windows/native/java/io/io_util_md.c.
+ * This function does not take JNIEnv* and uses CreateFile (instead of
+ * CreateFileW). The expectation is that this function will be called only
+ * from ZIP_Open_Generic, which in turn is used by the JVM, where we do not
+ * need to concern ourselves with wide chars.
+ */
+static ZFILE
+ZFILE_Open(const char *fname, int flags) {
+#ifdef WIN32
+ const DWORD access =
+ (flags & O_RDWR) ? (GENERIC_WRITE | GENERIC_READ) :
+ (flags & O_WRONLY) ? GENERIC_WRITE :
+ GENERIC_READ;
+ const DWORD sharing =
+ FILE_SHARE_READ | FILE_SHARE_WRITE;
+ const DWORD disposition =
+ /* Note: O_TRUNC overrides O_CREAT */
+ (flags & O_TRUNC) ? CREATE_ALWAYS :
+ (flags & O_CREAT) ? OPEN_ALWAYS :
+ OPEN_EXISTING;
+ const DWORD maybeWriteThrough =
+ (flags & (O_SYNC | O_DSYNC)) ?
+ FILE_FLAG_WRITE_THROUGH :
+ FILE_ATTRIBUTE_NORMAL;
+ const DWORD maybeDeleteOnClose =
+ (flags & O_TEMPORARY) ?
+ FILE_FLAG_DELETE_ON_CLOSE :
+ FILE_ATTRIBUTE_NORMAL;
+ const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
+
+ return (jlong) CreateFile(
+ fname, /* Wide char path name */
+ access, /* Read and/or write permission */
+ sharing, /* File sharing flags */
+ NULL, /* Security attributes */
+ disposition, /* creation disposition */
+ flagsAndAttributes, /* flags and attributes */
+ NULL);
+#else
+ return JVM_Open(fname, flags, 0);
+#endif
+}
+
+/*
+ * The io_util_md.h files do not provide IO_CLOSE, hence we use platform
+ * specifics.
+ */
+static void
+ZFILE_Close(ZFILE zfd) {
+#ifdef WIN32
+ CloseHandle((HANDLE) zfd);
+#else
+ JVM_Close(zfd);
+#endif
+}
+
+static int
+ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
+#ifdef WIN32
+ return (int) IO_Read(zfd, buf, nbytes);
+#else
+ /*
+ * Calling JVM_Read will return JVM_IO_INTR when Thread.interrupt is called
+ * only on Solaris. Continue reading jar file in this case is the best
+ * thing to do since zip file reading is relatively fast and it is very onerous
+ * for a interrupted thread to deal with this kind of hidden I/O. However, handling
+ * JVM_IO_INTR is tricky and could cause undesired side effect. So we decided
+ * to simply call "read" on Solaris/Linux. See details in bug 6304463.
+ */
+ return read(zfd, buf, nbytes);
+#endif
+}
+
+/*
+ * Initialize zip file support. Return 0 if successful otherwise -1
+ * if could not be initialized.
+ */
+static jint
+InitializeZip()
+{
+ static jboolean inited = JNI_FALSE;
+
+ // Initialize errno to 0. It may be set later (e.g. during memory
+ // allocation) but we can disregard previous values.
+ errno = 0;
+
+ if (inited)
+ return 0;
+ zfiles_lock = MCREATE();
+ if (zfiles_lock == 0) {
+ return -1;
+ }
+ inited = JNI_TRUE;
+
+ return 0;
+}
+
+/*
+ * Reads len bytes of data into buf.
+ * Returns 0 if all bytes could be read, otherwise returns -1.
+ */
+static int
+readFully(ZFILE zfd, void *buf, jlong len) {
+ char *bp = (char *) buf;
+
+ while (len > 0) {
+ jlong limit = ((((jlong) 1) << 31) - 1);
+ jint count = (len < limit) ?
+ (jint) len :
+ (jint) limit;
+ jint n = ZFILE_read(zfd, bp, count);
+ if (n > 0) {
+ bp += n;
+ len -= n;
+ } else if (n == JVM_IO_ERR && errno == EINTR) {
+ /* Retry after EINTR (interrupted by signal).
+ We depend on the fact that JVM_IO_ERR == -1. */
+ continue;
+ } else { /* EOF or IO error */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Reads len bytes of data from the specified offset into buf.
+ * Returns 0 if all bytes could be read, otherwise returns -1.
+ */
+static int
+readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset)
+{
+ if (IO_Lseek(zfd, offset, SEEK_SET) == -1) {
+ return -1; /* lseek failure. */
+ }
+
+ return readFully(zfd, buf, len);
+}
+
+/*
+ * Allocates a new zip file object for the specified file name.
+ * Returns the zip file object or NULL if not enough memory.
+ */
+static jzfile *
+allocZip(const char *name)
+{
+ jzfile *zip;
+ if (((zip = calloc(1, sizeof(jzfile))) != NULL) &&
+ ((zip->name = strdup(name)) != NULL) &&
+ ((zip->lock = MCREATE()) != NULL)) {
+ zip->zfd = -1;
+ return zip;
+ }
+
+ if (zip != NULL) {
+ free(zip->name);
+ free(zip);
+ }
+ return NULL;
+}
+
+/*
+ * Frees all native resources owned by the specified zip file object.
+ */
+static void
+freeZip(jzfile *zip)
+{
+ /* First free any cached jzentry */
+ ZIP_FreeEntry(zip,0);
+ if (zip->lock != NULL) MDESTROY(zip->lock);
+ free(zip->name);
+ freeCEN(zip);
+
+#ifdef USE_MMAP
+ if (zip->usemmap) {
+ if (zip->maddr != NULL)
+ munmap((char *)zip->maddr, zip->mlen);
+ } else
+#endif
+ {
+ free(zip->cencache.data);
+ }
+ if (zip->comment != NULL)
+ free(zip->comment);
+ if (zip->zfd != -1) ZFILE_Close(zip->zfd);
+ free(zip);
+}
+
+/* The END header is followed by a variable length comment of size < 64k. */
+static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
+
+#define READBLOCKSZ 128
+
+static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
+ /* ENDSIG matched, however the size of file comment in it does not
+ match the real size. One "common" cause for this problem is some
+ "extra" bytes are padded at the end of the zipfile.
+ Let's do some extra verification, we don't care about the performance
+ in this situation.
+ */
+ jlong cenpos = endpos - ENDSIZ(endbuf);
+ jlong locpos = cenpos - ENDOFF(endbuf);
+ char buf[4];
+ return (cenpos >= 0 &&
+ locpos >= 0 &&
+ readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 &&
+ GETSIG(buf) == CENSIG &&
+ readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 &&
+ GETSIG(buf) == LOCSIG);
+}
+
+/*
+ * Searches for end of central directory (END) header. The contents of
+ * the END header will be read and placed in endbuf. Returns the file
+ * position of the END header, otherwise returns -1 if the END header
+ * was not found or an error occurred.
+ */
+static jlong
+findEND(jzfile *zip, void *endbuf)
+{
+ char buf[READBLOCKSZ];
+ jlong pos;
+ const jlong len = zip->len;
+ const ZFILE zfd = zip->zfd;
+ const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
+ const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
+ jint clen;
+
+ for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
+
+ int i;
+ jlong off = 0;
+ if (pos < 0) {
+ /* Pretend there are some NUL bytes before start of file */
+ off = -pos;
+ memset(buf, '\0', (size_t)off);
+ }
+
+ if (readFullyAt(zfd, buf + off, sizeof(buf) - off,
+ pos + off) == -1) {
+ return -1; /* System error */
+ }
+
+ /* Now scan the block backwards for END header signature */
+ for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
+ if (buf[i+0] == 'P' &&
+ buf[i+1] == 'K' &&
+ buf[i+2] == '\005' &&
+ buf[i+3] == '\006' &&
+ ((pos + i + ENDHDR + ENDCOM(buf + i) == len)
+ || verifyEND(zip, pos + i, buf + i))) {
+ /* Found END header */
+ memcpy(endbuf, buf + i, ENDHDR);
+
+ clen = ENDCOM(endbuf);
+ if (clen != 0) {
+ zip->comment = malloc(clen + 1);
+ if (zip->comment == NULL) {
+ return -1;
+ }
+ if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR)
+ == -1) {
+ free(zip->comment);
+ zip->comment = NULL;
+ return -1;
+ }
+ zip->comment[clen] = '\0';
+ zip->clen = clen;
+ }
+ return pos + i;
+ }
+ }
+ }
+
+ return -1; /* END header not found */
+}
+
+/*
+ * Searches for the ZIP64 end of central directory (END) header. The
+ * contents of the ZIP64 END header will be read and placed in end64buf.
+ * Returns the file position of the ZIP64 END header, otherwise returns
+ * -1 if the END header was not found or an error occurred.
+ *
+ * The ZIP format specifies the "position" of each related record as
+ * ...
+ * [central directory]
+ * [zip64 end of central directory record]
+ * [zip64 end of central directory locator]
+ * [end of central directory record]
+ *
+ * The offset of zip64 end locator can be calculated from endpos as
+ * "endpos - ZIP64_LOCHDR".
+ * The "offset" of zip64 end record is stored in zip64 end locator.
+ */
+static jlong
+findEND64(jzfile *zip, void *end64buf, jlong endpos)
+{
+ char loc64[ZIP64_LOCHDR];
+ jlong end64pos;
+ if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR, endpos - ZIP64_LOCHDR) == -1) {
+ return -1; // end64 locator not found
+ }
+ end64pos = ZIP64_LOCOFF(loc64);
+ if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR, end64pos) == -1) {
+ return -1; // end64 record not found
+ }
+ return end64pos;
+}
+
+/*
+ * Returns a hash code value for a C-style NUL-terminated string.
+ */
+static unsigned int
+hash(const char *s)
+{
+ int h = 0;
+ while (*s != '\0')
+ h = 31*h + *s++;
+ return h;
+}
+
+/*
+ * Returns a hash code value for a string of a specified length.
+ */
+static unsigned int
+hashN(const char *s, int length)
+{
+ int h = 0;
+ while (length-- > 0)
+ h = 31*h + *s++;
+ return h;
+}
+
+static unsigned int
+hash_append(unsigned int hash, char c)
+{
+ return ((int)hash)*31 + c;
+}
+
+/*
+ * Returns true if the specified entry's name begins with the string
+ * "META-INF/" irrespective of case.
+ */
+static int
+isMetaName(const char *name, int length)
+{
+ const char *s;
+ if (length < (int)sizeof("META-INF/") - 1)
+ return 0;
+ for (s = "META-INF/"; *s != '\0'; s++) {
+ char c = *name++;
+ // Avoid toupper; it's locale-dependent
+ if (c >= 'a' && c <= 'z') c += 'A' - 'a';
+ if (*s != c)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Increases the capacity of zip->metanames.
+ * Returns non-zero in case of allocation error.
+ */
+static int
+growMetaNames(jzfile *zip)
+{
+ jint i;
+ /* double the meta names array */
+ const jint new_metacount = zip->metacount << 1;
+ zip->metanames =
+ realloc(zip->metanames, new_metacount * sizeof(zip->metanames[0]));
+ if (zip->metanames == NULL) return -1;
+ for (i = zip->metacount; i < new_metacount; i++)
+ zip->metanames[i] = NULL;
+ zip->metacurrent = zip->metacount;
+ zip->metacount = new_metacount;
+ return 0;
+}
+
+/*
+ * Adds name to zip->metanames.
+ * Returns non-zero in case of allocation error.
+ */
+static int
+addMetaName(jzfile *zip, const char *name, int length)
+{
+ jint i;
+ if (zip->metanames == NULL) {
+ zip->metacount = INITIAL_META_COUNT;
+ zip->metanames = calloc(zip->metacount, sizeof(zip->metanames[0]));
+ if (zip->metanames == NULL) return -1;
+ zip->metacurrent = 0;
+ }
+
+ i = zip->metacurrent;
+
+ /* current meta name array isn't full yet. */
+ if (i < zip->metacount) {
+ zip->metanames[i] = (char *) malloc(length+1);
+ if (zip->metanames[i] == NULL) return -1;
+ memcpy(zip->metanames[i], name, length);
+ zip->metanames[i][length] = '\0';
+ zip->metacurrent++;
+ return 0;
+ }
+
+ /* No free entries in zip->metanames? */
+ if (growMetaNames(zip) != 0) return -1;
+ return addMetaName(zip, name, length);
+}
+
+static void
+freeMetaNames(jzfile *zip)
+{
+ if (zip->metanames) {
+ jint i;
+ for (i = 0; i < zip->metacount; i++)
+ free(zip->metanames[i]);
+ free(zip->metanames);
+ zip->metanames = NULL;
+ }
+}
+
+/* Free Zip data allocated by readCEN() */
+static void
+freeCEN(jzfile *zip)
+{
+ free(zip->entries); zip->entries = NULL;
+ free(zip->table); zip->table = NULL;
+ freeMetaNames(zip);
+}
+
+/*
+ * Counts the number of CEN headers in a central directory extending
+ * from BEG to END. Might return a bogus answer if the zip file is
+ * corrupt, but will not crash.
+ */
+static jint
+countCENHeaders(unsigned char *beg, unsigned char *end)
+{
+ jint count = 0;
+ ptrdiff_t i;
+ for (i = 0; i + CENHDR <= end - beg; i += CENSIZE(beg + i))
+ count++;
+ return count;
+}
+
+#define ZIP_FORMAT_ERROR(message) \
+if (1) { zip->msg = message; goto Catch; } else ((void)0)
+
+/*
+ * Reads zip file central directory. Returns the file position of first
+ * CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL
+ * then the error was a zip format error and zip->msg has the error text.
+ * Always pass in -1 for knownTotal; it's used for a recursive call.
+ */
+static jlong
+readCEN(jzfile *zip, jint knownTotal)
+{
+ /* Following are unsigned 32-bit */
+ jlong endpos, end64pos, cenpos, cenlen, cenoff;
+ /* Following are unsigned 16-bit */
+ jint total, tablelen, i, j;
+ unsigned char *cenbuf = NULL;
+ unsigned char *cenend;
+ unsigned char *cp;
+#ifdef USE_MMAP
+ static jlong pagesize;
+ jlong offset;
+#endif
+ unsigned char endbuf[ENDHDR];
+ jint endhdrlen = ENDHDR;
+ jzcell *entries;
+ jint *table;
+
+ /* Clear previous zip error */
+ zip->msg = NULL;
+ /* Get position of END header */
+ if ((endpos = findEND(zip, endbuf)) == -1)
+ return -1; /* no END header or system error */
+
+ if (endpos == 0) return 0; /* only END header present */
+
+ freeCEN(zip);
+ /* Get position and length of central directory */
+ cenlen = ENDSIZ(endbuf);
+ cenoff = ENDOFF(endbuf);
+ total = ENDTOT(endbuf);
+ if (cenlen == ZIP64_MAGICVAL || cenoff == ZIP64_MAGICVAL ||
+ total == ZIP64_MAGICCOUNT) {
+ unsigned char end64buf[ZIP64_ENDHDR];
+ if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
+ cenlen = ZIP64_ENDSIZ(end64buf);
+ cenoff = ZIP64_ENDOFF(end64buf);
+ total = (jint)ZIP64_ENDTOT(end64buf);
+ endpos = end64pos;
+ endhdrlen = ZIP64_ENDHDR;
+ }
+ }
+
+ if (cenlen > endpos)
+ ZIP_FORMAT_ERROR("invalid END header (bad central directory size)");
+ cenpos = endpos - cenlen;
+
+ /* Get position of first local file (LOC) header, taking into
+ * account that there may be a stub prefixed to the zip file. */
+ zip->locpos = cenpos - cenoff;
+ if (zip->locpos < 0)
+ ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)");
+
+#ifdef USE_MMAP
+ if (zip->usemmap) {
+ /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
+ * read the jar file contents. However, this greatly increased the perceived
+ * footprint numbers because the mmap'ed pages were adding into the totals shown
+ * by 'ps' and 'top'. We switched to mmaping only the central directory of jar
+ * file while calling 'read' to read the rest of jar file. Here are a list of
+ * reasons apart from above of why we are doing so:
+ * 1. Greatly reduces mmap overhead after startup complete;
+ * 2. Avoids dual path code maintainance;
+ * 3. Greatly reduces risk of address space (not virtual memory) exhaustion.
+ */
+ if (pagesize == 0) {
+ pagesize = (jlong)sysconf(_SC_PAGESIZE);
+ if (pagesize == 0) goto Catch;
+ }
+ if (cenpos > pagesize) {
+ offset = cenpos & ~(pagesize - 1);
+ } else {
+ offset = 0;
+ }
+ /* When we are not calling recursively, knownTotal is -1. */
+ if (knownTotal == -1) {
+ void* mappedAddr;
+ /* Mmap the CEN and END part only. We have to figure
+ out the page size in order to make offset to be multiples of
+ page size.
+ */
+ zip->mlen = cenpos - offset + cenlen + endhdrlen;
+ zip->offset = offset;
+ mappedAddr = mmap64(0, zip->mlen, PROT_READ, MAP_SHARED, zip->zfd, (off64_t) offset);
+ zip->maddr = (mappedAddr == (void*) MAP_FAILED) ? NULL :
+ (unsigned char*)mappedAddr;
+
+ if (zip->maddr == NULL) {
+ jio_fprintf(stderr, "mmap failed for CEN and END part of zip file\n");
+ goto Catch;
+ }
+ }
+ cenbuf = zip->maddr + cenpos - offset;
+ } else
+#endif
+ {
+ if ((cenbuf = malloc((size_t) cenlen)) == NULL ||
+ (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1))
+ goto Catch;
+ }
+
+ cenend = cenbuf + cenlen;
+
+ /* Initialize zip file data structures based on the total number
+ * of central directory entries as stored in ENDTOT. Since this
+ * is a 2-byte field, but we (and other zip implementations)
+ * support approx. 2**31 entries, we do not trust ENDTOT, but
+ * treat it only as a strong hint. When we call ourselves
+ * recursively, knownTotal will have the "true" value.
+ *
+ * Keep this path alive even with the Zip64 END support added, just
+ * for zip files that have more than 0xffff entries but don't have
+ * the Zip64 enabled.
+ */
+ total = (knownTotal != -1) ? knownTotal : total;
+ entries = zip->entries = calloc(total, sizeof(entries[0]));
+ tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
+ table = zip->table = malloc(tablelen * sizeof(table[0]));
+ if (entries == NULL || table == NULL) goto Catch;
+ for (j = 0; j < tablelen; j++)
+ table[j] = ZIP_ENDCHAIN;
+
+ /* Iterate through the entries in the central directory */
+ for (i = 0, cp = cenbuf; cp <= cenend - CENHDR; i++, cp += CENSIZE(cp)) {
+ /* Following are unsigned 16-bit */
+ jint method, nlen;
+ unsigned int hsh;
+
+ if (i >= total) {
+ /* This will only happen if the zip file has an incorrect
+ * ENDTOT field, which usually means it contains more than
+ * 65535 entries. */
+ cenpos = readCEN(zip, countCENHeaders(cenbuf, cenend));
+ goto Finally;
+ }
+
+ method = CENHOW(cp);
+ nlen = CENNAM(cp);
+
+ if (GETSIG(cp) != CENSIG)
+ ZIP_FORMAT_ERROR("invalid CEN header (bad signature)");
+ if (CENFLG(cp) & 1)
+ ZIP_FORMAT_ERROR("invalid CEN header (encrypted entry)");
+ if (method != STORED && method != DEFLATED)
+ ZIP_FORMAT_ERROR("invalid CEN header (bad compression method)");
+ if (cp + CENHDR + nlen > cenend)
+ ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
+
+ /* if the entry is metadata add it to our metadata names */
+ if (isMetaName((char *)cp+CENHDR, nlen))
+ if (addMetaName(zip, (char *)cp+CENHDR, nlen) != 0)
+ goto Catch;
+
+ /* Record the CEN offset and the name hash in our hash cell. */
+ entries[i].cenpos = cenpos + (cp - cenbuf);
+ entries[i].hash = hashN((char *)cp+CENHDR, nlen);
+
+ /* Add the entry to the hash table */
+ hsh = entries[i].hash % tablelen;
+ entries[i].next = table[hsh];
+ table[hsh] = i;
+ }
+ if (cp != cenend)
+ ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
+
+ zip->total = i;
+ goto Finally;
+
+ Catch:
+ freeCEN(zip);
+ cenpos = -1;
+
+ Finally:
+#ifdef USE_MMAP
+ if (!zip->usemmap)
+#endif
+ free(cenbuf);
+
+ return cenpos;
+}
+
+/*
+ * Opens a zip file with the specified mode. Returns the jzfile object
+ * or NULL if an error occurred. If a zip error occurred then *pmsg will
+ * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
+ * set to NULL. Caller is responsible to free the error message.
+ */
+jzfile *
+ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
+{
+ jzfile *zip = NULL;
+
+ /* Clear zip error message */
+ if (pmsg != 0) {
+ *pmsg = NULL;
+ }
+
+ zip = ZIP_Get_From_Cache(name, pmsg, lastModified);
+
+ if (zip == NULL && *pmsg == NULL) {
+ ZFILE zfd = ZFILE_Open(name, mode);
+ zip = ZIP_Put_In_Cache(name, zfd, pmsg, lastModified);
+ }
+ return zip;
+}
+
+/*
+ * Returns the jzfile corresponding to the given file name from the cache of
+ * zip files, or NULL if the file is not in the cache. If the name is longer
+ * than PATH_MAX or a zip error occurred then *pmsg will be set to the error
+ * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller
+ * is responsible to free the error message.
+ */
+jzfile *
+ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified)
+{
+ char buf[PATH_MAX];
+ jzfile *zip;
+
+ if (InitializeZip()) {
+ return NULL;
+ }
+
+ /* Clear zip error message */
+ if (pmsg != 0) {
+ *pmsg = NULL;
+ }
+
+ if (strlen(name) >= PATH_MAX) {
+ if (pmsg) {
+ *pmsg = strdup("zip file name too long");
+ }
+ return NULL;
+ }
+ strcpy(buf, name);
+ JVM_NativePath(buf);
+ name = buf;
+
+ MLOCK(zfiles_lock);
+ for (zip = zfiles; zip != NULL; zip = zip->next) {
+ if (strcmp(name, zip->name) == 0
+ && (zip->lastModified == lastModified || zip->lastModified == 0)
+ && zip->refs < MAXREFS) {
+ zip->refs++;
+ break;
+ }
+ }
+ MUNLOCK(zfiles_lock);
+ return zip;
+}
+
+/*
+ * Reads data from the given file descriptor to create a jzfile, puts the
+ * jzfile in a cache, and returns that jzfile. Returns NULL in case of error.
+ * If a zip error occurs, then *pmsg will be set to the error message text if
+ * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to
+ * free the error message.
+ */
+
+jzfile *
+ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified)
+{
+ return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE);
+}
+
+jzfile *
+ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified,
+ jboolean usemmap)
+{
+ char errbuf[256];
+ jlong len;
+ jzfile *zip;
+
+ if ((zip = allocZip(name)) == NULL) {
+ return NULL;
+ }
+
+#ifdef USE_MMAP
+ zip->usemmap = usemmap;
+#endif
+ zip->refs = 1;
+ zip->lastModified = lastModified;
+
+ if (zfd == -1) {
+ if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
+ *pmsg = strdup(errbuf);
+ freeZip(zip);
+ return NULL;
+ }
+
+ // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
+ if (readFully(zfd, errbuf, 4) != -1) { // errors will be handled later
+ if (GETSIG(errbuf) == LOCSIG)
+ zip->locsig = JNI_TRUE;
+ else
+ zip->locsig = JNI_FALSE;
+ }
+
+ len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
+ if (len <= 0) {
+ if (len == 0) { /* zip file is empty */
+ if (pmsg) {
+ *pmsg = strdup("zip file is empty");
+ }
+ } else { /* error */
+ if (pmsg && JVM_GetLastErrorString(errbuf, sizeof(errbuf)) > 0)
+ *pmsg = strdup(errbuf);
+ }
+ ZFILE_Close(zfd);
+ freeZip(zip);
+ return NULL;
+ }
+
+ zip->zfd = zfd;
+ if (readCEN(zip, -1) < 0) {
+ /* An error occurred while trying to read the zip file */
+ if (pmsg != 0) {
+ /* Set the zip error message */
+ if (zip->msg != NULL)
+ *pmsg = strdup(zip->msg);
+ }
+ freeZip(zip);
+ return NULL;
+ }
+ MLOCK(zfiles_lock);
+ zip->next = zfiles;
+ zfiles = zip;
+ MUNLOCK(zfiles_lock);
+
+ return zip;
+}
+
+/*
+ * Opens a zip file for reading. Returns the jzfile object or NULL
+ * if an error occurred. If a zip error occurred then *msg will be
+ * set to the error message text if msg != 0. Otherwise, *msg will be
+ * set to NULL. Caller doesn't need to free the error message.
+ */
+jzfile * JNICALL
+ZIP_Open(const char *name, char **pmsg)
+{
+ jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
+ if (file == NULL && pmsg != NULL && *pmsg != NULL) {
+ free(*pmsg);
+ *pmsg = "Zip file open error";
+ }
+ return file;
+}
+
+/*
+ * Closes the specified zip file object.
+ */
+void JNICALL
+ZIP_Close(jzfile *zip)
+{
+ MLOCK(zfiles_lock);
+ if (--zip->refs > 0) {
+ /* Still more references so just return */
+ MUNLOCK(zfiles_lock);
+ return;
+ }
+ /* No other references so close the file and remove from list */
+ if (zfiles == zip) {
+ zfiles = zfiles->next;
+ } else {
+ jzfile *zp;
+ for (zp = zfiles; zp->next != 0; zp = zp->next) {
+ if (zp->next == zip) {
+ zp->next = zip->next;
+ break;
+ }
+ }
+ }
+ MUNLOCK(zfiles_lock);
+ freeZip(zip);
+ return;
+}
+
+/* Empirically, most CEN headers are smaller than this. */
+#define AMPLE_CEN_HEADER_SIZE 160
+
+/* A good buffer size when we want to read CEN headers sequentially. */
+#define CENCACHE_PAGESIZE 8192
+
+static char *
+readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
+{
+ jint censize;
+ ZFILE zfd = zip->zfd;
+ char *cen;
+ if (bufsize > zip->len - cenpos)
+ bufsize = (jint)(zip->len - cenpos);
+ if ((cen = malloc(bufsize)) == NULL) goto Catch;
+ if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch;
+ censize = CENSIZE(cen);
+ if (censize <= bufsize) return cen;
+ if ((cen = realloc(cen, censize)) == NULL) goto Catch;
+ if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
+ return cen;
+
+ Catch:
+ free(cen);
+ return NULL;
+}
+
+static char *
+sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
+{
+ cencache *cache = &zip->cencache;
+ char *cen;
+ if (cache->data != NULL
+ && (cenpos >= cache->pos)
+ && (cenpos + CENHDR <= cache->pos + CENCACHE_PAGESIZE))
+ {
+ cen = cache->data + cenpos - cache->pos;
+ if (cenpos + CENSIZE(cen) <= cache->pos + CENCACHE_PAGESIZE)
+ /* A cache hit */
+ return cen;
+ }
+
+ if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE)) == NULL)
+ return NULL;
+ free(cache->data);
+ cache->data = cen;
+ cache->pos = cenpos;
+ return cen;
+}
+
+typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
+
+/*
+ * Return a new initialized jzentry corresponding to a given hash cell.
+ * In case of error, returns NULL.
+ * We already sanity-checked all the CEN headers for ZIP format errors
+ * in readCEN(), so we don't check them again here.
+ * The ZIP lock should be held here.
+ */
+static jzentry *
+newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
+{
+ jlong locoff;
+ jint nlen, elen, clen;
+ jzentry *ze;
+ char *cen;
+
+ if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL) return NULL;
+ ze->name = NULL;
+ ze->extra = NULL;
+ ze->comment = NULL;
+
+#ifdef USE_MMAP
+ if (zip->usemmap) {
+ cen = (char*) zip->maddr + zc->cenpos - zip->offset;
+ } else
+#endif
+ {
+ if (accessHint == ACCESS_RANDOM)
+ cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE);
+ else
+ cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
+ if (cen == NULL) goto Catch;
+ }
+
+ nlen = CENNAM(cen);
+ elen = CENEXT(cen);
+ clen = CENCOM(cen);
+ ze->time = CENTIM(cen);
+ ze->size = CENLEN(cen);
+ ze->csize = (CENHOW(cen) == STORED) ? 0 : CENSIZ(cen);
+ ze->crc = CENCRC(cen);
+ locoff = CENOFF(cen);
+ ze->pos = -(zip->locpos + locoff);
+ ze->flag = CENFLG(cen);
+
+ if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
+ memcpy(ze->name, cen + CENHDR, nlen);
+ ze->name[nlen] = '\0';
+ if (elen > 0) {
+ char *extra = cen + CENHDR + nlen;
+
+ /* This entry has "extra" data */
+ if ((ze->extra = malloc(elen + 2)) == NULL) goto Catch;
+ ze->extra[0] = (unsigned char) elen;
+ ze->extra[1] = (unsigned char) (elen >> 8);
+ memcpy(ze->extra+2, extra, elen);
+ if (ze->csize == ZIP64_MAGICVAL || ze->size == ZIP64_MAGICVAL ||
+ locoff == ZIP64_MAGICVAL) {
+ jint off = 0;
+ while ((off + 4) < elen) { // spec: HeaderID+DataSize+Data
+ jint sz = SH(extra, off + 2);
+ if (SH(extra, off) == ZIP64_EXTID) {
+ off += 4;
+ if (ze->size == ZIP64_MAGICVAL) {
+ // if invalid zip64 extra fields, just skip
+ if (sz < 8 || (off + 8) > elen)
+ break;
+ ze->size = LL(extra, off);
+ sz -= 8;
+ off += 8;
+ }
+ if (ze->csize == ZIP64_MAGICVAL) {
+ if (sz < 8 || (off + 8) > elen)
+ break;
+ ze->csize = LL(extra, off);
+ sz -= 8;
+ off += 8;
+ }
+ if (locoff == ZIP64_MAGICVAL) {
+ if (sz < 8 || (off + 8) > elen)
+ break;
+ ze->pos = -(zip->locpos + LL(extra, off));
+ sz -= 8;
+ off += 8;
+ }
+ break;
+ }
+ off += (sz + 4);
+ }
+ }
+ }
+
+ if (clen > 0) {
+ /* This entry has a comment */
+ if ((ze->comment = malloc(clen + 1)) == NULL) goto Catch;
+ memcpy(ze->comment, cen + CENHDR + nlen + elen, clen);
+ ze->comment[clen] = '\0';
+ }
+ goto Finally;
+
+ Catch:
+ free(ze->name);
+ free(ze->extra);
+ free(ze->comment);
+ free(ze);
+ ze = NULL;
+
+ Finally:
+#ifdef USE_MMAP
+ if (!zip->usemmap)
+#endif
+ if (cen != NULL && accessHint == ACCESS_RANDOM) free(cen);
+ return ze;
+}
+
+/*
+ * Free the given jzentry.
+ * In fact we maintain a one-entry cache of the most recently used
+ * jzentry for each zip. This optimizes a common access pattern.
+ */
+
+void
+ZIP_FreeEntry(jzfile *jz, jzentry *ze)
+{
+ jzentry *last;
+ ZIP_Lock(jz);
+ last = jz->cache;
+ jz->cache = ze;
+ ZIP_Unlock(jz);
+ if (last != NULL) {
+ /* Free the previously cached jzentry */
+ free(last->name);
+ if (last->extra) free(last->extra);
+ if (last->comment) free(last->comment);
+ free(last);
+ }
+}
+
+/*
+ * Returns the zip entry corresponding to the specified name, or
+ * NULL if not found.
+ */
+jzentry *
+ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
+{
+ unsigned int hsh = hash(name);
+ jint idx;
+ jzentry *ze = 0;
+
+ ZIP_Lock(zip);
+ if (zip->total == 0) {
+ goto Finally;
+ }
+
+ idx = zip->table[hsh % zip->tablelen];
+
+ /*
+ * This while loop is an optimization where a double lookup
+ * for name and name+/ is being performed. The name char
+ * array has enough room at the end to try again with a
+ * slash appended if the first table lookup does not succeed.
+ */
+ while(1) {
+
+ /* Check the cached entry first */
+ ze = zip->cache;
+ if (ze && strcmp(ze->name,name) == 0) {
+ /* Cache hit! Remove and return the cached entry. */
+ zip->cache = 0;
+ ZIP_Unlock(zip);
+ return ze;
+ }
+ ze = 0;
+
+ /*
+ * Search down the target hash chain for a cell whose
+ * 32 bit hash matches the hashed name.
+ */
+ while (idx != ZIP_ENDCHAIN) {
+ jzcell *zc = &zip->entries[idx];
+
+ if (zc->hash == hsh) {
+ /*
+ * OK, we've found a ZIP entry whose 32 bit hashcode
+ * matches the name we're looking for. Try to read
+ * its entry information from the CEN. If the CEN
+ * name matches the name we're looking for, we're
+ * done.
+ * If the names don't match (which should be very rare)
+ * we keep searching.
+ */
+ ze = newEntry(zip, zc, ACCESS_RANDOM);
+ if (ze && strcmp(ze->name, name)==0) {
+ break;
+ }
+ if (ze != 0) {
+ /* We need to release the lock across the free call */
+ ZIP_Unlock(zip);
+ ZIP_FreeEntry(zip, ze);
+ ZIP_Lock(zip);
+ }
+ ze = 0;
+ }
+ idx = zc->next;
+ }
+
+ /* Entry found, return it */
+ if (ze != 0) {
+ break;
+ }
+
+ /* If no real length was passed in, we are done */
+ if (ulen == 0) {
+ break;
+ }
+
+ /* Slash is already there? */
+ if (name[ulen-1] == '/') {
+ break;
+ }
+
+ /* Add slash and try once more */
+ name[ulen] = '/';
+ name[ulen+1] = '\0';
+ hsh = hash_append(hsh, '/');
+ idx = zip->table[hsh % zip->tablelen];
+ ulen = 0;
+ }
+
+Finally:
+ ZIP_Unlock(zip);
+ return ze;
+}
+
+/*
+ * Returns the n'th (starting at zero) zip file entry, or NULL if the
+ * specified index was out of range.
+ */
+jzentry * JNICALL
+ZIP_GetNextEntry(jzfile *zip, jint n)
+{
+ jzentry *result;
+ if (n < 0 || n >= zip->total) {
+ return 0;
+ }
+ ZIP_Lock(zip);
+ result = newEntry(zip, &zip->entries[n], ACCESS_SEQUENTIAL);
+ ZIP_Unlock(zip);
+ return result;
+}
+
+/*
+ * Locks the specified zip file for reading.
+ */
+void
+ZIP_Lock(jzfile *zip)
+{
+ MLOCK(zip->lock);
+}
+
+/*
+ * Unlocks the specified zip file.
+ */
+void
+ZIP_Unlock(jzfile *zip)
+{
+ MUNLOCK(zip->lock);
+}
+
+/*
+ * Returns the offset of the entry data within the zip file.
+ * Returns -1 if an error occurred, in which case zip->msg will
+ * contain the error text.
+ */
+jlong
+ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry)
+{
+ /* The Zip file spec explicitly allows the LOC extra data size to
+ * be different from the CEN extra data size, although the JDK
+ * never creates such zip files. Since we cannot trust the CEN
+ * extra data size, we need to read the LOC to determine the entry
+ * data offset. We do this lazily to avoid touching the virtual
+ * memory page containing the LOC when initializing jzentry
+ * objects. (This speeds up javac by a factor of 10 when the JDK
+ * is installed on a very slow filesystem.)
+ */
+ if (entry->pos <= 0) {
+ unsigned char loc[LOCHDR];
+ if (readFullyAt(zip->zfd, loc, LOCHDR, -(entry->pos)) == -1) {
+ zip->msg = "error reading zip file";
+ return -1;
+ }
+ if (GETSIG(loc) != LOCSIG) {
+ zip->msg = "invalid LOC header (bad signature)";
+ return -1;
+ }
+ entry->pos = (- entry->pos) + LOCHDR + LOCNAM(loc) + LOCEXT(loc);
+ }
+ return entry->pos;
+}
+
+/*
+ * Reads bytes from the specified zip entry. Assumes that the zip
+ * file had been previously locked with ZIP_Lock(). Returns the
+ * number of bytes read, or -1 if an error occurred. If zip->msg != 0
+ * then a zip error occurred and zip->msg contains the error text.
+ *
+ * The current implementation does not support reading an entry that
+ * has the size bigger than 2**32 bytes in ONE invocation.
+ */
+jint
+ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
+{
+ jlong entry_size = (entry->csize != 0) ? entry->csize : entry->size;
+ jlong start;
+
+ /* Clear previous zip error */
+ zip->msg = NULL;
+
+ /* Check specified position */
+ if (pos < 0 || pos > entry_size - 1) {
+ zip->msg = "ZIP_Read: specified offset out of range";
+ return -1;
+ }
+
+ /* Check specified length */
+ if (len <= 0)
+ return 0;
+ if (len > entry_size - pos)
+ len = (jint)(entry_size - pos);
+
+ /* Get file offset to start reading data */
+ start = ZIP_GetEntryDataOffset(zip, entry);
+ if (start < 0)
+ return -1;
+ start += pos;
+
+ if (start + len > zip->len) {
+ zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
+ return -1;
+ }
+
+ if (readFullyAt(zip->zfd, buf, len, start) == -1) {
+ zip->msg = "ZIP_Read: error reading zip file";
+ return -1;
+ }
+ return len;
+}
+
+
+/* The maximum size of a stack-allocated buffer.
+ */
+#define BUF_SIZE 4096
+
+/*
+ * This function is used by the runtime system to load compressed entries
+ * from ZIP/JAR files specified in the class path. It is defined here
+ * so that it can be dynamically loaded by the runtime if the zip library
+ * is found.
+ *
+ * The current implementation does not support reading an entry that
+ * has the size bigger than 2**32 bytes in ONE invocation.
+ */
+jboolean
+InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
+{
+ z_stream strm;
+ char tmp[BUF_SIZE];
+ jlong pos = 0;
+ jlong count = entry->csize;
+
+ *msg = 0; /* Reset error message */
+
+ if (count == 0) {
+ *msg = "inflateFully: entry not compressed";
+ return JNI_FALSE;
+ }
+
+ memset(&strm, 0, sizeof(z_stream));
+ if (inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
+ *msg = strm.msg;
+ return JNI_FALSE;
+ }
+
+ strm.next_out = buf;
+ strm.avail_out = (uInt)entry->size;
+
+ while (count > 0) {
+ jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count;
+ ZIP_Lock(zip);
+ n = ZIP_Read(zip, entry, pos, tmp, n);
+ ZIP_Unlock(zip);
+ if (n <= 0) {
+ if (n == 0) {
+ *msg = "inflateFully: Unexpected end of file";
+ }
+ inflateEnd(&strm);
+ return JNI_FALSE;
+ }
+ pos += n;
+ count -= n;
+ strm.next_in = (Bytef *)tmp;
+ strm.avail_in = n;
+ do {
+ switch (inflate(&strm, Z_PARTIAL_FLUSH)) {
+ case Z_OK:
+ break;
+ case Z_STREAM_END:
+ if (count != 0 || strm.total_out != entry->size) {
+ *msg = "inflateFully: Unexpected end of stream";
+ inflateEnd(&strm);
+ return JNI_FALSE;
+ }
+ break;
+ default:
+ break;
+ }
+ } while (strm.avail_in > 0);
+ }
+ inflateEnd(&strm);
+ return JNI_TRUE;
+}
+
+/*
+ * The current implementation does not support reading an entry that
+ * has the size bigger than 2**32 bytes in ONE invocation.
+ */
+jzentry * JNICALL
+ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
+{
+ jzentry *entry = ZIP_GetEntry(zip, name, 0);
+ if (entry) {
+ *sizeP = (jint)entry->size;
+ *nameLenP = strlen(entry->name);
+ }
+ return entry;
+}
+
+/*
+ * Reads a zip file entry into the specified byte array
+ * When the method completes, it releases the jzentry.
+ * Note: this is called from the separately delivered VM (hotspot/classic)
+ * so we have to be careful to maintain the expected behaviour.
+ */
+jboolean JNICALL
+ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
+{
+ char *msg;
+
+ strcpy(entryname, entry->name);
+ if (entry->csize == 0) {
+ /* Entry is stored */
+ jlong pos = 0;
+ jlong size = entry->size;
+ while (pos < size) {
+ jint n;
+ jlong limit = ((((jlong) 1) << 31) - 1);
+ jint count = (size - pos < limit) ?
+ /* These casts suppress a VC++ Internal Compiler Error */
+ (jint) (size - pos) :
+ (jint) limit;
+ ZIP_Lock(zip);
+ n = ZIP_Read(zip, entry, pos, buf, count);
+ msg = zip->msg;
+ ZIP_Unlock(zip);
+ if (n == -1) {
+ jio_fprintf(stderr, "%s: %s\n", zip->name,
+ msg != 0 ? msg : strerror(errno));
+ return JNI_FALSE;
+ }
+ buf += n;
+ pos += n;
+ }
+ } else {
+ /* Entry is compressed */
+ int ok = InflateFully(zip, entry, buf, &msg);
+ if (!ok) {
+ if ((msg == NULL) || (*msg == 0)) {
+ msg = zip->msg;
+ }
+ jio_fprintf(stderr, "%s: %s\n", zip->name,
+ msg != 0 ? msg : strerror(errno));
+ return JNI_FALSE;
+ }
+ }
+
+ ZIP_FreeEntry(zip, entry);
+
+ return JNI_TRUE;
+}
diff --git a/ojluni/src/main/native/zip_util.h b/ojluni/src/main/native/zip_util.h
new file mode 100755
index 0000000..124e3f7
--- /dev/null
+++ b/ojluni/src/main/native/zip_util.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Prototypes for zip file support
+ */
+
+#ifndef _ZIP_H_
+#define _ZIP_H_
+
+/*
+ * Header signatures
+ */
+#define LOCSIG 0x04034b50L /* "PK\003\004" */
+#define EXTSIG 0x08074b50L /* "PK\007\008" */
+#define CENSIG 0x02014b50L /* "PK\001\002" */
+#define ENDSIG 0x06054b50L /* "PK\005\006" */
+
+#define ZIP64_ENDSIG 0x06064b50L /* "PK\006\006" */
+#define ZIP64_LOCSIG 0x07064b50L /* "PK\006\007" */
+
+/*
+ * Header sizes including signatures
+ */
+
+#define LOCHDR 30
+#define EXTHDR 16
+#define CENHDR 46
+#define ENDHDR 22
+
+#define ZIP64_ENDHDR 56 // ZIP64 end header size
+#define ZIP64_LOCHDR 20 // ZIP64 end loc header size
+#define ZIP64_EXTHDR 24 // EXT header size
+#define ZIP64_EXTID 1 // Extra field Zip64 header ID
+
+#define ZIP64_MAGICVAL 0xffffffffLL
+#define ZIP64_MAGICCOUNT 0xffff
+
+
+/*
+ * Header field access macros
+ */
+#define CH(b, n) (((unsigned char *)(b))[n])
+#define SH(b, n) (CH(b, n) | (CH(b, n+1) << 8))
+#define LG(b, n) ((SH(b, n) | (SH(b, n+2) << 16)) &0xffffffffUL)
+#define LL(b, n) (((jlong)LG(b, n)) | (((jlong)LG(b, n+4)) << 32))
+#define GETSIG(b) LG(b, 0)
+
+/*
+ * Macros for getting local file (LOC) header fields
+ */
+#define LOCVER(b) SH(b, 4) /* version needed to extract */
+#define LOCFLG(b) SH(b, 6) /* general purpose bit flags */
+#define LOCHOW(b) SH(b, 8) /* compression method */
+#define LOCTIM(b) LG(b, 10) /* modification time */
+#define LOCCRC(b) LG(b, 14) /* crc of uncompressed data */
+#define LOCSIZ(b) LG(b, 18) /* compressed data size */
+#define LOCLEN(b) LG(b, 22) /* uncompressed data size */
+#define LOCNAM(b) SH(b, 26) /* filename length */
+#define LOCEXT(b) SH(b, 28) /* extra field length */
+
+/*
+ * Macros for getting extra local (EXT) header fields
+ */
+#define EXTCRC(b) LG(b, 4) /* crc of uncompressed data */
+#define EXTSIZ(b) LG(b, 8) /* compressed size */
+#define EXTLEN(b) LG(b, 12) /* uncompressed size */
+
+/*
+ * Macros for getting central directory header (CEN) fields
+ */
+#define CENVEM(b) SH(b, 4) /* version made by */
+#define CENVER(b) SH(b, 6) /* version needed to extract */
+#define CENFLG(b) SH(b, 8) /* general purpose bit flags */
+#define CENHOW(b) SH(b, 10) /* compression method */
+#define CENTIM(b) LG(b, 12) /* modification time */
+#define CENCRC(b) LG(b, 16) /* crc of uncompressed data */
+#define CENSIZ(b) LG(b, 20) /* compressed size */
+#define CENLEN(b) LG(b, 24) /* uncompressed size */
+#define CENNAM(b) SH(b, 28) /* length of filename */
+#define CENEXT(b) SH(b, 30) /* length of extra field */
+#define CENCOM(b) SH(b, 32) /* file comment length */
+#define CENDSK(b) SH(b, 34) /* disk number start */
+#define CENATT(b) SH(b, 36) /* internal file attributes */
+#define CENATX(b) LG(b, 38) /* external file attributes */
+#define CENOFF(b) LG(b, 42) /* offset of local header */
+
+/*
+ * Macros for getting end of central directory header (END) fields
+ */
+#define ENDSUB(b) SH(b, 8) /* number of entries on this disk */
+#define ENDTOT(b) SH(b, 10) /* total number of entries */
+#define ENDSIZ(b) LG(b, 12) /* central directory size */
+#define ENDOFF(b) LG(b, 16) /* central directory offset */
+#define ENDCOM(b) SH(b, 20) /* size of zip file comment */
+
+/*
+ * Macros for getting Zip64 end of central directory header fields
+ */
+#define ZIP64_ENDLEN(b) LL(b, 4) /* size of zip64 end of central dir */
+#define ZIP64_ENDVEM(b) SH(b, 12) /* version made by */
+#define ZIP64_ENDVER(b) SH(b, 14) /* version needed to extract */
+#define ZIP64_ENDNMD(b) LG(b, 16) /* number of this disk */
+#define ZIP64_ENDDSK(b) LG(b, 20) /* disk number of start */
+#define ZIP64_ENDTOD(b) LL(b, 24) /* total number of entries on this disk */
+#define ZIP64_ENDTOT(b) LL(b, 32) /* total number of entries */
+#define ZIP64_ENDSIZ(b) LL(b, 40) /* central directory size in bytes */
+#define ZIP64_ENDOFF(b) LL(b, 48) /* offset of first CEN header */
+
+/*
+ * Macros for getting Zip64 end of central directory locator fields
+ */
+#define ZIP64_LOCDSK(b) LG(b, 4) /* disk number start */
+#define ZIP64_LOCOFF(b) LL(b, 8) /* offset of zip64 end */
+#define ZIP64_LOCTOT(b) LG(b, 16) /* total number of disks */
+
+/*
+ * Supported compression methods
+ */
+#define STORED 0
+#define DEFLATED 8
+
+/*
+ * Support for reading ZIP/JAR files. Some things worth noting:
+ *
+ * - Zip file entries larger than 2**32 bytes are not supported.
+ * - jzentry time and crc fields are signed even though they really
+ * represent unsigned quantities.
+ * - If csize is zero then the entry is uncompressed.
+ * - If extra != 0 then the first two bytes are the length of the extra
+ * data in intel byte order.
+ * - If pos <= 0 then it is the position of entry LOC header.
+ * If pos > 0 then it is the position of entry data.
+ * pos should not be accessed directly, but only by ZIP_GetEntryDataOffset.
+ */
+
+typedef struct jzentry { /* Zip file entry */
+ char *name; /* entry name */
+ jlong time; /* modification time */
+ jlong size; /* size of uncompressed data */
+ jlong csize; /* size of compressed data (zero if uncompressed) */
+ jint crc; /* crc of uncompressed data */
+ char *comment; /* optional zip file comment */
+ jbyte *extra; /* optional extra data */
+ jlong pos; /* position of LOC header or entry data */
+ jint flag; /* general purpose flag */
+} jzentry;
+
+/*
+ * In-memory hash table cell.
+ * In a typical system we have a *lot* of these, as we have one for
+ * every entry in every active JAR.
+ * Note that in order to save space we don't keep the name in memory,
+ * but merely remember a 32 bit hash.
+ */
+typedef struct jzcell {
+ unsigned int hash; /* 32 bit hashcode on name */
+ unsigned int next; /* hash chain: index into jzfile->entries */
+ jlong cenpos; /* Offset of central directory file header */
+} jzcell;
+
+typedef struct cencache {
+ char *data; /* A cached page of CEN headers */
+ jlong pos; /* file offset of data */
+} cencache;
+
+/*
+ * Use ZFILE to represent access to a file in a platform-indepenent
+ * fashion.
+ */
+#ifdef WIN32
+#define ZFILE jlong
+#else
+#define ZFILE int
+#endif
+
+/*
+ * Descriptor for a ZIP file.
+ */
+typedef struct jzfile { /* Zip file */
+ char *name; /* zip file name */
+ jint refs; /* number of active references */
+ jlong len; /* length (in bytes) of zip file */
+#ifdef USE_MMAP
+ unsigned char *maddr; /* beginning address of the CEN & ENDHDR */
+ jlong mlen; /* length (in bytes) mmaped */
+ jlong offset; /* offset of the mmapped region from the
+ start of the file. */
+ jboolean usemmap; /* if mmap is used. */
+#endif
+ jboolean locsig; /* if zip file starts with LOCSIG */
+ cencache cencache; /* CEN header cache */
+ ZFILE zfd; /* open file descriptor */
+ void *lock; /* read lock */
+ char *comment; /* zip file comment */
+ jint clen; /* length of the zip file comment */
+ char *msg; /* zip error message */
+ jzcell *entries; /* array of hash cells */
+ jint total; /* total number of entries */
+ jint *table; /* Hash chain heads: indexes into entries */
+ jint tablelen; /* number of hash heads */
+ struct jzfile *next; /* next zip file in search list */
+ jzentry *cache; /* we cache the most recently freed jzentry */
+ /* Information on metadata names in META-INF directory */
+ char **metanames; /* array of meta names (may have null names) */
+ jint metacurrent; /* the next empty slot in metanames array */
+ jint metacount; /* number of slots in metanames array */
+ jlong lastModified; /* last modified time */
+ jlong locpos; /* position of first LOC header (usually 0) */
+} jzfile;
+
+/*
+ * Index representing end of hash chain
+ */
+#define ZIP_ENDCHAIN ((jint)-1)
+
+jzentry * JNICALL
+ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP);
+
+jboolean JNICALL
+ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm);
+
+jzentry * JNICALL
+ZIP_GetNextEntry(jzfile *zip, jint n);
+
+jzfile * JNICALL
+ZIP_Open(const char *name, char **pmsg);
+
+jzfile *
+ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified);
+
+jzfile *
+ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified);
+
+jzfile *
+ZIP_Put_In_Cache(const char *name, ZFILE zfd, char **pmsg, jlong lastModified);
+
+jzfile *
+ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, jboolean usemmap);
+
+void JNICALL
+ZIP_Close(jzfile *zip);
+
+jzentry * ZIP_GetEntry(jzfile *zip, char *name, jint ulen);
+void ZIP_Lock(jzfile *zip);
+void ZIP_Unlock(jzfile *zip);
+jint ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len);
+void ZIP_FreeEntry(jzfile *zip, jzentry *ze);
+jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
+
+#endif /* !_ZIP_H_ */