Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libjava/java_props_md.c
41119 views
1
/*
2
* Copyright (c) 1998, 2021, 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
26
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
27
#include <stdio.h>
28
#include <ctype.h>
29
#endif
30
#include <pwd.h>
31
#include <locale.h>
32
#ifndef ARCHPROPNAME
33
#error "The macro ARCHPROPNAME has not been defined"
34
#endif
35
#include <sys/utsname.h> /* For os_name and os_version */
36
#include <langinfo.h> /* For nl_langinfo */
37
#include <stdlib.h>
38
#include <string.h>
39
#include <sys/types.h>
40
#include <unistd.h>
41
#include <sys/param.h>
42
#include <time.h>
43
#include <errno.h>
44
45
#ifdef MACOSX
46
#include "java_props_macosx.h"
47
#endif
48
49
#ifdef __ANDROID__
50
// From https://android.googlesource.com/platform/bionic/+/master/libc/bionic/langinfo.cpp
51
/*
52
* Copyright (C) 2016 The Android Open Source Project
53
* All rights reserved.
54
*
55
* Redistribution and use in source and binary forms, with or without
56
* modification, are permitted provided that the following conditions
57
* are met:
58
* * Redistributions of source code must retain the above copyright
59
* notice, this list of conditions and the following disclaimer.
60
* * Redistributions in binary form must reproduce the above copyright
61
* notice, this list of conditions and the following disclaimer in
62
* the documentation and/or other materials provided with the
63
* distribution.
64
*
65
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
66
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
67
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
68
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
69
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
70
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
71
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
72
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
73
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
74
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
75
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
76
* SUCH DAMAGE.
77
*/
78
79
char* nl_langinfo(nl_item item) {
80
const char* result = "";
81
switch (item) {
82
case CODESET: result = (MB_CUR_MAX == 1) ? "ASCII" : "UTF-8"; break;
83
case D_T_FMT: result = "%F %T %z"; break;
84
case D_FMT: result = "%F"; break;
85
case T_FMT: result = "%T"; break;
86
case T_FMT_AMPM: result = "%I:%M:%S %p"; break;
87
case AM_STR: result = "AM"; break;
88
case PM_STR: result = "PM"; break;
89
case DAY_1: result = "Sunday"; break;
90
case DAY_2: result = "Monday"; break;
91
case DAY_3: result = "Tuesday"; break;
92
case DAY_4: result = "Wednesday"; break;
93
case DAY_5: result = "Thursday"; break;
94
case DAY_6: result = "Friday"; break;
95
case DAY_7: result = "Saturday"; break;
96
case ABDAY_1: result = "Sun"; break;
97
case ABDAY_2: result = "Mon"; break;
98
case ABDAY_3: result = "Tue"; break;
99
case ABDAY_4: result = "Wed"; break;
100
case ABDAY_5: result = "Thu"; break;
101
case ABDAY_6: result = "Fri"; break;
102
case ABDAY_7: result = "Sat"; break;
103
case MON_1: result = "January"; break;
104
case MON_2: result = "February"; break;
105
case MON_3: result = "March"; break;
106
case MON_4: result = "April"; break;
107
case MON_5: result = "May"; break;
108
case MON_6: result = "June"; break;
109
case MON_7: result = "July"; break;
110
case MON_8: result = "August"; break;
111
case MON_9: result = "September"; break;
112
case MON_10: result = "October"; break;
113
case MON_11: result = "November"; break;
114
case MON_12: result = "December"; break;
115
case ABMON_1: result = "Jan"; break;
116
case ABMON_2: result = "Feb"; break;
117
case ABMON_3: result = "Mar"; break;
118
case ABMON_4: result = "Apr"; break;
119
case ABMON_5: result = "May"; break;
120
case ABMON_6: result = "Jun"; break;
121
case ABMON_7: result = "Jul"; break;
122
case ABMON_8: result = "Aug"; break;
123
case ABMON_9: result = "Sep"; break;
124
case ABMON_10: result = "Oct"; break;
125
case ABMON_11: result = "Nov"; break;
126
case ABMON_12: result = "Dec"; break;
127
case ERA: result = ""; break;
128
case ERA_D_FMT: result = ""; break;
129
case ERA_D_T_FMT: result = ""; break;
130
case ERA_T_FMT: result = ""; break;
131
case ALT_DIGITS: result = ""; break;
132
case RADIXCHAR: result = "."; break;
133
case THOUSEP: result = ""; break;
134
case YESEXPR: result = "^[yY]"; break;
135
case NOEXPR: result = "^[nN]"; break;
136
case CRNCYSTR: result = ""; break;
137
default: break;
138
}
139
return (char*) result;
140
}
141
#endif
142
143
#if defined(_ALLBSD_SOURCE)
144
#if !defined(P_tmpdir)
145
#include <paths.h>
146
#define P_tmpdir _PATH_VARTMP
147
#endif
148
#endif
149
150
#include "locale_str.h"
151
#include "java_props.h"
152
153
#if !defined(_ALLBSD_SOURCE)
154
#ifdef __linux__
155
#ifndef CODESET
156
#define CODESET _NL_CTYPE_CODESET_NAME
157
#endif
158
#else
159
#ifdef ALT_CODESET_KEY
160
#define CODESET ALT_CODESET_KEY
161
#endif
162
#endif
163
#endif /* !_ALLBSD_SOURCE */
164
165
/* Take an array of string pairs (map of key->value) and a string (key).
166
* Examine each pair in the map to see if the first string (key) matches the
167
* string. If so, store the second string of the pair (value) in the value and
168
* return 1. Otherwise do nothing and return 0. The end of the map is
169
* indicated by an empty string at the start of a pair (key of "").
170
*/
171
static int
172
mapLookup(char* map[], const char* key, char** value) {
173
int i;
174
for (i = 0; strcmp(map[i], ""); i += 2){
175
if (!strcmp(key, map[i])){
176
*value = map[i + 1];
177
return 1;
178
}
179
}
180
return 0;
181
}
182
183
#ifndef P_tmpdir
184
#define P_tmpdir "/var/tmp"
185
#endif
186
187
static int ParseLocale(JNIEnv* env, int cat, char ** std_language, char ** std_script,
188
char ** std_country, char ** std_variant, char ** std_encoding) {
189
char *temp = NULL;
190
char *language = NULL, *country = NULL, *variant = NULL,
191
*encoding = NULL;
192
char *p, *encoding_variant, *old_temp, *old_ev;
193
char *lc;
194
195
/* Query the locale set for the category */
196
197
#ifdef MACOSX
198
lc = setupMacOSXLocale(cat); // malloc'd memory, need to free
199
#else
200
lc = setlocale(cat, NULL);
201
#endif
202
203
#ifndef __linux__
204
if (lc == NULL) {
205
return 0;
206
}
207
208
temp = malloc(strlen(lc) + 1);
209
if (temp == NULL) {
210
#ifdef MACOSX
211
free(lc); // malloced memory
212
#endif
213
JNU_ThrowOutOfMemoryError(env, NULL);
214
return 0;
215
}
216
217
if (cat == LC_CTYPE) {
218
/*
219
* Workaround for Solaris bug 4201684: Xlib doesn't like @euro
220
* locales. Since we don't depend on the libc @euro behavior,
221
* we just remove the qualifier.
222
* On Linux, the bug doesn't occur; on the other hand, @euro
223
* is needed there because it's a shortcut that also determines
224
* the encoding - without it, we wouldn't get ISO-8859-15.
225
* Therefore, this code section is Solaris-specific.
226
*/
227
strcpy(temp, lc);
228
p = strstr(temp, "@euro");
229
if (p != NULL) {
230
*p = '\0';
231
setlocale(LC_ALL, temp);
232
}
233
}
234
#else
235
if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
236
lc = "en_US";
237
}
238
239
temp = malloc(strlen(lc) + 1);
240
if (temp == NULL) {
241
JNU_ThrowOutOfMemoryError(env, NULL);
242
return 0;
243
}
244
245
#endif
246
247
/*
248
* locale string format in Solaris is
249
* <language name>_<country name>.<encoding name>@<variant name>
250
* <country name>, <encoding name>, and <variant name> are optional.
251
*/
252
253
strcpy(temp, lc);
254
#ifdef MACOSX
255
free(lc); // malloced memory
256
#endif
257
/* Parse the language, country, encoding, and variant from the
258
* locale. Any of the elements may be missing, but they must occur
259
* in the order language_country.encoding@variant, and must be
260
* preceded by their delimiter (except for language).
261
*
262
* If the locale name (without .encoding@variant, if any) matches
263
* any of the names in the locale_aliases list, map it to the
264
* corresponding full locale name. Most of the entries in the
265
* locale_aliases list are locales that include a language name but
266
* no country name, and this facility is used to map each language
267
* to a default country if that's possible. It's also used to map
268
* the Solaris locale aliases to their proper Java locale IDs.
269
*/
270
271
encoding_variant = malloc(strlen(temp)+1);
272
if (encoding_variant == NULL) {
273
free(temp);
274
JNU_ThrowOutOfMemoryError(env, NULL);
275
return 0;
276
}
277
278
if ((p = strchr(temp, '.')) != NULL) {
279
strcpy(encoding_variant, p); /* Copy the leading '.' */
280
*p = '\0';
281
} else if ((p = strchr(temp, '@')) != NULL) {
282
strcpy(encoding_variant, p); /* Copy the leading '@' */
283
*p = '\0';
284
} else {
285
*encoding_variant = '\0';
286
}
287
288
if (mapLookup(locale_aliases, temp, &p)) {
289
old_temp = temp;
290
temp = realloc(temp, strlen(p)+1);
291
if (temp == NULL) {
292
free(old_temp);
293
free(encoding_variant);
294
JNU_ThrowOutOfMemoryError(env, NULL);
295
return 0;
296
}
297
strcpy(temp, p);
298
old_ev = encoding_variant;
299
encoding_variant = realloc(encoding_variant, strlen(temp)+1);
300
if (encoding_variant == NULL) {
301
free(old_ev);
302
free(temp);
303
JNU_ThrowOutOfMemoryError(env, NULL);
304
return 0;
305
}
306
// check the "encoding_variant" again, if any.
307
if ((p = strchr(temp, '.')) != NULL) {
308
strcpy(encoding_variant, p); /* Copy the leading '.' */
309
*p = '\0';
310
} else if ((p = strchr(temp, '@')) != NULL) {
311
strcpy(encoding_variant, p); /* Copy the leading '@' */
312
*p = '\0';
313
}
314
}
315
316
language = temp;
317
if ((country = strchr(temp, '_')) != NULL) {
318
*country++ = '\0';
319
}
320
321
p = encoding_variant;
322
if ((encoding = strchr(p, '.')) != NULL) {
323
p[encoding++ - p] = '\0';
324
p = encoding;
325
}
326
if ((variant = strchr(p, '@')) != NULL) {
327
p[variant++ - p] = '\0';
328
}
329
330
/* Normalize the language name */
331
if (std_language != NULL) {
332
*std_language = "en";
333
if (language != NULL && mapLookup(language_names, language, std_language) == 0) {
334
*std_language = malloc(strlen(language)+1);
335
strcpy(*std_language, language);
336
}
337
}
338
339
/* Normalize the country name */
340
if (std_country != NULL && country != NULL) {
341
if (mapLookup(country_names, country, std_country) == 0) {
342
*std_country = malloc(strlen(country)+1);
343
strcpy(*std_country, country);
344
}
345
}
346
347
/* Normalize the script and variant name. Note that we only use
348
* variants listed in the mapping array; others are ignored.
349
*/
350
if (variant != NULL) {
351
if (std_script != NULL) {
352
mapLookup(script_names, variant, std_script);
353
}
354
355
if (std_variant != NULL) {
356
mapLookup(variant_names, variant, std_variant);
357
}
358
}
359
360
/* Normalize the encoding name. Note that we IGNORE the string
361
* 'encoding' extracted from the locale name above. Instead, we use the
362
* more reliable method of calling nl_langinfo(CODESET). This function
363
* returns an empty string if no encoding is set for the given locale
364
* (e.g., the C or POSIX locales); we use the default ISO 8859-1
365
* converter for such locales.
366
*/
367
if (std_encoding != NULL) {
368
/* OK, not so reliable - nl_langinfo() gives wrong answers on
369
* Euro locales, in particular. */
370
if (strcmp(p, "ISO8859-15") == 0)
371
p = "ISO8859-15";
372
else
373
p = nl_langinfo(CODESET);
374
375
/* Convert the bare "646" used on Solaris to a proper IANA name */
376
if (strcmp(p, "646") == 0)
377
p = "ISO646-US";
378
379
/* return same result nl_langinfo would return for en_UK,
380
* in order to use optimizations. */
381
*std_encoding = (*p != '\0') ? p : "ISO8859-1";
382
383
#ifdef __linux__
384
/*
385
* Remap the encoding string to a different value for japanese
386
* locales on linux so that customized converters are used instead
387
* of the default converter for "EUC-JP". The customized converters
388
* omit support for the JIS0212 encoding which is not supported by
389
* the variant of "EUC-JP" encoding used on linux
390
*/
391
if (strcmp(p, "EUC-JP") == 0) {
392
*std_encoding = "EUC-JP-LINUX";
393
}
394
#endif
395
396
#ifdef _AIX
397
if (strcmp(p, "big5") == 0) {
398
/* On AIX Traditional Chinese Big5 codeset is mapped to IBM-950 */
399
*std_encoding = "IBM-950";
400
} else if (strcmp(p, "IBM-943") == 0) {
401
/*
402
* On AIX, IBM-943 is mapped to IBM-943C in which symbol 'yen' and
403
* 'overline' are replaced with 'backslash' and 'tilde' from ASCII
404
* making first 96 code points same as ASCII.
405
*/
406
*std_encoding = "IBM-943C";
407
}
408
#endif
409
410
#ifdef MACOSX
411
/*
412
* For the case on MacOS X where encoding is set to US-ASCII, but we
413
* don't have any encoding hints from LANG/LC_ALL/LC_CTYPE, use UTF-8
414
* instead.
415
*
416
* The contents of ASCII files will still be read and displayed
417
* correctly, but so will files containing UTF-8 characters beyond the
418
* standard ASCII range.
419
*
420
* Specifically, this allows apps launched by double-clicking a .jar
421
* file to correctly read UTF-8 files using the default encoding (see
422
* 8011194).
423
*/
424
const char* env_lang = getenv("LANG");
425
const char* env_lc_all = getenv("LC_ALL");
426
const char* env_lc_ctype = getenv("LC_CTYPE");
427
428
if (strcmp(p,"US-ASCII") == 0 &&
429
(env_lang == NULL || strlen(env_lang) == 0) &&
430
(env_lc_all == NULL || strlen(env_lc_all) == 0) &&
431
(env_lc_ctype == NULL || strlen(env_lc_ctype) == 0)) {
432
*std_encoding = "UTF-8";
433
}
434
#endif
435
}
436
437
free(temp);
438
free(encoding_variant);
439
440
return 1;
441
}
442
443
/* This function gets called very early, before VM_CALLS are setup.
444
* Do not use any of the VM_CALLS entries!!!
445
*/
446
java_props_t *
447
GetJavaProperties(JNIEnv *env)
448
{
449
static java_props_t sprops;
450
char *v; /* tmp var */
451
452
if (sprops.user_dir) {
453
return &sprops;
454
}
455
456
/* tmp dir */
457
sprops.tmp_dir = P_tmpdir;
458
#ifdef MACOSX
459
/* darwin has a per-user temp dir */
460
static char tmp_path[PATH_MAX];
461
int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, tmp_path, PATH_MAX);
462
if (pathSize > 0 && pathSize <= PATH_MAX) {
463
sprops.tmp_dir = tmp_path;
464
}
465
#endif /* MACOSX */
466
467
/* patches/service packs installed */
468
sprops.patch_level = NULL; // leave it undefined
469
470
#ifdef SI_ISALIST
471
/* supported instruction sets */
472
{
473
char list[258];
474
sysinfo(SI_ISALIST, list, sizeof(list));
475
sprops.cpu_isalist = strdup(list);
476
}
477
#else
478
sprops.cpu_isalist = NULL;
479
#endif
480
481
/* endianness of platform */
482
{
483
unsigned int endianTest = 0xff000000;
484
if (((char*)(&endianTest))[0] != 0)
485
sprops.cpu_endian = "big";
486
else
487
sprops.cpu_endian = "little";
488
}
489
490
/* os properties */
491
{
492
#ifdef MACOSX
493
setOSNameAndVersion(&sprops);
494
#else
495
struct utsname name;
496
uname(&name);
497
sprops.os_name = strdup(name.sysname);
498
#ifdef _AIX
499
{
500
char *os_version = malloc(strlen(name.version) +
501
strlen(name.release) + 2);
502
if (os_version != NULL) {
503
strcpy(os_version, name.version);
504
strcat(os_version, ".");
505
strcat(os_version, name.release);
506
}
507
sprops.os_version = os_version;
508
}
509
#else
510
sprops.os_version = strdup(name.release);
511
#endif /* _AIX */
512
#endif /* MACOSX */
513
514
sprops.os_arch = ARCHPROPNAME;
515
}
516
517
/* ABI property (optional) */
518
#ifdef JDK_ARCH_ABI_PROP_NAME
519
sprops.sun_arch_abi = JDK_ARCH_ABI_PROP_NAME;
520
#endif
521
522
/* Determine the language, country, variant, and encoding from the host,
523
* and store these in the user.language, user.country, user.variant and
524
* file.encoding system properties. */
525
setlocale(LC_ALL, "");
526
if (ParseLocale(env, LC_CTYPE,
527
&(sprops.format_language),
528
&(sprops.format_script),
529
&(sprops.format_country),
530
&(sprops.format_variant),
531
&(sprops.encoding))) {
532
ParseLocale(env, LC_MESSAGES,
533
&(sprops.display_language),
534
&(sprops.display_script),
535
&(sprops.display_country),
536
&(sprops.display_variant),
537
NULL);
538
} else {
539
sprops.display_language = "en";
540
sprops.encoding = "ISO8859-1";
541
}
542
543
/* ParseLocale failed with OOME */
544
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
545
546
#ifdef MACOSX
547
sprops.sun_jnu_encoding = "UTF-8";
548
#else
549
sprops.sun_jnu_encoding = sprops.encoding;
550
#endif
551
if (isatty(STDOUT_FILENO) == 1) {
552
sprops.sun_stdout_encoding = sprops.encoding;
553
}
554
if (isatty(STDERR_FILENO) == 1) {
555
sprops.sun_stderr_encoding = sprops.encoding;
556
}
557
558
#ifdef _ALLBSD_SOURCE
559
#if BYTE_ORDER == _LITTLE_ENDIAN
560
sprops.unicode_encoding = "UnicodeLittle";
561
#else
562
sprops.unicode_encoding = "UnicodeBig";
563
#endif
564
#else /* !_ALLBSD_SOURCE */
565
#ifdef __linux__
566
#if __BYTE_ORDER == __LITTLE_ENDIAN
567
sprops.unicode_encoding = "UnicodeLittle";
568
#else
569
sprops.unicode_encoding = "UnicodeBig";
570
#endif
571
#else
572
sprops.unicode_encoding = "UnicodeBig";
573
#endif
574
#endif /* _ALLBSD_SOURCE */
575
576
/* user properties */
577
{
578
struct passwd *pwent = getpwuid(getuid());
579
sprops.user_name = pwent ? strdup(pwent->pw_name) : "?";
580
#ifdef MACOSX
581
setUserHome(&sprops);
582
#else
583
sprops.user_home = pwent ? strdup(pwent->pw_dir) : NULL;
584
#endif
585
if (sprops.user_home == NULL) {
586
sprops.user_home = "?";
587
}
588
}
589
590
/* User TIMEZONE
591
* We defer setting up timezone until it's actually necessary.
592
* Refer to TimeZone.getDefault(). The system property
593
* is able to be set by the command line interface -Duser.timezone.
594
*/
595
tzset(); /* for compatibility */
596
597
/* Current directory */
598
{
599
char buf[MAXPATHLEN];
600
errno = 0;
601
if (getcwd(buf, sizeof(buf)) == NULL)
602
JNU_ThrowByName(env, "java/lang/Error",
603
"Properties init: Could not determine current working directory.");
604
else
605
sprops.user_dir = strdup(buf);
606
}
607
608
sprops.file_separator = "/";
609
sprops.path_separator = ":";
610
sprops.line_separator = "\n";
611
612
#ifdef MACOSX
613
setProxyProperties(&sprops);
614
#endif
615
616
return &sprops;
617
}
618
619
jstring
620
GetStringPlatform(JNIEnv *env, nchar* cstr)
621
{
622
return JNU_NewStringPlatform(env, cstr);
623
}
624
625