Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/unix/native/libjava/canonicalize_md.c
41119 views
1
/*
2
* Copyright (c) 1994, 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
/*
27
* Pathname canonicalization for Unix file systems
28
*/
29
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <sys/stat.h>
34
#include <errno.h>
35
#include <limits.h>
36
#if !defined(_ALLBSD_SOURCE)
37
#include <alloca.h>
38
#endif
39
40
#include "jdk_util.h"
41
42
/* Note: The comments in this file use the terminology
43
defined in the java.io.File class */
44
45
46
/* Check the given name sequence to see if it can be further collapsed.
47
Return zero if not, otherwise return the number of names in the sequence. */
48
49
static int
50
collapsible(char *names)
51
{
52
char *p = names;
53
int dots = 0, n = 0;
54
55
while (*p) {
56
if ((p[0] == '.') && ((p[1] == '\0')
57
|| (p[1] == '/')
58
|| ((p[1] == '.') && ((p[2] == '\0')
59
|| (p[2] == '/'))))) {
60
dots = 1;
61
}
62
n++;
63
while (*p) {
64
if (*p == '/') {
65
p++;
66
break;
67
}
68
p++;
69
}
70
}
71
return (dots ? n : 0);
72
}
73
74
75
/* Split the names in the given name sequence,
76
replacing slashes with nulls and filling in the given index array */
77
78
static void
79
splitNames(char *names, char **ix)
80
{
81
char *p = names;
82
int i = 0;
83
84
while (*p) {
85
ix[i++] = p++;
86
while (*p) {
87
if (*p == '/') {
88
*p++ = '\0';
89
break;
90
}
91
p++;
92
}
93
}
94
}
95
96
97
/* Join the names in the given name sequence, ignoring names whose index
98
entries have been cleared and replacing nulls with slashes as needed */
99
100
static void
101
joinNames(char *names, int nc, char **ix)
102
{
103
int i;
104
char *p;
105
106
for (i = 0, p = names; i < nc; i++) {
107
if (!ix[i]) continue;
108
if (i > 0) {
109
p[-1] = '/';
110
}
111
if (p == ix[i]) {
112
p += strlen(p) + 1;
113
} else {
114
char *q = ix[i];
115
while ((*p++ = *q++));
116
}
117
}
118
*p = '\0';
119
}
120
121
122
/* Collapse "." and ".." names in the given path wherever possible.
123
A "." name may always be eliminated; a ".." name may be eliminated if it
124
follows a name that is neither "." nor "..". This is a syntactic operation
125
that performs no filesystem queries, so it should only be used to cleanup
126
after invoking the realpath() procedure. */
127
128
static void
129
collapse(char *path)
130
{
131
char *names = (path[0] == '/') ? path + 1 : path; /* Preserve first '/' */
132
int nc;
133
char **ix;
134
int i, j;
135
char *p, *q;
136
137
nc = collapsible(names);
138
if (nc < 2) return; /* Nothing to do */
139
ix = (char **)alloca(nc * sizeof(char *));
140
splitNames(names, ix);
141
142
for (i = 0; i < nc; i++) {
143
int dots = 0;
144
145
/* Find next occurrence of "." or ".." */
146
do {
147
char *p = ix[i];
148
if (p[0] == '.') {
149
if (p[1] == '\0') {
150
dots = 1;
151
break;
152
}
153
if ((p[1] == '.') && (p[2] == '\0')) {
154
dots = 2;
155
break;
156
}
157
}
158
i++;
159
} while (i < nc);
160
if (i >= nc) break;
161
162
/* At this point i is the index of either a "." or a "..", so take the
163
appropriate action and then continue the outer loop */
164
if (dots == 1) {
165
/* Remove this instance of "." */
166
ix[i] = 0;
167
}
168
else {
169
/* If there is a preceding name, remove both that name and this
170
instance of ".."; otherwise, leave the ".." as is */
171
for (j = i - 1; j >= 0; j--) {
172
if (ix[j]) break;
173
}
174
if (j < 0) continue;
175
ix[j] = 0;
176
ix[i] = 0;
177
}
178
/* i will be incremented at the top of the loop */
179
}
180
181
joinNames(names, nc, ix);
182
}
183
184
185
/* Convert a pathname to canonical form. The input path is assumed to contain
186
no duplicate slashes. On Solaris we can use realpath() to do most of the
187
work, though once that's done we still must collapse any remaining "." and
188
".." names by hand. */
189
190
JNIEXPORT int
191
JDK_Canonicalize(const char *orig, char *out, int len)
192
{
193
if (len < PATH_MAX) {
194
errno = EINVAL;
195
return -1;
196
}
197
198
if (strlen(orig) > PATH_MAX) {
199
errno = ENAMETOOLONG;
200
return -1;
201
}
202
203
/* First try realpath() on the entire path */
204
if (realpath(orig, out)) {
205
/* That worked, so return it */
206
collapse(out);
207
return 0;
208
} else {
209
/* Something's bogus in the original path, so remove names from the end
210
until either some subpath works or we run out of names */
211
char *p, *end, *r = NULL;
212
char path[PATH_MAX + 1];
213
214
// strlen(orig) <= PATH_MAX, see above
215
strncpy(path, orig, PATH_MAX);
216
// append null for == case
217
path[PATH_MAX] = '\0';
218
end = path + strlen(path);
219
220
for (p = end; p > path;) {
221
222
/* Skip last element */
223
while ((--p > path) && (*p != '/'));
224
if (p == path) break;
225
226
/* Try realpath() on this subpath */
227
*p = '\0';
228
r = realpath(path, out);
229
*p = (p == end) ? '\0' : '/';
230
231
if (r != NULL) {
232
/* The subpath has a canonical path */
233
break;
234
} else if (errno == ENOENT || errno == ENOTDIR || errno == EACCES) {
235
/* If the lookup of a particular subpath fails because the file
236
does not exist, because it is of the wrong type, or because
237
access is denied, then remove its last name and try again.
238
Other I/O problems cause an error return. */
239
continue;
240
} else {
241
return -1;
242
}
243
}
244
245
if (r != NULL) {
246
/* Append unresolved subpath to resolved subpath */
247
int rn = strlen(r);
248
if (rn + (int)strlen(p) >= len) {
249
/* Buffer overflow */
250
errno = ENAMETOOLONG;
251
return -1;
252
}
253
if ((rn > 0) && (r[rn - 1] == '/') && (*p == '/')) {
254
/* Avoid duplicate slashes */
255
p++;
256
}
257
strcpy(r + rn, p);
258
collapse(r);
259
return 0;
260
} else {
261
/* Nothing resolved, so just return the original path */
262
strcpy(out, path);
263
collapse(out);
264
return 0;
265
}
266
}
267
}
268
269