btrfs_stream: Java (read-write) parsing library

Btrfs is a copy on write file system based on B-trees focusing on fault tolerance, repair and easy administration. Btrfs is intended to address the lack of pooling, snapshots, checksums, and integral multi-device spanning in Linux file systems. Given any pair of subvolumes (or snapshots), Btrfs can generate a binary diff between them by using the btrfs send command that can be replayed later by using btrfs receive, possibly on a different Btrfs file system. The btrfs send command creates a set of data modifications required for converting one subvolume into another. This spec can be used to disassemble the binary diff created by the btrfs send command. If you want a text representation you may want to checkout btrfs receive --dump instead.

Application

Btrfs

KS implementation details

License: CC0-1.0

References

This page hosts a formal specification of btrfs_stream using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Java (read-write) source code to parse btrfs_stream

BtrfsStream.java

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

import io.kaitai.struct.ByteBufferKaitaiStream;
import io.kaitai.struct.KaitaiStruct;
import io.kaitai.struct.KaitaiStream;
import java.io.IOException;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import io.kaitai.struct.ConsistencyError;
import java.util.Objects;
import java.nio.charset.StandardCharsets;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Arrays;


/**
 * Btrfs is a copy on write file system based on B-trees focusing on fault tolerance, repair and easy
 * administration. Btrfs is intended to address the lack of pooling, snapshots, checksums, and
 * integral multi-device spanning in Linux file systems.
 * Given any pair of subvolumes (or snapshots), Btrfs can generate a binary diff between them by
 * using the `btrfs send` command that can be replayed later by using `btrfs receive`, possibly on a
 * different Btrfs file system. The `btrfs send` command creates a set of data modifications required
 * for converting one subvolume into another.
 * This spec can be used to disassemble the binary diff created by the `btrfs send` command.
 * If you want a text representation you may want to checkout `btrfs receive --dump` instead.
 * @see <a href="https://archive.kernel.org/oldwiki/btrfs.wiki.kernel.org/index.php/Design_notes_on_Send/Receive.html">Source</a>
 */
public class BtrfsStream extends KaitaiStruct.ReadWrite {
    public static BtrfsStream fromFile(String fileName) throws IOException {
        return new BtrfsStream(new ByteBufferKaitaiStream(fileName));
    }

    public enum Attribute {
        UNSPEC(0),
        UUID(1),
        CTRANSID(2),
        INO(3),
        SIZE(4),
        MODE(5),
        UID(6),
        GID(7),
        RDEV(8),
        CTIME(9),
        MTIME(10),
        ATIME(11),
        OTIME(12),
        XATTR_NAME(13),
        XATTR_DATA(14),
        PATH(15),
        PATH_TO(16),
        PATH_LINK(17),
        FILE_OFFSET(18),
        DATA(19),
        CLONE_UUID(20),
        CLONE_CTRANSID(21),
        CLONE_PATH(22),
        CLONE_OFFSET(23),
        CLONE_LEN(24);

        private final long id;
        Attribute(long id) { this.id = id; }
        public long id() { return id; }
        private static final Map<Long, Attribute> byId = new HashMap<Long, Attribute>(25);
        static {
            for (Attribute e : Attribute.values())
                byId.put(e.id(), e);
        }
        public static Attribute byId(long id) { return byId.get(id); }
    }

    public enum Command {
        UNSPEC(0),
        SUBVOL(1),
        SNAPSHOT(2),
        MKFILE(3),
        MKDIR(4),
        MKNOD(5),
        MKFIFO(6),
        MKSOCK(7),
        SYMLINK(8),
        RENAME(9),
        LINK(10),
        UNLINK(11),
        RMDIR(12),
        SET_XATTR(13),
        REMOVE_XATTR(14),
        WRITE(15),
        CLONE(16),
        TRUNCATE(17),
        CHMOD(18),
        CHOWN(19),
        UTIMES(20),
        END(21),
        UPDATE_EXTENT(22);

