1 /* ---------------------------------------------------------------------------------------------- */
2 /* MHash-384 - Example application (utility functions) */
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 /* ---------------------------------------------------------------------------------------------- */
21 #ifndef MHASH_CLI_UTILS_INCLUDED
22 #define MHASH_CLI_UTILS_INCLUDED
24 /*Enable large files*/
25 #define __USE_LARGEFILE64 1
53 #define MY_HASH_LENGTH mhash_384::MHash384::HASH_LEN
55 #define MY_HASH_LENGTH MHASH_384_LEN
59 static const CHAR *const BUILD_DATE = T(__DATE__);
67 typedef struct param_t
80 typedef struct version_t
89 static version_t get_version(void)
91 version_t version_info;
93 mhash_384::MHash384::version(version_info.major, version_info.minor, version_info.patch);
95 version_info.major = MHASH_384_VERSION_MAJOR;
96 version_info.minor = MHASH_384_VERSION_MINOR;
97 version_info.patch = MHASH_384_VERSION_PATCH;
103 static void print_logo(void)
105 const version_t version = get_version();
106 FPRINTF(stderr, T("\nMHash384 v%u.%u.%u, simple fast portable header-only hashing library [%s]\n"), (unsigned int)version.major, (unsigned int)version.minor, (unsigned int)version.patch, BUILD_DATE);
107 FPRINTF(stderr, T("Copyright(c) 2016-%s LoRd_MuldeR <mulder2@gmx.de>, released under the MIT License.\n\n"), &BUILD_DATE[7]);
111 static void print_vers(void)
113 const version_t version = get_version();
114 FPRINTF(stdout, T("mhash-384 version %u.%u.%u (built %s)\n"), (unsigned int)version.major, (unsigned int)version.minor, (unsigned int)version.patch, BUILD_DATE);
119 #define EXE_SUFFIX ".exe"
121 #define EXE_SUFFIX ""
124 /*Print help screen*/
125 static void print_help(void)
128 FPRINTF(stderr, T("Built with %s v%u.%u.%u on %s [%s]\n\n"), T(COMPILER_TYPE), COMPILER_VERS_MAJOR, COMPILER_VERS_MINOR, COMPILER_VERS_PATCH, T(SYSTEM_TYPE), T(COMPILER_ARCH));
129 FPUTS(T("Usage:\n"), stderr);
130 FPRINTF(stderr, T(" mhash384%s [options] [input_file]...\n\n"), T(EXE_SUFFIX));
131 FPUTS(T("Options:\n"), stderr);
132 FPUTS(T(" -p, --progress show progress while processing\n"), stderr);
133 FPUTS(T(" -u, --upper print digest in upper case letters\n"), stderr);
134 FPUTS(T(" -c, --curly print digest using C-style curly brackets\n"), stderr);
135 FPUTS(T(" -r, --raw output \"raw\" bytes (no \"hex\" encoding)\n"), stderr);
136 FPUTS(T(" -b, --bench compute and print throughput\n"), stderr);
137 FPUTS(T(" -i, --ignore ignore errors and proceed with ntext file\n"), stderr);
138 FPUTS(T(" -v, --version print the version string and exit\n"), stderr);
139 FPUTS(T(" -t, --test execute self-test and exit\n"), stderr);
140 FPUTS(T(" -h, --help print this help screen and exit\n\n"), stderr);
141 FPUTS(T("If no input file is specified, input will be read from STDIN.\n\n"), stderr);
144 /*Check specific option*/
145 #define IS_OPTION(ARGV, IS_LONG, NAME_SHRT, NAME_LONG) \
146 ((IS_LONG) ? (!STRICMP((ARGV), (NAME_LONG))) : (TOLOWER(*(ARGV)) == (NAME_SHRT)))
149 static int parse_option(param_t *param, const CHAR *const argv, const int is_long)
151 if (IS_OPTION(argv, is_long, T('b'), T("bench")))
153 param->enable_bench = 1;
156 if (IS_OPTION(argv, is_long, T('i'), T("ignore")))
158 param->ignore_errors = 1;
161 if (IS_OPTION(argv, is_long, T('p'), T("progress")))
163 param->show_progress = 1;
166 if (IS_OPTION(argv, is_long, T('u'), T("upper")))
168 param->use_upper_case = 1;
171 if (IS_OPTION(argv, is_long, T('c'), T("curly")))
173 param->curly_brackets = 1;
176 if (IS_OPTION(argv, is_long, T('r'), T("raw")))
178 param->raw_output = 1;
181 if (IS_OPTION(argv, is_long, T('h'), T("help")))
183 param->opmode = OPMODE_HELP;
186 if (IS_OPTION(argv, is_long, T('v'), T("version")))
188 param->opmode = OPMODE_VERS;
191 if (IS_OPTION(argv, is_long, T('t'), T("test")))
193 param->opmode = OPMODE_TEST;
200 static int parse_arguments(param_t *const param, int argc, CHAR *argv[])
203 memset(param, 0, sizeof(param_t));
204 for (i = 1; i < argc; ++i)
206 if (argv[i][0] == T('-'))
208 if (argv[i][1] == T('-'))
215 if (!parse_option(param, &argv[i][2], 1))
218 FPRINTF(stderr, T("Unknown option:\n%s\n\n"), argv[i]);
225 for (j = 1; argv[i][j]; ++j)
227 if(!parse_option(param, &argv[i][j], 0))
230 FPRINTF(stderr, T("Unknown option(s):\n%s\n\n"), argv[i]);
237 break; /*no more options*/
239 if (param->raw_output && (param->use_upper_case || param->curly_brackets))
242 FPRINTF(stderr, T("Error: Options \"-%c\" and \"-r\" are mutually exclusive!\n\n"), param->use_upper_case ? T('u') : T('c'));
249 static int get_file_info(FILE *const file, uint64_t *const file_size, MODE_T *const file_type)
252 if (!FSTAT64(FILENO(file), &info))
254 *file_type = (info.st_mode & S_IFMT);
255 *file_size = (*file_type == S_IFREG) ? (uint64_t)info.st_size : UINT64_MAX;
262 static void print_progress(const uint64_t size_total, const uint64_t size_processed)
264 if (size_total != UINT64_MAX)
266 const double progress = (((double)size_processed) / (((double)size_total) + DBL_EPSILON)) * 100.0;
267 FPRINTF(stderr, T("\r%.1f%% of %") T(PRIu64) T(" bytes processed..."), progress, size_total);
271 FPRINTF(stderr, T("\r%") T(PRIu64) T(" bytes processed..."), size_processed);
276 #define _PUT_HEX_CHAR(W,X,Y,Z) FPUTC(W[((X) >> (Y)) & 0xFU], (Z))
277 static void print_digest(FILE *const stream, const uint8_t *const digest, const int uppercase, const int curly)
279 static const CHAR *const HEX_UPR = T("0123456789ABCDEF");
280 static const CHAR *const HEX_LWR = T("0123456789abcdef");
281 const CHAR *const hex = uppercase ? HEX_UPR : HEX_LWR;
285 FPUTS(T("{ "), stream);
287 for (count = 0U; count < MY_HASH_LENGTH; ++count)
291 FPUTS(count ? T(", 0x") : T("0x"), stream);
293 _PUT_HEX_CHAR(hex, digest[count], 4, stream);
294 _PUT_HEX_CHAR(hex, digest[count], 0, stream);
298 FPUTS(T(" }"), stream);
303 static volatile int g_interrupted;
304 static void sigint_handler(int sig_no)
307 signal(sig_no, sigint_handler);
312 static void clear_errors()
319 static void print_error(const CHAR *const message, const CHAR *const file_name, const param_t *const param, const int multi_file)
321 const CHAR *const source_name = file_name ? file_name : T("<STDIN>");
322 if (param->ignore_errors && multi_file)
324 FPRINTF(stderr, T("Skipped file: %s\n"), source_name); /*skip error message*/
328 const errno_t error = errno;
329 const unsigned long syserrno = SYSERRNO;
331 if (error && syserrno)
333 FPRINTF(stderr, T("%s:\n%s\n\n>>> %s [Code: 0x%X] <<<\n\n"), message, source_name, STRERROR(error), syserrno);
337 FPRINTF(stderr, T("%s:\n%s\n\n>>> %s <<<\n\n"), message, source_name, STRERROR(error));
342 #endif /*MHASH_CLI_UTILS_INCLUDED*/