2

In Windows a file may not be writable because the user simply doesn't have permission to modify the file due to Access Control Lists permissions, or just because the read only attribute is set for the file.

My application is written in Java and either of these conditions could cause Files.isWritable(file) to fail, but how can I determine which condition caused the failure, specifically I just want to know if the read only attribute is set.

I note that there is a File.setReadOnly() method (as well as File.setWritable()), and I assume on Windows this would just set the attribute, but there doesn;t seem to be a File.isReadOnly() method.

Paul Taylor
  • 13,411
  • 42
  • 184
  • 351

3 Answers3

2

I used this method to check if read only, (it uses custom method Platform .ifWindows() to only run on Windows, but you could use alternatives).

private boolean isReadOnlyFile(Path file)
    {
        if(Platform.isWindows())
        {
            if (!file.toFile().canWrite())
            {
                DosFileAttributes dosAttr;
                try
                {
                    dosAttr = Files.readAttributes(file, DosFileAttributes.class);
                    if(dosAttr.isReadOnly())
                    {
                        return true;
                    }
                }
                catch (IOException e)
                {

                }
            }
        }
        return false;
    }
Paul Taylor
  • 13,411
  • 42
  • 184
  • 351
1

Use the canWrite() method:

if(file.canWrite()) {
    System.out.println("you can write");
} else {
     System.out.println("you cannot write");
}

Useful info:

Returns: true if and only if the file system actually contains a file denoted by this abstract pathname and the application is allowed to write to the file; false otherwise.

Throws: SecurityException - If a security manager exists and its SecurityManager.checkWrite(java.lang.String) method denies write access to the file

Eduardo Briguenti Vieira
  • 4,351
  • 3
  • 37
  • 49
  • On Windows, does this really only test the read-only bit, or does it do something more complicated? – Harry Johnston Feb 02 '16 at 01:30
  • Im pretty sure this would also check permissions as well like the Files.isWritable() method. – Paul Taylor Feb 02 '16 at 08:28
  • Actually Ive tried it and isWritable() only returns false when read only attribute checked, if I just remove write access from ACl it still returns true, so I think this will work. I assume there is no such distinction on an OSX/Unix system ? – Paul Taylor Feb 02 '16 at 08:46
  • But doesn't seem quite as simple as that, I think sometimes setting the read-only flag also affects the permissions and sometimes it doesn't, maybe depending on whether the file is inheriting permissions form its parent folder or not. – Paul Taylor Feb 02 '16 at 09:03
  • Ah, I could (double)check using Java 7 NIO2 DosFileAttributes dosAttr = Files.readAttributes(file, DosFileAttributes.class);if(dosAttr.isReadOnly()) – Paul Taylor Feb 02 '16 at 09:27
  • @PaulTaylor: that sounds right. You might want to post that as an answer. – Harry Johnston Feb 03 '16 at 01:15
-1

Don't. Just try to open the file for output. If it isn't writable, it will fail. Catch the exception and deal with it then. Don't try to predict the future. You could test it wrong, or it could change between test and use, both ways.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Doesn't really answer the question, IMO. After the file has failed to open, the OP is presumably still going to want to know whether the reason it failed to open might be that the read-only bit was set. – Harry Johnston Feb 02 '16 at 01:29
  • @HarryJohnston The exception message will tell him that, and it will also tell him a lot of other reasons the file wasn't opened, and it doesn't involve fortune-telling. And in your comment to another answer you have precisely identified another shortcoming of these fortune-telling techniques. If you test the wrong thing you get a different answer. And if you test the right thing, it may change between test and use. And if it doesn't change, the system has to repeat the test anyway when you go to use the resource. – user207421 Feb 02 '16 at 03:23
  • *The exception message will tell him that* - really? That's unexpected; why would Java bother? Are you sure it doesn't just say something like "access denied"? – Harry Johnston Feb 02 '16 at 03:44
  • 1
    The actual writing is done by a library that doesnt return the original exception so I cant do as you suggest. I understand your concern about predicting the future but since the check is done immediately before the actual write this isnt really an issue for my application, it could hapen but very unlikley, and if does happen they would just get a less helpful error message that couldn't be saved. But what I am trying to do is give the user more help in identifying why there file is not writable as usually failure to write is unexpected for them. – Paul Taylor Feb 02 '16 at 08:49
  • @HarryJohnston The exception message contains whatever the operating system provides for the error concerned. Your example is strange. 'Access denied' is certainly a sufficient message, as opposed to for example 'no such file or directory', wihch would indicate that an intermediate directory didn't exist in the case of an output file. – user207421 Feb 03 '16 at 09:09
  • @EJP no its no sufficient at all, I want to be able to report to the user why it failed, just telling them they dont have permission is not enough. – Paul Taylor Feb 03 '16 at 20:13
  • 1
    There's a distinction between "access denied because the ACL doesn't give you access to the file" and "access denied because the read-only bit is set". From the user's point of view, these are two completely different problems, with completely different solutions. Generally speaking I personally would be happy to present the user with an error message saying "you might not have access to write to the file, or the read-only bit might be set" but I can understand why someone might want to be more specific. – Harry Johnston Feb 03 '16 at 22:57