完善 Windows 运维封装与 NTFS 索引解析
- 新增自启动幂等配置、统一错误语义、进程等待和进程树终止能力 - 增强服务生命周期管理,支持等待状态、重启、幂等创建和配置更新 - 新增 NTFS 卷索引、文件 ID 解析、文件遍历、USN 变更监听和 bookmark 持久化 - 修复 NTFS boot sector、fragment、MFT、USN 解析边界和路径重建问题 - 补充权限、进程、服务、NTFS 解析和工作流回归测试 - 增加 Windows 测试脚本和管理员 NTFS smoke 验证脚本 - 升级 Go 兼容版本到 1.18,并更新 stario、win32api 及相关间接依赖
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Package bootsect provides functions to parse the boot sector (also sometimes called Volume Boot Record, VBR, or
|
||||
$Boot file) of an NTFS volume.
|
||||
Package bootsect provides functions to parse the boot sector (also sometimes called Volume Boot Record, VBR, or
|
||||
$Boot file) of an NTFS volume.
|
||||
*/
|
||||
package bootsect
|
||||
|
||||
@@ -35,12 +35,7 @@ func Parse(data []byte) (BootSector, error) {
|
||||
}
|
||||
r := binutil.NewLittleEndianReader(data)
|
||||
bytesPerSector := int(r.Uint16(0x0B))
|
||||
sectorsPerCluster := int(int8(r.Byte(0x0D)))
|
||||
if sectorsPerCluster < 0 {
|
||||
// Quoth Wikipedia: The number of sectors in a cluster. If the value is negative, the amount of sectors is 2
|
||||
// to the power of the absolute value of this field.
|
||||
sectorsPerCluster = 1 << -sectorsPerCluster
|
||||
}
|
||||
sectorsPerCluster := int(r.Byte(0x0D))
|
||||
bytesPerCluster := bytesPerSector * sectorsPerCluster
|
||||
return BootSector{
|
||||
OemId: string(r.Read(0x03, 8)),
|
||||
@@ -49,7 +44,7 @@ func Parse(data []byte) (BootSector, error) {
|
||||
MediaDescriptor: r.Byte(0x15),
|
||||
SectorsPerTrack: int(r.Uint16(0x18)),
|
||||
NumberofHeads: int(r.Uint16(0x1A)),
|
||||
HiddenSectors: int(r.Uint16(0x1C)),
|
||||
HiddenSectors: int(r.Uint32(0x1C)),
|
||||
TotalSectors: r.Uint64(0x28),
|
||||
MftClusterNumber: r.Uint64(0x30),
|
||||
MftMirrorClusterNumber: r.Uint64(0x38),
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package bootsect
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseBootSectorUsesCorrectFieldWidths(t *testing.T) {
|
||||
data := make([]byte, 512)
|
||||
copy(data[0x03:], []byte("NTFS "))
|
||||
binary.LittleEndian.PutUint16(data[0x0B:], 512)
|
||||
data[0x0D] = 8
|
||||
data[0x15] = 0xF8
|
||||
binary.LittleEndian.PutUint16(data[0x18:], 63)
|
||||
binary.LittleEndian.PutUint16(data[0x1A:], 255)
|
||||
binary.LittleEndian.PutUint32(data[0x1C:], 0x11223344)
|
||||
binary.LittleEndian.PutUint64(data[0x28:], 0x0102030405060708)
|
||||
binary.LittleEndian.PutUint64(data[0x30:], 0x1112131415161718)
|
||||
binary.LittleEndian.PutUint64(data[0x38:], 0x2122232425262728)
|
||||
data[0x40] = 0xF6
|
||||
data[0x44] = 1
|
||||
copy(data[0x48:], []byte{1, 2, 3, 4, 5, 6, 7, 8})
|
||||
|
||||
boot, err := Parse(data)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse failed: %v", err)
|
||||
}
|
||||
|
||||
if boot.SectorsPerCluster != 8 {
|
||||
t.Fatalf("SectorsPerCluster = %d, want 8", boot.SectorsPerCluster)
|
||||
}
|
||||
if boot.HiddenSectors != 0x11223344 {
|
||||
t.Fatalf("HiddenSectors = %#x, want %#x", boot.HiddenSectors, 0x11223344)
|
||||
}
|
||||
if boot.FileRecordSegmentSizeInBytes != 1024 {
|
||||
t.Fatalf("FileRecordSegmentSizeInBytes = %d, want 1024", boot.FileRecordSegmentSizeInBytes)
|
||||
}
|
||||
if boot.IndexBufferSizeInBytes != 4096 {
|
||||
t.Fatalf("IndexBufferSizeInBytes = %d, want 4096", boot.IndexBufferSizeInBytes)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user