home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / dskutl / rewrite.arc / REWRITE.C next >
C/C++ Source or Header  |  1989-10-12  |  6KB  |  229 lines

  1. /*
  2.  
  3. REWRITE.C, a program to make 360K floppies written to in a 1.2M drive
  4. readable in all machines by reading and rewriting each sector, with
  5. optional formatting.
  6.  
  7. Copyright (c), Steven Fischkoff, M.D., 1989.
  8. Last modification 10/11/89
  9.  
  10. Compile with huge model. Lesser may be fine, not tested.
  11.  
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <dos.h>
  16. #include <ctype.h>
  17. #include <stdlib.h>
  18. #include <bios.h>
  19.  
  20. char cpywrt_msg [] = 
  21.     "\nREWRITE, Copyright (c), Steven Fischkoff, M.D., 1989.\n";
  22.  
  23. extern int errno;
  24.  
  25. struct track_addr_field {
  26.     unsigned char track;
  27.     unsigned char head;
  28.     unsigned char sector;
  29.     unsigned char size;
  30.     };
  31.  
  32. int break_status, abort_flag;
  33. char tbl_buffer [11];
  34. struct track_addr_field taf_table [9];
  35. unsigned int seg_es, off_bx;
  36.  
  37. union REGS regs;
  38. struct SREGS segs;
  39.  
  40. int verify (int drive, int track, int side);
  41. void error_exit (int errno);
  42.  
  43.  
  44. int c_break (void)    /* Control-break handler */
  45.     {
  46.     abort_flag = 1;
  47.     return (1);
  48.     }; /* end of c_break */
  49.  
  50.  
  51. #pragma warn -par
  52. int handler (int errval, int ax, int bp, int si)
  53.     {                /* hardware error handler */
  54.     bdosptr (0x09, "Error accessing disk.$", 0);
  55.     return (2);            /* abort program */
  56.     }; /* end of handler */
  57. #pragma warn .par
  58.  
  59.  
  60. void format (int drive, int track)
  61.     {int i, count = 0;        /* since this must only work on a PC or XT,
  62.                     we can avoid many sticky issues
  63.                     like selecting disk parameter tables
  64.                     and the code is much simpler */
  65.  
  66.     for (i=0; i<9; i++) {        /* set up track address table */
  67.         taf_table [i].track = (char) track;
  68.         taf_table [i].head = 0;
  69.         taf_table [i].sector = (char) (i+1);
  70.         taf_table [i].size = 2;
  71.     };
  72.  
  73.     do {
  74.         if (count++ == 3) error_exit (1);    /* try as many as 3 times */
  75.         regs.h.ah = 5;                /* to make sure motor is up */
  76.         regs.h.ch = track;            /* to speed */
  77.         regs.h.dl = drive;
  78.         regs.h.dh = 0;
  79.         regs.h.al = 9;
  80.         regs.x.bx = off_bx;
  81.         segs.es = seg_es;
  82.         int86x (0x13, ®s, ®s, &segs);
  83.     } while (regs.x.cflag || verify (drive, track, 0));
  84.  
  85.     count = 0;
  86.     for (i=0; i<9; i++) {    /* must format other side of track */
  87.         taf_table [i].track = (char) track;
  88.         taf_table [i].head = 1;
  89.         taf_table [i].sector = (char) (i+1);
  90.         taf_table [i].size = 2;
  91.     };
  92.  
  93.     do {
  94.         if (count++ == 3) error_exit (1);
  95.         regs.h.ah = 5;
  96.         regs.h.ch = track;
  97.         regs.h.dl = drive;
  98.         regs.h.dh = 1;
  99.         regs.h.al = 9;
  100.         regs.x.bx = off_bx;
  101.         segs.es = seg_es;
  102.         int86x (0x13, ®s, ®s, &segs);
  103.     } while (regs.x.cflag || verify (drive, track, 1));
  104.     return;
  105.     }; /* end of format */
  106.  
  107.  
  108. int verify (int drive, int track, int side)
  109.     {                /* verify correct formatting */
  110.  
  111.     regs.h.ah = 4;
  112.     regs.h.al = 9;
  113.     regs.h.ch = track;
  114.     regs.h.cl = 1;
  115.     regs.h.dh = side;
  116.     regs.h.dl = drive;
  117.     int86 (0x13, ®s, ®s);
  118.     return (regs.x.cflag);
  119.  
  120.     }; /* end of verify */
  121.  
  122.  
  123. void error_exit (int errno) {
  124.  
  125.     char blanks [] = "                ";
  126.     errno &= 0xFF;        /* We want only the low byte */
  127.     switch (errno) {
  128.         case 0: printf ("Disk write protected. Aborting.%s\n\n", blanks); break;
  129.         case 1: printf ("Unable to format disk. Aborting.%s\n\n", blanks); break;
  130.             /* case 1 doesn't really belong here - just taking advantage of a hole */
  131.         case 2: printf ("Drive not ready. Aborting.%s\n\n", blanks); break;
  132.         case 4:
  133.         case 8: printf ("Error reading drive. Aborting.%s\n\n", blanks); break;
  134.         case 12: printf ("Cannot read drive. Aborting.%s\n\n", blanks); break;
  135.     };
  136.     exit (5);
  137.     }; /* end of error_exit */
  138.  
  139.  
  140. void main (int argc, char **argv)
  141.  
  142.     {int drive, i, j, reformat = 0;
  143.     char *buffer;
  144.     struct fatinfo drive_table;
  145.  
  146.     printf ("%s", cpywrt_msg);
  147.     if (argc < 2) {
  148.         printf ("No drive specified.\n");
  149.         printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
  150.         exit (1);
  151.     };
  152.     
  153.     drive = _toupper (argv [1][0]) - 'A';
  154.     if ((drive!=1 && drive!=0) || argv [1][1]!=':') {
  155.         printf ("Error in drive specification.\n");
  156.         printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
  157.         exit (2);
  158.     };
  159.  
  160.     if (argc == 3) {
  161.         if ((argv[2][0] == '/' || argv[2][0] == '-') &&
  162.             (toupper (argv[2][1]) == 'F')) reformat = 1;
  163.             else {
  164.                 printf ("Improper command line switch.\n");
  165.                 printf ("REWRITE A: (or B:) [/F or /f (optional)]\n\n");
  166.                 exit (2);
  167.             };
  168.     };
  169.  
  170.     regs.h.ah = 0x33;    /* save break status for later */
  171.     regs.h.al = 0;
  172.     intdos (®s, ®s);
  173.     break_status = regs.h.dl;
  174.  
  175.     ctrlbrk (c_break);    /* set up control-break (c) handler */
  176.     harderr (handler);    /* hardware error handler set up */
  177.  
  178.     getfat ((char) (drive + 1), &drive_table);    /* is diskette type appropriate? */
  179.     if (drive_table.fi_fatid != 0xFD) {
  180.         printf ("Disk not formatted to 360K.\n\n");
  181.         exit (3);
  182.     };
  183.     buffer = malloc (18 * drive_table.fi_bysec);    /* 18 represents 1 track */
  184.     if (buffer == NULL) {
  185.         printf ("Insufficient memory to proceed.\n\n");
  186.         exit (4);
  187.     };
  188.  
  189.     seg_es = FP_SEG (taf_table);    /* address of track address table */
  190.     off_bx = FP_OFF (taf_table);
  191.     abort_flag = 0;
  192.  
  193.     regs.h.ah = 0x33;    /* turn on break flag */
  194.     regs.h.al = 1;
  195.     regs.h.dl = 1;
  196.     intdos (®s, ®s);
  197.  
  198.     for (i=j=0; i<720; i+=18,j++) {    /* 720 sectors per disk */
  199.         if (abort_flag) break;    /* safe place to abort on control-break */
  200.         printf ("Reading sectors   %d-%d.      \r", i,i+17);
  201.         if (absread (drive, 18, i, buffer)) {    /* read a track at a time to reduce overhead
  202.                             for head motion */
  203.             error_exit (errno);
  204.         };
  205.  
  206.         if (reformat) {
  207.             printf ("Reading sectors   %d-%d.   Formatting track %d.\r", i,i+17,j);
  208.             format (drive, j);
  209.         };
  210.  
  211.         printf ("Rewriting sectors %d-%d.                        \r", i,i+17);
  212.  
  213.         if (abswrite (drive, 18, i, buffer)) {
  214.             error_exit (errno);
  215.         };
  216.  
  217.     };
  218.     free (buffer);
  219.  
  220.     regs.h.ah = 0x33;    /* return break flag to original status */
  221.     regs.h.al = 1;
  222.     regs.h.dl = break_status;
  223.     intdos (®s, ®s);
  224.  
  225.     if (!abort_flag) printf ("Operation completed successfully.\n\n");
  226.         else printf ("Program aborted at user request.\n\n");
  227.  
  228.     exit (0);
  229.     }; /* end of main */