Compare commits

...

2 Commits

Author SHA1 Message Date
1206f776ca Updated README file. 2022-09-19 21:53:58 +02:00
06ae68eaea Added support for the "--append-length" option. 2022-09-19 21:41:32 +02:00
2 changed files with 70 additions and 36 deletions

View File

@ -1,29 +1,39 @@
CRC-64 # CRC-64
======
Simple cross-platform command-line tool for computing **CRC-64** ([ECMA-182](https://www.ecma-international.org/wp-content/uploads/ECMA-182_1st_edition_december_1992.pdf)) checksums. Simple cross-platform command-line tool for computing **CRC-64** ([ECMA-182](https://www.ecma-international.org/wp-content/uploads/ECMA-182_1st_edition_december_1992.pdf)) checksums.
Generator polynomial: **`0x42F0E1EBA9EA3693`** The `crc64` utility writes to the standard output three whitespace separated fields for each input file. These fields are the CRC (Cyclic Redundancy Check) checksum of the file, the total number of octets in the file and the file name. If *no* file name is specified, the standard input is used.
The generator polynomial use for CRC-64 computations is: **`0x42F0E1EBA9EA3693`**
## Synopsis
``` ```
Synopsis:
crc64.exe [OPTIONS] [<file_1> [<file_2> ... <file_n>]] crc64.exe [OPTIONS] [<file_1> [<file_2> ... <file_n>]]
Options:
-h --help --version Show help screen / show version information
-b --binary Output digest in binary format (default is hex-string)
-d --decimal Output digest in decimal string format
-u --upper-case Print digest as upper-case (default is lower-case)
-p --no-padding Print digest *without* any leading zeros
-s --silent Suppress error messages
-e --ignore-errors Ignore I/O errors and proceeed with the next file
-f --no-flush Do *not* flush output stream after each file
-z --init-with-zero Initialize CRC with 0x000..000 (default is 0xFFF..FFF)
-n --negate-final Negate the final CRC result
-t --self-test Run integrated self-test and exit program
``` ```
One output line is generated per input file: ## Options
```
<CRC64-Checksum>[SP]<File-Size>[SP]<File-Name>[LF] | Option | Description |
``` |-----------------------------|--------------------------------------------------------|
| `-h`, `--help`, `--version` | Show help screen / show version information |
| `-b`, `--binary` | Output digest in binary format (default is hex-string) |
| `-d`, `--decimal` | Output digest in decimal string format |
| `-u`, `--upper-case` | Print digest as upper-case (default is lower-case) |
| `-p`, `--no-padding` | Print digest **without** any leading zeros |
| `-s`, `--silent` | Suppress error messages |
| `-e`, `--ignore-errors` | Ignore I/O errors and proceed with the next file |
| `-f`, `--no-flush` | Do **not** flush output stream after each file |
| `-z`, `--init-with-zero` | Initialize CRC with 0x000…000 (default is 0xFFF…FFF) |
| `-n`, `--negate-final` | Negate the final CRC result |
| `-l`, `--append-length` | Append to the input its length for CRC computation |
| `-t`, `--self-test` | Run integrated self-test and exit program |
## License
This work has been released under the **CC0 1.0 Universal** license.
For details, please refer to:
<https://creativecommons.org/publicdomain/zero/1.0/legalcode>

52
crc64.c
View File

@ -29,20 +29,21 @@
static const int VERSION_MAJOR = 1; static const int VERSION_MAJOR = 1;
static const int VERSION_MINOR = 0; static const int VERSION_MINOR = 0;
static const int VERSION_PATCH = 2; static const int VERSION_PATCH = 3;
#define OPT_HELPSC 0x001 #define OPT_HELPSC 0x0001
#define OPT_VERSNO 0x002 #define OPT_VERSNO 0x0002
#define OPT_BINARY 0x004 #define OPT_BINARY 0x0004
#define OPT_UPPERC 0x008 #define OPT_UPPERC 0x0008
#define OPT_DECIML 0x010 #define OPT_DECIML 0x0010
#define OPT_NOPADD 0x020 #define OPT_NOPADD 0x0020
#define OPT_IGNERR 0x040 #define OPT_IGNERR 0x0040
#define OPT_SILENT 0x080 #define OPT_SILENT 0x0080
#define OPT_NOFLSH 0x100 #define OPT_NOFLSH 0x0100
#define OPT_ZEROIN 0x200 #define OPT_ZEROIN 0x0200
#define OPT_NEGATE 0x400 #define OPT_NEGATE 0x0400
#define OPT_SLFTST 0x800 #define OPT_LENGTH 0x0800
#define OPT_SLFTST 0x1000
/* ======================================================================== */ /* ======================================================================== */
/* Compiler */ /* Compiler */
@ -238,6 +239,20 @@ static int is_directory(FILE *const file)
return 0; return 0;
} }
/* ======================================================================== */
/* Store 64-Bit value (LE) */
/* ======================================================================== */
static size_t store_uint64(uint64_t value, uint8_t *const buffer)
{
size_t count = 0U;
for (; value; value >>= 8)
{
buffer[count++] = value & 0xFF;
}
return count;
}
/* ======================================================================== */ /* ======================================================================== */
/* Process File */ /* Process File */
/* ======================================================================== */ /* ======================================================================== */
@ -306,6 +321,12 @@ static int process_file(const CHAR *const file_name, const int options)
} }
} }
if (total_size && (options & OPT_LENGTH))
{
const size_t count = store_uint64(total_size, buffer);
crc = crc64_update(crc, buffer, count);
}
if (options & OPT_NEGATE) if (options & OPT_NEGATE)
{ {
crc = ~crc; crc = ~crc;
@ -388,6 +409,7 @@ static const struct
CRC64_TESTCASE[] = CRC64_TESTCASE[] =
{ {
{ { 0xffffffffffffffffULL, 0x0000000000000000ULL }, 0x0000001, "" }, { { 0xffffffffffffffffULL, 0x0000000000000000ULL }, 0x0000001, "" },
{ { 0x9d13a61c0e5b0ff5ULL, 0x6c40df5f0b497347ULL }, 0x0000001, "123456789" },
{ { 0xfb747ec5060b68fdULL, 0x66501a349a0e0855ULL }, 0x0000001, "abc" }, { { 0xfb747ec5060b68fdULL, 0x66501a349a0e0855ULL }, 0x0000001, "abc" },
{ { 0xe48092e3bf0112faULL, 0x29d18301fe33ca5dULL }, 0x0000001, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, { { 0xe48092e3bf0112faULL, 0x29d18301fe33ca5dULL }, 0x0000001, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
{ { 0x763e5273763ec641ULL, 0x86751df1edd9a621ULL }, 0x0000001, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, { { 0x763e5273763ec641ULL, 0x86751df1edd9a621ULL }, 0x0000001, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
@ -452,6 +474,7 @@ CLI_OPTION_NAMES[] =
{ T('f'), T("no-flush"), OPT_NOFLSH }, { T('f'), T("no-flush"), OPT_NOFLSH },
{ T('z'), T("init-with-zero"), OPT_ZEROIN }, { T('z'), T("init-with-zero"), OPT_ZEROIN },
{ T('n'), T("negate-final"), OPT_NEGATE }, { T('n'), T("negate-final"), OPT_NEGATE },
{ T('l'), T("append-length"), OPT_LENGTH },
{ T('t'), T("self-test"), OPT_SLFTST } { T('t'), T("self-test"), OPT_SLFTST }
}; };
@ -543,10 +566,11 @@ print_help:
FPUTS(T(" -u --upper-case Print digest as upper-case (default is lower-case)\n"), stderr); FPUTS(T(" -u --upper-case Print digest as upper-case (default is lower-case)\n"), stderr);
FPUTS(T(" -p --no-padding Print digest *without* any leading zeros\n"), stderr); FPUTS(T(" -p --no-padding Print digest *without* any leading zeros\n"), stderr);
FPUTS(T(" -s --silent Suppress error messages\n"), stderr); FPUTS(T(" -s --silent Suppress error messages\n"), stderr);
FPUTS(T(" -e --ignore-errors Ignore I/O errors and proceeed with the next file\n"), stderr); FPUTS(T(" -e --ignore-errors Ignore I/O errors and proceed with the next file\n"), stderr);
FPUTS(T(" -f --no-flush Do *not* flush output stream after each file\n"), stderr); FPUTS(T(" -f --no-flush Do *not* flush output stream after each file\n"), stderr);
FPUTS(T(" -z --init-with-zero Initialize CRC with 0x000..000 (default is 0xFFF..FFF)\n"), stderr); FPUTS(T(" -z --init-with-zero Initialize CRC with 0x000..000 (default is 0xFFF..FFF)\n"), stderr);
FPUTS(T(" -n --negate-final Negate the final CRC result\n"), stderr); FPUTS(T(" -n --negate-final Negate the final CRC result\n"), stderr);
FPUTS(T(" -l --append-length Append to the input its length for CRC computation\n"), stderr);
FPUTS(T(" -t --self-test Run integrated self-test and exit program\n\n"), stderr); FPUTS(T(" -t --self-test Run integrated self-test and exit program\n\n"), stderr);
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;