diff options
-rw-r--r-- | cmd/btrfs-dbg/main.go | 71 | ||||
-rw-r--r-- | pkg/btrfs/crc32c.go | 16 | ||||
-rw-r--r-- | pkg/btrfs/image.go | 71 | ||||
-rw-r--r-- | pkg/btrfs/types.go (renamed from cmd/btrfs-dbg/types.go) | 28 | ||||
-rw-r--r-- | pkg/btrfs/uuid.go | 19 |
5 files changed, 112 insertions, 93 deletions
diff --git a/cmd/btrfs-dbg/main.go b/cmd/btrfs-dbg/main.go index 0990378..3d2103a 100644 --- a/cmd/btrfs-dbg/main.go +++ b/cmd/btrfs-dbg/main.go @@ -6,7 +6,7 @@ import ( "github.com/davecgh/go-spew/spew" - "lukeshu.com/btrfs-tools/pkg/binstruct" + "lukeshu.com/btrfs-tools/pkg/btrfs" ) func main() { @@ -27,7 +27,7 @@ func Main(imgfilename string) (err error) { if err != nil { return err } - img := &Img{ + img := &btrfs.Img{ File: fh, } defer func() { @@ -42,8 +42,8 @@ func Main(imgfilename string) (err error) { spew := spew.NewDefaultConfig() spew.DisablePointerAddresses = true - spew.Dump(superblocks[0].data) - sum, err := superblocks[0].data.CalculateChecksum() + spew.Dump(superblocks[0].Data) + sum, err := superblocks[0].Data.CalculateChecksum() if err != nil { return err } @@ -51,66 +51,3 @@ func Main(imgfilename string) (err error) { return nil } - -type Img struct { - *os.File -} - -func (img *Img) Size() (int64, error) { - fi, err := img.Stat() - if err != nil { - return 0, err - } - return fi.Size(), nil -} - -type Ref[T any] struct { - img *Img - addr int64 - data T -} - -func (r *Ref[T]) Read() error { - size, err := binstruct.Size(r.data) - if err != nil { - return err - } - buf := make([]byte, size) - if _, err := r.img.ReadAt(buf, r.addr); err != nil { - return err - } - return binstruct.Unmarshal(buf, &r.data) -} - -func (img *Img) Superblocks() ([]Ref[Superblock], error) { - const superblockSize = 0x1000 - - var superblockAddrs = []int64{ - 0x00_0001_0000, // 64KiB - 0x00_0400_0000, // 64MiB - 0x40_0000_0000, // 256GiB - } - - sz, err := img.Size() - if err != nil { - return nil, err - } - - var ret []Ref[Superblock] - for i, addr := range superblockAddrs { - if addr+superblockSize <= sz { - superblock := Ref[Superblock]{ - img: img, - addr: addr, - } - if err := superblock.Read(); err != nil { - return nil, fmt.Errorf("superblock %d: %w", i, err) - } - ret = append(ret, superblock) - } - } - if len(ret) == 0 { - return nil, fmt.Errorf("no superblocks") - } - return ret, nil -} diff --git a/pkg/btrfs/crc32c.go b/pkg/btrfs/crc32c.go new file mode 100644 index 0000000..4ea4169 --- /dev/null +++ b/pkg/btrfs/crc32c.go @@ -0,0 +1,16 @@ +package btrfs + +import ( + "encoding/binary" + "hash/crc32" +) + +type CSum [0x20]byte + +func CRC32c(data []byte) CSum { + crc := crc32.Update(0, crc32.MakeTable(crc32.Castagnoli), data) + + var ret CSum + binary.LittleEndian.PutUint32(ret[:], crc) + return ret +} diff --git a/pkg/btrfs/image.go b/pkg/btrfs/image.go new file mode 100644 index 0000000..6037c4d --- /dev/null +++ b/pkg/btrfs/image.go @@ -0,0 +1,71 @@ +package btrfs + +import ( + "fmt" + "os" + + "lukeshu.com/btrfs-tools/pkg/binstruct" +) + +type Img struct { + *os.File +} + +func (img *Img) Size() (int64, error) { + fi, err := img.Stat() + if err != nil { + return 0, err + } + return fi.Size(), nil +} + +type Ref[T any] struct { + img *Img + addr int64 + Data T +} + +func (r *Ref[T]) Read() error { + size, err := binstruct.Size(r.Data) + if err != nil { + return err + } + buf := make([]byte, size) + if _, err := r.img.ReadAt(buf, r.addr); err != nil { + return err + } + return binstruct.Unmarshal(buf, &r.Data) +} + +func (img *Img) Superblocks() ([]Ref[Superblock], error) { + const superblockSize = 0x1000 + + var superblockAddrs = []int64{ + 0x00_0001_0000, // 64KiB + 0x00_0400_0000, // 64MiB + 0x40_0000_0000, // 256GiB + } + + sz, err := img.Size() + if err != nil { + return nil, err + } + + var ret []Ref[Superblock] + for i, addr := range superblockAddrs { + if addr+superblockSize <= sz { + superblock := Ref[Superblock]{ + img: img, + addr: addr, + } + if err := superblock.Read(); err != nil { + return nil, fmt.Errorf("superblock %d: %w", i, err) + } + ret = append(ret, superblock) + } + } + if len(ret) == 0 { + return nil, fmt.Errorf("no superblocks") + } + return ret, nil +} diff --git a/cmd/btrfs-dbg/types.go b/pkg/btrfs/types.go index 3cd348d..2949a8b 100644 --- a/cmd/btrfs-dbg/types.go +++ b/pkg/btrfs/types.go @@ -1,10 +1,6 @@ -package main +package btrfs import ( - "encoding/binary" - "encoding/hex" - "hash/crc32" - "strings" "time" "lukeshu.com/btrfs-tools/pkg/binstruct" @@ -14,28 +10,8 @@ type ( PhysicalAddr int64 LogicalAddr int64 ObjID int64 - CSum [0x20]byte - UUID [16]byte ) -func (uuid UUID) String() string { - str := hex.EncodeToString(uuid[:]) - return strings.Join([]string{ - str[:8], - str[8:12], - str[12:16], - str[16:20], - str[20:32], - }, "-") -} - -func crc32c(data []byte) CSum { - sum := crc32.Update(0xFFFFFFFF, crc32.MakeTable(0x1EDC6F41), data) - var buf CSum - binary.LittleEndian.PutUint32(buf[:], sum) - return buf -} - type Key struct { ObjectID ObjID `bin:"off=0, siz=8, desc=Object ID. Each tree has its own set of Object IDs."` ItemType uint8 `bin:"off=8, siz=1, desc=Item type."` @@ -107,7 +83,7 @@ func (sb Superblock) CalculateChecksum() (CSum, error) { if err != nil { return CSum{}, err } - return crc32c(data[0x20:]), nil + return CRC32c(data[0x20:]), nil } type DevItem struct { diff --git a/pkg/btrfs/uuid.go b/pkg/btrfs/uuid.go new file mode 100644 index 0000000..5218a3f --- /dev/null +++ b/pkg/btrfs/uuid.go @@ -0,0 +1,19 @@ +package btrfs + +import ( + "encoding/hex" + "strings" +) + +type UUID [16]byte + +func (uuid UUID) String() string { + str := hex.EncodeToString(uuid[:]) + return strings.Join([]string{ + str[:8], + str[8:12], + str[12:16], + str[16:20], + str[20:32], + }, "-") +} |