phil@vaxwaller.UUCP (Phil Newton) (09/25/90)
I'm interested in seeing if anyone out there has written either a
Arithmetic Checksum program in "C" or a CRC-16 checksum program in "C".
I need to create a utility that will allow our software engineers the
ability to perform either an Arithmetic checksum or a CRC-16 checksum on a
software module. Before I create this utility from scratch, I thought I'd ask
and see if anyone's coded either of these Checksum algorithms already.
If you have any helpful information, please email me at
"... {lll-winken,zehntel,pacbell}!varian!phil"
Thanks for your assistance.
--
Philip T. Newton (415)945-2272
Varian Instruments 2700 Mitchell Drive Walnut Creek, CA. 94598
{zehntel,pacbell,lll-winken}!varian!phil@tree.uucp (Chris Gonnerman) (09/30/90)
I am also interested in such a program... -- +----------------------------------------------------------------------------+ | Chris Gonnerman (Mad Programmer At Large) csusac.ecs.csus.edu!tree!jcg | | @ the Tree BBS, Sacramento, CA ucbvax!ucdavis!csusac!tree!jcg | +---------- DISCLAIMER: These opinions are mine... MINE, I say! -----------+
trt@rti.rti.org (Thomas Truscott) (10/01/90)
Here is a CRC program. I set up the main program to
use memcrc_16 (CRC-16).
Tom Truscott
/*
* Cyclic redundancy check calculation:
* memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags)
*
* Returns the CRC of the "len" characters starting at "bfr".
* The "crc_value" is initially 0, and should subsequently
* be the previous result of memcrc to permit a CRC
* to be calculated using multiple calls to memcrc.
* The low-order "bits_per_char" bits of each character
* are presented serially to the CRC, low-order bit first.
*
* The "poly" is the CRC generating polynomial expressed in binary:
* for an N-bit CRC, for each term x^i, set the bit valued 2^(N-1-i).
* Ignore the high-order x^N term which is "implied".
* Both "crc_value" and "poly" are "bits_in_crc" long.
*
* The "flags" are used to provide special functions
* needed for particular CRC implementations.
* It currently supports complementation of input and output crc values.
* Future flags may support bit-reversal of the input and output crc values,
* the input character values, etc. This would be needed to
* support the "pathalias" CRC, for example.
*
* Tom Truscott, trt@rti.rti.org, (919) 541-7005
*/
#define CRC_COMPLEMENT 01
/*
* Here are some macros that implement popular polynomials.
* Eight bits per character is assumed.
*/
/* CRC-32 (FIPS PUB 78, CCITT X.25). Highly Recommended. */
/* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 */
#define memcrc_32(b,l,c) memcrc(b,l,c,8,(long)0xEDB88320L,32,CRC_COMPLEMENT)
/* CRC-16 (DDCMP,BISYNC). x^16 + x^15 + x^2 + x^1 */
#define memcrc_16(b,l,c) memcrc(b,l,c,8,(long)0xA001L,16,0)
/* CRC-CCITT (ADCCP,HDLC,SDLC). x^16 + x12 + x^5 + x^1 */
#define memcrc_ccitt(b,l,c) memcrc(b,l,c,8,(long)0x1021L,16,CRC_COMPLEMENT)
#ifdef SLOW_AND_SIMPLE
long
memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags)
register char *bfr;
int len;
register long crc_value;
long poly;
int bits_in_crc;
int flags;
{
register int i, val;
if (flags & CRC_COMPLEMENT)
{
if (bits_in_crc == 32)
crc_value ^= 0xffffffffL; /* needed due to bug in << */
else
crc_value ^= ~(~0L << bits_in_crc);
}
while (--len >= 0)
{
val = *bfr++;
for (i = 0; i < bits_per_char; i++)
{
crc_value = ((unsigned long)crc_value >> 1) ^
(((crc_value ^ val) & 1)? poly: 0);
val >>= 1;
}
}
if (flags & CRC_COMPLEMENT)
{
if (bits_in_crc == 32)
crc_value ^= 0xffffffffL;
else
crc_value ^= ~(~0L << bits_in_crc);
}
return (crc_value);
}
#else
/*
* In this implementation, the CRC calculation is performed on
* "bits_per_char" characters at a time by using a table lookup.
* The table is recomputed whenever memcrc is called with
* new CRC parameters.
*/
static int cached_bits_per_char, cached_flags;
static long cached_poly;
static long *cached_table;
/* ARGSUSED */
init_crc(bits_per_char, poly, flags)
int bits_per_char;
long poly;
int flags;
{
register int i, val, j;
register long crc_value;
extern char *malloc();
cached_table =
(long *)malloc((unsigned int)(sizeof(long)*(1<<bits_per_char)));
if (cached_table == 0)
abort("init_crc malloc failed");
for (i = 0; i < 1<<bits_per_char; i++)
{
/* compute the CRC of the "i"th char */
val = i;
crc_value = 0;
for (j = 0; j < bits_per_char; j++)
{
crc_value = ((unsigned long)crc_value >> 1) ^
(((crc_value ^ val) & 1)? poly: 0);
val >>= 1;
}
cached_table[i] = crc_value;
}
}
long
memcrc(bfr, len, crc_value, bits_per_char, poly, bits_in_crc, flags)
register char *bfr;
int len;
long crc_value;
register int bits_per_char;
long poly;
int bits_in_crc;
int flags;
{
register long *tabp;
register int bitmask;
register char *ebfr;
if (bits_per_char != cached_bits_per_char
|| poly != cached_poly
|| flags != cached_flags
|| cached_table == 0)
{
init_crc(bits_per_char, poly, flags);
}
if (flags & CRC_COMPLEMENT)
{
if (bits_in_crc == 32)
crc_value ^= 0xffffffffL;
else
crc_value ^= ~(~0L << bits_in_crc);
}
tabp = cached_table; /* probably more efficient this way */
bitmask = ~(~0 << bits_per_char); /* ditto */
ebfr = bfr + len; /* ditto */
while (bfr < ebfr)
{
crc_value = ((unsigned long)crc_value >> bits_per_char) ^
tabp[(crc_value ^ *bfr++) & bitmask];
}
if (flags & CRC_COMPLEMENT)
{
if (bits_in_crc == 32)
crc_value ^= 0xffffffffL;
else
crc_value ^= ~(~0L << bits_in_crc);
}
return (crc_value);
}
#endif
/*
* test program
*/
#include <stdio.h>
main(argc, argv)
int argc; char **argv;
{
FILE *fp;
int errors;
errors = 0;
if (argc <= 1)
errors += do_crc(stdin, "<stdin>");
else while (--argc > 0)
{
if ((fp = fopen(*++argv, "r")) == 0)
{
perror(*argv);
errors++;
continue;
}
errors += do_crc(fp, *argv);
(void) fclose(fp);
}
exit(errors != 0);
}
do_crc(fp, fname)
FILE *fp;
char *fname;
{
char bfr[8192];
int n;
long nbytes, crcval;
nbytes = 0;
crcval = 0;
while ((n = fread(bfr, 1, sizeof(bfr), fp)) > 0)
{
crcval = memcrc_16(bfr, n, crcval);
nbytes += n;
}
if (ferror(fp))
{
perror(fname);
return(1);
}
printf("%010lu %7ld %s\n", crcval, nbytes, fname);
return(0);
}