diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/btrfs-fsck.go | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/cmd/btrfs-fsck.go b/cmd/btrfs-fsck.go new file mode 100644 index 0000000..8f48430 --- /dev/null +++ b/cmd/btrfs-fsck.go @@ -0,0 +1,79 @@ +package main + +import ( + "fmt" + "os" + + "lukeshu.com/btrfs-tools/pkg/btrfs" + "lukeshu.com/btrfs-tools/pkg/btrfsmisc" + "lukeshu.com/btrfs-tools/pkg/util" +) + +func main() { + if err := Main(os.Args[1]); err != nil { + fmt.Fprintf(os.Stderr, "%s: error: %v\n", os.Args[0], err) + os.Exit(1) + } +} + +func Main(imgfilename string) (err error) { + maybeSetErr := func(_err error) { + if _err != nil && err == nil { + err = _err + } + } + + fh, err := os.Open(imgfilename) + if err != nil { + return err + } + defer func() { + maybeSetErr(fh.Close()) + }() + fs := &btrfs.FS{ + Devices: []*btrfs.Device{ + { + File: fh, + }, + }, + } + + superblock, err := fs.Superblock() + if err != nil { + return fmt.Errorf("superblock: %w", err) + } + + if err := fs.Init(); err != nil { + fmt.Printf("init chunk tree: error: %v\n", err) + } + + foundNodes := make(map[btrfs.LogicalAddr]struct{}) + + if err := btrfsmisc.ScanForNodes(fs.Devices[0], superblock.Data, func(nodeRef *util.Ref[btrfs.PhysicalAddr, btrfs.Node], err error) { + if err != nil { + fmt.Println(err) + return + } + foundNodes[nodeRef.Data.Head.Addr] = struct{}{} + fmt.Printf("node@%d: physical_addr=0x%0X logical_addr=0x%0X generation=%d owner=%v level=%d\n", + nodeRef.Addr, + nodeRef.Addr, nodeRef.Data.Head.Addr, + nodeRef.Data.Head.Generation, nodeRef.Data.Head.Owner, nodeRef.Data.Head.Level) + srcPaddr := btrfs.QualifiedPhysicalAddr{ + Dev: superblock.Data.DevItem.DevUUID, + Addr: nodeRef.Addr, + } + resPaddrs, _ := fs.Resolve(nodeRef.Data.Head.Addr) + if len(resPaddrs) == 0 { + fmt.Printf("node@%d: logical_addr=0x%0X is not mapped\n", + nodeRef.Addr, nodeRef.Data.Head.Addr) + } else if _, ok := resPaddrs[srcPaddr]; !ok { + fmt.Printf("node@%d: logical_addr=0x%0X maps to %v, not %v\n", + nodeRef.Addr, nodeRef.Data.Head.Addr, resPaddrs, srcPaddr) + } + }); err != nil { + return err + } + + return nil +} |