summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/btrfs-dump-tree/main.go4
-rw-r--r--pkg/btrfs/crc32c.go28
-rw-r--r--pkg/btrfs/csum.go78
-rw-r--r--pkg/btrfs/csum_test.go (renamed from pkg/btrfs/crc32c_test.go)0
-rw-r--r--pkg/btrfs/types_btree.go17
-rw-r--r--pkg/btrfs/types_superblock.go4
-rw-r--r--pkg/btrfsmisc/print_tree.go4
7 files changed, 97 insertions, 38 deletions
diff --git a/cmd/btrfs-dump-tree/main.go b/cmd/btrfs-dump-tree/main.go
index e32d677..3c7bcda 100644
--- a/cmd/btrfs-dump-tree/main.go
+++ b/cmd/btrfs-dump-tree/main.go
@@ -16,7 +16,7 @@ func main() {
}
}
-const version = "5.17"
+const version = "5.18.1"
func Main(imgfilename string) (err error) {
maybeSetErr := func(_err error) {
@@ -49,7 +49,7 @@ func Main(imgfilename string) (err error) {
return err
}
- fmt.Printf("btrfs-progs v%v \n", version)
+ fmt.Printf("btrfs-progs v%v\n", version)
if superblock.Data.RootTree != 0 {
fmt.Printf("root tree\n")
if err := btrfsmisc.PrintTree(fs, superblock.Data.RootTree); err != nil {
diff --git a/pkg/btrfs/crc32c.go b/pkg/btrfs/crc32c.go
deleted file mode 100644
index 52058e8..0000000
--- a/pkg/btrfs/crc32c.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package btrfs
-
-import (
- "encoding/binary"
- "encoding/hex"
- "fmt"
- "hash/crc32"
-
- "lukeshu.com/btrfs-tools/pkg/util"
-)
-
-type CSum [0x20]byte
-
-func (csum CSum) String() string {
- return hex.EncodeToString(csum[:])
-}
-
-func (csum CSum) Format(f fmt.State, verb rune) {
- util.FormatByteArrayStringer(csum, csum[:], f, verb)
-}
-
-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/csum.go b/pkg/btrfs/csum.go
new file mode 100644
index 0000000..6245fa4
--- /dev/null
+++ b/pkg/btrfs/csum.go
@@ -0,0 +1,78 @@
+package btrfs
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "hash/crc32"
+
+ "lukeshu.com/btrfs-tools/pkg/util"
+)
+
+type CSum [0x20]byte
+
+func (csum CSum) String() string {
+ return hex.EncodeToString(csum[:])
+}
+
+func (csum CSum) Fmt(typ CSumType) string {
+ return hex.EncodeToString(csum[:typ.Size()])
+}
+
+func (csum CSum) Format(f fmt.State, verb rune) {
+ util.FormatByteArrayStringer(csum, csum[:], f, verb)
+}
+
+type CSumType uint16
+
+const (
+ CSUM_TYPE_CRC32 = CSumType(iota)
+ CSUM_TYPE_XXHASH
+ CSUM_TYPE_SHA256
+ CSUM_TYPE_BLAKE2
+)
+
+func (typ CSumType) String() string {
+ names := map[CSumType]string{
+ CSUM_TYPE_CRC32: "crc32c",
+ CSUM_TYPE_XXHASH: "xxhash64",
+ CSUM_TYPE_SHA256: "sha256",
+ CSUM_TYPE_BLAKE2: "blake2",
+ }
+ if name, ok := names[typ]; ok {
+ return name
+ }
+ return fmt.Sprintf("%d", typ)
+}
+
+func (typ CSumType) Size() int {
+ sizes := map[CSumType]int{
+ CSUM_TYPE_CRC32: 4,
+ CSUM_TYPE_XXHASH: 8,
+ CSUM_TYPE_SHA256: 32,
+ CSUM_TYPE_BLAKE2: 32,
+ }
+ if size, ok := sizes[typ]; ok {
+ return size
+ }
+ return len(CSum{})
+}
+
+func (typ CSumType) Sum(data []byte) (CSum, error) {
+ switch typ {
+ case CSUM_TYPE_CRC32:
+ crc := crc32.Update(0, crc32.MakeTable(crc32.Castagnoli), data)
+
+ var ret CSum
+ binary.LittleEndian.PutUint32(ret[:], crc)
+ return ret, nil
+ case CSUM_TYPE_XXHASH:
+ panic("not implemented")
+ case CSUM_TYPE_SHA256:
+ panic("not implemented")
+ case CSUM_TYPE_BLAKE2:
+ panic("not implemented")
+ default:
+ return CSum{}, fmt.Errorf("unknown checksum type: %v", typ)
+ }
+}
diff --git a/pkg/btrfs/crc32c_test.go b/pkg/btrfs/csum_test.go
index 335b3cc..335b3cc 100644
--- a/pkg/btrfs/crc32c_test.go
+++ b/pkg/btrfs/csum_test.go
diff --git a/pkg/btrfs/types_btree.go b/pkg/btrfs/types_btree.go
index 99371d2..32c063e 100644
--- a/pkg/btrfs/types_btree.go
+++ b/pkg/btrfs/types_btree.go
@@ -54,7 +54,8 @@ func (f NodeFlags) String() string { return util.BitfieldString(f, nodeF
type Node struct {
// Some context from the parent filesystem
- Size uint32 // superblock.NodeSize
+ Size uint32 // superblock.NodeSize
+ ChecksumType CSumType // superblock.ChecksumType
// The node's header (always present)
Head NodeHeader
@@ -97,7 +98,7 @@ func (node Node) CalculateChecksum() (CSum, error) {
if err != nil {
return CSum{}, err
}
- return CRC32c(data[binstruct.StaticSize(CSum{}):]), nil
+ return node.ChecksumType.Sum(data[binstruct.StaticSize(CSum{}):])
}
func (node Node) ValidateChecksum() error {
@@ -115,7 +116,8 @@ func (node Node) ValidateChecksum() error {
func (node *Node) UnmarshalBinary(nodeBuf []byte) (int, error) {
*node = Node{
- Size: uint32(len(nodeBuf)),
+ Size: uint32(len(nodeBuf)),
+ ChecksumType: node.ChecksumType,
}
n, err := binstruct.Unmarshal(nodeBuf, &node.Head)
if err != nil {
@@ -334,6 +336,10 @@ func ReadNode[Addr ~int64](fs util.File[Addr], sb Superblock, addr Addr, laddrCB
nodeRef := &util.Ref[Addr, Node]{
File: fs,
Addr: addr,
+ Data: Node{
+ Size: sb.NodeSize,
+ ChecksumType: sb.ChecksumType,
+ },
}
if _, err := binstruct.Unmarshal(nodeBuf, &nodeRef.Data.Head); err != nil {
return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, err)
@@ -346,7 +352,10 @@ func ReadNode[Addr ~int64](fs util.File[Addr], sb Superblock, addr Addr, laddrCB
}
stored := nodeRef.Data.Head.Checksum
- calced := CRC32c(nodeBuf[binstruct.StaticSize(CSum{}):])
+ calced, err := nodeRef.Data.ChecksumType.Sum(nodeBuf[binstruct.StaticSize(CSum{}):])
+ if err != nil {
+ return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: %w", addr, err)
+ }
if stored != calced {
return nodeRef, fmt.Errorf("btrfs.ReadNode: node@%v: looks like a node but is corrupt: checksum mismatch: stored=%v calculated=%v",
addr, stored, calced)
diff --git a/pkg/btrfs/types_superblock.go b/pkg/btrfs/types_superblock.go
index 0f63389..3ed1055 100644
--- a/pkg/btrfs/types_superblock.go
+++ b/pkg/btrfs/types_superblock.go
@@ -37,7 +37,7 @@ type Superblock struct {
CompatFlags uint64 `bin:"off=0xac, siz=0x8"` // compat_flags
CompatROFlags uint64 `bin:"off=0xb4, siz=0x8"` // compat_ro_flags - only implementations that support the flags can write to the filesystem
IncompatFlags IncompatFlags `bin:"off=0xbc, siz=0x8"` // incompat_flags - only implementations that support the flags can use the filesystem
- ChecksumType uint16 `bin:"off=0xc4, siz=0x2"` // csum_type - Btrfs currently uses the CRC32c little-endian hash function with seed -1.
+ ChecksumType CSumType `bin:"off=0xc4, siz=0x2"`
RootLevel uint8 `bin:"off=0xc6, siz=0x1"` // root_level
ChunkLevel uint8 `bin:"off=0xc7, siz=0x1"` // chunk_root_level
@@ -74,7 +74,7 @@ func (sb Superblock) CalculateChecksum() (CSum, error) {
if err != nil {
return CSum{}, err
}
- return CRC32c(data[binstruct.StaticSize(CSum{}):]), nil
+ return sb.ChecksumType.Sum(data[binstruct.StaticSize(CSum{}):])
}
func (sb Superblock) ValidateChecksum() error {
diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go
index fa864a5..580a0ca 100644
--- a/pkg/btrfsmisc/print_tree.go
+++ b/pkg/btrfsmisc/print_tree.go
@@ -273,11 +273,11 @@ func printHeaderInfo(node btrfs.Node) {
node.Head.Flags,
node.Head.BackrefRev)
- fmt.Printf("checksum stored %v\n", node.Head.Checksum)
+ fmt.Printf("checksum stored %v\n", node.Head.Checksum.Fmt(node.ChecksumType))
if calcSum, err := node.CalculateChecksum(); err != nil {
fmt.Printf("checksum calced %v\n", err)
} else {
- fmt.Printf("checksum calced %v\n", calcSum)
+ fmt.Printf("checksum calced %v\n", calcSum.Fmt(node.ChecksumType))
}
fmt.Printf("fs uuid %v\n", node.Head.MetadataUUID)