README

Build Status Coverage Status GoDoc

Overview

This package allows you to browse an ext4 filesystem directly. It does not use FUSE or touch the kernel, so no privileges are required.

This package also exposes the data in the journal (if one is available).

Example

Recursively walk all of the files in the filesystem:

inodeNumber := InodeRootDirectory

filepath := path.Join(assetsPath, "hierarchy_32.ext4")

f, err := os.Open(filepath)
log.PanicIf(err)

defer f.Close()

_, err = f.Seek(Superblock0Offset, io.SeekStart)
log.PanicIf(err)

sb, err := NewSuperblockWithReader(f)
log.PanicIf(err)

bgdl, err := NewBlockGroupDescriptorListWithReadSeeker(f, sb)
log.PanicIf(err)

bgd, err := bgdl.GetWithAbsoluteInode(inodeNumber)
log.PanicIf(err)

dw, err := NewDirectoryWalk(f, bgd, inodeNumber)
log.PanicIf(err)

allEntries := make([]string, 0)

for {
	fullPath, de, err := dw.Next()
	if err == io.EOF {
		break
	} else if err != nil {
		log.Panic(err)
	}

	description := fmt.Sprintf("%s: %s", fullPath, de.String())
	allEntries = append(allEntries, description)
}

sort.Strings(allEntries)

for _, entryDescription := range allEntries {
	fmt.Println(entryDescription)
}

// Output:
//
// directory1/fortune1: DirectoryEntry<NAME=[fortune1] INODE=(15) TYPE=[regular]-(1)>
// directory1/fortune2: DirectoryEntry<NAME=[fortune2] INODE=(14) TYPE=[regular]-(1)>
// directory1/fortune5: DirectoryEntry<NAME=[fortune5] INODE=(20) TYPE=[regular]-(1)>
// directory1/fortune6: DirectoryEntry<NAME=[fortune6] INODE=(21) TYPE=[regular]-(1)>
// directory1/subdirectory1/fortune3: DirectoryEntry<NAME=[fortune3] INODE=(17) TYPE=[regular]-(1)>
// directory1/subdirectory1/fortune4: DirectoryEntry<NAME=[fortune4] INODE=(18) TYPE=[regular]-(1)>
// directory1/subdirectory1: DirectoryEntry<NAME=[subdirectory1] INODE=(16) TYPE=[directory]-(2)>
// directory1/subdirectory2/fortune7: DirectoryEntry<NAME=[fortune7] INODE=(22) TYPE=[regular]-(1)>
// directory1/subdirectory2/fortune8: DirectoryEntry<NAME=[fortune8] INODE=(23) TYPE=[regular]-(1)>
// directory1/subdirectory2: DirectoryEntry<NAME=[subdirectory2] INODE=(19) TYPE=[directory]-(2)>
// directory1: DirectoryEntry<NAME=[directory1] INODE=(13) TYPE=[directory]-(2)>
// directory2/fortune10: DirectoryEntry<NAME=[fortune10] INODE=(26) TYPE=[regular]-(1)>
// directory2/fortune9: DirectoryEntry<NAME=[fortune9] INODE=(25) TYPE=[regular]-(1)>
// directory2: DirectoryEntry<NAME=[directory2] INODE=(24) TYPE=[directory]-(2)>
// lost+found: DirectoryEntry<NAME=[lost+found] INODE=(11) TYPE=[directory]-(2)>
// thejungle.txt: DirectoryEntry<NAME=[thejungle.txt] INODE=(12) TYPE=[regular]-(1)>

This example and others are documented here.

Notes

  • Modern filesystems are supported, including both 32-bit and 64-bit addressing. Obscure filesystem options may not be compatible. See the compatibility assertions in NewSuperblockWithReader.
    • 64-bit addressing should be fine, as the high addressing should likely be zero when 64-bit addressing is turned-off (which is primarily what our unit-tests test with). However, the available documentation is limited on the subject. It's specifically not clear which of the various high/low addresses are affected by the 64-bit mode.

To Do

  • Finish implementing checksum calculation and validation. Currently all checksums are readable but with no additional functionality.

Documentation

Index

Examples

Constants

