< prev index next >

src/java.base/windows/classes/java/io/WinNTFileSystem.java

Print this page

 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 java.io;
 27 
 28 import java.io.File;
 29 import java.nio.file.Path;
 30 import java.util.BitSet;
 31 import java.util.Locale;
 32 import java.util.Properties;

 33 import sun.security.action.GetPropertyAction;
 34 
 35 /**
 36  * Unicode-aware FileSystem for Windows NT/2000.
 37  *
 38  * @author Konstantin Kladko
 39  * @since 1.4
 40  */
 41 class WinNTFileSystem extends FileSystem {
 42 
 43     private final char slash;
 44     private final char altSlash;
 45     private final char semicolon;
 46     private final String userDir;
 47 
 48     public WinNTFileSystem() {
 49         Properties props = GetPropertyAction.privilegedGetProperties();
 50         slash = props.getProperty("file.separator").charAt(0);
 51         semicolon = props.getProperty("path.separator").charAt(0);
 52         altSlash = (this.slash == '\\') ? '/' : '\\';

397     public String canonicalize(String path) throws IOException {
398         // If path is a drive letter only then skip canonicalization
399         int len = path.length();
400         if ((len == 2) &&
401             (isLetter(path.charAt(0))) &&
402             (path.charAt(1) == ':')) {
403             char c = path.charAt(0);
404             if ((c >= 'A') && (c <= 'Z'))
405                 return path;
406             return "" + ((char) (c-32)) + ':';
407         } else if ((len == 3) &&
408                    (isLetter(path.charAt(0))) &&
409                    (path.charAt(1) == ':') &&
410                    (path.charAt(2) == '\\')) {
411             char c = path.charAt(0);
412             if ((c >= 'A') && (c <= 'Z'))
413                 return path;
414             return "" + ((char) (c-32)) + ':' + '\\';
415         }
416         if (!useCanonCaches) {
417             return canonicalize0(path);




418         } else {
419             String res = cache.get(path);
420             if (res == null) {
421                 String dir = null;
422                 String resDir = null;
423                 if (useCanonPrefixCache) {
424                     dir = parentOrNull(path);
425                     if (dir != null) {
426                         resDir = prefixCache.get(dir);
427                         if (resDir != null) {
428                             /*
429                              * Hit only in prefix cache; full path is canonical,
430                              * but we need to get the canonical name of the file
431                              * in this directory to get the appropriate
432                              * capitalization
433                              */
434                             String filename = path.substring(1 + dir.length());
435                             res = canonicalizeWithPrefix(resDir, filename);
436                             cache.put(dir + File.separatorChar + filename, res);
437                         }

514                 return path.substring(0, idx);
515             } else if (c == altSep) {
516                 // Punt on pathnames containing both backward and
517                 // forward slashes
518                 return null;
519             } else if (c == '*' || c == '?') {
520                 // Punt on pathnames containing wildcards
521                 return null;
522             } else {
523                 ++nonDotCount;
524                 adjacentDots = 0;
525             }
526             --idx;
527         }
528         return null;
529     }
530 
531     /* -- Attribute accessors -- */
532 
533     @Override
534     public native int getBooleanAttributes(File f);







535 
536     @Override
537     public native boolean checkAccess(File f, int access);







538 
539     @Override
540     public native long getLastModifiedTime(File f);







541 
542     @Override
543     public native long getLength(File f);







544 
545     @Override
546     public native boolean setPermission(File f, int access, boolean enable,
547             boolean owneronly);






548 
549     /* -- File operations -- */
550 
551     @Override
552     public native boolean createFileExclusively(String path)
553             throws IOException;






554 
555     @Override
556     public native String[] list(File f);







557 
558     @Override
559     public native boolean createDirectory(File f);







560 
561     @Override
562     public native boolean setLastModifiedTime(File f, long time);







563 
564     @Override
565     public native boolean setReadOnly(File f);







566 
567     @Override
568     public boolean delete(File f) {
569         // Keep canonicalization caches in sync after file deletion
570         // and renaming operations. Could be more clever than this
571         // (i.e., only remove/update affected entries) but probably
572         // not worth it since these entries expire after 30 seconds
573         // anyway.
574         if (useCanonCaches) {
575             cache.clear();
576         }
577         if (useCanonPrefixCache) {
578             prefixCache.clear();
579         }
580         return delete0(f);




581     }
582 
583     private native boolean delete0(File f);
584 
585     @Override
586     public boolean rename(File f1, File f2) {
587         // Keep canonicalization caches in sync after file deletion
588         // and renaming operations. Could be more clever than this
589         // (i.e., only remove/update affected entries) but probably
590         // not worth it since these entries expire after 30 seconds
591         // anyway.
592         if (useCanonCaches) {
593             cache.clear();
594         }
595         if (useCanonPrefixCache) {
596             prefixCache.clear();
597         }
598         return rename0(f1, f2);




599     }
600 
601     private native boolean rename0(File f1, File f2);
602 
603     /* -- Filesystem interface -- */
604 
605     @Override
606     public File[] listRoots() {
607         return BitSet
608             .valueOf(new long[] {listRoots0()})
609             .stream()
610             .mapToObj(i -> new File((char)('A' + i) + ":" + slash))
611             .filter(f -> access(f.getPath()) && f.exists())
612             .toArray(File[]::new);
613     }
614 
615     private static native int listRoots0();
616 
617     private boolean access(String path) {
618         try {
619             @SuppressWarnings("removal")
620             SecurityManager security = System.getSecurityManager();
621             if (security != null) security.checkRead(path);
622             return true;
623         } catch (SecurityException x) {
624             return false;
625         }
626     }
627 
628     /* -- Disk usage -- */
629 
630     @Override
631     public long getSpace(File f, int t) {
632         if (f.exists()) {
633             return getSpace0(f, t);
634         }
635         return 0;
636     }
637 
638     private native long getSpace0(File f, int t);
639 
640     /* -- Basic infrastructure -- */
641 
642     // Obtain maximum file component length from GetVolumeInformation which
643     // expects the path to be null or a root component ending in a backslash
644     private native int getNameMax0(String path);
645 
646     @Override
647     public int getNameMax(String path) {
648         String s = null;
649         if (path != null) {
650             File f = new File(path);
651             if (f.isAbsolute()) {
652                 Path root = f.toPath().getRoot();
653                 if (root != null) {
654                     s = root.toString();
655                     if (!s.endsWith("\\")) {
656                         s = s + "\\";
657                     }

 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 java.io;
 27 
 28 import java.io.File;
 29 import java.nio.file.Path;
 30 import java.util.BitSet;
 31 import java.util.Locale;
 32 import java.util.Properties;
 33 import jdk.internal.misc.Blocker;
 34 import sun.security.action.GetPropertyAction;
 35 
 36 /**
 37  * Unicode-aware FileSystem for Windows NT/2000.
 38  *
 39  * @author Konstantin Kladko
 40  * @since 1.4
 41  */
 42 class WinNTFileSystem extends FileSystem {
 43 
 44     private final char slash;
 45     private final char altSlash;
 46     private final char semicolon;
 47     private final String userDir;
 48 
 49     public WinNTFileSystem() {
 50         Properties props = GetPropertyAction.privilegedGetProperties();
 51         slash = props.getProperty("file.separator").charAt(0);
 52         semicolon = props.getProperty("path.separator").charAt(0);
 53         altSlash = (this.slash == '\\') ? '/' : '\\';

398     public String canonicalize(String path) throws IOException {
399         // If path is a drive letter only then skip canonicalization
400         int len = path.length();
401         if ((len == 2) &&
402             (isLetter(path.charAt(0))) &&
403             (path.charAt(1) == ':')) {
404             char c = path.charAt(0);
405             if ((c >= 'A') && (c <= 'Z'))
406                 return path;
407             return "" + ((char) (c-32)) + ':';
408         } else if ((len == 3) &&
409                    (isLetter(path.charAt(0))) &&
410                    (path.charAt(1) == ':') &&
411                    (path.charAt(2) == '\\')) {
412             char c = path.charAt(0);
413             if ((c >= 'A') && (c <= 'Z'))
414                 return path;
415             return "" + ((char) (c-32)) + ':' + '\\';
416         }
417         if (!useCanonCaches) {
418             if (Thread.currentThread().isVirtual()) {
419                 return Blocker.managedBlock(() -> canonicalize0(path));
420             } else {
421                 return canonicalize0(path);
422             }
423         } else {
424             String res = cache.get(path);
425             if (res == null) {
426                 String dir = null;
427                 String resDir = null;
428                 if (useCanonPrefixCache) {
429                     dir = parentOrNull(path);
430                     if (dir != null) {
431                         resDir = prefixCache.get(dir);
432                         if (resDir != null) {
433                             /*
434                              * Hit only in prefix cache; full path is canonical,
435                              * but we need to get the canonical name of the file
436                              * in this directory to get the appropriate
437                              * capitalization
438                              */
439                             String filename = path.substring(1 + dir.length());
440                             res = canonicalizeWithPrefix(resDir, filename);
441                             cache.put(dir + File.separatorChar + filename, res);
442                         }

519                 return path.substring(0, idx);
520             } else if (c == altSep) {
521                 // Punt on pathnames containing both backward and
522                 // forward slashes
523                 return null;
524             } else if (c == '*' || c == '?') {
525                 // Punt on pathnames containing wildcards
526                 return null;
527             } else {
528                 ++nonDotCount;
529                 adjacentDots = 0;
530             }
531             --idx;
532         }
533         return null;
534     }
535 
536     /* -- Attribute accessors -- */
537 
538     @Override
539     public int getBooleanAttributes(File f) {
540         if (Thread.currentThread().isVirtual()) {
541             return Blocker.managedBlock(() -> getBooleanAttributes0(f));
542         } else {
543             return getBooleanAttributes0(f);
544         }
545     }
546     private native int getBooleanAttributes0(File f);
547 
548     @Override
549     public boolean checkAccess(File f, int access) {
550         if (Thread.currentThread().isVirtual()) {
551             return Blocker.managedBlock(() -> checkAccess0(f, access));
552         } else {
553             return checkAccess0(f, access);
554         }
555     }
556     private native boolean checkAccess0(File f, int access);
557 
558     @Override
559     public long getLastModifiedTime(File f) {
560         if (Thread.currentThread().isVirtual()) {
561             return Blocker.managedBlock(() -> getLastModifiedTime0(f));
562         } else {
563             return getLastModifiedTime0(f);
564         }
565     }
566     private native long getLastModifiedTime0(File f);
567 
568     @Override
569     public long getLength(File f) {
570         if (Thread.currentThread().isVirtual()) {
571             return Blocker.managedBlock(() -> getLength0(f));
572         } else {
573             return getLength0(f);
574         }
575     }
576     private native long getLength0(File f);
577 
578     @Override
579     public boolean setPermission(File f, int access, boolean enable, boolean owneronly) {
580         if (Thread.currentThread().isVirtual()) {
581             return Blocker.managedBlock(() -> setPermission0(f, access, enable, owneronly));
582         } else {
583             return setPermission0(f, access, enable, owneronly);
584         }
585     }
586     private native boolean setPermission0(File f, int access, boolean enable, boolean owneronly);
587 
588     /* -- File operations -- */
589 
590     @Override
591     public boolean createFileExclusively(String path) throws IOException {
592         if (Thread.currentThread().isVirtual()) {
593             return Blocker.managedBlock(() -> createFileExclusively0(path));
594         } else {
595             return createFileExclusively0(path);
596         }
597     }
598     private native boolean createFileExclusively0(String path) throws IOException;
599 
600     @Override
601     public String[] list(File f) {
602         if (Thread.currentThread().isVirtual()) {
603             return Blocker.managedBlock(() -> list0(f));
604         } else {
605             return list0(f);
606         }
607     }
608     private native String[] list0(File f);
609 
610     @Override
611     public boolean createDirectory(File f) {
612         if (Thread.currentThread().isVirtual()) {
613             return Blocker.managedBlock(() -> createDirectory0(f));
614         } else {
615             return createDirectory0(f);
616         }
617     }
618     private native boolean createDirectory0(File f);
619 
620     @Override
621     public boolean setLastModifiedTime(File f, long time) {
622         if (Thread.currentThread().isVirtual()) {
623             return Blocker.managedBlock(() -> setLastModifiedTime0(f, time));
624         } else {
625             return setLastModifiedTime0(f, time);
626         }
627     }
628     private native boolean setLastModifiedTime0(File f, long time);
629 
630     @Override
631     public boolean setReadOnly(File f) {
632         if (Thread.currentThread().isVirtual()) {
633             return Blocker.managedBlock(() -> setReadOnly0(f));
634         } else {
635             return setReadOnly0(f);
636         }
637     }
638     private native boolean setReadOnly0(File f);
639 
640     @Override
641     public boolean delete(File f) {
642         // Keep canonicalization caches in sync after file deletion
643         // and renaming operations. Could be more clever than this
644         // (i.e., only remove/update affected entries) but probably
645         // not worth it since these entries expire after 30 seconds
646         // anyway.
647         if (useCanonCaches) {
648             cache.clear();
649         }
650         if (useCanonPrefixCache) {
651             prefixCache.clear();
652         }
653         if (Thread.currentThread().isVirtual()) {
654             return Blocker.managedBlock(() -> delete0(f));
655         } else {
656             return delete0(f);
657         }
658     }

659     private native boolean delete0(File f);
660 
661     @Override
662     public boolean rename(File f1, File f2) {
663         // Keep canonicalization caches in sync after file deletion
664         // and renaming operations. Could be more clever than this
665         // (i.e., only remove/update affected entries) but probably
666         // not worth it since these entries expire after 30 seconds
667         // anyway.
668         if (useCanonCaches) {
669             cache.clear();
670         }
671         if (useCanonPrefixCache) {
672             prefixCache.clear();
673         }
674         if (Thread.currentThread().isVirtual()) {
675             return Blocker.managedBlock(() -> rename0(f1, f2));
676         } else {
677             return rename0(f1, f2);
678         }
679     }

680     private native boolean rename0(File f1, File f2);
681 
682     /* -- Filesystem interface -- */
683 
684     @Override
685     public File[] listRoots() {
686         return BitSet
687             .valueOf(new long[] {listRoots0()})
688             .stream()
689             .mapToObj(i -> new File((char)('A' + i) + ":" + slash))
690             .filter(f -> access(f.getPath()) && f.exists())
691             .toArray(File[]::new);
692     }

693     private static native int listRoots0();
694 
695     private boolean access(String path) {
696         try {
697             @SuppressWarnings("removal")
698             SecurityManager security = System.getSecurityManager();
699             if (security != null) security.checkRead(path);
700             return true;
701         } catch (SecurityException x) {
702             return false;
703         }
704     }
705 
706     /* -- Disk usage -- */
707 
708     @Override
709     public long getSpace(File f, int t) {
710         if (f.exists()) {
711             return getSpace0(f, t);
712         }
713         return 0;
714     }

715     private native long getSpace0(File f, int t);
716 
717     /* -- Basic infrastructure -- */
718 
719     // Obtain maximum file component length from GetVolumeInformation which
720     // expects the path to be null or a root component ending in a backslash
721     private native int getNameMax0(String path);
722 
723     @Override
724     public int getNameMax(String path) {
725         String s = null;
726         if (path != null) {
727             File f = new File(path);
728             if (f.isAbsolute()) {
729                 Path root = f.toPath().getRoot();
730                 if (root != null) {
731                     s = root.toString();
732                     if (!s.endsWith("\\")) {
733                         s = s + "\\";
734                     }
< prev index next >