Directories | |
| src | |
A C++20 data-recovery component for the BastionGuard Linux security suite. Reads disk images and live block devices to recover files from 6 filesystem families plus a filesystem-agnostic carving pass.
Built from scratch – no external filesystem libraries (no libfsxfs, libhfs, libapfs, libntfs-3g). Only zlib (mandatory) and optionally liblzo2 + libzstd for Btrfs compressed extent decompression.
Recovers regular files, directories, and (where applicable) symlinks from filesystems on a Linux host. Designed for these scenarios, in order of typical success rate:
Detection is automatic. Per-filesystem support level:
FAT32 Live files: FULL Deleted files: Best-effort (assumes contiguous, ~70% success) LFN UTF-16 names: YES LFN deleted name reconstruction: YES (where LFN slots intact)
exFAT Live files: FULL Deleted files: Best-effort (assumes contiguous, ~70%) No-FAT-chain optimization: YES (faster on contiguous large files) TexFAT (transactional exFAT): NOT supported (rare)
NTFS Live files: FULL Deleted files: YES (via live MFT scan + $LogFile redo + $MFTMirr fallback) LZNT1 compressed streams: YES (homegrown decoder) Multiple ADS (alternate data streams): YES Reparse points (symlinks/junctions): RECREATED as real symlinks on output (with sidecar fallback) Sequence number tracking: YES (orphan detection) $I30 directory index walker: YES (recovers filenames from corrupted MFT records, handles renames) EFS-encrypted streams: SKIPPED (cannot decrypt, requires Windows account keys); reported in the log USN journal: summary sidecar only
ext4 Live files: FULL Deleted files: YES (dtime != 0 inodes; journal replay) Extents: FULL recursive walk Classic indirect block map: YES (legacy ext2/3 compat) Sparse files / UNINITIALIZED extents: YES (zero-fill, correct) inline_data feature: YES, including:
Btrfs Live files: FULL Deleted files: NO (Btrfs is copy-on-write; live tree only) Compressed extents: YES, all three: zlib, LZO, zstd (LZO and zstd use Btrfs's chunked framing) RAID 5/6 reconstruction: YES (notable feature; uncommon in recovery tools) Multi-device pools: Single-device only Snapshots: Default subvolume only (no enumeration) Encryption: n/a (Btrfs has no native encryption)
XFS V4 / V5 Live files: FULL Deleted files: V5 only, via FINOBT (Free Inode B+tree). V4 has no FINOBT, so no deleted recovery on V4. Inode formats: extent, btree, local (dirs + symlinks) BMBT extent decoding: 9 + 43 byte formats Sparse inodes: YES CRC32C checksums: Validated where present Reflink, rmapbt, project quotas: NOT supported (rare)
HFS+ / HFSX Live files: FULL Deleted files: NO (catalog B-tree records reused immediately on delete) Extents Overflow file: YES (files with > 8 extents) Hardlinks: YES (resolved via HFS+ Private Data
A filesystem-agnostic byte-pattern scanner that recovers files WITHOUT relying on filesystem metadata. Useful when MFT/inode table/catalog is destroyed.
Opt-in via environment variable:
BASTIONGUARD_CARVING=1 ./bastionguard-recovery-data ...
Recovers 19 file format families:
Images: JPEG, PNG, GIF87a, GIF89a, BMP, TIFF (LE+BE) Documents: PDF, OLE Compound File (DOC/XLS/PPT old) Archives: ZIP (covers DOCX/XLSX/PPTX/ODT/JAR) Audio: WAV, MP3 (ID3v2 + MPEG-1/2 Layer III sync), OGG Video: MP4, MOV, AVI (via RIFF), MKV, WebM Database: SQLite
Honest limits:
On Debian/Ubuntu install:
sudo apt-get install build-essential cmake zlib1g-dev \
liblzo2-dev libzstd-dev
This package is part of the BastionGuard suite. Standalone build:
mkdir build && cd build cmake .. make -j$(nproc)
The recovery binary takes a target device or image and an output directory:
sudo bastionguard-recovery-data /dev/sdb1 /tmp/recovered/
Or with a disk image:
bastionguard-recovery-data /path/to/image.dd /tmp/recovered/
For full pipeline (FS recovery + carving):
BASTIONGUARD_CARVING=1 bastionguard-recovery-data /dev/sdb1 /tmp/recovered/
Recovered files are organized under the output directory:
/tmp/recovered/
filesystem_recovered/
ntfs/offset_<N>/
live/<original_path> <- live MFT files
deleted/<path> <- deleted MFT files
logfile_recovered/ <- $LogFile redo recoveries
orphaned-seq-mismatch/ <- seq mismatch records
ext4/offset_<N>/
<recovered tree>
btrfs/offset_<N>/
<recovered tree>
xfs/offset_<N>/
<recovered tree>
deleted/inode_<N>.bin <- FINOBT deleted-inode dumps
hfs/offset_<N>/
<recovered tree>
FAT32/offset_<N>/
<recovered tree>
deleted/ <- deleted-recovery
exFAT/offset_<N>/
<recovered tree>
deleted/
carved/ <- only if carving enabled
jpeg/<offset>_<n>.jpg
png/<offset>_<n>.png
...
Each recovered file is logged with metadata:
Honest per-scenario success rates (% of recoverable files actually recovered, where "recoverable" means "the data still exists on disk in some form"):
| Scenario | FAT32 | exFAT | NTFS | ext4 | Btrfs | XFS | HFS+ |
|---|---|---|---|---|---|---|---|
| Live volume | 98% | 98% | 98% | 97% | 95% | 96% | 95% |
| Recently deleted | 60% | 60% | 88% | 85% | 0% | 80% | 0% |
| Quick format (with carving) | 85% | 85% | 85% | 85% | 85% | 85% | 85% |
| Corrupt FS metadata | 50% | 50% | 75% | 60% | 40% | 60% | 60% |
| MBR/GPT destroyed (carving) | | | ~70% (filesystem-agnostic) |
Btrfs and HFS+ have 0% deleted-file recovery because both reuse metadata structures immediately on delete (Btrfs is copy-on-write with no in-place free list; HFS+ catalog records are reused immediately). This is a fundamental property of the filesystem, not a missing feature in this recovery tool.
For comparison with other recovery tools (estimates, your mileage may vary):
| Tool | Typical NTFS recovery |
|---|---|
| TestDisk (open source) | ~75% |
| BastionGuard Recovery | ~88% |
| R-Studio (commercial ~$80) | ~92% |
| WinHex / X-Ways (~€1500) | ~96% |
| EnCase (~€3000) | ~98% |
BastionGuard sits above TestDisk (gold standard open source) due to: $LogFile redo recovery, $I30 directory index walker, $MFTMirr fallback, sequence number tracking, deleted-FAT contiguous-guess, and 19-format file carving. It approaches commercial entry-level tools without their licensing cost.
Notable distinctive features vs other open-source recovery:
By priority of remaining work (none of these are blocking for the current release):
The codebase ships with 14 unit/integration tests for the incrementally-built filesystems (XFS, HFS+) and key features (decmpfs, carving, ext4 inline data, NTFS $I30 parser). All pass:
test_xfs_finobt_integration ........... PASS test_hfs_format ....................... PASS (8 sub-tests) test_hfs_btree_walk ................... PASS test_hfs_fork_io ...................... PASS (4 sub-tests) test_hfs_session3_integration ......... PASS test_hfs_session45_integration ........ PASS test_hfs_decmpfs_unit ................. PASS (4 sub-tests) test_decmpfs_xattr_unit ............... PASS (5 sub-tests) test_hfs_unicode ...................... PASS (10 sub-tests) test_btrfs_lzo ........................ PASS (3 sub-tests) test_ext4_inline_data ................. PASS test_ext4_inline_xattr ............... PASS test_carving_integration .............. PASS test_ntfs_i30_parser .................. PASS (4 sub-tests)
FAT32, exFAT, full NTFS, full ext4, full Btrfs do NOT yet have synthetic-FS integration tests in the package – only compile-time warnings are checked (-Wall -Wextra -Wpedantic, zero warnings on all 23 filesystem source files).
The tests are standalone .cpp files in the development workspace; CTest integration in CMakeLists.txt is a planned improvement.
For the detailed history of features added by session, see:
CHANGELOG_BUGFIX.txt (initial bug fixes)
CHANGELOG_XFS_S1.txt..S5.txt (XFS support, 5 sessions)
CHANGELOG_HFS_S1.txt..S3.txt + S4_S5.txt (HFS+ support, 5 sessions)
AUDIT_REPORT.txt (codebase audit, gaps)
CHANGELOG_FUNCTIONAL_FIXES.txt (ext4 inline_data,
Btrfs LZO/zstd chunked,
NTFS EFS reporting)
CHANGELOG_NTFS_LOGFILE_PLUS_DELETED.txt (NTFS $LogFile redo,
FAT/exFAT deleted)
CHANGELOG_CARVING.txt (initial 9-format carving)
CHANGELOG_CARVING_EXT_AND_MFTMIRR.txt (carving 9->19 formats,
NTFS $MFTMirr fallback)
CHANGELOG_PRIORITY_2_GAPS_CLOSED.txt (HFS+ Attributes walker
+ decmpfs type 3,
ext4 xattr inline overflow)
CHANGELOG_EXT4_SPARSE_NTFS_SEQ_REPARSE.txt (ext4 sparse fix,
NTFS seq tracking,
NTFS reparse->symlink)
CHANGELOG_NTFS_I30_WALKER.txt (NTFS $I30 directory
index walker)
BastionGuard™ Recovery Data is free and open-source software released under the GNU General Public License, version 3 or (at your option) any later version (GPL-3.0-or-later).
Copyright (C) 2025–2026 Calogero Scarnà. See the LICENSE file for the complete GNU GPLv3 terms. Bundled third-party components retain their respective compatible licenses. The GPL does not grant rights to use the BastionGuard™ name or branding as a trademark.
Production-ready for the supported filesystems and scenarios listed above. Known gaps are documented honestly. APFS support is the next major investment.
For bug reports, feature requests, or recovery scenarios that underperform: please report with disk image samples (where appropriate) and the relevant log output.
Compile mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=/usr
The installed desktop launcher starts BastionGuard through bastionguard-recovery-data-pkexec, so the application asks for administrator authentication at startup and runs as root. This is required for raw block-device access on many Linux systems. No activation key, machine binding, or license validation is required; scanning and recovery features are available without restrictions.