Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
41139 views
1
/*
2
* Copyright (c) 2008, 2021, 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
package sun.nio.fs;
27
28
import java.nio.file.*;
29
import java.nio.file.attribute.*;
30
import java.nio.channels.*;
31
import java.nio.charset.StandardCharsets;
32
import java.net.URI;
33
import java.util.concurrent.ExecutorService;
34
import java.io.*;
35
import java.util.*;
36
import java.security.AccessController;
37
import jdk.internal.misc.Unsafe;
38
import jdk.internal.util.StaticProperty;
39
import sun.nio.ch.ThreadPool;
40
import sun.security.util.SecurityConstants;
41
42
import static sun.nio.fs.WindowsNativeDispatcher.*;
43
import static sun.nio.fs.WindowsSecurity.*;
44
import static sun.nio.fs.WindowsConstants.*;
45
46
class WindowsFileSystemProvider
47
extends AbstractFileSystemProvider
48
{
49
private static final byte[] EMPTY_PATH = new byte[0];
50
51
private final WindowsFileSystem theFileSystem;
52
53
public WindowsFileSystemProvider() {
54
theFileSystem = new WindowsFileSystem(this, StaticProperty.userDir());
55
}
56
57
WindowsFileSystem theFileSystem() {
58
return theFileSystem;
59
}
60
61
@Override
62
public String getScheme() {
63
return "file";
64
}
65
66
private void checkUri(URI uri) {
67
if (!uri.getScheme().equalsIgnoreCase(getScheme()))
68
throw new IllegalArgumentException("URI does not match this provider");
69
if (uri.getRawAuthority() != null)
70
throw new IllegalArgumentException("Authority component present");
71
String path = uri.getPath();
72
if (path == null)
73
throw new IllegalArgumentException("Path component is undefined");
74
if (!path.equals("/"))
75
throw new IllegalArgumentException("Path component should be '/'");
76
if (uri.getRawQuery() != null)
77
throw new IllegalArgumentException("Query component present");
78
if (uri.getRawFragment() != null)
79
throw new IllegalArgumentException("Fragment component present");
80
}
81
82
@Override
83
public FileSystem newFileSystem(URI uri, Map<String,?> env)
84
throws IOException
85
{
86
checkUri(uri);
87
throw new FileSystemAlreadyExistsException();
88
}
89
90
@Override
91
public final FileSystem getFileSystem(URI uri) {
92
checkUri(uri);
93
return theFileSystem;
94
}
95
96
@Override
97
public Path getPath(URI uri) {
98
return WindowsUriSupport.fromUri(theFileSystem, uri);
99
}
100
101
@Override
102
public FileChannel newFileChannel(Path path,
103
Set<? extends OpenOption> options,
104
FileAttribute<?>... attrs)
105
throws IOException
106
{
107
if (path == null)
108
throw new NullPointerException();
109
if (!(path instanceof WindowsPath))
110
throw new ProviderMismatchException();
111
WindowsPath file = (WindowsPath)path;
112
113
WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);
114
try {
115
return WindowsChannelFactory
116
.newFileChannel(file.getPathForWin32Calls(),
117
file.getPathForPermissionCheck(),
118
options,
119
sd.address());
120
} catch (WindowsException x) {
121
x.rethrowAsIOException(file);
122
return null;
123
} finally {
124
if (sd != null)
125
sd.release();
126
}
127
}
128
129
@Override
130
public AsynchronousFileChannel newAsynchronousFileChannel(Path path,
131
Set<? extends OpenOption> options,
132
ExecutorService executor,
133
FileAttribute<?>... attrs)
134
throws IOException
135
{
136
if (path == null)
137
throw new NullPointerException();
138
if (!(path instanceof WindowsPath))
139
throw new ProviderMismatchException();
140
WindowsPath file = (WindowsPath)path;
141
ThreadPool pool = (executor == null) ? null : ThreadPool.wrap(executor, 0);
142
WindowsSecurityDescriptor sd =
143
WindowsSecurityDescriptor.fromAttribute(attrs);
144
try {
145
return WindowsChannelFactory
146
.newAsynchronousFileChannel(file.getPathForWin32Calls(),
147
file.getPathForPermissionCheck(),
148
options,
149
sd.address(),
150
pool);
151
} catch (WindowsException x) {
152
x.rethrowAsIOException(file);
153
return null;
154
} finally {
155
if (sd != null)
156
sd.release();
157
}
158
}
159
160
@Override
161
@SuppressWarnings("unchecked")
162
public <V extends FileAttributeView> V
163
getFileAttributeView(Path obj, Class<V> view, LinkOption... options)
164
{
165
WindowsPath file = WindowsPath.toWindowsPath(obj);
166
if (view == null)
167
throw new NullPointerException();
168
boolean followLinks = Util.followLinks(options);
169
if (view == BasicFileAttributeView.class)
170
return (V) WindowsFileAttributeViews.createBasicView(file, followLinks);
171
if (view == DosFileAttributeView.class)
172
return (V) WindowsFileAttributeViews.createDosView(file, followLinks);
173
if (view == AclFileAttributeView.class)
174
return (V) new WindowsAclFileAttributeView(file, followLinks);
175
if (view == FileOwnerAttributeView.class)
176
return (V) new FileOwnerAttributeViewImpl(
177
new WindowsAclFileAttributeView(file, followLinks));
178
if (view == UserDefinedFileAttributeView.class)
179
return (V) new WindowsUserDefinedFileAttributeView(file, followLinks);
180
return (V) null;
181
}
182
183
@Override
184
@SuppressWarnings("unchecked")
185
public <A extends BasicFileAttributes> A readAttributes(Path file,
186
Class<A> type,
187
LinkOption... options)
188
throws IOException
189
{
190
Class<? extends BasicFileAttributeView> view;
191
if (type == BasicFileAttributes.class)
192
view = BasicFileAttributeView.class;
193
else if (type == DosFileAttributes.class)
194
view = DosFileAttributeView.class;
195
else if (type == null)
196
throw new NullPointerException();
197
else
198
throw new UnsupportedOperationException();
199
return (A) getFileAttributeView(file, view, options).readAttributes();
200
}
201
202
@Override
203
public DynamicFileAttributeView getFileAttributeView(Path obj, String name, LinkOption... options) {
204
WindowsPath file = WindowsPath.toWindowsPath(obj);
205
boolean followLinks = Util.followLinks(options);
206
if (name.equals("basic"))
207
return WindowsFileAttributeViews.createBasicView(file, followLinks);
208
if (name.equals("dos"))
209
return WindowsFileAttributeViews.createDosView(file, followLinks);
210
if (name.equals("acl"))
211
return new WindowsAclFileAttributeView(file, followLinks);
212
if (name.equals("owner"))
213
return new FileOwnerAttributeViewImpl(
214
new WindowsAclFileAttributeView(file, followLinks));
215
if (name.equals("user"))
216
return new WindowsUserDefinedFileAttributeView(file, followLinks);
217
return null;
218
}
219
220
@Override
221
public SeekableByteChannel newByteChannel(Path obj,
222
Set<? extends OpenOption> options,
223
FileAttribute<?>... attrs)
224
throws IOException
225
{
226
WindowsPath file = WindowsPath.toWindowsPath(obj);
227
WindowsSecurityDescriptor sd =
228
WindowsSecurityDescriptor.fromAttribute(attrs);
229
try {
230
return WindowsChannelFactory
231
.newFileChannel(file.getPathForWin32Calls(),
232
file.getPathForPermissionCheck(),
233
options,
234
sd.address());
235
} catch (WindowsException x) {
236
x.rethrowAsIOException(file);
237
return null; // keep compiler happy
238
} finally {
239
sd.release();
240
}
241
}
242
243
@Override
244
boolean implDelete(Path obj, boolean failIfNotExists) throws IOException {
245
WindowsPath file = WindowsPath.toWindowsPath(obj);
246
file.checkDelete();
247
248
WindowsFileAttributes attrs = null;
249
try {
250
// need to know if file is a directory or junction
251
attrs = WindowsFileAttributes.get(file, false);
252
if (attrs.isDirectory() || attrs.isDirectoryLink()) {
253
RemoveDirectory(file.getPathForWin32Calls());
254
} else {
255
DeleteFile(file.getPathForWin32Calls());
256
}
257
return true;
258
} catch (WindowsException x) {
259
260
// no-op if file does not exist
261
if (!failIfNotExists &&
262
(x.lastError() == ERROR_FILE_NOT_FOUND ||
263
x.lastError() == ERROR_PATH_NOT_FOUND)) return false;
264
265
if (attrs != null && attrs.isDirectory()) {
266
// ERROR_ALREADY_EXISTS is returned when attempting to delete
267
// non-empty directory on SAMBA servers.
268
if (x.lastError() == ERROR_DIR_NOT_EMPTY ||
269
x.lastError() == ERROR_ALREADY_EXISTS)
270
{
271
throw new DirectoryNotEmptyException(
272
file.getPathForExceptionMessage());
273
}
274
}
275
x.rethrowAsIOException(file);
276
return false;
277
}
278
}
279
280
@Override
281
public void copy(Path source, Path target, CopyOption... options)
282
throws IOException
283
{
284
WindowsFileCopy.copy(WindowsPath.toWindowsPath(source),
285
WindowsPath.toWindowsPath(target),
286
options);
287
}
288
289
@Override
290
public void move(Path source, Path target, CopyOption... options)
291
throws IOException
292
{
293
WindowsFileCopy.move(WindowsPath.toWindowsPath(source),
294
WindowsPath.toWindowsPath(target),
295
options);
296
}
297
298
/**
299
* Checks the file security against desired access.
300
*/
301
private static boolean hasDesiredAccess(WindowsPath file, int rights) throws IOException {
302
// read security descriptor containing ACL (symlinks are followed)
303
boolean hasRights = false;
304
String target = WindowsLinkSupport.getFinalPath(file, true);
305
NativeBuffer aclBuffer = WindowsAclFileAttributeView
306
.getFileSecurity(target,
307
DACL_SECURITY_INFORMATION
308
| OWNER_SECURITY_INFORMATION
309
| GROUP_SECURITY_INFORMATION);
310
try {
311
hasRights = checkAccessMask(aclBuffer.address(), rights,
312
FILE_GENERIC_READ,
313
FILE_GENERIC_WRITE,
314
FILE_GENERIC_EXECUTE,
315
FILE_ALL_ACCESS);
316
} catch (WindowsException exc) {
317
exc.rethrowAsIOException(file);
318
} finally {
319
aclBuffer.release();
320
}
321
return hasRights;
322
}
323
324
/**
325
* Checks if the given file(or directory) exists and is readable.
326
*/
327
private void checkReadAccess(WindowsPath file) throws IOException {
328
try {
329
Set<OpenOption> opts = Collections.emptySet();
330
FileChannel fc = WindowsChannelFactory
331
.newFileChannel(file.getPathForWin32Calls(),
332
file.getPathForPermissionCheck(),
333
opts,
334
0L);
335
fc.close();
336
} catch (WindowsException exc) {
337
try {
338
if (exc.lastError() == ERROR_CANT_ACCESS_FILE && isUnixDomainSocket(file)) {
339
// socket file is accessible
340
return;
341
}
342
} catch (WindowsException ignore) {}
343
344
// Windows errors are very inconsistent when the file is a directory
345
// (ERROR_PATH_NOT_FOUND returned for root directories for example)
346
// so we retry by attempting to open it as a directory.
347
try {
348
new WindowsDirectoryStream(file, null).close();
349
} catch (IOException ioe) {
350
// translate and throw original exception
351
exc.rethrowAsIOException(file);
352
}
353
}
354
}
355
356
private static boolean isUnixDomainSocket(WindowsPath path) throws WindowsException {
357
WindowsFileAttributes attrs = WindowsFileAttributes.get(path, false);
358
return attrs.isUnixDomainSocket();
359
}
360
361
@Override
362
public void checkAccess(Path obj, AccessMode... modes) throws IOException {
363
WindowsPath file = WindowsPath.toWindowsPath(obj);
364
365
boolean r = false;
366
boolean w = false;
367
boolean x = false;
368
for (AccessMode mode: modes) {
369
switch (mode) {
370
case READ : r = true; break;
371
case WRITE : w = true; break;
372
case EXECUTE : x = true; break;
373
default: throw new AssertionError("Should not get here");
374
}
375
}
376
377
// special-case read access to avoid needing to determine effective
378
// access to file; default if modes not specified
379
if (!w && !x) {
380
checkReadAccess(file);
381
return;
382
}
383
384
int mask = 0;
385
if (r) {
386
file.checkRead();
387
mask |= FILE_READ_DATA;
388
}
389
if (w) {
390
file.checkWrite();
391
mask |= FILE_WRITE_DATA;
392
}
393
if (x) {
394
@SuppressWarnings("removal")
395
SecurityManager sm = System.getSecurityManager();
396
if (sm != null)
397
sm.checkExec(file.getPathForPermissionCheck());
398
mask |= FILE_EXECUTE;
399
}
400
401
if (!hasDesiredAccess(file, mask))
402
throw new AccessDeniedException(
403
file.getPathForExceptionMessage(), null,
404
"Permissions does not allow requested access");
405
406
// for write access we need to check if the DOS readonly attribute
407
// and if the volume is read-only
408
if (w) {
409
try {
410
WindowsFileAttributes attrs = WindowsFileAttributes.get(file, true);
411
if (!attrs.isDirectory() && attrs.isReadOnly())
412
throw new AccessDeniedException(
413
file.getPathForExceptionMessage(), null,
414
"DOS readonly attribute is set");
415
} catch (WindowsException exc) {
416
exc.rethrowAsIOException(file);
417
}
418
419
if (WindowsFileStore.create(file).isReadOnly()) {
420
throw new AccessDeniedException(
421
file.getPathForExceptionMessage(), null, "Read-only file system");
422
}
423
}
424
}
425
426
@Override
427
public boolean isSameFile(Path obj1, Path obj2) throws IOException {
428
WindowsPath file1 = WindowsPath.toWindowsPath(obj1);
429
if (file1.equals(obj2))
430
return true;
431
if (obj2 == null)
432
throw new NullPointerException();
433
if (!(obj2 instanceof WindowsPath))
434
return false;
435
WindowsPath file2 = (WindowsPath)obj2;
436
437
// check security manager access to both files
438
file1.checkRead();
439
file2.checkRead();
440
441
// open both files and see if they are the same
442
long h1 = 0L;
443
try {
444
h1 = file1.openForReadAttributeAccess(true);
445
} catch (WindowsException x) {
446
x.rethrowAsIOException(file1);
447
}
448
try {
449
WindowsFileAttributes attrs1 = null;
450
try {
451
attrs1 = WindowsFileAttributes.readAttributes(h1);
452
} catch (WindowsException x) {
453
x.rethrowAsIOException(file1);
454
}
455
long h2 = 0L;
456
try {
457
h2 = file2.openForReadAttributeAccess(true);
458
} catch (WindowsException x) {
459
x.rethrowAsIOException(file2);
460
}
461
try {
462
WindowsFileAttributes attrs2 = null;
463
try {
464
attrs2 = WindowsFileAttributes.readAttributes(h2);
465
} catch (WindowsException x) {
466
x.rethrowAsIOException(file2);
467
}
468
return WindowsFileAttributes.isSameFile(attrs1, attrs2);
469
} finally {
470
CloseHandle(h2);
471
}
472
} finally {
473
CloseHandle(h1);
474
}
475
}
476
477
@Override
478
public boolean isHidden(Path obj) throws IOException {
479
WindowsPath file = WindowsPath.toWindowsPath(obj);
480
file.checkRead();
481
WindowsFileAttributes attrs = null;
482
try {
483
attrs = WindowsFileAttributes.get(file, true);
484
} catch (WindowsException x) {
485
x.rethrowAsIOException(file);
486
}
487
return attrs.isHidden();
488
}
489
490
@Override
491
public FileStore getFileStore(Path obj) throws IOException {
492
WindowsPath file = WindowsPath.toWindowsPath(obj);
493
@SuppressWarnings("removal")
494
SecurityManager sm = System.getSecurityManager();
495
if (sm != null) {
496
sm.checkPermission(new RuntimePermission("getFileStoreAttributes"));
497
file.checkRead();
498
}
499
return WindowsFileStore.create(file);
500
}
501
502
503
@Override
504
public void createDirectory(Path obj, FileAttribute<?>... attrs)
505
throws IOException
506
{
507
WindowsPath dir = WindowsPath.toWindowsPath(obj);
508
dir.checkWrite();
509
WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.fromAttribute(attrs);
510
try {
511
CreateDirectory(dir.getPathForWin32Calls(), sd.address());
512
} catch (WindowsException x) {
513
// convert ERROR_ACCESS_DENIED to FileAlreadyExistsException if we can
514
// verify that the directory exists
515
if (x.lastError() == ERROR_ACCESS_DENIED) {
516
try {
517
if (WindowsFileAttributes.get(dir, false).isDirectory())
518
throw new FileAlreadyExistsException(dir.toString());
519
} catch (WindowsException ignore) { }
520
}
521
x.rethrowAsIOException(dir);
522
} finally {
523
sd.release();
524
}
525
}
526
527
@Override
528
public DirectoryStream<Path> newDirectoryStream(Path obj, DirectoryStream.Filter<? super Path> filter)
529
throws IOException
530
{
531
WindowsPath dir = WindowsPath.toWindowsPath(obj);
532
dir.checkRead();
533
if (filter == null)
534
throw new NullPointerException();
535
return new WindowsDirectoryStream(dir, filter);
536
}
537
538
@Override
539
public void createSymbolicLink(Path obj1, Path obj2, FileAttribute<?>... attrs)
540
throws IOException
541
{
542
WindowsPath link = WindowsPath.toWindowsPath(obj1);
543
WindowsPath target = WindowsPath.toWindowsPath(obj2);
544
545
// no attributes allowed
546
if (attrs.length > 0) {
547
WindowsSecurityDescriptor.fromAttribute(attrs); // may throw NPE or UOE
548
throw new UnsupportedOperationException("Initial file attributes" +
549
"not supported when creating symbolic link");
550
}
551
552
// permission check
553
@SuppressWarnings("removal")
554
SecurityManager sm = System.getSecurityManager();
555
if (sm != null) {
556
sm.checkPermission(new LinkPermission("symbolic"));
557
link.checkWrite();
558
}
559
560
/**
561
* Throw I/O exception for the drive-relative case because Windows
562
* creates a link with the resolved target for this case.
563
*/
564
if (target.type() == WindowsPathType.DRIVE_RELATIVE) {
565
throw new IOException("Cannot create symbolic link to working directory relative target");
566
}
567
568
/*
569
* Windows treats symbolic links to directories differently than it
570
* does to other file types. For that reason we need to check if the
571
* target is a directory (or a directory junction).
572
*/
573
WindowsPath resolvedTarget;
574
if (target.type() == WindowsPathType.RELATIVE) {
575
WindowsPath parent = link.getParent();
576
resolvedTarget = (parent == null) ? target : parent.resolve(target);
577
} else {
578
resolvedTarget = link.resolve(target);
579
}
580
int flags = 0;
581
try {
582
WindowsFileAttributes wattrs = WindowsFileAttributes.get(resolvedTarget, false);
583
if (wattrs.isDirectory() || wattrs.isDirectoryLink())
584
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
585
} catch (WindowsException x) {
586
// unable to access target so assume target is not a directory
587
}
588
589
// create the link
590
try {
591
CreateSymbolicLink(link.getPathForWin32Calls(),
592
WindowsPath.addPrefixIfNeeded(target.toString()),
593
flags);
594
} catch (WindowsException x) {
595
if (x.lastError() == ERROR_INVALID_REPARSE_DATA) {
596
x.rethrowAsIOException(link, target);
597
} else {
598
x.rethrowAsIOException(link);
599
}
600
}
601
}
602
603
@Override
604
public void createLink(Path obj1, Path obj2) throws IOException {
605
WindowsPath link = WindowsPath.toWindowsPath(obj1);
606
WindowsPath existing = WindowsPath.toWindowsPath(obj2);
607
608
// permission check
609
@SuppressWarnings("removal")
610
SecurityManager sm = System.getSecurityManager();
611
if (sm != null) {
612
sm.checkPermission(new LinkPermission("hard"));
613
link.checkWrite();
614
existing.checkWrite();
615
}
616
617
// create hard link
618
try {
619
CreateHardLink(link.getPathForWin32Calls(),
620
existing.getPathForWin32Calls());
621
} catch (WindowsException x) {
622
x.rethrowAsIOException(link, existing);
623
}
624
}
625
626
@Override
627
public Path readSymbolicLink(Path obj1) throws IOException {
628
WindowsPath link = WindowsPath.toWindowsPath(obj1);
629
WindowsFileSystem fs = link.getFileSystem();
630
631
// permission check
632
@SuppressWarnings("removal")
633
SecurityManager sm = System.getSecurityManager();
634
if (sm != null) {
635
FilePermission perm = new FilePermission(link.getPathForPermissionCheck(),
636
SecurityConstants.FILE_READLINK_ACTION);
637
sm.checkPermission(perm);
638
}
639
640
String target = WindowsLinkSupport.readLink(link);
641
return WindowsPath.createFromNormalizedPath(fs, target);
642
}
643
644
@Override
645
public byte[] getSunPathForSocketFile(Path obj) {
646
WindowsPath file = WindowsPath.toWindowsPath(obj);
647
String s = file.toString();
648
return s.isEmpty() ? EMPTY_PATH : s.getBytes(StandardCharsets.UTF_8);
649
}
650
651
}
652
653