- 新增自启动幂等配置、统一错误语义、进程等待和进程树终止能力 - 增强服务生命周期管理,支持等待状态、重启、幂等创建和配置更新 - 新增 NTFS 卷索引、文件 ID 解析、文件遍历、USN 变更监听和 bookmark 持久化 - 修复 NTFS boot sector、fragment、MFT、USN 解析边界和路径重建问题 - 补充权限、进程、服务、NTFS 解析和工作流回归测试 - 增加 Windows 测试脚本和管理员 NTFS smoke 验证脚本 - 升级 Go 兼容版本到 1.18,并更新 stario、win32api 及相关间接依赖
143 lines
3.4 KiB
Go
143 lines
3.4 KiB
Go
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)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|