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