1 /* 2 * Copyright (c) 2008, 2011, 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 @Override 157 public int getBlockSize() throws IOException { 158 return (int)readDiskFreeSpace().bytesPerSector(); 159 } 160 161 @Override 162 public long getUnallocatedSpace() throws IOException { 163 return readDiskFreeSpaceEx().freeBytesAvailable(); 164 } 165 166 @Override 167 public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) { 168 if (type == null) 169 throw new NullPointerException(); 170 return (V) null; 171 } 172 173 @Override 174 public Object getAttribute(String attribute) throws IOException { 175 // standard 176 if (attribute.equals("totalSpace")) 177 return getTotalSpace(); 178 if (attribute.equals("usableSpace")) 179 return getUsableSpace(); 180 if (attribute.equals("unallocatedSpace")) 181 return getUnallocatedSpace(); 182 if (attribute.equals("bytesPerSector")) 183 return getBlockSize(); 184 // windows specific for testing purposes 185 if (attribute.equals("volume:vsn")) 186 return volInfo.volumeSerialNumber(); 187 if (attribute.equals("volume:isRemovable")) 188 return volType == DRIVE_REMOVABLE; 189 if (attribute.equals("volume:isCdrom")) 190 return volType == DRIVE_CDROM; 191 throw new UnsupportedOperationException("'" + attribute + "' not recognized"); 192 } 193 194 @Override 195 public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) { 196 if (type == null) 197 throw new NullPointerException(); 198 if (type == BasicFileAttributeView.class || type == DosFileAttributeView.class) 199 return true; 200 if (type == AclFileAttributeView.class || type == FileOwnerAttributeView.class) 201 return ((volInfo.flags() & FILE_PERSISTENT_ACLS) != 0); 202 if (type == UserDefinedFileAttributeView.class) 203 return ((volInfo.flags() & FILE_NAMED_STREAMS) != 0); 204 return false; 205 } 206 207 @Override 208 public boolean supportsFileAttributeView(String name) { 209 if (name.equals("basic") || name.equals("dos")) 210 return true; 211 if (name.equals("acl")) 212 return supportsFileAttributeView(AclFileAttributeView.class); 213 if (name.equals("owner")) 214 return supportsFileAttributeView(FileOwnerAttributeView.class); 215 if (name.equals("user")) 216 return supportsFileAttributeView(UserDefinedFileAttributeView.class); 217 return false; 218 } 219 220 @Override 221 public boolean equals(Object ob) { 222 if (ob == this) 223 return true; 224 if (!(ob instanceof WindowsFileStore)) 225 return false; 226 WindowsFileStore other = (WindowsFileStore)ob; 227 return root.equals(other.root); 228 } 229 230 @Override 231 public int hashCode() { 232 return root.hashCode(); 233 } 234 235 @Override 236 public String toString() { 237 StringBuilder sb = new StringBuilder(displayName); 238 if (sb.length() > 0) 239 sb.append(" "); 240 sb.append("("); 241 // drop trailing slash 242 sb.append(root.subSequence(0, root.length()-1)); 243 sb.append(")"); 244 return sb.toString(); 245 } 246 }