From 53e3fdee50f05590acb6c7a7d2a7ed55924892da Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sat, 20 Jul 2024 03:19:23 +0300 Subject: [PATCH] create a faster implementation --- include/common.h | 2 ++ include/corrupter.h | 3 --- src/corrupter.c | 66 +++++++++++++++++---------------------------- src/main.c | 11 +------- 4 files changed, 28 insertions(+), 54 deletions(-) diff --git a/include/common.h b/include/common.h index 065ab4b..e6fb1c1 100644 --- a/include/common.h +++ b/include/common.h @@ -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 */ diff --git a/include/corrupter.h b/include/corrupter.h index 3a63667..8d87a50 100644 --- a/include/corrupter.h +++ b/include/corrupter.h @@ -20,9 +20,6 @@ /* structures */ struct _corrupter_result { bool error; - size_t hit_counter, - file_size, - damaged_bytes; }; struct _corrupter_param { diff --git a/src/corrupter.c b/src/corrupter.c index 2d16445..6964563 100644 --- a/src/corrupter.c +++ b/src/corrupter.c @@ -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; diff --git a/src/main.c b/src/main.c index 99cf158..0bc8e2f 100644 --- a/src/main.c +++ b/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