From 9c581316735f78c4fec9787aa4fd8635398b4c51 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 2 Jul 2022 12:49:24 -0600 Subject: wip ls-files --- cmd/btrfs-ls-files/main.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 cmd/btrfs-ls-files/main.go (limited to 'cmd/btrfs-ls-files') diff --git a/cmd/btrfs-ls-files/main.go b/cmd/btrfs-ls-files/main.go new file mode 100644 index 0000000..4cb4b56 --- /dev/null +++ b/cmd/btrfs-ls-files/main.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + "os" + + "lukeshu.com/btrfs-tools/pkg/btrfs" + "lukeshu.com/btrfs-tools/pkg/btrfs/btrfsitem" + "lukeshu.com/btrfs-tools/pkg/btrfsmisc" + "lukeshu.com/btrfs-tools/pkg/util" +) + +func main() { + if err := Main(os.Args[1:]...); err != nil { + fmt.Fprintf(os.Stderr, "%v: error: %v\n", os.Args[0], err) + os.Exit(1) + } +} + +func Main(imgfilenames ...string) (err error) { + maybeSetErr := func(_err error) { + if _err != nil && err == nil { + err = _err + } + } + + fs, err := btrfsmisc.Open(os.O_RDONLY, imgfilenames...) + if err != nil { + return err + } + defer func() { + maybeSetErr(fs.Close()) + }() + + sb, err := fs.Superblock() + if err != nil { + return err + } + + fsTreeRoot, err := fs.TreeLookup(sb.Data.RootTree, 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 + + return printDir(fs, fsTree, "", "/", fsTreeRootBody.RootDirID, fsTreeRootBody.Inode) +} + +func printDir(fs *btrfs.FS, fsTree btrfs.LogicalAddr, prefix, dirName string, dirInodeNum btrfs.ObjID, dirInode btrfsitem.Inode) error { + fmt.Printf("%s[%s\tino=%d\tuid=%d\tgid=%d\tsize=%d] %s\n", + prefix, + dirInode.Mode, dirInodeNum, dirInode.UID, dirInode.GID, dirInode.Size, + dirName) + items, err := fs.TreeSearchAll(fsTree, func(key btrfs.Key) int { + return util.CmpUint(dirInodeNum, key.ObjectID) + }) + if err != nil { + return fmt.Errorf("read directory %q: %w", dirName, err) + } + for _, item := range items { + switch item.Head.Key.ItemType { + case btrfsitem.INODE_ITEM_KEY: + // TODO + case btrfsitem.INODE_REF_KEY: + // TODO + case btrfsitem.DIR_ITEM_KEY: + // skip? + case btrfsitem.DIR_INDEX_KEY: + for _, entry := range item.Body.(btrfsitem.DirList) { + fmt.Println(string(entry.Name)) + } + case btrfsitem.XATTR_ITEM_KEY: + default: + panic(fmt.Errorf("TODO: handle item type %v", item.Head.Key.ItemType)) + } + } + return nil +} -- cgit v1.2.3-2-g168b