home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / DATABASE / HEADFIX.ZIP / HEADFIX.C next >
Text File  |  1990-01-26  |  7KB  |  237 lines

  1. /*  HEADFIX.C  by Erik A McBeth
  2.     Program will replace the bad header of a dBASE II/III/IV file with
  3.     a clean one from another file.
  4.     1989.12.12
  5.  
  6.     History:
  7.       1989.10.23  Version 1.2.3 of HEADFIX released on SAS
  8.       1989.10.31  Version 1.2.4 has the following changes:
  9.                     Allows good file to be read-only
  10.                     File size of bad file is calculated through ANSI
  11.                       stdio.h functions fgetpos()/fseek()
  12.                     Does fcloseall() on error condition
  13.                     Smaller EXE file
  14.       1989.11.10  Added prototypes and casting for portablity in
  15.                   v 1.2.4
  16.       1989.11.16  Changed dBASE II header length to 521
  17.       1989.11.17  v 1.2.4a released
  18.  
  19.       1989.11.18  Changed return value check for fwrite and
  20.                   fread to check for the actual number of bytes
  21.                   written
  22.       1989.11.19  Got rid of pow256 function, replaced with constants
  23.                   changed fsize again to use ftell/fseek for unix
  24.                   portability, changed fcloseall() for portability
  25.       1989.12.12  Changed fsize again for speed, fseek might be slow
  26.                   on some machines or file sizes (speculating).  Also
  27.                   made it so that the default extension to input
  28.                   files is ".DBF"
  29.       1989.12.18  Added to the default extension routine to take into
  30.                   consideration those cases when we have
  31.                   ..\directory\filename
  32. */
  33.  
  34. #include "stdio.h"
  35. #include "stdlib.h"
  36. #include "string.h"
  37.  
  38. #define NO_FSTAT 0    /* Set true if no fstat() in library */
  39. #define VERSION "126"
  40. #define NAMELEN  128
  41.  
  42. #if !NO_FSTAT
  43. #include "sys\types.h"
  44. #include "sys\stat.h"
  45. #endif
  46.  
  47. int hferror(char *msg,char *filename,int warning);
  48. fsize(FILE *fp,long *filelen);
  49.  
  50. static FILE *bfp,*gfp;
  51.  
  52. main(argc,argv)
  53. int argc;
  54. char *argv[];
  55. {
  56.  
  57.      unsigned char buffer[32],*header;
  58.      char badfile[NAMELEN+1],goodfile[NAMELEN+1];
  59.      unsigned int headlen,reclen;
  60.      int dbase2=0;
  61.      long numrec=0,filelen,estnum=0;
  62.  
  63.      fprintf(stderr,"HEADFIX  Erik A McBeth  v%s  %s\n"\
  64.           "-- Repairs damaged dBASE II/III/IV file headers\n"
  65.           ,VERSION,__DATE__);
  66.  
  67.      if (argc < 4)
  68.        hferror("Usage:  HEADFIX  Bad File  Good File  # of Records | ?","",0);
  69.  
  70.      strcpy(badfile,argv[1]);
  71.      if (!strrchr(badfile,'.') ||
  72.          strrchr(badfile,'.')<strrchr(badfile,'\\'))
  73.        strcat(badfile,".DBF");
  74. /* Open bad file */
  75.      if (!(bfp=fopen(badfile,"r+b")))
  76.        hferror("Unable to open -> ",badfile,0);
  77.  
  78.      strcpy(goodfile,argv[2]);
  79.      if (!strrchr(goodfile,'.') ||
  80.         strrchr(goodfile,'.')<strrchr(goodfile,'\\'))
  81.        strcat(goodfile,".DBF");
  82. /* Open good file */
  83.      if (!(gfp=fopen(goodfile,"rb")))
  84.        hferror("Unable to open -> ",goodfile,0);
  85.  
  86.      if (fsize(bfp,&filelen))
  87.        hferror("Unable to find file info on -> ",badfile,0);
  88.  
  89.      printf("\tReading clean header ....\n");
  90.  
  91. /* Read the first 16 chars in the good header so we can determine
  92.    the length of the entire header */
  93.      if (fread(buffer,sizeof(char),16,gfp)<16)
  94.        hferror("Unable to read header length from -> ",goodfile,0);
  95.  
  96.      dbase2     = buffer[0] == 2;   /* Have a dBASE II file ? */
  97.      if (!dbase2) {
  98.         headlen = buffer[8]+buffer[9]*256;    /* Size of good header */
  99.         reclen  = buffer[10]+buffer[11]*256;  /* Record length */
  100.         }
  101.      else {
  102.         headlen = 521;           /* The value for dBASE II headers */
  103.         reclen  = buffer[6]+buffer[7]*256;
  104.         }
  105.  
  106.  
  107.      if (!(header=(unsigned char *)calloc(headlen,sizeof(char))))
  108.        hferror("Unable to allocate memory for header record","",0);
  109.  
  110.      if (fseek(gfp,0,SEEK_SET))
  111.        hferror("Unable to seek BOF of -> ",goodfile,0);
  112.  
  113.      if (fread(header,sizeof(char),headlen,gfp)<headlen)
  114.        hferror("Unable to read header from -> ",goodfile,0);
  115.  
  116.      printf("\tSetting record count ....\n");
  117.  
  118. /* Estimate the number of records in the bad file */
  119.      estnum = (filelen - (long) headlen) / (long) reclen;
  120.  
  121.      if (argv[3][0] == '?')   /* Use the computer's estimate of records */
  122.        numrec=estnum;
  123.      else
  124.        numrec=atol(argv[3]);  /* Or ours */
  125.  
  126. /* This next block of code breaks apart our record count into 4 bytes
  127.    with the low byte first, if we have a dBASE II database then we
  128.    only break it into 2 bytes */
  129.      if (dbase2) {
  130.        header[1]=(unsigned char)(numrec % 256L);
  131.        header[2]=(unsigned char)(numrec / 256L);
  132.            }
  133.      else {
  134.        header[4]=(unsigned char)((((numrec % 16777216L) %
  135.                                                 65536L) %
  136.                                                   256L));
  137.        header[5]=(unsigned char)((((numrec % 16777216L) %
  138.                                                 65536L) /
  139.                                                   256L));
  140.        header[6]=(unsigned char)(((numrec % 16777216L) /
  141.                                                 65536L));
  142.        header[7]=(unsigned char)(numrec / 16777216L);
  143.       }
  144.  
  145. /* Warn the user so he doesn't screw up, setting the record count too
  146.    low could be a disaster if he does a PACK */
  147.      if (numrec < estnum)
  148.           hferror("WARNING - Number of records may be set too low","",1);
  149.  
  150.      if (numrec > estnum)
  151.           hferror("WARNING - Number of records may be set too high","",1);
  152.  
  153.  
  154.      printf("\tWriting clean header .... \n");
  155.  
  156.      if (fwrite(header,sizeof(char),headlen,bfp)<headlen)
  157.        hferror("Unable to write header to -> ",badfile,0);
  158.  
  159. /* Print out some stats on the repaired file */
  160.      printf("\n");
  161.      printf("\tFixed file name: %s\n",badfile);
  162.      printf("\t           type: %s\n",dbase2 ? "dBASE II":"dBASE III/IV");
  163.      printf("\t           size: %ld\n",filelen);
  164.      printf("\t    header size: %u\n",headlen);
  165.      printf("\t    record size: %u\n",reclen);
  166.      printf("\t   # of records: %lu\n",numrec);
  167.      printf("\t       estimate: %lu\n",estnum);
  168. /* We print the following warning message because dBASE II writes out
  169.    files in 512 byte increments, meaning that it will round up the file
  170.    size to the next multiple of 512, this would of course throw off our
  171.    estimate of the number of actual records */
  172.      if (dbase2 && !(filelen % 512))
  173.         hferror("WARNING - Estimate of dBASE II records may be set too high","",1);
  174.  
  175.      free(header);
  176.      fcloseall();
  177.  
  178.      return 0;
  179. }
  180.  
  181. hferror(msg,file,warning)
  182. char *msg;
  183. char *file;
  184. int warning;
  185. {
  186.       int i;
  187.  
  188.       i=fprintf(stderr,"%s%s\n",msg,file);
  189.       if (!warning) {
  190.          fcloseall();
  191.          exit(2);
  192.         }
  193.       return i;
  194. }
  195.  
  196. fsize(fp,filelen)
  197. FILE *fp;
  198. long *filelen;
  199. {
  200. #if NO_FSTAT
  201.  
  202.     long cur_pos;
  203.  
  204.     if ((cur_pos=ftell(fp)) < 0)   /* Get the current position */
  205.        return -1;
  206.  
  207.     if (fseek(fp,0,SEEK_END))  /* Go to the end of file */
  208.        return -1;
  209.  
  210.     if ((*filelen=ftell(fp)) < 0)  /* Get the EOF position */
  211.        return -1;
  212.  
  213.     return fseek(fp,cur_pos,SEEK_SET); /* Go back to our original position*/
  214.  
  215. #else
  216.  
  217.     struct stat info;
  218.  
  219.     if (fstat(fileno(fp),&info))
  220.        return -1;
  221.  
  222.     *filelen=info.st_size;
  223.  
  224.     return 0;
  225.  
  226. #endif
  227.  
  228. }
  229.  
  230.  
  231. fcloseall()
  232. {
  233.      fclose(bfp);
  234.      fclose(gfp);
  235.      return 0;
  236. }
  237.