14

I'm getting a different result for Files.exists(path) to path.toFile().exists() for a local file on Windows. I can see this file in Windows Explorer although I have (randomly) modified permissions and perhaps the permissions do not make sense.

However this doesn't explain why the old method returns true and the new methods returns false. The file definently exists but maybe it is invisible to the user running the Java code, so I'm not sure what the correct answer should be. Nor can I see how to see which user is running the code, there is only one real user Paul on the computer, but I'm wondering if whether if run as administrator or not effects things.

System.out.println("Path Exists(1):"+Files.exists(path));
System.out.println("Path Exist(2) :"+path.toFile().exists());

gives

Path Exists(1):false
Path Exist(2) :true

Also

System.out.println("Path readable(3) :"+Files.isReadable(path));
System.out.println("Path readable(4):"+path.toFile().canRead());

works in same way giving

Path readable(3) :false
Path readable(4):true

Permissions output

File C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf permissions
owner:PCLAPTOP\Paul
NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTIN\Administrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTIN\Administrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
NT AUTHORITY\SYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
BUILTIN\Users:READ_DATA/READ_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/READ_ACL/SYNCHRONIZE:ALLOW
NT AUTHORITY\Authenticated Users:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/SYNCHRONIZE:ALLOW


c:\Code\jthink\opensrc\jaudiotagger>attrib C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf
A    R       C:\Code\jthink\opensrc\jaudiotagger\testdata\test157.dsf

Update I dont have a conclusion but thought this information could be useful.

I was running code in IntelliJ IDE without the IDE Run program as Administrator option enabled, enabling this did then cause the Java application to also get the administrator privileges.

Interesting for another file I didn't add any DENY privileges, I just disabled inherit permissions and remove READ permissions from all groups. Then when I ran as user without run as admin enabled it could not read the file and also this code could not any output any information

AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
if (view != null)
{
    sb.append("Owner:"+view.getOwner().getName()+"**");
    for (AclEntry acl : view.getAcl())
    {
        sb.append(acl.principal()+"**");
        for(AclEntryPermission aep:acl.permissions())
        {
            sb.append(aep.toString() + "**");
        }
    }
}

but when I run with Run program as adminstrator enabled it still couldnt read the file, but the above code did now output some of the permissions as follows:

Owner:BUILTIN\Administrators

NT AUTHORITY\SYSTEM:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCHRONIZE:ALLOW PCLAPTOP\Paul:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCHRONIZE:ALLOW BUILTIN\Administrators:WRITE_DATA/APPEND_DATA/WRITE_NAMED_ATTRS/WRITE_ATTRIBUTES/SYNCHRONIZE:ALLOW

as you can see even though Administrators do not have READ or READ PERMISSIONS options they can output the permissions whereas before they couldn't, perhaps due to BUILTIN/Administraor being returned as owner.

soufrk
  • 825
  • 1
  • 10
  • 24
Paul Taylor
  • 13,411
  • 42
  • 184
  • 351

2 Answers2

8

Try reading this: https://docs.oracle.com/javase/tutorial/essential/io/check.html

It states that, Files.exists(path) returning false does not mean that it does not exist, so yeah it would seem there is a permission problem. Try the Files.notExists(path) as well and see what it returns. If it is false it means that it can not be determined whether the file exists, but if it returns true, there is probably some problem in your code.

Try running your file from the command line instead of netbeans. If you don't know how to do this you can just search google, there is tons of stuff on this, but basically what you want to do is to compile the .java file with javac myfile.java and then run it with java myfile. Do this with a normal command prompt and one you open as administrator and see what you get.

