home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
DATABASE
/
HEADFIX.ZIP
/
HEADXTRK.C
< prev
next >
Wrap
Text File
|
1990-01-26
|
7KB
|
223 lines
/* HEADXTRK.C by Erik A McBeth
Program will extract and create a new header from a corrupt
dBASE II/III/IV header file
1989.12.12
History
1989.10.26 Most part completed
1989.11.10 Increased portability through prototypes
and casts
1989.11.13 Changed method of reading and writing fields
for future expansion of dBASE format.
1989.11.16 Clean up head length for dBASE 2, also End
of header marker
1989.11.17 Released version 1.0.5
1989.11.18 Changed return value check for fwrite and
fread to check for the actual number of bytes
written
1989.11.19 Changed fcloseall() for portablity
1989.12.12 Added code to have the default file
extension ".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 VERSION "107"
#define NAMELEN 128
int hferror(char *msg,char *filename,int warn);
static FILE *bfp,*gfp;
main(argc,argv)
int argc;
char *argv[];
{
unsigned char buffer[32],sbuffer[4];
unsigned int headlen,reclen=1,numflds=0,db2flds=0;
int dbase2=0,guess=(argc > 4);
char badfile[NAMELEN+1],goodfile[NAMELEN+1];
fprintf(stderr,"HEADXTRK Erik A McBeth v%s %s\n"\
"-- Extracts headers from damaged "\
"dBASE II/III/IV file headers\n",VERSION,__DATE__);
if (argc < 4)
hferror(
"Usage: HEADXTRK Bad File Output file Type of dBASE file (2,3,4) [/?] \n"\
" ? = HEADXTRK Guesses fields"
,"",0);
strcpy(badfile,argv[1]);
if (!strrchr(badfile,'.') ||
strrchr(badfile,'.')<strrchr(badfile,'\\'))
strcat(badfile,".DBF");
/* Open bad file */
if (!(bfp=fopen(badfile,"rb")))
hferror("Unable to open -> ",badfile,0);
strcpy(goodfile,argv[2]);
if (!strrchr(goodfile,'.') ||
strrchr(goodfile,'.')<strrchr(goodfile,'\\'))
strcat(goodfile,".DBF");
/* Create good file */
if (!(gfp=fopen(goodfile,"wb")))
hferror("Unable to open -> ",goodfile,0);
dbase2 = (argv[3][0] == '2'); /* Have a dBASE II file ? */
printf("\tReading damaged header ....\n");
if (fseek(bfp,dbase2 ? 8:32,SEEK_SET))
hferror("Unable to seek field location in -> ",badfile,0);
if (fseek(gfp,dbase2 ? 8:32,SEEK_SET))
hferror("Unable to seek field location in -> ",goodfile,0);
printf("\tSelecting fields ....\n");
/* Read in the fields, stopping to ask if the field is valid for
dBASE III/IV databases, with dBASE II we should read 32 of them */
while(1) {
if (dbase2 && numflds==32)
break;
if (fread(buffer,sizeof(unsigned char),dbase2 ? 16:32,bfp)<
(dbase2 ? 16:32))
break;
if (!dbase2 && guess && buffer[10]) /* Valid fields have buffer[10]=0 */
break;
db2flds += (buffer[0] && buffer[0] != 0xd ? 1:0);
/* Check for actual dBASE 2 fields */
printf("\t %3d %-10s %c %3d %2d\n",
numflds+1,
buffer[0] && buffer[0] != 0xd ? (char *)buffer:"(blank)",
buffer[11],
buffer[dbase2 ? 12:16],
buffer[dbase2 ? 15:17]
);
if ((dbase2 || guess) && !((numflds+1) % 20)) {
fprintf(stderr,"Hit RETURN for more fields");
gets((char *)sbuffer);
}
if (!dbase2) {
if (guess)
sbuffer[0]='Y';
else {
printf("\tIs this a field? (Y/n) "); /* Ask if not dBASE II */
gets((char *)sbuffer);
}
/* Default the answer to yes */
if ((sbuffer[0]=='N' || sbuffer[0]=='n'))
break;
} /* !dbase2 */
if (fwrite(buffer,sizeof(unsigned char),dbase2 ? 16:32,gfp)<
(dbase2 ? 16:32))
hferror("Unable to write field info to -> ",goodfile,0);
numflds++;
reclen += buffer[dbase2 ? 12:16]; /* Increase record length */
}
/* Check for valid numbers of fields */
if ((dbase2 && numflds != 32) ||
(numflds > 128 && argv[3][0]=='3')
) /* Check for valid number of fields */ {
sprintf((char *)buffer,
"WARNING - Found %d fields, number of fields may be incorrect",numflds);
hferror((char *)buffer,"",1);
}
if ((dbase2 && db2flds>=32) || !dbase2)
sbuffer[0]=(char)0xd; /* End of header marker */
else
sbuffer[0]='\0';
sbuffer[1]=(char)0x1a; /* End of file marker */
if (fwrite(sbuffer,sizeof(unsigned char),2,gfp)<2)
hferror("Unable to write EOF marker to -> ",goodfile,0);
/* Calc the header and record length */
headlen= (dbase2 ? 521:(numflds + 1)* 32 +1);
/* Set up header intro info */
memset(buffer,0,sizeof(buffer));
if (dbase2) {
buffer[0]=(char)2; /* Program ID */
buffer[3]=12; /* Month of last update */
buffer[4]=25; /* Day */
buffer[5]=89; /* Year */
buffer[6]=(char)(reclen % 256); /* Record length */
buffer[7]=(char)(reclen / 256);
}
else {
buffer[0]=(char)3; /* Program ID */
buffer[1]=89; /* Year of last update*/
buffer[2]=12; /* Month of last update */
buffer[3]=25; /* Day */
buffer[8]=(char)(headlen % 256); /* Header length */
buffer[9]=(char)(headlen / 256);
buffer[10]=(char)(reclen % 256); /* Record length */
buffer[11]=(char)(reclen / 256);
}
printf("\tWriting new header intro ....\n");
if (fseek(gfp,(long)0,SEEK_SET))
hferror("Unable to seek BOF in -> ",goodfile,0);
if (fwrite(buffer,sizeof(unsigned char),dbase2 ? 8:32,gfp)<
(dbase2 ? 8:32))
hferror("Unable to write header intro to -> ",goodfile,0);
/* Print out some stats on the new header file */
printf("\n");
printf("\tFixed header name: %s\n",goodfile);
printf("\t type: %s\n",dbase2 ? "dBASE II":
argv[3][0]=='3' ? "dBASE III":"dBASE IV");
printf("\t Header size: %u\n",headlen);
printf("\t Total fields: %u\n",dbase2 ? db2flds:numflds);
printf("\t Record size: %u\n",reclen);
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;
}
fcloseall()
{
fclose(gfp);
fclose(bfp);
return 0;
}