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], +	}, "-") +} | 
