Skip to content
API Documentation
BastionGuard™
LostPartitionFinder Class Reference

#include <lost_partition_finder.hpp>

Static Public Member Functions

static std::vector< ScanResult > find (DiskReader &reader, const std::vector< ScanResult > &known_results, std::vector< std::string > &logs)

Detailed Description

Definition at line 8 of file lost_partition_finder.hpp.

Member Function Documentation

◆ find()

std::vector< ScanResult > LostPartitionFinder::find ( DiskReader & reader,
const std::vector< ScanResult > & known_results,
std::vector< std::string > & logs )
static

Definition at line 159 of file lost_partition_finder.cpp.

161 {
162 std::vector<ScanResult> out;
163 std::vector<Range> claimed_ranges;
164 claimed_ranges.reserve(known_results.size());
165
166 for (const auto& r : known_results) {
167 if (r.kind == ResultKind::Partition && r.size_bytes > 0) {
168 claimed_ranges.push_back({r.offset_bytes, r.offset_bytes + r.size_bytes});
169 }
170 }
171
172 const uint64_t disk_size = reader.size();
173 const uint64_t max_scan = std::min<uint64_t>(disk_size, std::min<uint64_t>(DEFAULT_MAX_SCAN, HARD_MAX_SCAN));
174
175 logs.push_back(trs("Lost partition finder: deep scan started."));
176 logs.push_back(trs("Lost partition scan stride:") + std::string(" ") +
177 std::to_string(SCAN_STRIDE / MiB) + " MiB");
178 logs.push_back(trs("Lost partition scan range:") + std::string(" ") +
179 std::to_string(max_scan / GiB) + " GiB");
180
181 // Bug #10/#13 fix: scan with fixed 1 MiB stride from offset SCAN_STRIDE
182 // up to max_scan. Partitions are 1 MiB aligned on every modern OS, and the
183 // first MiB is reserved for MBR/GPT, never a partition boundary.
184 for (uint64_t offset = SCAN_STRIDE; offset + 4096 < max_scan; offset += SCAN_STRIDE) {
185 std::array<unsigned char, 512> sector{};
186 if (!reader.read_at(offset, sector.data(), sector.size())) {
187 continue;
188 }
189
190 if (is_ntfs(sector)) {
191 const uint64_t size_bytes = ntfs_size_bytes(sector);
192 const uint64_t end = size_bytes > 0 ? offset + size_bytes : offset + MiB;
193 if (!overlaps(claimed_ranges, offset, end)) {
195 offset,
196 size_bytes,
197 "Lost NTFS partition candidate",
198 trs("Lost partition finder"),
199 trs("Unallocated NTFS boot sector candidate"),
200 0.88});
201 claimed_ranges.push_back({offset, end});
202 }
203 } else if (is_fat32(sector)) {
204 const uint64_t size_bytes = fat32_size_bytes(sector);
205 const uint64_t end = size_bytes > 0 ? offset + size_bytes : offset + MiB;
206 if (!overlaps(claimed_ranges, offset, end)) {
208 offset,
209 size_bytes,
210 "Lost FAT32 partition candidate",
211 trs("Lost partition finder"),
212 trs("Unallocated FAT32 boot sector candidate"),
213 0.84});
214 claimed_ranges.push_back({offset, end});
215 }
216 } else if (is_exfat(sector)) {
217 const uint64_t size_bytes = exfat_size_bytes(sector);
218 const uint64_t end = size_bytes > 0 ? offset + size_bytes : offset + MiB;
219 if (!overlaps(claimed_ranges, offset, end)) {
221 offset,
222 size_bytes,
223 "Lost exFAT partition candidate",
224 trs("Lost partition finder"),
225 trs("Unallocated exFAT boot sector candidate"),
226 0.86});
227 claimed_ranges.push_back({offset, end});
228 }
229 } else if (looks_ext4(reader, offset)) {
230 // Bug #20 fix: compute real ext4 volume size instead of leaving 0
231 const uint64_t size_bytes = ext4_size_bytes(reader, offset);
232 const uint64_t end = size_bytes > 0 ? offset + size_bytes : offset + MiB;
233 if (!overlaps(claimed_ranges, offset, end)) {
235 offset,
236 size_bytes,
237 "Lost ext4 partition candidate",
238 trs("Lost partition finder"),
239 trs("Unallocated ext4 superblock candidate"),
240 0.80});
241 claimed_ranges.push_back({offset, end});
242 }
243 } else if (looks_btrfs(reader, offset)) {
244 // Bug #20 fix: compute real btrfs volume size instead of leaving 0
245 const uint64_t size_bytes = btrfs_size_bytes(reader, offset);
246 const uint64_t end = size_bytes > 0 ? offset + size_bytes : offset + MiB;
247 if (!overlaps(claimed_ranges, offset, end)) {
249 offset,
250 size_bytes,
251 trs("Lost Btrfs partition candidate"),
252 trs("Lost partition finder"),
253 trs("Unallocated Btrfs superblock candidate"),
254 0.81});
255 claimed_ranges.push_back({offset, end});
256 }
257 } else if (looks_xfs(reader, offset)) {
258 // Use parse_superblock to also validate geometry (rejects false
259 // positives where 'XFSB' appears as random bytes).
260 const uint64_t size_bytes = xfs_size_bytes(reader, offset);
261 if (size_bytes > 0) {
262 const uint64_t end = offset + size_bytes;
263 if (!overlaps(claimed_ranges, offset, end)) {
265 offset,
266 size_bytes,
267 "Lost XFS partition candidate",
268 trs("Lost partition finder"),
269 trs("Unallocated XFS superblock candidate"),
270 0.86});
271 claimed_ranges.push_back({offset, end});
272 }
273 }
274 } else if (looks_hfs(reader, offset)) {
275 // HFS+/HFSX: validate geometry through parse_volume_header.
276 const uint64_t size_bytes = hfs_size_bytes(reader, offset);
277 if (size_bytes > 0) {
278 const uint64_t end = offset + size_bytes;
279 if (!overlaps(claimed_ranges, offset, end)) {
281 offset,
282 size_bytes,
283 "Lost HFS+ partition candidate",
284 trs("Lost partition finder"),
285 trs("Unallocated HFS+/HFSX volume header candidate"),
286 0.85});
287 claimed_ranges.push_back({offset, end});
288 }
289 }
290 }
291 }
292
293 if (max_scan < disk_size) {
294 logs.push_back(trs("Lost partition finder: scan limited to first ") +
295 std::to_string(max_scan / GiB) + " GiB " +
296 trs("(disk is larger; remaining area not scanned)."));
297 }
298 logs.push_back(trs("Lost partition finder: deep scan completed."));
299 return out;
300}
bool read_at(uint64_t offset, void *buffer, size_t len)
uint64_t size() const
std::string trs(const char *msgid)
Definition i18n.cpp:22
@ Partition
Definition models.hpp:8
@ LostPartitionCandidate
Definition models.hpp:9
bool is_exfat(const std::array< unsigned char, 512 > &sector)
bool is_fat32(const std::array< unsigned char, 512 > &sector)
bool looks_xfs(DiskReader &reader, uint64_t offset)
bool looks_hfs(DiskReader &reader, uint64_t offset)
uint64_t xfs_size_bytes(DiskReader &reader, uint64_t offset)
uint64_t hfs_size_bytes(DiskReader &reader, uint64_t offset)
bool looks_btrfs(DiskReader &reader, uint64_t offset)
uint64_t ntfs_size_bytes(const std::array< unsigned char, 512 > &b)
bool is_ntfs(const std::array< unsigned char, 512 > &b)
uint64_t exfat_size_bytes(const std::array< unsigned char, 512 > &b)
uint64_t ext4_size_bytes(DiskReader &reader, uint64_t offset)
uint64_t btrfs_size_bytes(DiskReader &reader, uint64_t offset)
bool overlaps(const std::vector< Range > &ranges, uint64_t start, uint64_t end)
uint64_t fat32_size_bytes(const std::array< unsigned char, 512 > &b)
bool looks_ext4(DiskReader &reader, uint64_t offset)

References LostPartitionCandidate, Partition, DiskReader::read_at(), DiskReader::size(), and trs().

Referenced by ScannerEngine::run_scan().


The documentation for this class was generated from the following files: