1 /*
2  * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 #define LOG_TAG "libcore"
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 
31 #include <log/log.h>
32 
33 #include "io_util.h"
34 #include "jni.h"
35 #include "jni_util.h"
36 #include "jvm.h"
37 
38 #include "openssl/opensslv.h"
39 #include "zlib.h"
40 #include <nativehelper/JNIHelp.h>
41 #include <nativehelper/jni_macros.h>
42 
43 #if defined(__ANDROID__)
44 void android_get_LD_LIBRARY_PATH(char*, size_t);
45 #endif
46 
47 #define PUTPROP(props, key, val) \
48     if (1) { \
49         jstring jkey = (*env)->NewStringUTF(env, key); \
50         jstring jval = (*env)->NewStringUTF(env, val); \
51         jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \
52         if ((*env)->ExceptionOccurred(env)) return NULL; \
53         (*env)->DeleteLocalRef(env, jkey); \
54         (*env)->DeleteLocalRef(env, jval); \
55         (*env)->DeleteLocalRef(env, r); \
56     } else ((void) 0)
57 
58 /*  "key" is a char type string with only ASCII character in it.
59     "val" is a nchar (typedefed in java_props.h) type string  */
60 
61 #define PUTPROP_ForPlatformNString(props, key, val) \
62     if (1) { \
63         jstring jkey = (*env)->NewStringUTF(env, key);  \
64         jstring jval = GetStringPlatform(env, val); \
65         jobject r = (*env)->CallObjectMethod(env, props, putID, jkey, jval); \
66         if ((*env)->ExceptionOccurred(env)) return NULL; \
67         (*env)->DeleteLocalRef(env, jkey); \
68         (*env)->DeleteLocalRef(env, jval); \
69         (*env)->DeleteLocalRef(env, r); \
70     } else ((void) 0)
71 #define REMOVEPROP(props, key) \
72     if (1) { \
73         jstring jkey = JNU_NewStringPlatform(env, key); \
74         jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \
75         if ((*env)->ExceptionOccurred(env)) return NULL; \
76         (*env)->DeleteLocalRef(env, jkey); \
77         (*env)->DeleteLocalRef(env, r); \
78     } else ((void) 0)
79 #define GETPROP(props, key, jret) \
80     if (1) { \
81         jstring jkey = JNU_NewStringPlatform(env, key); \
82         (jret) = (*env)->CallObjectMethod(env, props, getPropID, jkey); \
83         if ((*env)->ExceptionOccurred(env)) return NULL; \
84         (*env)->DeleteLocalRef(env, jkey); \
85     } else ((void) 0)
86 
87 #ifndef VENDOR /* Third party may overwrite this. */
88 #define VENDOR "Oracle Corporation"
89 #define VENDOR_URL "http://java.oracle.com/"
90 #define VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/"
91 #endif
92 
93 #define JAVA_MAX_SUPPORTED_VERSION 51
94 #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0
95 
96 #ifdef JAVA_SPECIFICATION_VENDOR /* Third party may NOT overwrite this. */
97   #error "ERROR: No override of JAVA_SPECIFICATION_VENDOR is allowed"
98 #else
99   #define JAVA_SPECIFICATION_VENDOR "Oracle Corporation"
100 #endif
101 
102 /*
103  * The following three functions implement setter methods for
104  * java.lang.System.{in, out, err}. They are natively implemented
105  * because they violate the semantics of the language (i.e. set final
106  * variable).
107  */
108 JNIEXPORT void JNICALL
System_setIn0(JNIEnv * env,jclass cla,jobject stream)109 System_setIn0(JNIEnv *env, jclass cla, jobject stream)
110 {
111     jfieldID fid =
112         (*env)->GetStaticFieldID(env,cla,"in","Ljava/io/InputStream;");
113     if (fid == 0)
114         return;
115     (*env)->SetStaticObjectField(env,cla,fid,stream);
116 }
117 
118 JNIEXPORT void JNICALL
System_setOut0(JNIEnv * env,jclass cla,jobject stream)119 System_setOut0(JNIEnv *env, jclass cla, jobject stream)
120 {
121     jfieldID fid =
122         (*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
123     if (fid == 0)
124         return;
125     (*env)->SetStaticObjectField(env,cla,fid,stream);
126 }
127 
128 JNIEXPORT void JNICALL
System_setErr0(JNIEnv * env,jclass cla,jobject stream)129 System_setErr0(JNIEnv *env, jclass cla, jobject stream)
130 {
131     jfieldID fid =
132         (*env)->GetStaticFieldID(env,cla,"err","Ljava/io/PrintStream;");
133     if (fid == 0)
134         return;
135     (*env)->SetStaticObjectField(env,cla,fid,stream);
136 }
137 
cpchars(jchar * dst,char * src,int n)138 static void cpchars(jchar *dst, char *src, int n)
139 {
140     int i;
141     for (i = 0; i < n; i++) {
142         dst[i] = src[i];
143     }
144 }
145 
146 JNIEXPORT jstring JNICALL
System_mapLibraryName(JNIEnv * env,jclass ign,jstring libname)147 System_mapLibraryName(JNIEnv *env, jclass ign, jstring libname)
148 {
149     int len;
150     int prefix_len = (int) strlen(JNI_LIB_PREFIX);
151     int suffix_len = (int) strlen(JNI_LIB_SUFFIX);
152 
153     jchar chars[256];
154     if (libname == NULL) {
155         JNU_ThrowNullPointerException(env, 0);
156         return NULL;
157     }
158     len = (*env)->GetStringLength(env, libname);
159     if (len > 240) {
160         JNU_ThrowIllegalArgumentException(env, "name too long");
161         return NULL;
162     }
163     cpchars(chars, JNI_LIB_PREFIX, prefix_len);
164     (*env)->GetStringRegion(env, libname, 0, len, chars + prefix_len);
165     len += prefix_len;
166     cpchars(chars + len, JNI_LIB_SUFFIX, suffix_len);
167     len += suffix_len;
168 
169     return (*env)->NewString(env, chars, len);
170 }
171 
System_specialProperties(JNIEnv * env,jclass ignored)172 static jobjectArray System_specialProperties(JNIEnv* env, jclass ignored) {
173     jclass stringClass = (*env)->FindClass(env, "java/lang/String");
174     jobjectArray result = (*env)->NewObjectArray(env, 4, stringClass, NULL);
175 
176     char path[PATH_MAX];
177     char* process_path = getcwd(path, sizeof(path));
178     char user_dir[PATH_MAX + 10] = "user.dir=";
179     strncat(user_dir, process_path, PATH_MAX);
180     jstring user_dir_str = (*env)->NewStringUTF(env, user_dir);
181     if ((*env)->ExceptionCheck(env)) {
182         return NULL;
183     }
184     (*env)->SetObjectArrayElement(env, result, 0, user_dir_str);
185     if ((*env)->ExceptionCheck(env)) {
186         return NULL;
187     }
188     jstring zlib_str = (*env)->NewStringUTF(env, "android.zlib.version=" ZLIB_VERSION);
189     if ((*env)->ExceptionCheck(env)) {
190         return NULL;
191     }
192     (*env)->SetObjectArrayElement(env, result, 1, zlib_str);
193     if ((*env)->ExceptionCheck(env)) {
194         return NULL;
195     }
196     jstring ssl_str = (*env)->NewStringUTF(env, "android.openssl.version=" OPENSSL_VERSION_TEXT);
197     if ((*env)->ExceptionCheck(env)) {
198         return NULL;
199     }
200     (*env)->SetObjectArrayElement(env, result, 2, ssl_str);
201     if ((*env)->ExceptionCheck(env)) {
202         return NULL;
203     }
204 
205 
206     const char* library_path = getenv("LD_LIBRARY_PATH");
207 #if defined(__ANDROID__)
208     if (library_path == NULL) {
209         android_get_LD_LIBRARY_PATH(path, sizeof(path));
210         library_path = path;
211     }
212 #endif
213     if (library_path == NULL) {
214         library_path = "";
215     }
216     char* java_path = malloc(strlen("java.library.path=") + strlen(library_path) + 1);
217     strcpy(java_path, "java.library.path=");
218     strcat(java_path, library_path);
219     jstring java_path_str = (*env)->NewStringUTF(env, java_path);
220     free((void*)java_path);
221     if ((*env)->ExceptionCheck(env)) {
222         return NULL;
223     }
224     (*env)->SetObjectArrayElement(env, result, 3, java_path_str);
225     if ((*env)->ExceptionCheck(env)) {
226         return NULL;
227     }
228 
229     return result;
230 }
231 
System_log(JNIEnv * env,jclass ignored,jchar type,jstring javaMessage,jthrowable exception)232 static void System_log(JNIEnv* env, jclass ignored, jchar type, jstring javaMessage, jthrowable exception) {
233     int priority;
234     switch (type) {
235     case 'D': case 'd': priority = ANDROID_LOG_DEBUG;   break;
236     case 'E': case 'e': priority = ANDROID_LOG_ERROR;   break;
237     case 'F': case 'f': priority = ANDROID_LOG_FATAL;   break;
238     case 'I': case 'i': priority = ANDROID_LOG_INFO;    break;
239     case 'S': case 's': priority = ANDROID_LOG_SILENT;  break;
240     case 'V': case 'v': priority = ANDROID_LOG_VERBOSE; break;
241     case 'W': case 'w': priority = ANDROID_LOG_WARN;    break;
242     default:            priority = ANDROID_LOG_DEFAULT; break;
243     }
244 
245     WITH_PLATFORM_STRING(env, javaMessage, message) {
246       LOG_PRI(priority, "System", "%s", message);
247     } END_PLATFORM_STRING(env, message);
248 
249     if (exception != NULL) {
250         jniLogException(env, priority, "System", exception);
251     }
252 }
253 
System_nanoTime()254 static jlong System_nanoTime() {
255   struct timespec now;
256   clock_gettime(CLOCK_MONOTONIC, &now);
257   return now.tv_sec * 1000000000LL + now.tv_nsec;
258 }
259 
System_currentTimeMillis()260 static jlong System_currentTimeMillis() {
261   return JVM_CurrentTimeMillis(NULL, NULL);
262 }
263 
264 static JNINativeMethod gMethods[] = {
265   NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"),
266   NATIVE_METHOD(System, setErr0, "(Ljava/io/PrintStream;)V"),
267   NATIVE_METHOD(System, setOut0, "(Ljava/io/PrintStream;)V"),
268   NATIVE_METHOD(System, setIn0, "(Ljava/io/InputStream;)V"),
269   NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"),
270   NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"),
271   CRITICAL_NATIVE_METHOD(System, currentTimeMillis, "()J"),
272   CRITICAL_NATIVE_METHOD(System, nanoTime, "()J"),
273 };
274 
register_java_lang_System(JNIEnv * env)275 void register_java_lang_System(JNIEnv* env) {
276   jniRegisterNativeMethods(env, "java/lang/System", gMethods, NELEM(gMethods));
277 }
278