Documentation
¶
Overview ¶
Package libxfs is a read-only, forensics-oriented parser for the XFS filesystem, written in pure Go with no external dependencies.
Entry points ¶
Open a volume from any io.ReaderAt — a file, a device handle, or a section of a larger image — with Open, or from a path with OpenVolumeFromPath:
volume, err := libxfs.OpenVolumeFromPath("disk.img")
if err != nil {
return err
}
defer volume.Close()
entries, err := volume.ListRootDirectoryEntries()
if err != nil {
return err
}
for _, entry := range entries {
fmt.Println(entry.Name, entry.InodeNumber, libxfs.DirEntryFileTypeName(entry.FileType))
}
From a volume, the API divides into four groups:
- Geometry and features: Volume.Superblock, and the feature predicates on Superblock such as Superblock.HasBigTimestamps.
- Metadata: Volume.OpenInode, Volume.OpenInodeByPath and the timestamp accessors on Inode.
- Content: Volume.ReadFileData, Volume.ReadInodeData and Volume.ListInodeExtendedAttributes.
- Directories: Volume.ListDirectoryEntries for the plain view, and Volume.ScanDirectoryRecordsWithOptions for the forensic view that also reports free slots and carved candidates.
Reading damaged images ¶
The default behaviour is strict: a malformed structure is reported as an error rather than guessed at. Forensic callers usually want the opposite, so the directory scanners accept DirectoryScanOptions with BestEffort set, which keeps whatever was recovered from healthy blocks, resynchronises past the damage, and records a ReportAnomaly for each problem found.
Work is bounded on hostile input. Sizes are validated against the volume's own capacity, directory walks allocate a single directory block at a time rather than a recorded size, and path resolution is protected against directory loops.
Facts versus candidates ¶
Deleted directory entries are recovered by carving reclaimed space, which is inherently probabilistic. Every DirectoryRecord therefore says how it was obtained: use DirectoryRecord.IsVerified for records parsed from intact framing and DirectoryRecord.IsProbabilistic for carve candidates. Do not gate on Confidence alone — an active entry and a strong carve candidate can both be ConfidenceHigh.
Format coverage ¶
Both v4 and v5 (CRC) filesystems are supported, including short-form, block, leaf, node and btree directories, directory blocks larger than the filesystem block size, extent-list and b-tree data forks, short-form and block-based extended attributes with remote values, 64-bit "bigtime" timestamps, and 64-bit (nrext64) extent counters. An image carrying an incompatible feature this parser does not understand is refused rather than silently misread.
Writing is out of scope; this package never modifies its input.
Index ¶
- Constants
- Variables
- func DirEntryFileTypeName(fileType uint8) string
- type Concurrency
- type DirectoryArtifactReport
- type DirectoryEntry
- type DirectoryIndexReport
- type DirectoryListing
- type DirectoryRecord
- type DirectoryRecordKind
- type DirectoryScanOptions
- type ExtendedAttribute
- type Extent
- type FragmentationReport
- type IOError
- type Inode
- type InodeForensicReport
- type InodeFragment
- type InodeInformation
- type ParseError
- type RecoveryConfidence
- type ReportAnomaly
- type ReportOptions
- type ReportProvenance
- type Superblock
- type VerificationMode
- type Volume
- func (v *Volume) AnalyzeInodeFragmentation(inodeNumber uint64) (FragmentationReport, error)
- func (v *Volume) AnalyzeInodeFragmentationByPath(path string) (FragmentationReport, error)
- func (v *Volume) Close() error
- func (v *Volume) DirectoryArtifactReport(inodeNumber uint64) (DirectoryArtifactReport, error)
- func (v *Volume) DirectoryArtifactReportByPath(path string) (DirectoryArtifactReport, error)
- func (v *Volume) DirectoryParentInode(inodeNumber uint64) (uint64, error)
- func (v *Volume) DirectoryParentInodeByPath(path string) (uint64, error)
- func (v *Volume) GetRootInode() (*Inode, error)
- func (v *Volume) InodeForensicReport(inodeNumber uint64) (InodeForensicReport, error)
- func (v *Volume) InodeForensicReportByPath(path string) (InodeForensicReport, error)
- func (v *Volume) IsClosed() bool
- func (v *Volume) ListDirectoryEntries(inodeNumber uint64) ([]DirectoryEntry, error)
- func (v *Volume) ListDirectoryEntriesByPath(path string) ([]DirectoryEntry, error)
- func (v *Volume) ListDirectoryEntriesWithOptions(inodeNumber uint64, options DirectoryScanOptions) (DirectoryListing, error)
- func (v *Volume) ListInodeExtendedAttributes(inodeNumber uint64) ([]ExtendedAttribute, error)
- func (v *Volume) ListRootDirectoryEntries() ([]DirectoryEntry, error)
- func (v *Volume) OpenInode(inodeNumber uint64) (*Inode, error)
- func (v *Volume) OpenInodeByPath(path string) (*Inode, error)
- func (v *Volume) ReadFileData(inodeNumber uint64) ([]byte, error)
- func (v *Volume) ReadFileDataByPath(path string) ([]byte, error)
- func (v *Volume) ReadInodeAttributeForkData(inodeNumber uint64) ([]byte, error)
- func (v *Volume) ReadInodeData(inodeNumber uint64, p []byte, off int64) (int, error)
- func (v *Volume) Report() (*XFSReport, error)
- func (v *Volume) ReportWithContext(ctx context.Context, options ReportOptions) (*XFSReport, error)
- func (v *Volume) ReportWithOptions(options ReportOptions) (*XFSReport, error)
- func (v *Volume) ResolveInodeByPath(path string) (uint64, error)
- func (v *Volume) ScanDirectoryRecords(inodeNumber uint64) ([]DirectoryRecord, error)
- func (v *Volume) ScanDirectoryRecordsByPath(path string) ([]DirectoryRecord, error)
- func (v *Volume) ScanDirectoryRecordsByPathWithOptions(path string, options DirectoryScanOptions) (DirectoryListing, error)
- func (v *Volume) ScanDirectoryRecordsWithOptions(inodeNumber uint64, options DirectoryScanOptions) (DirectoryListing, error)
- func (v *Volume) Superblock() Superblock
- func (v *Volume) VerifyDirectoryIndex(inodeNumber uint64) (DirectoryIndexReport, error)
- func (v *Volume) VerifyDirectoryIndexByPath(path string) (DirectoryIndexReport, error)
- func (v *Volume) VolumeIntegrityReport() (VolumeIntegrityReport, error)
- type VolumeError
- type VolumeIntegrityReport
- type XFSReport
Constants ¶
const ( FileTypeFIFO uint16 = 0x1000 FileTypeCharacterDevice uint16 = 0x2000 FileTypeDirectory uint16 = 0x4000 FileTypeBlockDevice uint16 = 0x6000 FileTypeRegularFile uint16 = 0x8000 FileTypeSymbolicLink uint16 = 0xa000 FileTypeSocket uint16 = 0xc000 )
const ( ForkTypeDevice uint8 = 0 ForkTypeInlineData uint8 = 1 ForkTypeExtents uint8 = 2 ForkTypeBtree uint8 = 3 )
const ( // FeatureIncompatFileType marks directory entries as carrying an ftype byte. FeatureIncompatFileType uint32 = 1 << 0 // FeatureIncompatSparseInodes marks sparse inode chunk allocation. FeatureIncompatSparseInodes uint32 = 1 << 1 // FeatureIncompatMetaUUID marks metadata stamped with a separate UUID. FeatureIncompatMetaUUID uint32 = 1 << 2 // FeatureIncompatBigTime marks 64-bit nanosecond inode timestamps. FeatureIncompatBigTime uint32 = 1 << 3 // FeatureIncompatNeedsRepair marks a filesystem left needing repair. FeatureIncompatNeedsRepair uint32 = 1 << 4 // FeatureIncompatLargeExtentCounts marks 64-bit inode extent counters // (the nrext64 feature). FeatureIncompatLargeExtentCounts uint32 = 1 << 5 )
Incompatible feature bits from the v5 superblock (sb_features_incompat).
A filesystem carrying an incompatible bit cannot be interpreted correctly by an implementation that does not understand it. BigTime and LargeExtentCounts both change the on-disk inode layout.
const ( DirEntryFileTypeUnknown uint8 = 0 DirEntryFileTypeRegularFile uint8 = 1 DirEntryFileTypeDirectory uint8 = 2 DirEntryFileTypeCharacterDevice uint8 = 3 DirEntryFileTypeBlockDevice uint8 = 4 DirEntryFileTypeFIFO uint8 = 5 DirEntryFileTypeSocket uint8 = 6 DirEntryFileTypeSymbolicLink uint8 = 7 DirEntryFileTypeWhiteout uint8 = 8 )
Directory entry file types (XFS_DIR3_FT_*).
These are stored in the optional ftype byte of a directory entry when the filesystem has the ftype feature enabled, and describe the target inode without requiring it to be read.
const ( DirectoryFormatShortForm = "short_form" DirectoryFormatBlock = "block" DirectoryFormatMultiBlock = "multi_block" )
Directory layout names reported in DirectoryListing.Format.
const ( XattrNamespaceUser = "user" XattrNamespaceTrusted = "trusted" XattrNamespaceSecurity = "security" )
Extended attribute namespace names, as Linux presents them. Downstream tools match on these strings, so they are part of the library's contract.
const ( SeverityInfo = "info" SeverityLow = "low" SeverityMedium = "medium" SeverityWarning = "warning" SeverityHigh = "high" SeverityError = "error" )
Severity levels reported in ReportAnomaly.Severity.
const ( InodeTypeFile = "file" InodeTypeDirectory = "directory" )
Inode type labels reported in InodeForensicReport.Type.
const ( ReasonIntactFraming = "intact_framing" ReasonTagMatchesOffset = "tag_matches_offset" ReasonNamePrintable = "name_printable" ReasonAlignedOffset = "aligned_offset" ReasonFileTypeValid = "ftype_valid" ReasonInodeAllocated = "inode_allocated" ReasonInodeUnallocated = "inode_unallocated" // ReasonInodeUnaddressable marks a recovered inode number that cannot // address anything on this volume — strong evidence of a false match. ReasonInodeUnaddressable = "inode_unaddressable" ReasonInFreeSlot = "in_free_slot" )
Evidence codes reported in DirectoryRecord.ConfidenceReasons.
const (
ExtentFlagSparse uint32 = 0x00000001
)
const FilesystemTypeName = "xfs"
FilesystemTypeName is the filesystem label reported by VolumeIntegrityReport.
Variables ¶
var ( ErrInvalidSuperblock = errors.New("invalid or corrupted XFS superblock") ErrInvalidInode = errors.New("invalid or corrupted XFS inode") ErrInvalidInodeNumber = errors.New("invalid inode number") ErrInvalidPath = errors.New("invalid path") ErrInvalidInodeInfo = errors.New("invalid allocation-group inode information") ErrInvalidAttributeData = errors.New("invalid attribute fork data") ErrUnsupportedDirFormat = errors.New("unsupported directory format") ErrInodeNotFound = errors.New("inode not found") ErrUnsupportedFeatureFlag = errors.New("unsupported XFS feature flag") ErrUnsupportedXattrFormat = errors.New("unsupported extended attribute format") ErrVolumeClosed = errors.New("volume is closed") ErrVerificationFailed = errors.New("forensic verification failed") )
Functions ¶
func DirEntryFileTypeName ¶
DirEntryFileTypeName returns a human readable name for an XFS directory entry file type value.
Types ¶
type Concurrency ¶
type Concurrency struct {
// Workers is the maximum number of tasks executed in parallel. Zero or one
// runs sequentially on the calling goroutine. Negative means "one per
// available CPU".
Workers int
}
Concurrency configures optional parallel execution.
The zero value is sequential.
type DirectoryArtifactReport ¶
type DirectoryArtifactReport struct {
InodeNumber uint64 `json:"inode_number"`
Path string `json:"path,omitempty"`
RecordCount int `json:"record_count"`
ActiveCount int `json:"active_count"`
DeletedCount int `json:"deleted_count"`
CarvedCount int `json:"carved_count"`
Records []DirectoryRecord `json:"records"`
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
}
DirectoryArtifactReport summarizes active/deleted/carved records for one directory inode.
type DirectoryEntry ¶
type DirectoryIndexReport ¶
type DirectoryIndexReport struct {
InodeNumber uint64 `json:"inode_number"`
// HasIndex is false for short-form and single-block directories, which
// have no separate hash index to check.
HasIndex bool `json:"has_index"`
// IndexedEntries counts usable entries in the hash index.
IndexedEntries int `json:"indexed_entries"`
// DataEntries counts active entries found by walking the data blocks.
DataEntries int `json:"data_entries"`
// MissingFromIndex lists entries present in the data blocks whose hash and
// address are absent from the index.
MissingFromIndex []string `json:"missing_from_index,omitempty"`
// DanglingIndexEntries counts index entries that do not resolve to a
// readable directory entry.
DanglingIndexEntries int `json:"dangling_index_entries"`
// HashMismatches lists entries whose name does not hash to the value the
// index records for it.
HashMismatches []string `json:"hash_mismatches,omitempty"`
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
}
DirectoryIndexReport compares a directory's hash index against the entries actually present in its data blocks.
The two structures are maintained together by the kernel, so any divergence means the directory was modified by something that did not maintain both — a tampering indicator that no other check in this package provides.
func (DirectoryIndexReport) Consistent ¶
func (r DirectoryIndexReport) Consistent() bool
Consistent reports whether the index and the data blocks agree.
type DirectoryListing ¶
type DirectoryListing struct {
InodeNumber uint64 `json:"inode_number"`
// Entries holds active entries only, in on-disk order.
Entries []DirectoryEntry `json:"entries,omitempty"`
// Records holds every record produced by a forensic scan: active entries,
// free slots and carved candidates. It is populated by the
// ScanDirectoryRecords* APIs. A plain listing leaves it empty, since
// building it would double the cost of the common path; use Entries there.
Records []DirectoryRecord `json:"records,omitempty"`
// Anomalies records structural problems encountered in best-effort mode.
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
// Truncated reports that a cap was reached and results are incomplete.
Truncated bool `json:"truncated,omitempty"`
// BlocksScanned counts directory blocks actually read.
BlocksScanned uint64 `json:"blocks_scanned,omitempty"`
// Format names the directory layout that was parsed.
Format string `json:"format,omitempty"`
}
DirectoryListing is the result of a directory scan.
type DirectoryRecord ¶
type DirectoryRecord struct {
Name string
InodeNumber uint64
IsDeleted bool
Offset uint16
RecordLength uint16
IsCarved bool
Confidence RecoveryConfidence
// Kind describes how this record was obtained. Prefer it over the
// IsDeleted/IsCarved pair when gating downstream decisions.
Kind DirectoryRecordKind
// FileType is the XFS directory entry file type (DirEntryFileType*).
FileType uint8
// BlockIndex is the directory-block index this record was found in.
BlockIndex uint64
// LogicalOffset is the absolute byte offset of the record within the
// directory data stream. Offset is only meaningful within its block.
LogicalOffset uint64
// ConfidenceReasons lists the evidence codes behind Confidence.
ConfidenceReasons []string
}
DirectoryRecord represents an active or deleted slot recovered from directory data structures.
func (DirectoryRecord) IsProbabilistic ¶
func (r DirectoryRecord) IsProbabilistic() bool
IsProbabilistic reports whether the record was carved heuristically and must be presented as a candidate rather than as fact.
func (DirectoryRecord) IsVerified ¶
func (r DirectoryRecord) IsVerified() bool
IsVerified reports whether the record was parsed from intact directory framing and can be treated as fact.
type DirectoryRecordKind ¶
type DirectoryRecordKind = string
DirectoryRecordKind distinguishes how a record was obtained. Confidence alone is not a safe gate: an active entry and a carved candidate can both be ConfidenceHigh. Switch on Kind, or use IsVerified/IsProbabilistic.
const ( // RecordKindActive is an entry parsed from intact directory framing. RecordKindActive DirectoryRecordKind = "active" // RecordKindFreeSlot is an unused-space run. It marks reclaimed space and // carries no recovered name or inode number. RecordKindFreeSlot DirectoryRecordKind = "free_slot" // RecordKindCarved is a probabilistic candidate recovered from free space // by pattern matching. It may be stale, partial, or entirely spurious. RecordKindCarved DirectoryRecordKind = "carved" )
type DirectoryScanOptions ¶
type DirectoryScanOptions struct {
// IncludeDeleted reports free-space runs and carved candidates alongside
// active entries.
IncludeDeleted bool
// BestEffort keeps whatever was recovered when a block is malformed,
// recording a ReportAnomaly and resynchronising instead of failing. This
// is usually what forensic callers want on a damaged image.
BestEffort bool
// MaxBlocks caps the number of directory blocks read. Zero applies the
// default cap.
MaxBlocks uint64
// MaxEntries caps the number of records collected. Zero applies the
// default cap.
MaxEntries int
}
DirectoryScanOptions controls how a directory is walked.
The zero value is strict: any framing error aborts the scan, and only active entries are reported.
type ExtendedAttribute ¶
type FragmentationReport ¶
type FragmentationReport struct {
InodeNumber uint64
Size uint64
DataExtentCount int
AllocatedExtentCount int
SparseExtentCount int
PhysicalFragmentRuns int
HasLogicalHoles bool
HasPhysicalFragmentation bool
HasAnyFragmentationOrHoles bool
}
FragmentationReport summarizes how a file's data is laid out across extents.
type Inode ¶
type Inode struct {
FormatVersion uint8
FileMode uint16
ForkType uint8
OwnerID uint32
GroupID uint32
NumberOfLinks uint32
AccessTimeNS int64
ModificationTimeNS int64
InodeChangeTimeNS int64
CreationTimeNS int64
Size uint64
// NumberOfDataExtents is the data fork extent count, saturated to 32 bits.
// On filesystems with the nrext64 feature the on-disk counter is 64 bits
// wide; prefer DataExtentCount, which cannot overflow.
NumberOfDataExtents uint32
// NumberOfAttributesExtent is the attribute fork extent count, saturated
// to 16 bits. Prefer AttributeExtentCount.
NumberOfAttributesExtent uint16
// DataExtentCount is the full-width data fork extent count.
DataExtentCount uint64
// AttributeExtentCount is the full-width attribute fork extent count.
AttributeExtentCount uint32
// HasBigTimestamps records whether this inode's timestamps were decoded
// using the 64-bit bigtime encoding.
HasBigTimestamps bool
AttributesForkType uint8
DeviceIdentifier uint32
DataForkOffset uint16
DataForkSize uint16
AttributesForkOffset uint16
AttributesForkSize uint16
InlineData []byte
DataExtents []Extent
InlineAttributesData []byte
AttributesExtents []Extent
Raw []byte
}
func (*Inode) AccessTime ¶
func (*Inode) CreationTime ¶
func (*Inode) InodeChangeTime ¶
func (*Inode) IsDirectory ¶
func (*Inode) ModificationTime ¶
type InodeForensicReport ¶
type InodeForensicReport struct {
InodeNumber uint64 `json:"inode_number"`
Path string `json:"path,omitempty"`
Type string `json:"type"`
FileMode uint16 `json:"file_mode"`
ForkType uint8 `json:"fork_type"`
Size uint64 `json:"size"`
OwnerID uint32 `json:"owner_id"`
GroupID uint32 `json:"group_id"`
NumberOfLinks uint32 `json:"number_of_links"`
AccessTime time.Time `json:"access_time"`
ModificationTime time.Time `json:"modification_time"`
InodeChangeTime time.Time `json:"inode_change_time"`
CreationTime time.Time `json:"creation_time,omitempty"`
DataExtentCount int `json:"data_extent_count"`
AttributesExtentCount int `json:"attributes_extent_count"`
HasInlineData bool `json:"has_inline_data"`
Fragmentation FragmentationReport `json:"fragmentation"`
Fragments []InodeFragment `json:"fragments,omitempty"`
ExtendedAttributeNames []string `json:"extended_attribute_names,omitempty"`
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
}
InodeForensicReport is structured metadata for one inode.
type InodeFragment ¶
type InodeFragment struct {
StartOffset uint64 `json:"start_offset"`
EndOffset uint64 `json:"end_offset"`
LengthBytes uint64 `json:"length_bytes"`
LogicalBlockNumber uint64 `json:"logical_block_number"`
PhysicalBlockNumber uint64 `json:"physical_block_number"`
NumberOfBlocks uint32 `json:"number_of_blocks"`
IsSparse bool `json:"is_sparse"`
}
InodeFragment describes one extent from the inode data fork.
type InodeInformation ¶
type ParseError ¶
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
type RecoveryConfidence ¶
type RecoveryConfidence = string
RecoveryConfidence labels how much trust a recovered directory record deserves. It is a string alias so that existing comparisons against plain string literals keep compiling.
const ( ConfidenceLow RecoveryConfidence = "low" ConfidenceMedium RecoveryConfidence = "medium" ConfidenceHigh RecoveryConfidence = "high" )
Confidence levels applied to DirectoryRecord.Confidence.
type ReportAnomaly ¶
type ReportAnomaly struct {
Code string `json:"code"`
Severity string `json:"severity"`
Message string `json:"message"`
Path string `json:"path,omitempty"`
Inode uint64 `json:"inode,omitempty"`
}
ReportAnomaly captures a parsing or consistency concern encountered while building reports.
type ReportOptions ¶
type ReportOptions struct {
// RootPath selects the start path for traversal. Defaults to "/".
RootPath string
// MaxEntries limits the number of discovered inodes in Files.
// Zero or negative means unlimited.
MaxEntries int
// IncludeDirectoryArtifacts includes deleted/carved directory record output
// for each visited directory inode.
IncludeDirectoryArtifacts bool
// VerificationMode controls whether checksum/verification mismatches are
// fatal (`strict`) or recorded as anomalies (`best_effort`).
VerificationMode VerificationMode
// Concurrency optionally analyses discovered inodes in parallel. The
// zero value is sequential. Output is identical regardless of the
// worker count.
Concurrency Concurrency
}
ReportOptions controls how volume-level report generation behaves.
type ReportProvenance ¶
type ReportProvenance struct {
VerificationMode VerificationMode `json:"verification_mode"`
Coverage []string `json:"coverage"`
SuperblockCRCChecked bool `json:"superblock_crc_checked"`
InodeCRCChecked bool `json:"inode_crc_checked"`
}
ReportProvenance captures parser and verification context for reproducibility.
type Superblock ¶
type Superblock struct {
BlockSize uint32
NumberOfBlocks uint64
JournalBlockNumber uint64
RootDirectoryInodeNumber uint64
AllocationGroupSize uint32
NumberOfAllocationGroups uint32
FormatVersion uint8
FeatureFlags uint16
SectorSize uint16
InodeSize uint16
DirectoryBlockSize uint32
VolumeLabel [12]byte
SecondaryFeatureFlags uint32
RelativeBlockNumberBits uint8
RelativeInodeNumberBits uint8
// v5-only feature words. These are zero on v4 filesystems, which do not
// have the fields at all.
FeaturesCompat uint32
FeaturesReadOnlyCompat uint32
FeaturesIncompat uint32
FeaturesLogIncompat uint32
}
func (Superblock) HasBigTimestamps ¶
func (s Superblock) HasBigTimestamps() bool
HasBigTimestamps reports whether inode timestamps use the 64-bit "bigtime" encoding rather than the legacy 32-bit seconds/nanoseconds pair.
func (Superblock) HasFeatureIncompat ¶
func (s Superblock) HasFeatureIncompat(feature uint32) bool
HasFeatureIncompat reports whether an incompatible feature bit is set.
func (Superblock) HasLargeExtentCounts ¶
func (s Superblock) HasLargeExtentCounts() bool
HasLargeExtentCounts reports whether inodes use the 64-bit extent counters introduced by the nrext64 feature.
func (Superblock) NeedsRepair ¶
func (s Superblock) NeedsRepair() bool
NeedsRepair reports whether the filesystem was marked as requiring repair. Such an image was left in an inconsistent state and its metadata should be treated with suspicion.
type VerificationMode ¶
type VerificationMode string
VerificationMode defines how report generation handles verification failures.
const ( // VerificationModeBestEffort records anomalies and continues report generation. VerificationModeBestEffort VerificationMode = "best_effort" // VerificationModeStrict fails report generation on verification mismatch. VerificationModeStrict VerificationMode = "strict" )
type Volume ¶
type Volume struct {
// contains filtered or unexported fields
}
Volume is an XFS volume parser with concurrency-safe read APIs.
func Open ¶
Open parses an XFS volume from a random-access reader.
The reader is not closed by Volume.Close; the caller retains ownership. Use OpenVolumeFromPath when the volume should own its file handle. To read a filesystem embedded in a larger image, pass an io.SectionReader covering the partition.
The returned Volume is safe for concurrent use.
func OpenVolumeFromPath ¶
OpenVolumeFromPath opens an XFS volume from a filesystem path.
This is a convenience wrapper around os.Open and Open. The returned volume owns the underlying file handle, and Volume.Close will close it.
Raw device access generally requires elevated privileges: run as Administrator on Windows and use a path such as \\.\PhysicalDrive0, or read a block device such as /dev/sda1 on Linux.
func (*Volume) AnalyzeInodeFragmentation ¶
func (v *Volume) AnalyzeInodeFragmentation(inodeNumber uint64) (FragmentationReport, error)
AnalyzeInodeFragmentation analyzes the data-fork extent layout of an inode.
func (*Volume) AnalyzeInodeFragmentationByPath ¶
func (v *Volume) AnalyzeInodeFragmentationByPath(path string) (FragmentationReport, error)
AnalyzeInodeFragmentationByPath resolves a file path then analyzes fragmentation.
func (*Volume) Close ¶
Close releases the volume.
It waits for in-flight reads to finish before releasing the backing reader, so it is safe to call concurrently with reads. Subsequent operations return ErrVolumeClosed. Closing an already closed volume returns ErrVolumeClosed.
func (*Volume) DirectoryArtifactReport ¶
func (v *Volume) DirectoryArtifactReport(inodeNumber uint64) (DirectoryArtifactReport, error)
DirectoryArtifactReport reports active/deleted/carved records for one directory.
func (*Volume) DirectoryArtifactReportByPath ¶
func (v *Volume) DirectoryArtifactReportByPath(path string) (DirectoryArtifactReport, error)
DirectoryArtifactReportByPath resolves a path and reports directory artifacts.
func (*Volume) DirectoryParentInode ¶
DirectoryParentInode returns the inode number a directory's ".." refers to.
For short-form directories the parent is stored in the directory header; for block-backed directories it is the ".." entry in the first data block. It is the only in-inode link back up the tree, which makes it the starting point for reconstructing the path of an orphaned directory.
func (*Volume) DirectoryParentInodeByPath ¶
DirectoryParentInodeByPath resolves a directory path and returns its parent inode number.
func (*Volume) GetRootInode ¶
func (*Volume) InodeForensicReport ¶
func (v *Volume) InodeForensicReport(inodeNumber uint64) (InodeForensicReport, error)
InodeForensicReport builds a structured report for one inode.
func (*Volume) InodeForensicReportByPath ¶
func (v *Volume) InodeForensicReportByPath(path string) (InodeForensicReport, error)
InodeForensicReportByPath resolves a path and reports that inode.
func (*Volume) IsClosed ¶
IsClosed reports whether the volume has been closed.
It is a point-in-time answer: on a volume shared with a goroutine that may call Close, prefer acting on ErrVolumeClosed from the operation itself.
func (*Volume) ListDirectoryEntries ¶
func (v *Volume) ListDirectoryEntries(inodeNumber uint64) ([]DirectoryEntry, error)
ListDirectoryEntries lists active entries for a directory inode.
Short-form, block, leaf, node and btree directories are all supported: entries always live in the directory's data-block region, which is walked one directory block at a time.
func (*Volume) ListDirectoryEntriesByPath ¶
func (v *Volume) ListDirectoryEntriesByPath(path string) ([]DirectoryEntry, error)
ListDirectoryEntriesByPath resolves a directory path and lists its entries.
func (*Volume) ListDirectoryEntriesWithOptions ¶
func (v *Volume) ListDirectoryEntriesWithOptions(inodeNumber uint64, options DirectoryScanOptions) (DirectoryListing, error)
ListDirectoryEntriesWithOptions lists a directory under explicit scan options.
func (*Volume) ListInodeExtendedAttributes ¶
func (v *Volume) ListInodeExtendedAttributes(inodeNumber uint64) ([]ExtendedAttribute, error)
ListInodeExtendedAttributes lists decoded inode extended attributes.
For block-based attribute trees, returned entries preserve traversal order. If duplicate fully-qualified names are present, duplicates are preserved in the returned slice (no deduplication is performed).
func (*Volume) ListRootDirectoryEntries ¶
func (v *Volume) ListRootDirectoryEntries() ([]DirectoryEntry, error)
ListRootDirectoryEntries lists entries for the root directory inode.
func (*Volume) OpenInodeByPath ¶
OpenInodeByPath resolves an absolute path and opens the corresponding inode.
func (*Volume) ReadFileData ¶
ReadFileData reads all data bytes from a non-directory inode.
func (*Volume) ReadFileDataByPath ¶
ReadFileDataByPath resolves an absolute path and reads all file data bytes.
func (*Volume) ReadInodeAttributeForkData ¶
ReadInodeAttributeForkData reads the inode attributes fork payload. For inline attributes, this returns the inline bytes; for extent/btree forks, it reconstructs data from mapped extents up to the attributes fork size.
func (*Volume) ReadInodeData ¶
ReadInodeData reads file data from an inode at offset. It supports inline data and extent-list backed regular files.
func (*Volume) ReportWithContext ¶
ReportWithContext builds a combined forensic report, honouring context cancellation.
Discovery of the inode set is sequential, because a directory must be read before its children are known. Per-inode analysis then runs across the pool configured by options.Concurrency. The result does not depend on the worker count: entries are stored by position and sorted before returning.
func (*Volume) ReportWithOptions ¶
func (v *Volume) ReportWithOptions(options ReportOptions) (*XFSReport, error)
ReportWithOptions builds a combined forensic report.
It is equivalent to ReportWithContext with a background context.
func (*Volume) ResolveInodeByPath ¶
ResolveInodeByPath resolves an absolute path to an inode number.
func (*Volume) ScanDirectoryRecords ¶
func (v *Volume) ScanDirectoryRecords(inodeNumber uint64) ([]DirectoryRecord, error)
ScanDirectoryRecords lists active and deleted directory records for an inode.
Records carrying IsCarved are probabilistic: see DirectoryRecord.Kind and IsProbabilistic before presenting them as fact.
func (*Volume) ScanDirectoryRecordsByPath ¶
func (v *Volume) ScanDirectoryRecordsByPath(path string) ([]DirectoryRecord, error)
ScanDirectoryRecordsByPath resolves a directory path and scans its records.
func (*Volume) ScanDirectoryRecordsByPathWithOptions ¶
func (v *Volume) ScanDirectoryRecordsByPathWithOptions(path string, options DirectoryScanOptions) (DirectoryListing, error)
ScanDirectoryRecordsByPathWithOptions resolves a path and scans it.
func (*Volume) ScanDirectoryRecordsWithOptions ¶
func (v *Volume) ScanDirectoryRecordsWithOptions(inodeNumber uint64, options DirectoryScanOptions) (DirectoryListing, error)
ScanDirectoryRecordsWithOptions scans a directory for active, free and carved records under explicit scan options.
func (*Volume) Superblock ¶
func (v *Volume) Superblock() Superblock
func (*Volume) VerifyDirectoryIndex ¶
func (v *Volume) VerifyDirectoryIndex(inodeNumber uint64) (DirectoryIndexReport, error)
VerifyDirectoryIndex cross-checks a directory's hash index against its data blocks. Directories with no index report HasIndex false and are consistent by definition.
func (*Volume) VerifyDirectoryIndexByPath ¶
func (v *Volume) VerifyDirectoryIndexByPath(path string) (DirectoryIndexReport, error)
VerifyDirectoryIndexByPath resolves a path and verifies its hash index.
func (*Volume) VolumeIntegrityReport ¶
func (v *Volume) VolumeIntegrityReport() (VolumeIntegrityReport, error)
VolumeIntegrityReport builds a metadata/geometry report for the open volume.
type VolumeError ¶
func (*VolumeError) Error ¶
func (e *VolumeError) Error() string
func (*VolumeError) Unwrap ¶
func (e *VolumeError) Unwrap() error
type VolumeIntegrityReport ¶
type VolumeIntegrityReport struct {
Type string `json:"type"`
FormatVersion uint8 `json:"format_version"`
BlockSize uint32 `json:"block_size"`
InodeSize uint16 `json:"inode_size"`
DirectoryBlockSize uint32 `json:"directory_block_size"`
RootDirectoryInodeNumber uint64 `json:"root_directory_inode"`
AllocationGroupSize uint32 `json:"allocation_group_size"`
NumberOfAllocationGroups uint32 `json:"number_of_allocation_groups"`
NumberOfBlocks uint64 `json:"number_of_blocks"`
VolumeLabel string `json:"volume_label,omitempty"`
SuperblockCRCChecked bool `json:"superblock_crc_checked"`
SuperblockCRCValid bool `json:"superblock_crc_valid"`
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
}
VolumeIntegrityReport summarizes core XFS geometry and validation findings.
type XFSReport ¶
type XFSReport struct {
GeneratedAt time.Time `json:"generated_at"`
RootPath string `json:"root_path"`
Provenance ReportProvenance `json:"provenance"`
Volume VolumeIntegrityReport `json:"volume"`
Files []InodeForensicReport `json:"files"`
DirectoryArtifacts []DirectoryArtifactReport `json:"directory_artifacts,omitempty"`
Anomalies []ReportAnomaly `json:"anomalies,omitempty"`
}
XFSReport is a combined volume + inode + directory-artifact report.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic
command
|
|
|
dirscan
command
|
|
|
extract
command
|
|
|
forensics
command
|
|
|
fragmentation
command
|
|
|
inode_read
command
|
|
|
report
command
|
|
|
traverse
command
|
|
|
xattrs
command
|