crc32/main.c

185 lines
3.4 KiB
C
Raw Normal View History

2012-04-13 02:43:39 -07:00
#include <stdio.h>
#include <stdlib.h>
2012-08-04 10:03:16 -07:00
typedef unsigned long ulong;
2015-04-11 10:34:48 -07:00
#include "crc32.c"
#include "args.c"
2012-04-13 02:43:39 -07:00
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;
static ulong starting = 0xFFFFFFFF;
2012-08-05 19:24:31 -07:00
static char big_endian = 0;
2012-08-05 19:58:43 -07:00
static ulong polynomial = 0x04C11DB7;
2012-04-13 02:43:39 -07:00
static char print_binary = 0;
static char xor_output = 1;
static char reflect_output = 0;
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:34:48 -07:00
static ulong
cycle_file(FILE *stream)
2012-04-13 02:43:39 -07:00
{
2012-08-04 09:12:37 -07:00
ulong remainder = starting;
2012-08-05 19:58:43 -07:00
void (*cycle)(ulong*, ulong*, char) =
(big_endian) ? crc_be_cycle : crc_le_cycle;
ulong table[CRC_TABLE_SIZE];
crc_fill_table(table, big_endian, 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
print_crc(ulong 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;
}