View Source
const (
	BgdFlagInodeTableAndBitmapNotInitialized = uint16(0x1)
	BgdFlagBitmapNotInitialized              = uint16(0x2)
	BgdFlagInodeTableZeroed                  = uint16(0x4)
)
View Source
const (
	Ext4FilenameMaxLen     = 255
	Ext4DirectoryEntrySize = Ext4FilenameMaxLen + 8
)
View Source
const (
	FileTypeUnknown         = uint8(0x0)
	FileTypeRegular         = uint8(0x1)
	FileTypeDirectory       = uint8(0x2)
	FileTypeCharacterDevice = uint8(0x3)
	FileTypeBlockDevice     = uint8(0x4)
	FileTypeFifo            = uint8(0x5)
	FileTypeSocket          = uint8(0x6)
	FileTypeSymbolicLink    = uint8(0x7)
)

    File types.

    View Source
    const (
    	ExtentMagic            = uint16(0xf30A)
    	ExtentHeaderSize       = 12
    	ExtentIndexAndLeafSize = 12
    )
    View Source
    const (
    	InodeDefectiveBlocks          = 1
    	InodeRootDirectory            = 2
    	InodeUserQuota                = 3
    	InodeGroupQuota               = 4
    	InodeBootLoader               = 5
    	InodeUndeleteDirectory        = 6
    	InodeReservedGroupDescriptors = 7
    	InodeJournal                  = 8
    	InodeExclude                  = 9
    	InodeReplica                  = 10
    )

      Reserved inodes.

      View Source
      const (
      	Ext4NdirBlocks = 12
      	Ext4IndBlock   = Ext4NdirBlocks
      	Ext4DindBlock  = (Ext4IndBlock + 1)
      	Ext4TindBlock  = (Ext4DindBlock + 1)
      	Ext4NBlocks    = (Ext4TindBlock + 1)
      )
      View Source
      const (
      	InodeFlagSecrm           = 0x1
      	InodeFlagUnrm            = 0x2
      	InodeFlagCompr           = 0x4
      	InodeFlagSync            = 0x8
      	InodeFlagImmutable       = 0x10
      	InodeFlagAppend          = 0x20
      	InodeFlagNodump          = 0x40
      	InodeFlagNoatime         = 0x80
      	InodeFlagDirty           = 0x100
      	InodeFlagComprblk        = 0x200
      	InodeFlagNocompr         = 0x400
      	InodeFlagEncrypt         = 0x800
      	InodeFlagIndex           = 0x1000
      	InodeFlagImagic          = 0x2000
      	InodeFlagJournalData     = 0x4000
      	InodeFlagNotail          = 0x8000
      	InodeFlagDirsync         = 0x10000
      	InodeFlagTopdir          = 0x20000
      	InodeFlagHugeFile        = 0x40000
      	InodeFlagExtents         = 0x80000
      	InodeFlagEaInode         = 0x200000
      	InodeFlagEofblocks       = 0x400000
      	InodeFlagSnapfile        = 0x01000000
      	InodeFlagSnapfileDeleted = 0x04000000
      	InodeFlagSnapfileShrunk  = 0x08000000
      	InodeFlagInlineData      = 0x10000000
      	InodeFlagProjinherit     = 0x20000000
      )
      View Source
      const (
      	Ext4Magic = 0xef53
      
      	SuperblockSize = 1024
      
      	// The first superblock is after the bootloader code.
      	Superblock0Offset = int64(1024)
      )
      View Source
      const (
      	SbStateCleanlyUnmounted      = 0x0001
      	SbStateErrorsDetected        = 0x0002
      	SbStateOrphansBeingRecovered = 0x0004
      )
      View Source
      const (
      	SbErrorsContinue        = 1
      	SbErrorsRemountReadonly = 2
      	SbErrorsPanic           = 3
      )
      View Source
      const (
      	SbOsLinux   = 0
      	SbOsHurd    = 1
      	SbOsMasix   = 2
      	SbOsFreebsd = 3
      	SbOsLites   = 4
      )
      View Source
      const (
      	SbRevlevelGoodOldRev = 0
      	SbRevlevelDynamicRev = 1
      )
      View Source
      const (
      	SbDefHashVersionLegacy          = 0x0
      	SbDefHashVersionHalfMd4         = 0x1
      	SbDefHashVersionTea             = 0x2
      	SbDefHashVersionLegacyUnsigned  = 0x3
      	SbDefHashVersionHalfMd4Unsigned = 0x4
      	SbDefHashVersionTeaUnsigned     = 0x5
      )
      View Source
      const (
      	SbMountOptionDebug         = uint32(0x001)
      	SbMountOptionBsdGroups     = uint32(0x002)
      	SbMountOptionXattrUser     = uint32(0x004)
      	SbMountOptionAcl           = uint32(0x008)
      	SbMountOptionUid16         = uint32(0x010)
      	SbMountOptionJmodeData     = uint32(0x020)
      	SbMountOptionJmodeOrdered  = uint32(0x040)
      	SbMountOptionJmodeWback    = uint32(0x060)
      	SbMountOptionNoBarrier     = uint32(0x100)
      	SbMountOptionBlockValidity = uint32(0x200)
      	SbMountOptionDiscard       = uint32(0x400)
      	SbMountOptionNoDelAlloc    = uint32(0x800)
      )
      View Source
      const (
      	SbFlagSignedDirectoryHash   = uint32(0x1)
      	SbFlagUnsignedDirectoryHash = uint32(0x2)
      	SbFlagTestDevelopmentCode   = uint32(0x4)
      )
      View Source
      const (
      	SbEncryptAlgoInvalid   = uint8(0)
      	SbEncryptAlgoAes256Xt  = uint8(1)
      	SbEncryptAlgoAes256Gcm = uint8(2)
      	SbEncryptAlgoAes256Cbc = uint8(3)
      )
      View Source
      const (
      	// COMPAT_DIR_PREALLOC
      	SbFeatureCompatDirPrealloc = uint32(0x0001)
      
      	// COMPAT_IMAGIC_INODES
      	SbFeatureCompatImagicInodes = uint32(0x0002)
      
      	// COMPAT_HAS_JOURNAL
      	SbFeatureCompatHasJournal = uint32(0x0004)
      
      	// COMPAT_EXT_ATTR
      	SbFeatureCompatExtAttr = uint32(0x0008)
      
      	// COMPAT_RESIZE_INODE
      	SbFeatureCompatResizeInode = uint32(0x0010)
      
      	// COMPAT_DIR_INDEX
      	SbFeatureCompatDirIndex = uint32(0x0020)
      
      	// COMPAT_LAZY_BG
      	SbFeatureCompatLazyBg = uint32(0x40)
      
      	// COMPAT_EXCLUDE_INODE
      	SbFeatureCompatExcludeInode = uint32(0x80)
      
      	// COMPAT_EXCLUDE_BITMAP
      	SbFeatureCompatExcludeBitmap = uint32(0x100)
      
      	// COMPAT_SPARSE_SUPER2
      	SbFeatureCompatSparseSuperblockV2 = uint32(0x200)
      )
      View Source
      const (
      	// RO_COMPAT_SPARSE_SUPER
      	SbFeatureRoCompatSparseSuper = uint32(0x1)
      
      	// RO_COMPAT_LARGE_FILE
      	SbFeatureRoCompatLargeFile = uint32(0x2)
      
      	// RO_COMPAT_BTREE_DIR
      	SbFeatureRoCompatBtreeDir = uint32(0x4)
      
      	// RO_COMPAT_HUGE_FILE
      	SbFeatureRoCompatHugeFile = uint32(0x8)
      
      	// RO_COMPAT_GDT_CSUM
      	SbFeatureRoCompatGdtCsum = uint32(0x10)
      
      	// RO_COMPAT_DIR_NLINK
      	SbFeatureRoCompatDirNlink = uint32(0x20)
      
      	// RO_COMPAT_EXTRA_ISIZE
      	SbFeatureRoCompatExtraIsize = uint32(0x40)
      
      	// RO_COMPAT_HAS_SNAPSHOT
      	SbFeatureRoCompatHasSnapshot = uint32(0x80)
      
      	// RO_COMPAT_QUOTA
      	SbFeatureRoCompatQuota = uint32(0x100)
      
      	// RO_COMPAT_BIGALLOC
      	SbFeatureRoCompatBigAlloc = uint32(0x200)
      
      	// RO_COMPAT_METADATA_CSUM
      	SbFeatureRoCompatMetadataCsum = uint32(0x400)
      
      	// RO_COMPAT_REPLICA
      	SbFeatureRoCompatReplica = uint32(0x800)
      
      	// RO_COMPAT_READONLY
      	SbFeatureRoCompatReadonly = uint32(0x1000)
      
      	// RO_COMPAT_PROJECT
      	SbFeatureRoCompatProject = uint32(0x2000)
      )
      View Source
      const (
      	// INCOMPAT_COMPRESSION
      	SbFeatureIncompatCompression = uint32(0x0001)
      
      	// INCOMPAT_FILETYPE
      	SbFeatureIncompatFiletype = uint32(0x0002)
      
      	// INCOMPAT_RECOVER
      	SbFeatureIncompatRecover = uint32(0x0004) /* Needs recovery */
      
      	// INCOMPAT_JOURNAL_DEV
      	SbFeatureIncompatJournalDev = uint32(0x0008) /* Journal device */
      
      	// INCOMPAT_META_BG
      	SbFeatureIncompatMetaBg = uint32(0x0010)
      
      	// INCOMPAT_EXTENTS
      	SbFeatureIncompatExtents = uint32(0x0040) /* extents support */
      
      	// INCOMPAT_64BIT
      	SbFeatureIncompat64bit = uint32(0x0080)
      
      	// INCOMPAT_MMP
      	SbFeatureIncompatMmp = uint32(0x0100)
      
      	// INCOMPAT_FLEX_BG
      	SbFeatureIncompatFlexBg = uint32(0x0200)
      
      	// INCOMPAT_EA_INODE
      	SbFeatureIncompatLargeExtendedAttributeValues = uint32(0x400)
      
      	// INCOMPAT_DIRDATA
      	SbFeatureIncompatDirData = uint32(0x1000)
      
      	// INCOMPAT_CSUM_SEED
      	SbFeatureIncompatCsumSeed = uint32(0x2000)
      
      	// INCOMPAT_LARGEDIR
      	SbFeatureIncompatLargeDir = uint32(0x4000)
      
      	// INCOMPAT_INLINE_DATA
      	SbFeatureIncompatInlineData = uint32(0x8000)
      
      	// INCOMPAT_ENCRYPT
      	SbFeatureIncompatEncrypt = uint32(0x10000)
      )
      View Source
      const (
      	TestDirectoryInodeNumber = 2
      	TestFileInodeNumber      = 12
      )
      View Source
      const (
      	BlockGroupDescriptorSize = 64
      )
      View Source
      const (
      	Ext4ExtentChecksumTailSize = 4
      )

      Variables

      View Source
      var (
      	// SbFeatureCompatNames is an ordered list of names.
      	SbFeatureCompatNames = []string{
      		"DirIndex",
      		"DirPrealloc",
      		"ExcludeBitmap",
      		"ExcludeInode",
      		"ExtAttr",
      		"HasJournal",
      		"ImagicInodes",
      		"LazyBg",
      		"ResizeInode",
      		"SparseSuper2",
      	}
      
      	SbFeatureCompatLookup = map[string]uint32{
      		"DirPrealloc":   SbFeatureCompatDirPrealloc,
      		"ImagicInodes":  SbFeatureCompatImagicInodes,
      		"HasJournal":    SbFeatureCompatHasJournal,
      		"ExtAttr":       SbFeatureCompatExtAttr,
      		"ResizeInode":   SbFeatureCompatResizeInode,
      		"DirIndex":      SbFeatureCompatDirIndex,
      		"LazyBg":        SbFeatureCompatLazyBg,
      		"ExcludeInode":  SbFeatureCompatExcludeInode,
      		"ExcludeBitmap": SbFeatureCompatExcludeBitmap,
      		"SparseSuper2":  SbFeatureCompatSparseSuperblockV2,
      	}
      )
      View Source
      var (
      	// SbFeatureRoCompatNames is an ordered list of names.
      	SbFeatureRoCompatNames = []string{
      		"BigAlloc",
      		"BtreeDir",
      		"DirNlink",
      		"ExtraIsize",
      		"GdtCsum",
      		"HasSnapshot",
      		"HugeFile",
      		"LargeFile",
      		"MetadataCsum",
      		"Project",
      		"Quota",
      		"Readonly",
      		"Replica",
      		"SparseSuper",
      	}
      
      	SbFeatureRoCompatLookup = map[string]uint32{
      		"SparseSuper":  SbFeatureRoCompatSparseSuper,
      		"LargeFile":    SbFeatureRoCompatLargeFile,
      		"BtreeDir":     SbFeatureRoCompatBtreeDir,
      		"HugeFile":     SbFeatureRoCompatHugeFile,
      		"GdtCsum":      SbFeatureRoCompatGdtCsum,
      		"DirNlink":     SbFeatureRoCompatDirNlink,
      		"ExtraIsize":   SbFeatureRoCompatExtraIsize,
      		"HasSnapshot":  SbFeatureRoCompatHasSnapshot,
      		"Quota":        SbFeatureRoCompatQuota,
      		"BigAlloc":     SbFeatureRoCompatBigAlloc,
      		"MetadataCsum": SbFeatureRoCompatMetadataCsum,
      		"Replica":      SbFeatureRoCompatReplica,
      		"Readonly":     SbFeatureRoCompatReadonly,
      		"Project":      SbFeatureRoCompatProject,
      	}
      )
      View Source
      var (
      	// SbFeatureIncompatNames is an ordered list of names.
      	SbFeatureIncompatNames = []string{
      		"64bit",
      		"Compression",
      		"CsumSeed",
      		"DirData",
      		"Encrypt",
      		"Extents",
      		"Filetype",
      		"FlexBg",
      		"InlineData",
      		"JournalDev",
      		"LargeDir",
      		"LargeExtendedAttributeValues",
      		"MetaBg",
      		"Mmp",
      		"Recover",
      	}
      
      	SbFeatureIncompatLookup = map[string]uint32{
      		"Compression":                  SbFeatureIncompatCompression,
      		"Filetype":                     SbFeatureIncompatFiletype,
      		"Recover":                      SbFeatureIncompatRecover,
      		"JournalDev":                   SbFeatureIncompatJournalDev,
      		"MetaBg":                       SbFeatureIncompatMetaBg,
      		"Extents":                      SbFeatureIncompatExtents,
      		"64bit":                        SbFeatureIncompat64bit,
      		"Mmp":                          SbFeatureIncompatMmp,
      		"FlexBg":                       SbFeatureIncompatFlexBg,
      		"LargeExtendedAttributeValues": SbFeatureIncompatLargeExtendedAttributeValues,
      		"DirData":                      SbFeatureIncompatDirData,
      		"CsumSeed":                     SbFeatureIncompatCsumSeed,
      		"LargeDir":                     SbFeatureIncompatLargeDir,
      		"InlineData":                   SbFeatureIncompatInlineData,
      		"Encrypt":                      SbFeatureIncompatEncrypt,
      	}
      )
      View Source
      var (
      	ErrNotExt4 = errors.New("not ext4")
      )
      View Source
      var (
      	FileTypeLookup = map[uint8]string{
      		FileTypeUnknown:         "unknown",
      		FileTypeRegular:         "regular",
      		FileTypeDirectory:       "directory",
      		FileTypeCharacterDevice: "character device",
      		FileTypeBlockDevice:     "block device",
      		FileTypeFifo:            "fifo",
      		FileTypeSocket:          "socket",
      		FileTypeSymbolicLink:    "symbolic link",
      	}
      )
      View Source
      var (
      	InodeFlagLookup = map[string]int{
      		"Secrm":           InodeFlagSecrm,
      		"Unrm":            InodeFlagUnrm,
      		"Compr":           InodeFlagCompr,
      		"Sync":            InodeFlagSync,
      		"Immutable":       InodeFlagImmutable,
      		"Append":          InodeFlagAppend,
      		"Nodump":          InodeFlagNodump,
      		"Noatime":         InodeFlagNoatime,
      		"Dirty":           InodeFlagDirty,
      		"Comprblk":        InodeFlagComprblk,
      		"Nocompr":         InodeFlagNocompr,
      		"Encrypt":         InodeFlagEncrypt,
      		"Index":           InodeFlagIndex,
      		"Imagic":          InodeFlagImagic,
      		"JournalData":     InodeFlagJournalData,
      		"Notail":          InodeFlagNotail,
      		"Dirsync":         InodeFlagDirsync,
      		"Topdir":          InodeFlagTopdir,
      		"HugeFile":        InodeFlagHugeFile,
      		"Extents":         InodeFlagExtents,
      		"EaInode":         InodeFlagEaInode,
      		"Eofblocks":       InodeFlagEofblocks,
      		"Snapfile":        InodeFlagSnapfile,
      		"SnapfileDeleted": InodeFlagSnapfileDeleted,
      		"SnapfileShrunk":  InodeFlagSnapfileShrunk,
      		"InlineData":      InodeFlagInlineData,
      		"Projinherit":     InodeFlagProjinherit,
      	}
      )

      Functions

      This section is empty.

      Types

      type BlockGroupDescriptor

      type BlockGroupDescriptor struct {
      	// contains filtered or unexported fields
      }

      func NewBlockGroupDescriptorWithReader

      func NewBlockGroupDescriptorWithReader(r io.Reader, sb *Superblock) (bgd *BlockGroupDescriptor, err error)

      func (*BlockGroupDescriptor) Data

      func (*BlockGroupDescriptor) Dump

      func (bgd *BlockGroupDescriptor) Dump()

      func (*BlockGroupDescriptor) InodeBitmapBlock

      func (bgd *BlockGroupDescriptor) InodeBitmapBlock() uint64

      func (*BlockGroupDescriptor) InodeTableBlock

      func (bgd *BlockGroupDescriptor) InodeTableBlock() uint64

        InodeTableBlock returns the absolute block number of the inode-table.

        func (*BlockGroupDescriptor) IsBitmapNotInitialized

        func (bgd *BlockGroupDescriptor) IsBitmapNotInitialized() bool

        func (*BlockGroupDescriptor) IsInodeTableAndBitmapNotInitialized

        func (bgd *BlockGroupDescriptor) IsInodeTableAndBitmapNotInitialized() bool

        func (*BlockGroupDescriptor) IsInodeTableZeroed

        func (bgd *BlockGroupDescriptor) IsInodeTableZeroed() bool

        func (*BlockGroupDescriptor) Superblock

        func (bgd *BlockGroupDescriptor) Superblock() *Superblock

        type BlockGroupDescriptorData

        type BlockGroupDescriptorData struct {
        	BgBlockBitmapLo     uint32 /* Blocks bitmap block */
        	BgInodeBitmapLo     uint32 /* Inodes bitmap block */
        	BgInodeTableLo      uint32 /* Inodes table block */
        	BgFreeBlocksCountLo uint16 /* Free blocks count */
        	BgFreeInodesCountLo uint16 /* Free inodes count */
        	BgUsedDirsCountLo   uint16 /* Directories count */
        	BgFlags             uint16 /* EXT4_BG_flags (INODE_UNINIT, etc) */
        	BgExcludeBitmapLo   uint32 /* Lower 32-bits of location of snapshot exclusion bitmap. */
        	BgBlockBitmapCsumLo uint16 /* Lower 16-bits of the block bitmap checksum. */
        	BgInodeBitmapCsumLo uint16 /* Lower 16-bits of the inode bitmap checksum. */
        	BgItableUnusedLo    uint16 /* Unused inodes count */
        	BgChecksum          uint16 /* crc16(sb_uuid+group+desc) */
        	BgBlockBitmapHi     uint32 /* Blocks bitmap block MSB */
        	BgInodeBitmapHi     uint32 /* Inodes bitmap block MSB */
        	BgInodeTableHi      uint32 /* Inodes table block MSB */
        	BgFreeBlocksCountHi uint16 /* Free blocks count MSB */
        	BgFreeInodesCountHi uint16 /* Free inodes count MSB */
        	BgUsedDirsCountHi   uint16 /* Directories count MSB */
        	BgItableUnusedHi    uint16 /* Unused inodes count MSB */
        	BgExcludeBitmapHi   uint32 /* Upper 32-bits of location of snapshot exclusion bitmap. */
        	BgBlockBitmapCsumHi uint16 /* Upper 16-bits of the block bitmap checksum. */
        	BgInodeBitmapCsumHi uint16 /* Upper 16-bits of the inode bitmap checksum. */
        	BgReserved2         uint32 /* Padding to 64 bytes. */
        }

        type BlockGroupDescriptorList

        type BlockGroupDescriptorList struct {
        	// contains filtered or unexported fields
        }

        func NewBlockGroupDescriptorListWithReadSeeker

        func NewBlockGroupDescriptorListWithReadSeeker(rs io.ReadSeeker, sb *Superblock) (bgdl *BlockGroupDescriptorList, err error)

          NewBlockGroupDescriptorListWithReadSeeker returns a `BlockGroupDescriptorsList`, which has all block-group-descriptors in a big slice. Filesystems with the flex_bg capability flag (most) will group all of the BGD data together right at the top.

          func (*BlockGroupDescriptorList) GetWithAbsoluteInode

          func (bgdl *BlockGroupDescriptorList) GetWithAbsoluteInode(n int) (bgd *BlockGroupDescriptor, err error)

          type DirectoryBrowser

          type DirectoryBrowser struct {
          	// contains filtered or unexported fields
          }

            DirectoryBrowser provides high-level directory navigation.

            func NewDirectoryBrowser

            func NewDirectoryBrowser(rs io.ReadSeeker, inode *Inode) *DirectoryBrowser

            func (*DirectoryBrowser) Next

            func (db *DirectoryBrowser) Next() (de *DirectoryEntry, err error)

              Next parses the next directory entry from the underlying inode data reader. Returns `io.EOF` when done. This will also return the "." and ".." entries.

              type DirectoryEntry

              type DirectoryEntry struct {
              	// contains filtered or unexported fields
              }

                DirectoryEntry wraps the raw directory entry and provides higher-level functionality.

                func (*DirectoryEntry) Data

                func (de *DirectoryEntry) Data() *Ext4DirEntry2

                func (*DirectoryEntry) IsBlockDevice

                func (de *DirectoryEntry) IsBlockDevice() bool

                func (*DirectoryEntry) IsCharacterDevice

                func (de *DirectoryEntry) IsCharacterDevice() bool

                func (*DirectoryEntry) IsDirectory

                func (de *DirectoryEntry) IsDirectory() bool

                func (*DirectoryEntry) IsFifo

                func (de *DirectoryEntry) IsFifo() bool

                func (*DirectoryEntry) IsRegular

                func (de *DirectoryEntry) IsRegular() bool

                func (*DirectoryEntry) IsSocket

                func (de *DirectoryEntry) IsSocket() bool
                func (de *DirectoryEntry) IsSymbolicLink() bool

                func (*DirectoryEntry) IsUnknownType

                func (de *DirectoryEntry) IsUnknownType() bool

                func (*DirectoryEntry) Name

                func (de *DirectoryEntry) Name() string

                func (*DirectoryEntry) String

                func (de *DirectoryEntry) String() string

                func (*DirectoryEntry) TypeName

                func (de *DirectoryEntry) TypeName() string

                type DirectoryWalk

                type DirectoryWalk struct {
                	// contains filtered or unexported fields
                }

                  DirectoryWalk provides full directory-structure recursion.

                  func NewDirectoryWalk

                  func NewDirectoryWalk(rs io.ReadSeeker, bgd *BlockGroupDescriptor, rootInodeNumber int) (dw *DirectoryWalk, err error)

                  func (*DirectoryWalk) Next

                  func (dw *DirectoryWalk) Next() (fullPath string, de *DirectoryEntry, err error)

                    Next steps through the entire tree starting at the given root inode, one entry at a time. We guarantee that all adjacent entries will be processed adjacently. This will not return the "." and ".." entries.

                    Example
                    Output:
                    
                    
                    directory1/fortune1: DirectoryEntry<NAME=[fortune1] INODE=(15) TYPE=[regular]-(1)>
                    directory1/fortune2: DirectoryEntry<NAME=[fortune2] INODE=(14) TYPE=[regular]-(1)>
                    directory1/fortune5: DirectoryEntry<NAME=[fortune5] INODE=(20) TYPE=[regular]-(1)>
                    directory1/fortune6: DirectoryEntry<NAME=[fortune6] INODE=(21) TYPE=[regular]-(1)>
                    directory1/subdirectory1/fortune3: DirectoryEntry<NAME=[fortune3] INODE=(17) TYPE=[regular]-(1)>
                    directory1/subdirectory1/fortune4: DirectoryEntry<NAME=[fortune4] INODE=(18) TYPE=[regular]-(1)>
                    directory1/subdirectory1: DirectoryEntry<NAME=[subdirectory1] INODE=(16) TYPE=[directory]-(2)>
                    directory1/subdirectory2/fortune7: DirectoryEntry<NAME=[fortune7] INODE=(22) TYPE=[regular]-(1)>
                    directory1/subdirectory2/fortune8: DirectoryEntry<NAME=[fortune8] INODE=(23) TYPE=[regular]-(1)>
                    directory1/subdirectory2: DirectoryEntry<NAME=[subdirectory2] INODE=(19) TYPE=[directory]-(2)>
                    directory1: DirectoryEntry<NAME=[directory1] INODE=(13) TYPE=[directory]-(2)>
                    directory2/fortune10: DirectoryEntry<NAME=[fortune10] INODE=(26) TYPE=[regular]-(1)>
                    directory2/fortune9: DirectoryEntry<NAME=[fortune9] INODE=(25) TYPE=[regular]-(1)>
                    directory2: DirectoryEntry<NAME=[directory2] INODE=(24) TYPE=[directory]-(2)>
                    lost+found: DirectoryEntry<NAME=[lost+found] INODE=(11) TYPE=[directory]-(2)>
                    thejungle.txt: DirectoryEntry<NAME=[thejungle.txt] INODE=(12) TYPE=[regular]-(1)>
                    

                    type Ext4DirEntry2

                    type Ext4DirEntry2 struct {
                    	Inode    uint32 // Number of the inode that this directory entry points to.
                    	RecLen   uint16 // Length of this directory entry.
                    	NameLen  uint8  // Length of the file name.
                    	FileType uint8  // File type code, see ftype table below.
                    	Name     []byte // File name. Has a maximum size of Ext4FilenameMaxLen but actual length derived from `RecLen`.
                    }

                      Ext4DirEntry2 is one of potentially many sequential entries stored in a directory inode.

                      type ExtentHeaderNode

                      type ExtentHeaderNode struct {
                      	EhMagic      uint16 /* probably will support different formats */
                      	EhEntryCount uint16 /* number of valid entries */
                      	EhMax        uint16 /* capacity of store in entries */
                      	EhDepth      uint16 /* has tree real underlying blocks? */
                      	EhGeneration uint32 /* generation of the tree */
                      }

                      func (*ExtentHeaderNode) String

                      func (eh *ExtentHeaderNode) String() string

                      type ExtentIndexNode

                      type ExtentIndexNode struct {
                      	EiLogicalBlock        uint32 /* index covers logical blocks from 'block' */
                      	EiLeafPhysicalBlockLo uint32 /* pointer to the physical block of the next level. leaf or next index could be there */
                      	EiLeafPhysicalBlockHi uint16 /* high 16 bits of physical block */
                      	EiUnused              uint16
                      }

                      func (*ExtentIndexNode) LeafPhysicalBlock

                      func (ein *ExtentIndexNode) LeafPhysicalBlock() uint64

                      func (*ExtentIndexNode) String

                      func (ein *ExtentIndexNode) String() string

                      type ExtentLeafNode

                      type ExtentLeafNode struct {
                      	EeFirstLogicalBlock    uint32 /* first logical block extent covers */
                      	EeLogicalBlockCount    uint16 /* number of blocks covered by extent */
                      	EeStartPhysicalBlockHi uint16 /* high 16 bits of physical block */
                      	EeStartPhysicalBlockLo uint32 /* low 32 bits of physical block */
                      }

                      func (*ExtentLeafNode) StartPhysicalBlock

                      func (eln *ExtentLeafNode) StartPhysicalBlock() uint64

                      func (*ExtentLeafNode) String

                      func (eln *ExtentLeafNode) String() string

                      type ExtentNavigator

                      type ExtentNavigator struct {
                      	// contains filtered or unexported fields
                      }

                      func NewExtentNavigatorWithReadSeeker

                      func NewExtentNavigatorWithReadSeeker(rs io.ReadSeeker, inode *Inode) *ExtentNavigator

                      func (*ExtentNavigator) Read

                      func (en *ExtentNavigator) Read(offset uint64) (data []byte, err error)

                        Read returns the inode data from the given offset to the end of the logical block that it's found in.

                        "logical", meaning that (0) refers to the first block of this inode's data.

                        Example
                        Output:
                        
                        
                        The Project Gutenberg EBook of The Jungle, by Upton Sinclair
                        
                        This eBook is for the use of anyo
                        

                        type ExtentTail

                        type ExtentTail struct {
                        	EbChecksum uint32
                        }

                        type Inode

                        type Inode struct {
                        	// contains filtered or unexported fields
                        }

                        func GetInode

                        func GetInode(filesystemPath string, inodeNumber int) (f *os.File, inode *Inode, err error)

                        func GetTestInode

                        func GetTestInode(inodeNumber int) (f *os.File, inode *Inode, err error)

                          GetTestInode returns a test inode struct and `os.File` for the file. It's the responsibility of the caller to close it.

                          func NewInodeWithReadSeeker

                          func NewInodeWithReadSeeker(bgd *BlockGroupDescriptor, rs io.ReadSeeker, absoluteInodeNumber int) (inode *Inode, err error)

                          func (*Inode) AccessTime

                          func (inode *Inode) AccessTime() time.Time

                          func (*Inode) BlockGroupDescriptor

                          func (inode *Inode) BlockGroupDescriptor() (bgd *BlockGroupDescriptor)

                          func (*Inode) Data

                          func (inode *Inode) Data() *InodeData

                          func (*Inode) DeletionTime

                          func (inode *Inode) DeletionTime() time.Time

                          func (*Inode) Dump

                          func (inode *Inode) Dump()

                          func (*Inode) DumpFlags

                          func (inode *Inode) DumpFlags(includeFalses bool)

                          func (*Inode) FileCreationTime

                          func (inode *Inode) FileCreationTime() time.Time

                          func (*Inode) Flag

                          func (inode *Inode) Flag(flag int) bool

                          func (*Inode) InodeChangeTime

                          func (inode *Inode) InodeChangeTime() time.Time

                          func (*Inode) ModificationTime

                          func (inode *Inode) ModificationTime() time.Time

                          func (*Inode) Size

                          func (inode *Inode) Size() uint64

                          func (*Inode) String

                          func (inode *Inode) String() string

                          type InodeData

                          type InodeData struct {
                          	IMode       uint16 /* File mode */
                          	IUid        uint16 /* Low 16 bits of Owner Uid */
                          	ISizeLo     uint32 /* Size in bytes */
                          	IAtime      uint32 /* Access time */
                          	ICtime      uint32 /* Inode Change time */
                          	IMtime      uint32 /* Modification time */
                          	IDtime      uint32 /* Deletion Time */
                          	IGid        uint16 /* Low 16 bits of Group Id */
                          	ILinksCount uint16 /* Links count */
                          	IBlocksLo   uint32 /* Blocks count */
                          	IFlags      uint32 /* File flags */
                          
                          	// union {
                          	//     struct {
                          	//         __le32  l_i_version;
                          	//     } linux1;
                          	//     struct {
                          	//         __u32  h_i_translator;
                          	//     } hurd1;
                          	//     struct {
                          	//         __u32  m_i_reserved1;
                          	//     } masix1;
                          	// } osd1;             /* OS dependent 1 */
                          	Osd1 [4]byte
                          
                          	/*
                          		IBlock is a general buffer for our data, which can have various
                          		interpretations. `Ext4NBlocks` comes from the kernel where it is a count in
                          		terms of uint32's, which is then cast as a struct. However, it works better
                          		for us as an array of bytes.
                          	*/
                          	IBlock [Ext4NBlocks * 4]byte
                          
                          	IGeneration uint32 /* File version (for NFS) */
                          	IFileAclLo  uint32 /* File ACL */
                          	ISizeHigh   uint32
                          	IObsoFaddr  uint32 /* Obsoleted fragment address */
                          
                          	// union {
                          	//     struct {
                          	//         __le16  l_i_blocks_high; /* were l_i_reserved1 */
                          	//         __le16  l_i_file_acl_high;
                          	//         __le16  l_i_uid_high;   /* these 2 fields */
                          	//         __le16  l_i_gid_high;   /* were reserved2[0] */
                          	//         __le16  l_i_checksum_lo;/* crc32c(uuid+inum+inode) LE */
                          	//         __le16  l_i_reserved;
                          	//     } linux2;
                          	//     struct {
                          	//         __le16  h_i_reserved1;   Obsoleted fragment number/size which are removed in ext4
                          	//         __u16   h_i_mode_high;
                          	//         __u16   h_i_uid_high;
                          	//         __u16   h_i_gid_high;
                          	//         __u32   h_i_author;
                          	//     } hurd2;
                          	//     struct {
                          	//         __le16  h_i_reserved1;  /* Obsoleted fragment number/size which are removed in ext4 */
                          	//         __le16  m_i_file_acl_high;
                          	//         __u32   m_i_reserved2[2];
                          	//     } masix2;
                          	// } osd2;             /* OS dependent 2 */
                          	Osd2 [12]byte
                          
                          	IExtraIsize  uint16
                          	IChecksumHi  uint16 /* crc32c(uuid+inum+inode) BE */
                          	ICtimeExtra  uint32 /* extra Change time      (nsec << 2 | epoch) */
                          	IMtimeExtra  uint32 /* extra Modification time(nsec << 2 | epoch) */
                          	IAtimeExtra  uint32 /* extra Access time      (nsec << 2 | epoch) */
                          	ICrtime      uint32 /* File Creation time */
                          	ICrtimeExtra uint32 /* extra FileCreationtime (nsec << 2 | epoch) */
                          	IVersionHi   uint32 /* high 32 bits for 64-bit version */
                          	IProjid      uint32 /* Project ID */
                          }

                          type InodeReader

                          type InodeReader struct {
                          	// contains filtered or unexported fields
                          }

                            InodeReader fulfills the `io.Reader` interface to read arbitrary amounts of data.

                            func NewInodeReader

                            func NewInodeReader(en *ExtentNavigator) *InodeReader

                            func (*InodeReader) Offset

                            func (ir *InodeReader) Offset() uint64

                            func (*InodeReader) Read

                            func (ir *InodeReader) Read(p []byte) (n int, err error)

                              Read fills the given slice with data and returns an `io.EOF` error with (0) bytes when done. (`n`) may be less then `len(p)`.

                              func (*InodeReader) Skip

                              func (ir *InodeReader) Skip(n uint64) (skipped uint64, err error)

                                Skip simulates a read but just discards the data.

                                type Superblock

                                type Superblock struct {
                                	// contains filtered or unexported fields
                                }

                                func NewSuperblockWithReader

                                func NewSuperblockWithReader(rs io.ReadSeeker) (sb *Superblock, err error)
                                Example
                                Output:
                                
                                tinyimage
                                

                                func (*Superblock) BlockCount

                                func (sb *Superblock) BlockCount() uint64

                                func (*Superblock) BlockGroupCount

                                func (sb *Superblock) BlockGroupCount() (blockGroups uint64)

                                func (*Superblock) BlockGroupInodeNumberWithAbsoluteInodeNumber

                                func (sb *Superblock) BlockGroupInodeNumberWithAbsoluteInodeNumber(absoluteInodeNumber int) int

                                func (*Superblock) BlockGroupNumberWithAbsoluteInodeNumber

                                func (sb *Superblock) BlockGroupNumberWithAbsoluteInodeNumber(absoluteInodeNumber int) int

                                func (*Superblock) BlockSize

                                func (sb *Superblock) BlockSize() uint32

                                func (*Superblock) Data

                                func (sb *Superblock) Data() *SuperblockData

                                func (*Superblock) Dump

                                func (sb *Superblock) Dump()

                                func (*Superblock) DumpFeatures

                                func (sb *Superblock) DumpFeatures(includeFalses bool)

                                func (*Superblock) HasCompatibleFeature

                                func (sb *Superblock) HasCompatibleFeature(mask uint32) bool

                                func (*Superblock) HasExtended

                                func (sb *Superblock) HasExtended() bool

                                func (*Superblock) HasIncompatibleFeature

                                func (sb *Superblock) HasIncompatibleFeature(mask uint32) bool

                                func (*Superblock) HasReadonlyCompatibleFeature

                                func (sb *Superblock) HasReadonlyCompatibleFeature(mask uint32) bool

                                func (*Superblock) Is64Bit

                                func (sb *Superblock) Is64Bit() bool

                                func (*Superblock) LastCheckTime

                                func (sb *Superblock) LastCheckTime() time.Time

                                func (*Superblock) MountTime

                                func (sb *Superblock) MountTime() time.Time

                                func (*Superblock) ReadPhysicalBlock

                                func (sb *Superblock) ReadPhysicalBlock(absoluteBlockNumber uint64, length uint64) (data []byte, err error)
                                Example
                                Output:
                                
                                

                                func (*Superblock) VolumeName

                                func (sb *Superblock) VolumeName() string

                                func (*Superblock) WriteTime

                                func (sb *Superblock) WriteTime() time.Time

                                type SuperblockData

                                type SuperblockData struct {
                                
                                	// 0x00
                                	SInodesCount       uint32
                                	SBlocksCountLo     uint32
                                	SRBlocksCountLo    uint32
                                	SFreeBlocksCountLo uint32
                                
                                	// 0x10
                                	SFreeInodesCount uint32
                                	SFirstDataBlock  uint32
                                	SLogBlockSize    uint32
                                	SLogClusterSize  uint32
                                
                                	// 0x20
                                	SBlocksPerGroup   uint32
                                	SClustersPerGroup uint32
                                	SInodesPerGroup   uint32
                                	SMtime            uint32
                                
                                	// 0x30
                                	SWtime         uint32
                                	SMntCount      uint16
                                	SMaxMntCount   uint16
                                	SMagic         uint16
                                	SState         uint16
                                	SErrors        uint16
                                	SMinorRevLevel uint16
                                
                                	// 0x40
                                	SLastcheck     uint32
                                	SCheckinterval uint32
                                	SCreatorOs     uint32
                                	SRevLevel      uint32
                                
                                	// 0x50
                                	SDefResuid uint16
                                	SDefResgid uint16
                                
                                	/*
                                	 * These fields are for EXT4_DYNAMIC_REV superblocks only.
                                	 *
                                	 * Note: the difference between the compatible feature set and
                                	 * the incompatible feature set is that if there is a bit set
                                	 * in the incompatible feature set that the kernel doesn't
                                	 * know about, it should refuse to mount the filesystem.
                                	 *
                                	 * e2fsck's requirements are more strict; if it doesn't know
                                	 * about a feature in either the compatible or incompatible
                                	 * feature set, it must abort and not try to meddle with
                                	 * things it doesn't understand...
                                	 */
                                	SFirstIno      uint32 /* First non-reserved inode */
                                	SInodeSize     uint16 /* size of inode structure */
                                	SBlockGroupNr  uint16 /* block group # of this superblock */
                                	SFeatureCompat uint32 /* compatible feature set */
                                
                                	// 0x60
                                	SFeatureIncompat uint32 /* incompatible feature set */
                                	SFeatureRoCompat uint32 /* readonly-compatible feature set */
                                
                                	// 0x68
                                	SUuid [16]uint8 /* 128-bit uuid for volume */
                                
                                	// 0x78
                                	SVolumeName [16]byte /* volume name */
                                
                                	// 0x88
                                	SLastMounted [64]byte /* directory where last mounted */
                                
                                	// 0xC8
                                	SAlgorithmUsageBitmap uint32 /* For compression */
                                
                                	/*
                                	 * Performance hints.  Directory preallocation should only
                                	 * happen if the EXT4_FEATURE_COMPAT_DIR_PREALLOC flag is on.
                                	 */
                                	SPreallocBlocks    uint8  /* Nr of blocks to try to preallocate*/
                                	SPreallocDirBlocks uint8  /* Nr to preallocate for dirs */
                                	SReservedGdtBlocks uint16 /* Per group desc for online growth */
                                
                                	// 0xD0
                                	/*
                                	 * Journaling support valid if EXT4_FEATURE_COMPAT_HAS_JOURNAL set.
                                	 */
                                	SJournalUuid [16]uint8 /* uuid of journal superblock */
                                
                                	// 0xE0
                                	SJournalInum    uint32    /* inode number of journal file */
                                	SJournalDev     uint32    /* device number of journal file */
                                	SLastOrphan     uint32    /* start of list of inodes to delete */
                                	SHashSeed       [4]uint32 /* HTREE hash seed */
                                	SDefHashVersion uint8     /* Default hash version to use */
                                	SJnlBackupType  uint8
                                	SDescSize       uint16 /* Size of group descriptors, in bytes, if the 64bit incompat feature flag is set. */
                                
                                	// 0x100
                                	SDefaultMountOpts uint32
                                	SFirstMetaBg      uint32     /* First metablock block group */
                                	SMkfsTime         uint32     /* When the filesystem was created */
                                	SJnlBlocks        [17]uint32 /* Backup of the journal inode */
                                
                                	// 0x150
                                	SBlocksCountHi     uint32 /* Blocks count */
                                	SRBlocksCountHi    uint32 /* Reserved blocks count */
                                	SFreeBlocksCountHi uint32 /* Free blocks count */
                                	SMinExtraIsize     uint16 /* All inodes have at least # bytes */
                                	SWantExtraIsize    uint16 /* New inodes should reserve # bytes */
                                
                                	SFlags            uint32 /* Miscellaneous flags */
                                	SRaidStride       uint16 /* RAID stride */
                                	SMmpInterval      uint16 /* # seconds to wait in MMP checking */
                                	SMmpBlock         uint64 /* Block for multi-mount protection */
                                	SRaidStripeWidth  uint32 /* blocks on all data disks (N*stride)*/
                                	SLogGroupsPerFlex uint8  /* FLEX_BG group size */
                                	SChecksumType     uint8  /* metadata checksum algorithm used */
                                	SEncryptionLevel  uint8  /* versioning level for encryption */
                                	SReservedPad      uint8  /* Padding to next 32bits */
                                	SKbytesWritten    uint64 /* nr of lifetime kilobytes written */
                                
                                	SSnapshotInum         uint32 /* Inode number of active snapshot */
                                	SSnapshotId           uint32 /* sequential ID of active snapshot */
                                	SSnapshotRBlocksCount uint64 /* reserved blocks for active snapshot's future use */
                                	SSnapshotList         uint32 /* inode number of the head of the on-disk snapshot list */
                                
                                	SErrorCount      uint32    /* number of fs errors */
                                	SFirstErrorTime  uint32    /* first time an error happened */
                                	SFirstErrorIno   uint32    /* inode involved in first error */
                                	SFirstErrorBlock uint64    /* block involved of first error */
                                	SFirstErrorFunc  [32]uint8 /* function where the error happened */
                                	SFirstErrorLine  uint32    /* line number where error happened */
                                	SLastErrorTime   uint32    /* most recent time of an error */
                                	SLastErrorIno    uint32    /* inode involved in last error */
                                	SLastErrorLine   uint32    /* line number where error happened */
                                	SLastErrorBlock  uint64    /* block involved of last error */
                                	SLastErrorFunc   [32]uint8 /* function where the error happened */
                                
                                	SMountOpts        [64]uint8
                                	SUsrQuotaInum     uint32    /* inode for tracking user quota */
                                	SGrpQuotaInum     uint32    /* inode for tracking group quota */
                                	SOverheadClusters uint32    /* overhead blocks/clusters in fs */
                                	SBackupBgs        [2]uint32 /* groups with sparse_super2 SBs */
                                	SEncryptAlgos     [4]uint8  /* Encryption algorithms in use  */
                                	SEncryptPwSalt    [16]uint8 /* Salt used for string2key algorithm */
                                	SLpfIno           uint32    /* Location of the lost+found inode */
                                	SPrjQuotaInum     uint32    /* inode for tracking project quota */
                                	SChecksumSeed     uint32    /* crc32c(uuid) if csum_seed set */
                                	SWtimeHi          uint8
                                	SMtimeHi          uint8
                                	SMkfsTimeHi       uint8
                                	SLastcheckHi      uint8
                                	SFirstErrorTimeHi uint8
                                	SLastErrorTimeHi  uint8
                                	SPad              [2]uint8
                                	SReserved         [96]uint32 /* Padding to the end of the block */
                                	SChecksum         int32      /* crc32c(superblock) */
                                }

                                Directories

                                Path Synopsis