6867101: Path.checkAccess fails with sharing violation on special files such as pagefile.sys
authoralanb
Fri, 31 Jul 2009 08:44:28 +0100
changeset 3423 3dd3615c1748
parent 3421 e3af585364e7
child 3424 8f6c0145dc8f
6867101: Path.checkAccess fails with sharing violation on special files such as pagefile.sys Reviewed-by: sherman
jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java
jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java
jdk/test/java/nio/file/Path/Misc.java
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Wed Jul 29 21:45:52 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Fri Jul 31 08:44:28 2009 +0100
@@ -92,6 +92,7 @@
     public static final int ERROR_INVALID_DATA          = 13;
     public static final int ERROR_NOT_SAME_DEVICE       = 17;
     public static final int ERROR_NOT_READY             = 21;
+    public static final int ERROR_SHARING_VIOLATION     = 32;
     public static final int ERROR_FILE_EXISTS           = 80;
     public static final int ERROR_INVALID_PARAMATER     = 87;
     public static final int ERROR_DISK_FULL             = 112;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Wed Jul 29 21:45:52 2009 -0700
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Fri Jul 31 08:44:28 2009 +0100
@@ -299,6 +299,9 @@
         throws WindowsException
     {
         if (!ensureAccurateMetadata) {
+            WindowsException firstException = null;
+
+            // GetFileAttributesEx is the fastest way to read the attributes
             NativeBuffer buffer =
                 NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA);
             try {
@@ -310,9 +313,39 @@
                     .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
                 if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
                     return fromFileAttributeData(address, 0);
+            } catch (WindowsException x) {
+                if (x.lastError() != ERROR_SHARING_VIOLATION)
+                    throw x;
+                firstException = x;
             } finally {
                 buffer.release();
             }
+
+            // For sharing violations, fallback to FindFirstFile if the file
+            // is not a root directory.
+            if (firstException != null) {
+                String search = path.getPathForWin32Calls();
+                char last = search.charAt(search.length() -1);
+                if (last == ':' || last == '\\')
+                    throw firstException;
+                buffer = getBufferForFindData();
+                try {
+                    long handle = FindFirstFile(search, buffer.address());
+                    FindClose(handle);
+                    WindowsFileAttributes attrs = fromFindData(buffer.address());
+                    // FindFirstFile does not follow sym links. Even if
+                    // followLinks is false, there isn't sufficient information
+                    // in the WIN32_FIND_DATA structure to know if the reparse
+                    // point is a sym link.
+                    if (attrs.isReparsePoint())
+                        throw firstException;
+                    return attrs;
+                } catch (WindowsException ignore) {
+                    throw firstException;
+                } finally {
+                    buffer.release();
+                }
+            }
         }
 
         // file is reparse point so need to open file to get attributes
--- a/jdk/test/java/nio/file/Path/Misc.java	Wed Jul 29 21:45:52 2009 -0700
+++ b/jdk/test/java/nio/file/Path/Misc.java	Fri Jul 31 08:44:28 2009 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 6866804
  * @summary Unit test for java.nio.file.Path for miscellenous methods not
  *   covered by other tests
  * @library ..
@@ -107,6 +107,28 @@
         dir.checkAccess(AccessMode.READ, AccessMode.WRITE);
 
         /**
+         * Test: Check access to all files in all root directories.
+         * (A useful test on Windows for special files such as pagefile.sys)
+         */
+        for (Path root: FileSystems.getDefault().getRootDirectories()) {
+            DirectoryStream<Path> stream;
+            try {
+                stream = root.newDirectoryStream();
+            } catch (IOException x) {
+                continue; // skip root directories that aren't accessible
+            }
+            try {
+                for (Path entry: stream) {
+                    try {
+                        entry.checkAccess();
+                    } catch (AccessDeniedException ignore) { }
+                }
+            } finally {
+                stream.close();
+            }
+        }
+
+        /**
          * Test: File does not exist
          */
         Path doesNotExist = dir.resolve("thisDoesNotExists");