PNS
  • 750
  • 1
  • 5
  • 19
  • 1
    When I read this I took that to mean it didnt have access because of network problems, but yes I think you are right. But I dont see this as an improvement over the old method. I used to check for file existence, and then for file readability, now its seems I can only check for file existence if I have file read permissions. I know how to run from command line , but how do you run as Adminstrator from command line on Windows. – Paul Taylor Feb 01 '16 at 09:13
  • To the best of my knowledge it should suffice to start the command line as admin. I'm not sure I understand what you mean about improvement. Your approach is fine I think, it follows the doc and checks for existence and readability. The problem seems to be your access rights as Alex says, If you are running it on a web server of some sort (JBoss, Tomcat) try checking their settings. – PNS Feb 01 '16 at 09:52
  • By 'improvement' I mean with the old file.exists() method you can check if the file exists regardless of your permissions, then you can use canRead(0 to check if you can read it. With the new exists() method it seems you can only check if it it exists if you have permissions to do, so you cant differentiate between doesnt exist and exists but dont have permission to check if exists. Thanks found the Command Prompt (Adminstrator) option now but I would stil like to know as how to run choose whether to run as adminsitrator form JetBrains. – Paul Taylor Feb 01 '16 at 10:44
  • Ah ok. I don't think there is any improvement for one over the other, they simply have different use cases. Afterall path.toFile().exists() could also return true for a folder which you may or may not want in some case. Have you tried starting intellij as admin ? That should give the child processes (running a main method) the same privileges. Check this: http://stackoverflow.com/questions/7736536/does-intellij-start-processes-with-administrator-rights Otherwise you probably need to set a configuration file or in registry that that program should run as admin or turn off UAC (not recommended) – PNS Feb 01 '16 at 11:07
  • 1
    I think most developers would see there is a new exists() method andjust use it over the old one as it really not clear from the Javadoc how they differ. – Paul Taylor Feb 01 '16 at 11:47
  • Perhaps. I think there are differences, as discussed by us and also by Alex below, but whether it is good design from java is another story. I think they should have perhaps made it more clear why this method has been introduced, though I don't think it is intended to deprecate the old one. – PNS Feb 01 '16 at 12:20
  • Ah okay i thought it was, I thought the idea was to move away from File and only use Path instead, is that incorrect. – Paul Taylor Feb 01 '16 at 12:30
  • Well path is more of an abstract (easier) way of managing paths, but when you need to work with an actual directory the file system is still in effect. Otherwise java would have probably deprecated it (and may at som point). But for now it seems that path is just doing a lot of what file was previously doing, but cannot totally replace it. – PNS Feb 01 '16 at 12:40
4

Theses are two different methods: Files.exists() and path.toFile().exists().

Files.exists() defines that file denoted by this abstract pathname exists. In other words that file exists and user has READ access to it.

path.toFile().exists() indicates the file exists then there is no guarantee that a subsequence access will succeed. In other words file exist without checking that user has READ access to it.

It really depends on user which runs the program. When you work under your ID (Paul) it works fine. Especially in command line where you gan you ATTRIB command.

However, when you use some other application to run your code it depends on the system configuration. Run this ATTRIB or similar command inside your application and you will see.

I think you run some web site under IIS. This way is usually configured for lowest level user in the system with almost no rights to prevent security breaks. Usually it is everyone or NT AUTHORITY. As I can see this particular access has no rights to read your file

NT AUTHORITY\SYSTEM:READ_DATA/...:DENY

Naturally you have 2 different answers - FALSE: user which ID is used by running application cannot read this file, TRUE: file physically exist.

Change running ID for your application or grant READ access to everyone for this particular file including all directories in its path and you will have the same result in this two methods which check different meanings.

Alkanshel
  • 4,198
  • 1
  • 35
  • 54
Alex
  • 4,457
  • 2
  • 20
  • 59
  • Thanks I expect you are right, but I'm not getting it from reading the Javadoc, both say If a security manager exists they check its SecurityManager.checkRead(java.lang.String) method for file access, it really isnt clear that one ignore read access and the other does not.(BTW your Javadoc links are the wrong way round). Im not running a website, it is a Swing java application. what I don't understand if Im running as Adminstrator do I not still have the permissions of the normal user in additional to the permissions of the adminsitrator. – Paul Taylor Feb 01 '16 at 09:09
  • Inside your app run command (Runtime.exec) to determine who you are (whoami) and see what user is used to run your app. That's the only possible explanation what I can see. (BTW it looks for me my links are correct File is for File and Files is for Files) – Alex Feb 01 '16 at 13:44
  • never knew whoami was available on Windows - thanks. But I know the user what I dont know is know if application is being 'run as administrator' , i.e with additional administrator priviledges, is thus possible. Ive checked your Javadoc links again and they still appear to be wrong way round. – Paul Taylor Feb 01 '16 at 14:57
  • Found it, http://stackoverflow.com/questions/18631597/java-on-windows-test-if-a-java-application-is-run-as-an-elevated-process-with – Paul Taylor Feb 01 '16 at 15:43