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