jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
changeset 2057 3acf8e5e2ca0
child 2071 5e6af6d106cb
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.nio.fs;
       
    27 
       
    28 import java.nio.file.attribute.*;
       
    29 import java.util.concurrent.TimeUnit;
       
    30 import java.security.AccessController;
       
    31 import sun.misc.Unsafe;
       
    32 import sun.security.action.GetPropertyAction;
       
    33 
       
    34 import static sun.nio.fs.WindowsNativeDispatcher.*;
       
    35 import static sun.nio.fs.WindowsConstants.*;
       
    36 
       
    37 /**
       
    38  * Windows implementation of DosFileAttributes/BasicFileAttributes
       
    39  */
       
    40 
       
    41 class WindowsFileAttributes
       
    42     implements DosFileAttributes
       
    43 {
       
    44     private static final Unsafe unsafe = Unsafe.getUnsafe();
       
    45 
       
    46     /*
       
    47      * typedef struct _BY_HANDLE_FILE_INFORMATION {
       
    48      *     DWORD    dwFileAttributes;
       
    49      *     FILETIME ftCreationTime;
       
    50      *     FILETIME ftLastAccessTime;
       
    51      *     FILETIME ftLastWriteTime;
       
    52      *     DWORD    dwVolumeSerialNumber;
       
    53      *     DWORD    nFileSizeHigh;
       
    54      *     DWORD    nFileSizeLow;
       
    55      *     DWORD    nNumberOfLinks;
       
    56      *     DWORD    nFileIndexHigh;
       
    57      *     DWORD    nFileIndexLow;
       
    58      * } BY_HANDLE_FILE_INFORMATION;
       
    59      */
       
    60     private static final short SIZEOF_FILE_INFORMATION  = 52;
       
    61     private static final short OFFSETOF_FILE_INFORMATION_ATTRIBUTES      = 0;
       
    62     private static final short OFFSETOF_FILE_INFORMATION_CREATETIME      = 4;
       
    63     private static final short OFFSETOF_FILE_INFORMATION_LASTACCESSTIME  = 12;
       
    64     private static final short OFFSETOF_FILE_INFORMATION_LASTWRITETIME   = 20;
       
    65     private static final short OFFSETOF_FILE_INFORMATION_VOLSERIALNUM    = 28;
       
    66     private static final short OFFSETOF_FILE_INFORMATION_SIZEHIGH        = 32;
       
    67     private static final short OFFSETOF_FILE_INFORMATION_SIZELOW         = 36;
       
    68     private static final short OFFSETOF_FILE_INFORMATION_NUMLINKS        = 40;
       
    69     private static final short OFFSETOF_FILE_INFORMATION_INDEXHIGH       = 44;
       
    70     private static final short OFFSETOF_FILE_INFORMATION_INDEXLOW        = 48;
       
    71 
       
    72     /*
       
    73      * typedef struct _WIN32_FILE_ATTRIBUTE_DATA {
       
    74      *   DWORD dwFileAttributes;
       
    75      *   FILETIME ftCreationTime;
       
    76      *   FILETIME ftLastAccessTime;
       
    77      *   FILETIME ftLastWriteTime;
       
    78      *   DWORD nFileSizeHigh;
       
    79      *   DWORD nFileSizeLow;
       
    80      * } WIN32_FILE_ATTRIBUTE_DATA;
       
    81      */
       
    82     private static final short SIZEOF_FILE_ATTRIBUTE_DATA = 36;
       
    83     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES      = 0;
       
    84     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME      = 4;
       
    85     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME  = 12;
       
    86     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME   = 20;
       
    87     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH        = 28;
       
    88     private static final short OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW         = 32;
       
    89 
       
    90     // indicates if accurate metadata is required (interesting on NTFS only)
       
    91     private static final boolean ensureAccurateMetadata;
       
    92     static {
       
    93         String propValue = AccessController.doPrivileged(
       
    94             new GetPropertyAction("sun.nio.fs.ensureAccurateMetadata", "false"));
       
    95         ensureAccurateMetadata = (propValue.length() == 0) ?
       
    96             true : Boolean.valueOf(propValue);
       
    97     }
       
    98 
       
    99     // attributes
       
   100     private final int fileAttrs;
       
   101     private final long creationTime;
       
   102     private final long lastAccessTime;
       
   103     private final long lastWriteTime;
       
   104     private final long size;
       
   105     private final int reparseTag;
       
   106 
       
   107     // additional attributes when using GetFileInformationByHandle
       
   108     private final int linkCount;
       
   109     private final int volSerialNumber;
       
   110     private final int fileIndexHigh;
       
   111     private final int fileIndexLow;
       
   112 
       
   113     /**
       
   114      * Convert 64-bit value representing the number of 100-nanosecond intervals
       
   115      * since January 1, 1601 to java time.
       
   116      */
       
   117     private static long toJavaTime(long time) {
       
   118         time /= 10000L;
       
   119         time -= 11644473600000L;
       
   120         return time;
       
   121     }
       
   122 
       
   123     /**
       
   124      * Convert java time to 64-bit value representing the number of 100-nanosecond
       
   125      * intervals since January 1, 1601.
       
   126      */
       
   127     static long toWindowsTime(long time) {
       
   128         time += 11644473600000L;
       
   129         time *= 10000L;
       
   130         return time;
       
   131     }
       
   132 
       
   133     /**
       
   134      * Initialize a new instance of this class
       
   135      */
       
   136     private WindowsFileAttributes(int fileAttrs,
       
   137                                   long creationTime,
       
   138                                   long lastAccessTime,
       
   139                                   long lastWriteTime,
       
   140                                   long size,
       
   141                                   int reparseTag,
       
   142                                   int linkCount,
       
   143                                   int volSerialNumber,
       
   144                                   int fileIndexHigh,
       
   145                                   int fileIndexLow)
       
   146     {
       
   147         this.fileAttrs = fileAttrs;
       
   148         this.creationTime = creationTime;
       
   149         this.lastAccessTime = lastAccessTime;
       
   150         this.lastWriteTime = lastWriteTime;
       
   151         this.size = size;
       
   152         this.reparseTag = reparseTag;
       
   153         this.linkCount = linkCount;
       
   154         this.volSerialNumber = volSerialNumber;
       
   155         this.fileIndexHigh = fileIndexHigh;
       
   156         this.fileIndexLow = fileIndexLow;
       
   157     }
       
   158 
       
   159     /**
       
   160      * Create a WindowsFileAttributes from a BY_HANDLE_FILE_INFORMATION structure
       
   161      */
       
   162     private static WindowsFileAttributes fromFileInformation(long address, int reparseTag) {
       
   163         int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
       
   164         long creationTime =
       
   165             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_CREATETIME));
       
   166         long lastAccessTime =
       
   167             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTACCESSTIME));
       
   168         long lastWriteTime =
       
   169             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_INFORMATION_LASTWRITETIME));
       
   170         long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZEHIGH)) << 32)
       
   171             + (unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_SIZELOW) & 0xFFFFFFFFL);
       
   172         int linkCount = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_NUMLINKS);
       
   173         int volSerialNumber = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_VOLSERIALNUM);
       
   174         int fileIndexHigh = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXHIGH);
       
   175         int fileIndexLow = unsafe.getInt(address + OFFSETOF_FILE_INFORMATION_INDEXLOW);
       
   176         return new WindowsFileAttributes(fileAttrs,
       
   177                                          creationTime,
       
   178                                          lastAccessTime,
       
   179                                          lastWriteTime,
       
   180                                          size,
       
   181                                          reparseTag,
       
   182                                          linkCount,
       
   183                                          volSerialNumber,
       
   184                                          fileIndexHigh,
       
   185                                          fileIndexLow);
       
   186     }
       
   187 
       
   188     /**
       
   189      * Create a WindowsFileAttributes from a WIN32_FILE_ATTRIBUTE_DATA structure
       
   190      */
       
   191     private static WindowsFileAttributes fromFileAttributeData(long address, int reparseTag) {
       
   192         int fileAttrs = unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
       
   193         long creationTime =
       
   194             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_CREATETIME));
       
   195         long lastAccessTime =
       
   196             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTACCESSTIME));
       
   197         long lastWriteTime =
       
   198             toJavaTime(unsafe.getLong(address + OFFSETOF_FILE_ATTRIBUTE_DATA_LASTWRITETIME));
       
   199         long size = ((long)(unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZEHIGH)) << 32)
       
   200             + (unsafe.getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_SIZELOW) & 0xFFFFFFFFL);
       
   201         return new WindowsFileAttributes(fileAttrs,
       
   202                                          creationTime,
       
   203                                          lastAccessTime,
       
   204                                          lastWriteTime,
       
   205                                          size,
       
   206                                          reparseTag,
       
   207                                          1,  // linkCount
       
   208                                          0,  // volSerialNumber
       
   209                                          0,  // fileIndexHigh
       
   210                                          0); // fileIndexLow
       
   211     }
       
   212 
       
   213     /**
       
   214      * Reads the attributes of an open file
       
   215      */
       
   216     static WindowsFileAttributes readAttributes(long handle)
       
   217         throws WindowsException
       
   218     {
       
   219         NativeBuffer buffer = NativeBuffers
       
   220             .getNativeBuffer(SIZEOF_FILE_INFORMATION);
       
   221         try {
       
   222             long address = buffer.address();
       
   223             GetFileInformationByHandle(handle, address);
       
   224 
       
   225             // if file is a reparse point then read the tag
       
   226             int reparseTag = 0;
       
   227             int fileAttrs = unsafe
       
   228                 .getInt(address + OFFSETOF_FILE_INFORMATION_ATTRIBUTES);
       
   229             if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
       
   230                 int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
       
   231                 NativeBuffer reparseBuffer = NativeBuffers.getNativeBuffer(size);
       
   232                 try {
       
   233                     DeviceIoControlGetReparsePoint(handle, reparseBuffer.address(), size);
       
   234                     reparseTag = (int)unsafe.getLong(reparseBuffer.address());
       
   235                 } finally {
       
   236                     reparseBuffer.release();
       
   237                 }
       
   238             }
       
   239 
       
   240             return fromFileInformation(address, reparseTag);
       
   241         } finally {
       
   242             buffer.release();
       
   243         }
       
   244     }
       
   245 
       
   246     /**
       
   247      * Returns attributes of given file.
       
   248      */
       
   249     static WindowsFileAttributes get(WindowsPath path, boolean followLinks)
       
   250         throws WindowsException
       
   251     {
       
   252         if (!ensureAccurateMetadata) {
       
   253             NativeBuffer buffer =
       
   254                 NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA);
       
   255             try {
       
   256                 long address = buffer.address();
       
   257                 GetFileAttributesEx(path.getPathForWin32Calls(), address);
       
   258                 // if reparse point then file may be a sym link; otherwise
       
   259                 // just return the attributes
       
   260                 int fileAttrs = unsafe
       
   261                     .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
       
   262                 if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
       
   263                     return fromFileAttributeData(address, 0);
       
   264             } finally {
       
   265                 buffer.release();
       
   266             }
       
   267         }
       
   268 
       
   269         // file is reparse point so need to open file to get attributes
       
   270         long handle = path.openForReadAttributeAccess(followLinks);
       
   271         try {
       
   272             return readAttributes(handle);
       
   273         } finally {
       
   274             CloseHandle(handle);
       
   275         }
       
   276     }
       
   277 
       
   278     /**
       
   279      * Returns true if the attribtues are of the same file - both files must
       
   280      * be open.
       
   281      */
       
   282     static boolean isSameFile(WindowsFileAttributes attrs1,
       
   283                               WindowsFileAttributes attrs2)
       
   284     {
       
   285         // volume serial number and file index must be the same
       
   286         return (attrs1.volSerialNumber == attrs2.volSerialNumber) &&
       
   287                (attrs1.fileIndexHigh == attrs2.fileIndexHigh) &&
       
   288                (attrs1.fileIndexLow == attrs2.fileIndexLow);
       
   289     }
       
   290 
       
   291     // package-private
       
   292     int attributes() {
       
   293         return fileAttrs;
       
   294     }
       
   295 
       
   296     int volSerialNumber() {
       
   297         if (volSerialNumber == 0)
       
   298             throw new AssertionError("Should not get here");
       
   299         return volSerialNumber;
       
   300     }
       
   301 
       
   302     int fileIndexHigh() {
       
   303         if (volSerialNumber == 0)
       
   304             throw new AssertionError("Should not get here");
       
   305         return fileIndexHigh;
       
   306     }
       
   307 
       
   308     int fileIndexLow() {
       
   309         if (volSerialNumber == 0)
       
   310             throw new AssertionError("Should not get here");
       
   311         return fileIndexLow;
       
   312     }
       
   313 
       
   314     @Override
       
   315     public long size() {
       
   316         return size;
       
   317     }
       
   318 
       
   319     @Override
       
   320     public long lastModifiedTime() {
       
   321         return (lastWriteTime >= 0L) ? lastWriteTime : 0L;
       
   322     }
       
   323 
       
   324     @Override
       
   325     public long lastAccessTime() {
       
   326         return (lastAccessTime >= 0L) ? lastAccessTime : 0L;
       
   327     }
       
   328 
       
   329     @Override
       
   330     public long creationTime() {
       
   331         return (creationTime >= 0L) ? creationTime : 0L;
       
   332     }
       
   333 
       
   334     @Override
       
   335     public TimeUnit resolution() {
       
   336         return TimeUnit.MILLISECONDS;
       
   337     }
       
   338 
       
   339     @Override
       
   340     public int linkCount() {
       
   341         return linkCount;
       
   342     }
       
   343 
       
   344     @Override
       
   345     public Object fileKey() {
       
   346         return null;
       
   347     }
       
   348 
       
   349     // package private
       
   350     boolean isReparsePoint() {
       
   351         return (fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
       
   352     }
       
   353 
       
   354     boolean isDirectoryLink() {
       
   355         return isSymbolicLink() && ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0);
       
   356     }
       
   357 
       
   358     @Override
       
   359     public boolean isSymbolicLink() {
       
   360         return reparseTag == IO_REPARSE_TAG_SYMLINK;
       
   361     }
       
   362 
       
   363     @Override
       
   364     public boolean isDirectory() {
       
   365         // ignore FILE_ATTRIBUTE_DIRECTORY attribute if file is a sym link
       
   366         if (isSymbolicLink())
       
   367             return false;
       
   368         return ((fileAttrs & FILE_ATTRIBUTE_DIRECTORY) != 0);
       
   369     }
       
   370 
       
   371     @Override
       
   372     public boolean isOther() {
       
   373         if (isSymbolicLink())
       
   374             return false;
       
   375         // return true if device or reparse point
       
   376         return ((fileAttrs & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) != 0);
       
   377     }
       
   378 
       
   379     @Override
       
   380     public boolean isRegularFile() {
       
   381         return !isSymbolicLink() && !isDirectory() && !isOther();
       
   382     }
       
   383 
       
   384     @Override
       
   385     public boolean isReadOnly() {
       
   386         return (fileAttrs & FILE_ATTRIBUTE_READONLY) != 0;
       
   387     }
       
   388 
       
   389     @Override
       
   390     public boolean isHidden() {
       
   391         return (fileAttrs & FILE_ATTRIBUTE_HIDDEN) != 0;
       
   392     }
       
   393 
       
   394     @Override
       
   395     public boolean isArchive() {
       
   396         return (fileAttrs & FILE_ATTRIBUTE_ARCHIVE) != 0;
       
   397     }
       
   398 
       
   399     @Override
       
   400     public boolean isSystem() {
       
   401         return (fileAttrs & FILE_ATTRIBUTE_SYSTEM) != 0;
       
   402     }
       
   403 }