This tutorial is part of Java NIO tutorial series. In this tutorial, let us get introduced to Files
class from java.nio.file
package, it offers static methods to operate on files and directories. Let us start our Java files tutorial with permissions. How to check a file if it has a certain permission before operating on it. Like check if a file has a read permission before reading it or a directory has a write permission before writing on it. Before going into how to check permissions, lets think about should we really do it? Or is this the right approach? My opinion is no, we should not check before we use it. Are you aware of TOCTTOU (pronounced ‘Tock too’).
TOCTTOU is short form for “Time to Check to Time of Use”. We do a permission check and then based on result we perform operation on the respective object. What will happen if the permission is changed in between? This might lead to security holes as our logic is based on this race condition. A possible solution to this scenario is to design our application logic to directly perform the action and if it is allowed let the operation complete and if not let us have a fallback. So eventually going to exception handling mechanism based programming.
Now let us learn about how to check file permissions. Be aware of TOCTTOU and use the below accordingly. I suggest an alternate approach below instead of checking for permissions and acting based on it.
package com.javapapers.java.nio; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class FilePermissionNIO { public static void main(String args[]) { Path file = Paths.get("C:\\Users\\Cycle\\Desktop\\a.html"); boolean isRegularFile = Files.isRegularFile(file); boolean isHidden = Files.isReadable(file); boolean isReadable = Files.isReadable(file); boolean isExecutable = Files.isExecutable(file); boolean isSymbolicLink = Files.isSymbolicLink(file); Path directory = Paths.get("C:\\Users\\Cycle\\Desktop"); boolean isDirectory = Files.isDirectory(directory); boolean isWritable = Files.isWritable(directory); } }
Nice thing about these methods by default can identify symbolic links and trace to the real file and check for permission. It provides argument if it is not required to do so.
These methods are actually convenience methods. This delegates to some other APIs and eventually to native file system calls. AccessDeniedException
is checked exception and a type of IOException. It is thrown when a file system operation is denied due to insufficient permissions. AccessControlException
is a RuntimeException
and it is thrown by the SecurityManager when a security policy is restricting the required operation on the file.
Path file = Paths.get("C:\\Users\\Cycle\\Desktop\\a.txt"); Files.delete(file);
Delete a file using the above line of code and then change the permission to read-only. Now try to delete the file and you will get the following exception on a Windows operating system and this is dependent on the native calls.
Exception in thread "main" java.nio.file.AccessDeniedException: C:\Users\Cycle\Desktop\a.txt at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97) at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102) at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269) at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103) at java.nio.file.Files.delete(Files.java:1126) at com.javapapers.java.nio.FilePermissionNIO.main(FilePermissionNIO.java:24)
People have different opinions on this. I strongly believe we should follow “strategy-B” to design our programs when encountering file permission based decision scenarios. Generally exception handling mechanism is not to be used for decision making or branching but this scenario is different.
package com.javapapers.java.nio; import java.io.IOException; import java.nio.file.AccessDeniedException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class FilePermissionNIO { public static void main(String args[]) throws IOException { Path file = Paths.get("C:\\Users\\Cycle\\Desktop\\a.txt"); String userMessage = ""; userMessage = strategyA(file); System.out.println("Strategy A: " + userMessage); userMessage = strategyB(file); System.out.println("Strategy B: " + userMessage); } public static String strategyA(Path file) throws IOException { String userMessage = ""; boolean isWritable = Files.isWritable(file); if (isWritable) { Files.delete(file); userMessage = "Deleted Successfully!"; } else { userMessage = "File is not writable."; } return userMessage; } public static String strategyB(Path file) throws IOException { String userMessage = ""; try { // do not check for permission // just go ahead and delete // if denied, act based on it Files.delete(file); userMessage = "Deleted Successfully!"; } catch (AccessDeniedException ade) { ade.printStackTrace(); userMessage = ade.getMessage() + " File is not writable."; } return userMessage; } }
Please share your opinion as comments for this tutorial as it will really help.
Comments are closed for "Java File Permissions – Don’t Check Permissions before Use".
Please avoid using implementation dependent device and dudirectory separators. This examples doesn’t work in Unix, OSX or Linux. And it doesn’t need to be that.
And yes, I do agree with you.
It is normal to have the needed access to files your program work with. If not, that is an exception that is needed to be handle…
Hi Joe…
Very nice article. Keep going.
Regards
Pushparaj S
Hi Joe,
Good article. Will be waiting to read more articles from you.
Regards
Vishwam
Hi Joe, Article is nice. I have two question.
1. I am still not clear strategy B is exception and should be handled for file system only.
2. Jor and Anders, why this example will not work for Unix, OSX and Linux. What should be in this case ?
Hi , joe Very nice article. Keep going.
Very nice looking for more such article
Hi, Joe this is very nice article on java.nio but i want know how do achieve this when doing operations on file using java.io
Nice approach to code for such situations ,thanks joe
Hi Joe,
Best thank for your article, Very nice. I really like it.
But When I read it, I try to find somethings which is not good point when we use strategy-B. In my opinion It will be better when we know good point and not good point of 1 solution, and we will know correctly when we can use it.
What do you think about the performance of strategy-B ? The time to throw 1 exception maybe need more than check isWritable.
Is it good if we have a lot of locals try to detele 1 file at the same time ? and only 1 local can delete it, other local maybe got FileNotFoundException not AccessDeniedException.
Finally, best thanks for your posts. I really like your website.
Regards, Dzung
[…] File Permissions […]
Thanks for giving such a information, can you tell me something more about Java NIO..?