summaryrefslogtreecommitdiff
path: root/cmd/btrfs-dump-tree/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/btrfs-dump-tree/main.go')
-rw-r--r--cmd/btrfs-dump-tree/main.go215
1 files changed, 110 insertions, 105 deletions
diff --git a/cmd/btrfs-dump-tree/main.go b/cmd/btrfs-dump-tree/main.go
index ca9d527..d5aa94e 100644
--- a/cmd/btrfs-dump-tree/main.go
+++ b/cmd/btrfs-dump-tree/main.go
@@ -7,6 +7,8 @@ import (
"lukeshu.com/btrfs-tools/pkg/binstruct"
"lukeshu.com/btrfs-tools/pkg/btrfs"
+ "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem"
+ "lukeshu.com/btrfs-tools/pkg/util"
)
func main() {
@@ -72,64 +74,68 @@ func Main(imgfilename string) (err error) {
// printTree mimics btrfs-progs kernel-shared/print-tree.c:btrfs_print_tree() and kernel-shared/print-tree.c:btrfs_print_leaf()
func printTree(fs *btrfs.FS, root btrfs.LogicalAddr) {
- node, err := fs.ReadNode(root)
+ nodeRef, err := fs.ReadNode(root)
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
+ node := nodeRef.Data
printHeaderInfo(node)
- switch node := node.(type) {
- case *btrfs.InternalNode:
- for _, item := range node.Body {
+ if node.Head.Level > 0 { // internal
+ for _, item := range node.BodyInternal {
fmt.Printf("\t%s block %d gen %d\n",
- fmtKey(item.Data.Key),
- item.Data.BlockPtr,
- item.Data.Generation)
+ fmtKey(item.Key),
+ item.BlockPtr,
+ item.Generation)
}
- for _, item := range node.Body {
- printTree(fs, item.Data.BlockPtr)
+ for _, item := range node.BodyInternal {
+ printTree(fs, item.BlockPtr)
}
- case *btrfs.LeafNode:
- for i, item := range node.Body {
+ } else { // leaf
+ for i, item := range node.BodyLeaf {
fmt.Printf("\titem %d %s itemoff %d itemsize %d\n",
i,
- fmtKey(item.Data.Key),
- item.Data.DataOffset,
- item.Data.DataSize)
- switch item.Data.Key.ItemType {
- case btrfs.BTRFS_UNTYPED_KEY:
- // TODO
- case btrfs.BTRFS_INODE_ITEM_KEY:
- // TODO(!)
- case btrfs.BTRFS_INODE_REF_KEY:
- dat := item.Data.Data.Data
+ fmtKey(item.Head.Key),
+ item.Head.DataOffset,
+ item.Head.DataSize)
+ switch item.Head.Key.ItemType {
+ //case btrfsitem.UNTYPED_KEY:
+ // // TODO
+ //case btrfsitem.INODE_ITEM_KEY:
+ // // TODO(!)
+ case btrfsitem.INODE_REF_KEY:
+ dat := item.Body
for len(dat) > 0 {
- var ref btrfs.InodeRefItem
- if err := binstruct.Unmarshal(dat, &ref); err != nil {
+ var ref btrfsitem.InodeRef
+ n, err := binstruct.Unmarshal(dat, &ref)
+ if err != nil {
fmt.Printf("error: %v\n", err)
return
}
- dat = dat[0xA:]
- ref.Name = dat[:ref.NameLen]
- dat = dat[ref.NameLen:]
-
fmt.Printf("\t\tindex %d namelen %d name: %s\n",
ref.Index, ref.NameLen, ref.Name)
+ dat = dat[n:]
}
- case btrfs.BTRFS_INODE_EXTREF_KEY:
- // TODO
- case btrfs.BTRFS_DIR_ITEM_KEY, btrfs.BTRFS_DIR_INDEX_KEY, btrfs.BTRFS_XATTR_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_DIR_LOG_INDEX_KEY, btrfs.BTRFS_DIR_LOG_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_ORPHAN_ITEM_KEY:
+ //case btrfsitem.INODE_EXTREF_KEY:
+ // // TODO
+ //case btrfsitem.DIR_ITEM_KEY, btrfsitem.DIR_INDEX_KEY, btrfsitem.XATTR_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.DIR_LOG_INDEX_KEY, btrfsitem.DIR_LOG_ITEM_KEY:
+ // // TODO
+ case btrfsitem.ORPHAN_ITEM_KEY:
fmt.Printf("\t\torphan item\n")
- case btrfs.BTRFS_ROOT_ITEM_KEY:
- var obj btrfs.RootItem
- if err := binstruct.Unmarshal(item.Data.Data.Data, &obj); err != nil {
+ case btrfsitem.ROOT_ITEM_KEY:
+ var obj btrfsitem.Root
+ n, err := binstruct.Unmarshal(item.Body, &obj)
+ if err != nil {
fmt.Printf("error: %v\n", err)
return
}
+ if n != len(item.Body) {
+ fmt.Printf("error: left over data: got %d bytes but only consumed %d\n", len(item.Body), n)
+ return
+ }
+
fmt.Printf("\t\tgeneration %d root_dirid %d bytenr %d byte_limit %d bytes_used %d\n",
obj.Generation, obj.RootDirID, obj.ByteNr, obj.ByteLimit, obj.BytesUsed)
fmt.Printf("\t\tlast_snapshot %d flags %s refs %d\n",
@@ -149,58 +155,58 @@ func printTree(fs *btrfs.FS, root btrfs.LogicalAddr) {
fmt.Printf("\t\tstime %s\n", fmtTime(obj.STime))
fmt.Printf("\t\trtime %s\n", fmtTime(obj.RTime))
}
- case btrfs.BTRFS_ROOT_REF_KEY:
- // TODO
- case btrfs.BTRFS_ROOT_BACKREF_KEY:
- // TODO
- case btrfs.BTRFS_EXTENT_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_METADATA_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_TREE_BLOCK_REF_KEY:
+ //case btrfsitem.ROOT_REF_KEY:
+ // // TODO
+ //case btrfsitem.ROOT_BACKREF_KEY:
+ // // TODO
+ //case btrfsitem.EXTENT_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.METADATA_ITEM_KEY:
+ // // TODO
+ case btrfsitem.TREE_BLOCK_REF_KEY:
fmt.Printf("\t\ttree block backref\n")
- case btrfs.BTRFS_SHARED_BLOCK_REF_KEY:
+ case btrfsitem.SHARED_BLOCK_REF_KEY:
fmt.Printf("\t\tshared block backref\n")
- case btrfs.BTRFS_EXTENT_DATA_REF_KEY:
- // TODO
- case btrfs.BTRFS_SHARED_DATA_REF_KEY:
- // TODO
- case btrfs.BTRFS_EXTENT_REF_V0_KEY:
+ //case btrfsitem.EXTENT_DATA_REF_KEY:
+ // // TODO
+ //case btrfsitem.SHARED_DATA_REF_KEY:
+ // // TODO
+ case btrfsitem.EXTENT_REF_V0_KEY:
fmt.Printf("\t\textent ref v0 (deprecated)\n")
- case btrfs.BTRFS_CSUM_ITEM_KEY:
+ case btrfsitem.CSUM_ITEM_KEY:
fmt.Printf("\t\tcsum item\n")
- case btrfs.BTRFS_EXTENT_CSUM_KEY:
- // TODO
- case btrfs.BTRFS_EXTENT_DATA_KEY:
- // TODO
- case btrfs.BTRFS_BLOCK_GROUP_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_FREE_SPACE_INFO_KEY:
- // TODO
- case btrfs.BTRFS_FREE_SPACE_EXTENT_KEY:
+ //case btrfsitem.EXTENT_CSUM_KEY:
+ // // TODO
+ //case btrfsitem.EXTENT_DATA_KEY:
+ // // TODO
+ //case btrfsitem.BLOCK_GROUP_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.FREE_SPACE_INFO_KEY:
+ // // TODO
+ case btrfsitem.FREE_SPACE_EXTENT_KEY:
fmt.Printf("\t\tfree space extent\n")
- case btrfs.BTRFS_FREE_SPACE_BITMAP_KEY:
+ case btrfsitem.FREE_SPACE_BITMAP_KEY:
fmt.Printf("\t\tfree space bitmap\n")
- case btrfs.BTRFS_CHUNK_ITEM_KEY:
- // TODO(!)
- case btrfs.BTRFS_DEV_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_DEV_EXTENT_KEY:
- // TODO
- case btrfs.BTRFS_QGROUP_STATUS_KEY:
- // TODO
- case btrfs.BTRFS_QGROUP_RELATION_KEY, btrfs.BTRFS_QGROUP_INFO_KEY:
- // TODO
- case btrfs.BTRFS_QGROUP_LIMIT_KEY:
- // TODO
- case btrfs.BTRFS_UUID_KEY_SUBVOL, btrfs.BTRFS_UUID_KEY_RECEIVED_SUBVOL:
- // TODO
- case btrfs.BTRFS_STRING_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_PERSISTENT_ITEM_KEY:
- // TODO
- case btrfs.BTRFS_TEMPORARY_ITEM_KEY:
- // TODO
+ //case btrfsitem.CHUNK_ITEM_KEY:
+ // // TODO(!)
+ //case btrfsitem.DEV_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.DEV_EXTENT_KEY:
+ // // TODO
+ //case btrfsitem.QGROUP_STATUS_KEY:
+ // // TODO
+ //case btrfsitem.QGROUP_RELATION_KEY, btrfsitem.QGROUP_INFO_KEY:
+ // // TODO
+ //case btrfsitem.QGROUP_LIMIT_KEY:
+ // // TODO
+ //case btrfsitem.UUID_KEY_SUBVOL, btrfsitem.UUID_KEY_RECEIVED_SUBVOL:
+ // // TODO
+ //case btrfsitem.STRING_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.PERSISTENT_ITEM_KEY:
+ // // TODO
+ //case btrfsitem.TEMPORARY_ITEM_KEY:
+ // // TODO
}
}
}
@@ -209,36 +215,35 @@ func printTree(fs *btrfs.FS, root btrfs.LogicalAddr) {
// printHeaderInfo mimics btrfs-progs kernel-shared/print-tree.c:print_header_info()
func printHeaderInfo(node btrfs.Node) {
var typename string
- switch node := node.(type) {
- case *btrfs.InternalNode:
+ if node.Head.Level > 0 { // internal node
typename = "node"
fmt.Printf("node %d level %d items %d free space %d",
- node.Header.Addr,
- node.Header.Data.Level,
- node.Header.Data.NumItems,
- node.Header.Data.MaxItems-node.Header.Data.NumItems)
- case *btrfs.LeafNode:
+ node.Head.Addr,
+ node.Head.Level,
+ node.Head.NumItems,
+ node.MaxItems()-node.Head.NumItems)
+ } else { // leaf node
typename = "leaf"
fmt.Printf("leaf %d items %d free space %d",
- node.Header.Addr,
- node.Header.Data.NumItems,
- node.FreeSpace())
+ node.Head.Addr,
+ node.Head.NumItems,
+ node.LeafFreeSpace())
}
fmt.Printf(" generation %d owner %v\n",
- node.GetNodeHeader().Data.Generation,
- node.GetNodeHeader().Data.Owner)
+ node.Head.Generation,
+ node.Head.Owner)
fmt.Printf("%s %d flags %s backref revision %d\n",
typename,
- node.GetNodeHeader().Addr,
- node.GetNodeHeader().Data.Flags,
- node.GetNodeHeader().Data.BackrefRev)
+ node.Head.Addr,
+ node.Head.Flags,
+ node.Head.BackrefRev)
- fmt.Printf("checksum stored %x\n", node.GetNodeHeader().Data.Checksum)
+ fmt.Printf("checksum stored %x\n", node.Head.Checksum)
fmt.Printf("checksum calced %v\n", "TODO")
- fmt.Printf("fs uuid %s\n", node.GetNodeHeader().Data.MetadataUUID)
- fmt.Printf("chunk uuid %s\n", node.GetNodeHeader().Data.ChunkTreeUUID)
+ fmt.Printf("fs uuid %s\n", node.Head.MetadataUUID)
+ fmt.Printf("chunk uuid %s\n", node.Head.ChunkTreeUUID)
}
// mimics print-tree.c:btrfs_print_key()
@@ -246,14 +251,14 @@ func fmtKey(key btrfs.Key) string {
var out strings.Builder
fmt.Fprintf(&out, "key (%s %v", key.ObjectID.Format(key.ItemType), key.ItemType)
switch key.ItemType {
- case btrfs.BTRFS_QGROUP_RELATION_KEY, btrfs.BTRFS_QGROUP_INFO_KEY, btrfs.BTRFS_QGROUP_LIMIT_KEY:
+ case btrfsitem.QGROUP_RELATION_KEY, btrfsitem.QGROUP_INFO_KEY, btrfsitem.QGROUP_LIMIT_KEY:
panic("not implemented")
- case btrfs.BTRFS_UUID_KEY_SUBVOL, btrfs.BTRFS_UUID_KEY_RECEIVED_SUBVOL:
+ case btrfsitem.UUID_KEY_SUBVOL, btrfsitem.UUID_KEY_RECEIVED_SUBVOL:
fmt.Fprintf(&out, " 0x%016x)", key.Offset)
- case btrfs.BTRFS_ROOT_ITEM_KEY:
+ case btrfsitem.ROOT_ITEM_KEY:
fmt.Fprintf(&out, " %v)", btrfs.ObjID(key.Offset))
default:
- if key.Offset == btrfs.MaxUint64pp-1 {
+ if key.Offset == util.MaxUint64pp-1 {
fmt.Fprintf(&out, " -1)")
} else {
fmt.Fprintf(&out, " %d)", key.Offset)