Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libjli/java_md_common.c
41119 views
1
/*
2
* Copyright (c) 2012, 2020, 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
#include <sys/time.h>
26
#include "java.h"
27
28
/*
29
* Find the last occurrence of a string
30
*/
31
static char* findLastPathComponent(char *buffer, const char *comp) {
32
char* t = buffer;
33
char* p = NULL;
34
size_t l = JLI_StrLen(comp);
35
t = JLI_StrStr(t, comp);
36
37
while (t != NULL) {
38
p = t;
39
t += l;
40
t = JLI_StrStr(t, comp);
41
}
42
return p;
43
}
44
45
/*
46
* Removes the trailing file name and any intermediate platform
47
* directories, if any, and its enclosing directory.
48
* Ex: if a buffer contains "/foo/bin/javac" or "/foo/bin/x64/javac", the
49
* truncated resulting buffer will contain "/foo".
50
*/
51
static jboolean
52
TruncatePath(char *buf)
53
{
54
// try bin directory, maybe an executable
55
char *p = findLastPathComponent(buf, "/bin/");
56
if (p != NULL) {
57
*p = '\0';
58
return JNI_TRUE;
59
}
60
// try lib directory, maybe a library
61
p = findLastPathComponent(buf, "/lib/");
62
if (p != NULL) {
63
*p = '\0';
64
return JNI_TRUE;
65
}
66
return JNI_FALSE;
67
}
68
69
/*
70
* Retrieves the path to the JRE home by locating the executable file
71
* of the current process and then truncating the path to the executable
72
*/
73
jboolean
74
GetApplicationHome(char *buf, jint bufsize)
75
{
76
const char *execname = GetExecName();
77
if (execname != NULL) {
78
JLI_Snprintf(buf, bufsize, "%s", execname);
79
buf[bufsize-1] = '\0';
80
} else {
81
return JNI_FALSE;
82
}
83
return TruncatePath(buf);
84
}
85
86
/*
87
* Retrieves the path to the JRE home by locating the
88
* shared library and then truncating the path to it.
89
*/
90
jboolean
91
GetApplicationHomeFromDll(char *buf, jint bufsize)
92
{
93
/* try to find ourselves instead */
94
Dl_info info;
95
if (dladdr((void*)&GetApplicationHomeFromDll, &info) != 0) {
96
char *path = realpath(info.dli_fname, buf);
97
if (path == buf) {
98
return TruncatePath(buf);
99
}
100
}
101
return JNI_FALSE;
102
}
103
104
/*
105
* Return true if the named program exists
106
*/
107
static int
108
ProgramExists(char *name)
109
{
110
struct stat sb;
111
if (stat(name, &sb) != 0) return 0;
112
if (S_ISDIR(sb.st_mode)) return 0;
113
return (sb.st_mode & S_IEXEC) != 0;
114
}
115
116
/*
117
* Find a command in a directory, returning the path.
118
*/
119
static char *
120
Resolve(char *indir, char *cmd)
121
{
122
char name[PATH_MAX + 2], *real;
123
124
if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1) > PATH_MAX) return 0;
125
JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd);
126
if (!ProgramExists(name)) return 0;
127
real = JLI_MemAlloc(PATH_MAX + 2);
128
if (!realpath(name, real))
129
JLI_StrCpy(real, name);
130
return real;
131
}
132
133
/*
134
* Find a path for the executable
135
*/
136
char *
137
FindExecName(char *program)
138
{
139
char cwdbuf[PATH_MAX+2];
140
char *path;
141
char *tmp_path;
142
char *f;
143
char *result = NULL;
144
145
/* absolute path? */
146
if (*program == FILE_SEPARATOR ||
147
(FILE_SEPARATOR=='\\' && JLI_StrRChr(program, ':')))
148
return Resolve("", program+1);
149
150
/* relative path? */
151
if (JLI_StrRChr(program, FILE_SEPARATOR) != 0) {
152
char buf[PATH_MAX+2];
153
return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
154
}
155
156
/* from search path? */
157
path = getenv("PATH");
158
if (!path || !*path) path = ".";
159
tmp_path = JLI_MemAlloc(JLI_StrLen(path) + 2);
160
JLI_StrCpy(tmp_path, path);
161
162
for (f=tmp_path; *f && result==0; ) {
163
char *s = f;
164
while (*f && (*f != PATH_SEPARATOR)) ++f;
165
if (*f) *f++ = 0;
166
if (*s == FILE_SEPARATOR)
167
result = Resolve(s, program);
168
else {
169
/* relative path element */
170
char dir[2*PATH_MAX];
171
JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
172
FILE_SEPARATOR, s);
173
result = Resolve(dir, program);
174
}
175
if (result != 0) break;
176
}
177
178
JLI_MemFree(tmp_path);
179
return result;
180
}
181
182
JNIEXPORT void JNICALL
183
JLI_ReportErrorMessage(const char* fmt, ...) {
184
va_list vl;
185
va_start(vl, fmt);
186
vfprintf(stderr, fmt, vl);
187
fprintf(stderr, "\n");
188
va_end(vl);
189
}
190
191
JNIEXPORT void JNICALL
192
JLI_ReportErrorMessageSys(const char* fmt, ...) {
193
va_list vl;
194
char *emsg;
195
196
/*
197
* TODO: its safer to use strerror_r but is not available on
198
* Solaris 8. Until then....
199
*/
200
emsg = strerror(errno);
201
if (emsg != NULL) {
202
fprintf(stderr, "%s\n", emsg);
203
}
204
205
va_start(vl, fmt);
206
vfprintf(stderr, fmt, vl);
207
fprintf(stderr, "\n");
208
va_end(vl);
209
}
210
211
JNIEXPORT void JNICALL
212
JLI_ReportExceptionDescription(JNIEnv * env) {
213
(*env)->ExceptionDescribe(env);
214
}
215
216
/*
217
* Since using the file system as a registry is a bit risky, perform
218
* additional sanity checks on the identified directory to validate
219
* it as a valid jre/sdk.
220
*
221
* Return 0 if the tests fail; otherwise return non-zero (true).
222
*
223
* Note that checking for anything more than the existence of an
224
* executable object at bin/java relative to the path being checked
225
* will break the regression tests.
226
*/
227
static int
228
CheckSanity(char *path, char *dir)
229
{
230
char buffer[PATH_MAX];
231
232
if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX)
233
return (0); /* Silently reject "impossibly" long paths */
234
235
JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir);
236
return ((access(buffer, X_OK) == 0) ? 1 : 0);
237
}
238
239
/*
240
* "Borrowed" from Solaris 10 where the unsetenv() function is being added
241
* to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
242
* such, in the fullness of time this will appear in libc on all relevant
243
* Solaris/Linux platforms and maybe even the Windows platform. At that
244
* time, this stub can be removed.
245
*
246
* This implementation removes the environment locking for multithreaded
247
* applications. (We don't have access to these mutexes within libc and
248
* the launcher isn't multithreaded.) Note that what remains is platform
249
* independent, because it only relies on attributes that a POSIX environment
250
* defines.
251
*
252
* Returns 0 on success, -1 on failure.
253
*
254
* Also removed was the setting of errno. The only value of errno set
255
* was EINVAL ("Invalid Argument").
256
*/
257
258
/*
259
* s1(environ) is name=value
260
* s2(name) is name(not the form of name=value).
261
* if names match, return value of 1, else return 0
262
*/
263
static int
264
match_noeq(const char *s1, const char *s2)
265
{
266
while (*s1 == *s2++) {
267
if (*s1++ == '=')
268
return (1);
269
}
270
if (*s1 == '=' && s2[-1] == '\0')
271
return (1);
272
return (0);
273
}
274
275
/*
276
* added for SUSv3 standard
277
*
278
* Delete entry from environ.
279
* Do not free() memory! Other threads may be using it.
280
* Keep it around forever.
281
*/
282
static int
283
borrowed_unsetenv(const char *name)
284
{
285
long idx; /* index into environ */
286
287
if (name == NULL || *name == '\0' ||
288
JLI_StrChr(name, '=') != NULL) {
289
return (-1);
290
}
291
292
for (idx = 0; environ[idx] != NULL; idx++) {
293
if (match_noeq(environ[idx], name))
294
break;
295
}
296
if (environ[idx] == NULL) {
297
/* name not found but still a success */
298
return (0);
299
}
300
/* squeeze up one entry */
301
do {
302
environ[idx] = environ[idx+1];
303
} while (environ[++idx] != NULL);
304
305
return (0);
306
}
307
/* --- End of "borrowed" code --- */
308
309
/*
310
* Wrapper for unsetenv() function.
311
*/
312
int
313
UnsetEnv(char *name)
314
{
315
return(borrowed_unsetenv(name));
316
}
317
318
jboolean
319
IsJavaw()
320
{
321
/* noop on UNIX */
322
return JNI_FALSE;
323
}
324
325
void
326
InitLauncher(jboolean javaw)
327
{
328
JLI_SetTraceLauncher();
329
}
330
331
/*
332
* The implementation for finding classes from the bootstrap
333
* class loader, refer to java.h
334
*/
335
static FindClassFromBootLoader_t *findBootClass = NULL;
336
337
jclass
338
FindBootStrapClass(JNIEnv *env, const char* classname)
339
{
340
if (findBootClass == NULL) {
341
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
342
"JVM_FindClassFromBootLoader");
343
if (findBootClass == NULL) {
344
JLI_ReportErrorMessage(DLL_ERROR4,
345
"JVM_FindClassFromBootLoader");
346
return NULL;
347
}
348
}
349
return findBootClass(env, classname);
350
}
351
352
JNIEXPORT StdArg JNICALL
353
*JLI_GetStdArgs()
354
{
355
return NULL;
356
}
357
358
JNIEXPORT int JNICALL
359
JLI_GetStdArgc() {
360
return 0;
361
}
362
363
jobjectArray
364
CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
365
{
366
return NewPlatformStringArray(env, strv, argc);
367
}
368
369
/*
370
* Provide a CurrentTimeMicros() implementation based on gettimeofday() which
371
* is universally available, even though it may not be 'high resolution'
372
* compared to platforms that provide gethrtime() (like Solaris). It is
373
* also subject to time-of-day changes, but alternatives may not be
374
* known to be available at either build time or run time.
375
*/
376
jlong CurrentTimeMicros() {
377
jlong result = 0;
378
struct timeval tv;
379
if (gettimeofday(&tv, NULL) != -1) {
380
result = 1000000LL * (jlong)tv.tv_sec;
381
result += (jlong)tv.tv_usec;
382
}
383
return result;
384
}
385
386