1 /* ---------------------------------------------------------------------------------------------- */
2 /* MHash-384 - Example application (plain C) */
3 /* Copyright(c) 2016-2018 LoRd_MuldeR <mulder2@gmx.de> */
5 /* Permission is hereby granted, free of charge, to any person obtaining a copy of this software */
6 /* and associated documentation files (the "Software"), to deal in the Software without */
7 /* restriction, including without limitation the rights to use, copy, modify, merge, publish, */
8 /* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the */
9 /* Software is furnished to do so, subject to the following conditions: */
11 /* The above copyright notice and this permission notice shall be included in all copies or */
12 /* substantial portions of the Software. */
14 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING */
15 /* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
16 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, */
17 /* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */
18 /* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
19 /* ---------------------------------------------------------------------------------------------- */
22 #include "mhash_384.h"
23 #include "utilities.h"
27 #include "self_test.h"
36 #define BUFF_SIZE 4096
38 /*process a single file*/
39 static int process_file(const int multi_file, const param_t *const param, uint64_t *const bytes_total, CHAR *const file_name)
42 uint64_t file_size, bytes_processed;
45 uint8_t buffer[BUFF_SIZE], result[MHASH_384_LEN];
47 uint_fast16_t update_iter;
49 /*clear error indicators first*/
52 /*check if file is accessible*/
53 if (file_name && ACCESS(file_name, R_OK))
55 PRINT_ERROR(T("Specified input file is inaccessible"));
60 if (!(source = file_name ? FOPEN(file_name, T("rb")) : stdin))
62 PRINT_ERROR(T("Failed to open specified input file"));
66 /*determine file properties*/
67 if(!get_file_info(source, &file_size, &file_type))
69 PRINT_ERROR(T("Failed to determine file properties"));
74 if(file_type == S_IFDIR)
77 PRINT_ERROR(T("Unsupported file type encountered"));
82 mhash_384_initialize(&context);
86 /*process file contents*/
87 while (!(ferror(source) || feof(source)))
89 count = (uint_fast32_t)fread(buffer, sizeof(uint8_t), BUFF_SIZE, source);
92 mhash_384_update(&context, buffer, count);
93 bytes_processed += count;
95 if (g_interrupted || (count != BUFF_SIZE))
99 if (param->show_progress && ((update_iter++ & 0x3FF) == 0))
101 print_progress(file_size, bytes_processed);
106 /*check file error status*/
107 if ((!g_interrupted) && ferror(source))
109 errno = EIO; /*fread() doesn't set errno!*/
110 PRINT_ERROR(T("Error encountered while reading from file"));
115 /*update gloabl counter*/
116 *bytes_total += bytes_processed;
119 if (param->show_progress)
121 print_progress(file_size, bytes_processed);
122 FPRINTF(stderr, T(" %s\n"), g_interrupted ? T("stop!") : T("done"));
126 /*finalize the hash*/
127 mhash_384_finalize(&context, result);
129 /*output result as Hex string*/
130 if (param->raw_output)
132 fwrite(result, sizeof(uint8_t), MY_HASH_LENGTH, stdout);
136 print_digest(stdout, result, param->use_upper_case, param->curly_brackets);
139 FPRINTF(stdout, param->curly_brackets ? T(" /* %s */") : T(" %s"), file_name);
141 FPUTC(T('\n'), stdout);
147 /*check for interruption*/
150 FPUTS(T("\nInterrupted!\n\n"), stderr);
164 /*The "main" function*/
165 int MAIN(int argc, CHAR *argv[])
169 clock_t ts_start, ts_finish;
170 uint64_t bytes_total;
172 /*set up std i/o streams*/
176 /*disable buffering*/
177 setvbuf(stderr, NULL, _IONBF, 0);
179 /*install CTRL+C handler*/
180 signal(SIGINT, sigint_handler);
182 /*process command-line arguments*/
183 if ((file_id = parse_arguments(¶m, argc, argv)) < 1)
188 /*select mode of operation*/
189 switch (param.opmode)
199 FPUTS("Not compiled with self-test code!\n", stderr);
206 /*set up stdout mode*/
207 SETMODE(stdout, param.raw_output);
212 retval = EXIT_SUCCESS;
214 /*process all input files*/
217 const int multi_file = file_id < (argc - 1);
218 while (file_id < argc)
220 if (!process_file(multi_file, ¶m, &bytes_total, argv[file_id++]))
222 retval = EXIT_FAILURE;
223 if (!param.ignore_errors)
232 if(!process_file(0U, ¶m, &bytes_total, NULL))
234 retval = EXIT_FAILURE;
242 if (param.enable_bench)
244 const double time_total = (ts_finish - ts_start) / (double)CLOCKS_PER_SEC;
245 const double throughput = bytes_total / (time_total + DBL_EPSILON);
246 FPRINTF(stderr, T("\nProcessed %") T(PRIu64) T(" bytes in %.1f seconds, %.1f bytes/sec.\n\n"), bytes_total, time_total, throughput);