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

948 lines
30 KiB
C

// Analyses the output from the new chkeckrel
// t-mhills
#include <direct.h>
#include <io.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define F_flag 1 //Values to store in the command line switches flag
#define I1_flag 2
#define I2_flag 4
#define X_flag 8
// These codes should match the codes below in the usage description
#define par_err 6 //comand line parameter error exit code 5
#define exep_err 5 //error in the exception file
#define chk_err 4 //error in the one of the source files
#define mem_err 3 //memory allocation error
#define file_err 2 //file find/read error
#define comp_err 1 //comparison found differences
#define no_err 0 // files compared okay
#define exceptionfilelinelength 512 //These value used to control the size of temporary strings
#define chkfilelinelength 2048 //Ideally there would be no limit but file reads require static variables
#define maxpathlength 200
struct translatetable //Used to store translate commands from the exception file.
{
struct translatetable *next;
char *source1name;
char *source2name;
};
struct excludetable //Used to store exclude commands from the exception file.
{
struct excludetable *next;
char *path;
};
struct checksums //Used to store checksums with file names.
{
struct checksums *next;
long sum;
char filename; // This structure is of variable length to accomodate any string length.
};
void error (char exitcode); //Ends program and returns exitcode to the system.
void showchecksumlist (struct checksums *list); //Displays Checksums with filenames.
void showdualchecksumlist (struct checksums *list); //Shows checksums in a format good for missmatched checksums.
char excluded (char *str, struct excludetable *ex); //If any of the exclude strings are in str it returns true.
char *translate (char *str, struct translatetable *tran); //Make a copy of str with changes from exception file.
long readhex (char *str); //Convert hex string to long.
char proccessline (char *tempstr, struct translatetable *translations, struct excludetable *exclusions,
char *startpath, char flags, char **filename, long *filesum);
//Parse line and apply all exceptions and flags
char loadsource1 (char *filename, struct checksums **sums,
struct translatetable *translations, struct excludetable * exclusions,
char *startpath, char flags); //Load source1 into a checksum list.
char comparesource2 (char *filename, struct checksums **sums,
struct checksums **extrasource2, struct checksums **missmatched,
struct translatetable *translations, struct excludetable * exclusions,
char *startpath, char flags); //Compare the second file to the checksum list.
void removewhitespace (char *str); //Removes whitespace from the end of a string.
char *strstrupcase (char *str1, char *str2); //Case insensitive strstr.
char proccess_exception_file (char *filename, struct translatetable **trans, struct excludetable **exclude, char **path);
//Parse exception file.
char proccess_command_line (int argc, char *argv[ ], char **source1, char **source2, char *flags, char **exception);
//Parse command line arguments
void completehelp (); //Show nearly complete documentation
// ******************************** MAIN ***************************
void __cdecl
main(
int argc,
char *argv[ ]
)
{
char errnum = 0;
char *source1filename = NULL;
char *source2filename = NULL;
char *exceptionfilename = NULL;
char flags; // flags: /F=1=(F_flag); /I1=2=(I1_flag); /I2=4=(I2_flag); /X=8=(X_flag)
struct translatetable *translations = NULL; //
struct excludetable *exclusions = NULL; //Information from exception file stored here.
char *startpath = NULL; //
struct checksums *source1checksums = NULL; //List of extra files in Source1
struct checksums *source2checksums = NULL; //List of extra files in Source2
struct checksums *missmatched = NULL; //List of files with chechsums that don't match.
struct translatetable *temp = NULL; //
struct checksums *temp2 = NULL; //Temporary pointers used to help deallocate memory
//Parse command line.
if (errnum = proccess_command_line (argc, argv, &source1filename, &source2filename, &flags, &exceptionfilename))
{
goto freecommandline; // skip to end and deallocate memory
}
//Show information obtained from command line.
printf ("Source1 = %s\n", source1filename);
printf ("Source2 = %s\n", source2filename);
if (flags & F_flag)
printf ("Comparing flat Share.\n");
if (flags & I1_flag)
printf ("Ignoring extra files in Source1.\n");
if (flags & I2_flag)
printf ("Ignoring extra files in Source2.\n");
if (flags & X_flag)
printf ("Exception file = %s\n", exceptionfilename);
//Parse the excpetion file if it exists.
if (flags & X_flag)
{
if (errnum = proccess_exception_file (exceptionfilename, &translations, &exclusions, &startpath))
{
goto freeexceptiontable; //skip to end and dealocate memory
};
//Display information from exception file.
temp = translations;
while (temp != NULL)
{
printf ("TRANSLATE %s --> %s\n", temp->source1name, temp->source2name);
temp = temp->next;
};
temp = (struct translatetable *) exclusions; //note: using wrong type to avoid making another temp pointer
while (temp != NULL)
{
printf ("EXCLUDE %s\n", temp->source1name);
temp = temp->next;
};
if (startpath != NULL)
printf ("STARTPATH %s\n", startpath);
};
//Read source1 and store files and checksums in source1checksums.
if (errnum = loadsource1 (source1filename, &source1checksums, translations, exclusions, startpath, flags))
{
goto freesource1checksums;
};
//printf ("\n\nSource1:\n\n"); //for debugging
//showchecksumlist (source1checksums);
//Read source2 and compare it to the files/checksums from source1. Store differences.
if (errnum = comparesource2 (source2filename, &source1checksums, &source2checksums, &missmatched,
translations, exclusions, startpath, flags))
{
goto freesource2checksums;
};
//Display extra files unless /I1 or /I2 was used in the command line.
if ((!(flags & I1_flag)) & (source1checksums != NULL))
{
errnum = 1;
printf ("\n********** Extra files in %s **********\n", source1filename);
showchecksumlist (source1checksums);
};
if ((!(flags & I2_flag)) & (source2checksums != NULL))
{
errnum = 1;
printf ("\n********** Extra files in %s **********\n", source2filename);
showchecksumlist (source2checksums);
};
//Display missmatched checksums.
if (missmatched != NULL)
{
errnum = 1;
printf ("\n********** Checksums from %s != checksums from %s.**********\n", source1filename, source2filename);
showdualchecksumlist (missmatched);
};
//Deallocate memory.
freesource2checksums:
while (source2checksums != NULL)
{
temp2 = source2checksums;
source2checksums = source2checksums->next;
free (temp2);
};
while (missmatched != NULL)
{
temp2 = missmatched;
missmatched = missmatched->next;
free (temp2);
};
freesource1checksums:
while (source1checksums != NULL)
{
temp2 = source1checksums;
source1checksums = source1checksums->next;
free (temp2);
};
freeexceptiontable:
if (startpath != NULL)
free (startpath);
while (translations != NULL)
{
if (translations->source1name != NULL)
free (translations->source1name);
if (translations->source2name != NULL)
free (translations->source2name);
temp = translations;
translations = translations->next;
free (temp);
};
while (exclusions != NULL)
{
if (exclusions->path != NULL)
free (exclusions->path);
temp = (struct translatetable *) exclusions;
exclusions = exclusions->next;
free (temp);
};
freecommandline:
if (source1filename != NULL)
free (source1filename);
if (source2filename != NULL)
free (source2filename);
if (exceptionfilename != NULL)
free (exceptionfilename);
//End program and show help if needed.
error (errnum);
};
void showchecksumlist (struct checksums *list)
{
while (list != NULL)
{
printf ("%d %s\n", list->sum, &(list->filename));
list = list->next;
};
};
void showdualchecksumlist (struct checksums *list)
//This can only be used with the missmatched checksums list since it assumes that the files
//come in pairs of identical filenames with different checksums.
{
while (list != NULL)
{
if (list->next == NULL)
{
printf ("Error: list corruption detected in showdualchecksumlist function.\n");
return;
};
printf ("%d != %d %s\n", list->sum, list->next->sum, &(list->filename));
list = list->next->next;
};
};
char excluded (char *str, struct excludetable *ex) //If any of the exclude strings are in str it returns true.
{
while (ex != NULL)
{
if (strstr (str, ex->path))
return (1);
ex = ex->next;
}
return (0);
};
char *translate (char *str, struct translatetable *tran)
{
char *temp;
char *newstr;
while (tran != NULL) //Search translate table.
{
if ((temp = strstr (str, tran->source1name)) != NULL) //If we found one that needs translating
{
//Allocate memory for new string.
if ((newstr = malloc (strlen (str) + strlen (tran->source2name) - strlen(tran->source1name) + 1))==NULL)
return (NULL);
strncpy(newstr, str, (size_t)(temp - str)); //Write part before translations.
strcpy (&newstr [temp-str], tran->source2name); //Add translated part
strcat (newstr, &temp [strlen (tran->source1name)]); //Add end of string
return (newstr);
};
tran = tran->next;
};
return (_strdup (str)); //If didn't need to be translated, make a new copy anyway for uniformity.
};
long readhex (char *str)
{
long temp = 0;
int position = 0;
for (position = 0; 1;position++)
{
if ((str[position] == ' ')|(str[position] == '\n')|(str[position] == '\x00'))
{
return (temp);
}
else
{
temp *= 16;
if ((str [position] >= '0') & (str [position] <= '9'))
{
temp+=(str[position]-'0');
}
else if ((str [position] >= 'a') & (str [position] <= 'f'))
{
temp+=(str[position]-'a'+10);
}
else
return (-1);
};
};
};
char proccessline (char *tempstr, struct translatetable *translations, struct excludetable *exclusions,
char *startpath, char flags, char **filename, long *filesum)
{
char *name;
char *newname;
char *sumstr;
*filename = NULL; //Make sure that if no name is returned this is blank
removewhitespace (tempstr);
//If it is a line that says "- N0 files" then the sum is assigned to 0
if ((sumstr = strstr (tempstr, " - No files")) != NULL)
{
*filesum=0;
sumstr [0]=0;
}
//Otherwise find checksum
else
{
sumstr = tempstr + strlen (tempstr); //Find checksum by finding the last space in the line
while ((sumstr [0] != ' ')&(sumstr != tempstr)) //
sumstr--; //
if (sumstr==tempstr) //
{
printf ("Comment: %s", tempstr); //If there is no space before the first character,
return (chk_err); //the line is invalid. Assume it is a comment.
};
sumstr [0] = 0; //Split string into path/filename and checksum
sumstr++; //
//convert checksum string to a number
if ((*filesum = readhex (sumstr))==-1)
{
printf ("Comment: %s %s\n", tempstr, sumstr); //If the checksum isn't a valid hex number
return (chk_err); //assume the line is a commment.
};
};
//Apply any translations that may be valid for this path/file.
if ((name = translate (tempstr, translations)) == NULL)
{
printf ("Need memory.");
return (mem_err);
};
//Make sure this file isn't excluded.
if (!excluded (name, exclusions))
{
//If there isn't a startpath then all files will be proccessed
//If there is a startpath then only the ones containing the path will be proccessed
if (startpath == NULL)
{
newname = name;
goto instartpath;
}
else if ((newname = strstr (name, startpath)) != NULL) //If this file is in startpath
{
newname = newname + strlen (startpath); //Remove startpath
instartpath: //This happens if one of the above conditions was true
//Remove path if doing a flat compare.
if (flags & F_flag)
{
while (strstr (newname, "\\") != NULL) // Remove path
{ //
newname = strstr (newname, "\\"); //
newname++; // and leading "\\"
};
};
//Make a final copy of the path/file to return
if ((*filename = _strdup (newname)) == NULL)
{
printf ("Memory err.");
free (name);
return (mem_err);
};
};
};
free (name);
return (0);
};
char loadsource1 (char *filename, struct checksums **sums,
struct translatetable *translations, struct excludetable * exclusions,
char *startpath, char flags)
{
FILE *chkfile;
char tempstr [chkfilelinelength];
char *name;
char err;
long tempsum;
struct checksums *newsum;
struct checksums **last; //Used to keep trak of the end of the linked list.
last = sums;
if ((chkfile = fopen (filename, "r"))==NULL)
{
printf ("Error opening source1.\n\n");
return (file_err);
};
//Proccess all lines
while (fgets (tempstr, chkfilelinelength, chkfile) != NULL)
{
//Verify that the entire line was read in and not just part of it
if (tempstr [strlen (tempstr)-1] != '\n')
{
printf ("Unexpected end of line. chkfilelinelength may need to be larger.\n %s\n", tempstr);
fclose (chkfile);
return (chk_err);
};
//Parse line
if ((err = proccessline (tempstr, translations, exclusions, startpath, flags, &name, &tempsum)) == 0)
{
//If this line was excluded or not in the path don't do anything, just go on to the next line.
if (name != NULL)
{
//Create a new structure and add it to the end of the linked list.
if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
{ //Note: this is a variable length structure to fit any size of string.
printf ("Memory err.");
fclose (chkfile);
return (mem_err);
};
*last = newsum;
newsum->next = NULL;
newsum->sum = tempsum;
strcpy(&(newsum->filename), name);
last = &((*last)->next);
//Free temporary storage.
free (name);
};
}
else
{
if (err != chk_err) //Just skip line if it isn't understandable.
{
fclose (chkfile);
return (err);
};
};
};
//Ckeck to make sure it quit because it was done and not because of file errors.
if (ferror (chkfile))
{
printf ("Error reading source1.\n\n");
return (file_err);
};
if (fclose (chkfile))
{
printf ("Error closing source1.\n\nContinuing anyway...");
};
return (0);
};
char notnull_strcmp (struct checksums *sum, char *str)
// perform short circuit evaluation of ((sum != NULL) & (strcmp (&(sum->filename), str) != 0)
{
if (sum != NULL)
{
if (strcmp (&(sum->filename), str) != 0)
{
return (1);
};
};
return (0);
};
char comparesource2 (char *filename, struct checksums **sums,
struct checksums **extrasource2, struct checksums **missmatched,
struct translatetable *translations, struct excludetable * exclusions,
char *startpath, char flags)
{
FILE *chkfile;
char tempstr [chkfilelinelength];
char *name;
char err;
long tempsum;
struct checksums *newsum;
struct checksums *search;
struct checksums **lastlink;
if ((chkfile = fopen (filename, "r"))==NULL)
{
printf ("Error opening source2.\n\n");
return (file_err);
};
while (fgets (tempstr, chkfilelinelength, chkfile) != NULL)
{
//Verify that the entire line was read.
if (tempstr [strlen (tempstr)-1] != '\n')
{
printf ("Unexpected end of line. chkfilelinelength may need to be larger.\n %s\n", tempstr);
fclose (chkfile);
return (chk_err);
};
//Parse line
if ((err = proccessline (tempstr, NULL, exclusions, startpath, flags, &name, &tempsum)) == 0)
{
//If file was skipped do nothing
if (name != NULL)
{
//Prepare to look for a match
search = *sums;
lastlink = sums;
//short circuit evaluation of:(search != NULL) & (strcmp (&(search->filename), name) != 0)
while (notnull_strcmp (search, name))
{
search = search->next;
lastlink = &((*lastlink)->next);
};
if (search != NULL) //If a match was found
{ // remove it from the sums list
*lastlink = search->next; // by linking around it
if (search->sum == tempsum) // If checksums match
{ //
search->sum=0;
free (search); // Deallocate memory
} //
else // If the checksums didn't match
{ //
if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
{ // Add 2nd name and checksum to missmatched list
printf ("Memory err."); //
fclose (chkfile); //
return (mem_err); //
}; //
newsum->next = *missmatched; //
newsum->sum = tempsum; //
strcpy(&(newsum->filename), name);
*missmatched = newsum; //
search->next = *missmatched; // Add 1st name to the missmatched list
*missmatched = search; //
}; //
} //
else //If no match was found
{ // this needs to be added to extrasource2 list
if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
{ //Note: this is a variable length structure to fit any size of string.
printf ("Memory err.");
fclose (chkfile);
return (mem_err);
};
newsum->next = *extrasource2;
newsum->sum = tempsum;
strcpy(&(newsum->filename), name);
*extrasource2 = newsum;
};
//free temporary storage
free (name);
};
}
else
{
if (err != chk_err) //Just skip the line (don't abort) if it is bad
{
fclose (chkfile);
return (err);
};
};
};
if (ferror (chkfile))
{
printf ("Error reading source2.\n\n");
return (file_err);
};
if (fclose (chkfile))
{
printf ("Error closing source2.\n\nContinuing anyway...");
};
return (0);
};
void removewhitespace (char *str) // removes whitespace from the end of a string
{
int end;
end = strlen (str);
while ((end > 0)&((str [end-1] == '\n')|(str [end-1] == ' ')))
end--;
str [end] = 0;
};
char *strstrupcase (char *str1, char *str2)
{
char *temp;
size_t count;
size_t length;
length = strlen (str2);
for (temp = str1; strlen (temp) > length; temp++)
{
for (count = 0; (toupper (temp [count]) == toupper (str2 [count]))&(count < length); count++);
if (count==length)
{
return (temp);
};
};
return (NULL);
};
char proccess_exception_file (char *filename, struct translatetable **trans, struct excludetable **exclude, char **path)
{
FILE *efile;
char tempstr [exceptionfilelinelength];
char *start;
char *end;
struct translatetable *temp;
if ((efile = fopen (filename, "r"))==NULL)
{
printf ("Error opening excetion file.\n\n");
return (file_err);
}
while (fgets (tempstr, exceptionfilelinelength, efile) != NULL)
{
start = tempstr;
while (start [0] == ' ') //Remove leading whitespace
start++;
//If it is a translate command
if (strstrupcase (start, "TRANSLATE") == start)
{
start = start + 10; //Go past translate
while (start [0] == ' ') //skip spaces
start++;
if (start [0] == 0)
{
printf ("Unexpected end of line in exception file:\n%s", tempstr);
return (exep_err);
};
end = strstr (start, "-->"); //Find second part of string
if (end == NULL)
{
printf ("Line: %s \nmust have two file names separated by -->", tempstr);
return (exep_err);
}
end [0] = '\0'; //Split string
removewhitespace (start);
if ((temp = malloc (sizeof (struct translatetable))) == NULL)
{
printf ("Insufficient memory to load exception table.");
return (mem_err);
}
if ((temp->source1name = _strdup (start)) == NULL)
{
printf ("Unable to allocate memory for char temp->source1name in proccess_exception_file.\n");
free (temp);
return (mem_err);
}
start = end + 3;
while (start [0] == ' ') //Remove leading whitespace
start++;
if (start [0] == 0)
{
printf ("Unexpected end of line in exception file:\n %s", tempstr);
free (temp->source1name);
free (temp);
return (exep_err);
};
removewhitespace (start);
if ((temp->source2name = _strdup (start)) == NULL)
{
printf ("Unable to allocate memory for char temp->source1name in proccess_exception_file.\n");
free (temp->source1name);
free (temp);
return (mem_err);
}
temp->next = *trans;
*trans = temp;
}
//If it is an exclude command.
else if (strstrupcase (start, "EXCLUDE") == start)
{
start = start + 7; //Go past exclude
while (start [0] == ' ') //skip spaces
start++;
if (start [0] == 0)
{
printf ("Unexpected end of line in exception file:\n %s", tempstr);
return (exep_err);
};
removewhitespace (start);
if ((temp = malloc (sizeof (struct excludetable))) == NULL)
{
printf ("Insufficient memory to load exception table.");
return (mem_err);
}
if ((temp->source1name = _strdup (start)) == NULL) //source1name coresponds to path
{
printf ("Unable to allocate memory for char temp->path in proccess_exception_file.\n");
free (temp);
return (mem_err);
}
temp->next = (struct translatetable *) *exclude;
*exclude = (struct excludetable *) temp;
}
//If it is a startpath command
else if (strstrupcase (start, "STARTPATH") == start)
{
if (*path != NULL)
{
printf ("Only one STARTPATH command is allowed in the exception file.\n");
return (exep_err);
};
start = start + 9; //Go past startpath
while (start [0] == ' ') //skip spaces
start++;
if (start [0] == 0)
{
printf ("Unexpected end of line in exception file:\n %s", tempstr);
return (exep_err);
};
removewhitespace (start);
if ((*path = _strdup (start)) == NULL)
{
printf ("Unable to allocate memory for char path in proccess_exception_file.\n");
return (mem_err);
}
}
else if (!start [0] == ';') //if it's not a comment
{
printf ("Unexpected line in exception file:\n %s", tempstr);
return (exep_err);
};
};
if (ferror (efile))
{
printf ("Error reading exception file.\n\n");
return (file_err);
};
if (fclose (efile))
{
printf ("Error closing excetion file.\n\nContinuing anyway...");
};
return (0);
};
char proccess_command_line (int argc, char *argv[ ], char **source1, char **source2, char *flags, char **exception)
// flags: /F=1=(F_flag); /I1=2=(I1_flag); /I2=4=(I2_flag); /X=8=(X_flag)
{
int argloop;
*flags=0; //temporarily using 16=source1 found; 32=source2 found
for (argloop = 1;argloop < argc; argloop++)
{
if (argv[argloop][0] == '/')
{
if ((argv[argloop][1] == 'F')|(argv[argloop][1] == 'f')) //we got a /f
{
*flags|=F_flag; //duplicate flags will not cause errors
}
else if (argv[argloop][1] == '?')
{
completehelp ();
}
else if ((argv[argloop][1] == 'I')|(argv[argloop][1] == 'i'))
{
if (argv[argloop][2] == '1')
{
*flags|=I1_flag; //we got a /i1
}
else if (argv[argloop][2] == '2')
{
*flags|=I2_flag; //we got a /i2
}
else
{
printf ("Unknown switch \"/I%c\" .\n\n", argv[argloop][2]);
return (par_err);
}
}
else if ((argv[argloop][1] == 'X')|(argv[argloop][1] == 'x'))
{
*flags|=X_flag; // we got a /x
if (argloop+1 == argc)
{
printf ("Parameter /X must be followed by a filename.\n\n");
return (par_err);
};
if ((*exception = _strdup (argv [argloop + 1]))==NULL)
{
printf ("Unable to allocate memory for char *exception in proccess_command_line.\n");
error (mem_err);
};
argloop++; //to skip this parameter in the general parser
}
else
{
printf ("Unknown switch \"/%c\" .\n\n", argv[argloop][1]);
return (par_err);
}
}
else // it must be a source filename
{
if (!(*flags & 16)) //first source in command line
{
if ((*source1 = _strdup (argv [argloop]))==NULL)
{
printf ("Unable to allocate memory for char *source1 in proccess_command_line.\n");
return (mem_err);
};
*flags|=16;
}
else if (!(*flags & 32)) //second source in command line
{
if ((*source2 = _strdup (argv [argloop]))==NULL)
{
printf ("Unable to allocate memory for char *source2 in proccess_command_line.\n");
return (mem_err);
};
*flags|=32;
}
else
{
printf ("Too many source filenames in the command line.\n\n");
return (par_err);
};
};
};
if (!(*flags & 32))
{
printf ("Command line must contain two source files.\n\n");
return (par_err);
};
*flags|=(!(32+16)); // clear temporary source1 and source2 flags
return (0);
};
void completehelp ()
{
printf ("Usage:\n"
"CHKVERFY <Source1> <Source2> [/F] [/X <exceptionfile>] [/I1] [/I2]\n"
" /F = Flat share (ignore paths).\n"
" /I1 = Ignore extra files in Source1.\n"
" /I2 = Ignore extra files in Source2.\n"
" /X = excetion file with the following commands.\n"
" TRANSLATE <Source1name> --> <Source2name>\n"
" Replaces <Source1name> with <Sourece2name> whereever found.\n"
" Note: make sure the filename you are using is only in the full\n"
" filename of the files you mant to translate.\n\n"
" EXCLUDE <pathsegment>\n"
" Any path and file containing this string will be ignored.\n\n"
" STARTPATH <directory name>\n"
" Files without this string in the path will be ignored.\n"
" The part of the path before this string will be ignored.\n\n"
" Note: These three commands are proccessed in the order shown above. \n"
" For example, the command \"TRANSLATE C:\\nt --> C:\\\" will\n"
" override the command \"EXCLUDE C:\\nt\".\n"
" The order of commands in the exception files doesn't matter\n"
" unless two commands both try to translate the same file.\n"
" In that case, the last command in the file takes precedence.\n"
"Exit codes:\n" // These code values should match the codes defined above.
" 6 = Invalid command line arguments.\n"
" 5 = Error in exception file format.\n"
" 4 = Error in chkfile.\n"
" 3 = Memory allocation error.\n"
" 2 = File access error.\n"
" 1 = No errors: Source1 and Source2 failed compare.\n"
" 0 = No errors: Source1 and Source2 compared successfully.\n\n"
);
exit (0);
};
void error (char exitcode)
{
if (exitcode >= exep_err)
{
printf ("Usage:\n"
"CHKVERFY <Source1> <Source2> [/F] [/X <exceptionfile>] [/I1] [/I2]\n"
" /? = Complete help.\n"
" /F = Flat share (ignore paths).\n"
" /I1 = Ignore extra files in Source1.\n"
" /I2 = Ignore extra files in Source2.\n"
" /X = excetion file with the following commands.\n"
);
};
switch (exitcode)
{
case 0:
printf ("\n\n(0) Files compare okay.\n");
break;
case 1:
printf ("\n\n(1) Some files or checksums don't match.\n");
break;
case 2:
printf ("\n\n(2) Terminated due to file access error.\n");
break;
case 3:
printf ("\n\n(3) Terminated due to memory allocation error.\n");
break;
case 4:
printf ("\n\n(4) The format of the source files was not as expected.\n");
break;
case 5:
printf ("\n\n(5) Error in exception file format.\n");
break;
case 6:
printf ("\n\n(6) Bad command line argument.\n");
break;
};
exit (exitcode);
};