starainrt 7e6cc73106
完善 Windows 运维封装与 NTFS 索引解析
- 新增自启动幂等配置、统一错误语义、进程等待和进程树终止能力
- 增强服务生命周期管理,支持等待状态、重启、幂等创建和配置更新
- 新增 NTFS 卷索引、文件 ID 解析、文件遍历、USN 变更监听和 bookmark 持久化
- 修复 NTFS boot sector、fragment、MFT、USN 解析边界和路径重建问题
- 补充权限、进程、服务、NTFS 解析和工作流回归测试
- 增加 Windows 测试脚本和管理员 NTFS smoke 验证脚本
- 升级 Go 兼容版本到 1.18,并更新 stario、win32api 及相关间接依赖
2026-06-09 15:59:31 +08:00

143 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"b612.me/wincmd"
"b612.me/wincmd/ntfs/mft"
"b612.me/wincmd/ntfs/usn"
"b612.me/wincmd/ntfs/utf16"
"encoding/binary"
"errors"
"fmt"
"io"
"log"
_ "net/http/pprof"
"regexp"
"runtime"
"time"
)
func main() {
f, size, err := mft.GetMFTFileReader(`C:\`)
if err != nil {
panic(err)
}
defer f.Close()
recordSize := int64(1024)
i := int64(0)
fmt.Println("start size is", size)
alreadyGot := int64(0)
maxRecordSize := size / recordSize
if maxRecordSize > 1024 {
maxRecordSize = 1024
}
for {
for {
if (size - alreadyGot) < maxRecordSize*recordSize {
maxRecordSize--
} else {
break
}
}
if maxRecordSize < 10 {
maxRecordSize = 1
}
buf := make([]byte, maxRecordSize*recordSize)
got, err := io.ReadFull(f, buf)
if err != nil {
if errors.Is(err, io.EOF) {
break
}
log.Fatalln("Unable to read record data", err)
}
alreadyGot += int64(got)
for j := int64(0); j < 1024*maxRecordSize; j += 1024 {
record, err := mft.ParseRecord(buf[j : j+1024])
if err != nil {
// fmt.Println("Unable to parse MFT record", err)
continue
}
fname := record.FindAttributes(mft.AttributeTypeFileName)
for _, v := range fname {
if (record.Flags&mft.RecordFlagIsIndex)>>3 == 0 && record.Flags&mft.RecordFlagInUse == 1 {
filename := utf16.DecodeString(v.Data[66:], binary.LittleEndian)
//data:=utf16.DecodeString(v.Data, binary.LittleEndian)
if filename != "" {
attbr := record.FindAttributes(mft.AttributeTypeStandardInformation)
if len(attbr) == 0 {
break
}
stand, _ := mft.ParseStandardInformation(attbr[0].Data)
if stand.FileAttributes&mft.FileAttributeNormal == 1 {
i++
}
//oo:=record.FindAttributes(mft.AttributeTypeData)
//if len(oo)!=0 {
// fmt.Println(oo[0].ActualSize)
//}
//r := binutil.NewLittleEndianReader(v.Data[:8])
//fmt.Println(record.FileReference.ToUint64(), r.Uint64(0))
//fmt.Println(filename)
//log.Println("Read MFT record")
}
}
}
}
}
fmt.Println(i)
//go http.ListenAndServe("0.0.0.0:8888", nil)
fmt.Println("开始获取Windows磁盘列表")
lists, err := wincmd.ListDrivers()
if err != nil {
panic(err)
}
info := []usn.DiskInfo{}
for _, v := range lists {
data, err := wincmd.GetDiskInfo(v)
if err != nil {
continue
}
fmt.Println("获取到磁盘信息:", data)
info = append(info, data)
}
fmt.Println("忽略非NTFS磁盘")
var m runtime.MemStats
for _, v := range info {
if v.Format == "NTFS" && v.Driver == `C:\` {
fmt.Println("开始获取NTFS USN日志磁盘", v.Driver)
fileLists, err := usn.ListUsnFileFn(v.Driver, func(name string, typed bool) bool {
return true
if ok, _ := regexp.MatchString(`\.exe$`, name); ok {
return true
}
return false
})
if err != nil {
panic(err)
}
fmt.Println(len(fileLists))
return
for k, _ := range fileLists {
fmt.Println(k)
}
runtime.ReadMemStats(&m)
log.Printf("Alloc = %v TotalAlloc = %v Sys = %v NumGC = %v\n", m.Alloc/1024, m.TotalAlloc/1024, m.Sys/1024, m.NumGC)
runtime.GC()
p := time.After(time.Second * 86400)
for {
select {
case <-p:
return
case <-time.After(time.Second * 10):
runtime.ReadMemStats(&m)
log.Printf("Alloc = %v TotalAlloc = %v Sys = %v NumGC = %v\n", m.Alloc/1024, m.TotalAlloc/1024, m.Sys/1024, m.NumGC)
}
}
}
}
}