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  }