如何从 NTFS/FAT32 中的逻辑簇号查找有关文件的信息?
我正在尝试通过 Windows 碎片整理 API 对单个文件进行碎片整理 ( http://msdn.microsoft.com/en-us/library/aa363911(VS.85).aspx )但是如果没有足够大的可用空间块容纳我的文件我想移动其他部分文件为其腾出空间。
链接的文章提到了移动其他文件的部分,但我找不到任何有关如何查找要移动的文件的信息。从可用空间位图中,我可以找到一个几乎足够大的空间,并且我知道它周围的逻辑簇号,但是从中我无法找出它周围有哪些文件,并且需要文件的句柄来执行 FSCTL_MOVE_FILE 移动文件的一部分。
有没有什么办法,通过API或通过解析MFT,找出逻辑簇号属于哪个文件,以及文件中的哪个虚拟簇号对应于通过位图找到的逻辑簇号?
I am trying to defragment a single file through Windows defragmentation API ( http://msdn.microsoft.com/en-us/library/aa363911(VS.85).aspx ) but if there is no free space block large enough for my file I would like to move other parts of files to make room for it.
The linked article mentions moving parts of other files but I can't find any information about how to find out which files to move. From the free space bitmap I can find an almost large enough space and I know the logical cluster numbers surrounding it, but from this I can't find out which files are surrounding it and a handle to the files is required to do FSCTL_MOVE_FILE which moves parts of files.
Is there any way, through the API or by parsing the MFT, to find out what file a logical cluster number is part of, and what virtual cluster number in the file corresponds to the logical cluster number found through the bitmap?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
缓慢但兼容的方法是递归扫描所有目录中的文件,并使用 FSCTL_GET_RETRIEVAL_POINTERS。然后扫描生成的 VCN-LCN 映射以查找相关集群。
另一种选择是查询驱动器的 USN 日志以获取文件引用 ID,然后使用 FSCT_GET_NTFS_FILE_RECORD 获取 $MFT 文件记录。
我目前正在开发一个简单的碎片整理程序(用Java 编写),目的是将目录中的文件(例如大型游戏的所有文件)紧密地打包在一起,以减少加载时间和加载延迟。
我使用更快的方法来检索 NTFS 或 FAT32 驱动器上的文件映射。
我直接解析 $MFT 文件(该格式有一些缺陷),或者 FAT32 文件分配表以及目录。
诀窍是使用 FileCreate 打开驱动器(例如“c:”)以进行完全共享的 GENERIC 读取。然后可以使用 FileRead 和 FileSeek 以字节粒度读取生成的句柄。这仅适用于管理员模式(或提升模式)。
在 NTFS 上,$MFT 可能是碎片,并且从引导扇区信息中定位它有点棘手。我在 C:\$MFT 文件上使用 FSCTL_GET_RETRIEVAL_POINTERS 来获取其集群。
在 FAT32 上,必须解析引导扇区以定位 FAT 表和包含根目录文件的簇。您需要解析目录条目并递归地定位子目录的簇。
The slow but compatible method is to recursively scan all directories for files, and use the FSCTL_GET_RETRIEVAL_POINTERS. Then scan the resulting VCN-LCN mapping for the cluster in question.
Another option would be to query the USN Journal of the drive to get the File Reference IDs, then use FSCT_GET_NTFS_FILE_RECORD to get the $MFT file record.
I'm currently working on a simple Defrag program (written in Java) with the aim to pack files of a directory (e.g. all files of a large game) close together to reduce loading times and loading lags.
I use a faster method to retrieve the file mappings on the NTFS or FAT32 drive.
I parse the $MFT file directly (the format has some pitfalls), or the FAT32 file allocation table along with the directories.
The trick is to open the drive (e.g. "c:") with FileCreate for fully shared GENERIC read. The resulting handle can then be read with FileRead and FileSeek on a byte granularity. This works only in administrator mode (or elevated).
On NTFS, the $MFT might be fragmented and is a bit tricky to locate it from the boot sector info. I use the FSCTL_GET_RETRIEVAL_POINTERS on the C:\$MFT file to get its clusters.
On FAT32, one must parse the boot sector to locate the FAT table and the cluster containing root directory file. You need to parse the directory entries and recursively locate the clusters of the sub-directories.
不存在从块 # 映射到文件的 O(1) 方式。您需要遍历整个 MFT 来查找包含该块的文件。
当然,在实时系统中,一旦您读取了该数据,它就已过时,并且您必须为移动数据 FSCTL 中的故障做好准备。
There is no O(1) way of mapping from block # to file. You need to walk the entire MFT looking for files that contain that block.
Of course, in a live system, once you've read that data it's out-of-date and you must be prepared for failures in the move data FSCTL.