summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-07-02 22:10:55 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-07-02 22:10:55 -0600
commit6b3974fe1c4616d8b9872d88d737623cc48c4368 (patch)
treea4b795bfbef48aefca949c96b4bd9f14b4a79992
parente43749b899d09b57310240fe3abf0f964b9e0cd0 (diff)
subvolumes
-rw-r--r--cmd/btrfs-ls-files/main.go42
-rw-r--r--pkg/btrfs/btrfsitem/item_rootref.go34
-rw-r--r--pkg/btrfs/btrfsitem/item_uuid.go3
-rw-r--r--pkg/btrfs/btrfsitem/items.txt2
-rw-r--r--pkg/btrfs/btrfsitem/items_gen.go5
-rw-r--r--pkg/btrfs/internal/itemtype.go4
-rw-r--r--pkg/btrfsmisc/print_tree.go18
7 files changed, 90 insertions, 18 deletions
diff --git a/cmd/btrfs-ls-files/main.go b/cmd/btrfs-ls-files/main.go
index 375f427..9f5b85d 100644
--- a/cmd/btrfs-ls-files/main.go
+++ b/cmd/btrfs-ls-files/main.go
@@ -37,23 +37,12 @@ func Main(imgfilenames ...string) (err error) {
maybeSetErr(fs.Close())
}()
- sb, err := fs.Superblock()
- if err != nil {
- return err
- }
-
- fsTreeRoot, err := fs.TreeLookup(sb.Data.RootTree, btrfs.Key{
+ printSubvol(fs, "", "", "/", btrfs.Key{
ObjectID: btrfs.FS_TREE_OBJECTID,
ItemType: btrfsitem.ROOT_ITEM_KEY,
Offset: 0,
})
- if err != nil {
- return fmt.Errorf("look up FS_TREE: %w", err)
- }
- fsTreeRootBody := fsTreeRoot.Body.(btrfsitem.Root)
- fsTree := fsTreeRootBody.ByteNr
- printDir(fs, fsTree, "", "", "/", fsTreeRootBody.RootDirID)
return nil
}
@@ -64,6 +53,23 @@ const (
tL = "└── "
)
+func printSubvol(fs *btrfs.FS, prefix0, prefix1, name string, key btrfs.Key) {
+ sb, err := fs.Superblock()
+ if err != nil {
+ fmt.Printf("%s%q error: could not read superblock: %v\n", prefix0, name, err)
+ return
+ }
+
+ root, err := fs.TreeLookup(sb.Data.RootTree, key)
+ if err != nil {
+ fmt.Printf("%s%q error: could not look up root %v: %v\n", prefix0, name, key, err)
+ return
+ }
+ rootBody := root.Body.(btrfsitem.Root)
+
+ printDir(fs, rootBody.ByteNr, prefix0, prefix1, name, rootBody.RootDirID)
+}
+
func printDir(fs *btrfs.FS, fsTree btrfsvol.LogicalAddr, prefix0, prefix1, dirName string, dirInode btrfs.ObjID) {
var errs derror.MultiError
items, err := fs.TreeSearchAll(fsTree, func(key btrfs.Key) int {
@@ -176,7 +182,17 @@ func printDirEntry(fs *btrfs.FS, fsTree btrfsvol.LogicalAddr, prefix0, prefix1 s
}
switch entry.Type {
case btrfsitem.FT_DIR:
- printDir(fs, fsTree, prefix0, prefix1, string(entry.Name), entry.Location.ObjectID)
+ switch entry.Location.ItemType {
+ case btrfsitem.INODE_ITEM_KEY:
+ printDir(fs, fsTree, prefix0, prefix1, string(entry.Name), entry.Location.ObjectID)
+ case btrfsitem.ROOT_ITEM_KEY:
+ key := entry.Location
+ key.Offset = 0
+ printSubvol(fs, prefix0, prefix1, string(entry.Name), key)
+ default:
+ fmt.Printf("%s%q\t[location=%v type=%v] error: I'm not sure how to print a %v directory\n",
+ prefix0, entry.Name, entry.Location, entry.Type, entry.Location.ItemType)
+ }
default:
fmt.Printf("%s%q\t[location=%v type=%v]\n", prefix0, entry.Name, entry.Location, entry.Type)
}
diff --git a/pkg/btrfs/btrfsitem/item_rootref.go b/pkg/btrfs/btrfsitem/item_rootref.go
new file mode 100644
index 0000000..567e9c7
--- /dev/null
+++ b/pkg/btrfs/btrfsitem/item_rootref.go
@@ -0,0 +1,34 @@
+package btrfsitem
+
+import (
+ "lukeshu.com/btrfs-tools/pkg/binstruct"
+ "lukeshu.com/btrfs-tools/pkg/btrfs/internal"
+)
+
+type RootRef struct { // ROOT_REF=156 ROOT_BACKREF=144
+ DirID internal.ObjID `bin:"off=0x00, siz=0x8"`
+ Sequence int64 `bin:"off=0x08, siz=0x8"`
+ NameLen uint16 `bin:"off=0x10, siz=0x2"` // [ignored-when-writing]
+ binstruct.End `bin:"off=0x12"`
+ Name []byte `bin:"-"`
+}
+
+func (o *RootRef) UnmarshalBinary(dat []byte) (int, error) {
+ n, err := binstruct.UnmarshalWithoutInterface(dat, o)
+ if err != nil {
+ return n, err
+ }
+ o.Name = dat[n : n+int(o.NameLen)]
+ n += int(o.NameLen)
+ return n, nil
+}
+
+func (o RootRef) MarshalBinary() ([]byte, error) {
+ o.NameLen = uint16(len(o.Name))
+ dat, err := binstruct.MarshalWithoutInterface(o)
+ if err != nil {
+ return dat, err
+ }
+ dat = append(dat, o.Name...)
+ return dat, nil
+}
diff --git a/pkg/btrfs/btrfsitem/item_uuid.go b/pkg/btrfs/btrfsitem/item_uuid.go
index d66e102..6b47547 100644
--- a/pkg/btrfs/btrfsitem/item_uuid.go
+++ b/pkg/btrfs/btrfsitem/item_uuid.go
@@ -7,6 +7,9 @@ import (
// The Key for this item is a UUID, and the item is a list of
// subvolume IDs (ObjectIDs) that that UUID maps to.
+//
+// key.objectid = first half of UUID
+// key.offset = second half of UUID
type UUIDMap []internal.ObjID // UUID_SUBVOL=251 UUID_RECEIVED_SUBVOL=252
func (o *UUIDMap) UnmarshalBinary(dat []byte) (int, error) {
diff --git a/pkg/btrfs/btrfsitem/items.txt b/pkg/btrfs/btrfsitem/items.txt
index a5f247f..2820788 100644
--- a/pkg/btrfs/btrfsitem/items.txt
+++ b/pkg/btrfs/btrfsitem/items.txt
@@ -17,7 +17,9 @@ METADATA_ITEM=169 Metadata
ORPHAN_ITEM=48 Empty
PERSISTENT_ITEM=249 DevStats
QGROUP_RELATION=246 Empty
+ROOT_BACKREF=144 RootRef
ROOT_ITEM=132 Root
+ROOT_REF=156 RootRef
SHARED_BLOCK_REF=182 Empty
SHARED_DATA_REF=184 SharedDataRef
TREE_BLOCK_REF=176 Empty
diff --git a/pkg/btrfs/btrfsitem/items_gen.go b/pkg/btrfs/btrfsitem/items_gen.go
index 92e2523..030202b 100644
--- a/pkg/btrfs/btrfsitem/items_gen.go
+++ b/pkg/btrfs/btrfsitem/items_gen.go
@@ -28,7 +28,9 @@ const (
ORPHAN_ITEM_KEY = internal.ORPHAN_ITEM_KEY
PERSISTENT_ITEM_KEY = internal.PERSISTENT_ITEM_KEY
QGROUP_RELATION_KEY = internal.QGROUP_RELATION_KEY
+ ROOT_BACKREF_KEY = internal.ROOT_BACKREF_KEY
ROOT_ITEM_KEY = internal.ROOT_ITEM_KEY
+ ROOT_REF_KEY = internal.ROOT_REF_KEY
SHARED_BLOCK_REF_KEY = internal.SHARED_BLOCK_REF_KEY
SHARED_DATA_REF_KEY = internal.SHARED_DATA_REF_KEY
TREE_BLOCK_REF_KEY = internal.TREE_BLOCK_REF_KEY
@@ -58,7 +60,9 @@ var keytype2gotype = map[Type]reflect.Type{
ORPHAN_ITEM_KEY: reflect.TypeOf(Empty{}),
PERSISTENT_ITEM_KEY: reflect.TypeOf(DevStats{}),
QGROUP_RELATION_KEY: reflect.TypeOf(Empty{}),
+ ROOT_BACKREF_KEY: reflect.TypeOf(RootRef{}),
ROOT_ITEM_KEY: reflect.TypeOf(Root{}),
+ ROOT_REF_KEY: reflect.TypeOf(RootRef{}),
SHARED_BLOCK_REF_KEY: reflect.TypeOf(Empty{}),
SHARED_DATA_REF_KEY: reflect.TypeOf(SharedDataRef{}),
TREE_BLOCK_REF_KEY: reflect.TypeOf(Empty{}),
@@ -88,5 +92,6 @@ func (Inode) isItem() {}
func (InodeRefList) isItem() {}
func (Metadata) isItem() {}
func (Root) isItem() {}
+func (RootRef) isItem() {}
func (SharedDataRef) isItem() {}
func (UUIDMap) isItem() {}
diff --git a/pkg/btrfs/internal/itemtype.go b/pkg/btrfs/internal/itemtype.go
index e4b1302..60731aa 100644
--- a/pkg/btrfs/internal/itemtype.go
+++ b/pkg/btrfs/internal/itemtype.go
@@ -26,7 +26,9 @@ const (
ORPHAN_ITEM_KEY = ItemType(48)
PERSISTENT_ITEM_KEY = ItemType(249)
QGROUP_RELATION_KEY = ItemType(246)
+ ROOT_BACKREF_KEY = ItemType(144)
ROOT_ITEM_KEY = ItemType(132)
+ ROOT_REF_KEY = ItemType(156)
SHARED_BLOCK_REF_KEY = ItemType(182)
SHARED_DATA_REF_KEY = ItemType(184)
TREE_BLOCK_REF_KEY = ItemType(176)
@@ -57,7 +59,9 @@ func (t ItemType) String() string {
ORPHAN_ITEM_KEY: "ORPHAN_ITEM",
PERSISTENT_ITEM_KEY: "PERSISTENT_ITEM",
QGROUP_RELATION_KEY: "QGROUP_RELATION",
+ ROOT_BACKREF_KEY: "ROOT_BACKREF",
ROOT_ITEM_KEY: "ROOT_ITEM",
+ ROOT_REF_KEY: "ROOT_REF",
SHARED_BLOCK_REF_KEY: "SHARED_BLOCK_REF",
SHARED_DATA_REF_KEY: "SHARED_DATA_REF",
TREE_BLOCK_REF_KEY: "TREE_BLOCK_REF",
diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go
index 76eb19c..f78f653 100644
--- a/pkg/btrfsmisc/print_tree.go
+++ b/pkg/btrfsmisc/print_tree.go
@@ -97,10 +97,18 @@ func PrintTree(fs *btrfs.FS, root btrfsvol.LogicalAddr) error {
fmt.Printf("\t\tstime %v\n", fmtTime(body.STime))
fmt.Printf("\t\trtime %v\n", fmtTime(body.RTime))
}
- //case btrfsitem.ROOT_REF_KEY:
- // // TODO
- //case btrfsitem.ROOT_BACKREF_KEY:
- // // TODO
+ case btrfsitem.RootRef:
+ var tag string
+ switch item.Head.Key.ItemType {
+ case btrfsitem.ROOT_REF_KEY:
+ tag = "ref"
+ case btrfsitem.ROOT_BACKREF_KEY:
+ tag = "backref"
+ default:
+ tag = fmt.Sprintf("(error: unhandled RootRef item type: %v)", item.Head.Key.ItemType)
+ }
+ fmt.Printf("\t\troot %v key dirid %v sequence %v name %s\n",
+ tag, body.DirID, body.Sequence, body.Name)
case btrfsitem.Extent:
fmt.Printf("\t\trefs %v gen %v flags %v\n",
body.Head.Refs, body.Head.Generation, body.Head.Flags)
@@ -340,7 +348,7 @@ func FmtKey(key btrfs.Key) string {
case btrfsitem.QGROUP_RELATION_KEY: //TODO, btrfsitem.QGROUP_INFO_KEY, btrfsitem.QGROUP_LIMIT_KEY:
panic("not implemented")
case btrfsitem.UUID_SUBVOL_KEY, btrfsitem.UUID_RECEIVED_SUBVOL_KEY:
- fmt.Fprintf(&out, " %v)", btrfsvol.PhysicalAddr(key.Offset))
+ fmt.Fprintf(&out, " %#08x)", key.Offset)
case btrfsitem.ROOT_ITEM_KEY:
fmt.Fprintf(&out, " %v)", btrfs.ObjID(key.Offset))
default: