2012-04-13 02:43:39 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2015-04-11 10:41:52 -07:00
|
|
|
#include <stdint.h>
|
2012-08-04 10:03:16 -07:00
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
#include "crc32.c"
|
|
|
|
#include "args.c"
|
2012-04-13 02:43:39 -07:00
|
|
|
|
2015-04-11 10:53:07 -07:00
|
|
|
typedef int bool;
|
|
|
|
|
2012-08-04 13:14:49 -07:00
|
|
|
#ifndef BUFFER_SIZE
|
|
|
|
#define BUFFER_SIZE 4096
|
|
|
|
#endif
|
|
|
|
char buff[BUFFER_SIZE];
|
|
|
|
|
2012-08-04 09:12:37 -07:00
|
|
|
typedef struct string_node_s string_node;
|
|
|
|
struct string_node_s {
|
|
|
|
char *s;
|
|
|
|
string_node *next;
|
|
|
|
};
|
2012-04-13 02:43:39 -07:00
|
|
|
|
2012-08-04 09:12:37 -07:00
|
|
|
static string_node *input_node = NULL;
|
|
|
|
|
2015-04-11 10:41:52 -07:00
|
|
|
static uint32_t starting = 0xFFFFFFFF;
|
2015-04-11 10:53:07 -07:00
|
|
|
static bool big_endian = 0;
|
2015-04-11 10:41:52 -07:00
|
|
|
static uint32_t polynomial = 0x04C11DB7;
|
2015-04-11 10:53:07 -07:00
|
|
|
static bool print_binary = 0;
|
|
|
|
static bool xor_output = 1;
|
|
|
|
static bool reflect_output = 0;
|
2012-04-13 02:43:39 -07:00
|
|
|
|
2012-08-04 07:52:09 -07:00
|
|
|
static const char help1[] = "\
|
2012-08-04 07:03:08 -07:00
|
|
|
crc32 - a 32-bit cyclic rendundancy check calculator\n\
|
|
|
|
\n\
|
2012-08-04 09:12:37 -07:00
|
|
|
<files...> open files as inputs\n\
|
2012-08-04 07:03:08 -07:00
|
|
|
-h display this text\n\
|
|
|
|
-s <n> start cycle with n (default: 0xFFFFFFFF)\n\
|
|
|
|
-p <n> use n as the crc divisor (default: 0x04C11DB7)\n\
|
|
|
|
-e use big endian calculations\n\
|
|
|
|
-b output as binary\n\
|
2012-08-04 07:52:09 -07:00
|
|
|
-x NOT the output\n\
|
|
|
|
-r reverse output's bits\n\
|
2012-08-04 07:03:08 -07:00
|
|
|
\n\
|
|
|
|
";
|
2012-08-04 07:52:09 -07:00
|
|
|
static const char help2[] = "\
|
2012-08-04 07:03:08 -07:00
|
|
|
numbers <n> may be entered as hexadecimal or octal with prefixes\n\
|
|
|
|
";
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static char
|
|
|
|
*check_next(char flag, char *next) {
|
2012-08-04 09:12:37 -07:00
|
|
|
if (!next) {
|
|
|
|
fprintf(stderr, "-%c requires another argument\n", flag);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static void
|
|
|
|
handle_flag(char flag, char *(*nextarg)())
|
2012-08-04 09:12:37 -07:00
|
|
|
{
|
2012-08-04 07:52:09 -07:00
|
|
|
char *next;
|
2012-08-04 07:03:08 -07:00
|
|
|
switch (flag) {
|
2015-04-11 10:34:48 -07:00
|
|
|
case 'h': {
|
2012-08-04 07:03:08 -07:00
|
|
|
printf(help1);
|
|
|
|
printf(help2);
|
2015-04-11 10:34:48 -07:00
|
|
|
} exit(0);
|
|
|
|
case 'e': {
|
2012-08-05 19:24:31 -07:00
|
|
|
big_endian = 1;
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
case 'b': {
|
2012-08-04 07:03:08 -07:00
|
|
|
print_binary = 1;
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
case 'x': {
|
2012-08-04 07:03:08 -07:00
|
|
|
xor_output = 0;
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
case 'r': {
|
2012-08-04 07:03:08 -07:00
|
|
|
reflect_output = 1;
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
case 's': {
|
2012-08-04 09:12:37 -07:00
|
|
|
next = check_next(flag, nextarg());
|
|
|
|
starting = strtoul(next, NULL, 0);
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
case 'p': {
|
2012-08-04 09:12:37 -07:00
|
|
|
next = check_next(flag, nextarg());
|
2012-08-05 19:58:43 -07:00
|
|
|
polynomial = strtoul(next, NULL, 0);
|
2015-04-11 10:34:48 -07:00
|
|
|
} break;
|
|
|
|
default: {
|
2012-08-04 07:52:09 -07:00
|
|
|
fprintf(stderr, "Unknown flag: -%c\n", flag);
|
2015-04-11 10:34:48 -07:00
|
|
|
} exit(1);
|
2012-08-04 07:03:08 -07:00
|
|
|
}
|
2012-04-13 02:43:39 -07:00
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static void
|
|
|
|
add_input(char *arg)
|
2012-04-13 02:43:39 -07:00
|
|
|
{
|
2012-08-04 09:12:37 -07:00
|
|
|
static string_node *last = NULL;
|
|
|
|
string_node *n = calloc(1, sizeof(string_node));
|
|
|
|
if (!n) {
|
|
|
|
fprintf(stderr, "calloc failed\n");
|
2012-04-13 02:43:39 -07:00
|
|
|
exit(1);
|
|
|
|
}
|
2012-08-04 09:12:37 -07:00
|
|
|
|
|
|
|
n->s = arg;
|
|
|
|
if (!input_node)
|
|
|
|
input_node = n;
|
|
|
|
else
|
|
|
|
last->next = n;
|
|
|
|
last = n;
|
2012-04-13 02:43:39 -07:00
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static FILE *
|
|
|
|
open_stream(char *filename)
|
2012-04-13 02:43:39 -07:00
|
|
|
{
|
2012-08-04 09:12:37 -07:00
|
|
|
FILE *stream = NULL;
|
|
|
|
stream = fopen(filename, "rb");
|
|
|
|
if (stream == NULL) {
|
|
|
|
perror(filename);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
return stream;
|
2012-04-13 02:43:39 -07:00
|
|
|
}
|
|
|
|
|
2012-08-04 13:14:49 -07:00
|
|
|
|
2015-04-11 10:41:52 -07:00
|
|
|
static uint32_t
|
2015-04-11 10:34:48 -07:00
|
|
|
cycle_file(FILE *stream)
|
2012-04-13 02:43:39 -07:00
|
|
|
{
|
2015-04-11 10:41:52 -07:00
|
|
|
uint32_t remainder = starting;
|
|
|
|
void (*cycle)(uint32_t*, uint32_t*, char) =
|
2012-08-05 19:58:43 -07:00
|
|
|
(big_endian) ? crc_be_cycle : crc_le_cycle;
|
2015-04-11 10:41:52 -07:00
|
|
|
uint32_t table[CRC_TABLE_SIZE];
|
2012-08-05 19:58:43 -07:00
|
|
|
|
2015-04-11 11:04:03 -07:00
|
|
|
if (big_endian)
|
|
|
|
crc_be_fill_table(table, polynomial);
|
|
|
|
else
|
|
|
|
crc_le_fill_table(table, polynomial);
|
2012-08-04 13:14:49 -07:00
|
|
|
do {
|
2015-04-11 10:34:48 -07:00
|
|
|
int len = fread(buff, 1, BUFFER_SIZE, stream);
|
2012-08-04 13:14:49 -07:00
|
|
|
if (ferror(stream)) {
|
|
|
|
perror(NULL);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
for (int i = 0; i < len; i++)
|
2012-08-05 19:58:43 -07:00
|
|
|
cycle(table, &remainder, buff[i]);
|
2012-08-04 13:14:49 -07:00
|
|
|
} while (!feof(stream));
|
2012-08-04 09:12:37 -07:00
|
|
|
|
2012-04-13 02:43:39 -07:00
|
|
|
if (xor_output)
|
|
|
|
remainder ^= 0xFFFFFFFF;
|
|
|
|
if (reflect_output)
|
|
|
|
remainder = crc_reflect(remainder);
|
2012-08-04 09:12:37 -07:00
|
|
|
return remainder;
|
2012-04-13 02:43:39 -07:00
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static void
|
2015-04-11 10:41:52 -07:00
|
|
|
print_crc(uint32_t remainder)
|
2012-04-13 02:43:39 -07:00
|
|
|
{
|
|
|
|
if (print_binary)
|
|
|
|
fwrite(&remainder, sizeof(remainder), 1, stdout);
|
|
|
|
else
|
|
|
|
printf("%08X\n", (int) remainder);
|
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
static void
|
|
|
|
free_nodes(string_node *n)
|
2012-08-28 18:02:00 -07:00
|
|
|
{
|
|
|
|
string_node *next;
|
|
|
|
while (n) {
|
|
|
|
next = n->next;
|
|
|
|
free(n);
|
|
|
|
n = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-11 10:34:48 -07:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
2012-04-13 02:43:39 -07:00
|
|
|
{
|
2012-08-04 09:12:37 -07:00
|
|
|
args_parse(argc, argv, handle_flag, add_input);
|
|
|
|
|
|
|
|
if (!input_node) {
|
2015-04-11 10:34:48 -07:00
|
|
|
freopen(NULL, "rb", stdin);
|
2012-08-04 09:12:37 -07:00
|
|
|
print_crc(cycle_file(stdin));
|
|
|
|
}
|
2015-04-11 10:34:48 -07:00
|
|
|
for (string_node *n = input_node; n; n = n->next) {
|
2012-08-04 09:12:37 -07:00
|
|
|
FILE *stream = open_stream(n->s);
|
|
|
|
print_crc(cycle_file(stream));
|
|
|
|
fclose(stream);
|
|
|
|
}
|
2012-08-28 18:02:00 -07:00
|
|
|
free_nodes(input_node);
|
2012-04-13 02:43:39 -07:00
|
|
|
return 0;
|
|
|
|
}
|