Skip to content
API Documentation
BastionGuard™
anonymous_namespace{recovery_exporter.cpp} Namespace Reference

Functions

bool export_range (DiskReader &reader, uint64_t offset, uint64_t size, const fs::path &out_path, std::string &error, std::function< bool()> cancel_cb)
bool should_export (const ScanResult &r)
std::string sanitize (const std::string &s)
void write_recovery_manifest (const fs::path &output_dir, const ScanReport &report, const std::unordered_set< size_t > &selected_indices, bool filter_results, const RecoverySummary &summary, const std::vector< RecoveredFileRecord > &fs_recovered, const std::vector< CarvedFile > &carved, std::string &error)
std::vector< std::pair< uint64_t, uint64_t > > selected_carve_ranges (const ScanReport &report, const std::unordered_set< size_t > &selected_indices, bool filter_results, uint64_t source_size)

Function Documentation

◆ export_range()

bool anonymous_namespace{recovery_exporter.cpp}::export_range ( DiskReader & reader,
uint64_t offset,
uint64_t size,
const fs::path & out_path,
std::string & error,
std::function< bool()> cancel_cb )

Definition at line 20 of file recovery_exporter.cpp.

26 {
27 std::ofstream out(out_path, std::ios::binary);
28 if (!out) {
29 error = trs("Unable to create output file") + std::string(": ") + out_path.string();
30 return false;
31 }
32
33 std::vector<unsigned char> buffer(1024 * 1024);
34
35 uint64_t remaining = size;
36 uint64_t cursor = offset;
37
38 while (remaining > 0)
39 {
40 if (cancel_cb && cancel_cb())
41 {
42 error = trs("Recovery cancelled by user");
43 return false;
44 }
45
46 const size_t chunk = static_cast<size_t>(
47 std::min<uint64_t>(buffer.size(), remaining));
48
49 if (!reader.read_at(cursor, buffer.data(), chunk))
50 {
51 error = trs("Read error while exporting partition image");
52 return false;
53 }
54
55 out.write(reinterpret_cast<const char*>(buffer.data()),
56 static_cast<std::streamsize>(chunk));
57
58 if (!out)
59 {
60 error = trs("Write error while exporting partition image");
61 return false;
62 }
63
64 cursor += chunk;
65 remaining -= chunk;
66 }
67
68 return true;
69 }
bool read_at(uint64_t offset, void *buffer, size_t len)
std::string trs(const char *msgid)
Definition i18n.cpp:22

References export_range(), DiskReader::read_at(), and trs().

Referenced by export_range().

◆ sanitize()

std::string anonymous_namespace{recovery_exporter.cpp}::sanitize ( const std::string & s)

Definition at line 79 of file recovery_exporter.cpp.

80 {
81 std::string out;
82
83 for (char c : s)
84 {
85 if (isalnum(static_cast<unsigned char>(c)))
86 out.push_back(c);
87 else if (c == ' ' || c == '-' || c == '_')
88 out.push_back('_');
89 }
90
91 if (out.empty())
92 out = "item";
93
94 return out;
95 }

References sanitize().

Referenced by sanitize().

◆ selected_carve_ranges()

std::vector< std::pair< uint64_t, uint64_t > > anonymous_namespace{recovery_exporter.cpp}::selected_carve_ranges ( const ScanReport & report,
const std::unordered_set< size_t > & selected_indices,
bool filter_results,
uint64_t source_size )

Definition at line 148 of file recovery_exporter.cpp.

