summaryrefslogtreecommitdiff
path: root/lib/btrfs/btrfsitem/item_fileextent.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2022-07-10 13:18:30 -0600
committerLuke Shumaker <lukeshu@lukeshu.com>2022-07-10 13:35:20 -0600
commit27401b6ea459921a6152ab1744da1618358465f4 (patch)
tree2c4f9c096f1a593e65d7f824901e815ca48bfaf0 /lib/btrfs/btrfsitem/item_fileextent.go
parent42f6f78e0a32ba0eda707154f8e1ffb4579604ee (diff)
Rename the module, mv pkg lib
Diffstat (limited to 'lib/btrfs/btrfsitem/item_fileextent.go')
-rw-r--r--lib/btrfs/btrfsitem/item_fileextent.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/lib/btrfs/btrfsitem/item_fileextent.go b/lib/btrfs/btrfsitem/item_fileextent.go
new file mode 100644
index 0000000..2f3ac2b
--- /dev/null
+++ b/lib/btrfs/btrfsitem/item_fileextent.go
@@ -0,0 +1,137 @@
+package btrfsitem
+
+import (
+ "fmt"
+
+ "git.lukeshu.com/btrfs-progs-ng/lib/binstruct"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/btrfsvol"
+ "git.lukeshu.com/btrfs-progs-ng/lib/btrfs/internal"
+)
+
+// key.objectid = inode
+// key.offset = offset within file
+type FileExtent struct { // EXTENT_DATA=108
+ Generation internal.Generation `bin:"off=0x0, siz=0x8"` // transaction ID that created this extent
+ RAMBytes int64 `bin:"off=0x8, siz=0x8"` // upper bound of what compressed data will decompress to
+
+ // 32 bits describing the data encoding
+ Compression CompressionType `bin:"off=0x10, siz=0x1"`
+ Encryption uint8 `bin:"off=0x11, siz=0x1"`
+ OtherEncoding uint16 `bin:"off=0x12, siz=0x2"` // reserved for later use
+
+ Type FileExtentType `bin:"off=0x14, siz=0x1"` // inline data or real extent
+
+ binstruct.End `bin:"off=0x15"`
+
+ // only one of these, depending on .Type
+ BodyInline []byte `bin:"-"` // .Type == FILE_EXTENT_INLINE
+ BodyExtent struct { // .Type == FILE_EXTENT_REG or FILE_EXTENT_PREALLOC
+ // Position and size of extent within the device
+ DiskByteNr btrfsvol.LogicalAddr `bin:"off=0x0, siz=0x8"`
+ DiskNumBytes btrfsvol.AddrDelta `bin:"off=0x8, siz=0x8"`
+
+ // Position of data within the extent
+ Offset btrfsvol.AddrDelta `bin:"off=0x10, siz=0x8"`
+
+ // Decompressed/unencrypted size
+ NumBytes int64 `bin:"off=0x18, siz=0x8"`
+
+ binstruct.End `bin:"off=0x20"`
+ } `bin:"-"`
+}
+
+func (o *FileExtent) UnmarshalBinary(dat []byte) (int, error) {
+ n, err := binstruct.UnmarshalWithoutInterface(dat, o)
+ if err != nil {
+ return n, err
+ }
+ switch o.Type {
+ case FILE_EXTENT_INLINE:
+ o.BodyInline = dat[n:]
+ n += len(o.BodyInline)
+ case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC:
+ _n, err := binstruct.Unmarshal(dat[n:], &o.BodyExtent)
+ n += _n
+ if err != nil {
+ return n, err
+ }
+ default:
+ return n, fmt.Errorf("unknown file extent type %v", o.Type)
+ }
+ return n, nil
+}
+
+func (o FileExtent) MarshalBinary() ([]byte, error) {
+ dat, err := binstruct.MarshalWithoutInterface(o)
+ if err != nil {
+ return dat, err
+ }
+ switch o.Type {
+ case FILE_EXTENT_INLINE:
+ dat = append(dat, o.BodyInline...)
+ case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC:
+ bs, err := binstruct.Marshal(o.BodyExtent)
+ dat = append(dat, bs...)
+ if err != nil {
+ return dat, err
+ }
+ default:
+ return dat, fmt.Errorf("unknown file extent type %v", o.Type)
+ }
+ return dat, nil
+}
+
+type FileExtentType uint8
+
+const (
+ FILE_EXTENT_INLINE = FileExtentType(iota)
+ FILE_EXTENT_REG
+ FILE_EXTENT_PREALLOC
+)
+
+func (o FileExtent) Size() (int64, error) {
+ switch o.Type {
+ case FILE_EXTENT_INLINE:
+ return int64(len(o.BodyInline)), nil
+ case FILE_EXTENT_REG, FILE_EXTENT_PREALLOC:
+ return o.BodyExtent.NumBytes, nil
+ default:
+ return 0, fmt.Errorf("unknown file extent type %v", o.Type)
+ }
+}
+
+func (fet FileExtentType) String() string {
+ names := map[FileExtentType]string{
+ FILE_EXTENT_INLINE: "inline",
+ FILE_EXTENT_REG: "regular",
+ FILE_EXTENT_PREALLOC: "prealloc",
+ }
+ name, ok := names[fet]
+ if !ok {
+ name = "unknown"
+ }
+ return fmt.Sprintf("%d (%s)", fet, name)
+}
+
+type CompressionType uint8
+
+const (
+ COMPRESS_NONE = CompressionType(iota)
+ COMPRESS_ZLIB
+ COMPRESS_LZO
+ COMPRESS_ZSTD
+)
+
+func (ct CompressionType) String() string {
+ names := map[CompressionType]string{
+ COMPRESS_NONE: "none",
+ COMPRESS_ZLIB: "zlib",
+ COMPRESS_LZO: "lzo",
+ COMPRESS_ZSTD: "zstd",
+ }
+ name, ok := names[ct]
+ if !ok {
+ name = "unknown"
+ }
+ return fmt.Sprintf("%d (%s)", ct, name)
+}