java - 哪些java.nio.file.Files方法遵循符号链接(symbolic link),哪些不遵循符号链接(symbolic link)?

标签 java symlink symlink-traversal

Java帮助程序类java.nio.file.Files具有访问文件属性的方法。一些类方法遵循符号链接(所有带有LinkOption参数的方法),而对于其他一些方法,不清楚是否遵循符号链接(没有LinkOption参数的方法)。

这些是遵循符号链接的方法:


Files.isDirectory(Path, LinkOption...)
Files.isRegular(Path, LinkOption...)
Files.getAttribute(Path, String, LinkOption...)
Files.getLastModified(Path, LinkOption...)
Files.getOwner(Path, LinkOption...)
Files.getPosixFilePermission(Path, LinkOption...)


对于其他一些方法,确定它们是否遵循符号链接并不明显(在Javadoc中没有LinkOption...参数并且没有提及符号链接):


Files.isSymbolicLink(Path)
Files.isExecutable(Path)
Files.isReadable(Path)
Files.isWritable(Path)
Files.isHidden(Path)
Files.size(Path)
Files.getFileStore(Path)


跟随符号链接的不带LinkOption...参数的方法有哪些,为什么?

最佳答案

TLDR:在大多数情况下,这似乎是FileSystemProvider实现方式的选择,即不遵循符号链接(这可以回答“为什么”问题)。符号链接是:

已关注:


Files.size(Path)


主要关注:


Files.getFileStore(Path):在Windows和Linux上紧随其后,在Jimfs上不紧随其后


未遵循:


Files.isSymbolic(Path)


通常不遵循:


Files.isExecutable(Path):在Windows和Unix上不遵循,但在Jimfs上遵循
Files.isReadable(Path):在Windows和Unix上不遵循,但在Jimfs上遵循


完全特定于实现:


Files.isWritable(Path):在Windows上遵循,但在Unix上没有
Files.isHidden(Path):在Windows上遵循,但在Unix上没有


您可以通过调用Files.readAttributes(Path, Class, LinkOption...)并使用返回的属性来确定是否跟随符号链接。

Files.isSymbolic(Path)不跟随符号链接

对于Files.isSymbolic(Path),原因很明显:如果默认情况下该方法遵循符号链接,则该方法将始终返回false

Files.isHidden(Path)在Windows上遵循符号链接,但在Unix上不遵循

从方法签名来看,我们可能认为该方法未遵循符号链接(因为没有LinkOption...参数)。但是,这并不是很明显。

Files.isHidden(Path)方法委托给java.nio.file.spi.FileSystemProvider.isHidden(Path)的实现,并且无论该方法是否遵循符号链接,javadoc均未指定。

在Windows上,它是implemented by following symbolic links,请参见第465行(true调用中的WindowsFileAttributes.get(file, true)参数指示遵循符号链接):

@Override
public boolean isHidden(Path obj) throws IOException { 
    WindowsPath file = WindowsPath.toWindowsPath(obj); 
    file.checkRead(); 
    WindowsFileAttributes attrs = null; 
    try { 
        attrs = WindowsFileAttributes.get(file, true); 
    } catch (WindowsException x) { 
        x.rethrowAsIOException(file); 
    } 
    // DOS hidden attribute not meaningful when set on directories 
    if (attrs.isDirectory()) 
        return false; 
    return attrs.isHidden(); 
} 


在Unix上,此方法为implemented without following symbolic links(它仅检查文件以“。”开头):

@Override
public boolean isHidden(Path obj) {
    UnixPath file = UnixPath.toUnixPath(obj);
    file.checkRead();
    UnixPath name = file.getFileName();
    if (name == null)
        return false;
    return (name.asByteArray()[0] == '.');
}


因此,我们可以得出结论,这是特定于实现的。

Files.isExecutable(Path)在大多数文件系统中不遵循符号链接

此方法委托给Files.isAccessible(Path, AccessMode.EXECUTE),后者委托给FileSystemProvider.checkAccess(Path, AccessMode...)方法。

