1 /* 2 * Copyright (c) 2008, 2017, 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.IOException; 31 32 import static sun.nio.fs.WindowsConstants.*; 33 import static sun.nio.fs.WindowsNativeDispatcher.*; 34 35 /** 36 * Windows implementation of FileStore. 37 */ 38 39 class WindowsFileStore 40 extends FileStore 41 { 42 private final String root; 43 private final VolumeInformation volInfo; 44 private final int volType; 45 private final String displayName; // returned by toString 46 47 private WindowsFileStore(String root) throws WindowsException { 48 assert root.charAt(root.length()-1) == '\\'; 49 this.root = root; 50 this.volInfo = GetVolumeInformation(root); 51 this.volType = GetDriveType(root); 52 53 // file store "display name" is the volume name if available 54 String vol = volInfo.volumeName(); 55 if (vol.length() > 0) { 56 this.displayName = vol; 57 } else { 58 // TBD - should we map all types? Does this need to be localized? 59 this.displayName = (volType == DRIVE_REMOVABLE) ? "Removable Disk" : ""; 60 } 61 } 62 63 static WindowsFileStore create(String root, boolean ignoreNotReady) 64 throws IOException 65 { 66 try { 67 return new WindowsFileStore(root); 68 } catch (WindowsException x) { 69 if (ignoreNotReady && x.lastError() == ERROR_NOT_READY) 70 return null; 71 x.rethrowAsIOException(root); 72 return null; // keep compiler happy 73 } 74 } 75 76 static WindowsFileStore create(WindowsPath file) throws IOException { 77 try { 78 // if the file is a link then GetVolumePathName returns the 79 // volume that the link is on so we need to call it with the 80 // final target 81 String target = WindowsLinkSupport.getFinalPath(file, true); 82 try { 83 return createFromPath(target); 84 } catch (WindowsException e) { 85 if (e.lastError() != ERROR_DIR_NOT_ROOT) 86 throw e; 87 target = WindowsLinkSupport.getFinalPath(file); 88 if (target == null) 89 throw new FileSystemException(file.getPathForExceptionMessage(), 90 null, "Couldn't resolve path"); 91 return createFromPath(target); 92 } 93 } catch (WindowsException x) { 94 x.rethrowAsIOException(file); 95 return null; // keep compiler happy 96 } 97 } 98 99 private static WindowsFileStore createFromPath(String target) throws WindowsException { 100 String root = GetVolumePathName(target); 101 return new WindowsFileStore(root); 102 } 103 104 VolumeInformation volumeInformation() { 105 return volInfo; 106 } 107 108 int volumeType() { 109 return volType; 110 } 111 112 @Override 113 public String name() { 114 return volInfo.volumeName(); // "SYSTEM", "DVD-RW", ... 115 } 116 117 @Override 118 public String type() { 119 return volInfo.fileSystemName(); // "FAT", "NTFS", ... 120 } 121 122 @Override 123 public boolean isReadOnly() { 124 return ((volInfo.flags() & FILE_READ_ONLY_VOLUME) != 0); 125 } 126 127 // read the free space info 128 private DiskFreeSpace readDiskFreeSpaceEx() throws IOException { 129 try { 130 return GetDiskFreeSpaceEx(root); 131 } catch (WindowsException x) { 132 x.rethrowAsIOException(root); 133 return null; 134 } 135 } 136 137 private DiskFreeSpace readDiskFreeSpace() throws IOException { 138 try { 139 return GetDiskFreeSpace(root); 140 } catch (WindowsException x) { 141 x.rethrowAsIOException(root); 142 return null; 143 } 144 } 145 146 @Override 147 public long getTotalSpace() throws IOException { 148 return readDiskFreeSpaceEx().totalNumberOfBytes(); 149 } 150 151 @Override 152 public long getUsableSpace() throws IOException { 153 return readDiskFreeSpaceEx().freeBytesAvailable(); 154 } 155 156 public long getBlockSize() throws IOException { 157 return readDiskFreeSpace().bytesPerSector(); 158 } 159 160 @Override 161 public long getUnallocatedSpace() throws IOException { 162 return readDiskFreeSpaceEx().freeBytesAvailable(); 163 } 164 165 @Override 166 public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) { 167 if (type == null) 168 throw new NullPointerException(); 169 return (V) null; 170 } 171 172 @Override 173 public Object getAttribute(String attribute) throws IOException { 174 // standard 175 if (attribute.equals("totalSpace")) 176 return getTotalSpace(); 177 if (attribute.equals("usableSpace")) 178 return getUsableSpace(); 179 if (attribute.equals("unallocatedSpace")) 180 return getUnallocatedSpace(); 181 if (attribute.equals("bytesPerSector")) 182 return getBlockSize(); 183 // windows specific for testing purposes 184 if (attribute.equals("volume:vsn")) 185 return volInfo.volumeSerialNumber(); 186 if (attribute.equals("volume:isRemovable")) 187 return volType == DRIVE_REMOVABLE; 188 if (attribute.equals("volume:isCdrom")) 189 return volType == DRIVE_CDROM; 190 throw new UnsupportedOperationException("'" + attribute + "' not recognized"); 191 } 192 193 @Override 194 public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) { 195 if (type == null) 196 throw new NullPointerException(); 197 if (type == BasicFileAttributeView.class || type == DosFileAttributeView.class) 198 return true; 199 if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class) 200 return ((volInfo.flags() & FILE_PERSISTENT_ACLS) != 0); 201 if (type == UserDefinedFileAttributeView.class) 202 return ((volInfo.flags() & FILE_NAMED_STREAMS) != 0); 203 return false; 204 } 205 206 @Override 207 public boolean supportsFileAttributeView(String name) { 208 if (name.equals("basic") || name.equals("dos")) 209 return true; 210 if (name.equals("acl")) 211 return supportsFileAttributeView(AclFileAttributeView.class); 212 if (name.equals("owner")) 213 return supportsFileAttributeView(FileOwnerAttributeView.class); 214 if (name.equals("user")) 215 return supportsFileAttributeView(UserDefinedFileAttributeView.class); 216 return false; 217 } 218 219 @Override 220 public boolean equals(Object ob) { 221 if (ob == this) 222 return true; 223 if (!(ob instanceof WindowsFileStore)) 224 return false; 225 WindowsFileStore other = (WindowsFileStore)ob; 226 return root.equals(other.root); 227 } 228 229 @Override 230 public int hashCode() { 231 return root.hashCode(); 232 } 233 234 @Override 235 public String toString() { 236 StringBuilder sb = new StringBuilder(displayName); 237 if (sb.length() > 0) 238 sb.append(" "); 239 sb.append("("); 240 // drop trailing slash 241 sb.append(root.subSequence(0, root.length()-1)); 242 sb.append(")"); 243 return sb.toString(); 244 } 245 }