153 {
154 std::vector<std::pair<uint64_t, uint64_t>> ranges;
155
156 auto add_range = [&](uint64_t offset, uint64_t size)
157 {
158 if (size == 0 || offset >= source_size)
159 return;
160
161 size = std::min<uint64_t>(size, source_size - offset);
162
163 if (ranges.empty())
164 {
165 ranges.emplace_back(offset, size);
166 return;
167 }
168
169 auto& last = ranges.back();
170
171 const uint64_t last_end = last.first + last.second;
172
173 if (offset <= last_end)
174 {
175 const uint64_t new_end = std::max<uint64_t>(last_end, offset + size);
176 last.second = new_end - last.first;
177 }
178 else
179 {
180 ranges.emplace_back(offset, size);
181 }
182 };
183
184 if (!filter_results)
185 {
186 ranges.emplace_back(0, source_size);
187 return ranges;
188 }
189
190 std::vector<std::pair<uint64_t, uint64_t>> temp;
191
192 for (size_t idx = 0; idx < report.results.size(); ++idx)
193 {
194 if (!selected_indices.count(idx))
195 continue;
196
197 const auto& r = report.results[idx];
198
199 if (r.offset_bytes == 0 && r.size_bytes == 0)
200 continue;
201
202 switch (r.kind)
203 {
210 temp.emplace_back(r.offset_bytes, r.size_bytes);
211 break;
212 default:
213 break;
214 }
215 }
216
217 if (temp.empty())
218 return ranges;
219
220 std::sort(temp.begin(), temp.end(),
221 [](const auto& a, const auto& b)
222 {
223 return a.first < b.first;
224 });
225
226 for (const auto& r : temp)
227 add_range(r.first, r.second);
228
229 return ranges;
230 }
@ Partition
Definition models.hpp:8
@ LostPartitionCandidate
Definition models.hpp:9
@ NtfsMetadata
Definition models.hpp:13
@ FilesystemCandidate
Definition models.hpp:10
@ FilesystemVolume
Definition models.hpp:11
std::vector< ScanResult > results
Definition models.hpp:40

References FilesystemCandidate, FilesystemVolume, LostPartitionCandidate, NtfsMetadata, NtfsVolume, Partition, ScanReport::results, and selected_carve_ranges().

Referenced by selected_carve_ranges().

◆ should_export()

bool anonymous_namespace{recovery_exporter.cpp}::should_export ( const ScanResult & r)

Definition at line 71 of file recovery_exporter.cpp.

72 {
73 return r.kind == ResultKind::Partition ||
76 r.kind == ResultKind::NtfsVolume;
77 }

References FilesystemVolume, LostPartitionCandidate, NtfsVolume, Partition, and should_export().

Referenced by should_export().

◆ write_recovery_manifest()

void anonymous_namespace{recovery_exporter.cpp}::write_recovery_manifest ( const fs::path & output_dir,
const ScanReport & report,
const std::unordered_set< size_t > & selected_indices,
bool filter_results,
const RecoverySummary & summary,
const std::vector< RecoveredFileRecord > & fs_recovered,
const std::vector< CarvedFile > & carved,
std::string & error )

Definition at line 97 of file recovery_exporter.cpp.

106 {
107 std::ofstream out(output_dir / "recovery_manifest.txt", std::ios::binary);
108
109 if (!out)
110 {
111 error = trs("Unable to create output file") + std::string(": ") +
112 (output_dir / "recovery_manifest.txt").string();
113 return;
114 }
115
116 out << "input=" << report.input_path << "\n";
117 out << "selected_filter=" << (filter_results ? 1 : 0) << "\n";
118 out << "selected_results=" << selected_indices.size() << "\n";
119 out << "exported_images=" << summary.exported_images.size() << "\n";
120 out << "recovered_files=" << summary.recovered_files.size() << "\n\n";
121
122 out << "[filesystem_recovery]\n";
123
124 for (const auto& rf : fs_recovered)
125 {
126 out << rf.filesystem << '\t'
127 << rf.integrity << '\t'
128 << rf.size_bytes << '\t'
129 << rf.original_path << '\t'
130 << rf.output_path;
131
132 if (!rf.note.empty())
133 out << '\t' << rf.note;
134
135 out << '\n';
136 }
137
138 out << "\n[carved]\n";
139
140 for (const auto& cf : carved)
141 {
142 out << cf.type << '\t'
143 << cf.size << '\t'
144 << cf.output_path << '\n';
145 }
146 }
std::vector< std::string > exported_images
std::vector< std::string > recovered_files
std::string input_path
Definition models.hpp:38

References RecoverySummary::exported_images, ScanReport::input_path, RecoverySummary::recovered_files, trs(), and write_recovery_manifest().

Referenced by write_recovery_manifest().