home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- VALIDATE - Portable "C" version of a CRC validation program which uses
- the same mechanisms as McAfee's VALIDATE program.
-
- Arguments: Filename(s) - The name(s) of the file(s) to be checked.
-
- Author: Gary P. Mussar (gmussar on BIX)
-
- This code is released to the public domain. There are no restrictions,
- however, acknowledging the author by keeping this comment around would
- be appreciated.
- ***********************************************************************/
- #include <stdio.h>
-
- /* This includes are used for obtaining and displaying the last modified
- time for the file. */
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- char version[] = {"Portable VALIDATE (Public Domain) V1.0 1991-01-05"};
-
- /***********************************************************************
- The following is used to define the types of variable used to hold or
- manipulate CRCs. The 16 bit CRCs require a data type which is at least
- 16 bits. In addition, the data bits reserved for the CRC must be
- manipulated in an unsigned fashion. It is possible to define a data
- type which is larger than required to hold the CRC, however, this is an
- inefficient use of memory and usually results in less efficient code
- when manipulating the CRCs.
- ***********************************************************************/
- #define CRC16 unsigned short
-
- /***********************************************************************
- The coefficient of each term of the generator polynomial is represented
- by a bit in the polynomial array (except for the highest order term
- which is always assumed to be 1). The coefficient for the second
- highest term in the LSB of the first byte of the polynomial array.
-
- CRC Check 1
- Polynomial x^16 + x^15 + x^2 + 1 (16 bit BCS polynomial)
- Generator is pre-initialized to 0x0000
-
- CRC Check 2
- Polynomial x^16 + x^15 + x^10 + x^3
- Generator is pre-initialized to 0x0000
- ***********************************************************************/
- CRC16 crcchk1[256*2]; /* Fast lookup table */
- CRC16 poly_crcchk1 = {0xa001}; /* Generator polynomial */
- CRC16 init_crcchk1 = {0x0000}; /* Pre-init value */
- CRC16 crc_crcchk1; /* CRC accumulator */
-
- CRC16 crcchk2[256*2]; /* Fast lookup table */
- CRC16 poly_crcchk2 = {0x1021}; /* Generator polynomial */
- CRC16 init_crcchk2 = {0x0000}; /* Pre-init value */
- CRC16 crc_crcchk2; /* CRC accumulator */
-
- /* File stuff. The file is read (and CRCs calculated) in chunks. The
- size of a chunk is determined by the size of buff[] */
- FILE *fp;
- char buff[8192];
-
- /***********************************************************************
- Utilities for fast CRC using table lookup
-
- CRC calculations are performed one byte at a time using a table lookup
- mechanism. Two routines are provided: one to initialize the CRC lookup
- table; and one to perform the CRC calculation over an array of bytes.
-
- A CRC is the remainder produced by dividing a generator polynomial into
- a data polynomial using binary arthimetic (XORs). The data polynomial
- is formed by using each bit of the data as a coefficient of a term in
- the polynomial. These utilities assume the data communications ordering
- of bits for the data polynomial, ie. the LSB of the first byte of data
- is the coefficient of the highest term of the polynomial, etc..
-
- I_CRC16 - Initialize the 256 entry CRC lookup table based on the
- specified generator polynomial.
- Input:
- Table[256] - Lookup table
- GenPolynomial - Generator polynomial
-
- F_CRC16 - Calculate CRC over an array of characters using fast
- table lookup.
- Input:
- Table[256] - Lookup table
- *CRC - Pointer to the variable containing the result of
- CRC calculations of previous characters. The CRC
- variable must be initialized to a known value
- before the first call to this routine.
- *dataptr - Pointer to array of characters to be included in
- the CRC calculation.
- count - Number of characters in the array.
- ***********************************************************************/
- I_CRC16(Table, GenPolynomial)
- CRC16 Table[256];
- CRC16 GenPolynomial;
- {
- int i;
- CRC16 crc;
-
- for (i=0; i<256; i++)
- {
- crc = (CRC16) i;
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
- crc = (crc >> 1) ^ ((crc & 1) ? GenPolynomial : 0);
-
- Table[i] = crc;
- }
- }
-
- F_CRC16(Table, CRC, dataptr, count)
- CRC16 Table[256];
- CRC16 *CRC;
- unsigned char *dataptr;
- unsigned int count;
- {
- CRC16 temp_crc;
-
- for (temp_crc = *CRC; count; count--)
- {
- temp_crc = (temp_crc >> 8) ^ Table[(temp_crc & 0xff) ^ *dataptr++];
- }
-
- *CRC = temp_crc;
- }
-
- /***********************************************************************
- Mainline
-
- Each file specified on the input line is opened (in binary mode) and two
- CRCs are calculated over the data.
-
- The CRC generators are initialized to 0 which means that null bytes (00)
- added to the front of a file will not affect the CRC (sigh, when will
- people ever learn). Hopefully the file length will catch these kinds of
- problems.
- ***********************************************************************/
- main(argc, argv)
- int argc;
- char *argv[];
- {
- unsigned len, files;
- unsigned long byte_cnt;
- struct stat statbuf;
-
- fprintf(stderr, "%s\n", version);
-
- /* We expect 1 or more arguments */
- if (argc < 2)
- {
- fprintf(stderr, "This program prints the validation information for a file.\n");
- fprintf(stderr, "Examples:\n");
- fprintf(stderr, " VALIDATE SCAN.EXE\n");
- fprintf(stderr, " VALIDATE SCANRES.EXE\n");
- exit(1);
- }
-
- /* Set up CRC tables */
- I_CRC16(crcchk1, poly_crcchk1);
- I_CRC16(crcchk2, poly_crcchk2);
-
- /* Loop through each filename on the invocation line */
- for (files=1; files < argc; files++)
- {
- printf("\n File Name: %s\n", argv[files]);
- fp=fopen(argv[files],"rb");
- if (!fp)
- {
- fprintf(stderr, "\n Sorry, I cannot open the input file.\n");
- continue;
- }
-
- /* Byte count and CRC generators to initial values */
- byte_cnt = 0;
- crc_crcchk1 = init_crcchk1;
- crc_crcchk2 = init_crcchk2;
-
- /* Read the file in chunks until done */
- while( (len = fread(buff,
- 1,
- sizeof(buff),
- fp) ) != 0)
- {
- /* Calculate CRC over this part of file */
- F_CRC16(crcchk1, &crc_crcchk1, buff, len);
- F_CRC16(crcchk2, &crc_crcchk2, buff, len);
-
- /* Byte count of file */
- byte_cnt += len;
- }
-
- /* Get file info so we can print last modified time for file */
- fstat(fileno(fp), &statbuf);
-
- /* Give the user the results */
- printf(" Size: %ld\n", byte_cnt);
- printf(" Date: %s", ctime(&statbuf.st_mtime));
- printf("File Authentication:\n");
- printf(" Check Method 1 - %04X\n", crc_crcchk1);
- printf(" Check Method 2 - %04X\n", crc_crcchk2);
- fclose(fp);
- }
-
- exit(0);
- }
-