Last active
May 12, 2022 17:56
-
-
Save KoKuToru/0b69d208882cae9822b82a3cefbf225b to your computer and use it in GitHub Desktop.
File Fixer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// g++ file_fixer.cpp --std=c++20 -O3 -o file_fixer | |
// usage: ./file_fixer file_to_fix file_ref_a file_ref_b .... | |
#include <string_view> | |
#include <iostream> | |
#include <span> | |
#include <vector> | |
#include <unistd.h> | |
#include <sys/mman.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
constexpr size_t CHUNK = 1024*1024; //mb | |
int main_cpp(std::span<const std::string> args) { | |
size_t max_size; | |
std::vector<std::span<unsigned char>> maps; | |
for (const auto arg : args) { | |
std::cout << "OPEN " << arg; | |
const bool writeable = (arg == args[0]); | |
if (writeable) { | |
std::cout << " (WRITE)"; | |
} | |
std::cout << std::endl; | |
int fd = open(arg.c_str(), writeable ? O_RDWR : O_RDONLY); | |
if (fd == -1) { | |
std::cerr << "Couln't open file " << arg << std::endl; | |
return -1; | |
} | |
struct stat sb; | |
if (fstat(fd, &sb) == -1) { | |
std::cerr << "Couln't get file size " << arg << std::endl; | |
return -2; | |
} | |
const size_t size = sb.st_size; | |
unsigned char* addr = (unsigned char*)mmap(NULL, size, writeable ? PROT_WRITE : PROT_READ, MAP_SHARED, fd, 0); | |
if (addr == MAP_FAILED) { | |
std::cerr << "Couln't memory map file " << arg << std::endl; | |
return -3; | |
} | |
max_size = std::max(max_size, size); | |
maps.push_back(std::span{ | |
addr, | |
size | |
}); | |
} | |
std::cout << "VALIDATE" << std::endl; | |
bool fix = false; | |
const size_t size = maps[0].size(); | |
for (size_t i = 0; i < size; ++i) { | |
if ((i % CHUNK) == 0) { | |
std::cout << "\e[2K" << (i / 1024 / 1024) << " / " << (size / 1024 / 1024) << "MiB" << std::flush << "\r"; | |
} | |
bool first = true; | |
unsigned char data; | |
unsigned char odata; | |
for (const auto map: maps) { | |
if (first) { | |
first = false; | |
data = map[i]; | |
odata = data; | |
} | |
if (i >= map.size()) { | |
continue; | |
} | |
if (odata != 0x00) { | |
if (map[i] != 0x00 && odata != map[i]) { | |
std::cerr << "WRONG DATA" << std::endl; | |
return -2; | |
} | |
} else if (data == 0x00) { | |
odata = map[i]; | |
} | |
} | |
if (data == 0x00 && odata != 0x00) { | |
fix = true; | |
} | |
} | |
std::cout << "\e[2K\r"; | |
if (!fix) { | |
std::cout << "NOTHING TO FIX" << std::endl; | |
return 0; | |
} | |
std::cout << "FIX" << std::endl; | |
for (size_t i = 0; i < size; ++i) { | |
if ((i % CHUNK) == 0) { | |
std::cout << "\e[2K" << (i / 1024 / 1024) << " / " << (size / 1024 / 1024) << "MiB" << std::flush << "\r"; | |
} | |
if (maps[0][i] == 0x00) { | |
for (const auto map: maps) { | |
if (i >= map.size()) { | |
continue; | |
} | |
if (map[i] != 0x00) { | |
maps[0][i] = map[i]; | |
break; | |
} | |
} | |
} | |
} | |
std::cout << "\e[2K\r"; | |
return 0; | |
} | |
int main(int argc, const char* argv[]) { | |
static std::vector<std::string> args(argv + 1, argv + argc); | |
return main_cpp(args); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment