160 const std::vector<ScanResult>& known_results,
161 std::vector<std::string>& logs) {
162 std::vector<ScanResult> out;
163 std::vector<Range> claimed_ranges;
164 claimed_ranges.reserve(known_results.size());
166 for (
const auto& r : known_results) {
168 claimed_ranges.push_back({r.offset_bytes, r.offset_bytes + r.size_bytes});
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));
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");
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())) {
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)) {
197 "Lost NTFS partition candidate",
198 trs(
"Lost partition finder"),
199 trs(
"Unallocated NTFS boot sector candidate"),
201 claimed_ranges.push_back({offset, end});
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)) {
210 "Lost FAT32 partition candidate",
211 trs(
"Lost partition finder"),
212 trs(
"Unallocated FAT32 boot sector candidate"),
214 claimed_ranges.push_back({offset, end});
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)) {
223 "Lost exFAT partition candidate",
224 trs(
"Lost partition finder"),
225 trs(
"Unallocated exFAT boot sector candidate"),
227 claimed_ranges.push_back({offset, end});
229 }
else if (looks_ext4(reader, offset)) {
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)) {
237 "Lost ext4 partition candidate",
238 trs(
"Lost partition finder"),
239 trs(
"Unallocated ext4 superblock candidate"),
241 claimed_ranges.push_back({offset, end});
243 }
else if (looks_btrfs(reader, offset)) {
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)) {
251 trs(
"Lost Btrfs partition candidate"),
252 trs(
"Lost partition finder"),
253 trs(
"Unallocated Btrfs superblock candidate"),
255 claimed_ranges.push_back({offset, end});
257 }
else if (looks_xfs(reader, offset)) {
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)) {
267 "Lost XFS partition candidate",
268 trs(
"Lost partition finder"),
269 trs(
"Unallocated XFS superblock candidate"),
271 claimed_ranges.push_back({offset, end});
274 }
else if (looks_hfs(reader, offset)) {
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)) {
283 "Lost HFS+ partition candidate",
284 trs(
"Lost partition finder"),
285 trs(
"Unallocated HFS+/HFSX volume header candidate"),
287 claimed_ranges.push_back({offset, end});
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)."));
298 logs.push_back(
trs(
"Lost partition finder: deep scan completed."));