Documentation
¶
Overview ¶
Package disklayout provides Linux ext file system's disk level structures which can be directly read into from the underlying device. Structs aim to emulate structures `exactly` how they are layed out on disk.
This library aims to be compatible with all ext(2/3/4) systems so it provides a generic interface for all major structures and various implementations (for different versions). The user code is responsible for using appropriate implementations based on the underlying device.
Interfacing all major structures here serves a few purposes:
- Abstracts away the complexity of the underlying structure from client code. The client only has to figure out versioning on set up and then can use these as black boxes and pass it higher up the stack.
- Having pointer receivers forces the user to use pointers to these heavy structs. Hence, prevents the client code from unintentionally copying these by value while passing the interface around.
- Version-based implementation selection is resolved on set up hence avoiding per call overhead of choosing implementation.
- All interface methods are pretty light weight (do not take in any parameters by design). Passing pointer arguments to interface methods can lead to heap allocation as the compiler won't be able to perform escape analysis on an unknown implementation at compile time.
Notes:
- All fields in these structs are exported because binary.Read would panic otherwise.
- All structures on disk are in little-endian order. Only jbd2 (journal) structures are in big-endian order.
- All OS dependent fields in these structures will be interpretted using the Linux version of that field.
- The suffix `Lo` in field names stands for lower bits of that field.
- The suffix `Hi` in field names stands for upper bits of that field.
- The suffix `Raw` has been added to indicate that the field is not split into Lo and Hi fields and also to resolve name collision with the respective interface.
Index ¶
- Constants
- type BGFlags
- type BlockGroup
- type BlockGroup32Bit
- func (bg *BlockGroup32Bit) BlockBitmap() uint64
- func (bg *BlockGroup32Bit) BlockBitmapChecksum() uint32
- func (bg *BlockGroup32Bit) Checksum() uint16
- func (bg *BlockGroup32Bit) DirectoryCount() uint32
- func (bg *BlockGroup32Bit) ExclusionBitmap() uint64
- func (bg *BlockGroup32Bit) Flags() BGFlags
- func (bg *BlockGroup32Bit) FreeBlocksCount() uint32
- func (bg *BlockGroup32Bit) FreeInodesCount() uint32
- func (bg *BlockGroup32Bit) InodeBitmap() uint64
- func (bg *BlockGroup32Bit) InodeBitmapChecksum() uint32
- func (bg *BlockGroup32Bit) InodeTable() uint64
- func (bg *BlockGroup32Bit) UnusedInodeCount() uint32
- type BlockGroup64Bit
- func (bg *BlockGroup64Bit) BlockBitmap() uint64
- func (bg *BlockGroup64Bit) BlockBitmapChecksum() uint32
- func (bg *BlockGroup64Bit) DirectoryCount() uint32
- func (bg *BlockGroup64Bit) ExclusionBitmap() uint64
- func (bg *BlockGroup64Bit) FreeBlocksCount() uint32
- func (bg *BlockGroup64Bit) FreeInodesCount() uint32
- func (bg *BlockGroup64Bit) InodeBitmap() uint64
- func (bg *BlockGroup64Bit) InodeBitmapChecksum() uint32
- func (bg *BlockGroup64Bit) InodeTable() uint64
- func (bg *BlockGroup64Bit) UnusedInodeCount() uint32
- type CompatFeatures
- type Dirent
- type DirentNew
- type DirentOld
- type Extent
- type ExtentEntry
- type ExtentEntryPair
- type ExtentHeader
- type ExtentIdx
- type ExtentNode
- type IncompatFeatures
- type Inode
- type InodeFlags
- type InodeNew
- type InodeOld
- func (in *InodeOld) AccessTime() time.Time
- func (in *InodeOld) ChangeTime() time.Time
- func (in *InodeOld) Data() []byte
- func (in *InodeOld) DeletionTime() time.Time
- func (in *InodeOld) Flags() InodeFlags
- func (in *InodeOld) GID() auth.KGID
- func (in *InodeOld) InodeSize() uint16
- func (in *InodeOld) LinksCount() uint16
- func (in *InodeOld) Mode() linux.FileMode
- func (in *InodeOld) ModificationTime() time.Time
- func (in *InodeOld) Size() uint64
- func (in *InodeOld) UID() auth.KUID
- type RoCompatFeatures
- type SbRevision
- type SuperBlock
- type SuperBlock32Bit
- type SuperBlock64Bit
- type SuperBlockOld
- func (sb *SuperBlockOld) BgDescSize() uint16
- func (sb *SuperBlockOld) BlockSize() uint64
- func (sb *SuperBlockOld) BlocksCount() uint64
- func (sb *SuperBlockOld) BlocksPerGroup() uint32
- func (sb *SuperBlockOld) ClusterSize() uint64
- func (sb *SuperBlockOld) ClustersPerGroup() uint32
- func (sb *SuperBlockOld) CompatibleFeatures() CompatFeatures
- func (sb *SuperBlockOld) FirstDataBlock() uint32
- func (sb *SuperBlockOld) FreeBlocksCount() uint64
- func (sb *SuperBlockOld) FreeInodesCount() uint32
- func (sb *SuperBlockOld) IncompatibleFeatures() IncompatFeatures
- func (sb *SuperBlockOld) InodeSize() uint16
- func (sb *SuperBlockOld) InodesCount() uint32
- func (sb *SuperBlockOld) InodesPerGroup() uint32
- func (sb *SuperBlockOld) Magic() uint16
- func (sb *SuperBlockOld) MaxMountCount() uint16
- func (sb *SuperBlockOld) MountCount() uint16
- func (sb *SuperBlockOld) ReadOnlyCompatibleFeatures() RoCompatFeatures
- func (sb *SuperBlockOld) Revision() SbRevision
Constants ¶
const ( // BgInodeUninit indicates that inode table and bitmap are not initialized. BgInodeUninit uint16 = 0x1 // BgBlockUninit indicates that block bitmap is not initialized. BgBlockUninit uint16 = 0x2 // BgInodeZeroed indicates that inode table is zeroed. BgInodeZeroed uint16 = 0x4 )
These are the different block group flags.
const ( // MaxFileName is the maximum length of an ext fs file's name. MaxFileName = 255 // DirentSize is the size of ext dirent structures. DirentSize = 263 )
const ( // ExtentStructsSize is the size of all the three extent on-disk structs. ExtentStructsSize = 12 // ExtentMagic is the magic number which must be present in the header. ExtentMagic = 0xf30a )
const ( // InSync indicates that all writes to the file must be synchronous. InSync = 0x8 // InImmutable indicates that this file is immutable. InImmutable = 0x10 // InAppend indicates that this file can only be appended to. InAppend = 0x20 // InNoDump indicates that teh dump(1) utility should not dump this file. InNoDump = 0x40 // InNoAccessTime indicates that the access time of this inode must not be // updated. InNoAccessTime = 0x80 // InIndex indicates that this directory has hashed indexes. InIndex = 0x1000 // InJournalData indicates that file data must always be written through a // journal device. InJournalData = 0x4000 // InDirSync indicates that all the directory entiry data must be written // synchronously. InDirSync = 0x10000 // InTopDir indicates that this inode is at the top of the directory hierarchy. InTopDir = 0x20000 // InHugeFile indicates that this is a huge file. InHugeFile = 0x40000 // InExtents indicates that this inode uses extents. InExtents = 0x80000 // InExtendedAttr indicates that this inode stores a large extended attribute // value in its data blocks. InExtendedAttr = 0x200000 // InInline indicates that this inode has inline data. InInline = 0x10000000 // InReserved indicates that this inode is reserved for the ext4 library. InReserved = 0x80000000 )
Inode flags. This is not comprehensive and flags which were not used in the Linux kernel have been excluded.
const ( InUserReadFlagMask = 0x4BDFFF InUserWriteFlagMask = 0x4B80FF )
These masks define how users can view/modify inode flags. The rest of the flags are for internal kernel usage only.
const ( // SbDirPrealloc indicates directory preallocation. SbDirPrealloc = 0x1 // SbHasJournal indicates the presence of a journal. jbd2 should only work // with this being set. SbHasJournal = 0x4 // SbExtAttr indicates extended attributes support. SbExtAttr = 0x8 // SbResizeInode indicates that the fs has reserved GDT blocks (right after // group descriptors) for fs expansion. SbResizeInode = 0x10 // SbDirIndex indicates that the fs has directory indices. SbDirIndex = 0x20 // SbSparseV2 stands for Sparse superblock version 2. SbSparseV2 = 0x200 )
Superblock compatible features. This is not exhaustive, unused features are not listed.
const ( // SbDirentFileType indicates that directory entries record the file type. // We should use struct DirentNew for dirents then. SbDirentFileType = 0x2 // SbRecovery indicates that the filesystem needs recovery. SbRecovery = 0x4 // SbJournalDev indicates that the filesystem has a separate journal device. SbJournalDev = 0x8 // SbMetaBG indicates that the filesystem is using Meta block groups. Moves // the group descriptors from the congested first block group into the first // group of each metablock group to increase the maximum block groups limit // and hence support much larger filesystems. // // See https://www.kernel.org/doc/html/latest/filesystems/ext4/overview.html#meta-block-groups. SbMetaBG = 0x10 // SbExtents indicates that the filesystem uses extents. Must be set in ext4 // filesystems. SbExtents = 0x40 // SbIs64Bit indicates that this filesystem addresses blocks with 64-bits. // Hence can support 2^64 data blocks. SbIs64Bit = 0x80 // SbMMP indicates that this filesystem has multiple mount protection. // // See https://www.kernel.org/doc/html/latest/filesystems/ext4/globals.html#multiple-mount-protection. SbMMP = 0x100 // SbFlexBg indicates that this filesystem has flexible block groups. Several // block groups are tied into one logical block group so that all the metadata // for the block groups (bitmaps and inode tables) are close together for // faster loading. Consequently, large files will be continuous on disk. // However, this does not affect the placement of redundant superblocks and // group descriptors. // // See https://www.kernel.org/doc/html/latest/filesystems/ext4/overview.html#flexible-block-groups. SbFlexBg = 0x200 // SbLargeDir shows that large directory enabled. Directory htree can be 3 // levels deep. Directory htrees are allowed to be 2 levels deep otherwise. SbLargeDir = 0x4000 // SbInlineData allows inline data in inodes for really small files. SbInlineData = 0x8000 // SbEncrypted indicates that this fs contains encrypted inodes. SbEncrypted = 0x10000 )
Superblock incompatible features. This is not exhaustive, unused features are not listed.
const ( // SbSparse indicates sparse superblocks. Only groups with number either 0 or // a power of 3, 5, or 7 will have redundant copies of the superblock and // block descriptors. SbSparse = 0x1 // SbLargeFile indicates that this fs has been used to store a file >= 2GiB. SbLargeFile = 0x2 // SbHugeFile indicates that this fs contains files whose sizes are // represented in units of logicals blocks, not 512-byte sectors. SbHugeFile = 0x8 // SbGdtCsum indicates that group descriptors have checksums. SbGdtCsum = 0x10 // SbDirNlink indicates that the new subdirectory limit is 64,999. Ext3 has a // 32,000 subdirectory limit. SbDirNlink = 0x20 // SbExtraIsize indicates that large inodes exist on this filesystem. SbExtraIsize = 0x40 // SbHasSnapshot indicates the existence of a snapshot. SbHasSnapshot = 0x80 // SbQuota enables usage tracking for all quota types. SbQuota = 0x100 // SbBigalloc maps to the bigalloc feature. When set, the minimum allocation // unit becomes a cluster rather than a data block. Then block bitmaps track // clusters, not data blocks. // // See https://www.kernel.org/doc/html/latest/filesystems/ext4/overview.html#bigalloc. SbBigalloc = 0x200 // SbMetadataCsum indicates that the fs supports metadata checksumming. SbMetadataCsum = 0x400 // SbReadOnly marks this filesystem as readonly. Should refuse to mount in // read/write mode. SbReadOnly = 0x1000 )
Superblock readonly compatible features. This is not exhaustive, unused features are not listed.
const (
// OldInodeSize is the inode size in ext2/ext3.
OldInodeSize = 128
)
const (
// RootDirInode is the inode number of the root directory inode.
RootDirInode = 2
)
Special inodes. See https://www.kernel.org/doc/html/latest/filesystems/ext4/overview.html#special-inodes.
const (
// SbOffset is the absolute offset at which the superblock is placed.
SbOffset = 1024
)
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type BGFlags ¶
BGFlags represents all the different combinations of block group flags.
func BGFlagsFromInt ¶
BGFlagsFromInt converts the 16-bit flag representation to a BGFlags struct.
type BlockGroup ¶
type BlockGroup interface { // InodeTable returns the absolute block number of the block containing the // inode table. This points to an array of Inode structs. Inode tables are // statically allocated at mkfs time. The superblock records the number of // inodes per group (length of this table) and the size of each inode struct. InodeTable() uint64 // BlockBitmap returns the absolute block number of the block containing the // block bitmap. This bitmap tracks the usage of data blocks within this block // group and has its own checksum. BlockBitmap() uint64 // InodeBitmap returns the absolute block number of the block containing the // inode bitmap. This bitmap tracks the usage of this group's inode table // entries and has its own checksum. InodeBitmap() uint64 // ExclusionBitmap returns the absolute block number of the snapshot exclusion // bitmap. ExclusionBitmap() uint64 // FreeBlocksCount returns the number of free blocks in the group. FreeBlocksCount() uint32 // FreeInodesCount returns the number of free inodes in the group. FreeInodesCount() uint32 // DirectoryCount returns the number of inodes that represent directories // under this block group. DirectoryCount() uint32 // UnusedInodeCount returns the number of unused inodes beyond the last used // inode in this group's inode table. As a result, we needn’t scan past the // (InodesPerGroup - UnusedInodeCount())th entry in the inode table. UnusedInodeCount() uint32 // BlockBitmapChecksum returns the block bitmap checksum. This is calculated // using crc32c(FS UUID + group number + entire bitmap). BlockBitmapChecksum() uint32 // InodeBitmapChecksum returns the inode bitmap checksum. This is calculated // using crc32c(FS UUID + group number + entire bitmap). InodeBitmapChecksum() uint32 // Checksum returns this block group's checksum. // // If SbMetadataCsum feature is set: // - checksum is crc32c(FS UUID + group number + group descriptor // structure) & 0xFFFF. // // If SbGdtCsum feature is set: // - checksum is crc16(FS UUID + group number + group descriptor // structure). // // SbMetadataCsum and SbGdtCsum should not be both set. // If they are, Linux warns and asks to run fsck. Checksum() uint16 // Flags returns BGFlags which represents the block group flags. Flags() BGFlags }
BlockGroup represents a Linux ext block group descriptor. An ext file system is split into a series of block groups. This provides an access layer to information needed to access and use a block group.
Location:
- The block group descriptor table is always placed in the blocks immediately after the block containing the superblock.
- The 1st block group descriptor in the original table is in the (sb.FirstDataBlock() + 1)th block.
- See SuperBlock docs to see where the block group descriptor table is replicated.
- sb.BgDescSize() must be used as the block group descriptor entry size while reading the table from disk.
See https://www.kernel.org/doc/html/latest/filesystems/ext4/globals.html#block-group-descriptors.
type BlockGroup32Bit ¶
type BlockGroup32Bit struct { BlockBitmapLo uint32 InodeBitmapLo uint32 InodeTableLo uint32 FreeBlocksCountLo uint16 FreeInodesCountLo uint16 UsedDirsCountLo uint16 FlagsRaw uint16 ExcludeBitmapLo uint32 BlockBitmapChecksumLo uint16 InodeBitmapChecksumLo uint16 ItableUnusedLo uint16 ChecksumRaw uint16 }
BlockGroup32Bit emulates the first half of struct ext4_group_desc in fs/ext4/ext4.h. It is the block group descriptor struct for ext2, ext3 and 32-bit ext4 filesystems. It implements BlockGroup interface.
func (*BlockGroup32Bit) BlockBitmap ¶
func (bg *BlockGroup32Bit) BlockBitmap() uint64
BlockBitmap implements BlockGroup.BlockBitmap.
func (*BlockGroup32Bit) BlockBitmapChecksum ¶
func (bg *BlockGroup32Bit) BlockBitmapChecksum() uint32
BlockBitmapChecksum implements BlockGroup.BlockBitmapChecksum.
func (*BlockGroup32Bit) Checksum ¶
func (bg *BlockGroup32Bit) Checksum() uint16
Checksum implements BlockGroup.Checksum.
func (*BlockGroup32Bit) DirectoryCount ¶
func (bg *BlockGroup32Bit) DirectoryCount() uint32
DirectoryCount implements BlockGroup.DirectoryCount.
func (*BlockGroup32Bit) ExclusionBitmap ¶
func (bg *BlockGroup32Bit) ExclusionBitmap() uint64
ExclusionBitmap implements BlockGroup.ExclusionBitmap.
func (*BlockGroup32Bit) Flags ¶
func (bg *BlockGroup32Bit) Flags() BGFlags
Flags implements BlockGroup.Flags.
func (*BlockGroup32Bit) FreeBlocksCount ¶
func (bg *BlockGroup32Bit) FreeBlocksCount() uint32
FreeBlocksCount implements BlockGroup.FreeBlocksCount.
func (*BlockGroup32Bit) FreeInodesCount ¶
func (bg *BlockGroup32Bit) FreeInodesCount() uint32
FreeInodesCount implements BlockGroup.FreeInodesCount.
func (*BlockGroup32Bit) InodeBitmap ¶
func (bg *BlockGroup32Bit) InodeBitmap() uint64
InodeBitmap implements BlockGroup.InodeBitmap.
func (*BlockGroup32Bit) InodeBitmapChecksum ¶
func (bg *BlockGroup32Bit) InodeBitmapChecksum() uint32
InodeBitmapChecksum implements BlockGroup.InodeBitmapChecksum.
func (*BlockGroup32Bit) InodeTable ¶
func (bg *BlockGroup32Bit) InodeTable() uint64
InodeTable implements BlockGroup.InodeTable.
func (*BlockGroup32Bit) UnusedInodeCount ¶
func (bg *BlockGroup32Bit) UnusedInodeCount() uint32
UnusedInodeCount implements BlockGroup.UnusedInodeCount.
type BlockGroup64Bit ¶
type BlockGroup64Bit struct { // We embed the 32-bit struct here because 64-bit version is just an extension // of the 32-bit version. BlockGroup32Bit // 64-bit specific fields. BlockBitmapHi uint32 InodeBitmapHi uint32 InodeTableHi uint32 FreeBlocksCountHi uint16 FreeInodesCountHi uint16 UsedDirsCountHi uint16 ItableUnusedHi uint16 ExcludeBitmapHi uint32 BlockBitmapChecksumHi uint16 InodeBitmapChecksumHi uint16 // contains filtered or unexported fields }
BlockGroup64Bit emulates struct ext4_group_desc in fs/ext4/ext4.h. It is the block group descriptor struct for 64-bit ext4 filesystems. It implements BlockGroup interface. It is an extension of the 32-bit version of BlockGroup.
func (*BlockGroup64Bit) BlockBitmap ¶
func (bg *BlockGroup64Bit) BlockBitmap() uint64
BlockBitmap implements BlockGroup.BlockBitmap.
func (*BlockGroup64Bit) BlockBitmapChecksum ¶
func (bg *BlockGroup64Bit) BlockBitmapChecksum() uint32
BlockBitmapChecksum implements BlockGroup.BlockBitmapChecksum.
func (*BlockGroup64Bit) DirectoryCount ¶
func (bg *BlockGroup64Bit) DirectoryCount() uint32
DirectoryCount implements BlockGroup.DirectoryCount.
func (*BlockGroup64Bit) ExclusionBitmap ¶
func (bg *BlockGroup64Bit) ExclusionBitmap() uint64
ExclusionBitmap implements BlockGroup.ExclusionBitmap.
func (*BlockGroup64Bit) FreeBlocksCount ¶
func (bg *BlockGroup64Bit) FreeBlocksCount() uint32
FreeBlocksCount implements BlockGroup.FreeBlocksCount.
func (*BlockGroup64Bit) FreeInodesCount ¶
func (bg *BlockGroup64Bit) FreeInodesCount() uint32
FreeInodesCount implements BlockGroup.FreeInodesCount.
func (*BlockGroup64Bit) InodeBitmap ¶
func (bg *BlockGroup64Bit) InodeBitmap() uint64
InodeBitmap implements BlockGroup.InodeBitmap.
func (*BlockGroup64Bit) InodeBitmapChecksum ¶
func (bg *BlockGroup64Bit) InodeBitmapChecksum() uint32
InodeBitmapChecksum implements BlockGroup.InodeBitmapChecksum.
func (*BlockGroup64Bit) InodeTable ¶
func (bg *BlockGroup64Bit) InodeTable() uint64
InodeTable implements BlockGroup.InodeTable.
func (*BlockGroup64Bit) UnusedInodeCount ¶
func (bg *BlockGroup64Bit) UnusedInodeCount() uint32
UnusedInodeCount implements BlockGroup.UnusedInodeCount.
type CompatFeatures ¶
type CompatFeatures struct { DirPrealloc bool HasJournal bool ExtAttr bool ResizeInode bool DirIndex bool SparseV2 bool }
CompatFeatures represents a superblock's compatible feature set. If the kernel does not understand any of these feature, it can still read/write to this fs.
func CompatFeaturesFromInt ¶
func CompatFeaturesFromInt(f uint32) CompatFeatures
CompatFeaturesFromInt converts the integer representation of superblock compatible features to CompatFeatures struct.
func (CompatFeatures) ToInt ¶
func (f CompatFeatures) ToInt() uint32
ToInt converts superblock compatible features back to its 32-bit rep.
type Dirent ¶
type Dirent interface { // Inode returns the absolute inode number of the underlying inode. // Inode number 0 signifies an unused dirent. Inode() uint32 // RecordSize returns the record length of this dirent on disk. The next // dirent in the dirent list should be read after these many bytes from // the current dirent. Must be a multiple of 4. RecordSize() uint16 // FileName returns the name of the file. Can be at most 255 is length. FileName() string // FileType returns the inode type of the underlying inode. This is a // performance hack so that we do not have to read the underlying inode struct // to know the type of inode. This will only work when the SbDirentFileType // feature is set. If not, the second returned value will be false indicating // that user code has to use the inode mode to extract the file type. FileType() (fs.InodeType, bool) }
The Dirent interface should be implemented by structs representing ext directory entries. These are for the linear classical directories which just store a list of dirent structs. A directory is a series of data blocks where is each data block contains a linear array of dirents. The last entry of the block has a record size that takes it to the end of the block. The end of the directory is when you read dirInode.Size() bytes from the blocks.
See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#linear-classic-directories.
type DirentNew ¶
type DirentNew struct { InodeNumber uint32 RecordLength uint16 NameLength uint8 FileTypeRaw uint8 FileNameRaw [MaxFileName]byte }
DirentNew represents the ext4 directory entry struct. This emulates Linux's ext4_dir_entry_2 struct. The FileName can not be more than 255 bytes so we only need 8 bits to store the NameLength. As a result, NameLength has been shortened and the other 8 bits are used to encode the file type. Use the FileTypeRaw field only if the SbDirentFileType feature is set.
Note: This struct can be of variable size on disk. The one described below is of maximum size and the FileName beyond NameLength bytes might contain garbage.
func (*DirentNew) RecordSize ¶
RecordSize implements Dirent.RecordSize.
type DirentOld ¶
type DirentOld struct { InodeNumber uint32 RecordLength uint16 NameLength uint16 FileNameRaw [MaxFileName]byte }
DirentOld represents the old directory entry struct which does not contain the file type. This emulates Linux's ext4_dir_entry struct.
Note: This struct can be of variable size on disk. The one described below is of maximum size and the FileName beyond NameLength bytes might contain garbage.
func (*DirentOld) RecordSize ¶
RecordSize implements Dirent.RecordSize.
type Extent ¶
Extent represents the ext4_extent struct in ext4. Only present in leaf nodes. Sorted in ascending order based on FirstFileBlock since Linux does a binary search on this. This points to an array of data blocks containing the file data. It covers `Length` data blocks starting from `StartBlock`.
func (*Extent) PhysicalBlock ¶
PhysicalBlock implements ExtentEntry.PhysicalBlock. It returns the physical block number of the first data block this extent covers.
type ExtentEntry ¶
type ExtentEntry interface { // FileBlock returns the first file block number covered by this entry. FileBlock() uint32 // PhysicalBlock returns the child physical block that this entry points to. PhysicalBlock() uint64 }
ExtentEntry reprsents an extent tree node entry. The entry can either be an ExtentIdx or Extent itself. This exists to simplify navigation logic.
type ExtentEntryPair ¶
type ExtentEntryPair struct { // Entry points to the child node on disk. Entry ExtentEntry // Node points to child node in memory. Is nil if the current node is a leaf. Node *ExtentNode }
ExtentEntryPair couples an in-memory ExtendNode with the ExtentEntry that points to it. We want to cache these structs in memory to avoid repeated disk reads.
Note: This struct itself does not represent an on-disk struct.
type ExtentHeader ¶
type ExtentHeader struct { // Magic in the extent magic number, must be 0xf30a. Magic uint16 // NumEntries indicates the number of valid entries following the header. NumEntries uint16 // MaxEntries that could follow the header. Used while adding entries. MaxEntries uint16 // Height represents the distance of this node from the farthest leaf. Please // note that Linux incorrectly calls this `Depth` (which means the distance // of the node from the root). Height uint16 // contains filtered or unexported fields }
ExtentHeader emulates the ext4_extent_header struct in ext4. Each extent tree node begins with this and is followed by `NumEntries` number of:
- Extent if `Depth` == 0
- ExtentIdx otherwise
type ExtentIdx ¶
type ExtentIdx struct { FirstFileBlock uint32 ChildBlockLo uint32 ChildBlockHi uint16 // contains filtered or unexported fields }
ExtentIdx emulates the ext4_extent_idx struct in ext4. Only present in internal nodes. Sorted in ascending order based on FirstFileBlock since Linux does a binary search on this. This points to a block containing the child node.
func (*ExtentIdx) PhysicalBlock ¶
PhysicalBlock implements ExtentEntry.PhysicalBlock. It returns the physical block number of the child block.
type ExtentNode ¶
type ExtentNode struct { Header ExtentHeader Entries []ExtentEntryPair }
ExtentNode represents an extent tree node. For internal nodes, all Entries will be ExtendIdxs. For leaf nodes, they will all be Extents.
Note: This struct itself does not represent an on-disk struct.
type IncompatFeatures ¶
type IncompatFeatures struct { DirentFileType bool Recovery bool JournalDev bool MetaBG bool Extents bool Is64Bit bool MMP bool FlexBg bool LargeDir bool InlineData bool Encrypted bool }
IncompatFeatures represents a superblock's incompatible feature set. If the kernel does not understand any of these feature, it should refuse to mount.
func IncompatFeaturesFromInt ¶
func IncompatFeaturesFromInt(f uint32) IncompatFeatures
IncompatFeaturesFromInt converts the integer representation of superblock incompatible features to IncompatFeatures struct.
func (IncompatFeatures) ToInt ¶
func (f IncompatFeatures) ToInt() uint32
ToInt converts superblock incompatible features back to its 32-bit rep.
type Inode ¶
type Inode interface { // Mode returns the linux file mode which is majorly used to extract // information like: // - File permissions (read/write/execute by user/group/others). // - Sticky, set UID and GID bits. // - File type. // // Masks to extract this information are provided in pkg/abi/linux/file.go. Mode() linux.FileMode // UID returns the owner UID. UID() auth.KUID // GID returns the owner GID. GID() auth.KGID // Size returns the size of the file in bytes. Size() uint64 // InodeSize returns the size of this inode struct in bytes. // In ext2 and ext3, the inode struct and inode disk record size was fixed at // 128 bytes. Ext4 makes it possible for the inode struct to be bigger. // However, accessing any field beyond the 128 bytes marker must be verified // using this method. InodeSize() uint16 // AccessTime returns the last access time. Shows when the file was last read. // // If InExtendedAttr is set, then this should NOT be used because the // underlying field is used to store the extended attribute value checksum. AccessTime() time.Time // ChangeTime returns the last change time. Shows when the file meta data // (like permissions) was last changed. // // If InExtendedAttr is set, then this should NOT be used because the // underlying field is used to store the lower 32 bits of the attribute // value’s reference count. ChangeTime() time.Time // ModificationTime returns the last modification time. Shows when the file // content was last modified. // // If InExtendedAttr is set, then this should NOT be used because // the underlying field contains the number of the inode that owns the // extended attribute. ModificationTime() time.Time // DeletionTime returns the deletion time. Inodes are marked as deleted by // writing to the underlying field. FS tools can restore files until they are // actually overwritten. DeletionTime() time.Time // LinksCount returns the number of hard links to this inode. // // Normally there is an upper limit on the number of hard links: // - ext2/ext3 = 32,000 // - ext4 = 65,000 // // This implies that an ext4 directory cannot have more than 64,998 // subdirectories because each subdirectory will have a hard link to the // directory via the `..` entry. The directory has hard link via the `.` entry // of its own. And finally the inode is initiated with 1 hard link (itself). // // The underlying value is reset to 1 if all the following hold: // - Inode is a directory. // - SbDirNlink is enabled. // - Number of hard links is incremented past 64,999. // Hard link value of 1 for a directory would indicate that the number of hard // links is unknown because a directory can have minimum 2 hard links (itself // and `.` entry). LinksCount() uint16 // Flags returns InodeFlags which represents the inode flags. Flags() InodeFlags // Data returns the underlying inode.i_block array as a slice so it's // modifiable. This field is special and is used to store various kinds of // things depending on the filesystem version and inode type. The underlying // field name in Linux is a little misleading. // - In ext2/ext3, it contains the block map. // - In ext4, it contains the extent tree root node. // - For inline files, it contains the file contents. // - For symlinks, it contains the link path (if it fits here). // // See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#the-contents-of-inode-i-block. Data() []byte }
The Inode interface must be implemented by structs representing ext inodes. The inode stores all the metadata pertaining to the file (except for the file name which is held by the directory entry). It does NOT expose all fields and should be extended if need be.
Some file systems (e.g. FAT) use the directory entry to store all this information. Ext file systems do not so that they can support hard links. However, ext4 cheats a little bit and duplicates the file type in the directory entry for performance gains.
See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#index-nodes.
type InodeFlags ¶
type InodeFlags struct { Sync bool Immutable bool Append bool NoDump bool NoAccessTime bool Index bool JournalData bool DirSync bool TopDir bool HugeFile bool Extents bool ExtendedAttr bool Inline bool Reserved bool }
InodeFlags represents all possible combinations of inode flags. It aims to cover the bit masks and provide a more user-friendly interface.
func InodeFlagsFromInt ¶
func InodeFlagsFromInt(f uint32) InodeFlags
InodeFlagsFromInt converts the integer representation of inode flags to a InodeFlags struct.
func (InodeFlags) ToInt ¶
func (f InodeFlags) ToInt() uint32
ToInt converts inode flags back to its 32-bit rep.
type InodeNew ¶
type InodeNew struct { InodeOld ExtraInodeSize uint16 ChecksumHi uint16 ChangeTimeExtra uint32 ModificationTimeExtra uint32 AccessTimeExtra uint32 CreationTime uint32 CreationTimeExtra uint32 VersionHi uint32 ProjectID uint32 }
InodeNew represents ext4 inode structure which can be bigger than OldInodeSize. The actual size of this struct should be determined using inode.ExtraInodeSize. Accessing any field here should be verified with the actual size. The extra space between the end of the inode struct and end of the inode record can be used to store extended attr.
If the TimeExtra fields are in scope, the lower 2 bits of those are used to extend their counter part to be 34 bits wide; the rest (upper) 30 bits are used to provide nanoscond precision. Hence, these timestamps will now overflow in May 2446. See https://www.kernel.org/doc/html/latest/filesystems/ext4/dynamic.html#inode-timestamps.
func (*InodeNew) AccessTime ¶
AccessTime implements Inode.AccessTime.
func (*InodeNew) ChangeTime ¶
ChangeTime implements Inode.ChangeTime.
func (*InodeNew) ModificationTime ¶
ModificationTime implements Inode.ModificationTime.
type InodeOld ¶
type InodeOld struct { ModeRaw uint16 UIDLo uint16 SizeLo uint32 // The time fields are signed integers because they could be negative to // represent time before the epoch. AccessTimeRaw int32 ChangeTimeRaw int32 ModificationTimeRaw int32 DeletionTimeRaw int32 GIDLo uint16 LinksCountRaw uint16 BlocksCountLo uint32 FlagsRaw uint32 VersionLo uint32 // This is OS dependent. DataRaw [60]byte Generation uint32 FileACLLo uint32 SizeHi uint32 ObsoFaddr uint32 // OS dependent fields have been inlined here. BlocksCountHi uint16 FileACLHi uint16 UIDHi uint16 GIDHi uint16 ChecksumLo uint16 // contains filtered or unexported fields }
InodeOld implements Inode interface. It emulates ext2/ext3 inode struct. Inode struct size and record size are both 128 bytes for this.
All fields representing time are in seconds since the epoch. Which means that they will overflow in January 2038.
func (*InodeOld) AccessTime ¶
AccessTime implements Inode.AccessTime.
func (*InodeOld) ChangeTime ¶
ChangeTime implements Inode.ChangeTime.
func (*InodeOld) DeletionTime ¶
DeletionTime implements Inode.DeletionTime.
func (*InodeOld) LinksCount ¶
LinksCount implements Inode.LinksCount.
func (*InodeOld) ModificationTime ¶
ModificationTime implements Inode.ModificationTime.
type RoCompatFeatures ¶
type RoCompatFeatures struct { Sparse bool LargeFile bool HugeFile bool GdtCsum bool DirNlink bool ExtraIsize bool HasSnapshot bool Quota bool Bigalloc bool MetadataCsum bool ReadOnly bool }
RoCompatFeatures represents a superblock's readonly compatible feature set. If the kernel does not understand any of these feature, it can still mount readonly. But if the user wants to mount read/write, the kernel should refuse to mount.
func RoCompatFeaturesFromInt ¶
func RoCompatFeaturesFromInt(f uint32) RoCompatFeatures
RoCompatFeaturesFromInt converts the integer representation of superblock readonly compatible features to RoCompatFeatures struct.
func (RoCompatFeatures) ToInt ¶
func (f RoCompatFeatures) ToInt() uint32
ToInt converts superblock readonly compatible features to its 32-bit rep.
type SbRevision ¶
type SbRevision uint32
SbRevision is the type for superblock revisions.
const ( // OldRev is the good old (original) format. OldRev SbRevision = 0 // DynamicRev is v2 format w/ dynamic inode sizes. DynamicRev SbRevision = 1 )
Super block revisions.
type SuperBlock ¶
type SuperBlock interface { // InodesCount returns the total number of inodes in this filesystem. InodesCount() uint32 // BlocksCount returns the total number of data blocks in this filesystem. BlocksCount() uint64 // FreeBlocksCount returns the number of free blocks in this filesystem. FreeBlocksCount() uint64 // FreeInodesCount returns the number of free inodes in this filesystem. FreeInodesCount() uint32 // MountCount returns the number of mounts since the last fsck. MountCount() uint16 // MaxMountCount returns the number of mounts allowed beyond which a fsck is // needed. MaxMountCount() uint16 // FirstDataBlock returns the absolute block number of the first data block, // which contains the super block itself. // // If the filesystem has 1kb data blocks then this should return 1. For all // other configurations, this typically returns 0. FirstDataBlock() uint32 // BlockSize returns the size of one data block in this filesystem. // This can be calculated by 2^(10 + sb.s_log_block_size). This ensures that // the smallest block size is 1kb. BlockSize() uint64 // BlocksPerGroup returns the number of data blocks in a block group. BlocksPerGroup() uint32 // ClusterSize returns block cluster size (set during mkfs time by admin). // This can be calculated by 2^(10 + sb.s_log_cluster_size). This ensures that // the smallest cluster size is 1kb. // // sb.s_log_cluster_size must equal sb.s_log_block_size if bigalloc feature // is NOT set and consequently BlockSize() = ClusterSize() in that case. ClusterSize() uint64 // ClustersPerGroup returns: // - number of clusters per group if bigalloc is enabled. // - BlocksPerGroup() otherwise. ClustersPerGroup() uint32 // InodeSize returns the size of the inode disk record size in bytes. Use this // to iterate over inode arrays on disk. // // In ext2 and ext3: // - Each inode had a disk record of 128 bytes. // - The inode struct size was fixed at 128 bytes. // // In ext4 its possible to allocate larger on-disk inodes: // - Inode disk record size = sb.s_inode_size (function return value). // = 256 (default) // - Inode struct size = 128 + inode.i_extra_isize. // = 128 + 32 = 160 (default) InodeSize() uint16 // InodesPerGroup returns the number of inodes in a block group. InodesPerGroup() uint32 // BgDescSize returns the size of the block group descriptor struct. // // In ext2, ext3, ext4 (without 64-bit feature), the block group descriptor // is only 32 bytes long. // In ext4 with 64-bit feature, the block group descriptor expands to AT LEAST // 64 bytes. It might be bigger than that. BgDescSize() uint16 // CompatibleFeatures returns the CompatFeatures struct which holds all the // compatible features this fs supports. CompatibleFeatures() CompatFeatures // IncompatibleFeatures returns the CompatFeatures struct which holds all the // incompatible features this fs supports. IncompatibleFeatures() IncompatFeatures // ReadOnlyCompatibleFeatures returns the CompatFeatures struct which holds all the // readonly compatible features this fs supports. ReadOnlyCompatibleFeatures() RoCompatFeatures // Magic() returns the magic signature which must be 0xef53. Magic() uint16 // Revision returns the superblock revision. Superblock struct fields from // offset 0x54 till 0x150 should only be used if superblock has DynamicRev. Revision() SbRevision }
SuperBlock should be implemented by structs representing the ext superblock. The superblock holds a lot of information about the enclosing filesystem. This interface aims to provide access methods to important information held by the superblock. It does NOT expose all fields of the superblock, only the ones necessary. This can be expanded when need be.
Location and replication:
- The superblock is located at offset 1024 in block group 0.
- Redundant copies of the superblock and group descriptors are kept in all groups if SbSparse feature flag is NOT set. If it is set, the replicas only exist in groups whose group number is either 0 or a power of 3, 5, or 7.
- There is also a sparse superblock feature v2 in which there are just two replicas saved in the block groups pointed by sb.s_backup_bgs.
Replicas should eventually be updated if the superblock is updated.
See https://www.kernel.org/doc/html/latest/filesystems/ext4/globals.html#super-block.
type SuperBlock32Bit ¶
type SuperBlock32Bit struct { // We embed the old superblock struct here because the 32-bit version is just // an extension of the old version. SuperBlockOld FirstInode uint32 InodeSizeRaw uint16 BlockGroupNumber uint16 FeatureCompat uint32 FeatureIncompat uint32 FeatureRoCompat uint32 UUID [16]byte VolumeName [16]byte LastMounted [64]byte AlgoUsageBitmap uint32 PreallocBlocks uint8 PreallocDirBlocks uint8 ReservedGdtBlocks uint16 JournalUUID [16]byte JournalInum uint32 JournalDev uint32 LastOrphan uint32 HashSeed [4]uint32 DefaultHashVersion uint8 JnlBackupType uint8 BgDescSizeRaw uint16 DefaultMountOpts uint32 FirstMetaBg uint32 MkfsTime uint32 JnlBlocks [17]uint32 }
SuperBlock32Bit implements SuperBlock and represents the 32-bit version of the ext4_super_block struct in fs/ext4/ext4.h. Should be used only if RevLevel = DynamicRev and 64-bit feature is disabled.
func (*SuperBlock32Bit) CompatibleFeatures ¶
func (sb *SuperBlock32Bit) CompatibleFeatures() CompatFeatures
CompatibleFeatures implements SuperBlock.CompatibleFeatures.
func (*SuperBlock32Bit) IncompatibleFeatures ¶
func (sb *SuperBlock32Bit) IncompatibleFeatures() IncompatFeatures
IncompatibleFeatures implements SuperBlock.IncompatibleFeatures.
func (*SuperBlock32Bit) InodeSize ¶
func (sb *SuperBlock32Bit) InodeSize() uint16
InodeSize implements SuperBlock.InodeSize.
func (*SuperBlock32Bit) ReadOnlyCompatibleFeatures ¶
func (sb *SuperBlock32Bit) ReadOnlyCompatibleFeatures() RoCompatFeatures
ReadOnlyCompatibleFeatures implements SuperBlock.ReadOnlyCompatibleFeatures.
type SuperBlock64Bit ¶
type SuperBlock64Bit struct { // We embed the 32-bit struct here because 64-bit version is just an extension // of the 32-bit version. SuperBlock32Bit BlocksCountHi uint32 ReservedBlocksCountHi uint32 FreeBlocksCountHi uint32 MinInodeSize uint16 WantInodeSize uint16 Flags uint32 RaidStride uint16 MmpInterval uint16 MmpBlock uint64 RaidStripeWidth uint32 LogGroupsPerFlex uint8 ChecksumType uint8 KbytesWritten uint64 SnapshotInum uint32 SnapshotID uint32 SnapshotRsrvBlocksCount uint64 SnapshotList uint32 ErrorCount uint32 FirstErrorTime uint32 FirstErrorInode uint32 FirstErrorBlock uint64 FirstErrorFunction [32]byte FirstErrorLine uint32 LastErrorTime uint32 LastErrorInode uint32 LastErrorLine uint32 LastErrorBlock uint64 LastErrorFunction [32]byte MountOpts [64]byte UserQuotaInum uint32 GroupQuotaInum uint32 OverheadBlocks uint32 BackupBgs [2]uint32 EncryptAlgos [4]uint8 EncryptPwSalt [16]uint8 LostFoundInode uint32 ProjectQuotaInode uint32 ChecksumSeed uint32 WtimeHi uint8 MtimeHi uint8 MkfsTimeHi uint8 LastCheckHi uint8 FirstErrorTimeHi uint8 LastErrorTimeHi uint8 Encoding uint16 EncodingFlags uint16 Checksum uint32 // contains filtered or unexported fields }
SuperBlock64Bit implements SuperBlock and represents the 64-bit version of the ext4_super_block struct in fs/ext4/ext4.h. This sums up to be exactly 1024 bytes (smallest possible block size) and hence the superblock always fits in no more than one data block. Should only be used when the 64-bit feature is set.
func (*SuperBlock64Bit) BgDescSize ¶
func (sb *SuperBlock64Bit) BgDescSize() uint16
BgDescSize implements SuperBlock.BgDescSize.
func (*SuperBlock64Bit) BlocksCount ¶
func (sb *SuperBlock64Bit) BlocksCount() uint64
BlocksCount implements SuperBlock.BlocksCount.
func (*SuperBlock64Bit) FreeBlocksCount ¶
func (sb *SuperBlock64Bit) FreeBlocksCount() uint64
FreeBlocksCount implements SuperBlock.FreeBlocksCount.
type SuperBlockOld ¶
type SuperBlockOld struct { InodesCountRaw uint32 BlocksCountLo uint32 ReservedBlocksCount uint32 FreeBlocksCountLo uint32 FreeInodesCountRaw uint32 FirstDataBlockRaw uint32 LogBlockSize uint32 LogClusterSize uint32 BlocksPerGroupRaw uint32 ClustersPerGroupRaw uint32 InodesPerGroupRaw uint32 Mtime uint32 Wtime uint32 MountCountRaw uint16 MaxMountCountRaw uint16 MagicRaw uint16 State uint16 Errors uint16 MinorRevLevel uint16 LastCheck uint32 CheckInterval uint32 CreatorOS uint32 RevLevel uint32 DefResUID uint16 DefResGID uint16 }
SuperBlockOld implements SuperBlock and represents the old version of the superblock struct. Should be used only if RevLevel = OldRev.
func (*SuperBlockOld) BgDescSize ¶
func (sb *SuperBlockOld) BgDescSize() uint16
BgDescSize implements SuperBlock.BgDescSize.
func (*SuperBlockOld) BlockSize ¶
func (sb *SuperBlockOld) BlockSize() uint64
BlockSize implements SuperBlock.BlockSize.
func (*SuperBlockOld) BlocksCount ¶
func (sb *SuperBlockOld) BlocksCount() uint64
BlocksCount implements SuperBlock.BlocksCount.
func (*SuperBlockOld) BlocksPerGroup ¶
func (sb *SuperBlockOld) BlocksPerGroup() uint32
BlocksPerGroup implements SuperBlock.BlocksPerGroup.
func (*SuperBlockOld) ClusterSize ¶
func (sb *SuperBlockOld) ClusterSize() uint64
ClusterSize implements SuperBlock.ClusterSize.
func (*SuperBlockOld) ClustersPerGroup ¶
func (sb *SuperBlockOld) ClustersPerGroup() uint32
ClustersPerGroup implements SuperBlock.ClustersPerGroup.
func (*SuperBlockOld) CompatibleFeatures ¶
func (sb *SuperBlockOld) CompatibleFeatures() CompatFeatures
CompatibleFeatures implements SuperBlock.CompatibleFeatures.
func (*SuperBlockOld) FirstDataBlock ¶
func (sb *SuperBlockOld) FirstDataBlock() uint32
FirstDataBlock implements SuperBlock.FirstDataBlock.
func (*SuperBlockOld) FreeBlocksCount ¶
func (sb *SuperBlockOld) FreeBlocksCount() uint64
FreeBlocksCount implements SuperBlock.FreeBlocksCount.
func (*SuperBlockOld) FreeInodesCount ¶
func (sb *SuperBlockOld) FreeInodesCount() uint32
FreeInodesCount implements SuperBlock.FreeInodesCount.
func (*SuperBlockOld) IncompatibleFeatures ¶
func (sb *SuperBlockOld) IncompatibleFeatures() IncompatFeatures
IncompatibleFeatures implements SuperBlock.IncompatibleFeatures.
func (*SuperBlockOld) InodeSize ¶
func (sb *SuperBlockOld) InodeSize() uint16
InodeSize implements SuperBlock.InodeSize.
func (*SuperBlockOld) InodesCount ¶
func (sb *SuperBlockOld) InodesCount() uint32
InodesCount implements SuperBlock.InodesCount.
func (*SuperBlockOld) InodesPerGroup ¶
func (sb *SuperBlockOld) InodesPerGroup() uint32
InodesPerGroup implements SuperBlock.InodesPerGroup.
func (*SuperBlockOld) Magic ¶
func (sb *SuperBlockOld) Magic() uint16
Magic implements SuperBlock.Magic.
func (*SuperBlockOld) MaxMountCount ¶
func (sb *SuperBlockOld) MaxMountCount() uint16
MaxMountCount implements SuperBlock.MaxMountCount.
func (*SuperBlockOld) MountCount ¶
func (sb *SuperBlockOld) MountCount() uint16
MountCount implements SuperBlock.MountCount.
func (*SuperBlockOld) ReadOnlyCompatibleFeatures ¶
func (sb *SuperBlockOld) ReadOnlyCompatibleFeatures() RoCompatFeatures
ReadOnlyCompatibleFeatures implements SuperBlock.ReadOnlyCompatibleFeatures.
func (*SuperBlockOld) Revision ¶
func (sb *SuperBlockOld) Revision() SbRevision
Revision implements SuperBlock.Revision.