Date : Wed, 09 Oct 1985 05:49:29 EDT
From : "Paul R. Grupp" <GRUPP@MIT-MC.ARPA>
Subject: CRC in C (Nov 83 rerun)
Someone recently asked for CRC code in C but I've forgotten
who. So here it is again.
Date: 9 Nov 83 5:35:04-PST (Wed)
From: harpo!floyd!clyde!burl!hou3c!hocda!machaids!djj at ucb-vax
About a month ago I put a request for CRC (Cyclic Redundancy
Codes) information on this net. I received in a number of good
programs and comments, and several requests to forward whatever I
discovered. Since I have not been able send mail to several of
the people who made requests, I'll put this summary on the net.
It appears that CRC calculations are based on a polynomial that
is not standardized, so it is possible to have several different
valid CRC values for the same file simply by using different
polynomials. There is an article in the June 83 issue of IEEE
Micro which gives a little background on CRC and on a method for
calculating same. Unfortunately, the examples are given in
assembler.
One of the C programs I received, and modified slightly produces
CRC values identical to those produced by CRCK.COM and "uc" the
UNIX/CPM communications program that is intended to replace
"umodem". Here is the source code ---- "crck.c" (118 lines; 493
words; 2874 bytes):
/*
* ---- crck.c ----
*
* Version 1.0 - 4/9/83
*
* This UN*X program performs a file hashsum calculation consistent
* with the de facto standard (but misnamed) "CRCK" program for CP/M.
*
* Usage: crck [-w] filename...
*
* The -w flag suppresses the warning message that normally
* is printed when a file is found not to be a multiple of
* 128 bytes in size. (Such a file cannot be a faithful copy
* of a CP/M file, since CP/M files are always a multiple of
* 128 bytes).
*
* Notes:
* 1. Two versions of the CRCK program exist in the CP/M
* world. Variants of Keith Petersen's original program
* are the de facto standard, even though they misuse the
* underlying CRC calculation subroutine and therefore don't
* really perform a "CRC" function. This program produces
* hashsums consistent with Petersen's scheme, currently
* found in the "CRCK4x.ASM" series.
*
* 2. In order for valid comparisons to be made between the
* CP/M and UNIX copies of a file, the file must, of course,
* have been transferred intact; i.e., with the "-rb" option
* of umodem, or the "-b" option of rb.
*
* Jeff Martin
* Naperville, Il.
* 4/9/83
* Version 1.1 -- djj Oct 13, 1983
* Changed output print format, to make it more readable!
* Don Jackowski, Mine Hill, NJ
*/
#include <stdio.h>
#include <fcntl.h>
#define CPMSEC 128
main(argc, argv)
int argc;
char *argv[];
{
int c, fdi, warn, wflg;
char *s, *in_file;
char cbuf[CPMSEC];
unsigned crc, crck();
warn = 1;
while (--argc > 0 && (*++argv)[0] == '-') {
for (s = argv[0]+1; *s != '\0'; s++) {
switch (*s) {
case 'w':
warn = 0;
break;
default:
printf("illegal option: '%c'\n", *s);
argc = 0;
break;
}
}
}
if (argc < 1) {
printf("Usage: crck [-w] filename...\n");
exit(1);
}
while (argc-- > 0) {
in_file = (argv++)[0];
fdi = open(in_file, O_RDONLY);
if (fdi < 0) {
printf("Cannot access %s\n", in_file);
continue;
}
crc = wflg = 0;
while ((c = read(fdi, cbuf, CPMSEC)) > 0) {
if ((c != CPMSEC) && warn) {
wflg++;
}
crc = crck(cbuf, c, crc);
}
printf("%14s --> %04X", in_file, crc);
if(wflg)printf(" <-- not CP/M sector sized.\n");
else printf("\n");
close(fdi);
continue;
}
}
/*
* The only good thing to be said about the following function is that
* it faithfully emulates the 8080 code in the CRCK4x.ASM series. It
* does NOT perform a CRC calculation, but does a rather bizarre hash
* sum.
*/
unsigned
crck(buf, size, oldcrc)
char *buf;
int size;
unsigned oldcrc;
{
register unsigned newcrc, tmp;
register int i, qbit;
newcrc = oldcrc;
for (i = 0; i < size; i++) {
qbit = newcrc & 0x8000;
newcrc <<= 1;
tmp = (newcrc + *buf++) & 0xff;
newcrc = (newcrc & 0xff00) | tmp;
if (qbit) {
newcrc ^= 0xA097;
}
}
return (newcrc);
}