diff options
author | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-06 03:19:40 -0600 |
---|---|---|
committer | Luke Shumaker <lukeshu@lukeshu.com> | 2022-07-08 00:16:00 -0600 |
commit | 12d10ff2e3317c280e5f6ebfd913c73a6a1d896b (patch) | |
tree | 25d3decc4677d1d1f24b88e09e22ba958f6d082e /pkg | |
parent | 90e26899daa3013e4dd18df0ab507b6b59a20406 (diff) |
subvolumes working, kinda
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/btrfs/btrfsitem/item_inoderef.go | 33 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/items.txt | 2 | ||||
-rw-r--r-- | pkg/btrfs/btrfsitem/items_gen.go | 4 | ||||
-rw-r--r-- | pkg/btrfs/io3_fs.go | 52 | ||||
-rw-r--r-- | pkg/btrfsmisc/print_tree.go | 8 |
5 files changed, 57 insertions, 42 deletions
diff --git a/pkg/btrfs/btrfsitem/item_inoderef.go b/pkg/btrfs/btrfsitem/item_inoderef.go index 78dd677..2c26df6 100644 --- a/pkg/btrfs/btrfsitem/item_inoderef.go +++ b/pkg/btrfs/btrfsitem/item_inoderef.go @@ -4,36 +4,9 @@ import ( "lukeshu.com/btrfs-tools/pkg/binstruct" ) -type InodeRefList []InodeRef // INODE_REF=12 - -func (o *InodeRefList) UnmarshalBinary(dat []byte) (int, error) { - *o = nil - n := 0 - for n < len(dat) { - var ref InodeRef - _n, err := binstruct.Unmarshal(dat, &ref) - n += _n - if err != nil { - return n, err - } - *o = append(*o, ref) - } - return n, nil -} - -func (o InodeRefList) MarshalBinary() ([]byte, error) { - var ret []byte - for _, ref := range o { - bs, err := binstruct.Marshal(ref) - ret = append(ret, bs...) - if err != nil { - return ret, err - } - } - return ret, nil -} - -type InodeRef struct { +// key.objectid = inode number of the file +// key.offset = inode number of the parent file +type InodeRef struct { // INODE_REF=12 Index int64 `bin:"off=0x0, siz=0x8"` NameLen uint16 `bin:"off=0x8, siz=0x2"` // [ignored-when-writing] binstruct.End `bin:"off=0xa"` diff --git a/pkg/btrfs/btrfsitem/items.txt b/pkg/btrfs/btrfsitem/items.txt index 2820788..7898775 100644 --- a/pkg/btrfs/btrfsitem/items.txt +++ b/pkg/btrfs/btrfsitem/items.txt @@ -12,7 +12,7 @@ FREE_SPACE_BITMAP=200 FreeSpaceBitmap FREE_SPACE_EXTENT=199 Empty FREE_SPACE_INFO=198 FreeSpaceInfo INODE_ITEM=1 Inode -INODE_REF=12 InodeRefList +INODE_REF=12 InodeRef METADATA_ITEM=169 Metadata ORPHAN_ITEM=48 Empty PERSISTENT_ITEM=249 DevStats diff --git a/pkg/btrfs/btrfsitem/items_gen.go b/pkg/btrfs/btrfsitem/items_gen.go index 030202b..b5b64bd 100644 --- a/pkg/btrfs/btrfsitem/items_gen.go +++ b/pkg/btrfs/btrfsitem/items_gen.go @@ -55,7 +55,7 @@ var keytype2gotype = map[Type]reflect.Type{ FREE_SPACE_EXTENT_KEY: reflect.TypeOf(Empty{}), FREE_SPACE_INFO_KEY: reflect.TypeOf(FreeSpaceInfo{}), INODE_ITEM_KEY: reflect.TypeOf(Inode{}), - INODE_REF_KEY: reflect.TypeOf(InodeRefList{}), + INODE_REF_KEY: reflect.TypeOf(InodeRef{}), METADATA_ITEM_KEY: reflect.TypeOf(Metadata{}), ORPHAN_ITEM_KEY: reflect.TypeOf(Empty{}), PERSISTENT_ITEM_KEY: reflect.TypeOf(DevStats{}), @@ -89,7 +89,7 @@ func (FreeSpaceBitmap) isItem() {} func (FreeSpaceHeader) isItem() {} func (FreeSpaceInfo) isItem() {} func (Inode) isItem() {} -func (InodeRefList) isItem() {} +func (InodeRef) isItem() {} func (Metadata) isItem() {} func (Root) isItem() {} func (RootRef) isItem() {} diff --git a/pkg/btrfs/io3_fs.go b/pkg/btrfs/io3_fs.go index a418b05..75b973b 100644 --- a/pkg/btrfs/io3_fs.go +++ b/pkg/btrfs/io3_fs.go @@ -3,6 +3,7 @@ package btrfs import ( "fmt" "io" + "path/filepath" "reflect" "sort" "sync" @@ -25,10 +26,17 @@ type FullInode struct { OtherItems []Item } +type InodeRef struct { + Inode ObjID + btrfsitem.InodeRef +} + type Dir struct { FullInode + DotDot *InodeRef ChildrenByName map[string]btrfsitem.DirEntry ChildrenByIndex map[uint64]btrfsitem.DirEntry + SV *Subvolume } type FileExtent struct { @@ -39,7 +47,7 @@ type FileExtent struct { type File struct { FullInode Extents []FileExtent - FS *FS + SV *Subvolume } type Subvolume struct { @@ -182,6 +190,7 @@ func (sv *Subvolume) LoadDir(inode ObjID) (*Dir, error) { return } val.FullInode = *fullInode + val.SV = sv val.populate() return }) @@ -197,7 +206,17 @@ func (ret *Dir) populate() { for _, item := range ret.OtherItems { switch item.Head.Key.ItemType { case btrfsitem.INODE_REF_KEY: - // TODO + ref := InodeRef{ + Inode: ObjID(item.Head.Key.Offset), + InodeRef: item.Body.(btrfsitem.InodeRef), + } + if ret.DotDot != nil { + if !reflect.DeepEqual(ref, *ret.DotDot) { + ret.Errs = append(ret.Errs, fmt.Errorf("multiple INODE_REF items on a directory")) + } + continue + } + ret.DotDot = &ref case btrfsitem.DIR_ITEM_KEY: body := item.Body.(btrfsitem.DirEntries) if len(body) != 1 { @@ -265,6 +284,28 @@ func (ret *Dir) populate() { return } +func (dir *Dir) AbsPath() (string, error) { + rootInode, err := dir.SV.GetRootInode() + if err != nil { + return "", err + } + if rootInode == dir.Inode { + return "/", nil + } + if dir.DotDot == nil { + return "", fmt.Errorf("missing .. entry in dir inode %v", dir.Inode) + } + parent, err := dir.SV.LoadDir(dir.DotDot.Inode) + if err != nil { + return "", err + } + parentName, err := parent.AbsPath() + if err != nil { + return "", err + } + return filepath.Join(parentName, string(dir.DotDot.Name)), nil +} + func (sv *Subvolume) LoadFile(inode ObjID) (*File, error) { val := sv.fileCache.GetOrElse(inode, func() (val *File) { val = new(File) @@ -274,7 +315,7 @@ func (sv *Subvolume) LoadFile(inode ObjID) (*File, error) { return } val.FullInode = *fullInode - val.FS = sv.FS + val.SV = sv val.populate() return }) @@ -370,12 +411,15 @@ func (file *File) maybeShortReadAt(dat []byte, off int64) (int, error) { case btrfsitem.FILE_EXTENT_INLINE: return copy(dat, extent.BodyInline[offsetWithinExt:offsetWithinExt+readSize]), nil case btrfsitem.FILE_EXTENT_REG, btrfsitem.FILE_EXTENT_PREALLOC: - return file.FS.ReadAt(dat[:readSize], + return file.SV.FS.ReadAt(dat[:readSize], extent.BodyExtent.DiskByteNr. Add(extent.BodyExtent.Offset). Add(btrfsvol.AddrDelta(offsetWithinExt))) } } + if file.InodeItem != nil && off >= file.InodeItem.Size { + return 0, io.EOF + } return 0, fmt.Errorf("read: could not map position %v", off) } diff --git a/pkg/btrfsmisc/print_tree.go b/pkg/btrfsmisc/print_tree.go index 61c5423..c03cb4a 100644 --- a/pkg/btrfsmisc/print_tree.go +++ b/pkg/btrfsmisc/print_tree.go @@ -57,11 +57,9 @@ func PrintTree(fs *btrfs.FS, root btrfsvol.LogicalAddr) error { fmt.Printf("\t\tctime %v\n", fmtTime(body.CTime)) fmt.Printf("\t\tmtime %v\n", fmtTime(body.MTime)) fmt.Printf("\t\totime %v\n", fmtTime(body.OTime)) - case btrfsitem.InodeRefList: - for _, ref := range body { - fmt.Printf("\t\tindex %v namelen %v name: %s\n", - ref.Index, ref.NameLen, ref.Name) - } + case btrfsitem.InodeRef: + fmt.Printf("\t\tindex %v namelen %v name: %s\n", + body.Index, body.NameLen, body.Name) //case btrfsitem.INODE_EXTREF_KEY: // // TODO case btrfsitem.DirEntries: |