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 >
Text File  |  1990-01-26  |  7KB  |  223 lines

  1. /*  HEADXTRK.C  by Erik A McBeth
  2.     Program will extract and create a new header from a corrupt
  3.     dBASE II/III/IV header file
  4.     1989.12.12
  5.  
  6.      History
  7.              1989.10.26  Most part completed
  8.              1989.11.10  Increased portability through prototypes
  9.                          and casts
  10.              1989.11.13  Changed method of reading and writing fields
  11.                          for future expansion of dBASE format.
  12.              1989.11.16  Clean up head length for dBASE 2, also End
  13.                          of header marker
  14.              1989.11.17  Released version 1.0.5
  15.  
  16.              1989.11.18  Changed return value check for fwrite and
  17.                          fread to check for the actual number of bytes
  18.                          written
  19.              1989.11.19  Changed fcloseall() for portablity
  20.              1989.12.12  Added code to have the default file
  21.                          extension ".DBF"
  22.  
  23.              1989.12.18  Added to the default extension routine to take
  24.                          into consideration those cases when we have
  25.                          ..\directory\filename
  26. */
  27.  
  28. #include "stdio.h"
  29. #include "stdlib.h"
  30. #include "string.h"
  31.  
  32. #define VERSION "107"
  33. #define NAMELEN  128
  34.  
  35. int hferror(char *msg,char *filename,int warn);
  36. static FILE *bfp,*gfp;
  37.  
  38. main(argc,argv)
  39. int argc;
  40. char *argv[];
  41. {
  42.  
  43.      unsigned char buffer[32],sbuffer[4];
  44.      unsigned int headlen,reclen=1,numflds=0,db2flds=0;
  45.      int dbase2=0,guess=(argc > 4);
  46.      char badfile[NAMELEN+1],goodfile[NAMELEN+1];
  47.  
  48.      fprintf(stderr,"HEADXTRK  Erik A McBeth  v%s  %s\n"\
  49.           "-- Extracts headers from damaged "\
  50.           "dBASE II/III/IV file headers\n",VERSION,__DATE__);
  51.  
  52.      if (argc < 4)
  53.        hferror(
  54.  "Usage:  HEADXTRK Bad File  Output file  Type of dBASE file (2,3,4) [/?] \n"\
  55.  "                 ? = HEADXTRK Guesses fields"
  56.     ,"",0);
  57.  
  58.      strcpy(badfile,argv[1]);
  59.      if (!strrchr(badfile,'.') ||
  60.          strrchr(badfile,'.')<strrchr(badfile,'\\'))
  61.        strcat(badfile,".DBF");
  62. /* Open bad file */
  63.      if (!(bfp=fopen(badfile,"rb")))
  64.        hferror("Unable to open -> ",badfile,0);
  65.  
  66.      strcpy(goodfile,argv[2]);
  67.      if (!strrchr(goodfile,'.') ||
  68.         strrchr(goodfile,'.')<strrchr(goodfile,'\\'))
  69.        strcat(goodfile,".DBF");
  70. /* Create good file */
  71.      if (!(gfp=fopen(goodfile,"wb")))
  72.          hferror("Unable to open -> ",goodfile,0);
  73.  
  74.      dbase2     = (argv[3][0] == '2');   /* Have a dBASE II file ? */
  75.  
  76.      printf("\tReading damaged header ....\n");
  77.  
  78.      if (fseek(bfp,dbase2 ? 8:32,SEEK_SET))
  79.          hferror("Unable to seek field location in -> ",badfile,0);
  80.  
  81.      if (fseek(gfp,dbase2 ? 8:32,SEEK_SET))
  82.          hferror("Unable to seek field location in -> ",goodfile,0);
  83.  
  84.      printf("\tSelecting fields ....\n");
  85.      /* Read in the fields, stopping to ask if the field is valid for
  86.         dBASE III/IV databases, with dBASE II we should read 32 of them */
  87.      while(1) {
  88.        if (dbase2 && numflds==32)
  89.           break;
  90.        if (fread(buffer,sizeof(unsigned char),dbase2 ? 16:32,bfp)<
  91.             (dbase2 ? 16:32))
  92.           break;
  93.        if (!dbase2 && guess && buffer[10]) /* Valid fields have buffer[10]=0 */
  94.          break;
  95.  
  96.        db2flds += (buffer[0] && buffer[0] != 0xd ? 1:0);
  97.                     /* Check for actual dBASE 2 fields */
  98.  
  99.         printf("\t     %3d  %-10s %c %3d %2d\n",
  100.            numflds+1,
  101.            buffer[0] && buffer[0] != 0xd ? (char *)buffer:"(blank)",
  102.            buffer[11],
  103.            buffer[dbase2 ? 12:16],
  104.            buffer[dbase2 ? 15:17]
  105.            );
  106.         if ((dbase2 || guess) && !((numflds+1) % 20)) {
  107.           fprintf(stderr,"Hit RETURN for more fields");
  108.           gets((char *)sbuffer);
  109.           }
  110.  
  111.         if (!dbase2) {
  112.          if (guess)
  113.            sbuffer[0]='Y';
  114.          else {
  115.            printf("\tIs this a field? (Y/n) ");  /* Ask if not dBASE II */
  116.            gets((char *)sbuffer);
  117.           }
  118.          /* Default the answer to yes */
  119.          if ((sbuffer[0]=='N' || sbuffer[0]=='n'))
  120.             break;
  121.           }  /* !dbase2 */
  122.  
  123.        if (fwrite(buffer,sizeof(unsigned char),dbase2 ? 16:32,gfp)<
  124.                    (dbase2 ? 16:32))
  125.           hferror("Unable to write field info to -> ",goodfile,0);
  126.  
  127.        numflds++;
  128.        reclen += buffer[dbase2 ? 12:16]; /* Increase record length */
  129.  
  130.       }
  131.  
  132.  
  133.      /* Check for valid numbers of fields */
  134.      if ((dbase2 && numflds != 32) ||
  135.           (numflds > 128 && argv[3][0]=='3')
  136.           )      /* Check for valid number of fields */ {
  137.         sprintf((char *)buffer,
  138.         "WARNING - Found %d fields, number of fields may be incorrect",numflds);
  139.         hferror((char *)buffer,"",1);
  140.        }
  141.  
  142.      if ((dbase2 && db2flds>=32) || !dbase2)
  143.         sbuffer[0]=(char)0xd;  /* End of header marker */
  144.      else
  145.         sbuffer[0]='\0';
  146.      sbuffer[1]=(char)0x1a; /* End of file marker */
  147.  
  148.      if (fwrite(sbuffer,sizeof(unsigned char),2,gfp)<2)
  149.          hferror("Unable to write EOF marker to -> ",goodfile,0);
  150.  
  151.      /* Calc the header and record length */
  152.      headlen= (dbase2 ? 521:(numflds + 1)* 32 +1);
  153.      /* Set up header intro info */
  154.      memset(buffer,0,sizeof(buffer));
  155.      if (dbase2) {
  156.         buffer[0]=(char)2;               /* Program ID */
  157.         buffer[3]=12;                    /* Month of last update */
  158.         buffer[4]=25;                    /* Day */
  159.         buffer[5]=89;                    /* Year */
  160.         buffer[6]=(char)(reclen % 256);  /* Record length */
  161.         buffer[7]=(char)(reclen / 256);
  162.         }
  163.      else {
  164.         buffer[0]=(char)3;                /* Program ID  */
  165.         buffer[1]=89;                     /* Year of last update*/
  166.         buffer[2]=12;                     /* Month of last update */
  167.         buffer[3]=25;                     /* Day */
  168.         buffer[8]=(char)(headlen % 256);  /* Header length */
  169.         buffer[9]=(char)(headlen / 256);
  170.         buffer[10]=(char)(reclen % 256);  /* Record length */
  171.         buffer[11]=(char)(reclen / 256);
  172.         }
  173.  
  174.      printf("\tWriting new header intro ....\n");
  175.  
  176.      if (fseek(gfp,(long)0,SEEK_SET))
  177.        hferror("Unable to seek BOF in -> ",goodfile,0);
  178.  
  179.      if (fwrite(buffer,sizeof(unsigned char),dbase2 ? 8:32,gfp)<
  180.           (dbase2 ? 8:32))
  181.        hferror("Unable to write header intro to -> ",goodfile,0);
  182.  
  183.  
  184. /* Print out some stats on the new header file */
  185.      printf("\n");
  186.      printf("\tFixed header name: %s\n",goodfile);
  187.      printf("\t             type: %s\n",dbase2 ? "dBASE II":
  188.                  argv[3][0]=='3' ? "dBASE III":"dBASE IV");
  189.      printf("\t      Header size: %u\n",headlen);
  190.      printf("\t     Total fields: %u\n",dbase2 ? db2flds:numflds);
  191.      printf("\t      Record size: %u\n",reclen);
  192.  
  193.      fcloseall();
  194.  
  195.      return 0;
  196. }
  197.  
  198.  
  199. hferror(msg,file,warning)
  200. char *msg;
  201. char *file;
  202. int warning;
  203. {
  204.       int i;
  205.  
  206.       i=fprintf(stderr,"%s%s\n",msg,file);
  207.       if (!warning) {
  208.          fcloseall();
  209.          exit(2);
  210.         }
  211.       return i;
  212. }
  213.  
  214. fcloseall()
  215. {
  216.     fclose(gfp);
  217.     fclose(bfp);
  218.  
  219.     return 0;
  220.  
  221. }
  222.  
  223.