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/WindowsPath.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.io.*;
31
import java.net.URI;
32
import java.util.*;
33
import java.lang.ref.WeakReference;
34
35
import static sun.nio.fs.WindowsNativeDispatcher.*;
36
import static sun.nio.fs.WindowsConstants.*;
37
38
/**
39
* Windows implementation of Path
40
*/
41
42
class WindowsPath implements Path {
43
44
// The maximum path that does not require long path prefix. On Windows
45
// the maximum path is 260 minus 1 (NUL) but for directories it is 260
46
// minus 12 minus 1 (to allow for the creation of a 8.3 file in the
47
// directory).
48
private static final int MAX_PATH = 247;
49
50
// Maximum extended-length path
51
private static final int MAX_LONG_PATH = 32000;
52
53
// FIXME - eliminate this reference to reduce space
54
private final WindowsFileSystem fs;
55
56
// path type
57
private final WindowsPathType type;
58
// root component (may be empty)
59
private final String root;
60
// normalized path
61
private final String path;
62
63
// the path to use in Win32 calls. This differs from path for relative
64
// paths and has a long path prefix for all paths longer than MAX_PATH.
65
private volatile WeakReference<String> pathForWin32Calls;
66
67
// offsets into name components (computed lazily)
68
private volatile Integer[] offsets;
69
70
// computed hash code (computed lazily, no need to be volatile)
71
private int hash;
72
73
74
/**
75
* Initializes a new instance of this class.
76
*/
77
private WindowsPath(WindowsFileSystem fs,
78
WindowsPathType type,
79
String root,
80
String path)
81
{
82
this.fs = fs;
83
this.type = type;
84
this.root = root;
85
this.path = path;
86
}
87
88
/**
89
* Creates a Path by parsing the given path.
90
*/
91
static WindowsPath parse(WindowsFileSystem fs, String path) {
92
WindowsPathParser.Result result = WindowsPathParser.parse(path);
93
return new WindowsPath(fs, result.type(), result.root(), result.path());
94
}
95
96
/**
97
* Creates a Path from a given path that is known to be normalized.
98
*/
99
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
100
String path,
101
BasicFileAttributes attrs)
102
{
103
try {
104
WindowsPathParser.Result result =
105
WindowsPathParser.parseNormalizedPath(path);
106
if (attrs == null) {
107
return new WindowsPath(fs,
108
result.type(),
109
result.root(),
110
result.path());
111
} else {
112
return new WindowsPathWithAttributes(fs,
113
result.type(),
114
result.root(),
115
result.path(),
116
attrs);
117
}
118
} catch (InvalidPathException x) {
119
throw new AssertionError(x.getMessage());
120
}
121
}
122
123
/**
124
* Creates a WindowsPath from a given path that is known to be normalized.
125
*/
126
static WindowsPath createFromNormalizedPath(WindowsFileSystem fs,
127
String path)
128
{
129
return createFromNormalizedPath(fs, path, null);
130
}
131
132
/**
133
* Special implementation with attached/cached attributes (used to quicken
134
* file tree traversal)
135
*/
136
private static class WindowsPathWithAttributes
137
extends WindowsPath implements BasicFileAttributesHolder
138
{
139
final WeakReference<BasicFileAttributes> ref;
140
141
WindowsPathWithAttributes(WindowsFileSystem fs,
142
WindowsPathType type,
143
String root,
144
String path,
145
BasicFileAttributes attrs)
146
{
147
super(fs, type, root, path);
148
ref = new WeakReference<BasicFileAttributes>(attrs);
149
}
150
151
@Override
152
public BasicFileAttributes get() {
153
return ref.get();
154
}
155
156
@Override
157
public void invalidate() {
158
ref.clear();
159
}
160
161
// no need to override equals/hashCode.
162
}
163
164
// use this message when throwing exceptions
165
String getPathForExceptionMessage() {
166
return path;
167
}
168
169
// use this path for permission checks
170
String getPathForPermissionCheck() {
171
return path;
172
}
173
174
// use this path for Win32 calls
175
// This method will prefix long paths with \\?\ or \\?\UNC as required.
176
String getPathForWin32Calls() throws WindowsException {
177
// short absolute paths can be used directly
178
if (isAbsolute() && path.length() <= MAX_PATH)
179
return path;
180
181
// return cached values if available
182
WeakReference<String> ref = pathForWin32Calls;
183
String resolved = (ref != null) ? ref.get() : null;
184
if (resolved != null) {
185
// Win32 path already available
186
return resolved;
187
}
188
189
// resolve against default directory
190
resolved = getAbsolutePath();
191
192
// Long paths need to have "." and ".." removed and be prefixed with
193
// "\\?\". Note that it is okay to remove ".." even when it follows
194
// a link - for example, it is okay for foo/link/../bar to be changed
195
// to foo/bar. The reason is that Win32 APIs to access foo/link/../bar
196
// will access foo/bar anyway (which differs to Unix systems)
197
if (resolved.length() > MAX_PATH) {
198
if (resolved.length() > MAX_LONG_PATH) {
199
throw new WindowsException("Cannot access file with path exceeding "
200
+ MAX_LONG_PATH + " characters");
201
}
202
resolved = addPrefixIfNeeded(GetFullPathName(resolved));
203
}
204
205
// cache the resolved path (except drive relative paths as the working
206
// directory on removal media devices can change during the lifetime
207
// of the VM)
208
if (type != WindowsPathType.DRIVE_RELATIVE) {
209
synchronized (this) {
210
pathForWin32Calls = new WeakReference<String>(resolved);
211
}
212
}
213
return resolved;
214
}
215
216
// return this path resolved against the file system's default directory
217
private String getAbsolutePath() throws WindowsException {
218
if (isAbsolute())
219
return path;
220
221
// Relative path ("foo" for example)
222
if (type == WindowsPathType.RELATIVE) {
223
String defaultDirectory = getFileSystem().defaultDirectory();
224
if (isEmpty())
225
return defaultDirectory;
226
if (defaultDirectory.endsWith("\\")) {
227
return defaultDirectory + path;
228
} else {
229
StringBuilder sb =
230
new StringBuilder(defaultDirectory.length() + path.length() + 1);
231
return sb.append(defaultDirectory).append('\\').append(path).toString();
232
}
233
}
234
235
// Directory relative path ("\foo" for example)
236
if (type == WindowsPathType.DIRECTORY_RELATIVE) {
237
String defaultRoot = getFileSystem().defaultRoot();
238
return defaultRoot + path.substring(1);
239
}
240
241
// Drive relative path ("C:foo" for example).
242
if (isSameDrive(root, getFileSystem().defaultRoot())) {
243
// relative to default directory
244
String remaining = path.substring(root.length());
245
String defaultDirectory = getFileSystem().defaultDirectory();
246
if (remaining.isEmpty()) {
247
return defaultDirectory;
248
} else if (defaultDirectory.endsWith("\\")) {
249
return defaultDirectory + remaining;
250
} else {
251
return defaultDirectory + "\\" + remaining;
252
}
253
} else {
254
// relative to some other drive
255
String wd;
256
try {
257
int dt = GetDriveType(root + "\\");
258
if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR)
259
throw new WindowsException("");
260
wd = GetFullPathName(root + ".");
261
} catch (WindowsException x) {
262
throw new WindowsException("Unable to get working directory of drive '" +
263
Character.toUpperCase(root.charAt(0)) + "'");
264
}
265
String result = wd;
266
if (wd.endsWith("\\")) {
267
result += path.substring(root.length());
268
} else {
269
if (path.length() > root.length())
270
result += "\\" + path.substring(root.length());
271
}
272
return result;
273
}
274
}
275
276
// returns true if same drive letter
277
private static boolean isSameDrive(String root1, String root2) {
278
return Character.toUpperCase(root1.charAt(0)) ==
279
Character.toUpperCase(root2.charAt(0));
280
}
281
282
// Add long path prefix to path if required
283
static String addPrefixIfNeeded(String path) {
284
if (path.length() > MAX_PATH) {
285
if (path.startsWith("\\\\")) {
286
path = "\\\\?\\UNC" + path.substring(1, path.length());
287
} else {
288
path = "\\\\?\\" + path;
289
}
290
}
291
return path;
292
}
293
294
@Override
295
public WindowsFileSystem getFileSystem() {
296
return fs;
297
}
298
299
// -- Path operations --
300
301
private boolean isEmpty() {
302
return path.isEmpty();
303
}
304
305
private WindowsPath emptyPath() {
306
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", "");
307
}
308
309
@Override
310
public Path getFileName() {
311
int len = path.length();
312
// represents empty path
313
if (len == 0)
314
return this;
315
// represents root component only
316
if (root.length() == len)
317
return null;
318
int off = path.lastIndexOf('\\');
319
if (off < root.length())
320
off = root.length();
321
else
322
off++;
323
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", path.substring(off));
324
}
325
326
@Override
327
public WindowsPath getParent() {
328
// represents root component only
329
if (root.length() == path.length())
330
return null;
331
int off = path.lastIndexOf('\\');
332
if (off < root.length())
333
return getRoot();
334
else
335
return new WindowsPath(getFileSystem(),
336
type,
337
root,
338
path.substring(0, off));
339
}
340
341
@Override
342
public WindowsPath getRoot() {
343
if (root.isEmpty())
344
return null;
345
return new WindowsPath(getFileSystem(), type, root, root);
346
}
347
348
// package-private
349
WindowsPathType type() {
350
return type;
351
}
352
353
// package-private
354
boolean isUnc() {
355
return type == WindowsPathType.UNC;
356
}
357
358
boolean needsSlashWhenResolving() {
359
if (path.endsWith("\\"))
360
return false;
361
return path.length() > root.length();
362
}
363
364
@Override
365
public boolean isAbsolute() {
366
return type == WindowsPathType.ABSOLUTE || type == WindowsPathType.UNC;
367
}
368
369
static WindowsPath toWindowsPath(Path path) {
370
if (path == null)
371
throw new NullPointerException();
372
if (!(path instanceof WindowsPath)) {
373
throw new ProviderMismatchException();
374
}
375
return (WindowsPath)path;
376
}
377
378
// return true if this path has "." or ".."
379
private boolean hasDotOrDotDot() {
380
int n = getNameCount();
381
for (int i=0; i<n; i++) {
382
String name = elementAsString(i);
383
if (name.length() == 1 && name.charAt(0) == '.')
384
return true;
385
if (name.length() == 2
386
&& name.charAt(0) == '.' && name.charAt(1) == '.')
387
return true;
388
}
389
return false;
390
}
391
392
@Override
393
public WindowsPath relativize(Path obj) {
394
WindowsPath child = toWindowsPath(obj);
395
if (this.equals(child))
396
return emptyPath();
397
398
// can only relativize paths of the same type
399
if (this.type != child.type)
400
throw new IllegalArgumentException("'other' is different type of Path");
401
402
// can only relativize paths if root component matches
403
if (!this.root.equalsIgnoreCase(child.root))
404
throw new IllegalArgumentException("'other' has different root");
405
406
// this path is the empty path
407
if (this.isEmpty())
408
return child;
409
410
411
WindowsPath base = this;
412
if (base.hasDotOrDotDot() || child.hasDotOrDotDot()) {
413
base = base.normalize();
414
child = child.normalize();
415
}
416
417
int baseCount = base.getNameCount();
418
int childCount = child.getNameCount();
419
420
// skip matching names
421
int n = Math.min(baseCount, childCount);
422
int i = 0;
423
while (i < n) {
424
if (!base.getName(i).equals(child.getName(i)))
425
break;
426
i++;
427
}
428
429
// remaining elements in child
430
WindowsPath childRemaining;
431
boolean isChildEmpty;
432
if (i == childCount) {
433
childRemaining = emptyPath();
434
isChildEmpty = true;
435
} else {
436
childRemaining = child.subpath(i, childCount);
437
isChildEmpty = childRemaining.isEmpty();
438
}
439
440
// matched all of base
441
if (i == baseCount) {
442
return childRemaining;
443
}
444
445
// the remainder of base cannot contain ".."
446
WindowsPath baseRemaining = base.subpath(i, baseCount);
447
if (baseRemaining.hasDotOrDotDot()) {
448
throw new IllegalArgumentException("Unable to compute relative "
449
+ " path from " + this + " to " + obj);
450
}
451
if (baseRemaining.isEmpty())
452
return childRemaining;
453
454
// number of ".." needed
455
int dotdots = baseRemaining.getNameCount();
456
if (dotdots == 0) {
457
return childRemaining;
458
}
459
460
StringBuilder result = new StringBuilder();
461
for (int j=0; j<dotdots; j++) {
462
result.append("..\\");
463
}
464
465
// append remaining names in child
466
if (!isChildEmpty) {
467
for (int j=0; j<childRemaining.getNameCount(); j++) {
468
result.append(childRemaining.getName(j).toString());
469
result.append("\\");
470
}
471
}
472
473
// drop trailing slash
474
result.setLength(result.length()-1);
475
return createFromNormalizedPath(getFileSystem(), result.toString());
476
}
477
478
@Override
479
public WindowsPath normalize() {
480
final int count = getNameCount();
481
if (count == 0 || isEmpty())
482
return this;
483
484
boolean[] ignore = new boolean[count]; // true => ignore name
485
int remaining = count; // number of names remaining
486
487
// multiple passes to eliminate all occurrences of "." and "name/.."
488
int prevRemaining;
489
do {
490
prevRemaining = remaining;
491
int prevName = -1;
492
for (int i=0; i<count; i++) {
493
if (ignore[i])
494
continue;
495
496
String name = elementAsString(i);
497
498
// not "." or ".."
499
if (name.length() > 2) {
500
prevName = i;
501
continue;
502
}
503
504
// "." or something else
505
if (name.length() == 1) {
506
// ignore "."
507
if (name.charAt(0) == '.') {
508
ignore[i] = true;
509
remaining--;
510
} else {
511
prevName = i;
512
}
513
continue;
514
}
515
516
// not ".."
517
if (name.charAt(0) != '.' || name.charAt(1) != '.') {
518
prevName = i;
519
continue;
520
}
521
522
// ".." found
523
if (prevName >= 0) {
524
// name/<ignored>/.. found so mark name and ".." to be
525
// ignored
526
ignore[prevName] = true;
527
ignore[i] = true;
528
remaining = remaining - 2;
529
prevName = -1;
530
} else {
531
// Cases:
532
// C:\<ignored>\..
533
// \\server\\share\<ignored>\..
534
// \<ignored>..
535
if (isAbsolute() || type == WindowsPathType.DIRECTORY_RELATIVE) {
536
boolean hasPrevious = false;
537
for (int j=0; j<i; j++) {
538
if (!ignore[j]) {
539
hasPrevious = true;
540
break;
541
}
542
}
543
if (!hasPrevious) {
544
// all proceeding names are ignored
545
ignore[i] = true;
546
remaining--;
547
}
548
}
549
}
550
}
551
} while (prevRemaining > remaining);
552
553
// no redundant names
554
if (remaining == count)
555
return this;
556
557
// corner case - all names removed
558
if (remaining == 0) {
559
return root.isEmpty() ? emptyPath() : getRoot();
560
}
561
562
// re-constitute the path from the remaining names.
563
StringBuilder result = new StringBuilder();
564
if (root != null)
565
result.append(root);
566
for (int i=0; i<count; i++) {
567
if (!ignore[i]) {
568
result.append(getName(i));
569
result.append("\\");
570
}
571
}
572
573
// drop trailing slash in result
574
result.setLength(result.length()-1);
575
return createFromNormalizedPath(getFileSystem(), result.toString());
576
}
577
578
@Override
579
public WindowsPath resolve(Path obj) {
580
WindowsPath other = toWindowsPath(obj);
581
if (other.isEmpty())
582
return this;
583
if (other.isAbsolute())
584
return other;
585
586
switch (other.type) {
587
case RELATIVE: {
588
String result;
589
if (path.endsWith("\\") || (root.length() == path.length())) {
590
result = path + other.path;
591
} else {
592
result = path + "\\" + other.path;
593
}
594
return new WindowsPath(getFileSystem(), type, root, result);
595
}
596
597
case DIRECTORY_RELATIVE: {
598
String result;
599
if (root.endsWith("\\")) {
600
result = root + other.path.substring(1);
601
} else {
602
result = root + other.path;
603
}
604
return createFromNormalizedPath(getFileSystem(), result);
605
}
606
607
case DRIVE_RELATIVE: {
608
if (!root.endsWith("\\"))
609
return other;
610
// if different roots then return other
611
String thisRoot = root.substring(0, root.length()-1);
612
if (!thisRoot.equalsIgnoreCase(other.root))
613
return other;
614
// same roots
615
String remaining = other.path.substring(other.root.length());
616
String result;
617
if (path.endsWith("\\")) {
618
result = path + remaining;
619
} else {
620
result = path + "\\" + remaining;
621
}
622
return createFromNormalizedPath(getFileSystem(), result);
623
}
624
625
default:
626
throw new AssertionError();
627
}
628
}
629
630
// generate offset array
631
private void initOffsets() {
632
if (offsets == null) {
633
ArrayList<Integer> list = new ArrayList<>();
634
if (isEmpty()) {
635
// empty path considered to have one name element
636
list.add(0);
637
} else {
638
int start = root.length();
639
int off = root.length();
640
while (off < path.length()) {
641
if (path.charAt(off) != '\\') {
642
off++;
643
} else {
644
list.add(start);
645
start = ++off;
646
}
647
}
648
if (start != off)
649
list.add(start);
650
}
651
synchronized (this) {
652
if (offsets == null)
653
offsets = list.toArray(new Integer[list.size()]);
654
}
655
}
656
}
657
658
@Override
659
public int getNameCount() {
660
initOffsets();
661
return offsets.length;
662
}
663
664
private String elementAsString(int i) {
665
initOffsets();
666
if (i == (offsets.length-1))
667
return path.substring(offsets[i]);
668
return path.substring(offsets[i], offsets[i+1]-1);
669
}
670
671
@Override
672
public WindowsPath getName(int index) {
673
initOffsets();
674
if (index < 0 || index >= offsets.length)
675
throw new IllegalArgumentException();
676
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", elementAsString(index));
677
}
678
679
@Override
680
public WindowsPath subpath(int beginIndex, int endIndex) {
681
initOffsets();
682
if (beginIndex < 0)
683
throw new IllegalArgumentException();
684
if (beginIndex >= offsets.length)
685
throw new IllegalArgumentException();
686
if (endIndex > offsets.length)
687
throw new IllegalArgumentException();
688
if (beginIndex >= endIndex)
689
throw new IllegalArgumentException();
690
691
StringBuilder sb = new StringBuilder();
692
for (int i = beginIndex; i < endIndex; i++) {
693
sb.append(elementAsString(i));
694
if (i != (endIndex-1))
695
sb.append("\\");
696
}
697
return new WindowsPath(getFileSystem(), WindowsPathType.RELATIVE, "", sb.toString());
698
}
699
700
@Override
701
public boolean startsWith(Path obj) {
702
if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
703
return false;
704
WindowsPath other = (WindowsPath)obj;
705
706
// if this path has a root component the given path's root must match
707
if (!this.root.equalsIgnoreCase(other.root)) {
708
return false;
709
}
710
711
// empty path starts with itself
712
if (other.isEmpty())
713
return this.isEmpty();
714
715
// roots match so compare elements
716
int thisCount = getNameCount();
717
int otherCount = other.getNameCount();
718
if (otherCount <= thisCount) {
719
while (--otherCount >= 0) {
720
String thisElement = this.elementAsString(otherCount);
721
String otherElement = other.elementAsString(otherCount);
722
// FIXME: should compare in uppercase
723
if (!thisElement.equalsIgnoreCase(otherElement))
724
return false;
725
}
726
return true;
727
}
728
return false;
729
}
730
731
@Override
732
public boolean endsWith(Path obj) {
733
if (!(Objects.requireNonNull(obj) instanceof WindowsPath))
734
return false;
735
WindowsPath other = (WindowsPath)obj;
736
737
// other path is longer
738
if (other.path.length() > this.path.length()) {
739
return false;
740
}
741
742
// empty path ends in itself
743
if (other.isEmpty()) {
744
return this.isEmpty();
745
}
746
747
int thisCount = this.getNameCount();
748
int otherCount = other.getNameCount();
749
750
// given path has more elements that this path
751
if (otherCount > thisCount) {
752
return false;
753
}
754
755
// compare roots
756
if (other.root.length() > 0) {
757
if (otherCount < thisCount)
758
return false;
759
// FIXME: should compare in uppercase
760
if (!this.root.equalsIgnoreCase(other.root))
761
return false;
762
}
763
764
// match last 'otherCount' elements
765
int off = thisCount - otherCount;
766
while (--otherCount >= 0) {
767
String thisElement = this.elementAsString(off + otherCount);
768
String otherElement = other.elementAsString(otherCount);
769
// FIXME: should compare in uppercase
770
if (!thisElement.equalsIgnoreCase(otherElement))
771
return false;
772
}
773
return true;
774
}
775
776
@Override
777
public int compareTo(Path obj) {
778
if (obj == null)
779
throw new NullPointerException();
780
String s1 = path;
781
String s2 = ((WindowsPath)obj).path;
782
int n1 = s1.length();
783
int n2 = s2.length();
784
int min = Math.min(n1, n2);
785
for (int i = 0; i < min; i++) {
786
char c1 = s1.charAt(i);
787
char c2 = s2.charAt(i);
788
if (c1 != c2) {
789
c1 = Character.toUpperCase(c1);
790
c2 = Character.toUpperCase(c2);
791
if (c1 != c2) {
792
return c1 - c2;
793
}
794
}
795
}
796
return n1 - n2;
797
}
798
799
@Override
800
public boolean equals(Object obj) {
801
if (obj instanceof WindowsPath path) {
802
return compareTo(path) == 0;
803
}
804
return false;
805
}
806
807
@Override
808
public int hashCode() {
809
// OK if two or more threads compute hash
810
int h = hash;
811
if (h == 0) {
812
for (int i = 0; i< path.length(); i++) {
813
h = 31*h + Character.toUpperCase(path.charAt(i));
814
}
815
hash = h;
816
}
817
return h;
818
}
819
820
@Override
821
public String toString() {
822
return path;
823
}
824
825
// -- file operations --
826
827
// package-private
828
long openForReadAttributeAccess(boolean followLinks)
829
throws WindowsException
830
{
831
int flags = FILE_FLAG_BACKUP_SEMANTICS;
832
if (!followLinks)
833
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
834
try {
835
return openFileForReadAttributeAccess(flags);
836
} catch (WindowsException e) {
837
if (followLinks && e.lastError() == ERROR_CANT_ACCESS_FILE) {
838
// Object could be a Unix domain socket
839
try {
840
return openSocketForReadAttributeAccess();
841
} catch (WindowsException ignore) {}
842
}
843
throw e;
844
}
845
}
846
847
private long openFileForReadAttributeAccess(int flags)
848
throws WindowsException
849
{
850
return CreateFile(getPathForWin32Calls(),
851
FILE_READ_ATTRIBUTES,
852
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
853
0L,
854
OPEN_EXISTING,
855
flags);
856
}
857
858
/**
859
* Returns a handle to the file if it is a socket.
860
* Throws WindowsException if file is not a socket
861
*/
862
private long openSocketForReadAttributeAccess()
863
throws WindowsException
864
{
865
// needs to specify FILE_FLAG_OPEN_REPARSE_POINT if the file is a socket
866
int flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
867
868
long handle = openFileForReadAttributeAccess(flags);
869
870
try {
871
WindowsFileAttributes attrs = WindowsFileAttributes.readAttributes(handle);
872
if (!attrs.isUnixDomainSocket()) {
873
throw new WindowsException("not a socket");
874
}
875
return handle;
876
} catch (WindowsException e) {
877
CloseHandle(handle);
878
throw e;
879
}
880
}
881
882
void checkRead() {
883
@SuppressWarnings("removal")
884
SecurityManager sm = System.getSecurityManager();
885
if (sm != null) {
886
sm.checkRead(getPathForPermissionCheck());
887
}
888
}
889
890
void checkWrite() {
891
@SuppressWarnings("removal")
892
SecurityManager sm = System.getSecurityManager();
893
if (sm != null) {
894
sm.checkWrite(getPathForPermissionCheck());
895
}
896
}
897
898
void checkDelete() {
899
@SuppressWarnings("removal")
900
SecurityManager sm = System.getSecurityManager();
901
if (sm != null) {
902
sm.checkDelete(getPathForPermissionCheck());
903
}
904
}
905
906
@Override
907
public URI toUri() {
908
return WindowsUriSupport.toUri(this);
909
}
910
911
@Override
912
public WindowsPath toAbsolutePath() {
913
if (isAbsolute())
914
return this;
915
916
// permission check as per spec
917
@SuppressWarnings("removal")
918
SecurityManager sm = System.getSecurityManager();
919
if (sm != null) {
920
sm.checkPropertyAccess("user.dir");
921
}
922
923
try {
924
return createFromNormalizedPath(getFileSystem(), getAbsolutePath());
925
} catch (WindowsException x) {
926
throw new IOError(new IOException(x.getMessage()));
927
}
928
}
929
930
@Override
931
public WindowsPath toRealPath(LinkOption... options) throws IOException {
932
checkRead();
933
String rp = WindowsLinkSupport.getRealPath(this, Util.followLinks(options));
934
return createFromNormalizedPath(getFileSystem(), rp);
935
}
936
937
@Override
938
public WatchKey register(WatchService watcher,
939
WatchEvent.Kind<?>[] events,
940
WatchEvent.Modifier... modifiers)
941
throws IOException
942
{
943
if (watcher == null)
944
throw new NullPointerException();
945
if (!(watcher instanceof WindowsWatchService))
946
throw new ProviderMismatchException();
947
948
// When a security manager is set then we need to make a defensive
949
// copy of the modifiers and check for the Windows specific FILE_TREE
950
// modifier. When the modifier is present then check that permission
951
// has been granted recursively.
952
@SuppressWarnings("removal")
953
SecurityManager sm = System.getSecurityManager();
954
if (sm != null) {
955
boolean watchSubtree = false;
956
final int ml = modifiers.length;
957
if (ml > 0) {
958
modifiers = Arrays.copyOf(modifiers, ml);
959
int i=0;
960
while (i < ml) {
961
if (ExtendedOptions.FILE_TREE.matches(modifiers[i++])) {
962
watchSubtree = true;
963
break;
964
}
965
}
966
}
967
String s = getPathForPermissionCheck();
968
sm.checkRead(s);
969
if (watchSubtree)
970
sm.checkRead(s + "\\-");
971
}
972
973
return ((WindowsWatchService)watcher).register(this, events, modifiers);
974
}
975
}
976
977