我在Java中编写了一个重复的查找器,但我需要为它添加硬链接支持。不幸的是,似乎没有办法在Java中挖出文件的MFT条目。
虽然在BasicFileAttributeView类中有一个名为fileKey()的方法,但它在NTFS文件系统上不起作用(我还没有在ext上测试过它)。
我还找到了方法isSameFile()(在java.nio.file.Path中)。有谁知道这种方法是如何工作的?它似乎正在做正确的事情,但它返回一个布尔值,所以它对我来说毫无价值(我希望将结果放入地图并按照MFT条目对它们进行分组)。
我总能比较每个文件的创建时间,修改时间等,但这只是放弃了。
有没有办法在C ++或Java中完成我想要做的事情?我更关心的是让它在NTFS上工作而不是分机。
答案 0 :(得分:1)
通常通过调用FindFirstFileNameW
来完成检测硬链接。但是有一个较低层次的方式。
要使NTFS等同于inode,请尝试使用FSCTL_GET_OBJECT_ID
ioctl代码。
BY_HANDLE_FILE_INFORMATION
structure中还有一个唯一的(直到文件被删除)标识符。
如果卷已启用USN Change Journal,您可以发出FSCTL_READ_FILE_USN_DATA
ioctl代码。查看USN_RECORD
structure
FileReferenceNumber
成员
答案 1 :(得分:1)
您需要使用FILE_ID_FULL_DIRECTORY_INFORMATION
结构以及NtQueryDirectoryFile
功能(或FILE_INTERNAL_INFORMATION
结构以及NtQueryInformationFile
,如果您已经拥有句柄) ntdll.dll
(自Windows XP以来可用,如果不是更早的话)获取8字节文件ID并检查它们是否相同。
这将告诉您它们是否是相同的文件,但如果它们是同一文件的 stream ,则不会。
我不确定如何检测两个文件是否是来自用户模式的相同流 - 有一个名为FILE_STREAM_INFORMATION
的结构可以返回与文件关联的所有流,但它不会告诉你你当前打开了哪个流。
答案 2 :(得分:0)
在Java中,您可以使用sun.nio.ch.FileKey
,它是NTFS Inode的非透明机箱。所有硬链接共享相同的Inode。
因此,如果您需要收集硬链接,可以从每个嫌疑人创建FileKey
并进行比较(例如,将一对FileKey - >文件放入Multimap
)
答案 3 :(得分:0)
我发现fileKey
始终为空。这是一些可以实际读取NTFS索引节点号的代码。我仍然不满意许多方面,尤其是它依赖反思。
import sun.nio.ch.FileKey;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Path;
public 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 privateStringField = FileKey.class.getDeclaredField("nFileIndexHigh");
privateStringField.setAccessible(true);
long high = (long) privateStringField.get(fk);
privateStringField = FileKey.class.getDeclaredField("nFileIndexLow");
privateStringField.setAccessible(true);
long low = (long) privateStringField.get(fk);
long power = (long) 1 << 32;
long inode = high * power + low;
return inode;
}
}
}