Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.instrument/windows/native/libinstrument/FileSystemSupport_md.c
41152 views
1
/*
2
* Copyright (c) 2004, 2020, 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 <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <malloc.h>
30
31
#include "FileSystemSupport_md.h"
32
33
/*
34
* Windows implementation of file system support functions
35
*/
36
37
#define slash '\\'
38
#define altSlash '/'
39
40
static int isSlash(char c) {
41
return (c == '\\') || (c == '/');
42
}
43
44
static int isLetter(char c) {
45
return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));
46
}
47
48
char* basePath(const char* path) {
49
char* pos = strchr(path, slash);
50
char* last = NULL;
51
while (pos != NULL) {
52
last = pos;
53
pos++;
54
pos = strchr(pos, slash);
55
}
56
if (last == NULL) {
57
return (char*)path;
58
} else {
59
int len = (int)(last - path);
60
char* str = (char*)malloc(len+1);
61
if (str == NULL) {
62
fprintf(stderr, "OOM error in native tmp buffer allocation");
63
return NULL;
64
}
65
if (len > 0) {
66
memcpy(str, path, len);
67
}
68
str[len] = '\0';
69
return str;
70
}
71
}
72
73
74
75
/* -- Normalization - src/windows/classes/java/io/Win32FileSystem.java */
76
77
78
/* A normal Win32 pathname contains no duplicate slashes, except possibly
79
* for a UNC prefix, and does not end with a slash. It may be the empty
80
* string. Normalized Win32 pathnames have the convenient property that
81
* the length of the prefix almost uniquely identifies the type of the path
82
* and whether it is absolute or relative:
83
*
84
* 0 relative to both drive and directory
85
* 1 drive-relative (begins with '\\')
86
* 2 absolute UNC (if first char is '\\'),
87
* else directory-relative (has form "z:foo")
88
* 3 absolute local pathname (begins with "z:\\")
89
*/
90
static int normalizePrefix(const char* path, int len, char* sb, int* sbLen) {
91
char c;
92
int src = 0;
93
while ((src < len) && isSlash(path[src])) src++;
94
if ((len - src >= 2)
95
&& isLetter(c = path[src])
96
&& path[src + 1] == ':') {
97
/* Remove leading slashes if followed by drive specifier.
98
This hack is necessary to support file URLs containing drive
99
specifiers (e.g., "file://c:/path"). As a side effect,
100
"/c:/path" can be used as an alternative to "c:/path". */
101
sb[(*sbLen)++] = c;
102
sb[(*sbLen)++] = ':';
103
src += 2;
104
} else {
105
src = 0;
106
if ((len >= 2)
107
&& isSlash(path[0])
108
&& isSlash(path[1])) {
109
/* UNC pathname: Retain first slash; leave src pointed at
110
second slash so that further slashes will be collapsed
111
into the second slash. The result will be a pathname
112
beginning with "\\\\" followed (most likely) by a host
113
name. */
114
src = 1;
115
sb[(*sbLen)++] = slash;
116
}
117
}
118
return src;
119
}
120
121
/*
122
* Normalize the given pathname, whose length is len, starting at the given
123
* offset; everything before this offset is already normal.
124
*/
125
static char* normalizePath(const char* path, int len, int off) {
126
int src;
127
char* sb;
128
int sbLen;
129
130
if (len == 0) return (char*)path;
131
if (off < 3) off = 0; /* Avoid fencepost cases with UNC pathnames */
132
133
sb = (char*)malloc(len+1);
134
if (sb == NULL) {
135
fprintf(stderr, "OOM error in native tmp buffer allocation");
136
return NULL;
137
}
138
sbLen = 0;
139
140
if (off == 0) {
141
/* Complete normalization, including prefix */
142
src = normalizePrefix(path, len, sb, &sbLen);
143
} else {
144
/* Partial normalization */
145
src = off;
146
memcpy(sb+sbLen, path, off);
147
sbLen += off;
148
}
149
150
/* Remove redundant slashes from the remainder of the path, forcing all
151
slashes into the preferred slash */
152
while (src < len) {
153
char c = path[src++];
154
if (isSlash(c)) {
155
while ((src < len) && isSlash(path[src])) src++;
156
if (src == len) {
157
/* Check for trailing separator */
158
if ((sbLen == 2) && (sb[1] == ':')) {
159
/* "z:\\" */
160
sb[sbLen++] = slash;
161
break;
162
}
163
if (sbLen == 0) {
164
/* "\\" */
165
sb[sbLen++] = slash;
166
break;
167
}
168
if ((sbLen == 1) && (isSlash(sb[0]))) {
169
/* "\\\\" is not collapsed to "\\" because "\\\\" marks
170
the beginning of a UNC pathname. Even though it is
171
not, by itself, a valid UNC pathname, we leave it as
172
is in order to be consistent with the win32 APIs,
173
which treat this case as an invalid UNC pathname
174
rather than as an alias for the root directory of
175
the current drive. */
176
sb[sbLen++] = slash;
177
break;
178
}
179
/* Path does not denote a root directory, so do not append
180
trailing slash */
181
break;
182
} else {
183
sb[sbLen++] = slash;
184
}
185
} else {
186
sb[sbLen++] = c;
187
}
188
}
189
190
sb[sbLen] = '\0';
191
return sb;
192
}
193
194
/*
195
* Check that the given pathname is normal. If not, invoke the real
196
* normalizer on the part of the pathname that requires normalization.
197
* This way we iterate through the whole pathname string only once.
198
*/
199
char* normalize(char* path) {
200
int n = (int)strlen(path);
201
int i;
202
char c = 0;
203
int prev = 0;
204
for (i = 0; i < n; i++) {
205
char c = path[i];
206
if (c == altSlash)
207
return normalizePath(path, n, (prev == slash) ? i - 1 : i);
208
if ((c == slash) && (prev == slash) && (i > 1))
209
return normalizePath(path, n, i - 1);
210
if ((c == ':') && (i > 1))
211
return normalizePath(path, n, 0);
212
prev = c;
213
}
214
if (prev == slash)
215
return normalizePath(path, n, n - 1);
216
return path;
217
}
218
219
220
/* -- Resolution - src/windows/classes/java/io/Win32FileSystem.java */
221
222
223
char* resolve(const char* parent, const char* child) {
224
char* c;
225
char* theChars;
226
int parentEnd, childStart, len;
227
228
int pn = (int)strlen(parent);
229
int cn = (int)strlen(child);
230
231
if (pn == 0) return (char*)child;
232
if (cn == 0) return (char*)parent;
233
234
c = (char*)child;
235
childStart = 0;
236
parentEnd = pn;
237
238
if ((cn > 1) && (c[0] == slash)) {
239
if (c[1] == slash) {
240
/* Drop prefix when child is a UNC pathname */
241
childStart = 2;
242
} else {
243
/* Drop prefix when child is drive-relative */
244
childStart = 1;
245
246
}
247
if (cn == childStart) { // Child is double slash
248
if (parent[pn - 1] == slash) {
249
char* str = strdup(parent);
250
str[pn-1] = '\0';
251
return str;
252
}
253
return (char*)parent;
254
}
255
}
256
257
if (parent[pn - 1] == slash)
258
parentEnd--;
259
260
len = parentEnd + cn - childStart;
261
262
if (child[childStart] == slash) {
263
theChars = (char*)malloc(len+1);
264
if (theChars == NULL) {
265
fprintf(stderr, "OOM error in native tmp buffer allocation");
266
return NULL;
267
}
268
memcpy(theChars, parent, parentEnd);
269
memcpy(theChars+parentEnd, child+childStart, (cn-childStart));
270
theChars[len] = '\0';
271
} else {
272
theChars = (char*)malloc(len+2);
273
if (theChars == NULL) {
274
fprintf(stderr, "OOM error in native tmp buffer allocation");
275
return NULL;
276
}
277
memcpy(theChars, parent, parentEnd);
278
theChars[parentEnd] = slash;
279
memcpy(theChars+parentEnd+1, child+childStart, (cn-childStart));
280
theChars[len+1] = '\0';
281
}
282
return theChars;
283
}
284
285
286
static int prefixLength(const char* path) {
287
char c0, c1;
288
289
int n = (int)strlen(path);
290
if (n == 0) return 0;
291
c0 = path[0];
292
c1 = (n > 1) ? path[1] : 0;
293
if (c0 == slash) {
294
if (c1 == slash) return 2; /* Absolute UNC pathname "\\\\foo" */
295
return 1; /* Drive-relative "\\foo" */
296
}
297
if (isLetter(c0) && (c1 == ':')) {
298
if ((n > 2) && (path[2] == slash))
299
return 3; /* Absolute local pathname "z:\\foo" */
300
return 2; /* Directory-relative "z:foo" */
301
}
302
return 0; /* Completely relative */
303
}
304
305
306
int isAbsolute(const char* path) {
307
int pl = prefixLength(path);
308
return (((pl == 2) && (path[0] == slash)) || (pl == 3));
309
}
310
311
312
char* fromURIPath(const char* path) {
313
int start = 0;
314
int len = (int)strlen(path);
315
316
if ((len > 2) && (path[2] == ':')) {
317
// "/c:/foo" --> "c:/foo"
318
start = 1;
319
// "c:/foo/" --> "c:/foo", but "c:/" --> "c:/"
320
if ((len > 3) && path[len-1] == '/')
321
len--;
322
} else if ((len > 1) && path[len-1] == '/') {
323
// "/foo/" --> "/foo"
324
len--;
325
}
326
327
if (start == 0 && len == (int)strlen(path)) {
328
return (char*)path;
329
} else {
330
char* p = (char*)malloc(len+1);
331
if (p == NULL) {
332
fprintf(stderr, "OOM error in native tmp buffer allocation");
333
return NULL;
334
}
335
memcpy(p, path+start, len);
336
p[len] = '\0';
337
return p;
338
}
339
}
340
341