【问题标题】:File.canWrite and Files.isWritable not giving correct value on LinuxFile.canWrite 和 Files.isWritable 在 Linux 上没有给出正确的值
【发布时间】:2015-04-06 15:13:36
【问题描述】:

我有这个测试java程序

import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.Files;

public class TestFileReadOnly
{    
    public static void main(String[] args)
    {
        String filePath = args[0];
        File f = new File(filePath);

        System.out.println("File.canWrite() for file: " + filePath + ", is: " + f.canWrite());
        System.out.println("Files.isWritable() for file: " + filePath + ", is: " + Files.isWritable(FileSystems.getDefault().getPath(f.getParent(), f.getName())));
    }
}  

我使用 root 登录 Linux 并创建两个文件。

echo "test file" > /root/ro.txt
echo "test file" > /root/rw.txt
chmod 444 /root/ro.txt
chmod 777 /root/rw.txt

当我这样执行测试程序时,输出总是不正确

[root@xxx ~]# /jdk1.8.0_31/bin/java TestFileReadOnly /root/ro.txt
File.canWrite() for file: /root/ro.txt, is: true
Files.isWritable() for file: /root/ro.txt, is: true
[root@xxx ~]# /jdk1.8.0_31/bin/java TestFileReadOnly /root/rw.txt
File.canWrite() for file: /root/rw.txt, is: true
Files.isWritable() for file: /root/rw.txt, is: true

我基本上是在寻找 java 代码来验证文件是否是只读的,但我无法使用上面的方法来实现它。但是,这在 Windows 上运行良好。我尝试使用 jdk1.7.0_07、jdk1.7.0_75 和 jdk1.8.0_31 编译和执行,但结果是一样的。非常感谢任何解决此问题的帮助。

解决方案: 使用 @Matteo 的建议,将 PosixFileAttributes 用于类 UNIX 平台。工作代码如下:

private boolean isFileReadOnly(File file)
{
    boolean isReadOnly = false;
    if (System.getProperty("os.name").startsWith("Windows"))
    {
        // All Windows versions
        isReadOnly = !file.canWrite();
    }
    else
    {
        // All Unix-like OSes.
        Path path = Paths.get(file.getParent(), file.getName());
        PosixFileAttributes attributes = null;
        try
        {
            attributes = Files.getFileAttributeView(path, PosixFileAttributeView.class).readAttributes();
        }
        catch (java.io.IOException e)
        {
            // File presence is guaranteed. Ignore
            e.printStackTrace();
        }

        if (attributes != null)
        {
            // A file is read-only in Linux only when it has 0444 permissions.
            Set<PosixFilePermission> permissions = attributes.permissions();

            if (!permissions.contains(PosixFilePermission.OWNER_WRITE)
                && !permissions.contains(PosixFilePermission.OWNER_EXECUTE)
                && !permissions.contains(PosixFilePermission.GROUP_WRITE)
                && !permissions.contains(PosixFilePermission.GROUP_EXECUTE)
                && !permissions.contains(PosixFilePermission.OTHERS_WRITE)
                && !permissions.contains(PosixFilePermission.OTHERS_EXECUTE))
            {
                isReadOnly = true;
            }
        }
    }
    return isReadOnly;
}

【问题讨论】:

  • 无论您运行 java 的用户是否有权查看这些文件夹?如果他们无法访问这些文件夹,我认为他们无法访问这些文件。
  • 你不能访问/root,除非你是root
  • 将文件放入您的主文件夹~/anysubfolder,然后重试
  • 我在 x86_64 平台上的 Red Hat Linux 6.4 上登录并以 root 身份执行。如果可行,有人可以在他们的系统上试用吗?
  • 我相信root可以绕过UNIX权限并写入只读文件。您应该以普通用户身份运行您的 java 程序。

标签: java file file-permissions


【解决方案1】:

以普通用户身份执行您的程序,在这两种情况下您都将获得false,因为您无法访问/root 目录。

root 执行您的程序,您将在这两种情况下得到true,因为root 即使没有写入权限也可以写入文件:

$ echo uuu > ro.txt 
$ echo > ro.txt 
$ ls -l ro.txt 
-r--r--r-- 1 root root 1 Feb  6 15:03 ro.txt
$ cat ro.txt 

$ echo Test > ro.txt 
$ cat ro.txt 
Test

【讨论】:

  • 我刚刚在我的机器上以 root 身份进行了测试,并按预期工作。能否请您发布ls -ld /root/的结果@
  • [root@xxx ~]# ls -ld /root/ dr-xr-x---。 33 根根 4096 年 2 月 6 日 18:57 /root/
  • 在Java中没有任何方法可以仅根据文件上设置的权限返回结果,而不考虑基于所有者和登录用户的有效能力吗?是否有其他 API 可以实现这一点?
  • 您可以使用docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/…,但它仅适用于 POSIX 系统
  • 由于 File.canWrite() 在 Windows 上工作,我对类 UNIX 平台使用了 PosixFileAttributes 方法(我想要的平台 - AIX、HP-UX 和 Solaris 都完全兼容 POSIX)。有效的方法如下:
猜你喜欢
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 2013-11-15
  • 1970-01-01
  • 2020-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多