8273111: Default timezone should return zone ID if /etc/localtime is valid but not canonicalization on linux
Co-authored-by: Sun Jianye <sunjianye@huawei.com> Reviewed-by: naoto, mli
This commit is contained in:
parent
4dec8fc4cc
commit
88bbf3c2e6
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
#include "jvm.h"
|
||||
#include "TimeZone_md.h"
|
||||
#include "path_util.h"
|
||||
|
||||
static char *isFileIdentical(char* buf, size_t size, char *pathname);
|
||||
|
||||
@ -77,6 +78,33 @@ static const char *ETC_ENVIRONMENT_FILE = "/etc/environment";
|
||||
|
||||
#if defined(__linux__) || defined(MACOSX)
|
||||
|
||||
/*
|
||||
* remove repeated path separators ('/') in the given 'path'.
|
||||
*/
|
||||
static void
|
||||
removeDuplicateSlashes(char *path)
|
||||
{
|
||||
char *left = path;
|
||||
char *right = path;
|
||||
char *end = path + strlen(path);
|
||||
|
||||
for (; right < end; right++) {
|
||||
// Skip sequence of multiple path-separators.
|
||||
while (*right == '/' && *(right + 1) == '/') {
|
||||
right++;
|
||||
}
|
||||
|
||||
while (*right != '\0' && !(*right == '/' && *(right + 1) == '/')) {
|
||||
*left++ = *right++;
|
||||
}
|
||||
|
||||
if (*right == '\0') {
|
||||
*left = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a pointer to the zone ID portion of the given zoneinfo file
|
||||
* name, or NULL if the given string doesn't contain "zoneinfo/".
|
||||
@ -296,6 +324,8 @@ getPlatformTimeZoneID()
|
||||
return NULL;
|
||||
}
|
||||
linkbuf[len] = '\0';
|
||||
removeDuplicateSlashes(linkbuf);
|
||||
collapse(linkbuf);
|
||||
tz = getZoneName(linkbuf);
|
||||
if (tz != NULL) {
|
||||
tz = strdup(tz);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,155 +33,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_ALLBSD_SOURCE)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "jdk_util.h"
|
||||
#include "path_util.h"
|
||||
|
||||
/* Note: The comments in this file use the terminology
|
||||
defined in the java.io.File class */
|
||||
|
||||
|
||||
/* Check the given name sequence to see if it can be further collapsed.
|
||||
Return zero if not, otherwise return the number of names in the sequence. */
|
||||
|
||||
static int
|
||||
collapsible(char *names)
|
||||
{
|
||||
char *p = names;
|
||||
int dots = 0, n = 0;
|
||||
|
||||
while (*p) {
|
||||
if ((p[0] == '.') && ((p[1] == '\0')
|
||||
|| (p[1] == '/')
|
||||
|| ((p[1] == '.') && ((p[2] == '\0')
|
||||
|| (p[2] == '/'))))) {
|
||||
dots = 1;
|
||||
}
|
||||
n++;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return (dots ? n : 0);
|
||||
}
|
||||
|
||||
|
||||
/* Split the names in the given name sequence,
|
||||
replacing slashes with nulls and filling in the given index array */
|
||||
|
||||
static void
|
||||
splitNames(char *names, char **ix)
|
||||
{
|
||||
char *p = names;
|
||||
int i = 0;
|
||||
|
||||
while (*p) {
|
||||
ix[i++] = p++;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
*p++ = '\0';
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Join the names in the given name sequence, ignoring names whose index
|
||||
entries have been cleared and replacing nulls with slashes as needed */
|
||||
|
||||
static void
|
||||
joinNames(char *names, int nc, char **ix)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
for (i = 0, p = names; i < nc; i++) {
|
||||
if (!ix[i]) continue;
|
||||
if (i > 0) {
|
||||
p[-1] = '/';
|
||||
}
|
||||
if (p == ix[i]) {
|
||||
p += strlen(p) + 1;
|
||||
} else {
|
||||
char *q = ix[i];
|
||||
while ((*p++ = *q++));
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
|
||||
/* Collapse "." and ".." names in the given path wherever possible.
|
||||
A "." name may always be eliminated; a ".." name may be eliminated if it
|
||||
follows a name that is neither "." nor "..". This is a syntactic operation
|
||||
that performs no filesystem queries, so it should only be used to cleanup
|
||||
after invoking the realpath() procedure. */
|
||||
|
||||
static void
|
||||
collapse(char *path)
|
||||
{
|
||||
char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
|
||||
int nc;
|
||||
char **ix;
|
||||
int i, j;
|
||||
char *p, *q;
|
||||
|
||||
nc = collapsible(names);
|
||||
if (nc < 2) return; /* Nothing to do */
|
||||
ix = (char **)alloca(nc * sizeof(char *));
|
||||
splitNames(names, ix);
|
||||
|
||||
for (i = 0; i < nc; i++) {
|
||||
int dots = 0;
|
||||
|
||||
/* Find next occurrence of "." or ".." */
|
||||
do {
|
||||
char *p = ix[i];
|
||||
if (p[0] == '.') {
|
||||
if (p[1] == '\0') {
|
||||
dots = 1;
|
||||
break;
|
||||
}
|
||||
if ((p[1] == '.') && (p[2] == '\0')) {
|
||||
dots = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while (i < nc);
|
||||
if (i >= nc) break;
|
||||
|
||||
/* At this point i is the index of either a "." or a "..", so take the
|
||||
appropriate action and then continue the outer loop */
|
||||
if (dots == 1) {
|
||||
/* Remove this instance of "." */
|
||||
ix[i] = 0;
|
||||
}
|
||||
else {
|
||||
/* If there is a preceding name, remove both that name and this
|
||||
instance of ".."; otherwise, leave the ".." as is */
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
if (ix[j]) break;
|
||||
}
|
||||
if (j < 0) continue;
|
||||
ix[j] = 0;
|
||||
ix[i] = 0;
|
||||
}
|
||||
/* i will be incremented at the top of the loop */
|
||||
}
|
||||
|
||||
joinNames(names, nc, ix);
|
||||
}
|
||||
|
||||
|
||||
/* Convert a pathname to canonical form. The input path is assumed to contain
|
||||
no duplicate slashes. On Solaris we can use realpath() to do most of the
|
||||
work, though once that's done we still must collapse any remaining "." and
|
||||
|
169
src/java.base/unix/native/libjava/path_util.c
Normal file
169
src/java.base/unix/native/libjava/path_util.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if !defined(_ALLBSD_SOURCE)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include "path_util.h"
|
||||
|
||||
/* Check the given name sequence to see if it can be further collapsed.
|
||||
Return zero if not, otherwise return the number of names in the sequence. */
|
||||
|
||||
static int
|
||||
collapsible(char *names)
|
||||
{
|
||||
char *p = names;
|
||||
int dots = 0, n = 0;
|
||||
|
||||
while (*p) {
|
||||
if ((p[0] == '.') && ((p[1] == '\0')
|
||||
|| (p[1] == '/')
|
||||
|| ((p[1] == '.') && ((p[2] == '\0')
|
||||
|| (p[2] == '/'))))) {
|
||||
dots = 1;
|
||||
}
|
||||
n++;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return (dots ? n : 0);
|
||||
}
|
||||
|
||||
|
||||
/* Split the names in the given name sequence,
|
||||
replacing slashes with nulls and filling in the given index array */
|
||||
|
||||
static void
|
||||
splitNames(char *names, char **ix)
|
||||
{
|
||||
char *p = names;
|
||||
int i = 0;
|
||||
|
||||
while (*p) {
|
||||
ix[i++] = p++;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
*p++ = '\0';
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Join the names in the given name sequence, ignoring names whose index
|
||||
entries have been cleared and replacing nulls with slashes as needed */
|
||||
|
||||
static void
|
||||
joinNames(char *names, int nc, char **ix)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
for (i = 0, p = names; i < nc; i++) {
|
||||
if (!ix[i]) continue;
|
||||
if (i > 0) {
|
||||
p[-1] = '/';
|
||||
}
|
||||
if (p == ix[i]) {
|
||||
p += strlen(p) + 1;
|
||||
} else {
|
||||
char *q = ix[i];
|
||||
while ((*p++ = *q++));
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/* Collapse "." and ".." names in the given path wherever possible.
|
||||
A "." name may always be eliminated; a ".." name may be eliminated if it
|
||||
follows a name that is neither "." nor "..". This is a syntactic operation
|
||||
that performs no filesystem queries, so it should only be used to cleanup
|
||||
after invoking the realpath() procedure. */
|
||||
|
||||
void
|
||||
collapse(char *path)
|
||||
{
|
||||
char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
|
||||
int nc;
|
||||
char **ix;
|
||||
int i, j;
|
||||
char *p, *q;
|
||||
|
||||
nc = collapsible(names);
|
||||
if (nc < 2) return; /* Nothing to do */
|
||||
ix = (char **)alloca(nc * sizeof(char *));
|
||||
splitNames(names, ix);
|
||||
|
||||
for (i = 0; i < nc; i++) {
|
||||
int dots = 0;
|
||||
|
||||
/* Find next occurrence of "." or ".." */
|
||||
do {
|
||||
char *p = ix[i];
|
||||
if (p[0] == '.') {
|
||||
if (p[1] == '\0') {
|
||||
dots = 1;
|
||||
break;
|
||||
}
|
||||
if ((p[1] == '.') && (p[2] == '\0')) {
|
||||
dots = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} while (i < nc);
|
||||
if (i >= nc) break;
|
||||
|
||||
/* At this point i is the index of either a "." or a "..", so take the
|
||||
appropriate action and then continue the outer loop */
|
||||
if (dots == 1) {
|
||||
/* Remove this instance of "." */
|
||||
ix[i] = 0;
|
||||
}
|
||||
else {
|
||||
/* If there is a preceding name, remove both that name and this
|
||||
instance of ".."; otherwise, leave the ".." as is */
|
||||
for (j = i - 1; j >= 0; j--) {
|
||||
if (ix[j]) break;
|
||||
}
|
||||
if (j < 0) continue;
|
||||
ix[j] = 0;
|
||||
ix[i] = 0;
|
||||
}
|
||||
/* i will be incremented at the top of the loop */
|
||||
}
|
||||
|
||||
joinNames(names, nc, ix);
|
||||
}
|
31
src/java.base/unix/native/libjava/path_util.h
Normal file
31
src/java.base/unix/native/libjava/path_util.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#ifndef PATH_UTIL_H
|
||||
#define PATH_UTIL_H
|
||||
|
||||
void collapse(char *path);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user