2

我用 Java 编写了一个重复查找器,但我需要包含对它的硬链接支持。不幸的是,似乎没有办法在 Java 中挖掘出文件的 MFT 条目。

虽然 BasicFileAttributeView 类中有一个名为 fileKey() 的方法,但它在 NTFS 文件系统上不起作用(我还没有在 ext 上测试过)。

我还找到了方法isSameFile()(在 java.nio.file.Path 中)。有谁知道这种方法是如何工作的?它似乎在做正确的事情,但它返回一个布尔值,所以对我来说毫无价值(我希望将结果放入映射并按其 MFT 条目对它们进行分组)。

我总是可以比较每个文件的创建时间、修改时间等,但这只是放弃。

有什么方法可以完成我在 C++ 或 Java 中尝试做的事情吗?我更关心让它在 NTFS 上工作而不是 ext。

4

4 回答 4

1

您需要在内部(从 Windows XP 开始可用,如果不是更早)使用FILE_ID_FULL_DIRECTORY_INFORMATION结构和NtQueryDirectoryFile函数(或者FILE_INTERNAL_INFORMATION结构和相同。NtQueryInformationFilentdll.dll

这将告诉您它们是否是同一个文件,但如果它们是同一个文件的同一个,则不会。

我不确定如何从用户模式检测两个文件是否是同一个流 - 有一个名为的结构FILE_STREAM_INFORMATION可以返回与文件关联的所有流,但它不会告诉您当前打开了哪个流.

于 2012-02-20T08:19:46.597 回答
1

检测硬链接通常通过调用FindFirstFileNameW. 但是有一个较低级别的方法。

要获得与 inode 等效的 NTFS,请尝试FSCTL_GET_OBJECT_IDioctl 代码。

BY_HANDLE_FILE_INFORMATION结构中还有一个唯一的(直到文件被删除)标识符。

如果卷具有启用的 USN 更改日志,您可以发出FSCTL_READ_FILE_USN_DATAioctl 代码。检查结构FileReferenceNumber中的成员USN_RECORD

于 2012-02-20T03:52:01.450 回答
0

在 Java 中,您可以使用sun.nio.ch.FileKeyNTFS Inode 的非透明外壳。所有硬链接共享同一个 Inode。

因此,如果您需要收集硬链接,您可以FileKey从每个嫌疑人创建并比较它们(例如,通过将 FileKey -> File 对放入 a 中Multimap

于 2017-01-17T13:23:40.087 回答
0

我发现fileKey总是空的。这是一些可以实际读取 NTFS inode 编号的代码。还有很多我不满意的方面,尤其是,它依赖于反思。

import sun.nio.ch.FileKey;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Path;

class NTFS {
    static long inodeFromPath(Path path) throws IOException, NoSuchFieldException, IllegalAccessException {
        try (FileInputStream fi = new FileInputStream(path.toFile())) {
            FileDescriptor fd = fi.getFD();

            FileKey fk = FileKey.create(fd);
            Field privateField = FileKey.class.getDeclaredField("nFileIndexHigh");
            privateField.setAccessible(true);
            long high = (long) privateField.get(fk);
            privateField = FileKey.class.getDeclaredField("nFileIndexLow");
            privateField.setAccessible(true);
            long low = (long) privateField.get(fk);

            long power = (long) 1 << 32;
            long inode = high * power + low;
            return inode;
        }
    }
}
于 2019-12-31T21:25:51.687 回答