diff options
Diffstat (limited to 'pkg/btrfs')
-rw-r--r-- | pkg/btrfs/Makefile | 17 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/item_empty.go | 2 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/item_untyped.go | 14 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/items.go | 32 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/items.txt | 2 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/items_gen.go | 5 | ||||
-rw-r--r-- | pkg/btrfs/types_btree.go | 2 |
7 files changed, 57 insertions, 17 deletions
diff --git a/pkg/btrfs/Makefile b/pkg/btrfs/Makefile index 9e1c29e..4bc4219 100644 --- a/pkg/btrfs/Makefile +++ b/pkg/btrfs/Makefile @@ -3,7 +3,13 @@ .DELETE_ON_ERROR: btrfsitem/items.txt: btrfsitem $(wildcard btrfsitem/item_*.go) $(MAKEFILE_LIST) - sed -En 's,^type (\S+) .* // (.*=.*),\1 \2,p' $(filter btrfsitem/item_%.go,$^) | while read -r typ keys; do for key in $$keys; do echo "$$key" "$$typ"; done; done | LC_COLLATE=C sort >$@ + { \ + sed -En 's,^type (\S+) .* // (.*=.*),\1 \2,p' $(filter btrfsitem/item_%.go,$^) | while read -r typ keys; do \ + for key in $$keys; do \ + echo "$$key" "$$typ"; \ + done; \ + done; \ + } | LC_COLLATE=C sort >$@ files += btrfsitem/items.txt btrfsitem/items_gen.go: btrfsitem/items.txt $(MAKEFILE_LIST) @@ -20,9 +26,12 @@ btrfsitem/items_gen.go: btrfsitem/items.txt $(MAKEFILE_LIST) sed -E 's,(.*)=(.*) (.*),\1_KEY=internal.\1_KEY,' $<; \ echo ')'; \ echo 'var keytype2gotype = map[Type]reflect.Type{'; \ - sed -E 's|(.*)=(.*) (.*)|\1_KEY: reflect.TypeOf(\3{}),|' $<; \ + sed -En 's|(.*)=([^:]*) (.*)|\1_KEY: reflect.TypeOf(\3{}),|p' $<; \ + echo '}'; \ + echo 'var untypedObjID2gotype = map[internal.ObjID]reflect.Type{'; \ + sed -En 's|UNTYPED=0:(.*) (.*)|internal.\1: reflect.TypeOf(\2{}),|p' $<; \ echo '}'; \ - sed -E 's,(.*)=(.*) (.*),\3,' $< | LC_COLLATE=C sort -u | sed 's,.*,func (&) isItem() {},'; \ + sed -En 's,(.*)=(.*) (.+),\3,p' $< | LC_COLLATE=C sort -u | sed 's,.*,func (&) isItem() {},'; \ } | gofmt >$@ files += btrfsitem/items_gen.go @@ -34,7 +43,7 @@ internal/itemtype.go: btrfsitem/items.txt $(MAKEFILE_LIST) echo 'import "fmt"'; \ echo 'type ItemType uint8'; \ echo 'const ('; \ - sed -E 's,(.*)=(.*) (.*),\1_KEY=ItemType(\2),' $<; \ + sed -E 's,(.*)=([^:]*)(:.*)? (.*),\1_KEY=ItemType(\2),' $< | uniq; \ echo ')'; \ echo 'func (t ItemType) String() string {'; \ echo ' names := map[ItemType]string{'; \ diff --git a/pkg/btrfs/btrfsitem/item_empty.go b/pkg/btrfs/btrfsitem/item_empty.go index 74645cc..93e2f9e 100644 --- a/pkg/btrfs/btrfsitem/item_empty.go +++ b/pkg/btrfs/btrfsitem/item_empty.go @@ -4,6 +4,6 @@ import ( "lukeshu.com/btrfs-tools/pkg/binstruct" ) -type Empty struct { // UNTYPED=0 ORPHAN_ITEM=48 TREE_BLOCK_REF=176 SHARED_BLOCK_REF=182 FREE_SPACE_EXTENT=199 QGROUP_RELATION=246 +type Empty struct { // ORPHAN_ITEM=48 TREE_BLOCK_REF=176 SHARED_BLOCK_REF=182 FREE_SPACE_EXTENT=199 QGROUP_RELATION=246 binstruct.End `bin:"off=0"` } diff --git a/pkg/btrfs/btrfsitem/item_untyped.go b/pkg/btrfs/btrfsitem/item_untyped.go new file mode 100644 index 0000000..51d0676 --- /dev/null +++ b/pkg/btrfs/btrfsitem/item_untyped.go @@ -0,0 +1,14 @@ +package btrfsitem + +import ( + "lukeshu.com/btrfs-tools/pkg/binstruct" + "lukeshu.com/btrfs-tools/pkg/btrfs/internal" +) + +type FreeSpaceHeader struct { // UNTYPED=0:FREE_SPACE_OBJECTID + Location internal.Key `bin:"off=0x00, siz=0x11"` + Generation int64 `bin:"off=0x11, siz=0x8"` + NumEntries int64 `bin:"off=0x19, siz=0x8"` + NumBitmaps int64 `bin:"off=0x21, siz=0x8"` + binstruct.End `bin:"off=0x29"` +} diff --git a/pkg/btrfs/btrfsitem/items.go b/pkg/btrfs/btrfsitem/items.go index 3c4392e..c4ad7e9 100644 --- a/pkg/btrfs/btrfsitem/items.go +++ b/pkg/btrfs/btrfsitem/items.go @@ -31,12 +31,26 @@ func (o *Error) UnmarshalBinary(dat []byte) (int, error) { } // Rather than returning a separate error value, return an Error item. -func UnmarshalItem(keytyp Type, dat []byte) Item { - gotyp, ok := keytype2gotype[keytyp] - if !ok { - return Error{ - Dat: dat, - Err: fmt.Errorf("btrfsitem.UnmarshalItem(typ=%v, dat): unknown item type", keytyp), +func UnmarshalItem(key internal.Key, dat []byte) Item { + var gotyp reflect.Type + if key.ItemType == UNTYPED_KEY { + var ok bool + gotyp, ok = untypedObjID2gotype[key.ObjectID] + if !ok { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v, ObjectID:%v}, dat): unknown object ID for untyped item", + key.ItemType, key.ObjectID), + } + } + } else { + var ok bool + gotyp, ok = keytype2gotype[key.ItemType] + if !ok { + return Error{ + Dat: dat, + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): unknown item type", key.ItemType), + } } } retPtr := reflect.New(gotyp) @@ -44,15 +58,15 @@ func UnmarshalItem(keytyp Type, dat []byte) Item { if err != nil { return Error{ Dat: dat, - Err: fmt.Errorf("btrfsitem.UnmarshalItem(typ=%v, dat): %w", keytyp, err), + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): %w", key.ItemType, err), } } if n < len(dat) { return Error{ Dat: dat, - Err: fmt.Errorf("btrfsitem.UnmarshalItem(typ=%v, dat): left over data: got %d bytes but only consumed %d", - keytyp, len(dat), n), + Err: fmt.Errorf("btrfsitem.UnmarshalItem({ItemType:%v}, dat): left over data: got %d bytes but only consumed %d", + key.ItemType, len(dat), n), } } return retPtr.Elem().Interface().(Item) diff --git a/pkg/btrfs/btrfsitem/items.txt b/pkg/btrfs/btrfsitem/items.txt index 8320650..59e3e76 100644 --- a/pkg/btrfs/btrfsitem/items.txt +++ b/pkg/btrfs/btrfsitem/items.txt @@ -20,7 +20,7 @@ ROOT_ITEM=132 Root SHARED_BLOCK_REF=182 Empty SHARED_DATA_REF=184 SharedDataRef TREE_BLOCK_REF=176 Empty -UNTYPED=0 Empty +UNTYPED=0:FREE_SPACE_OBJECTID FreeSpaceHeader UUID_RECEIVED_SUBVOL=252 UUIDMap UUID_SUBVOL=251 UUIDMap XATTR_ITEM=24 DirList diff --git a/pkg/btrfs/btrfsitem/items_gen.go b/pkg/btrfs/btrfsitem/items_gen.go index 02e2915..e60c50e 100644 --- a/pkg/btrfs/btrfsitem/items_gen.go +++ b/pkg/btrfs/btrfsitem/items_gen.go @@ -60,11 +60,13 @@ var keytype2gotype = map[Type]reflect.Type{ SHARED_BLOCK_REF_KEY: reflect.TypeOf(Empty{}), SHARED_DATA_REF_KEY: reflect.TypeOf(SharedDataRef{}), TREE_BLOCK_REF_KEY: reflect.TypeOf(Empty{}), - UNTYPED_KEY: reflect.TypeOf(Empty{}), UUID_RECEIVED_SUBVOL_KEY: reflect.TypeOf(UUIDMap{}), UUID_SUBVOL_KEY: reflect.TypeOf(UUIDMap{}), XATTR_ITEM_KEY: reflect.TypeOf(DirList{}), } +var untypedObjID2gotype = map[internal.ObjID]reflect.Type{ + internal.FREE_SPACE_OBJECTID: reflect.TypeOf(FreeSpaceHeader{}), +} func (BlockGroup) isItem() {} func (Chunk) isItem() {} @@ -77,6 +79,7 @@ func (Extent) isItem() {} func (ExtentDataRef) isItem() {} func (FileExtent) isItem() {} func (FreeSpaceBitmap) isItem() {} +func (FreeSpaceHeader) isItem() {} func (FreeSpaceInfo) isItem() {} func (Inode) isItem() {} func (InodeRefList) isItem() {} diff --git a/pkg/btrfs/types_btree.go b/pkg/btrfs/types_btree.go index 8ec1c9f..d65e599 100644 --- a/pkg/btrfs/types_btree.go +++ b/pkg/btrfs/types_btree.go @@ -143,7 +143,7 @@ func (node *Node) UnmarshalBinary(nodeBuf []byte) (int, error) { dataBuf := nodeBuf[dataOff : dataOff+dataSize] firstRead = min(firstRead, dataOff) lastRead = max(lastRead, dataOff+dataSize) - item.Body = btrfsitem.UnmarshalItem(item.Head.Key.ItemType, dataBuf) + item.Body = btrfsitem.UnmarshalItem(item.Head.Key, dataBuf) node.BodyLeaf = append(node.BodyLeaf, item) } |