836 {
837 std::set<uint64_t> ntfs_offsets;
838 std::set<uint64_t> fat32_offsets;
839 std::set<uint64_t> exfat_offsets;
840 std::set<uint64_t> ext4_offsets;
841 std::set<uint64_t> btrfs_offsets;
842 std::set<uint64_t> xfs_offsets;
843 std::set<uint64_t> hfs_offsets;
844 for (
const auto& r : report.
results) {
845 if (
r.type ==
"NTFS volume" ||
r.type ==
"Lost NTFS partition candidate" ||
r.type ==
"NTFS candidate") ntfs_offsets.insert(
r.offset_bytes);
846 if (
r.type ==
"FAT32 volume" ||
r.type ==
"Lost FAT32 partition candidate") fat32_offsets.insert(
r.offset_bytes);
847 if (
r.type ==
"exFAT volume" ||
r.type ==
"Lost exFAT partition candidate") exfat_offsets.insert(
r.offset_bytes);
848 if (
r.type ==
"ext4 volume" ||
r.type ==
"Lost ext4 partition candidate" ||
r.type ==
"ext4 candidate") ext4_offsets.insert(
r.offset_bytes);
849 if (
r.type ==
"Btrfs volume" ||
r.type ==
"Lost Btrfs partition candidate" ||
r.type ==
"Btrfs candidate") btrfs_offsets.insert(
r.offset_bytes);
850 if (
r.type ==
"XFS volume" ||
r.type ==
"Lost XFS partition candidate") xfs_offsets.insert(
r.offset_bytes);
851 if (
r.type ==
"HFS+ volume" ||
r.type ==
"HFSX volume" ||
r.type ==
"Lost HFS+ partition candidate") hfs_offsets.insert(
r.offset_bytes);
852 }
853
854 try {
855 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "ntfs");
856 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "fat32");
857 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "exfat");
858 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "ext4");
859 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "btrfs");
860 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "xfs");
861 fs::create_directories(fs::path(output_dir) / "filesystem_recovered" / "hfs");
862 } catch (const std::exception& ex) {
863 error = ex.what();
864 return false;
865 }
866
867
868 for (uint64_t offset : ntfs_offsets) {
869 NtfsRecovery ntfs(reader);
870 std::string local_error;
871 if (!ntfs.recover(offset, output_dir, recovered, logs, local_error)) {
872 logs.push_back(
trs(
"NTFS recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
873 }
874 }
875
876 for (uint64_t offset : fat32_offsets) {
877 Fat32Recovery fat32(reader);
878 const fs::path out_root = fs::path(output_dir) / "filesystem_recovered" / "fat32" / ("offset_" + std::to_string(offset));
879 std::string local_error;
880 if (!fat32.recover(offset, out_root, recovered, logs, local_error)) {
881 logs.push_back(
trs(
"FAT32 recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
882 }
883 }
884
885 for (uint64_t offset : exfat_offsets) {
886 ExfatRecovery exfat(reader);
887 const fs::path out_root = fs::path(output_dir) / "filesystem_recovered" / "exfat" / ("offset_" + std::to_string(offset));
888 std::string local_error;
889 if (!exfat.recover(offset, out_root, recovered, logs, local_error)) {
890 logs.push_back(
trs(
"exFAT recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
891 }
892 }
893
894 for (uint64_t offset : ext4_offsets) {
895 Ext4Recovery ext4(reader);
896 std::string local_error;
897 if (!ext4.recover(offset, output_dir, recovered, logs, local_error)) {
898 logs.push_back(
trs(
"ext4 recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
899 }
900 }
901
902 for (uint64_t offset : btrfs_offsets) {
903 BtrfsRecovery btrfs(reader);
904 std::string local_error;
905 if (!btrfs.recover(offset, output_dir, recovered, logs, local_error)) {
906 logs.push_back(
trs(
"Btrfs recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
907 }
908 }
909
910 for (uint64_t offset : xfs_offsets) {
911 XfsRecovery xfs(reader);
912 std::string local_error;
913 if (!xfs.recover(offset, output_dir, recovered, logs, local_error)) {
914 logs.push_back(
trs(
"XFS recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
915 }
916 }
917
918 for (uint64_t offset : hfs_offsets) {
919 HfsRecovery hfs(reader);
920 std::string local_error;
921 if (!hfs.recover(offset, output_dir, recovered, logs, local_error)) {
922 logs.push_back(
trs(
"HFS+ recovery skipped or failed at offset") + std::string(
" ") + std::to_string(offset) +
": " + local_error);
923 }
924 }
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942 {
943 const char* env = std::getenv("BASTIONGUARD_CARVING");
944 if (env != nullptr && env[0] == '1') {
945 carving::CarvingOptions opts;
946
947
948
949 std::string carve_err;
950 const size_t before = recovered.size();
952 logs, carve_err);
953 const size_t carved = recovered.size() - before;
954 if (!carve_err.empty()) {
955 logs.push_back(
trs(
"Carving error: ") + carve_err);
956 }
957 logs.push_back(
trs(
"Carving pass added ") +
958 std::to_string(carved) +
trs(
" file(s)"));
959 }
960 }
961
962 return true;
963}
std::string trs(const char *msgid)
bool run_carving(DiskReader &reader, const std::string &output_dir, const CarvingOptions &opts, std::vector< RecoveredFileRecord > &recovered, std::vector< std::string > &logs, std::string &error)
std::vector< ScanResult > results