Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/bin/java_md_common.c
32285 views
1
/*
2
* Copyright (c) 2012, 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 "java.h"
26
27
/*
28
* If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
29
* "/foo" into buf.
30
*/
31
jboolean
32
GetApplicationHome(char *buf, jint bufsize)
33
{
34
const char *execname = GetExecName();
35
if (execname != NULL) {
36
JLI_Snprintf(buf, bufsize, "%s", execname);
37
buf[bufsize-1] = '\0';
38
} else {
39
return JNI_FALSE;
40
}
41
42
if (JLI_StrRChr(buf, '/') == 0) {
43
buf[0] = '\0';
44
return JNI_FALSE;
45
}
46
*(JLI_StrRChr(buf, '/')) = '\0'; /* executable file */
47
if (JLI_StrLen(buf) < 4 || JLI_StrRChr(buf, '/') == 0) {
48
buf[0] = '\0';
49
return JNI_FALSE;
50
}
51
if (JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0)
52
*(JLI_StrRChr(buf, '/')) = '\0'; /* sparcv9 or amd64 */
53
if (JLI_StrLen(buf) < 4 || JLI_StrCmp("/bin", buf + JLI_StrLen(buf) - 4) != 0) {
54
buf[0] = '\0';
55
return JNI_FALSE;
56
}
57
*(JLI_StrRChr(buf, '/')) = '\0'; /* bin */
58
59
return JNI_TRUE;
60
}
61
/*
62
* Return true if the named program exists
63
*/
64
static int
65
ProgramExists(char *name)
66
{
67
struct stat sb;
68
if (stat(name, &sb) != 0) return 0;
69
if (S_ISDIR(sb.st_mode)) return 0;
70
#ifndef __ANDROID__
71
return (sb.st_mode & S_IEXEC) != 0;
72
#else
73
return (sb.st_mode & S_IXUSR) != 0;
74
#endif
75
}
76
77
/*
78
* Find a command in a directory, returning the path.
79
*/
80
static char *
81
Resolve(char *indir, char *cmd)
82
{
83
char name[PATH_MAX + 2], *real;
84
85
if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1) > PATH_MAX) return 0;
86
JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd);
87
if (!ProgramExists(name)) return 0;
88
real = JLI_MemAlloc(PATH_MAX + 2);
89
if (!realpath(name, real))
90
JLI_StrCpy(real, name);
91
return real;
92
}
93
94
/*
95
* Find a path for the executable
96
*/
97
char *
98
FindExecName(char *program)
99
{
100
char cwdbuf[PATH_MAX+2];
101
char *path;
102
char *tmp_path;
103
char *f;
104
char *result = NULL;
105
106
/* absolute path? */
107
if (*program == FILE_SEPARATOR ||
108
(FILE_SEPARATOR=='\\' && JLI_StrRChr(program, ':')))
109
return Resolve("", program+1);
110
111
/* relative path? */
112
if (JLI_StrRChr(program, FILE_SEPARATOR) != 0) {
113
char buf[PATH_MAX+2];
114
return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program);
115
}
116
117
/* from search path? */
118
path = getenv("PATH");
119
if (!path || !*path) path = ".";
120
tmp_path = JLI_MemAlloc(JLI_StrLen(path) + 2);
121
JLI_StrCpy(tmp_path, path);
122
123
for (f=tmp_path; *f && result==0; ) {
124
char *s = f;
125
while (*f && (*f != PATH_SEPARATOR)) ++f;
126
if (*f) *f++ = 0;
127
if (*s == FILE_SEPARATOR)
128
result = Resolve(s, program);
129
else {
130
/* relative path element */
131
char dir[2*PATH_MAX];
132
JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)),
133
FILE_SEPARATOR, s);
134
result = Resolve(dir, program);
135
}
136
if (result != 0) break;
137
}
138
139
JLI_MemFree(tmp_path);
140
return result;
141
}
142
143
void JLI_ReportErrorMessage(const char* fmt, ...) {
144
va_list vl;
145
va_start(vl, fmt);
146
vfprintf(stderr, fmt, vl);
147
fprintf(stderr, "\n");
148
va_end(vl);
149
}
150
151
void JLI_ReportErrorMessageSys(const char* fmt, ...) {
152
va_list vl;
153
char *emsg;
154
155
/*
156
* TODO: its safer to use strerror_r but is not available on
157
* Solaris 8. Until then....
158
*/
159
emsg = strerror(errno);
160
if (emsg != NULL) {
161
fprintf(stderr, "%s\n", emsg);
162
}
163
164
va_start(vl, fmt);
165
vfprintf(stderr, fmt, vl);
166
fprintf(stderr, "\n");
167
va_end(vl);
168
}
169
170
void JLI_ReportExceptionDescription(JNIEnv * env) {
171
(*env)->ExceptionDescribe(env);
172
}
173
174
/*
175
* Since using the file system as a registry is a bit risky, perform
176
* additional sanity checks on the identified directory to validate
177
* it as a valid jre/sdk.
178
*
179
* Return 0 if the tests fail; otherwise return non-zero (true).
180
*
181
* Note that checking for anything more than the existence of an
182
* executable object at bin/java relative to the path being checked
183
* will break the regression tests.
184
*/
185
static int
186
CheckSanity(char *path, char *dir)
187
{
188
char buffer[PATH_MAX];
189
190
if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX)
191
return (0); /* Silently reject "impossibly" long paths */
192
193
JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir);
194
return ((access(buffer, X_OK) == 0) ? 1 : 0);
195
}
196
197
/*
198
* Determine if there is an acceptable JRE in the directory dirname.
199
* Upon locating the "best" one, return a fully qualified path to
200
* it. "Best" is defined as the most advanced JRE meeting the
201
* constraints contained in the manifest_info. If no JRE in this
202
* directory meets the constraints, return NULL.
203
*
204
* Note that we don't check for errors in reading the directory
205
* (which would be done by checking errno). This is because it
206
* doesn't matter if we get an error reading the directory, or
207
* we just don't find anything interesting in the directory. We
208
* just return NULL in either case.
209
*
210
* The historical names of j2sdk and j2re were changed to jdk and
211
* jre respecively as part of the 1.5 rebranding effort. Since the
212
* former names are legacy on Linux, they must be recognized for
213
* all time. Fortunately, this is a minor cost.
214
*/
215
static char
216
*ProcessDir(manifest_info *info, char *dirname)
217
{
218
DIR *dirp;
219
struct dirent *dp;
220
char *best = NULL;
221
int offset;
222
int best_offset = 0;
223
char *ret_str = NULL;
224
char buffer[PATH_MAX];
225
226
if ((dirp = opendir(dirname)) == NULL)
227
return (NULL);
228
229
do {
230
if ((dp = readdir(dirp)) != NULL) {
231
offset = 0;
232
if ((JLI_StrNCmp(dp->d_name, "jre", 3) == 0) ||
233
(JLI_StrNCmp(dp->d_name, "jdk", 3) == 0))
234
offset = 3;
235
else if (JLI_StrNCmp(dp->d_name, "j2re", 4) == 0)
236
offset = 4;
237
else if (JLI_StrNCmp(dp->d_name, "j2sdk", 5) == 0)
238
offset = 5;
239
if (offset > 0) {
240
if ((JLI_AcceptableRelease(dp->d_name + offset,
241
info->jre_version)) && CheckSanity(dirname, dp->d_name))
242
if ((best == NULL) || (JLI_ExactVersionId(
243
dp->d_name + offset, best + best_offset) > 0)) {
244
if (best != NULL)
245
JLI_MemFree(best);
246
best = JLI_StringDup(dp->d_name);
247
best_offset = offset;
248
}
249
}
250
}
251
} while (dp != NULL);
252
(void) closedir(dirp);
253
if (best == NULL)
254
return (NULL);
255
else {
256
ret_str = JLI_MemAlloc(JLI_StrLen(dirname) + JLI_StrLen(best) + 2);
257
sprintf(ret_str, "%s/%s", dirname, best);
258
JLI_MemFree(best);
259
return (ret_str);
260
}
261
}
262
263
/*
264
* This is the global entry point. It examines the host for the optimal
265
* JRE to be used by scanning a set of directories. The set of directories
266
* is platform dependent and can be overridden by the environment
267
* variable JAVA_VERSION_PATH.
268
*
269
* This routine itself simply determines the set of appropriate
270
* directories before passing control onto ProcessDir().
271
*/
272
char*
273
LocateJRE(manifest_info* info)
274
{
275
char *path;
276
char *home;
277
char *target = NULL;
278
char *dp;
279
char *cp;
280
281
/*
282
* Start by getting JAVA_VERSION_PATH
283
*/
284
if (info->jre_restrict_search) {
285
path = JLI_StringDup(system_dir);
286
} else if ((path = getenv("JAVA_VERSION_PATH")) != NULL) {
287
path = JLI_StringDup(path);
288
} else {
289
if ((home = getenv("HOME")) != NULL) {
290
path = (char *)JLI_MemAlloc(JLI_StrLen(home) + \
291
JLI_StrLen(system_dir) + JLI_StrLen(user_dir) + 2);
292
sprintf(path, "%s%s:%s", home, user_dir, system_dir);
293
} else {
294
path = JLI_StringDup(system_dir);
295
}
296
}
297
298
/*
299
* Step through each directory on the path. Terminate the scan with
300
* the first directory with an acceptable JRE.
301
*/
302
cp = dp = path;
303
while (dp != NULL) {
304
cp = JLI_StrChr(dp, (int)':');
305
if (cp != NULL)
306
*cp = '\0';
307
if ((target = ProcessDir(info, dp)) != NULL)
308
break;
309
dp = cp;
310
if (dp != NULL)
311
dp++;
312
}
313
JLI_MemFree(path);
314
return (target);
315
}
316
317
/*
318
* Given a path to a jre to execute, this routine checks if this process
319
* is indeed that jre. If not, it exec's that jre.
320
*
321
* We want to actually check the paths rather than just the version string
322
* built into the executable, so that given version specification (and
323
* JAVA_VERSION_PATH) will yield the exact same Java environment, regardless
324
* of the version of the arbitrary launcher we start with.
325
*/
326
void
327
ExecJRE(char *jre, char **argv)
328
{
329
char wanted[PATH_MAX];
330
const char* progname = GetProgramName();
331
const char* execname = NULL;
332
333
/*
334
* Resolve the real path to the directory containing the selected JRE.
335
*/
336
if (realpath(jre, wanted) == NULL) {
337
JLI_ReportErrorMessage(JRE_ERROR9, jre);
338
exit(1);
339
}
340
341
/*
342
* Resolve the real path to the currently running launcher.
343
*/
344
SetExecname(argv);
345
execname = GetExecName();
346
if (execname == NULL) {
347
JLI_ReportErrorMessage(JRE_ERROR10);
348
exit(1);
349
}
350
351
/*
352
* If the path to the selected JRE directory is a match to the initial
353
* portion of the path to the currently executing JRE, we have a winner!
354
* If so, just return.
355
*/
356
if (JLI_StrNCmp(wanted, execname, JLI_StrLen(wanted)) == 0)
357
return; /* I am the droid you were looking for */
358
359
360
/*
361
* This should never happen (because of the selection code in SelectJRE),
362
* but check for "impossibly" long path names just because buffer overruns
363
* can be so deadly.
364
*/
365
if (JLI_StrLen(wanted) + JLI_StrLen(progname) + 6 > PATH_MAX) {
366
JLI_ReportErrorMessage(JRE_ERROR11);
367
exit(1);
368
}
369
370
/*
371
* Construct the path and exec it.
372
*/
373
(void)JLI_StrCat(JLI_StrCat(wanted, "/bin/"), progname);
374
argv[0] = JLI_StringDup(progname);
375
if (JLI_IsTraceLauncher()) {
376
int i;
377
printf("ReExec Command: %s (%s)\n", wanted, argv[0]);
378
printf("ReExec Args:");
379
for (i = 1; argv[i] != NULL; i++)
380
printf(" %s", argv[i]);
381
printf("\n");
382
}
383
JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n");
384
(void)fflush(stdout);
385
(void)fflush(stderr);
386
execv(wanted, argv);
387
JLI_ReportErrorMessageSys(JRE_ERROR12, wanted);
388
exit(1);
389
}
390
391
/*
392
* "Borrowed" from Solaris 10 where the unsetenv() function is being added
393
* to libc thanks to SUSv3 (Standard Unix Specification, version 3). As
394
* such, in the fullness of time this will appear in libc on all relevant
395
* Solaris/Linux platforms and maybe even the Windows platform. At that
396
* time, this stub can be removed.
397
*
398
* This implementation removes the environment locking for multithreaded
399
* applications. (We don't have access to these mutexes within libc and
400
* the launcher isn't multithreaded.) Note that what remains is platform
401
* independent, because it only relies on attributes that a POSIX environment
402
* defines.
403
*
404
* Returns 0 on success, -1 on failure.
405
*
406
* Also removed was the setting of errno. The only value of errno set
407
* was EINVAL ("Invalid Argument").
408
*/
409
410
/*
411
* s1(environ) is name=value
412
* s2(name) is name(not the form of name=value).
413
* if names match, return value of 1, else return 0
414
*/
415
static int
416
match_noeq(const char *s1, const char *s2)
417
{
418
while (*s1 == *s2++) {
419
if (*s1++ == '=')
420
return (1);
421
}
422
if (*s1 == '=' && s2[-1] == '\0')
423
return (1);
424
return (0);
425
}
426
427
/*
428
* added for SUSv3 standard
429
*
430
* Delete entry from environ.
431
* Do not free() memory! Other threads may be using it.
432
* Keep it around forever.
433
*/
434
static int
435
borrowed_unsetenv(const char *name)
436
{
437
long idx; /* index into environ */
438
439
if (name == NULL || *name == '\0' ||
440
JLI_StrChr(name, '=') != NULL) {
441
return (-1);
442
}
443
444
for (idx = 0; environ[idx] != NULL; idx++) {
445
if (match_noeq(environ[idx], name))
446
break;
447
}
448
if (environ[idx] == NULL) {
449
/* name not found but still a success */
450
return (0);
451
}
452
/* squeeze up one entry */
453
do {
454
environ[idx] = environ[idx+1];
455
} while (environ[++idx] != NULL);
456
457
return (0);
458
}
459
/* --- End of "borrowed" code --- */
460
461
/*
462
* Wrapper for unsetenv() function.
463
*/
464
int
465
UnsetEnv(char *name)
466
{
467
return(borrowed_unsetenv(name));
468
}
469
470
const char *
471
jlong_format_specifier() {
472
return "%lld";
473
}
474
475
jboolean
476
IsJavaw()
477
{
478
/* noop on UNIX */
479
return JNI_FALSE;
480
}
481
482
void
483
InitLauncher(jboolean javaw)
484
{
485
JLI_SetTraceLauncher();
486
}
487
488
/*
489
* The implementation for finding classes from the bootstrap
490
* class loader, refer to java.h
491
*/
492
static FindClassFromBootLoader_t *findBootClass = NULL;
493
494
jclass
495
FindBootStrapClass(JNIEnv *env, const char* classname)
496
{
497
if (findBootClass == NULL) {
498
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
499
"JVM_FindClassFromBootLoader");
500
if (findBootClass == NULL) {
501
JLI_ReportErrorMessage(DLL_ERROR4,
502
"JVM_FindClassFromBootLoader");
503
return NULL;
504
}
505
}
506
return findBootClass(env, classname);
507
}
508
509
StdArg
510
*JLI_GetStdArgs()
511
{
512
return NULL;
513
}
514
515
int
516
JLI_GetStdArgc() {
517
return 0;
518
}
519
520
jobjectArray
521
CreateApplicationArgs(JNIEnv *env, char **strv, int argc)
522
{
523
return NewPlatformStringArray(env, strv, argc);
524
}
525
526