/* ** ** (c) Yasiukevich M.M. 1996, 2000, 2001 yasiukevich@mail.ru ** ** ** FILE: crcdir32.cpp DATE: 09-Jan-2001 ** ** Calculation of 32-bit CRC. ( i386 Win32 file sharing version) ** ** Based on material from Borland Source Library and article by Anarchriz ** (article http://huizen.dd.nl/~noway66/programming/crc.htm) and optimized by me. ** Adapted to sharing file system and LFN. ** ** NOTE: 1. You must call InitMagic before calculate CRC32. ** 2. With 3 functions (StartCRC, IncCRC, FinishCRC) You can calculate CRC32 of ** any block in memory. The size of block must be from 0 to K63. If You need ** to proceed a larger messages see CRCFileB. ** ** EXAMPLE: ** ** --8<----------------------------- ** ** #include "crc32shr.cpp" ** #include // It is not necessary because stdio.h included in ** // crc32shr.cpp ** ** void main (void) ** { ** unsigned long CRC; ** char *FName1="C:\\AUTOEXEC.BAT"; ** char *FName2="C:\\MSDOS.SYS"; ** ** InitMagic(); ** CRCFile(FName1, &CRC) ** printf("C:\\AUTOEXEC.BAT CRC:%lu\n",CRC); ** CRCFile(FName2, &CRC) ** printf("C:\\MSDOS.SYS CRC:%lu\n",CRC); ** } ** ** --8<----------------------------- */ #include #include #include #include #include #include const K63 = 64*1024; long MagicConst = 0xEDB88320; // Constant used to fill Magic array long Magic[256]; // Table to translate bytes to CRC void *pBuff = NULL; // Work buffer /********************************************************************** * * IncMagic * * Purpose: * Generates the crc table and allocates work buffer. * It must be used first before using other crc-functions. * * Parameters: * void. * Returns: * void. */ int InitMagic(void) { __asm { xor ebx, ebx ; // ebx=0,will used as pointer InitTableLoop: xor eax, eax ; // eax=0 for geting new position mov al, bl ; // low 8 bit ebx is coping into 8 low bit eax ; // calculating position mov cl, 8 ; // start circle by byte EntryLoop: shr eax, 1 ; // shift right and test bit0 jnb EntryGoOn ; // if bit0 was 0 then skip xor xor eax, MagicConst ; // EntryGoOn: dec cl jnz entryLoop ; // if no, then repeat for next bit mov dword ptr [ ebx*4 + Magic ], eax ; // next table element inc bx test bx, 256 ; // that is all table ? jz InitTableLoop ; // if no repeat for the next element } if ( (pBuff = malloc(K63)) == NULL ) { fprintf( stdout, "\n*** Error: %s InitMagic() - insufficient memory.\n", __FILE__ ); return 1; } return 0; }; /********************************************************************* * * Closing of using module. */ void FinishMagic( void ) { free(pBuff); pBuff = NULL; } /********************************************************************** * * StartCRC * * Purpose: * Initialises CRC viriable the start value. * * Parameters: * pCRC Pointer to CRC * * Returns: * void. * */ inline void StartCRC(unsigned long *pCRC) { *pCRC = 0xFFFFFFFF; } /********************************************************************** * * IncCRC * * Purpose: * Calculates CRC of pointed block and corrects given CRC. * * Parameters: * pBuff Specifies the pointer on work buffer with size K63 * Count Specifies the number bytes of input stream which must be * processed * pCRC Pointer to CRC * * Returns: * void. */ void IncCRC(void *pBuff,unsigned int Count, unsigned long* pCRC) { __asm { mov edx, pCRC ; // deaddressing and copy pCRC to eax mov eax, DWORD PTR [edx] mov ecx, Count ; // length of input buff to calculate mov edx, pBuff ; // pointer to pBuff ComputeLoop: xor ebx, ebx xor al, [edx] mov bl, al shr eax, 8 xor eax, dword ptr [4*ebx+Magic] inc edx loop ComputeLoop mov edx, pCRC ; // deaddressing pCRC mov DWORD PTR [edx], eax ; // return calculated value to *pCRC }; }; /********************************************************************** * * FinishCRC * * Purpose: * Initialises CRC viriable the start value. * * Parameters: * pCRC Pointer to CRC * * Returns: * void. * */ inline void FinishCRC( unsigned long *pCRC ) { *pCRC ^= 0xFFFFFFFF; } /*-------------------------------------------------------------------- * Evaluate CRC-32 of a given file through disposed buffer; * returns 0 if file is OK, IOResult on file error, $FFFF on BuffLen = 0 */ int CRCFileB( char *FName, void *Buff, unsigned int BuffLen, unsigned long *CRC ) { unsigned __int64 Rest; unsigned int status, Portion, handle; WIN32_FIND_DATA FindFileData; if ( BuffLen==0 ) { CRC = 0; return 0xFFFF; } if ( FindFirstFile( FName, &FindFileData ) == INVALID_HANDLE_VALUE ) { *CRC = 0; return errno; } if ( (handle = sopen( FName,O_RDONLY + O_BINARY, SH_DENYNO, S_IREAD )) == -1) { *CRC = 0; return errno; } status = access(FName, 4); if ( status ) { close(handle); *CRC=0; return errno; } StartCRC(CRC); Rest = ( (unsigned __int64) FindFileData.nFileSizeHigh * MAXDWORD ) + (unsigned __int64) FindFileData.nFileSizeLow; while ( Rest > 0 ) { Portion = BuffLen; if ( (unsigned __int64) BuffLen > Rest) { Portion = (unsigned int) Rest; } read( handle, Buff, Portion ); IncCRC( Buff, Portion, CRC ); Rest -= Portion; }; close(handle); FinishCRC(CRC); return 0; } /*-------------------------------------------------------------------- * Evaluate CRC-32 of a given file using GetMem for 63Kb buffer; * Returns 0 if file is OK, IOResult on file error */ int CRCFile( char *FName, unsigned long *CRC ) { int r; if ( pBuff == NULL ) { fprintf( stdout, "\n*** Error: %s CRCFile() - Use InitMagic before call CRCFile().\n", __FILE__ ); return 0xFFFF; } r = CRCFileB( FName, pBuff, K63, CRC ); return r; };