<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
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);
}
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>