在Windows上,WindowsFileSystemProvider.checkAccess(Path, AccessMode...)方法委托给java.lang.SecurityManager,后者确定文件是否可执行。 AFAIK,SecurityManager不跟随符号链接,因此我们可以假定Files.isExecutable(Path)在Windows上不跟随符号链接。

在Unix上,UnixFileSystemProvider.checkAccess(Path, AccessMode...)方法也委托给SecurityManager,我们可以假定Files.isExecutable(Path)在Unix上也不遵循符号链接。

在Jimfs(来自Google的内存中文件系统)上,调用将委托给com.google.common.jimfs.FileSystemView.checkAccess(JimfsPath),该链接遵循符号链接(即使Jimfs不支持访问控制):

public void checkAccess(JimfsPath path) throws IOException {
    // just check that the file exists
    lookUpWithLock(path, Options.FOLLOW_LINKS).requireExists(path);
}


因此,我们可以得出结论,根据文件系统,Files.isExecutable(Path)可能跟随符号链接,但在大多数情况下(Unix + Windows)不会。

Files.isReadable(Path)在大多数文件系统上不遵循符号链接

Files.isReadable(Path)的实现与isExecutable(Path)的实现非常相似:在Unix和Windows上不遵循链接,但在Jimfs上遵循链接。

Files.isWritable(Path)

对于Files.isExecutable(Path)isWritable(Path)方法委托给FileSystemProvider.checkAccess(Path)

在Windows上,这需要确定文件是否具有只读属性,这是通过以下链接完成的(请参见上面的WindowsFileSystemProvider代码)。

在Unix上,显然无需跟随符号链接即可完成此操作(请参见上面的UnixFileSystemProvider)。

因此,我们可以得出结论,这是特定于实现的。

Files.size(Path)跟随符号链接

该实现委托给readAttributes,因此它遵循所有文件系统实现的符号链接:

public static long size(Path path) throws IOException {
    return readAttributes(path, BasicFileAttributes.class).size();
}


Files.getFileStore(Path)

该方法委托给FileSystemProvider.getFileStore(Path)方法。

在Windows上,它使用跟随符号链接的WindowsFileStore.create(Path)(请参阅true参数):

static WindowsFileStore create(WindowsPath file) throws IOException {
    try {
        // if the file is a link then GetVolumePathName returns the
        // volume that the link is on so we need to call it with the
        // final target
        String target = WindowsLinkSupport.getFinalPath(file, true);
  ...


在Unix上,FileSystemProvider.getFileStore(Path)方法是抽象的,由子类实现,例如[LinuxFileSystem][3]

@Override
LinuxFileStore getFileStore(UnixPath path) throws IOException {
    return new LinuxFileStore(path);


}

此类通过获取带有以下链接的属性(UnixFileStore调用中的true参数)来构造UnixFileAttributes.get()

private static long devFor(UnixPath file) throws IOException {
    try {
        return UnixFileAttributes.get(file, true).dev();
    } catch (UnixException x) {
        x.rethrowAsIOException(file);
        return 0L;  // keep compiler happy
    }
}


在Jimfs中,FileStore似乎是在创建时附加到文件的,因此,看起来没有遵循链接。

因此,我们可以得出结论,在大多数文件系统实现中,Files.getFileStore(Path)使用符号链接。

关于java - 哪些java.nio.file.Files方法遵循符号链接(symbolic link),哪些不遵循符号链接(symbolic link)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55894781/

相关文章:

python - 如何在 Homebrew 中对 python 进行符号链接(symbolic link)?

Node.js 确定符号链接(symbolic link)的目标路径

java - 奇怪的错误 - 从菜单中断后不执行任何操作

linux - 无法跟踪其他用户使用 root 创建的符号链接(symbolic link)

java - 如何创建 Java 程序的试用版

linux - 通过 tftp 访问符号链接(symbolic link)

swift - swift 从文件路径读取数据时如何处理符号链接(symbolic link)

java - 开发者站点在 webview-shouldOverrideUrlLoading 方面相互矛盾

java - 使用多维数组进行矩阵乘法 Java