home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
DATABASE
/
HEADFIX.ZIP
/
HEADFIX.C
next >
Wrap
Text File
|
1990-01-26
|
7KB
|
237 lines
/* HEADFIX.C by Erik A McBeth
Program will replace the bad header of a dBASE II/III/IV file with
a clean one from another file.
1989.12.12
History:
1989.10.23 Version 1.2.3 of HEADFIX released on SAS
1989.10.31 Version 1.2.4 has the following changes:
Allows good file to be read-only
File size of bad file is calculated through ANSI
stdio.h functions fgetpos()/fseek()
Does fcloseall() on error condition
Smaller EXE file
1989.11.10 Added prototypes and casting for portablity in
v 1.2.4
1989.11.16 Changed dBASE II header length to 521
1989.11.17 v 1.2.4a released
1989.11.18 Changed return value check for fwrite and
fread to check for the actual number of bytes
written
1989.11.19 Got rid of pow256 function, replaced with constants
changed fsize again to use ftell/fseek for unix
portability, changed fcloseall() for portability
1989.12.12 Changed fsize again for speed, fseek might be slow
on some machines or file sizes (speculating). Also
made it so that the default extension to input
files is ".DBF"
1989.12.18 Added to the default extension routine to take into
consideration those cases when we have
..\directory\filename
*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define NO_FSTAT 0 /* Set true if no fstat() in library */
#define VERSION "126"
#define NAMELEN 128
#if !NO_FSTAT
#include "sys\types.h"
#include "sys\stat.h"
#endif
int hferror(char *msg,char *filename,int warning);
fsize(FILE *fp,long *filelen);
static FILE *bfp,*gfp;
main(argc,argv)
int argc;
char *argv[];
{
unsigned char buffer[32],*header;
char badfile[NAMELEN+1],goodfile[NAMELEN+1];
unsigned int headlen,reclen;
int dbase2=0;
long numrec=0,filelen,estnum=0;
fprintf(stderr,"HEADFIX Erik A McBeth v%s %s\n"\
"-- Repairs damaged dBASE II/III/IV file headers\n"
,VERSION,__DATE__);
if (argc < 4)
hferror("Usage: HEADFIX Bad File Good File # of Records | ?","",0);
strcpy(badfile,argv[1]);
if (!strrchr(badfile,'.') ||
strrchr(badfile,'.')<strrchr(badfile,'\\'))
strcat(badfile,".DBF");
/* Open bad file */
if (!(bfp=fopen(badfile,"r+b")))
hferror("Unable to open -> ",badfile,0);
strcpy(goodfile,argv[2]);
if (!strrchr(goodfile,'.') ||
strrchr(goodfile,'.')<strrchr(goodfile,'\\'))
strcat(goodfile,".DBF");
/* Open good file */
if (!(gfp=fopen(goodfile,"rb")))
hferror("Unable to open -> ",goodfile,0);
if (fsize(bfp,&filelen))
hferror("Unable to find file info on -> ",badfile,0);
printf("\tReading clean header ....\n");
/* Read the first 16 chars in the good header so we can determine
the length of the entire header */
if (fread(buffer,sizeof(char),16,gfp)<16)
hferror("Unable to read header length from -> ",goodfile,0);
dbase2 = buffer[0] == 2; /* Have a dBASE II file ? */
if (!dbase2) {
headlen = buffer[8]+buffer[9]*256; /* Size of good header */
reclen = buffer[10]+buffer[11]*256; /* Record length */
}
else {
headlen = 521; /* The value for dBASE II headers */
reclen = buffer[6]+buffer[7]*256;
}
if (!(header=(unsigned char *)calloc(headlen,sizeof(char))))
hferror("Unable to allocate memory for header record","",0);
if (fseek(gfp,0,SEEK_SET))
hferror("Unable to seek BOF of -> ",goodfile,0);
if (fread(header,sizeof(char),headlen,gfp)<headlen)
hferror("Unable to read header from -> ",goodfile,0);
printf("\tSetting record count ....\n");
/* Estimate the number of records in the bad file */
estnum = (filelen - (long) headlen) / (long) reclen;
if (argv[3][0] == '?') /* Use the computer's estimate of records */
numrec=estnum;
else
numrec=atol(argv[3]); /* Or ours */
/* This next block of code breaks apart our record count into 4 bytes
with the low byte first, if we have a dBASE II database then we
only break it into 2 bytes */
if (dbase2) {
header[1]=(unsigned char)(numrec % 256L);
header[2]=(unsigned char)(numrec / 256L);
}
else {
header[4]=(unsigned char)((((numrec % 16777216L) %
65536L) %
256L));
header[5]=(unsigned char)((((numrec % 16777216L) %
65536L) /
256L));
header[6]=(unsigned char)(((numrec % 16777216L) /
65536L));
header[7]=(unsigned char)(numrec / 16777216L);
}
/* Warn the user so he doesn't screw up, setting the record count too
low could be a disaster if he does a PACK */
if (numrec < estnum)
hferror("WARNING - Number of records may be set too low","",1);
if (numrec > estnum)
hferror("WARNING - Number of records may be set too high","",1);
printf("\tWriting clean header .... \n");
if (fwrite(header,sizeof(char),headlen,bfp)<headlen)
hferror("Unable to write header to -> ",badfile,0);
/* Print out some stats on the repaired file */
printf("\n");
printf("\tFixed file name: %s\n",badfile);
printf("\t type: %s\n",dbase2 ? "dBASE II":"dBASE III/IV");
printf("\t size: %ld\n",filelen);
printf("\t header size: %u\n",headlen);
printf("\t record size: %u\n",reclen);
printf("\t # of records: %lu\n",numrec);
printf("\t estimate: %lu\n",estnum);
/* We print the following warning message because dBASE II writes out
files in 512 byte increments, meaning that it will round up the file
size to the next multiple of 512, this would of course throw off our
estimate of the number of actual records */
if (dbase2 && !(filelen % 512))
hferror("WARNING - Estimate of dBASE II records may be set too high","",1);
free(header);
fcloseall();
return 0;
}
hferror(msg,file,warning)
char *msg;
char *file;
int warning;
{
int i;
i=fprintf(stderr,"%s%s\n",msg,file);
if (!warning) {
fcloseall();
exit(2);
}
return i;
}
fsize(fp,filelen)
FILE *fp;
long *filelen;
{
#if NO_FSTAT
long cur_pos;
if ((cur_pos=ftell(fp)) < 0) /* Get the current position */
return -1;
if (fseek(fp,0,SEEK_END)) /* Go to the end of file */
return -1;
if ((*filelen=ftell(fp)) < 0) /* Get the EOF position */
return -1;
return fseek(fp,cur_pos,SEEK_SET); /* Go back to our original position*/
#else
struct stat info;
if (fstat(fileno(fp),&info))
return -1;
*filelen=info.st_size;
return 0;
#endif
}
fcloseall()
{
fclose(bfp);
fclose(gfp);
return 0;
}