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
47 #define MY_HASH_LENGTH mhash_384::MHash384::HASH_LEN
49 #define MY_HASH_LENGTH MHASH_384_LEN
53 static const CHAR *const BUILD_DATE = T(__DATE__);
61 typedef struct param_t
73 typedef struct version_t
82 static version_t get_version(void)
84 version_t version_info;
86 mhash_384::MHash384::version(version_info.major, version_info.minor, version_info.patch);
88 version_info.major = MHASH_384_VERSION_MAJOR;
89 version_info.minor = MHASH_384_VERSION_MINOR;
90 version_info.patch = MHASH_384_VERSION_PATCH;
96 static void print_logo(void)
98 const version_t version = get_version();
99 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);
100 FPRINTF(stderr, T("Copyright(c) 2016-%s LoRd_MuldeR <mulder2@gmx.de>, released under the MIT License.\n\n"), &BUILD_DATE[7]);
104 static void print_vers(void)
106 const version_t version = get_version();
107 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);
112 #define EXE_SUFFIX ".exe"
114 #define EXE_SUFFIX ""
117 /*Print help screen*/
118 static void print_help(void)
121 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));
122 FPUTS(T("Usage:\n"), stderr);
123 FPRINTF(stderr, T(" mhash384%s [options] [input_file]...\n\n"), T(EXE_SUFFIX));
124 FPUTS(T("Options:\n"), stderr);
125 FPUTS(T(" -p, --progress show progress while processing\n"), stderr);
126 FPUTS(T(" -u, --upper print digest in upper case letters\n"), stderr);
127 FPUTS(T(" -c, --curly print digest using C-style curly brackets\n"), stderr);
128 FPUTS(T(" -r, --raw output \"raw\" bytes (no \"hex\" encoding)\n"), stderr);
129 FPUTS(T(" -b, --bench compute and print throughput\n"), stderr);
130 FPUTS(T(" -v, --version print the version string and exit\n"), stderr);
131 FPUTS(T(" -t, --test execute self-test and exit\n"), stderr);
132 FPUTS(T(" -h, --help print this help screen and exit\n\n"), stderr);
133 FPUTS(T("If no input file is specified, input will be read from STDIN.\n\n"), stderr);
136 /*Check specific option*/
137 #define IS_OPTION(ARGV, IS_LONG, NAME_SHRT, NAME_LONG) \
138 ((IS_LONG) ? (!STRICMP((ARGV), (NAME_LONG))) : (TOLOWER(*(ARGV)) == (NAME_SHRT)))
141 static int parse_option(param_t *param, const CHAR *const argv, const int is_long)
143 if (IS_OPTION(argv, is_long, T('b'), T("bench")))
145 param->enable_bench = 1;
148 if (IS_OPTION(argv, is_long, T('p'), T("progress")))
150 param->show_progress = 1;
153 if (IS_OPTION(argv, is_long, T('u'), T("upper")))
155 param->use_upper_case = 1;
158 if (IS_OPTION(argv, is_long, T('c'), T("curly")))
160 param->curly_brackets = 1;
163 if (IS_OPTION(argv, is_long, T('r'), T("raw")))
165 param->raw_output = 1;
168 if (IS_OPTION(argv, is_long, T('h'), T("help")))
170 param->opmode = OPMODE_HELP;
173 if (IS_OPTION(argv, is_long, T('v'), T("version")))
175 param->opmode = OPMODE_VERS;
178 if (IS_OPTION(argv, is_long, T('t'), T("test")))
180 param->opmode = OPMODE_TEST;
187 static int parse_arguments(param_t *const param, int argc, CHAR *argv[])
190 memset(param, 0, sizeof(param_t));
191 for (i = 1; i < argc; ++i)
193 if (argv[i][0] == T('-'))
195 if (argv[i][1] == T('-'))
202 if (!parse_option(param, &argv[i][2], 1))
205 FPRINTF(stderr, T("Unknown option:\n%s\n\n"), argv[i]);
212 for (j = 1; argv[i][j]; ++j)
214 if(!parse_option(param, &argv[i][j], 0))
217 FPRINTF(stderr, T("Unknown option(s):\n%s\n\n"), argv[i]);
224 break; /*no more options*/
226 if (param->raw_output && (param->use_upper_case || param->curly_brackets))
229 FPRINTF(stderr, T("Error: Options \"-%c\" and \"-r\" are mutually exclusive!\n\n"), param->use_upper_case ? T('u') : T('c'));
235 /*is file readable?*/
236 static int is_file_readable(const CHAR *const filename)
239 if (!STAT64(filename, &info))
241 if ((info.st_mode & S_IFMT) == S_IFDIR)
247 return (!ACCESS(filename, R_OK));
251 static uint64_t get_file_size(FILE *const file)
254 if (fstat64(FILENO(file), &info) || ((info.st_mode & S_IFMT) != S_IFREG))
258 return (uint64_t) info.st_size;
262 static void print_progress(const uint64_t size_total, const uint64_t size_processed)
266 FPRINTF(stderr, T("\r%.1f%% of %") T(PRIu64) T(" bytes processed..."), ((double)size_processed) / ((double)size_total) * 100.0, size_total);
270 FPRINTF(stderr, T("\r%") T(PRIu64) T(" bytes processed..."), size_processed);
275 #define _PUT_HEX_CHAR(W,X,Y,Z) FPUTC(W[((X) >> (Y)) & 0xFU], (Z))
276 static void print_digest(FILE *const stream, const uint8_t *const digest, const int uppercase, const int curly)
278 static const CHAR *const HEX_UPR = T("0123456789ABCDEF");
279 static const CHAR *const HEX_LWR = T("0123456789abcdef");
280 const CHAR *const hex = uppercase ? HEX_UPR : HEX_LWR;
284 FPUTS(T("{ "), stream);
286 for (count = 0U; count < MY_HASH_LENGTH; ++count)
290 FPUTS(count ? T(", 0x") : T("0x"), stream);
292 _PUT_HEX_CHAR(hex, digest[count], 4, stream);
293 _PUT_HEX_CHAR(hex, digest[count], 0, stream);
297 FPUTS(T(" }"), stream);
302 static volatile int g_interrupted;
303 static void sigint_handler(int sig_no)
306 signal(sig_no, sigint_handler);
310 #endif /*MHASH_CLI_UTILS_INCLUDED*/