1 /* 2 * Copyright (c) 2008, 2018, 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.util.*; 31 import java.io.IOException; 32 33 /** 34 * Base implementation of FileStore for Unix/like implementations. 35 */ 36 37 abstract class UnixFileStore 38 extends FileStore 39 { 40 // original path of file that identified file system 41 private final UnixPath file; 42 43 // device ID 44 private final long dev; 45 46 // entry in the mount tab 47 private final UnixMountEntry entry; 48 49 // return the device ID where the given file resides devFor(UnixPath file)50 private static long devFor(UnixPath file) throws IOException { 51 try { 52 return UnixFileAttributes.get(file, true).dev(); 53 } catch (UnixException x) { 54 x.rethrowAsIOException(file); 55 return 0L; // keep compiler happy 56 } 57 } 58 UnixFileStore(UnixPath file)59 UnixFileStore(UnixPath file) throws IOException { 60 this.file = file; 61 this.dev = devFor(file); 62 this.entry = findMountEntry(); 63 } 64 UnixFileStore(UnixFileSystem fs, UnixMountEntry entry)65 UnixFileStore(UnixFileSystem fs, UnixMountEntry entry) throws IOException { 66 this.file = new UnixPath(fs, entry.dir()); 67 this.dev = (entry.dev() == 0L) ? devFor(this.file) : entry.dev(); 68 this.entry = entry; 69 } 70 71 /** 72 * Find the mount entry for the file store 73 */ findMountEntry()74 abstract UnixMountEntry findMountEntry() throws IOException; 75 file()76 UnixPath file() { 77 return file; 78 } 79 dev()80 long dev() { 81 return dev; 82 } 83 entry()84 UnixMountEntry entry() { 85 return entry; 86 } 87 88 @Override name()89 public String name() { 90 return entry.name(); 91 } 92 93 @Override type()94 public String type() { 95 return entry.fstype(); 96 } 97 98 @Override isReadOnly()99 public boolean isReadOnly() { 100 return entry.isReadOnly(); 101 } 102 103 // uses statvfs to read the file system information readAttributes()104 private UnixFileStoreAttributes readAttributes() throws IOException { 105 try { 106 return UnixFileStoreAttributes.get(file); 107 } catch (UnixException x) { 108 x.rethrowAsIOException(file); 109 return null; // keep compile happy 110 } 111 } 112 113 @Override getTotalSpace()114 public long getTotalSpace() throws IOException { 115 UnixFileStoreAttributes attrs = readAttributes(); 116 return attrs.blockSize() * attrs.totalBlocks(); 117 } 118 119 @Override getUsableSpace()120 public long getUsableSpace() throws IOException { 121 UnixFileStoreAttributes attrs = readAttributes(); 122 return attrs.blockSize() * attrs.availableBlocks(); 123 } 124 125 @Override getBlockSize()126 public long getBlockSize() throws IOException { 127 UnixFileStoreAttributes attrs = readAttributes(); 128 return attrs.blockSize(); 129 } 130 131 @Override getUnallocatedSpace()132 public long getUnallocatedSpace() throws IOException { 133 UnixFileStoreAttributes attrs = readAttributes(); 134 return attrs.blockSize() * attrs.freeBlocks(); 135 } 136 137 @Override getFileStoreAttributeView(Class<V> view)138 public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> view) 139 { 140 if (view == null) 141 throw new NullPointerException(); 142 return (V) null; 143 } 144 145 @Override getAttribute(String attribute)146 public Object getAttribute(String attribute) throws IOException { 147 if (attribute.equals("totalSpace")) 148 return getTotalSpace(); 149 if (attribute.equals("usableSpace")) 150 return getUsableSpace(); 151 if (attribute.equals("unallocatedSpace")) 152 return getUnallocatedSpace(); 153 throw new UnsupportedOperationException("'" + attribute + "' not recognized"); 154 } 155 156 @Override supportsFileAttributeView(Class<? extends FileAttributeView> type)157 public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) { 158 if (type == null) 159 throw new NullPointerException(); 160 if (type == BasicFileAttributeView.class) 161 return true; 162 if (type == PosixFileAttributeView.class || 163 type == FileOwnerAttributeView.class) 164 { 165 // lookup fstypes.properties 166 FeatureStatus status = checkIfFeaturePresent("posix"); 167 // assume supported if UNKNOWN 168 return (status != FeatureStatus.NOT_PRESENT); 169 } 170 return false; 171 } 172 173 @Override supportsFileAttributeView(String name)174 public boolean supportsFileAttributeView(String name) { 175 if (name.equals("basic") || name.equals("unix")) 176 return true; 177 if (name.equals("posix")) 178 return supportsFileAttributeView(PosixFileAttributeView.class); 179 if (name.equals("owner")) 180 return supportsFileAttributeView(FileOwnerAttributeView.class); 181 return false; 182 } 183 184 @Override equals(Object ob)185 public boolean equals(Object ob) { 186 if (ob == this) 187 return true; 188 if (!(ob instanceof UnixFileStore)) 189 return false; 190 UnixFileStore other = (UnixFileStore)ob; 191 return (this.dev == other.dev) && 192 Arrays.equals(this.entry.dir(), other.entry.dir()) && 193 this.entry.name().equals(other.entry.name()); 194 } 195 196 @Override hashCode()197 public int hashCode() { 198 return (int)(dev ^ (dev >>> 32)) ^ Arrays.hashCode(entry.dir()); 199 } 200 201 @Override toString()202 public String toString() { 203 StringBuilder sb = new StringBuilder(Util.toString(entry.dir())); 204 sb.append(" ("); 205 sb.append(entry.name()); 206 sb.append(")"); 207 return sb.toString(); 208 } 209 210 // -- fstypes.properties -- 211 212 private static final Object loadLock = new Object(); 213 private static volatile Properties props; 214 215 enum FeatureStatus { 216 PRESENT, 217 NOT_PRESENT, 218 UNKNOWN; 219 } 220 221 /** 222 * Returns status to indicate if file system supports a given feature 223 */ 224 // BEGIN Android-changed: fstypes properties file is not used on Android. checkIfFeaturePresent(String feature)225 FeatureStatus checkIfFeaturePresent(String feature) { 226 return FeatureStatus.UNKNOWN; 227 } 228 /* 229 FeatureStatus checkIfFeaturePresent(String feature) { 230 if (props == null) { 231 synchronized (loadLock) { 232 if (props == null) { 233 props = AccessController.doPrivileged( 234 new PrivilegedAction<>() { 235 @Override 236 public Properties run() { 237 return loadProperties(); 238 }}); 239 } 240 } 241 } 242 243 String value = props.getProperty(type()); 244 if (value != null) { 245 String[] values = value.split("\\s"); 246 for (String s: values) { 247 s = s.trim().toLowerCase(); 248 if (s.equals(feature)) { 249 return FeatureStatus.PRESENT; 250 } 251 if (s.startsWith("no")) { 252 s = s.substring(2); 253 if (s.equals(feature)) { 254 return FeatureStatus.NOT_PRESENT; 255 } 256 } 257 } 258 } 259 return FeatureStatus.UNKNOWN; 260 } 261 262 private static Properties loadProperties() { 263 Properties result = new Properties(); 264 String fstypes = StaticProperty.javaHome() + "/lib/fstypes.properties"; 265 Path file = Path.of(fstypes); 266 try { 267 try (ReadableByteChannel rbc = Files.newByteChannel(file)) { 268 result.load(Channels.newReader(rbc, UTF_8.INSTANCE)); 269 } 270 } catch (IOException x) { 271 } 272 return result; 273 } 274 */ 275 // END Android-changed: fstypes properties file is not used on Android. 276 } 277