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.attribute.*;
     29 import java.util.concurrent.TimeUnit;
     30 import java.util.Set;
     31 import java.util.HashSet;
     32 
     33 /**
     34  * Unix implementation of PosixFileAttributes.
     35  */
     36 
     37 class UnixFileAttributes
     38     implements PosixFileAttributes
     39 {
     40     private int     st_mode;
     41     private long    st_ino;
     42     private long    st_dev;
     43     private long    st_rdev;
     44     private int     st_nlink;
     45     private int     st_uid;
     46     private int     st_gid;
     47     private long    st_size;
     48     private long    st_atime_sec;
     49     private long    st_atime_nsec;
     50     private long    st_mtime_sec;
     51     private long    st_mtime_nsec;
     52     private long    st_ctime_sec;
     53     private long    st_ctime_nsec;
     54     private long    st_birthtime_sec;
     55 
     56     // created lazily
     57     private volatile UserPrincipal owner;
     58     private volatile GroupPrincipal group;
     59     private volatile UnixFileKey key;
     60 
     61     private UnixFileAttributes() {
     62     }
     63 
     64     // get the UnixFileAttributes for a given file
     65     static UnixFileAttributes get(UnixPath path, boolean followLinks)
     66         throws UnixException
     67     {
     68         UnixFileAttributes attrs = new UnixFileAttributes();
     69         if (followLinks) {
     70             UnixNativeDispatcher.stat(path, attrs);
     71         } else {
     72             UnixNativeDispatcher.lstat(path, attrs);
     73         }
     74         return attrs;
     75     }
     76 
     77     // get the UnixFileAttributes for an open file
     78     static UnixFileAttributes get(int fd) throws UnixException {
     79         UnixFileAttributes attrs = new UnixFileAttributes();
     80         UnixNativeDispatcher.fstat(fd, attrs);
     81         return attrs;
     82     }
     83 
     84     // get the UnixFileAttributes for a given file, relative to open directory
     85     static UnixFileAttributes get(int dfd, UnixPath path, boolean followLinks)
     86         throws UnixException
     87     {
     88         UnixFileAttributes attrs = new UnixFileAttributes();
     89         int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW;
     90         UnixNativeDispatcher.fstatat(dfd, path.asByteArray(), flag, attrs);
     91         return attrs;
     92     }
     93 
     94     // package-private
     95     boolean isSameFile(UnixFileAttributes attrs) {
     96         return ((st_ino == attrs.st_ino) && (st_dev == attrs.st_dev));
     97     }
     98 
     99     // package-private
    100     int mode()  { return st_mode; }
    101     long ino()  { return st_ino; }
    102     long dev()  { return st_dev; }
    103     long rdev() { return st_rdev; }
    104     int nlink() { return st_nlink; }
    105     int uid()   { return st_uid; }
    106     int gid()   { return st_gid; }
    107 
    108     private static FileTime toFileTime(long sec, long nsec) {
    109         if (nsec == 0) {
    110             return FileTime.from(sec, TimeUnit.SECONDS);
    111         } else {
    112             // truncate to microseconds to avoid overflow with timestamps
    113             // way out into the future. We can re-visit this if FileTime
    114             // is updated to define a from(secs,nsecs) method.
    115             long micro = sec*1000000L + nsec/1000L;
    116             return FileTime.from(micro, TimeUnit.MICROSECONDS);
    117         }
    118     }
    119 
    120     FileTime ctime() {
    121         return toFileTime(st_ctime_sec, st_ctime_nsec);
    122     }
    123 
    124     boolean isDevice() {
    125         int type = st_mode & UnixConstants.S_IFMT;
    126         return (type == UnixConstants.S_IFCHR ||
    127                 type == UnixConstants.S_IFBLK  ||
    128                 type == UnixConstants.S_IFIFO);
    129     }
    130 
    131     @Override
    132     public FileTime lastModifiedTime() {
    133         return toFileTime(st_mtime_sec, st_mtime_nsec);
    134     }
    135 
    136     @Override
    137     public FileTime lastAccessTime() {
    138         return toFileTime(st_atime_sec, st_atime_nsec);
    139     }
    140 
    141     @Override
    142     public FileTime creationTime() {
    143         if (UnixNativeDispatcher.birthtimeSupported()) {
    144             return FileTime.from(st_birthtime_sec, TimeUnit.SECONDS);
    145         } else {
    146             // return last modified when birth time not supported
    147             return lastModifiedTime();
    148         }
    149     }
    150 
    151     @Override
    152     public boolean isRegularFile() {
    153        return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFREG);
    154     }
    155 
    156     @Override
    157     public boolean isDirectory() {
    158         return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFDIR);
    159     }
    160 
    161     @Override
    162     public boolean isSymbolicLink() {
    163         return ((st_mode & UnixConstants.S_IFMT) == UnixConstants.S_IFLNK);
    164     }
    165 
    166     @Override
    167     public boolean isOther() {
    168         int type = st_mode & UnixConstants.S_IFMT;
    169         return (type != UnixConstants.S_IFREG &&
    170                 type != UnixConstants.S_IFDIR &&
    171                 type != UnixConstants.S_IFLNK);
    172     }
    173 
    174     @Override
    175     public long size() {
    176         return st_size;
    177     }
    178 
    179     @Override
    180     public UnixFileKey fileKey() {
    181         if (key == null) {
    182             synchronized (this) {
    183                 if (key == null) {
    184                     key = new UnixFileKey(st_dev, st_ino);
    185                 }
    186             }
    187         }
    188         return key;
    189     }
    190 
    191     @Override
    192     public UserPrincipal owner() {
    193         if (owner == null) {
    194             synchronized (this) {
    195                 if (owner == null) {
    196                     owner = UnixUserPrincipals.fromUid(st_uid);
    197                 }
    198             }
    199         }
    200         return owner;
    201     }
    202 
    203     @Override
    204     public GroupPrincipal group() {
    205         if (group == null) {
    206             synchronized (this) {
    207                 if (group == null) {
    208                     group = UnixUserPrincipals.fromGid(st_gid);
    209                 }
    210             }
    211         }
    212         return group;
    213     }
    214 
    215     @Override
    216     public Set<PosixFilePermission> permissions() {
    217         int bits = (st_mode & UnixConstants.S_IAMB);
    218         HashSet<PosixFilePermission> perms = new HashSet<>();
    219 
    220         if ((bits & UnixConstants.S_IRUSR) > 0)
    221             perms.add(PosixFilePermission.OWNER_READ);
    222         if ((bits & UnixConstants.S_IWUSR) > 0)
    223             perms.add(PosixFilePermission.OWNER_WRITE);
    224         if ((bits & UnixConstants.S_IXUSR) > 0)
    225             perms.add(PosixFilePermission.OWNER_EXECUTE);
    226 
    227         if ((bits & UnixConstants.S_IRGRP) > 0)
    228             perms.add(PosixFilePermission.GROUP_READ);
    229         if ((bits & UnixConstants.S_IWGRP) > 0)
    230             perms.add(PosixFilePermission.GROUP_WRITE);
    231         if ((bits & UnixConstants.S_IXGRP) > 0)
    232             perms.add(PosixFilePermission.GROUP_EXECUTE);
    233 
    234         if ((bits & UnixConstants.S_IROTH) > 0)
    235             perms.add(PosixFilePermission.OTHERS_READ);
    236         if ((bits & UnixConstants.S_IWOTH) > 0)
    237             perms.add(PosixFilePermission.OTHERS_WRITE);
    238         if ((bits & UnixConstants.S_IXOTH) > 0)
    239             perms.add(PosixFilePermission.OTHERS_EXECUTE);
    240 
    241         return perms;
    242     }
    243 
    244     // wrap this object with BasicFileAttributes object to prevent leaking of
    245     // user information
    246     BasicFileAttributes asBasicFileAttributes() {
    247         return UnixAsBasicFileAttributes.wrap(this);
    248     }
    249 
    250     // unwrap BasicFileAttributes to get the underlying UnixFileAttributes
    251     // object. Returns null is not wrapped.
    252     static UnixFileAttributes toUnixFileAttributes(BasicFileAttributes attrs) {
    253         if (attrs instanceof UnixFileAttributes)
    254             return (UnixFileAttributes)attrs;
    255         if (attrs instanceof UnixAsBasicFileAttributes) {
    256             return ((UnixAsBasicFileAttributes)attrs).unwrap();
    257         }
    258         return null;
    259     }
    260 
    261     // wrap a UnixFileAttributes object as a BasicFileAttributes
    262     private static class UnixAsBasicFileAttributes implements BasicFileAttributes {
    263         private final UnixFileAttributes attrs;
    264 
    265         private UnixAsBasicFileAttributes(UnixFileAttributes attrs) {
    266             this.attrs = attrs;
    267         }
    268 
    269         static UnixAsBasicFileAttributes wrap(UnixFileAttributes attrs) {
    270             return new UnixAsBasicFileAttributes(attrs);
    271         }
    272 
    273         UnixFileAttributes unwrap() {
    274             return attrs;
    275         }
    276 
    277         @Override
    278         public FileTime lastModifiedTime() {
    279             return attrs.lastModifiedTime();
    280         }
    281         @Override
    282         public FileTime lastAccessTime() {
    283             return attrs.lastAccessTime();
    284         }
    285         @Override
    286         public FileTime creationTime() {
    287             return attrs.creationTime();
    288         }
    289         @Override
    290         public boolean isRegularFile() {
    291             return attrs.isRegularFile();
    292         }
    293         @Override
    294         public boolean isDirectory() {
    295             return attrs.isDirectory();
    296         }
    297         @Override
    298         public boolean isSymbolicLink() {
    299             return attrs.isSymbolicLink();
    300         }
    301         @Override
    302         public boolean isOther() {
    303             return attrs.isOther();
    304         }
    305         @Override
    306         public long size() {
    307             return attrs.size();
    308         }
    309         @Override
    310         public Object fileKey() {
    311             return attrs.fileKey();
    312         }
    313     }
    314 }
    315