        private final long id;
        Command(long id) { this.id = id; }
        public long id() { return id; }
        private static final Map<Long, Command> byId = new HashMap<Long, Command>(23);
        static {
            for (Command e : Command.values())
                byId.put(e.id(), e);
        }
        public static Command byId(long id) { return byId.get(id); }
    }
    public BtrfsStream() {
        this(null, null, null);
    }

    public BtrfsStream(KaitaiStream _io) {
        this(_io, null, null);
    }

    public BtrfsStream(KaitaiStream _io, KaitaiStruct.ReadWrite _parent) {
        this(_io, _parent, null);
    }

    public BtrfsStream(KaitaiStream _io, KaitaiStruct.ReadWrite _parent, BtrfsStream _root) {
        super(_io);
        this._parent = _parent;
        this._root = _root == null ? this : _root;
    }
    public void _read() {
        this.header = new SendStreamHeader(this._io, this, _root);
        this.header._read();
        this.commands = new ArrayList<SendCommand>();
        {
            int i = 0;
            while (!this._io.isEof()) {
                SendCommand _t_commands = new SendCommand(this._io, this, _root);
                try {
                    _t_commands._read();
                } finally {
                    this.commands.add(_t_commands);
                }
                i++;
            }
        }
        _dirty = false;
    }

    public void _fetchInstances() {
        this.header._fetchInstances();
        for (int i = 0; i < this.commands.size(); i++) {
            this.commands.get(((Number) (i)).intValue())._fetchInstances();
        }
    }

    public void _write_Seq() {
        _assertNotDirty();
        this.header._write_Seq(this._io);
        for (int i = 0; i < this.commands.size(); i++) {
            if (this._io.isEof())
                throw new ConsistencyError("commands", 0, this._io.size() - this._io.pos());
            this.commands.get(((Number) (i)).intValue())._write_Seq(this._io);
        }
        if (!(this._io.isEof()))
            throw new ConsistencyError("commands", 0, this._io.size() - this._io.pos());
    }

    public void _check() {
        if (!Objects.equals(this.header._root(), _root()))
            throw new ConsistencyError("header", _root(), this.header._root());
        if (!Objects.equals(this.header._parent(), this))
            throw new ConsistencyError("header", this, this.header._parent());
        for (int i = 0; i < this.commands.size(); i++) {
            if (!Objects.equals(this.commands.get(((Number) (i)).intValue())._root(), _root()))
                throw new ConsistencyError("commands", _root(), this.commands.get(((Number) (i)).intValue())._root());
            if (!Objects.equals(this.commands.get(((Number) (i)).intValue())._parent(), this))
                throw new ConsistencyError("commands", this, this.commands.get(((Number) (i)).intValue())._parent());
        }
        _dirty = false;
    }
    public static class SendCommand extends KaitaiStruct.ReadWrite {
        public static SendCommand fromFile(String fileName) throws IOException {
            return new SendCommand(new ByteBufferKaitaiStream(fileName));
        }
        public SendCommand() {
            this(null, null, null);
        }

        public SendCommand(KaitaiStream _io) {
            this(_io, null, null);
        }

        public SendCommand(KaitaiStream _io, BtrfsStream _parent) {
            this(_io, _parent, null);
        }

        public SendCommand(KaitaiStream _io, BtrfsStream _parent, BtrfsStream _root) {
            super(_io);
            this._parent = _parent;
            this._root = _root;
        }
        public void _read() {
            this.lenData = this._io.readU4le();
            this.type = BtrfsStream.Command.byId(this._io.readU2le());
            this.checksum = this._io.readBytes(4);
            this._raw_data = this._io.readBytes(lenData());
            KaitaiStream _io__raw_data = new ByteBufferKaitaiStream(this._raw_data);
            this.data = new Tlvs(_io__raw_data, this, _root);
            this.data._read();
            _dirty = false;
        }

        public void _fetchInstances() {
            this.data._fetchInstances();
        }

