home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 August / PCWorld_1999-08_cd.bin / dosutils / fips15c / source / fipsspec.cpp < prev    next >
C/C++ Source or Header  |  1998-02-04  |  10KB  |  374 lines

  1. /*
  2.     FIPS - the First nondestructive Interactive Partition Splitting program
  3.  
  4.     Module fipsspec.cpp
  5.  
  6.     RCS - Header:
  7.     $Header: c:/daten/fips/source/main/RCS/fipsspec.cpp 1.4 1995/01/19 00:00:53 schaefer Exp schaefer $
  8.  
  9.     Copyright (C) 1993 Arno Schaefer
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.  
  26.     Report problems and direct all questions to:
  27.  
  28.     schaefer@rbg.informatik.th-darmstadt.de
  29. */
  30.  
  31. #include <dos.h>
  32.  
  33. #include "fipsspec.h"
  34. #include "global.h"
  35. #include "input.h"
  36.  
  37. #define FIRST_CHECK false
  38. #define FINAL_CHECK true
  39.  
  40. #define DISK_INT 0x13
  41.  
  42. #define RESET_DISK 0
  43. #define GET_DRIVE_PARAMS 8
  44.  
  45. void fips_bpb::print (void)
  46. {
  47.     printx ("Bytes per sector: %u\n",bytes_per_sector);
  48.     printx ("Sectors per cluster: %u\n",sectors_per_cluster);
  49.     printx ("Reserved sectors: %u\n",reserved_sectors);
  50.     printx ("Number of FATs: %u\n",no_of_fats);
  51.     printx ("Number of rootdirectory entries: %u\n",no_of_rootdir_entries);
  52.     printx ("Number of sectors (short): %u\n",no_of_sectors);
  53.     printx ("Media descriptor byte: %02Xh\n",media_descriptor);
  54.     printx ("Sectors per FAT: %u\n",sectors_per_fat);
  55.     printx ("Sectors per track: %u\n",sectors_per_track);
  56.     printx ("Drive heads: %u\n",drive_heads);
  57.     printx ("Hidden sectors: %lu\n",hidden_sectors);
  58.     printx ("Number of sectors (long): %lu\n",no_of_sectors_long);
  59.     printx ("Physical drive number: %02Xh\n",phys_drive_no);
  60.     printx ("Signature: %02Xh\n\n",signature);
  61. }
  62.  
  63. void fips_partition_table::print (void)
  64. {
  65.     printx ("     |        |     Start      |      |      End       | Start  |Number of|\n");
  66.     printx ("Part.|bootable|Head Cyl. Sector|System|Head Cyl. Sector| Sector |Sectors  |  MB\n");
  67.     printx ("-----+--------+----------------+------+----------------+--------+---------+----\n");
  68.     for (int i=0;i<4;i++)
  69.     {
  70.         printx ("%u    |    %s |%4u %4u   %4u|   %02Xh|%4u %4u   %4u|%8lu| %8lu|%4lu\n",i+1,
  71.         partition_info[i].bootable ? "yes" : " no",
  72.         partition_info[i].start_head,partition_info[i].start_cylinder,partition_info[i].start_sector,
  73.         partition_info[i].system,partition_info[i].end_head,partition_info[i].end_cylinder,partition_info[i].end_sector,
  74.         partition_info[i].start_sector_abs,partition_info[i].no_of_sectors_abs,partition_info[i].no_of_sectors_abs / 2048);
  75.     }
  76. }
  77.  
  78. void fips_harddrive::get_geometry (void)
  79. {
  80.     union REGS regs;
  81.  
  82.     regs.h.ah = GET_DRIVE_PARAMS;
  83.     regs.h.dl = number;
  84.     int86 (DISK_INT,®s,®s);
  85.     if (global.debug_mode)
  86.     {
  87.         fprintf (global.debugfile,"\nRegisters after call to int 13h 08h (drive %02Xh):\n\n",number);
  88.         fprintf (global.debugfile,"   00       sc/cl    hd\n");
  89.         fprintf (global.debugfile,"al ah bl bh cl ch dl dh   si    di    cflgs flags\n");
  90.         hexwrite ((byte *) ®s,16,global.debugfile);
  91.     }
  92.     if ((errorcode = regs.h.ah) != 0) return;
  93.     geometry.heads = (dword) regs.h.dh + 1;
  94.     geometry.sectors = (dword) regs.h.cl & 0x3f;
  95.     geometry.cylinders = ((dword) regs.h.ch | (((dword) regs.h.cl << 2) & 0x300)) + 1;
  96.  
  97.     if (global.debug_mode)
  98.     {
  99.         fprintf (global.debugfile, "\nGeometry reported by BIOS:\n");
  100.         fprintf
  101.         (
  102.             global.debugfile,
  103.             "%ld cylinders, %ld heads, %ld sectors\n",
  104.             geometry.cylinders,
  105.             geometry.heads,
  106.             geometry.sectors
  107.         );
  108.     }
  109. }
  110.  
  111. void fips_harddrive::reset (void)
  112. {
  113.     union REGS regs;
  114.  
  115.     regs.h.ah = RESET_DISK;
  116.     regs.h.dl = number;
  117.     int86 (DISK_INT,®s,®s);
  118.     if (global.debug_mode)
  119.     {
  120.         fprintf (global.debugfile,"\nRegisters after call to int 13h 00h (drive %02Xh):\n\n",number);
  121.         fprintf (global.debugfile,"al ah bl bh cl ch dl dh   si    di    cflgs flags\n");
  122.         hexwrite ((byte *) ®s,16,global.debugfile);
  123.     }
  124.     errorcode = regs.h.ah;
  125. }
  126.  
  127. void fips_logdrive_info::put_debug_info (void)
  128. {
  129.     fprintf (global.debugfile,"Calculated Partition Characteristica:\n\n");
  130.     fprintf (global.debugfile,"Start of FAT 1: %lu\n",start_fat1);
  131.     fprintf (global.debugfile,"Start of FAT 2: %lu\n",start_fat2);
  132.     fprintf (global.debugfile,"Start of Rootdirectory: %lu\n",start_rootdir);
  133.     fprintf (global.debugfile,"Start of Data: %lu\n",start_data);
  134.     fprintf (global.debugfile,"Number of Clusters: %lu\n",no_of_clusters);
  135. }
  136.  
  137. dword fips_partition::min_cylinder (fat16 fat, drive_geometry geometry)
  138. {
  139.     dword new_part_min_sector =
  140.         info().start_data
  141.         + (dword) 4085
  142.         * bpb().sectors_per_cluster;
  143.  
  144.     dword new_part_min_cylinder =
  145.         (
  146.             new_part_min_sector
  147.             + partition_info->start_sector_abs
  148.             - 1
  149.         )
  150.         / (geometry.heads * geometry.sectors)
  151.         + 1;
  152.  
  153.     if (new_part_min_cylinder > partition_info->end_cylinder)
  154.         error ("Partition too small - can't split");
  155.  
  156.     dword min_free_cluster = fat.min_free_cluster ();
  157.     dword min_free_sector =
  158.         info().start_data
  159.         + (min_free_cluster - 2)
  160.         * (dword) bpb().sectors_per_cluster;
  161.  
  162.     dword min_free_cylinder =
  163.         (
  164.             min_free_sector
  165.             + partition_info->start_sector_abs
  166.             - 1
  167.         )
  168.         / (geometry.heads * geometry.sectors)
  169.         + 1;
  170.  
  171.     if (min_free_cylinder > partition_info->end_cylinder)
  172.         error ("Last cylinder is not free");
  173.  
  174.     if (new_part_min_cylinder < min_free_cylinder)
  175.         new_part_min_cylinder = min_free_cylinder;
  176.  
  177.     return (new_part_min_cylinder);
  178. }
  179.  
  180.  
  181. dword fips_partition::min_cylinder (fat32 fat, drive_geometry geometry)
  182. {
  183.     dword new_part_min_sector = info().start_data;
  184.  
  185.     dword new_part_min_cylinder =
  186.         (
  187.             new_part_min_sector
  188.             + partition_info->start_sector_abs
  189.             - 1
  190.         )
  191.         / (geometry.heads * geometry.sectors)
  192.         + 1;
  193.  
  194.     if (new_part_min_cylinder > partition_info->end_cylinder)
  195.         error ("Partition too small - can't split");
  196.  
  197.     dword min_free_cluster = fat.min_free_cluster ();
  198.     dword min_free_sector =
  199.         info().start_data
  200.         + (min_free_cluster - 2)
  201.         * (dword) bpb().sectors_per_cluster;
  202.  
  203.     dword min_free_cylinder =
  204.         (
  205.             min_free_sector
  206.             + partition_info->start_sector_abs
  207.             - 1
  208.         )
  209.         / (geometry.heads * geometry.sectors)
  210.         + 1;
  211.  
  212.     if (min_free_cylinder > partition_info->end_cylinder)
  213.         error ("Last cylinder is not free");
  214.  
  215.     if (new_part_min_cylinder < min_free_cylinder)
  216.         new_part_min_cylinder = min_free_cylinder;
  217.  
  218.     return (new_part_min_cylinder);
  219. }
  220.  
  221.  
  222. boolean fips_partition::split (fips_harddrive hd)
  223. {
  224.     if (read_boot_sector ())
  225.         error ("Error reading boot sector");
  226.  
  227.     if (global.debug_mode)
  228.     {
  229.         fprintf
  230.         (
  231.             global.debugfile,
  232.             "\nBoot sector drive %02Xh, partition %u:\n\n",
  233.             hd.number,
  234.             number + 1
  235.         );
  236.  
  237.         hexwrite
  238.         (
  239.             boot_sector->data,
  240.             512,
  241.             global.debugfile
  242.         );
  243.     }
  244.  
  245.     get_bpb ();
  246.  
  247.     if (bpb().sectors_per_fat16 == 0)
  248.         if (read_fsinfo_sector ())
  249.             error ("Error reading FAT32 fsinfo sector");
  250.  
  251.     printx ("\nBoot sector:\n\n");
  252.     print_bpb ();
  253.  
  254.     get_info ();
  255.     if (global.debug_mode)
  256.         write_info_debugfile ();
  257.  
  258.     check ();
  259.  
  260.     dword new_start_cylinder;
  261.     if (bpb().sectors_per_fat16 != 0) {
  262.         fat16 fat1 (this,1);
  263.         fat16 fat2 (this,2);
  264.  
  265.         fat1.check_against (&fat2);
  266.  
  267.         dword new_part_min_cylinder =
  268.             min_cylinder (fat2, hd.geometry);
  269.  
  270.         if (ask_if_save()) save_root_and_boot(&hd,this);
  271.  
  272.         new_start_cylinder =
  273.             ask_for_new_start_cylinder(
  274.                 partition_info->start_cylinder,
  275.                 new_part_min_cylinder,
  276.                 partition_info->end_cylinder,
  277.                 hd.geometry.heads * hd.geometry.sectors
  278.                 );
  279.  
  280.         fat2.check_empty(new_start_cylinder
  281.                  * hd.geometry.heads
  282.                  * hd.geometry.sectors
  283.                  - partition_info->start_sector_abs
  284.             );
  285.     } else {
  286.         fat32 fat1 (this,1);
  287.         fat32 fat2 (this,2);
  288.  
  289.         fat1.check_against (&fat2);
  290.  
  291.         dword new_part_min_cylinder =
  292.             min_cylinder (fat2, hd.geometry);
  293.  
  294.         if (ask_if_save()) save_root_and_boot(&hd,this);
  295.  
  296.         new_start_cylinder =
  297.             ask_for_new_start_cylinder(
  298.                 partition_info->start_cylinder,
  299.                 new_part_min_cylinder,
  300.                 partition_info->end_cylinder,
  301.                 hd.geometry.heads * hd.geometry.sectors
  302.                 );
  303.  
  304.         fat2.check_empty(new_start_cylinder
  305.                  * hd.geometry.heads
  306.                  * hd.geometry.sectors
  307.                  - partition_info->start_sector_abs
  308.             );
  309.  
  310.     }
  311.     hd.calculate_new_root (new_start_cylinder, this);
  312.  
  313.     hd.put_partition_table();
  314.     hd.get_partition_table();
  315.  
  316.     printx ("\nNew partition table:\n\n");
  317.     hd.print_partition_table ();
  318.  
  319.     hd.check (FINAL_CHECK);
  320.  
  321.     if (ask_if_continue () == false)
  322.     {
  323.         return (false);
  324.     }
  325.  
  326.     calculate_new_boot ();
  327.     if (bpb().sectors_per_fat16 == 0)
  328.     {
  329.         dword clusters = info().no_of_clusters;
  330.         fsinfo_sector->data[0x1e8] = clusters & 0xffL;
  331.         fsinfo_sector->data[0x1e9] = (clusters & 0xff00L) >> 8;
  332.         fsinfo_sector->data[0x1ea] = (clusters & 0xff0000L) >> 16;
  333.         fsinfo_sector->data[0x1eb] = (clusters & 0xff000000L) >> 24;
  334.         fsinfo_sector->data[0x1ec] = 0xff;
  335.         fsinfo_sector->data[0x1ed] = 0xff;
  336.         fsinfo_sector->data[0x1ee] = 0xff;
  337.         fsinfo_sector->data[0x1ef] = 0xff;
  338.     }
  339.  
  340.     put_bpb ();
  341.     get_bpb ();
  342.  
  343.     printx ("\nNew boot sector:\n\n");
  344.     print_bpb ();
  345.  
  346.     get_info ();
  347.     if (global.debug_mode)
  348.         write_info_debugfile ();
  349.  
  350.     check();
  351.  
  352.     if (!global.test_mode)
  353.     {
  354.         ask_for_write_permission ();
  355.  
  356.         if (hd.write_root_sector ())
  357.             error ("Error writing root sector");
  358.  
  359.         if (write_boot_sector ())
  360.             error ("Error writing boot sector");
  361.  
  362.         if (bpb().sectors_per_fat16 == 0)
  363.             if (write_fsinfo_sector ())
  364.                 error ("Error writing FAT32 fsinfo sector");
  365.  
  366.         printx ("Repartitioning complete\n");
  367.  
  368.         if (bpb().sectors_per_fat16 == 0)
  369.             printx ("With FAT32 partitions, you should now run scandisk on the shortened partition.\n");
  370.     }
  371.  
  372.     return (true);
  373. }
  374.