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/native/java/util/TimeZone_md.c
32287 views
1
/*
2
* Copyright (c) 1999, 2019, 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
#include <stdlib.h>
27
#include <stdio.h>
28
#include <strings.h>
29
#include <time.h>
30
#include <limits.h>
31
#include <errno.h>
32
#include <stddef.h>
33
#include <sys/stat.h>
34
#include <sys/types.h>
35
#include <string.h>
36
#include <dirent.h>
37
#include <unistd.h>
38
#if defined(__solaris__)
39
#include <libscf.h>
40
#endif
41
42
#include "jvm.h"
43
#include "TimeZone_md.h"
44
45
static char *isFileIdentical(char* buf, size_t size, char *pathname);
46
47
#define SKIP_SPACE(p) while (*p == ' ' || *p == '\t') p++;
48
49
#if defined(_ALLBSD_SOURCE)
50
#define dirent64 dirent
51
#define readdir64_r readdir_r
52
#endif
53
54
#if !defined(__solaris__) || defined(__sparcv9) || defined(amd64)
55
#define fileopen fopen
56
#define filegets fgets
57
#define fileclose fclose
58
#endif
59
60
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
61
static const char *ETC_TIMEZONE_FILE = "/etc/timezone";
62
static const char *ZONEINFO_DIR = "/usr/share/zoneinfo";
63
static const char *DEFAULT_ZONEINFO_FILE = "/etc/localtime";
64
#else
65
static const char *SYS_INIT_FILE = "/etc/default/init";
66
static const char *ZONEINFO_DIR = "/usr/share/lib/zoneinfo";
67
static const char *DEFAULT_ZONEINFO_FILE = "/usr/share/lib/zoneinfo/localtime";
68
#endif /* defined(__linux__) || defined(_ALLBSD_SOURCE) */
69
70
static const char popularZones[][4] = {"UTC", "GMT"};
71
72
#if defined(_AIX)
73
static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
74
#endif
75
76
#if defined(__linux__) || defined(MACOSX) || defined(__solaris__)
77
78
/*
79
* Returns a pointer to the zone ID portion of the given zoneinfo file
80
* name, or NULL if the given string doesn't contain "zoneinfo/".
81
*/
82
static char *
83
getZoneName(char *str)
84
{
85
static const char *zidir = "zoneinfo/";
86
87
char *pos = strstr((const char *)str, zidir);
88
if (pos == NULL) {
89
return NULL;
90
}
91
return pos + strlen(zidir);
92
}
93
94
/*
95
* Returns a path name created from the given 'dir' and 'name' under
96
* UNIX. This function allocates memory for the pathname calling
97
* malloc(). NULL is returned if malloc() fails.
98
*/
99
static char *
100
getPathName(const char *dir, const char *name) {
101
char *path;
102
103
path = (char *) malloc(strlen(dir) + strlen(name) + 2);
104
if (path == NULL) {
105
return NULL;
106
}
107
return strcat(strcat(strcpy(path, dir), "/"), name);
108
}
109
110
/*
111
* Scans the specified directory and its subdirectories to find a
112
* zoneinfo file which has the same content as /etc/localtime on Linux
113
* or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
114
* If file is symbolic link, then the contents it points to are in buf.
115
* Returns a zone ID if found, otherwise, NULL is returned.
116
*/
117
static char *
118
findZoneinfoFile(char *buf, size_t size, const char *dir)
119
{
120
DIR *dirp = NULL;
121
struct dirent64 *dp = NULL;
122
struct dirent64 *entry = NULL;
123
char *pathname = NULL;
124
char *tz = NULL;
125
long name_max = 0;
126
127
if (strcmp(dir, ZONEINFO_DIR) == 0) {
128
/* fast path for 1st iteration */
129
unsigned int i;
130
for (i = 0; i < sizeof (popularZones) / sizeof (popularZones[0]); i++) {
131
pathname = getPathName(dir, popularZones[i]);
132
if (pathname == NULL) {
133
continue;
134
}
135
tz = isFileIdentical(buf, size, pathname);
136
free((void *) pathname);
137
pathname = NULL;
138
if (tz != NULL) {
139
return tz;
140
}
141
}
142
}
143
144
dirp = opendir(dir);
145
if (dirp == NULL) {
146
return NULL;
147
}
148
149
name_max = pathconf(dir, _PC_NAME_MAX);
150
// If pathconf did not work, fall back to a mimimum buffer size.
151
if (name_max < 1024) {
152
name_max = 1024;
153
}
154
155
entry = (struct dirent64 *)malloc(offsetof(struct dirent64, d_name) + name_max + 1);
156
if (entry == NULL) {
157
(void) closedir(dirp);
158
return NULL;
159
}
160
161
while (readdir64_r(dirp, entry, &dp) == 0 && dp != NULL) {
162
/*
163
* Skip '.' and '..' (and possibly other .* files)
164
*/
165
if (dp->d_name[0] == '.') {
166
continue;
167
}
168
169
/*
170
* Skip "ROC", "posixrules", and "localtime".
171
*/
172
if ((strcmp(dp->d_name, "ROC") == 0)
173
|| (strcmp(dp->d_name, "posixrules") == 0)
174
#if defined(__solaris__)
175
/*
176
* Skip the "src" and "tab" directories on Solaris.
177
*/
178
|| (strcmp(dp->d_name, "src") == 0)
179
|| (strcmp(dp->d_name, "tab") == 0)
180
#endif
181
|| (strcmp(dp->d_name, "localtime") == 0)) {
182
continue;
183
}
184
185
pathname = getPathName(dir, dp->d_name);
186
if (pathname == NULL) {
187
break;
188
}
189
190
tz = isFileIdentical(buf, size, pathname);
191
192
free((void *) pathname);
193
pathname = NULL;
194
if (tz != NULL) {
195
break;
196
}
197
}
198
199
if (entry != NULL) {
200
free((void *) entry);
201
}
202
if (dirp != NULL) {
203
(void) closedir(dirp);
204
}
205
return tz;
206
}
207
208
/*
209
* Checks if the file pointed to by pathname matches
210
* the data contents in buf.
211
* Returns a representation of the timezone file name
212
* if file match is found, otherwise NULL.
213
*/
214
static char *
215
isFileIdentical(char *buf, size_t size, char *pathname)
216
{
217
char *possibleMatch = NULL;
218
struct stat statbuf;
219
char *dbuf = NULL;
220
int fd = -1;
221
int res;
222
223
if (stat(pathname, &statbuf) == -1) {
224
return NULL;
225
}
226
227
if (S_ISDIR(statbuf.st_mode)) {
228
possibleMatch = findZoneinfoFile(buf, size, pathname);
229
} else if (S_ISREG(statbuf.st_mode) && (size_t)statbuf.st_size == size) {
230
dbuf = (char *) malloc(size);
231
if (dbuf == NULL) {
232
return NULL;
233
}
234
if ((fd = open(pathname, O_RDONLY)) == -1) {
235
goto freedata;
236
}
237
if (read(fd, dbuf, size) != (ssize_t) size) {
238
goto freedata;
239
}
240
if (memcmp(buf, dbuf, size) == 0) {
241
possibleMatch = getZoneName(pathname);
242
if (possibleMatch != NULL) {
243
possibleMatch = strdup(possibleMatch);
244
}
245
}
246
freedata:
247
free((void *) dbuf);
248
dbuf = NULL;
249
(void) close(fd);
250
}
251
return possibleMatch;
252
}
253
254
#if defined(__linux__) || defined(MACOSX)
255
256
/*
257
* Performs Linux specific mapping and returns a zone ID
258
* if found. Otherwise, NULL is returned.
259
*/
260
static char *
261
getPlatformTimeZoneID()
262
{
263
struct stat statbuf;
264
char *tz = NULL;
265
FILE *fp;
266
int fd;
267
char *buf;
268
size_t size;
269
270
#if defined(__linux__)
271
/*
272
* Try reading the /etc/timezone file for Debian distros. There's
273
* no spec of the file format available. This parsing assumes that
274
* there's one line of an Olson tzid followed by a '\n', no
275
* leading or trailing spaces, no comments.
276
*/
277
if ((fp = fopen(ETC_TIMEZONE_FILE, "r")) != NULL) {
278
char line[256];
279
280
if (fgets(line, sizeof(line), fp) != NULL) {
281
char *p = strchr(line, '\n');
282
if (p != NULL) {
283
*p = '\0';
284
}
285
if (strlen(line) > 0) {
286
tz = strdup(line);
287
}
288
}
289
(void) fclose(fp);
290
if (tz != NULL) {
291
return tz;
292
}
293
}
294
#endif /* defined(__linux__) */
295
296
/*
297
* Next, try /etc/localtime to find the zone ID.
298
*/
299
if (lstat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
300
return NULL;
301
}
302
303
/*
304
* If it's a symlink, get the link name and its zone ID part. (The
305
* older versions of timeconfig created a symlink as described in
306
* the Red Hat man page. It was changed in 1999 to create a copy
307
* of a zoneinfo file. It's no longer possible to get the zone ID
308
* from /etc/localtime.)
309
*/
310
if (S_ISLNK(statbuf.st_mode)) {
311
char linkbuf[PATH_MAX+1];
312
int len;
313
314
if ((len = readlink(DEFAULT_ZONEINFO_FILE, linkbuf, sizeof(linkbuf)-1)) == -1) {
315
jio_fprintf(stderr, (const char *) "can't get a symlink of %s\n",
316
DEFAULT_ZONEINFO_FILE);
317
return NULL;
318
}
319
linkbuf[len] = '\0';
320
tz = getZoneName(linkbuf);
321
if (tz != NULL) {
322
tz = strdup(tz);
323
return tz;
324
}
325
}
326
327
/*
328
* If it's a regular file, we need to find out the same zoneinfo file
329
* that has been copied as /etc/localtime.
330
* If initial symbolic link resolution failed, we should treat target
331
* file as a regular file.
332
*/
333
if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
334
return NULL;
335
}
336
if (fstat(fd, &statbuf) == -1) {
337
(void) close(fd);
338
return NULL;
339
}
340
size = (size_t) statbuf.st_size;
341
buf = (char *) malloc(size);
342
if (buf == NULL) {
343
(void) close(fd);
344
return NULL;
345
}
346
347
if (read(fd, buf, size) != (ssize_t) size) {
348
(void) close(fd);
349
free((void *) buf);
350
return NULL;
351
}
352
(void) close(fd);
353
354
tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
355
free((void *) buf);
356
return tz;
357
}
358
359
#elif defined(__solaris__)
360
361
#if !defined(__sparcv9) && !defined(amd64)
362
363
/*
364
* Those file* functions mimic the UNIX stream io functions. This is
365
* because of the limitation of the number of open files on Solaris
366
* (32-bit mode only) due to the System V ABI.
367
*/
368
369
#define BUFFER_SIZE 4096
370
371
static struct iobuffer {
372
int magic; /* -1 to distinguish from the real FILE */
373
int fd; /* file descriptor */
374
char *buffer; /* pointer to buffer */
375
char *ptr; /* current read pointer */
376
char *endptr; /* end pointer */
377
};
378
379
static int
380
fileclose(FILE *stream)
381
{
382
struct iobuffer *iop = (struct iobuffer *) stream;
383
384
if (iop->magic != -1) {
385
return fclose(stream);
386
}
387
388
if (iop == NULL) {
389
return 0;
390
}
391
close(iop->fd);
392
free((void *)iop->buffer);
393
free((void *)iop);
394
return 0;
395
}
396
397
static FILE *
398
fileopen(const char *fname, const char *fmode)
399
{
400
FILE *fp;
401
int fd;
402
struct iobuffer *iop;
403
404
if ((fp = fopen(fname, fmode)) != NULL) {
405
return fp;
406
}
407
408
/*
409
* It assumes read open.
410
*/
411
if ((fd = open(fname, O_RDONLY)) == -1) {
412
return NULL;
413
}
414
415
/*
416
* Allocate struct iobuffer and its buffer
417
*/
418
iop = malloc(sizeof(struct iobuffer));
419
if (iop == NULL) {
420
(void) close(fd);
421
errno = ENOMEM;
422
return NULL;
423
}
424
iop->magic = -1;
425
iop->fd = fd;
426
iop->buffer = malloc(BUFFER_SIZE);
427
if (iop->buffer == NULL) {
428
(void) close(fd);
429
free((void *) iop);
430
errno = ENOMEM;
431
return NULL;
432
}
433
iop->ptr = iop->buffer;
434
iop->endptr = iop->buffer;
435
return (FILE *)iop;
436
}
437
438
/*
439
* This implementation assumes that n is large enough and the line
440
* separator is '\n'.
441
*/
442
static char *
443
filegets(char *s, int n, FILE *stream)
444
{
445
struct iobuffer *iop = (struct iobuffer *) stream;
446
char *p;
447
448
if (iop->magic != -1) {
449
return fgets(s, n, stream);
450
}
451
452
p = s;
453
for (;;) {
454
char c;
455
456
if (iop->ptr == iop->endptr) {
457
ssize_t len;
458
459
if ((len = read(iop->fd, (void *)iop->buffer, BUFFER_SIZE)) == -1) {
460
return NULL;
461
}
462
if (len == 0) {
463
*p = 0;
464
if (s == p) {
465
return NULL;
466
}
467
return s;
468
}
469
iop->ptr = iop->buffer;
470
iop->endptr = iop->buffer + len;
471
}
472
c = *iop->ptr++;
473
*p++ = c;
474
if ((p - s) == (n - 1)) {
475
*p = 0;
476
return s;
477
}
478
if (c == '\n') {
479
*p = 0;
480
return s;
481
}
482
}
483
/*NOTREACHED*/
484
}
485
#endif /* !defined(__sparcv9) && !defined(amd64) */
486
487
/*
488
* Performs Solaris dependent mapping. Returns a zone ID if
489
* found. Otherwise, NULL is returned. Solaris libc looks up
490
* "/etc/default/init" to get the default TZ value if TZ is not defined
491
* as an environment variable.
492
*/
493
static char *
494
getPlatformTimeZoneID()
495
{
496
char *tz = NULL;
497
FILE *fp;
498
499
/*
500
* Try the TZ entry in /etc/default/init.
501
*/
502
if ((fp = fileopen(SYS_INIT_FILE, "r")) != NULL) {
503
char line[256];
504
char quote = '\0';
505
506
while (filegets(line, sizeof(line), fp) != NULL) {
507
char *p = line;
508
char *s;
509
char c;
510
511
/* quick check for comment lines */
512
if (*p == '#') {
513
continue;
514
}
515
if (strncmp(p, "TZ=", 3) == 0) {
516
p += 3;
517
SKIP_SPACE(p);
518
c = *p;
519
if (c == '"' || c == '\'') {
520
quote = c;
521
p++;
522
}
523
524
/*
525
* PSARC/2001/383: quoted string support
526
*/
527
for (s = p; (c = *s) != '\0' && c != '\n'; s++) {
528
/* No '\\' is supported here. */
529
if (c == quote) {
530
quote = '\0';
531
break;
532
}
533
if (c == ' ' && quote == '\0') {
534
break;
535
}
536
}
537
if (quote != '\0') {
538
jio_fprintf(stderr, "ZoneInfo: unterminated time zone name in /etc/TIMEZONE\n");
539
}
540
*s = '\0';
541
tz = strdup(p);
542
break;
543
}
544
}
545
(void) fileclose(fp);
546
}
547
return tz;
548
}
549
550
#define TIMEZONE_FMRI "svc:/system/timezone:default"
551
#define TIMEZONE_PG "timezone"
552
#define LOCALTIME_PROP "localtime"
553
554
static void
555
cleanupScf(scf_handle_t *h,
556
scf_snapshot_t *snap,
557
scf_instance_t *inst,
558
scf_propertygroup_t *pg,
559
scf_property_t *prop,
560
scf_value_t *val,
561
char *buf) {
562
if (buf != NULL) {
563
free(buf);
564
}
565
if (snap != NULL) {
566
scf_snapshot_destroy(snap);
567
}
568
if (val != NULL) {
569
scf_value_destroy(val);
570
}
571
if (prop != NULL) {
572
scf_property_destroy(prop);
573
}
574
if (pg != NULL) {
575
scf_pg_destroy(pg);
576
}
577
if (inst != NULL) {
578
scf_instance_destroy(inst);
579
}
580
if (h != NULL) {
581
scf_handle_destroy(h);
582
}
583
}
584
585
/*
586
* Returns a zone ID of Solaris when the TZ value is "localtime".
587
* First, it tries scf. If scf fails, it looks for the same file as
588
* /usr/share/lib/zoneinfo/localtime under /usr/share/lib/zoneinfo/.
589
*/
590
static char *
591
getSolarisDefaultZoneID() {
592
char *tz = NULL;
593
struct stat statbuf;
594
size_t size;
595
char *buf;
596
int fd;
597
/* scf specific variables */
598
scf_handle_t *h = NULL;
599
scf_snapshot_t *snap = NULL;
600
scf_instance_t *inst = NULL;
601
scf_propertygroup_t *pg = NULL;
602
scf_property_t *prop = NULL;
603
scf_value_t *val = NULL;
604
605
if ((h = scf_handle_create(SCF_VERSION)) != NULL
606
&& scf_handle_bind(h) == 0
607
&& (inst = scf_instance_create(h)) != NULL
608
&& (snap = scf_snapshot_create(h)) != NULL
609
&& (pg = scf_pg_create(h)) != NULL
610
&& (prop = scf_property_create(h)) != NULL
611
&& (val = scf_value_create(h)) != NULL
612
&& scf_handle_decode_fmri(h, TIMEZONE_FMRI, NULL, NULL, inst,
613
NULL, NULL, SCF_DECODE_FMRI_REQUIRE_INSTANCE) == 0
614
&& scf_instance_get_snapshot(inst, "running", snap) == 0
615
&& scf_instance_get_pg_composed(inst, snap, TIMEZONE_PG, pg) == 0
616
&& scf_pg_get_property(pg, LOCALTIME_PROP, prop) == 0
617
&& scf_property_get_value(prop, val) == 0) {
618
ssize_t len;
619
620
/* Gets the length of the zone ID string */
621
len = scf_value_get_astring(val, NULL, 0);
622
if (len != -1) {
623
tz = malloc(++len); /* +1 for a null byte */
624
if (tz != NULL && scf_value_get_astring(val, tz, len) != -1) {
625
cleanupScf(h, snap, inst, pg, prop, val, NULL);
626
return tz;
627
}
628
}
629
}
630
cleanupScf(h, snap, inst, pg, prop, val, tz);
631
632
if (stat(DEFAULT_ZONEINFO_FILE, &statbuf) == -1) {
633
return NULL;
634
}
635
size = (size_t) statbuf.st_size;
636
buf = malloc(size);
637
if (buf == NULL) {
638
return NULL;
639
}
640
if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
641
free((void *) buf);
642
return NULL;
643
}
644
645
if (read(fd, buf, size) != (ssize_t) size) {
646
(void) close(fd);
647
free((void *) buf);
648
return NULL;
649
}
650
(void) close(fd);
651
tz = findZoneinfoFile(buf, size, ZONEINFO_DIR);
652
free((void *) buf);
653
return tz;
654
}
655
656
#endif /* defined(__solaris__) */
657
658
#elif defined(_AIX)
659
660
static char *
661
getPlatformTimeZoneID()
662
{
663
FILE *fp;
664
char *tz = NULL;
665
char *tz_key = "TZ=";
666
char line[256];
667
size_t tz_key_len = strlen(tz_key);
668
669
if ((fp = fopen(ETC_ENVIRONMENT_FILE, "r")) != NULL) {
670
while (fgets(line, sizeof(line), fp) != NULL) {
671
char *p = strchr(line, '\n');
672
if (p != NULL) {
673
*p = '\0';
674
}
675
if (0 == strncmp(line, tz_key, tz_key_len)) {
676
tz = strdup(line + tz_key_len);
677
break;
678
}
679
}
680
(void) fclose(fp);
681
}
682
683
return tz;
684
}
685
686
static char *
687
mapPlatformToJavaTimezone(const char *java_home_dir, const char *tz) {
688
FILE *tzmapf;
689
char mapfilename[PATH_MAX + 1];
690
char line[256];
691
int linecount = 0;
692
char *tz_buf = NULL;
693
char *temp_tz = NULL;
694
char *javatz = NULL;
695
size_t tz_len = 0;
696
697
/* On AIX, the TZ environment variable may end with a comma
698
* followed by modifier fields. These are ignored here. */
699
temp_tz = strchr(tz, ',');
700
tz_len = (temp_tz == NULL) ? strlen(tz) : temp_tz - tz;
701
tz_buf = (char *)malloc(tz_len + 1);
702
memcpy(tz_buf, tz, tz_len);
703
tz_buf[tz_len] = 0;
704
705
/* Open tzmappings file, with buffer overrun check */
706
if ((strlen(java_home_dir) + 15) > PATH_MAX) {
707
jio_fprintf(stderr, "Path %s/lib/tzmappings exceeds maximum path length\n", java_home_dir);
708
goto tzerr;
709
}
710
strcpy(mapfilename, java_home_dir);
711
strcat(mapfilename, "/lib/tzmappings");
712
if ((tzmapf = fopen(mapfilename, "r")) == NULL) {
713
jio_fprintf(stderr, "can't open %s\n", mapfilename);
714
goto tzerr;
715
}
716
717
while (fgets(line, sizeof(line), tzmapf) != NULL) {
718
char *p = line;
719
char *sol = line;
720
char *java;
721
int result;
722
723
linecount++;
724
/*
725
* Skip comments and blank lines
726
*/
727
if (*p == '#' || *p == '\n') {
728
continue;
729
}
730
731
/*
732
* Get the first field, platform zone ID
733
*/
734
while (*p != '\0' && *p != '\t') {
735
p++;
736
}
737
if (*p == '\0') {
738
/* mapping table is broken! */
739
jio_fprintf(stderr, "tzmappings: Illegal format at near line %d.\n", linecount);
740
break;
741
}
742
743
*p++ = '\0';
744
if ((result = strncmp(tz_buf, sol, tz_len)) == 0) {
745
/*
746
* If this is the current platform zone ID,
747
* take the Java time zone ID (2nd field).
748
*/
749
java = p;
750
while (*p != '\0' && *p != '\n') {
751
p++;
752
}
753
754
if (*p == '\0') {
755
/* mapping table is broken! */
756
jio_fprintf(stderr, "tzmappings: Illegal format at line %d.\n", linecount);
757
break;
758
}
759
760
*p = '\0';
761
javatz = strdup(java);
762
break;
763
} else if (result < 0) {
764
break;
765
}
766
}
767
(void) fclose(tzmapf);
768
769
tzerr:
770
if (tz_buf != NULL ) {
771
free((void *) tz_buf);
772
}
773
774
if (javatz == NULL) {
775
return getGMTOffsetID();
776
}
777
778
return javatz;
779
}
780
781
#endif /* defined(_AIX) */
782
783
/*
784
* findJavaTZ_md() maps platform time zone ID to Java time zone ID
785
* using <java_home>/lib/tzmappings. If the TZ value is not found, it
786
* trys some libc implementation dependent mappings. If it still
787
* can't map to a Java time zone ID, it falls back to the GMT+/-hh:mm
788
* form.
789
*/
790
/*ARGSUSED1*/
791
char *
792
findJavaTZ_md(const char *java_home_dir)
793
{
794
char *tz;
795
char *javatz = NULL;
796
char *freetz = NULL;
797
798
tz = getenv("TZ");
799
800
if (tz == NULL || *tz == '\0') {
801
tz = getPlatformTimeZoneID();
802
freetz = tz;
803
}
804
805
if (tz != NULL) {
806
/* Ignore preceding ':' */
807
if (*tz == ':') {
808
tz++;
809
}
810
#if defined(__linux__)
811
/* Ignore "posix/" prefix on Linux. */
812
if (strncmp(tz, "posix/", 6) == 0) {
813
tz += 6;
814
}
815
#endif
816
817
#if defined(_AIX)
818
/* On AIX do the platform to Java mapping. */
819
javatz = mapPlatformToJavaTimezone(java_home_dir, tz);
820
if (freetz != NULL) {
821
free((void *) freetz);
822
}
823
#else
824
#if defined(__solaris__)
825
/* Solaris might use localtime, so handle it here. */
826
if (strcmp(tz, "localtime") == 0) {
827
javatz = getSolarisDefaultZoneID();
828
if (freetz != NULL) {
829
free((void *) freetz);
830
}
831
} else
832
#endif
833
if (freetz == NULL) {
834
/* strdup if we are still working on getenv result. */
835
javatz = strdup(tz);
836
} else if (freetz != tz) {
837
/* strdup and free the old buffer, if we moved the pointer. */
838
javatz = strdup(tz);
839
free((void *) freetz);
840
} else {
841
/* we are good if we already work on a freshly allocated buffer. */
842
javatz = tz;
843
}
844
#endif
845
}
846
847
return javatz;
848
}
849
850
/**
851
* Returns a GMT-offset-based zone ID. (e.g., "GMT-08:00")
852
*/
853
854
#if defined(MACOSX)
855
856
char *
857
getGMTOffsetID()
858
{
859
time_t offset;
860
char sign, buf[32];
861
struct tm *local_tm;
862
time_t clock;
863
time_t currenttime;
864
865
clock = time(NULL);
866
tzset();
867
local_tm = localtime(&clock);
868
if (local_tm->tm_gmtoff >= 0) {
869
offset = (time_t) local_tm->tm_gmtoff;
870
sign = '+';
871
} else {
872
offset = (time_t) -local_tm->tm_gmtoff;
873
sign = '-';
874
}
875
sprintf(buf, (const char *)"GMT%c%02d:%02d",
876
sign, (int)(offset/3600), (int)((offset%3600)/60));
877
return strdup(buf);
878
}
879
880
#else
881
882
char *
883
getGMTOffsetID()
884
{
885
time_t offset;
886
char sign, buf[32];
887
#if defined(__solaris__)
888
struct tm localtm;
889
time_t currenttime;
890
891
currenttime = time(NULL);
892
if (localtime_r(&currenttime, &localtm) == NULL) {
893
return NULL;
894
}
895
896
offset = localtm.tm_isdst ? altzone : timezone;
897
#else
898
offset = timezone;
899
#endif
900
901
if (offset == 0) {
902
return strdup("GMT");
903
}
904
905
/* Note that the time offset direction is opposite. */
906
if (offset > 0) {
907
sign = '-';
908
} else {
909
offset = -offset;
910
sign = '+';
911
}
912
sprintf(buf, (const char *)"GMT%c%02d:%02d",
913
sign, (int)(offset/3600), (int)((offset%3600)/60));
914
return strdup(buf);
915
}
916
#endif /* MACOSX */
917
918