home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
c
/
cnews011.arc
/
FILECHK.ARC
/
FILECHK.C
next >
Wrap
Text File
|
1988-08-14
|
11KB
|
400 lines
/* filechk.c -- Disk file integrity checker.
Reads all files on disk in current directory and in
lower level subdirectories to verify readability and
file size.
by Arnold Cherdak, 8/11/88, Turbo C, Version 1.5
RELEASED TO THE PUBLIC DOMAIN
*/
#include <stdio.h>
#include <dir.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\stat.h>
#define NOT_ENUFF_SPACE "\nINSUFFICIENT MEMORY SPACE!\n"
#define FILECHK "FILECHK"
#define BUFFER_SIZE 0x2000
#define BAD_FILE_SIZE ": FILE SIZE IS WRONG!"
#define PATH_SIZE 128
#define TRUE 0xffffu
#define FALSE 0u
#define TITLE "\nFILECHK version 1.0 by Arnold Cherdak, all rights reserved"
#define HEADER "\nFile Name Size Date Time Attributes"
/***************************************************************************
In the DOS directory entry, DOS time and date parameters are bit strings
that are to be interpreted as follows:
bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
TIME h h h h h m m m m m m x x x x x
DATE y y y y y y y M M M M d d d d d
where:
h is the binary number of hours (0-23)
m is the binary number of minutes (0-59)
x is the binary number of two-second increments (0-29) corresponding
to 0-58 seconds
y is the binary year number since 1980 (0-119) corresponding to
1980-2099 ( WOW! Think this program/operating system will be around
( that long?
M is the binary number of the month (1-12)
d is the binary number of the day of the month (1-31)
The attribute byte is a bit field with interpretation as follows:
BIT MEANING IF SET TO 1
0 read-only
1 hidden
2 system file
3 volume label
4 subdirectory file
5 archive bit
6 (reserved -- not used)
7 (reserved -- not used)
****************************************************************************/
struct DOS_TIME /* bit field definitions for time */
{
unsigned twosecs:5; /* NOTE: LSB first */
unsigned minute:6;
unsigned hour:5;
};
struct DOS_DATE /* bit field definitions for date */
{
unsigned day:5;
unsigned month:4;
unsigned year:7;
};
struct DOS_ATTRIB /* bit field definitions for attributes */
{
unsigned R :1; /* read only */
unsigned H :1; /* hidden */
unsigned S :1; /* system */
unsigned V :1; /* volume label */
unsigned D :1; /* subdirectory */
unsigned A :1; /* archive bit */
unsigned yy:2; /* reserved */
unsigned xx:8; /* filler, high-order 8-bits to make a full integer */
};
struct STACK_NODE
{
char path[PATH_SIZE];
int attribs;
struct ffblk dta;
struct STACK_NODE *next; /* double-linked list */
struct STACK_NODE *previous;
};
/**************************************************************************/
void main(int argc, char *argv[])
/**************************************************************************/
{
int j,files,ndirs,subdirs,handle,amount,retn,nfiles,nbrfiles,nerrs,flag;
int helpmax,i;
unsigned DOption;
long total,grand_total,dir_total;
char attr[6],*buffer,thisdir[PATH_SIZE],c;
struct STACK_NODE *dir = NULL;
union
{
struct DOS_DATE date;
struct DOS_TIME time;
struct DOS_ATTRIB attrib;
int value;
} entry;
char *help[] = {
"\n\nDisk File Integrity Checker: Reads all files on a disk or in",
"\none or more (sub)directories to verify that the directory entry",
"\nfor each file is correct and that the file is readable.",
"\n\nUsage: FILECHK [-D] [-H] [-?] [directoryname]",
"\n Default operation (without command line entries) causes FILECHK",
"\n to read all files in the current directory and all files in",
"\n subdirectories below the current directory.",
"\n\n -D option causes FILECHK to process files in the current directory,",
"\n only.",
"\n\n -H and -? options provide the help screen (this one).",
"\n\n The presence of a string, 'directoryname', causes FILECHK to begin",
"\n processing in the directory having the name, 'directoryname'.\n"};
helpmax = 12; /* there are 12 lines in the help screen */
/* print program header */
printf(TITLE);
/* allocate a file buffer */
if((buffer = (char *) malloc(BUFFER_SIZE)) == NULL)
{
printf(NOT_ENUFF_SPACE);
exit(1);
}
/* allocate a root directory node */
if((dir = (struct STACK_NODE *) calloc(1, sizeof(struct STACK_NODE))) == NULL)
{
printf(NOT_ENUFF_SPACE);
exit(1);
}
dir->previous = NULL;
dir->next = NULL;
/* Get current working directory. */
if(getcwd(thisdir, PATH_SIZE) == NULL)
{
printf("\n");
perror(FILECHK);
exit(1);
}
strcpy(dir->path, thisdir);
/* See if there are any command line parameters */
DOption = FALSE;
if(argc > 1)
{
/* find switches first */
for(j=1;j<argc;j++)
if(argv[j][0] == '-' || argv[j][0] == '/')
if((c = toupper(argv[j][1])) == 'D')
DOption = TRUE;
else if(c == 'H' | c == '?')
{
for(i=0;i<helpmax;i++)
printf(help[i]);
exit(0);
}
/* Now see if this is to take place in some other directory */
for(j=1;j<argc;j++)
if(argv[j][0] != '-' && argv[j][0] != '/')
{
strcpy(dir->path,argv[j]);
if(chdir(dir->path) < 0)
{
perror(FILECHK);
exit(1);
}
break;
}
}
/* Set up search criteria. These are file attributes defined in
header file, dos.h
*/
files = FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH;
subdirs = FA_DIREC;
dir->attribs = files;
flag = files;
/* Get the first file. */
if((retn = findfirst("*.*", &(dir->dta), dir->attribs)) != 0)
{
perror(FILECHK);
exit(1);
}
/* print path */
printf("\n\nSTARTING AT: %s",dir->path);
/* print file listing header */
printf(HEADER);
/* Now, print a structured directory listing and then examine the file.
Repeat this for all files in the current and lower subdirectories.
*/
ndirs = 1;
nfiles = nbrfiles = nerrs = 0;
grand_total = dir_total = 0L;
while(TRUE)
{
if(retn == -1)
/* at end */
{
if(dir->previous == NULL && dir->attribs == subdirs)
/* all done */
{
printf("\n\n%d Files Processed in %d (Sub)Directories",nfiles,ndirs);
printf("\n%ld Characters Processed",grand_total);
printf("\n%d Errors Detected\n",nerrs);
chdir(thisdir);
exit(0);
}
else if(dir->attribs == subdirs)
/* go back to next higher level subdirectory */
{
dir = dir->previous;
free(dir->next);
/* Change back to old subdirectory */
if(chdir(dir->path) < 0)
{
perror(FILECHK);
exit(1);
}
/* Get the next file. */
retn = findnext(&(dir->dta));
}
else /* attribs == files */
{
dir->attribs = subdirs;
flag = subdirs;
printf("\nThis Directory Total Files Processed = %d",nbrfiles);
printf("\nThis Directory Total Characters Processed = %ld",dir_total);
dir_total = 0L;
nbrfiles = 0;
if(DOption == TRUE)
retn = -1;
else
/* Get the first subdirectory. */
retn = findfirst("*.*", &(dir->dta), dir->attribs);
}
}
else
/* not at end of current subdirectory */
{
/* This is NOT a subdirectory. */
if(!(dir->dta.ff_attrib & FA_DIREC) && flag == files)
{
/* We are not looking for subdirectories here -- this is needed
because DOS will return ALL files even though we ask
only for subdirs. See DOS call 21h, function 4eh.
Print directory data.
*/
printf("\n%-12s",dir->dta.ff_name);
printf("%8ld",dir->dta.ff_fsize);
/* set up date */
entry.value = dir->dta.ff_fdate;
/* now print the date */
printf(" %2d-%02d-%2d",entry.date.month, entry.date.day,
entry.date.year + 80);
/* set up time */
entry.value = dir->dta.ff_ftime;
/* now print the file time */
printf(" %2d:%02d:%02d",entry.time.hour, entry.time.minute,
entry.time.twosecs * 2);
/* set up attributes */
entry.value = dir->dta.ff_attrib;
/* now print the attributes */
attr[0] = '\0';
if (entry.attrib.R == 1) strcat(attr,"R");
if (entry.attrib.H == 1) strcat(attr,"H");
if (entry.attrib.S == 1) strcat(attr,"S");
if (entry.attrib.D == 1) strcat(attr,"D");
if (entry.attrib.A == 1) strcat(attr,"A");
printf(" %s",attr);
nfiles++;
nbrfiles++;
/* Now verify the file by opening it and reading it. */
if((handle = open(dir->dta.ff_name, O_RDONLY | O_BINARY)) < 0)
{
/* error on open */
perror("");
nerrs++;
}
else
{
total = 0;
while((amount = read(handle, buffer, BUFFER_SIZE)) > 0)
total += amount;
if(amount < 0)
{
perror("");
nerrs++;
}
if(total != dir->dta.ff_fsize)
{
printf(BAD_FILE_SIZE);
nerrs++;
}
grand_total += total;
dir_total += total;
close(handle);
}
/* Now get the next directory entry */
retn = findnext(&(dir->dta));
} /* end: if file is not a subdirectory... */
else if(strcmp(dir->dta.ff_name,".") != 0 &&
strcmp(dir->dta.ff_name,"..") != 0 &&
(dir->dta.ff_attrib & subdirs))
/* file IS a proper subdirectory */
{
/* Change directory to go to the new subdirectory */
if(chdir(dir->dta.ff_name) < 0)
{
perror(FILECHK);
exit(1);
}
/* Allocate a stack node. */
if((dir->next = (struct STACK_NODE *)
calloc(1, sizeof(struct STACK_NODE))) == NULL)
{
printf(NOT_ENUFF_SPACE);
exit(1);
}
/* push it on the stack */
dir->next->previous = dir;
dir = dir->next;
/* Get current working directory. */
if(getcwd(dir->path, PATH_SIZE) == NULL)
{
printf("\n");
perror(FILECHK);
exit(1);
}
/* print path */
printf("\n\nSUBDIRECTORY: %s",dir->path);
/* print file listing header */
printf(HEADER);
/* count directories */
ndirs++;
/* Get the first file. */
dir->attribs = files;
flag = files;
retn = findfirst("*.*", &(dir->dta), dir->attribs);
} /* end: if file IS a proper subdirectory */
else
/* not "." or ".." - not a proper subdirectory */
/* get next */
retn = findnext(&(dir->dta));
} /* end: else - not at end of current subdirectory */
} /* end: while(TRUE) */
} /* end: main */