From 2cee77b108d3b309e13078e5620626d88fefd86b Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Tue, 12 Apr 2022 23:55:08 +0200 Subject: [PATCH] Adjust I/O buffer size according to file size + allow slightly bigger maximum buffer size. --- frontend/src/crypt.c | 65 ++++++++++++++++++++++++----------------- frontend/src/platform.h | 2 +- frontend/src/pwgen.c | 2 +- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/frontend/src/crypt.c b/frontend/src/crypt.c index 1845b55..13ca107 100644 --- a/frontend/src/crypt.c +++ b/frontend/src/crypt.c @@ -28,7 +28,7 @@ static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull; -#define BUFFER_SIZE 65536U +#define MAX_BUFFER_SIZE 1048576U // 1 MiB // ========================================================================== // Auxiliary functions @@ -36,25 +36,36 @@ static const uint64_t MAGIC_NUMBER = 0x243F6A8885A308D3ull; static int open_files(FILE **const file_in, FILE **const file_out, const CHR *const input_path, const CHR *const output_path) { - if (!(*file_in = FOPEN(input_path, T("rb")))) + if (!(*file_in = FOPEN(input_path, "rb"))) { FPRINTF(stderr, T("Error: Failed to open input file \"%") T(PRISTR) T("\" for reading!\n\n%") T(PRISTR) T("\n\n"), input_path, STRERROR(errno)); *file_out = NULL; return EXIT_FAILURE; } - if (!(*file_out = FOPEN(output_path, T("wb")))) + if (!(*file_out = FOPEN(output_path, "wb"))) { FPRINTF(stderr, T("Error: Failed to open output file \"%") T(PRISTR) T("\" for writing!\n\n%") T(PRISTR) T("\n\n"), output_path, STRERROR(errno)); return EXIT_FAILURE; } - setvbuf(*file_in, NULL, _IOFBF, (((8U * BUFFER_SIZE) + (BUFSIZ - 1U)) / BUFSIZ) * BUFSIZ); - setvbuf(*file_out, NULL, _IOFBF, (((8U * BUFFER_SIZE) + (BUFSIZ - 1U)) / BUFSIZ) * BUFSIZ); + //setvbuf(*file_in, NULL, _IOFBF, (((8U * BUFFER_SIZE) + (BUFSIZ - 1U)) / BUFSIZ) * BUFSIZ); + //setvbuf(*file_out, NULL, _IOFBF, (((8U * BUFFER_SIZE) + (BUFSIZ - 1U)) / BUFSIZ) * BUFSIZ); return EXIT_SUCCESS; } +static size_t get_buffer_size(const uint64_t file_size) +{ + const uint64_t upper_limit = file_size / 101U; + size_t pwr2, result = 0U; + for (pwr2 = 1U; (pwr2 <= MAX_BUFFER_SIZE) && (pwr2 <= upper_limit); pwr2 <<= 1) + { + result = pwr2; + } + return BOUND(BUFSIZ, result, MAX_BUFFER_SIZE); +} + static void init_slunk_param(slunkparam_t *const param, const crypt_options_t *const options) { slunkcrypt_bzero(param, sizeof(slunkparam_t)); @@ -82,15 +93,10 @@ int encrypt(const char *const passphrase, const CHR *const input_path, const CHR { slunkcrypt_t ctx = SLUNKCRYPT_NULL; slunkparam_t param; - FILE* file_in = NULL, * file_out = NULL; - int result = EXIT_FAILURE, status; - - uint8_t *buffer = malloc(BUFFER_SIZE * sizeof(uint8_t)); - if (!buffer) - { - FPUTS(T("Error: Failed to allocate the I/O buffer!\n\n"), stderr); - goto clean_up; - } + FILE *file_in = NULL, *file_out = NULL; + uint8_t *buffer = NULL; + size_t buffer_size = BUFSIZ; + int result = EXIT_FAILURE, status = -1; if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) { @@ -109,6 +115,12 @@ int encrypt(const char *const passphrase, const CHR *const input_path, const CHR goto clean_up; } + if (!(buffer = malloc((buffer_size = get_buffer_size(file_size)) * sizeof(uint8_t)))) + { + FPUTS(T("Error: Failed to allocate the I/O buffer!\n\n"), stderr); + goto clean_up; + } + FPUTS(T("Encrypting file contents, please be patient... "), stderr); fflush(stderr); @@ -145,7 +157,7 @@ int encrypt(const char *const passphrase, const CHR *const input_path, const CHR while (bytes_read < file_size) { const uint64_t bytes_remaining = file_size - bytes_read; - const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; + const size_t request_len = (bytes_remaining < buffer_size) ? ((size_t)bytes_remaining) : buffer_size; const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); if (count > 0U) { @@ -247,7 +259,7 @@ clean_up: if (buffer) { - slunkcrypt_bzero(buffer, BUFFER_SIZE * sizeof(uint8_t)); + slunkcrypt_bzero(buffer, buffer_size * sizeof(uint8_t)); free(buffer); } @@ -267,14 +279,9 @@ int decrypt(const char *const passphrase, const CHR *const input_path, const CHR slunkcrypt_t ctx = SLUNKCRYPT_NULL; slunkparam_t param; FILE *file_in = NULL, *file_out = NULL; - int result = EXIT_FAILURE, status; - - uint8_t *buffer = malloc(BUFFER_SIZE * sizeof(uint8_t)); - if (!buffer) - { - FPUTS(T("Error: Failed to allocate the I/O buffer!\n\n"), stderr); - goto clean_up; - } + uint8_t *buffer = NULL; + size_t buffer_size = BUFSIZ; + int result = EXIT_FAILURE, status = -1; if (open_files(&file_in, &file_out, input_path, output_path) != EXIT_SUCCESS) { @@ -297,6 +304,12 @@ int decrypt(const char *const passphrase, const CHR *const input_path, const CHR FPRINTF(stderr, T("Warning: File size is *not* an integer multiple of %u, ignoring excess bytes!\n\n"), (unsigned)sizeof(uint64_t)); } + if (!(buffer = malloc((buffer_size = get_buffer_size(file_size)) * sizeof(uint8_t)))) + { + FPUTS(T("Error: Failed to allocate the I/O buffer!\n\n"), stderr); + goto clean_up; + } + FPUTS(T("Decrypting file contents, please be patient... "), stderr); fflush(stderr); @@ -328,7 +341,7 @@ int decrypt(const char *const passphrase, const CHR *const input_path, const CHR while (bytes_read < read_limit) { const uint64_t bytes_remaining = read_limit - bytes_read; - const size_t request_len = (bytes_remaining < BUFFER_SIZE) ? ((size_t)bytes_remaining) : BUFFER_SIZE; + const size_t request_len = (bytes_remaining < buffer_size) ? ((size_t)bytes_remaining) : buffer_size; const size_t count = fread(buffer, sizeof(uint8_t), request_len, file_in); if (count > 0U) { @@ -442,7 +455,7 @@ clean_up: if (buffer) { - slunkcrypt_bzero(buffer, BUFFER_SIZE * sizeof(uint8_t)); + slunkcrypt_bzero(buffer, buffer_size * sizeof(uint8_t)); free(buffer); } diff --git a/frontend/src/platform.h b/frontend/src/platform.h index 7999fe8..9c7fb57 100644 --- a/frontend/src/platform.h +++ b/frontend/src/platform.h @@ -73,7 +73,7 @@ # define FPUTS(X,Y) fputws((X),(Y)) # define FPRINTF(X,Y,...) fwprintf((X),(Y),__VA_ARGS__) # define REMOVE(X) _wremove((X)) -# define FOPEN(X,Y) _wfsopen((X),(Y),_SH_SECURE) +# define FOPEN(X,Y) _wfsopen((X),_T(Y) L"S",_SH_SECURE) # define STRERROR(X) _wcserror((X)) # ifdef __USE_MINGW_ANSI_STDIO # define PRISTR "ls" diff --git a/frontend/src/pwgen.c b/frontend/src/pwgen.c index 7294abb..77e90bb 100644 --- a/frontend/src/pwgen.c +++ b/frontend/src/pwgen.c @@ -65,7 +65,7 @@ char *read_passphrase(const CHR *const file_name) goto finish; } - passphrase_file = STRICMP(file_name, T("-")) ? FOPEN(file_name, T("rb")) : stdin; + passphrase_file = STRICMP(file_name, T("-")) ? FOPEN(file_name, "rb") : stdin; if (!passphrase_file) { FPRINTF(stderr, T("Error: Failed to open passphrase file \"%") T(PRISTR) T("\" for reading!\n\n%") T(PRISTR) T("\n\n"), file_name, STRERROR(errno));