NTFS文件系统解析(二)

编程入门 行业动态 更新时间:2024-10-09 08:29:02

NTFS<a href=https://www.elefans.com/category/jswz/34/1771295.html style=文件系统解析(二)"/>

NTFS文件系统解析(二)

1、引言

NTFS文件系统的的工作流程主要依赖于两个部分,文件记录部分用于记录文件本身的信息,而索引部分则通过树的形式存储着文件系统的结构信息。
而无论是文件记录还是索引,NTFS文件系统都为其设计了标准的数据结构,便于解析。

2、结构

从结构层面上说,无论文件记录还是索引,其本身的结构都相对简单,如下所示:
| 文件记录头 | 属性列表 | 属性列表 |… …| 结束标志 |
| 索引记录头 | 索引头 | 索引数据 | … … | 结束标志 |

// File Record Layout
// Record Header
// Attribute
// Attribute
// ...
// End Marker (0xFFFFFFFF)
typedef struct {b32 magic;          // MFT标志,始终为"FILE"ub16 usn_offset;    // 更新序列号USN(update sequence number)偏移ub16 usn_size;      // 更新序列号数组大小,单位:wordb64 lsn;            // 日志文件序列号($LogFile Sequence Number,LSN)ub16 sn;            // 序列号(used times of this record)ub16 hard_links;    // 硬链接数ub16 attr_offset;   // 第一个属性列表的偏移ub16 flags;         // 标志(Flag),00H表示文件被删除,01H表示文件正在使用,02H表示目录被删除,03H表示目录正在使用b32 used;           // 文件记录实际使用的长度,可以理解为文件大小b32 alloced;        // 文件记录分配的长度,可以理解为磁盘占用大小b64 record_ref;     // 基本文件记录的文件索引号。当一个文件存在0x20属性列表时,用于区分是否主文件记录。ub16 next_attr;     // 下一属性IDub16 border;        // 填充b32 record_number;  // 文件记录的参考号
} FileRecordHeader;typedef struct {// Index Record Headerb32 magic;        // 索引记录标志,始终为"INDX"ub16 usn_offset;  // 更新序列号USN(update sequence number)偏移ub16 usn_size;    // 更新序列号数组大小,单位:wordb64 lsn;          // 日志文件序列号b64 vcn;          // 虚拟簇号// Index Headerb32 entry_offset;  // 第一个索引的偏移b32 total_size;    // 所有索引的实际大小b32 alloc_size;    // 所有索引的分配大小b8 flags;          // 标志(Flag),1表示存在子节点,2表示叶子节点b8 padding[3];     // 填充
} IndexBlock;

3、更新序列号(USN)

NTFS文件系统为了保持数据的一致性,在文件和索引记录的每个扇区的最后2个字节都会写入更新序列号。正常情况下,不需要考虑这种特殊情况。
但是,当一个记录的恰巧写到扇区最后2个字节时,由于扇区尾部已经写入了2个字节的更新序列号。因此,NTFS文件系统会将本应写入扇区尾部的2个字节记录到文件记录的USN数组中。所以当需要解析文件记录时,我们需要将USN数组中的内容还原到对应的位置上去。

bool CFileRecord::PatchUS(b16 *sector_pointer, b32 sector_num, b16 usn,b16 *us_data) const {// 遍历文件激烈的所有扇区for (b32 i = 0; i < sector_num; i++) {// 偏移到扇区的最后一个字sector_pointer += ((ntfs_volume_->sector_size_ >> 1) - 1);// 检测更新序列号是否一致if (*sector_pointer != usn) return false;  // USN check// 还原数据*sector_pointer = us_data[i];              // set data to update ussector_pointer++;}return true;
}// 当读取到文件记录时
if (frh->magic == kFileRecordMagic) {// 计算出USN数组的位置b16 *usn_addr = (b16 *)((b8 *)frh + frh->usn_offset);// 第一个字存储USNb16 usn = *usn_addr;// 第二个字开始存储实际数据b16 *usarray = usn_addr + 1;if (PatchUS((b16 *)frh,ntfs_volume_->mft_size_ / ntfs_volume_->sector_size_, usn,usarray)) {file_record_ = frh;return true;}
}

更多推荐

NTFS文件系统解析(二)

本文发布于:2023-11-16 11:58:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1620596.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文件系统   NTFS

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!