Why does Files.isWritable() method return true for a directory even when it is set to read only?

Viewed 423

I have explicitly set read only mode both through setReadOnly method as well as setWritable(false).

File file  = new File(myDir);
file.setReadOnly();
file.setWritable(false);
file.setExecutable(false);
return file.canWrite();

I also checked through windows explorer that the specified directory is marked read-only:

enter image description here

In the above example , the file.canWrite returns true. Is there a stricter way of enforcing read only mode?

1 Answers

The api specification for java.io.File states the following as kind of disclaimer -

A file system may implement restrictions to certain operations on the actual file-system object, such as reading, writing, and executing. These restrictions are collectively known as access permissions. The file system may have multiple sets of access permissions on a single object. For example, one set may apply to the object's owner, and another may apply to all other users. The access permissions on an object may cause some methods in this class to fail.

And definitely this is the case with you. On Linux(Ubuntu-18.04) things look to be very normal and as per specification. Outputs for the following code using Java sdk-1.8.0_222 in the 2 environments is printed below

import java.io.File;

public class FileDemo {

   public static void main(String[] args) {
      File f = null;
      boolean bool = false;

      try {

         // create new file
         f = new File("test");

         f.setWritable(false);
         bool = f.canWrite();
         System.out.println("Can write to test: "+bool);
         f.setWritable(true);
         bool = f.canWrite();
         System.out.println("Can write to test: "+bool+"\n\n");

                 f.mkdir();
                 //f.createNewFile();

                 f.setWritable(false);
         bool = f.canWrite();
         System.out.println("Can write to test: "+bool);
         f.setWritable(false);
         bool = f.canWrite();
         System.out.println("Can write to test: "+bool);

      } catch(Exception e) {

         // if any I/O error occurs
         e.printStackTrace();
      }
   }
}

Windows (file) -

C:\Users\rranjan\Desktop>java FileDemo
Can write to test: false
Can write to test: false


Can write to test: false
Can write to test: true

C:\Users\rranjan\Desktop>java FileDemo
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Can write to test: false
Can write to test: true


Can write to test: false
Can write to test: true

Linux (file) -

rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: false


Can write to test: false
Can write to test: true
rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: true


Can write to test: false
Can write to test: true

Windows (directory) -

C:\Users\rranjan\Desktop>java FileDemo
Can write to test: false
Can write to test: false


Can write to test: true
Can write to test: true

C:\Users\rranjan\Desktop>java FileDemo
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Can write to test: true
Can write to test: true


Can write to test: true
Can write to test: true

Linux (directory) -

rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: false


Can write to test: false
Can write to test: true
rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: true


Can write to test: false
Can write to test: true

Now, you can observe that for a file or directory, if it doesn't exist, canWrite() is always False. After the file/directory is created on a Linux platform, for both a file as well as a directory, setting writeable works seamlessly. Whereas, on a Windows box, directory seems to return true whatsoever. This is the kind of behavior which I quoted in the above lines.

Related