JDK-7190897 : (fs) Files.isWritable method returns false when the path is writable (win)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_vista,windows_7
  • CPU: x86
  • Submitted: 2012-08-13
  • Updated: 2019-12-06
  • Resolved: 2013-03-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u40Fixed 8 b84Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
C:\Program Files\Java\jdk1.7.0_05\bin>java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b06)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

A DESCRIPTION OF THE PROBLEM :
The java.nio.file.Files.isWritable(path) method returns false when the path is writable by Java.

I wonder whether the Windows 7 default practice of giving Read-Execute access to users in the Users group, and Modify access to users in the Authenticated Users group might have contributed to this bug.  However, this is just a hunch as I haven't tried to work through the source code (as I know that the Windows file access attributes are a bit messy).

The default access applying to the file used, which is inherited from the drive root is as described in the previous paragraph.  The bug does not occur if I use Windows Explorer to specifically give Full Control access to a file for my userid.  My userid is not part of the Administrators user group, but would belong to both the Users and Authenticated Users groups.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Please run the source code below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
java.vm.name:                Java HotSpot(TM) 64-Bit Server VM
java.vm.version:             23.1-b03
java.vm.vendor:              Oracle Corporation
java.version:                1.7.0_05
java.vendor:                 Oracle Corporation
java.class.path:             E:\work\niotests\build\classes
java.library.path:           C:\Program Files\Java\jdk1.7.0_05\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\CollabNet\Subversion Client;C:\Program Files (x86)\PuTTY;C:\Utils;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files (x86)\Common Files\Roxio Shared\DLLShared\;C:\Program Files (x86)\Common Files\Roxio Shared\13.0\DLLShared\;;.
java.ext.dirs:               C:\Program Files\Java\jdk1.7.0_05\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
os.name:                     Windows 7
os.arch:                     amd64
os.version:                  6.1
user.name:                   desk3200id
user.dir:                    E:\work\niotests
user.home:                   C:\Users\desk3200id
Default FileSystem Provider: file
Absolute path of demo file:  E:\work\niotests\demofile.txt
Result of deleteIfExists:    true
Result of isWritable:        true
Result of isWritable:        true
Line read:                   First line of text
Line read:                   Second line of text

ACTUAL -
java.vm.name:                Java HotSpot(TM) 64-Bit Server VM
java.vm.version:             23.1-b03
java.vm.vendor:              Oracle Corporation
java.version:                1.7.0_05
java.vendor:                 Oracle Corporation
java.class.path:             E:\work\niotests\build\classes
java.library.path:           C:\Program Files\Java\jdk1.7.0_05\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:\Program Files\CollabNet\Subversion Client;C:\Program Files (x86)\PuTTY;C:\Utils;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files (x86)\Common Files\Roxio Shared\DLLShared\;C:\Program Files (x86)\Common Files\Roxio Shared\13.0\DLLShared\;;.
java.ext.dirs:               C:\Program Files\Java\jdk1.7.0_05\jre\lib\ext;C:\Windows\Sun\Java\lib\ext
os.name:                     Windows 7
os.arch:                     amd64
os.version:                  6.1
user.name:                   desk3200id
user.dir:                    E:\work\niotests
user.home:                   C:\Users\desk3200id
Default FileSystem Provider: file
Absolute path of demo file:  E:\work\niotests\demofile.txt
Result of deleteIfExists:    true
Result of isWritable:        false
Result of isWritable:        false
Line read:                   First line of text
Line read:                   Second line of text


ERROR MESSAGES/STACK TRACES THAT OCCUR :
No crashes or error messages occurred.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package com.rosebell.niotests;

