Skip to content

Instantly share code, notes, and snippets.

@KoKuToru
Last active May 12, 2022 17:56
Show Gist options
  • Save KoKuToru/0b69d208882cae9822b82a3cefbf225b to your computer and use it in GitHub Desktop.
Save KoKuToru/0b69d208882cae9822b82a3cefbf225b to your computer and use it in GitHub Desktop.
File Fixer
// 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