windows-nt/Source/XPSP1/NT/sdktools/checkrel/newcheck.c
2020-09-26 16:20:57 +08:00

886 lines
20 KiB
C

#ifndef COMPILED_FORDOS
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#endif
#include <windows.h>
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <limits.h>
#include <malloc.h>
#include <errno.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <io.h>
#include <conio.h>
#include <sys\types.h>
#include <sys\stat.h>
#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;i<ThreadCount;i++){
Item = LocalAlloc(LMEM_ZEROINIT,sizeof(*Item));
Item->ItemType = 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;i<ThreadCount;i++) {
ThreadHandles[i] = CreateThread(
NULL,
0,
WorkerThread,
NULL,
0,
&ThreadId
);
if ( !ThreadHandles[i] ) {
ThreadCount = 0;
break;
}
}
}
else {
ThreadCount = 0;
}
}
else {
ThreadCount = 0;
}
break;
}
#endif
default:
fprintf( stderr, "checkrel: Invalid switch - /%c\n", c );
Result = FALSE;
break;
}
}
}
return( Result );
}
VOID
WalkTree(
FILE *CheckFile,
LPSTR SubDir
)
{
char NextSubDir[MAX_PATH];
DWORD FindHandle;
char FindPattern[MAX_PATH];
char FindName[MAX_PATH];
DWORD FindSize;
BOOL b;
BOOL IsDir;
//
// recursively walk the system searching all files
//
//
// build the find pattern
//
strcpy(FindPattern,RootOfTree);
if ( SubDir ) {
strcat(FindPattern,"\\");
strcat(FindPattern,SubDir);
}
strcat(FindPattern,"\\*.*");
if ( fVerbose ) {
fprintf(stdout,"WalkTree %s \n",FindPattern);
}
FindHandle = PortFindFirstFile(FindPattern,FindName,&IsDir,&FindSize);
if ( FindHandle == -1 ) {
fprintf(stderr,"checkrel: FindFirst(%s) failed %d\n",FindPattern,errno);
return;
}
b = TRUE;
while(b) {
_strlwr(FindName);
//
// recurse if we are at a directory
//
if ( IsDir ) {
//
// if name is . or .., skip to findnext
//
if ( !strcmp(FindName,".") || !strcmp(FindName,"..") ) {
goto findnext;
}
//
// if name is w32x86 or w32mips, skip to findnext
//
if ( !strcmp(FindName,"w32mips") || !strcmp(FindName,"w32x86") ) {
goto findnext;
}
NextSubDir[0] = '\0';
if ( SubDir ) {
strcat(NextSubDir,SubDir);
strcat(NextSubDir,"\\");
}
strcat(NextSubDir,FindName);
WalkTree(CheckFile,NextSubDir);
}
else {
NextSubDir[0] = '\0';
if ( SubDir ) {
strcat(NextSubDir,SubDir);
strcat(NextSubDir,"\\");
}
strcat(NextSubDir,FindName);
b = ComputeEntry(CheckFile,NextSubDir,FindSize);
}
if ( !b ) {
fprintf(stderr,"checkrel: ComputeEntry faild\n");
return;
}
findnext:
b = PortFindNextFile(FindHandle,FindName,&IsDir,&FindSize);
}
PortFindClose(FindHandle);
}
VOID
GenerateCheckFile( VOID )
{
FILE *CheckFile;
CheckFile = OpenCheckFile();
if ( !CheckFile ) {
return;
}
WalkTree(CheckFile,NULL);
}
VOID
ValidateCheckFile( VOID )
{
FILE *CheckFile;
DWORD CheckSize, CheckSum;
char CheckName[MAX_PATH];
DWORD n;
LPSTR PathName;
FILE *FileHandle;
DWORD ActualSize;
DWORD ActualSum;
CheckFile = OpenCheckFile();
if ( !CheckFile ) {
return;
}
PathName = malloc(strlen(RootOfTree)+MAX_PATH+1);
if ( !PathName ) {
fprintf(stderr,"checkrel: memory allocation for %d bytes failed\n",strlen(RootOfTree)+MAX_PATH+1);
return;
}
n = fscanf(CheckFile,"%s %x %x",CheckName,&CheckSum,&CheckSize);
while ( n != EOF ) {
if ( n != 3 ) {
fprintf(stderr,"checkrel: error in format\n");
return;
}
//
// Now form the file and do the checksum compare
//
strcpy(PathName,RootOfTree);
strcat(PathName,"\\");
strcat(PathName,CheckName);
FileHandle = fopen(PathName,"rb");
if ( !FileHandle ) {
fprintf(stderr,"checkrel: failed to open file %s %d\n",PathName,errno);
}
else {
ActualSize = _filelength(_fileno(FileHandle));
if ( ActualSize == 0xffffffff ) {
fprintf(stderr,"checkrel: unable to get file size for file %s %d\n",PathName,errno);
fclose(FileHandle);
}
else {
if ( ActualSize != CheckSize ) {
fprintf(stderr,"checkrel: FileSizes Differ for %s Actual %x vs. %x\n",PathName,ActualSize,CheckSize);
}
ActualSum = CheckSumFile(FileHandle,PathName,ActualSize,NULL);
if ( ActualSum ) {
if ( ActualSum != CheckSum ) {
fprintf(stderr,"checkrel: CheckSums Differ for %s Actual %x vs. %x\n",PathName,ActualSum,CheckSum);
}
}
if ( fVerbose ) {
fprintf(stdout,"%s Sum(%x vs %x) Size(%x vs %x)\n",PathName,ActualSum,CheckSum,ActualSize,CheckSize);
}
}
}
n = fscanf(CheckFile,"%s %x %x",CheckName,&CheckSum,&CheckSize);
}
}
FILE *
OpenCheckFile()
{
FILE *CheckFile;
GlobalCheckFile = (FILE *)-1;
CheckFileName = malloc(strlen(RootOfTree)+strlen(CHECK_NAME)+1);
if ( !CheckFileName ) {
return (FILE *)-1;
}
strcpy(CheckFileName,RootOfTree);
strcat(CheckFileName,CHECK_NAME);
if ( fVerbose ) {
fprintf(stdout,"checkrel: check name %s\n",CheckFileName);
}
CheckFile = fopen(CheckFileName,fGenerateCheck ? "wt" : "rt");
if ( !CheckFile ) {
fprintf(stderr,"checkrel: open %s failed %d\n",CheckFileName,errno);
}
GlobalCheckFile = CheckFile;
return CheckFile;
}
BOOL
ComputeEntry(
FILE *CheckFile,
LPSTR FileName,
DWORD FileLength
)
{
char PathName[MAX_PATH];
DWORD CheckSum;
DWORD LineLength;
strcpy(PathName,RootOfTree);
strcat(PathName,"\\");
strcat(PathName,FileName);
CheckSum = CheckSumFile(NULL,PathName,FileLength,FileName);
if ( CheckSum ) {
LineLength = sprintf(OutputLine,"%s %x %x\n",FileName,CheckSum,FileLength);
if ( fVerbose ) {
fprintf(stdout,"%s",OutputLine);
}
fwrite(OutputLine,1,LineLength,CheckFile);
}
return TRUE;
}
DWORD
CheckSumFile(
FILE *InputHandle,
LPSTR PathName,
DWORD FileLength,
LPSTR FileName
)
{
FILE *FileHandle;
DWORD Sum;
signed char *pb;
LPDWORD pul;
PVOID Base;
DWORD cbread, cbreadtotal;
if ( InputHandle ){
FileHandle = InputHandle;
}
else {
FileHandle = fopen(PathName,"rb");
if ( !FileHandle ) {
fprintf(stderr,"checkrel: failed to open file %s %d\n",PathName,errno);
return 0;
}
#ifndef COMPILED_FORDOS
if ( ThreadCount ) {
PWORK_ITEM Item;
HANDLE Win32FileHandle;
HANDLE MappingHandle;
//
// Queue the generate request to a worker thread
//
Item = LocalAlloc(LMEM_ZEROINIT,sizeof(*Item));
if (!Item) {
goto bail;
}
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;
}
fclose(FileHandle);
Item->ItemType = 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