#ifndef COMPILED_FORDOS #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef COMPILED_FORDOS #define MAX_PATH 256 #endif #define READ_BUFFER_SIZE (8192*sizeof(DWORD)) #define CHECK_NAME "\\chkfile.chk" extern BOOL fUsage; extern BOOL fGenerateCheck; extern LPSTR RootOfTree; char RootBuffer[MAX_PATH]; extern BOOL fVerbose; LPSTR CheckFileName; char OutputLine[512]; DWORD ReadBuffer[READ_BUFFER_SIZE/sizeof(DWORD)]; WORD CheckSum( DWORD ParitialSum, LPWORD Source, DWORD Length ); typedef struct _FINDBUF { char reserved[21]; char attrib; unsigned short wr_time; unsigned short wr_data; long size; char name[13]; } FINDBUF, *PFINDBUF; DWORD PortFindFirstFile( LPSTR FindPattern, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ); BOOL PortFindNextFile( DWORD FindHandle, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ); VOID PortFindClose( DWORD FindHandle ); VOID GenerateCheckFile( VOID ); VOID ValidateCheckFile( VOID ); BOOL ProcessParameters( int argc, LPSTR argv[] ); FILE *GlobalCheckFile; FILE * OpenCheckFile( VOID ); BOOL ComputeEntry( FILE *CheckFile, LPSTR FileName, DWORD FileLength ); DWORD CheckSumFile( FILE *InputHandle, LPSTR PathName, DWORD FileLength, LPSTR FileName ); BOOL fGenerateCheck = FALSE; LPSTR RootOfTree = "C:\\NT"; BOOL fVerbose = FALSE; BOOL fUsage = FALSE; #ifndef COMPILED_FORDOS int ThreadCount; HANDLE ThreadListMutex; HANDLE ThreadListSemaphore; LIST_ENTRY WorkList; #define ITEM_TYPE_EXIT 1 #define ITEM_TYPE_VALIDATE 2 #define ITEM_TYPE_GENERATE 3 typedef struct _WORK_ITEM { LIST_ENTRY ItemLinks; DWORD ItemType; PVOID Base; DWORD FileLength; DWORD ActualSum; char FileName[MAX_PATH]; } WORK_ITEM, *PWORK_ITEM; PHANDLE ThreadHandles; CRITICAL_SECTION GenerateCrit; VOID WriteCheckSumEntry( FileName, Sum, FileLength ) { char lOutputLine[512]; int LineLength; LineLength = sprintf(lOutputLine,"%s %x %x\n",FileName,Sum,FileLength); if ( fVerbose ) { fprintf(stdout,"Id %d %s",GetCurrentThreadId(),lOutputLine); } EnterCriticalSection(&GenerateCrit); fwrite(lOutputLine,1,LineLength,GlobalCheckFile); LeaveCriticalSection(&GenerateCrit); } DWORD WorkerThread( LPVOID WhoCares ) { HANDLE Objects[2]; PWORK_ITEM Item; PLIST_ENTRY Entry; int FilesProcessed = 0; Objects[0] = ThreadListMutex; Objects[1] = ThreadListSemaphore; SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL); // // Wait for and entry on the list, and exclusive ownership of the listhead // while(TRUE) { WaitForMultipleObjects(2,Objects,TRUE,INFINITE); Entry = RemoveHeadList(&WorkList); Item = (PWORK_ITEM)(CONTAINING_RECORD(Entry,WORK_ITEM,ItemLinks)); ReleaseMutex(ThreadListMutex); switch ( Item->ItemType ) { case ITEM_TYPE_VALIDATE : FilesProcessed++; break; case ITEM_TYPE_GENERATE : FilesProcessed++; { DWORD Sum; Sum = (DWORD)CheckSum(0,Item->Base,(Item->FileLength+1) >> 1); UnmapViewOfFile(Item->Base); WriteCheckSumEntry(Item->FileName,Sum,Item->FileLength); break; } break; case ITEM_TYPE_EXIT : default: fprintf(stdout,"Id %d Processed %d Files\n",GetCurrentThreadId(),FilesProcessed); ExitThread(1); } LocalFree(Item); } return 0; } #endif INT __cdecl main( argc, argv ) int argc; LPSTR argv[]; { if (!ProcessParameters( argc, argv )) { fUsage = TRUE; } if (fUsage) { fprintf( stderr, "usage: checkrel [-?] display this message\n" ); fprintf( stderr, " [-r pathname] supply release root\n" ); fprintf( stderr, " [-v] verbose output\n" ); fprintf( stderr, " [-g] generate check file\n" ); fprintf( stderr, " [-t n] use n threads to process the data\n" ); } else { // // if we are generating a check file, then generate it, // otherwise just check the release // if ( fGenerateCheck ) { GenerateCheckFile(); #ifndef COMPILED_FORDOS if ( ThreadCount ) { int i; PWORK_ITEM Item; for(i=0;iItemType = ITEM_TYPE_EXIT; WaitForSingleObject(ThreadListMutex,INFINITE); InsertTailList(&WorkList,&Item->ItemLinks); ReleaseSemaphore(ThreadListSemaphore,1,NULL); ReleaseMutex(ThreadListMutex); } WaitForMultipleObjects(ThreadCount,ThreadHandles,TRUE,INFINITE); } #endif } else { ValidateCheckFile(); } } return( 0 ); } BOOL ProcessParameters( int argc, LPSTR argv[] ) { char c, *p; BOOL Result; char *WhoCares; int i; Result = TRUE; while (--argc) { p = *++argv; if (*p == '/' || *p == '-') { while (c = *++p) switch (toupper( c )) { case '?': fUsage = TRUE; break; case 'R': { argc--; argv++; RootOfTree = *argv; GetFullPathName(RootOfTree,sizeof(RootBuffer),RootBuffer,&WhoCares); RootOfTree = RootBuffer; break; } case 'G': fGenerateCheck = TRUE; break; case 'V': fVerbose = TRUE; break; #ifndef COMPILED_FORDOS case 'T': { DWORD ThreadId; argc--; argv++; ThreadCount = atoi(*argv); InitializeListHead(&WorkList); ThreadListMutex = CreateMutex(NULL,FALSE,NULL); ThreadListSemaphore = CreateSemaphore(NULL,0,0x70000000,NULL); InitializeCriticalSection(&GenerateCrit); if ( ThreadListMutex && ThreadListSemaphore ) { ThreadHandles = LocalAlloc(LMEM_ZEROINIT,sizeof(HANDLE)*ThreadCount); if ( ThreadHandles ) { for(i=0;iItemType = ITEM_TYPE_GENERATE; Item->Base = Base; Item->FileLength = FileLength; strcpy(&Item->FileName[0],FileName); WaitForSingleObject(ThreadListMutex,INFINITE); InsertTailList(&WorkList,&Item->ItemLinks); ReleaseSemaphore(ThreadListSemaphore,1,NULL); ReleaseMutex(ThreadListMutex); return 0; } bail:; #endif } #ifdef COMPILED_FORDOS Base = ReadBuffer; // // Read the file in large blocks and compute the checksum. // Sum = 0; cbreadtotal = 0; while (cbread = fread(ReadBuffer, 1, READ_BUFFER_SIZE, FileHandle)) { cbreadtotal += cbread; pb = Base; // // Make sure the last byte of the buffer is zero in case a // partial buffer was read with an odd number of bytes in the // buffer. // ((PBYTE)ReadBuffer)[cbread] = 0; // // Compute the checksum using the same algorithm used for // tcp/ip network packets. This is a word checksum with all // carries folded back into the sum. // Sum = (DWORD)CheckSum(Sum, (LPWORD)ReadBuffer, (cbread + 1) >> 1); } #else { HANDLE Win32FileHandle; HANDLE MappingHandle; Win32FileHandle = (HANDLE)_get_osfhandle(_fileno(FileHandle)); MappingHandle = CreateFileMapping( Win32FileHandle, NULL, PAGE_READONLY, 0, 0, NULL ); if ( !MappingHandle ) { fprintf(stderr,"checkrel: failed to map file %s %d\n",PathName,GetLastError()); fclose(FileHandle); return 0; } Base = MapViewOfFile( MappingHandle, FILE_MAP_READ, 0, 0, 0 ); CloseHandle(MappingHandle); if ( !Base ) { fprintf(stderr,"checkrel: failed to map view of file %s %d\n",PathName,GetLastError()); fclose(FileHandle); return 0; } Sum = (DWORD)CheckSum(0,Base,(FileLength+1) >> 1); UnmapViewOfFile(Base); } #endif fclose(FileHandle); if (Sum == 0) { Sum = FileLength; } return(Sum); } #ifndef COMPILED_FORDOS DWORD PortFindFirstFile( LPSTR FindPattern, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ) { HANDLE FindHandle; WIN32_FIND_DATA FindFileData; FindHandle = FindFirstFile(FindPattern,&FindFileData); if ( FindHandle != INVALID_HANDLE_VALUE ) { strcpy(FindName,FindFileData.cFileName); *FindSize = FindFileData.nFileSizeLow; *IsDir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; } return (DWORD)FindHandle; } BOOL PortFindNextFile( DWORD FindHandle, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ) { BOOL b; WIN32_FIND_DATA FindFileData; b = FindNextFile((HANDLE)FindHandle,&FindFileData); if ( b ) { strcpy(FindName,FindFileData.cFileName); *FindSize = FindFileData.nFileSizeLow; *IsDir = FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; } return b; } VOID PortFindClose( DWORD FindHandle ) { FindClose((HANDLE)FindHandle); } #else DWORD PortFindFirstFile( LPSTR FindPattern, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ) { struct find_t *FindHandle; int error; FindHandle = malloc(sizeof(*FindHandle)); error = _dos_findfirst(FindPattern,_A_RDONLY | _A_NORMAL | _A_DIR, FindHandle); if ( error ) { free(FindHandle); return -1; } strcpy(FindName,FindHandle->name); *FindSize = FindHandle->size; *IsDir = FindHandle->attrib & 0x10; return (DWORD)FindHandle; } BOOL PortFindNextFile( DWORD FindHandle, LPSTR FindName, LPBOOL IsDir, LPDWORD FindSize ) { BOOL b; int error; struct find_t *xxFindHandle; xxFindHandle = (struct find_t *)FindHandle; error = _dos_findnext( xxFindHandle ); if ( error ) { return FALSE; } strcpy(FindName,xxFindHandle->name); *FindSize = xxFindHandle->size; *IsDir = FindHandle->attrib & 0x10; return TRUE; } VOID PortFindClose( DWORD FindHandle ) { free((int *)FindHandle); } WORD CheckSum( DWORD PartialSum, LPWORD Source, DWORD Length ) { register unsigned long t = PartialSum; register unsigned long r; while(Length--) { t += *Source++; } while (r = (t & 0xFFFF0000) { t &= 0x0000FFFF; t += (r >> 16); } return t; } #endif