        public void _write_Seq() {
            _assertNotDirty();
            this._io.writeU4le(this.lenData);
            this._io.writeU2le(((Number) (this.type.id())).intValue());
            this._io.writeBytes(this.checksum);
            final KaitaiStream _io__raw_data = new ByteBufferKaitaiStream(lenData());
            this._io.addChildStream(_io__raw_data);
            {
                long _pos2 = this._io.pos();
                this._io.seek(this._io.pos() + (lenData()));
                final SendCommand _this = this;
                _io__raw_data.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                    @Override
                    protected void write(KaitaiStream parent) {
                        _this._raw_data = _io__raw_data.toByteArray();
                        if (_this._raw_data.length != lenData())
                            throw new ConsistencyError("raw(data)", lenData(), _this._raw_data.length);
                        parent.writeBytes(_this._raw_data);
                    }
                });
            }
            this.data._write_Seq(_io__raw_data);
        }

        public void _check() {
            if (this.checksum.length != 4)
                throw new ConsistencyError("checksum", 4, this.checksum.length);
            if (!Objects.equals(this.data._root(), _root()))
                throw new ConsistencyError("data", _root(), this.data._root());
            if (!Objects.equals(this.data._parent(), this))
                throw new ConsistencyError("data", this, this.data._parent());
            _dirty = false;
        }
        public static class String extends KaitaiStruct.ReadWrite {
            public static String fromFile(String fileName) throws IOException {
                return new String(new ByteBufferKaitaiStream(fileName));
            }
            public String() {
                this(null, null, null);
            }

            public String(KaitaiStream _io) {
                this(_io, null, null);
            }

            public String(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent) {
                this(_io, _parent, null);
            }

            public String(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent, BtrfsStream _root) {
                super(_io);
                this._parent = _parent;
                this._root = _root;
            }
            public void _read() {
                this.string = new String(this._io.readBytesFull(), StandardCharsets.UTF_8);
                _dirty = false;
            }

            public void _fetchInstances() {
            }

            public void _write_Seq() {
                _assertNotDirty();
                this._io.writeBytes((this.string).getBytes(Charset.forName("UTF-8")));
                if (!(this._io.isEof()))
                    throw new ConsistencyError("string", 0, this._io.size() - this._io.pos());
            }

            public void _check() {
                _dirty = false;
            }
            private String string;
            private BtrfsStream _root;
            private BtrfsStream.SendCommand.Tlv _parent;
            public String string() { return string; }
            public void setString(String _v) { _dirty = true; string = _v; }
            public BtrfsStream _root() { return _root; }
            public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
            public BtrfsStream.SendCommand.Tlv _parent() { return _parent; }
            public void set_parent(BtrfsStream.SendCommand.Tlv _v) { _dirty = true; _parent = _v; }
        }
        public static class Timespec extends KaitaiStruct.ReadWrite {
            public static Timespec fromFile(String fileName) throws IOException {
                return new Timespec(new ByteBufferKaitaiStream(fileName));
            }
            public Timespec() {
                this(null, null, null);
            }

            public Timespec(KaitaiStream _io) {
                this(_io, null, null);
            }

            public Timespec(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent) {
                this(_io, _parent, null);
            }

            public Timespec(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent, BtrfsStream _root) {
                super(_io);
                this._parent = _parent;
                this._root = _root;
            }
            public void _read() {
                this.tsSec = this._io.readS8le();
                this.tsNsec = this._io.readS4le();
                _dirty = false;
            }

            public void _fetchInstances() {
            }

            public void _write_Seq() {
                _assertNotDirty();
                this._io.writeS8le(this.tsSec);
                this._io.writeS4le(this.tsNsec);
            }

            public void _check() {
                _dirty = false;
            }
            private long tsSec;
            private int tsNsec;
            private BtrfsStream _root;
            private BtrfsStream.SendCommand.Tlv _parent;
            public long tsSec() { return tsSec; }
            public void setTsSec(long _v) { _dirty = true; tsSec = _v; }
            public int tsNsec() { return tsNsec; }
            public void setTsNsec(int _v) { _dirty = true; tsNsec = _v; }
            public BtrfsStream _root() { return _root; }
            public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
            public BtrfsStream.SendCommand.Tlv _parent() { return _parent; }
            public void set_parent(BtrfsStream.SendCommand.Tlv _v) { _dirty = true; _parent = _v; }
        }
        public static class Tlv extends KaitaiStruct.ReadWrite {
            public static Tlv fromFile(String fileName) throws IOException {
                return new Tlv(new ByteBufferKaitaiStream(fileName));
            }
            public Tlv() {
                this(null, null, null);
            }

            public Tlv(KaitaiStream _io) {
                this(_io, null, null);
            }

            public Tlv(KaitaiStream _io, BtrfsStream.SendCommand.Tlvs _parent) {
                this(_io, _parent, null);
            }

            public Tlv(KaitaiStream _io, BtrfsStream.SendCommand.Tlvs _parent, BtrfsStream _root) {
                super(_io);
                this._parent = _parent;
                this._root = _root;
            }
            public void _read() {
                this.type = BtrfsStream.Attribute.byId(this._io.readU2le());
                this.length = this._io.readU2le();
                {
                    Attribute on = type();
                    if (on != null) {
                        switch (type()) {
                        case ATIME: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Timespec(_io__raw_value, this, _root);
                            ((Timespec) (this.value))._read();
                            break;
                        }
                        case CLONE_CTRANSID: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case CLONE_LEN: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case CLONE_OFFSET: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case CLONE_PATH: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new String(_io__raw_value, this, _root);
                            ((String) (this.value))._read();
                            break;
                        }
                        case CLONE_UUID: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Uuid(_io__raw_value, this, _root);
                            ((Uuid) (this.value))._read();
                            break;
                        }
                        case CTIME: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Timespec(_io__raw_value, this, _root);
                            ((Timespec) (this.value))._read();
                            break;
                        }
                        case CTRANSID: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case FILE_OFFSET: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case GID: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case MODE: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case MTIME: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Timespec(_io__raw_value, this, _root);
                            ((Timespec) (this.value))._read();
                            break;
                        }
                        case OTIME: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Timespec(_io__raw_value, this, _root);
                            ((Timespec) (this.value))._read();
                            break;
                        }
                        case PATH: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new String(_io__raw_value, this, _root);
                            ((String) (this.value))._read();
                            break;
                        }
                        case PATH_LINK: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new String(_io__raw_value, this, _root);
                            ((String) (this.value))._read();
                            break;
                        }
                        case PATH_TO: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new String(_io__raw_value, this, _root);
                            ((String) (this.value))._read();
                            break;
                        }
                        case RDEV: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case SIZE: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case UID: {
                            this.value = ((Object) (this._io.readU8le()));
                            break;
                        }
                        case UUID: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new Uuid(_io__raw_value, this, _root);
                            ((Uuid) (this.value))._read();
                            break;
                        }
                        case XATTR_NAME: {
                            this._raw_value = this._io.readBytes(length());
                            KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(this._raw_value);
                            this.value = new String(_io__raw_value, this, _root);
                            ((String) (this.value))._read();
                            break;
                        }
                        default: {
                            this.value = this._io.readBytes(length());
                            break;
                        }
                        }
                    } else {
                        this.value = this._io.readBytes(length());
                    }
                }
                _dirty = false;
            }

            public void _fetchInstances() {
                {
                    Attribute on = type();
                    if (on != null) {
                        switch (type()) {
                        case ATIME: {
                            ((Timespec) (this.value))._fetchInstances();
                            break;
                        }
                        case CLONE_CTRANSID: {
                            break;
                        }
                        case CLONE_LEN: {
                            break;
                        }
                        case CLONE_OFFSET: {
                            break;
                        }
                        case CLONE_PATH: {
                            ((String) (this.value))._fetchInstances();
                            break;
                        }
                        case CLONE_UUID: {
                            ((Uuid) (this.value))._fetchInstances();
                            break;
                        }
                        case CTIME: {
                            ((Timespec) (this.value))._fetchInstances();
                            break;
                        }
                        case CTRANSID: {
                            break;
                        }
                        case FILE_OFFSET: {
                            break;
                        }
                        case GID: {
                            break;
                        }
                        case MODE: {
                            break;
                        }
                        case MTIME: {
                            ((Timespec) (this.value))._fetchInstances();
                            break;
                        }
                        case OTIME: {
                            ((Timespec) (this.value))._fetchInstances();
                            break;
                        }
                        case PATH: {
                            ((String) (this.value))._fetchInstances();
                            break;
                        }
                        case PATH_LINK: {
                            ((String) (this.value))._fetchInstances();
                            break;
                        }
                        case PATH_TO: {
                            ((String) (this.value))._fetchInstances();
                            break;
                        }
                        case RDEV: {
                            break;
                        }
                        case SIZE: {
                            break;
                        }
                        case UID: {
                            break;
                        }
                        case UUID: {
                            ((Uuid) (this.value))._fetchInstances();
                            break;
                        }
                        case XATTR_NAME: {
                            ((String) (this.value))._fetchInstances();
                            break;
                        }
                        default: {
                            break;
                        }
                        }
                    } else {
                    }
                }
            }

            public void _write_Seq() {
                _assertNotDirty();
                this._io.writeU2le(((Number) (this.type.id())).intValue());
                this._io.writeU2le(this.length);
                {
                    Attribute on = type();
                    if (on != null) {
                        switch (type()) {
                        case ATIME: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Timespec) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case CLONE_CTRANSID: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case CLONE_LEN: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case CLONE_OFFSET: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case CLONE_PATH: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((String) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case CLONE_UUID: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Uuid) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case CTIME: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Timespec) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case CTRANSID: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case FILE_OFFSET: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case GID: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case MODE: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case MTIME: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Timespec) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case OTIME: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Timespec) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case PATH: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((String) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case PATH_LINK: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((String) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case PATH_TO: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((String) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case RDEV: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case SIZE: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case UID: {
                            this._io.writeU8le(((Number) (this.value)).longValue());
                            break;
                        }
                        case UUID: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((Uuid) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        case XATTR_NAME: {
                            final KaitaiStream _io__raw_value = new ByteBufferKaitaiStream(length());
                            this._io.addChildStream(_io__raw_value);
                            {
                                long _pos2 = this._io.pos();
                                this._io.seek(this._io.pos() + (length()));
                                final Tlv _this = this;
                                _io__raw_value.setWriteBackHandler(new KaitaiStream.WriteBackHandler(_pos2) {
                                    @Override
                                    protected void write(KaitaiStream parent) {
                                        _this._raw_value = _io__raw_value.toByteArray();
                                        if (((byte[]) (_this._raw_value)).length != length())
                                            throw new ConsistencyError("raw(value)", length(), ((byte[]) (_this._raw_value)).length);
                                        parent.writeBytes(((byte[]) (((byte[]) (_this._raw_value)))));
                                    }
                                });
                            }
                            ((String) (this.value))._write_Seq(_io__raw_value);
                            break;
                        }
                        default: {
                            this._io.writeBytes(((byte[]) (((byte[]) (this.value)))));
                            break;
                        }
                        }
                    } else {
                        this._io.writeBytes(((byte[]) (((byte[]) (this.value)))));
                    }
                }
            }

            public void _check() {
                {
                    Attribute on = type();
                    if (on != null) {
                        switch (type()) {
                        case ATIME: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Timespec) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Timespec) (this.value))._parent());
                            break;
                        }
                        case CLONE_CTRANSID: {
                            break;
                        }
                        case CLONE_LEN: {
                            break;
                        }
                        case CLONE_OFFSET: {
                            break;
                        }
                        case CLONE_PATH: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.String) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.String) (this.value))._parent());
                            break;
                        }
                        case CLONE_UUID: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Uuid) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Uuid) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Uuid) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Uuid) (this.value))._parent());
                            break;
                        }
                        case CTIME: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Timespec) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Timespec) (this.value))._parent());
                            break;
                        }
                        case CTRANSID: {
                            break;
                        }
                        case FILE_OFFSET: {
                            break;
                        }
                        case GID: {
                            break;
                        }
                        case MODE: {
                            break;
                        }
                        case MTIME: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Timespec) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Timespec) (this.value))._parent());
                            break;
                        }
                        case OTIME: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Timespec) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Timespec) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Timespec) (this.value))._parent());
                            break;
                        }
                        case PATH: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.String) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.String) (this.value))._parent());
                            break;
                        }
                        case PATH_LINK: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.String) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.String) (this.value))._parent());
                            break;
                        }
                        case PATH_TO: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.String) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.String) (this.value))._parent());
                            break;
                        }
                        case RDEV: {
                            break;
                        }
                        case SIZE: {
                            break;
                        }
                        case UID: {
                            break;
                        }
                        case UUID: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.Uuid) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.Uuid) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.Uuid) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.Uuid) (this.value))._parent());
                            break;
                        }
                        case XATTR_NAME: {
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._root(), _root()))
                                throw new ConsistencyError("value", _root(), ((BtrfsStream.SendCommand.String) (this.value))._root());
                            if (!Objects.equals(((BtrfsStream.SendCommand.String) (this.value))._parent(), this))
                                throw new ConsistencyError("value", this, ((BtrfsStream.SendCommand.String) (this.value))._parent());
                            break;
                        }
                        default: {
                            if (((byte[]) (this.value)).length != length())
                                throw new ConsistencyError("value", length(), ((byte[]) (this.value)).length);
                            break;
                        }
                        }
                    } else {
                        if (((byte[]) (this.value)).length != length())
                            throw new ConsistencyError("value", length(), ((byte[]) (this.value)).length);
                    }
                }
                _dirty = false;
            }
            private Attribute type;
            private int length;
            private Object value;
            private BtrfsStream _root;
            private BtrfsStream.SendCommand.Tlvs _parent;
            private byte[] _raw_value;
            public Attribute type() { return type; }
            public void setType(Attribute _v) { _dirty = true; type = _v; }
            public int length() { return length; }
            public void setLength(int _v) { _dirty = true; length = _v; }
            public Object value() { return value; }
            public void setValue(Object _v) { _dirty = true; value = _v; }
            public BtrfsStream _root() { return _root; }
            public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
            public BtrfsStream.SendCommand.Tlvs _parent() { return _parent; }
            public void set_parent(BtrfsStream.SendCommand.Tlvs _v) { _dirty = true; _parent = _v; }
            public byte[] _raw_value() { return _raw_value; }
            public void set_raw_Value(byte[] _v) { _dirty = true; _raw_value = _v; }
        }
        public static class Tlvs extends KaitaiStruct.ReadWrite {
            public static Tlvs fromFile(String fileName) throws IOException {
                return new Tlvs(new ByteBufferKaitaiStream(fileName));
            }
            public Tlvs() {
                this(null, null, null);
            }

            public Tlvs(KaitaiStream _io) {
                this(_io, null, null);
            }

            public Tlvs(KaitaiStream _io, BtrfsStream.SendCommand _parent) {
                this(_io, _parent, null);
            }

            public Tlvs(KaitaiStream _io, BtrfsStream.SendCommand _parent, BtrfsStream _root) {
                super(_io);
                this._parent = _parent;
                this._root = _root;
            }
            public void _read() {
                this.tlv = new ArrayList<Tlv>();
                {
                    int i = 0;
                    while (!this._io.isEof()) {
                        Tlv _t_tlv = new Tlv(this._io, this, _root);
                        try {
                            _t_tlv._read();
                        } finally {
                            this.tlv.add(_t_tlv);
                        }
                        i++;
                    }
                }
                _dirty = false;
            }

            public void _fetchInstances() {
                for (int i = 0; i < this.tlv.size(); i++) {
                    this.tlv.get(((Number) (i)).intValue())._fetchInstances();
                }
            }

            public void _write_Seq() {
                _assertNotDirty();
                for (int i = 0; i < this.tlv.size(); i++) {
                    if (this._io.isEof())
                        throw new ConsistencyError("tlv", 0, this._io.size() - this._io.pos());
                    this.tlv.get(((Number) (i)).intValue())._write_Seq(this._io);
                }
                if (!(this._io.isEof()))
                    throw new ConsistencyError("tlv", 0, this._io.size() - this._io.pos());
            }

            public void _check() {
                for (int i = 0; i < this.tlv.size(); i++) {
                    if (!Objects.equals(this.tlv.get(((Number) (i)).intValue())._root(), _root()))
                        throw new ConsistencyError("tlv", _root(), this.tlv.get(((Number) (i)).intValue())._root());
                    if (!Objects.equals(this.tlv.get(((Number) (i)).intValue())._parent(), this))
                        throw new ConsistencyError("tlv", this, this.tlv.get(((Number) (i)).intValue())._parent());
                }
                _dirty = false;
            }
            private List<Tlv> tlv;
            private BtrfsStream _root;
            private BtrfsStream.SendCommand _parent;
            public List<Tlv> tlv() { return tlv; }
            public void setTlv(List<Tlv> _v) { _dirty = true; tlv = _v; }
            public BtrfsStream _root() { return _root; }
            public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
            public BtrfsStream.SendCommand _parent() { return _parent; }
            public void set_parent(BtrfsStream.SendCommand _v) { _dirty = true; _parent = _v; }
        }
        public static class Uuid extends KaitaiStruct.ReadWrite {
            public static Uuid fromFile(String fileName) throws IOException {
                return new Uuid(new ByteBufferKaitaiStream(fileName));
            }
            public Uuid() {
                this(null, null, null);
            }

            public Uuid(KaitaiStream _io) {
                this(_io, null, null);
            }

            public Uuid(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent) {
                this(_io, _parent, null);
            }

            public Uuid(KaitaiStream _io, BtrfsStream.SendCommand.Tlv _parent, BtrfsStream _root) {
                super(_io);
                this._parent = _parent;
                this._root = _root;
            }
            public void _read() {
                this.uuid = this._io.readBytes(16);
                _dirty = false;
            }

            public void _fetchInstances() {
            }

            public void _write_Seq() {
                _assertNotDirty();
                this._io.writeBytes(this.uuid);
            }

            public void _check() {
                if (this.uuid.length != 16)
                    throw new ConsistencyError("uuid", 16, this.uuid.length);
                _dirty = false;
            }
            private byte[] uuid;
            private BtrfsStream _root;
            private BtrfsStream.SendCommand.Tlv _parent;
            public byte[] uuid() { return uuid; }
            public void setUuid(byte[] _v) { _dirty = true; uuid = _v; }
            public BtrfsStream _root() { return _root; }
            public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
            public BtrfsStream.SendCommand.Tlv _parent() { return _parent; }
            public void set_parent(BtrfsStream.SendCommand.Tlv _v) { _dirty = true; _parent = _v; }
        }
        private long lenData;
        private Command type;
        private byte[] checksum;
        private Tlvs data;
        private BtrfsStream _root;
        private BtrfsStream _parent;
        private byte[] _raw_data;
        public long lenData() { return lenData; }
        public void setLenData(long _v) { _dirty = true; lenData = _v; }
        public Command type() { return type; }
        public void setType(Command _v) { _dirty = true; type = _v; }

        /**
         * CRC32 checksum of a whole send command, including the header, with this attribute set to 0.
         */
        public byte[] checksum() { return checksum; }
        public void setChecksum(byte[] _v) { _dirty = true; checksum = _v; }
        public Tlvs data() { return data; }
        public void setData(Tlvs _v) { _dirty = true; data = _v; }
        public BtrfsStream _root() { return _root; }
        public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
        public BtrfsStream _parent() { return _parent; }
        public void set_parent(BtrfsStream _v) { _dirty = true; _parent = _v; }
        public byte[] _raw_data() { return _raw_data; }
        public void set_raw_Data(byte[] _v) { _dirty = true; _raw_data = _v; }
    }
    public static class SendStreamHeader extends KaitaiStruct.ReadWrite {
        public static SendStreamHeader fromFile(String fileName) throws IOException {
            return new SendStreamHeader(new ByteBufferKaitaiStream(fileName));
        }
        public SendStreamHeader() {
            this(null, null, null);
        }

        public SendStreamHeader(KaitaiStream _io) {
            this(_io, null, null);
        }

        public SendStreamHeader(KaitaiStream _io, BtrfsStream _parent) {
            this(_io, _parent, null);
        }

        public SendStreamHeader(KaitaiStream _io, BtrfsStream _parent, BtrfsStream _root) {
            super(_io);
            this._parent = _parent;
            this._root = _root;
        }
        public void _read() {
            this.magic = this._io.readBytes(13);
            if (!(Arrays.equals(this.magic, new byte[] { 98, 116, 114, 102, 115, 45, 115, 116, 114, 101, 97, 109, 0 }))) {
                throw new KaitaiStream.ValidationNotEqualError(new byte[] { 98, 116, 114, 102, 115, 45, 115, 116, 114, 101, 97, 109, 0 }, this.magic, this._io, "/types/send_stream_header/seq/0");
            }
            this.version = this._io.readU4le();
            _dirty = false;
        }

        public void _fetchInstances() {
        }

        public void _write_Seq() {
            _assertNotDirty();
            this._io.writeBytes(this.magic);
            this._io.writeU4le(this.version);
        }

        public void _check() {
            if (this.magic.length != 13)
                throw new ConsistencyError("magic", 13, this.magic.length);
            if (!(Arrays.equals(this.magic, new byte[] { 98, 116, 114, 102, 115, 45, 115, 116, 114, 101, 97, 109, 0 }))) {
                throw new KaitaiStream.ValidationNotEqualError(new byte[] { 98, 116, 114, 102, 115, 45, 115, 116, 114, 101, 97, 109, 0 }, this.magic, null, "/types/send_stream_header/seq/0");
            }
            _dirty = false;
        }
        private byte[] magic;
        private long version;
        private BtrfsStream _root;
        private BtrfsStream _parent;
        public byte[] magic() { return magic; }
        public void setMagic(byte[] _v) { _dirty = true; magic = _v; }
        public long version() { return version; }
        public void setVersion(long _v) { _dirty = true; version = _v; }
        public BtrfsStream _root() { return _root; }
        public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
        public BtrfsStream _parent() { return _parent; }
        public void set_parent(BtrfsStream _v) { _dirty = true; _parent = _v; }
    }
    private SendStreamHeader header;
    private List<SendCommand> commands;
    private BtrfsStream _root;
    private KaitaiStruct.ReadWrite _parent;
    public SendStreamHeader header() { return header; }
    public void setHeader(SendStreamHeader _v) { _dirty = true; header = _v; }
    public List<SendCommand> commands() { return commands; }
    public void setCommands(List<SendCommand> _v) { _dirty = true; commands = _v; }
    public BtrfsStream _root() { return _root; }
    public void set_root(BtrfsStream _v) { _dirty = true; _root = _v; }
    public KaitaiStruct.ReadWrite _parent() { return _parent; }
    public void set_parent(KaitaiStruct.ReadWrite _v) { _dirty = true; _parent = _v; }
}