16

The following is some simple code just to test the Files.walkFileTree() method. However, the folder /etc/ssl/private, which has these permissions (rwx--x---), throws an exception, even when I thought I guarded it with an if statement (if (permissions.equals("rwx--x---")).

What am I doing wrong? Thanks in advance.

public static void main (String []args) throws IOException, InterruptedException
{       
    Files.walkFileTree(Paths.get("/"), new WalkingTheThing2());
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
{
    PosixFileAttributeView posixView = Files.getFileAttributeView(dir, PosixFileAttributeView.class);
    PosixFileAttributes posixAttr = posixView.readAttributes();
    String permissions =PosixFilePermissions.toString(posixAttr.permissions());
    if (permissions.equals("rwx--x---"))
    {
        return FileVisitResult.SKIP_SUBTREE;
    }

    return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
        throws IOException {
    try{

        System.out.println(file.getFileName()+" " +Files.size(file));

        return FileVisitResult.CONTINUE;
    }
    catch(IOException io){return FileVisitResult.CONTINUE;}
}

The exception I get is: java.nio.file.AccessDeniedException: /etc/ssl/private

EDIT: Solved by overriding visitFileFailed:

public FileVisitResult visitFileFailed(Path file, IOException io)
{   
    return FileVisitResult.SKIP_SUBTREE;
}
Georg Leber
  • 3,470
  • 5
  • 40
  • 63
Rollerball
  • 12,618
  • 23
  • 92
  • 161
  • 2
    You just asked the exact same question a few minutes ago, and then deleted it. Why is this question any different? – Xynariz Aug 12 '13 at 21:25
  • @Xynariz Because I resolved the previous issue with a mere try catch in FileVisit. Here is another issue java.nio.file.AccessDeniedException: /etc/ssl/private – Rollerball Aug 12 '13 at 21:29
  • Then just catch the `AccessDeniedException` the same way. You can have multiple `catch` statements on a single `try` block. – Xynariz Aug 12 '13 at 21:30
  • 3
    You have almost 2000 rep and have not yet learnt to format your code? Please use your IDE's auto format functionality and edit your post. I, for one, cannot follow that mess... – Boris the Spider Aug 12 '13 at 21:30
  • Why with this check does not work? `if (permissions.equals("rwx--x---")) { return FileVisitResult.CONTINUE; }` – Rollerball Aug 12 '13 at 21:33
  • That if statement does NOTHING as your code currently stands... whether or not you go into the `if` statment, you will still execute `return FileVisitResult.CONTINUE` . What you want to do is add an additional `catch` block to your `try` block. – Xynariz Aug 12 '13 at 21:36
  • @Xynariz you are right my bad! I meant to type SKIP_SUBTREE, editing now. However it won't work that' why I asked the question – Rollerball Aug 12 '13 at 21:40
  • @Xynariz I am aware I can use another catch block. However with SKIP_SUBTREE should work and I cannot see why it does not. – Rollerball Aug 12 '13 at 21:42
  • Debug the code and see if you enter that `if`. You could work out what the permissions are too while you're at it... – Boris the Spider Aug 12 '13 at 21:43
  • Any time you have an error thrown that isn't caught, it will cause the program to halt. It doesn't matter what the error is, or where it's thrown. The reason your `SKIP_SUBTREE` doesn't work is because it doesn't prevent the error from happening. – Xynariz Aug 12 '13 at 21:44
  • @Xynariz The point of preVisitDirectory is to prevent this kind of things.. – Rollerball Aug 12 '13 at 21:46
  • Even catching the exception in preVisitDirectory does not work, I think it behind the scenes pass it to visitFileFailed, now I am trying to fix it from there. Thanks for your time everybody. – Rollerball Aug 12 '13 at 21:56

2 Answers2

2

If you are traversing the whole directory System and there is a situation where you got some type of Exception like AccessDeniedException and you want skip that file so that you could check the other file you need to override the visitFileFailed and skip that file or directory.

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
    System.err.printf("Visiting failed for %s\n", file);
    return FileVisitResult.SKIP_SUBTREE;
} 

This is the work around I have found when Walking through the directory system.

Root
  • 955
  • 1
  • 16
  • 39
0

Although overriding visitFileFailed solved your problem, it might be hiding the fact you are still doing several things wrong:

  1. Files.getFileAttributeView can return null (e.g. if the file system does not support POSIX file permissions) making posixView.readAttributes() fail on NPE
  2. posixView.readAttributes() can itself throw exceptions (e.g. if you don't have the required permissions to read the file's permissions) - this might be the cause of the AccessDeniedException you got
  3. Not entirely wrong, but comparing the string representation of the permissions might be inappropriate for this use case, unless you want to explicitly check that the file has the given permissions - and does not have the the others; a different approach would be to check just for the required permissions:

    Set<PosixFilePermission> perm = posixAttr.permissions();
    if (perm.contains(OWNER_READ) || perm.contains(GROUP_READ) || perm.contains(OTHERS_READ)) {
        return FileVisitResult.SKIP_SUBTREE;
    }
    
Kunda
  • 463
  • 3
  • 5