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) {
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
182
183
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
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 }
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 }
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 }
230
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 }
244
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 }
258
259
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 }
275
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)
std::string trs(const char *msgid)
bool is_exfat(const std::array< unsigned char, 512 > §or)
bool is_fat32(const std::array< unsigned char, 512 > §or)
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)
constexpr uint64_t SCAN_STRIDE
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)