2017-11-26 7 views
3

ディレクトリツリー(ディレクトリの場合は0755、ファイルの場合は644)で正しいアクセス権を確保したい。ここに私のクラスは次のとおりです。chmod -R 755を模倣するjava walkFileTreeが機能しない

package NRF_Utils; 

import java.io.IOException; 
import java.nio.file.FileVisitResult; 
import static java.nio.file.FileVisitResult.*; 
import java.nio.file.FileVisitor; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.util.Set; 
import java.util.logging.Logger; 
import java.nio.file.attribute.BasicFileAttributes; 
import java.nio.file.attribute.PosixFilePermission; 
import java.nio.file.attribute.PosixFilePermissions; 

public class DirectoryTreeOperations { 
    private static final Logger log = Logger.getLogger("spv." + DirectoryTreeOperations.class.getName()); 

    public static boolean setPermissions(String root, String directoryPermissions, String filePermissions) { 
     boolean result = true; 
     //declaring the path to delete 
     final Path path = Paths.get(root); 
     final Set<PosixFilePermission> dirPermissions = PosixFilePermissions.fromString(directoryPermissions); 
     final Set<PosixFilePermission> filPermissions = PosixFilePermissions.fromString(filePermissions); 

     try { 
      Files.walkFileTree(path, new FileVisitor<Path>() { 

       @Override 
       public FileVisitResult preVisitDirectory(Path dir, 
         BasicFileAttributes attrs) throws IOException { 
        System.out.println("setting dir permission on " + dir); 
        Files.setPosixFilePermissions(dir, dirPermissions);     
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult visitFile(Path file, 
         BasicFileAttributes attrs) throws IOException { 
        System.out.println("setting file permission on " + file); 
        Files.setPosixFilePermissions(file, filPermissions); 
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult visitFileFailed(Path file, IOException exc) 
         throws IOException { 
        log.severe("visitFileFailed failed on " + file + " : " + exc); 
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult postVisitDirectory(Path dir, 
         IOException exc) throws IOException { 
        return CONTINUE; 
       } 

      }); 
     } catch (IOException e) { 
      log.severe("setPermissions failed " + e); 
      result = false; 
     } 
     return result; 
    } 

    // TODO remove and provide a proper unit test 
    public static void main(String [] arg) { 
     System.out.println ("setPermissions returned: " + setPermissions("/tmp/x", "rwxr-xr-x", "rw-r--r--")); 
    } 
} 

テストを実行するには、私が行っている:

mkdir -p /tmp/x/y/z;touch /tmp/x/y/z/f;chmod 000 /tmp/x/y/z 

出力は次のとおりです。

setting dir permission on /tmp/x 
setting dir permission on /tmp/x/y 
setPermissions returned: true 
nov. 26, 2017 2:45:00 PM NRF_Utils.DirectoryTreeOperations$1 visitFileFailed 
GRAVE: visitFileFailed failed on /tmp/x/y/z : java.nio.file.AccessDeniedException: /tmp/x/y/z 

Javaがあるため、ディレクトリツリーを探索したくないようです権限は間違っていますが、私の目的はディレクトリツリーを調べて権限を修正することでした。 APIはクレイジーですか?

+3

のchmod 000は、まったくの読み取り/書き込みアクセス権がないことを意味します。そのため、 'AccessDeniedException'で正しく失敗しています。あなたのコードを 'root'ユーザとして実行すると動作するかもしれません! – RaviH

+0

chmod -R 755は完全にユーザーとして動作します。ルートの必要はありません。 – BOC

+0

詳細については、rootとして動作します。なぜシェルコマンドchmod -RをネイティブのJavaコードに置き換えるのが難しいのか分かりません。私はちょうどスクリプトを呼び出すことを避けたい。 – BOC

答えて

5

このように振る舞うのは奇妙なようです(狂ったAPIではないかもしれませんが)。実際には、preVisitDirectory()を使用してディレクトリにアクセスできる特定のケースに対応していません。

Files.walkFileTree() DOCは言う:

ファイルがディレクトリであり、ディレクトリを開くことができませんでした

、 その後、visitFileFailed方法は、I/O例外で呼び出され 、ファイルされた後、デフォルトでは、ディレクトリの次の 兄弟にツリーウォークが続きます。

を呼び出す前に、実装を見て実際にディレクトリを開こうとしていますが、実行中の問題について説明しています。

解決策として、FileTreeWalker.javaソースを取得し、自分のローカルバージョンのFileTreeWalkerでマイナー調整を行うことができます。まったく同じように、visitor.preVisitDirectory()への呼び出しを探して、開いたディレクトリコードをそれ。その後にコードを変更:あなたが実行すると

new FileTreeWalker(EnumSet.noneOf(FileVisitOption.class), new FileVisitor<Path>() { 
    ... 
    }, Integer.MAX_VALUE).walk(path); 

、あなたが買ってあげる:

setting dir permission on /tmp/x 
setting dir permission on /tmp/x/y 
setting dir permission on /tmp/x/y/z 
setting file permission on /tmp/x/y/z/f 
setPermissions returned: true 

あなたFileVisitorの実装の罰金であることを示しています。

希望に役立ちます。

2

chmod 755 /tmp/x/y/zをコマンドラインから実行すると、zのアクセス許可はチェックされません。 yに十分アクセスできる限り、chmodzに実行することができます。あなたがFiles.walkFileTreesource codeを見れば

OTOHは、それは実際に、それはあなたの訪問者のメソッドを呼び出す前に、などのファイル属性を収集するために、独自のvisit方法で、すべてのターゲットファイルにアクセスしようとします。したがって、アクセス拒否エラーです。

これを見ると、自分のファイルツリーウォーカーをロールバックしなければならない場合があります。先に目標パスにアクセスしようとせずに権限を変更するだけです。

1

walkFileTreeとの唯一の問題は、検索する権限のないディレクトリでpreVisitDirectory()を呼び出さないことです。 walkFileTreeが探している場所の直前にアクセス許可を修正することで回避できます。 手動preVisitDirectoy()に渡す任意のディレクトリの直接の子をスキャンし、(むしろvisitFileよりも)そこにアクセス権を適用することにより、すなわち:

  @Override 
      public FileVisitResult preVisitDirectory(Path dir, 
        BasicFileAttributes attrs) throws IOException { 
       for(File f : new File(dir.toUri()).listFiles()) { //iterate over the contents of the directory 
        System.out.println("setting dir permission on " + f); 
        Files.setPosixFilePermissions(dir.resolve(f.getName()), dirPermissions); 
       } 

       //System.out.println("setting dir permission on " + dir); 
       //Files.setPosixFilePermissions(dir, dirPermissions); 
       return CONTINUE; 
      } 

次にあなたがコメントアウトすることができますvisitFile()の体:

  @Override 
      public FileVisitResult visitFile(Path file, 
        BasicFileAttributes attrs) throws IOException { 
      // System.out.println("setting file permission on " + file); 
      // Files.setPosixFilePermissions(file, filPermissions); 
       return CONTINUE; 
      } 

ウォークスルーが行われた場所の下に1つ下の権限を適用するので、tryブロックのすぐ内側に追加の呼び出しが必要です。

 System.out.println("setting dir permission on " + path); //in case the initial path needs fixing 
     Files.setPosixFilePermissions(path, dirPermissions); 
例のケースで実行した場合

import java.io.File; 
import java.io.IOException; 
import java.nio.file.FileVisitResult; 
import static java.nio.file.FileVisitResult.*; 
import java.nio.file.FileVisitor; 
import java.nio.file.Files; 
import java.nio.file.Path; 
import java.nio.file.Paths; 
import java.util.Set; 
import java.util.logging.Logger; 
import java.nio.file.attribute.BasicFileAttributes; 
import java.nio.file.attribute.PosixFilePermission; 
import java.nio.file.attribute.PosixFilePermissions; 

public class DirectoryTreeOperations { 
    private static final Logger log = Logger.getLogger("spv." + DirectoryTreeOperations.class.getName()); 

    public static boolean setPermissions(String root, String directoryPermissions, String filePermissions) { 
     boolean result = true; 
     //declaring the path to delete 
     final Path path = Paths.get(root); 
     final Set<PosixFilePermission> dirPermissions = PosixFilePermissions.fromString(directoryPermissions); 
     final Set<PosixFilePermission> filPermissions = PosixFilePermissions.fromString(filePermissions); 

     try { 
      System.out.println("setting dir permission on " + path); //in case the initial path needs fixing 
      Files.setPosixFilePermissions(path, dirPermissions); 

      Files.walkFileTree(path, new FileVisitor<Path>() { 
       @Override 
       public FileVisitResult preVisitDirectory(Path dir, 
         BasicFileAttributes attrs) throws IOException { 
        for(File f : new File(dir.toUri()).listFiles()) { //iterate over the contents of the directory 
         System.out.println("setting dir permission on " + f); 
         Files.setPosixFilePermissions(dir.resolve(f.getName()), dirPermissions); 
        } 

        //System.out.println("setting dir permission on " + dir); 
        //Files.setPosixFilePermissions(dir, dirPermissions); 
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult visitFile(Path file, 
         BasicFileAttributes attrs) throws IOException { 
       // System.out.println("setting file permission on " + file); 
       // Files.setPosixFilePermissions(file, filPermissions); 
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult visitFileFailed(Path file, IOException exc) 
         throws IOException { 
        log.severe("visitFileFailed failed on " + file + " : " + exc); 
        return CONTINUE; 
       } 

       @Override 
       public FileVisitResult postVisitDirectory(Path dir, 
         IOException exc) throws IOException { 
        return CONTINUE; 
       } 

      }); 
     } catch (IOException e) { 
      log.severe("setPermissions failed " + e); 
      result = false; 
     } 
     return result; 
    } 

    // TODO remove and provide a proper unit test 
    public static void main(String [] arg) { 
     System.out.println ("setPermissions returned: " + setPermissions("/tmp/x", "rwxr-xr-x", "rw-r--r--")); 
    } 
} 

:ここ

は一緒に全部(まあ、私は利便性のためのあなたのパッケージ宣言を脱い)です

$ mkdir -p /tmp/x/y/z;touch /tmp/x/y/z/f;chmod 000 /tmp/x/y/z 
$ find /tmp/x 
/tmp/x 
/tmp/x/y 
/tmp/x/y/z 
find: â/tmp/x/y/zâ: Permission denied 
$ java DirectoryTreeOperations 
setting dir permission on /tmp/x 
setting dir permission on /tmp/x/y 
setting dir permission on /tmp/x/y/z 
setting dir permission on /tmp/x/y/z/f 
setPermissions returned: true 
$ find /tmp/x 
/tmp/x 
/tmp/x/y 
/tmp/x/y/z 
/tmp/x/y/z/f 
関連する問題