mirror of
https://git.disroot.org/80486DX2-66/polonium.git
synced 2024-11-09 15:02:20 +05:30
create a faster implementation
This commit is contained in:
parent
f81100fbf1
commit
53e3fdee50
@ -89,5 +89,7 @@ typedef off_t file_offset_t;
|
||||
#define LOOP_ACTION_CONFIG(f, x) \
|
||||
f(x); \
|
||||
continue
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#endif /* _COMMON_H */
|
||||
|
@ -20,9 +20,6 @@
|
||||
/* structures */
|
||||
struct _corrupter_result {
|
||||
bool error;
|
||||
size_t hit_counter,
|
||||
file_size,
|
||||
damaged_bytes;
|
||||
};
|
||||
|
||||
struct _corrupter_param {
|
||||
|
@ -3,12 +3,15 @@
|
||||
/* cached operations */
|
||||
const size_t UINT16_MAX_PLUS_1 = UINT16_MAX + 1;
|
||||
|
||||
/* global variables */
|
||||
uint16_t desired_chance;
|
||||
|
||||
/* function definitions */
|
||||
static bool get_chance(uint16_t desired_chance);
|
||||
static bool get_chance(void);
|
||||
static bool is_line_ending(byte c);
|
||||
|
||||
/* function implementations */
|
||||
static bool get_chance(uint16_t desired_chance) {
|
||||
static bool get_chance(void) {
|
||||
/* TODO: remove this multi-line comment before merging into main branch
|
||||
// algorithm v1
|
||||
// calculate the cumulative distribution function (CDF)
|
||||
@ -31,15 +34,10 @@ static bool get_chance(uint16_t desired_chance) {
|
||||
// algorithm v2
|
||||
if (desired_chance == UINT16_MAX)
|
||||
return true;
|
||||
else if (desired_chance == 0)
|
||||
return false;
|
||||
|
||||
uint16_t cdf[UINT16_MAX_PLUS_1];
|
||||
memset(cdf, 0, sizeof(cdf));
|
||||
for (uint16_t i = 0; i < UINT16_MAX; i++) {
|
||||
cdf[i] = (i <= desired_chance) ? i + 1 : cdf[i - 1];
|
||||
}
|
||||
|
||||
uint16_t random_number = mt_next() & UINT16_MAX;
|
||||
return random_number < cdf[desired_chance];
|
||||
return (bool) (mt_next() & 1);
|
||||
}
|
||||
|
||||
static bool is_line_ending(byte c) {
|
||||
@ -53,7 +51,7 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
|
||||
|
||||
// copy and cast parameters
|
||||
FILE* file = param->file;
|
||||
uint8_t probability = param->probability;
|
||||
desired_chance = param->probability;
|
||||
file_offset_t threshold = (file_offset_t) param->threshold;
|
||||
uint8_t config = param->config;
|
||||
|
||||
@ -70,6 +68,9 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
|
||||
FSEEK_MACRO(file, FILE_OFFSET_C(0), SEEK_END);
|
||||
end = FTELL_MACRO(file);
|
||||
|
||||
// calculate parameters
|
||||
file_offset_t increment_value = MAX((UINT16_MAX - desired_chance) >> 12, 1);
|
||||
|
||||
// determine file boundaries
|
||||
const char* failed_function = NULL;
|
||||
file_boundaries_t* boundaries = NULL;
|
||||
@ -93,22 +94,14 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
|
||||
break;
|
||||
}
|
||||
|
||||
// output data to result
|
||||
result->file_size = end;
|
||||
result->damaged_bytes = 0;
|
||||
|
||||
// initialize the PRNG
|
||||
mt_seed(param->seed);
|
||||
|
||||
for (size_t pass = 0; pass < param->passes; pass++) {
|
||||
// display information
|
||||
printf("Pass: %zu/%zu", pass + 1, param->passes);
|
||||
fflush(stdout);
|
||||
|
||||
rewind(file);
|
||||
|
||||
// iterate over the file contents
|
||||
for (file_offset_t i = start; i < end; i++) {
|
||||
for (file_offset_t i = start; i < end; i += increment_value) {
|
||||
FSEEK_MACRO(file, i, SEEK_SET);
|
||||
byte byte_value;
|
||||
if (fread(&byte_value, sizeof(byte), 1, file) != 1) {
|
||||
@ -122,27 +115,13 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
|
||||
else if (READ_CONFIG(C_LINE_ENDINGS) && is_line_ending(byte_value))
|
||||
continue;
|
||||
|
||||
// generate bit mask
|
||||
unsigned char damage_left = (unsigned char) param->threshold;
|
||||
static bool bit_mask[CHAR_BIT];
|
||||
for (unsigned char bit = 0; bit < CHAR_BIT; bit++) {
|
||||
if (get_chance(probability) && (damage_left > 0)) {
|
||||
bit_mask[bit] = true;
|
||||
damage_left--;
|
||||
} else {
|
||||
bit_mask[bit] = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool damaged_byte = false;
|
||||
for (unsigned char bit = 0; bit < threshold; bit++) {
|
||||
if (bit_mask[bit] == false)
|
||||
for (unsigned char shift = 0; shift < threshold; shift++) {
|
||||
if (get_chance())
|
||||
continue;
|
||||
|
||||
byte_value = FLIP_BIT(byte_value, bit);
|
||||
result->hit_counter++;
|
||||
unsigned char bit = 1 << shift;
|
||||
|
||||
damaged_byte = true;
|
||||
byte_value = FLIP_BIT(byte_value, bit);
|
||||
|
||||
// write the modified byte back to the file
|
||||
FSEEK_MACRO(file, i, SEEK_SET);
|
||||
@ -155,11 +134,16 @@ Corrupter_Result* corrupt_file(Corrupter_Param* param) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (damaged_byte)
|
||||
result->damaged_bytes++;
|
||||
// display progress
|
||||
if (((i - start) & 65535 /* reporting frequency */) == 0) {
|
||||
putc('.', stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
puts(" [OK]");
|
||||
// display progress
|
||||
putc('\n', stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
result->error = false;
|
||||
|
11
src/main.c
11
src/main.c
@ -325,6 +325,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
puts("Working, please wait");
|
||||
fflush(stdout);
|
||||
|
||||
Corrupter_Param param = {
|
||||
@ -354,16 +355,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
putchar('\n');
|
||||
|
||||
if (result->damaged_bytes) {
|
||||
size_t dmg = result->damaged_bytes, fsize = result->file_size,
|
||||
passes = param.passes;
|
||||
printf("Byte hit counter: %" PRIuMAX " / %" PRIuMAX " = %.3Lf%%\n",
|
||||
(uintmax_t) dmg, (uintmax_t) (fsize * passes),
|
||||
((long double) dmg * 100.l) / (long double) (fsize * passes));
|
||||
} else {
|
||||
puts("No bytes were damaged");
|
||||
}
|
||||
|
||||
free(result);
|
||||
|
||||
// finish working with the file
|
||||
|
Loading…
Reference in New Issue
Block a user