//=====================================================================================================IsWritableBugDemo
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
class
  IsWritableBugDemo
  {
  final static String
    NL = System.getProperty("line.separator")
   ;
  //..............................................................................................................main
  public static void
    main(final String[] p_params)
    {
                                                                                //--------------------------------------
                                                                                //Show environment.
                                                                                //--------------------------------------
    System.err.println("java.vm.name:                "+System.getProperty("java.vm.name"));
    System.err.println("java.vm.version:             "+System.getProperty("java.vm.version"));
    System.err.println("java.vm.vendor:              "+System.getProperty("java.vm.vendor"));
    System.err.println("java.version:                "+System.getProperty("java.version"));
    System.err.println("java.vendor:                 "+System.getProperty("java.vendor"));
    System.err.println("java.class.path:             "+System.getProperty("java.class.path"));
    System.err.println("java.library.path:           "+System.getProperty("java.library.path"));
    System.err.println("java.ext.dirs:               "+System.getProperty("java.ext.dirs"));
    System.err.println("os.name:                     "+System.getProperty("os.name"));
    System.err.println("os.arch:                     "+System.getProperty("os.arch"));
    System.err.println("os.version:                  "+System.getProperty("os.version"));
    System.err.println("user.name:                   "+System.getProperty("user.name"));
    System.err.println("user.dir:                    "+System.getProperty("user.dir"));
    System.err.println("user.home:                   "+System.getProperty("user.home"));
    System.err.println("Default FileSystem Provider: "+FileSystems.getDefault().provider().getScheme());

    final Path
      demoPath = Paths.get("demofile.txt")
     ;
    System.err.println("Absolute path of demo file:  "+demoPath.toAbsolutePath().toString());
    try
      {
      System.err.println("Result of deleteIfExists:    "+Files.deleteIfExists(demoPath));

      OutputStream
        demoOutputStream = Files.newOutputStream(demoPath)
       ;
      demoOutputStream.write(("First line of text"+NL).getBytes());
      demoOutputStream.close();

      System.err.println("Result of isWritable:        "+Files.isWritable(demoPath));
      demoOutputStream = Files.newOutputStream(demoPath
                                              ,StandardOpenOption.APPEND
                                              );
      demoOutputStream.write(("Second line of text"+NL).getBytes());
      demoOutputStream.close();

      System.err.println("Result of isWritable:        "+Files.isWritable(demoPath));

      final List<String>
        linesRead = Files.readAllLines(demoPath
                                      ,Charset.defaultCharset()
                                      );
      for (String line : linesRead)
        {
        System.err.println("Line read:                   "+line);
        }                                                   // for line
      }
    catch (IOException e)
      {
      System.err.println("IOException occurred: ");
      e.printStackTrace(System.err);
      }
    }                                                       // main method
  //..................................................................................................................
  }                                                         // IsWritableBugDemo class
//======================================================================================================================

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I have just commented out calls to this isWritable method.

I do appreciate that you have added these java.nio.file.Files methods, as those provided by java.io.File look only at the DOS file attributes and are well out-of-date.

Comments
There have been several reports of this issue so the impact (in ILW terms) of this bug is higher than originally thought so I've up'ed the priority to P3.
25-05-2013

That is hard to create the regression test. It needs the MS ACL-editor command line utilities.
13-03-2013

The attachments contain the NB project (JDK-7190897.zip) for the test and the screen shot of problematic security setup (demofileSec.png) for the [demofile.txt] file in MS Explorer. Test procedure : 1) Build the project to make a jar file (essential!) 2) Run the project output without fix: Result of isWritable vs Thread token: false Result of isWritable vs Process token: false output after the fix: Result of isWritable vs Thread token: true Result of isWritable vs Process token: true
28-02-2013

EVALUATION: The [AccessCheck] function need to be used. [GetEffectiveRightsFromAcl] takes into account just static TRUSTEE and ACL info (out of execution context) "The GetEffectiveRightsFromAcl function does not consider the following: - Implicitly granted access rights, such as READ_CONTROL and WRITE_DAC, for the owner of an object when determining effective rights. - Privileges held by the trustee when determining effective access rights. - =>>Group rights associated with the logon session, such as interactive, network, authenticated users, and so forth, in determining effective access rights.<== - Resource manager policy. For example, for file objects, Delete and Read attributes can be provided by the parent even if they have been denied on the object." http://msdn.microsoft.com/en-gb/library/windows/desktop/aa446637%28v=vs.85%29.aspx The selection is the bug source.
01-02-2013

EVALUATION We have had several reports of issues with Files.isReadable that we believe is the same issue but so far we have not been able to duplicate the problem. I suspect (but not proven) that it stems from the implementation using the Win32 GetEffectiveRightsFromAcl function which is known to be buggy and needs to be replaced to use AccessCheck instead. Once that is in jdk8 then we will contact the submitter and ask them to re-test to see if that resolves the issue.
13-08-2012