📄 main.c
字号:
/*
// Program: Format
// Version: 0.92
// (0.90b/c/d/e/f - mixed improvements - Eric Auer 2003)
// Written By: Brian E. Reifsnyder
// Copyright: 2003 under the terms of the GNU GPL, Version 2
// Module Name: main.c
// Module Description: Main Module
*/
#define MAIN
#include <dir.h>
#include <stdio.h>
#include <ctype.h> /* (jh) for isalpha, ... */
#include <string.h> /* strncpy */
#include <dos.h>
#include "format.h"
#include "hdisk.h"
#include "init.h"
#include "userint.h"
#include "createfs.h"
#include "uformat.h"
#include "btstrct.h"
#include "savefs.h"
#include "driveio.h"
#include "floppy.h"
#include "getopt.h" /* (jh) support for getopt */
char Check_For_Format(void);
void Write_System_Files(void);
void Initialization(void);
void Unconditional_Format(void);
void Record_Bad_Clusters(void);
void Set_Floppy_Media_Type(void);
void Enable_Disk_Access(void);
/* Check to see if the media is formatted. */
/* Returns TRUE if formatted and FALSE if it is not formatted. */
/* Non-DOS formats count as formats as well! (Eric) */
char Check_For_Format(void)
{
union REGS regs;
regs.h.ah = 0x0d;
intdos(®s,®s); /* flush buffers, reset disk system */
if (param.drive_number < 2) /* floppy? */
{
if (Drive_IO(READ, 0L, 1) == 0) /* try DIRECT sector read first */
{
/* still have to analyze DPB below */
/* *** TODO: analyze current format TYPE found in sector *** */
/* *** (to avoid "quickformat in spite of size change"). *** */
}
else
{
printf(" Boot sector unreadable, disk not yet formatted\n");
return FALSE;
}
} /* end floppy */
regs.h.ah = 0x32;
regs.h.dl = param.drive_number + 1; /* 0 default 1 A: 2 B: ... */
intdosx(®s,®s,&sregs); /* re-read DPB for that drive */
/* this can cause a critical error if boot sector not readable! */
if (regs.h.al == 0)
{
/* could analyze returned DPB - pointer is DS:BX */
return TRUE;
}
else
{
printf(" DPB not available - network drive?\n");
return FALSE; /* this is a network drive or something */
}
}
/* Write System Files */
void Write_System_Files(void)
{
int sys_found = FALSE;
char sys[9] = {'s','y','s',' ','x',':',13,0,0};
/* Check for the sys command. */
if (NULL!=searchpath("sys.com") ) sys_found = TRUE;
if (NULL!=searchpath("sys.exe") ) sys_found = TRUE;
if (sys_found==TRUE)
{
/* Issue the command to write system files. */
sys[4]=param.drive_letter[0];
printf("\nRunning SYS command: %s\n",sys);
system(sys);
}
else
{
printf("\n Error: The SYS command has not been located.\n");
printf( " System files have not be written to the disk.\n");
}
}
/*
/////////////////////////////////////////////////////////////////////////////
// MAIN ROUTINE
/////////////////////////////////////////////////////////////////////////////
*/
void main(int argc, char *argv[])
{
int ch;
int index;
int n;
int found_format_sectors_per_track = 0;
int found_format_heads = 0;
int drive_letter_found = FALSE;
Initialization();
param.n = FALSE;
param.t = FALSE;
param.v = FALSE;
param.q = FALSE;
param.u = FALSE;
param.b = FALSE;
param.s = FALSE;
param.f = FALSE;
param.one = FALSE;
param.four = FALSE;
param.eight = FALSE;
debug_prog = FALSE;
/* if FORMAT is typed without any options */
if (argc == 1)
{
Display_Help_Screen();
exit(1);
}
/* (jh) check command line */
while ( (index = getopt (argc, argv, "V:v:QqUuBbSsYy148F:f:T:t:N:n:/")) != EOF)
{
switch(index)
{
case 'V':
case 'v':
param.v=TRUE;
/* avoid overflow of param.volume_label (12 chars) */
/* need to skip over first character (':') */
strncpy (param.volume_label, optarg+1, 11);
param.volume_label[11] = '\0';
for (n = 0; param.volume_label[n] != '\0'; n++)
{
ch = param.volume_label[n];
param.volume_label[n] = toupper (ch);
}
break;
case 'Q': /* quick - flush metadata only */
case 'q':
param.q =TRUE;
break;
case 'U': /* unconditional - full format */
case 'u':
param.u=TRUE;
break;
case 'B': /* reserve space for system, deprecated */
case 'b':
param.b=TRUE;
break;
case 'S': /* run SYS command */
case 's':
param.s=TRUE;
break;
case 'Y': /* assume yes on questions - undocumented */
case 'y':
param.force_yes=TRUE;
break;
case 'D': /* debug mode, more verbose output */
case 'd':
debug_prog=TRUE;
break;
case '1': /* one side only */
param.one=TRUE;
break;
case '4': /* 360k disk in 1.2M drive */
param.four=TRUE;
break;
case '8': /* 8 sectors per track */
param.eight=TRUE;
break;
case 'F': /* /F:size */
case 'f': /* /F:size */
param.f=TRUE;
n = atoi (optarg + 1);
if ((n == 160) || (n == 180) || (n == 320) || (n == 360) ||
(n == 720) || (n == 1200) || (n == 1440) || (n == 2880) ||
(n == 400) || (n == 800) || (n == 1680) || (n == 3360) ||
(n == 1494) || (n == 1743) || (n == 3486))
{
param.size = n;
}
else
{
printf("Ok: 160, 180, 320, 360, 720, 1200, 1440, 2880.\n");
printf("???: 400, 800, 1680, 3360, 1494, 1743, 3486.\n");
IllegalArg("/F",optarg);
}
break;
case 'T': /* tracks (cylinders) */
case 't': /* tracks (cylinders) */
param.t=TRUE;
n = atoi (optarg + 1);
if ((n == 40) || (n == 80) || (n == 83))
{
param.cylinders = n;
}
else
{
printf("Ok: 40, 80. ???: 83.\n");
IllegalArg("/T",optarg);
}
break;
case 'N': /* sectors per track */
case 'n': /* sectors per track */
param.n=TRUE;
n = atoi (optarg + 1);
if ((n == 8) || (n == 9) || (n == 15) || (n == 18) || (n == 36) ||
(n == 10) || (n == 21) || (n == 42))
{
param.sectors = n;
}
else
{
printf("Ok: 8, 9, 15, 18, 36. ???: 10, 21, 42.\n");
IllegalArg("/N",optarg);
}
break;
case '~':
param.drive_letter[0] = toupper (optarg[0]);
param.drive_number = param.drive_letter[0] - 'A';
param.drive_letter[1] = ':';
drive_letter_found = TRUE;
break;
default:
printf("Unrecognized option: /%c\n", index);
Display_Help_Screen();
exit(1);
case '/': /* Ignore '/' in middle of option */
break;
} /* switch (index) */
} /* for all args (getopt) */
if ( (argc > optind) && (isalpha (argv[optind][0])) &&
(argv[optind][1] == ':') && (argv[optind][2] == '\0') &&
(drive_letter_found == FALSE) )
{
param.drive_letter[0] = toupper (argv[optind][0]);
param.drive_number = param.drive_letter[0] - 'A';
param.drive_letter[1] = ':';
}
else
if (drive_letter_found == FALSE)
{
printf("Required parameter missing -\n");
exit(1);
}
/* (jh) done with parsing command line */
/* if FORMAT is typed with a drive letter */
if (debug_prog==TRUE)
printf("\n[DEBUG] Drive To Format-> %s \n\n",param.drive_letter);
/* Set the type of disk */
if (param.drive_number>1)
param.drive_type=HARD;
else
param.drive_type=FLOPPY;
/* *** TODO: complain about ANY size determination if type HARD *** */
/* Ensure that valid switch combinations were entered */
if ( (param.b==TRUE) && (param.s==TRUE) )
Display_Invalid_Combination();
/* cannot reserve space for SYS and actually SYS at the same time */
if ( (param.v==TRUE) && (param.eight==TRUE) )
Display_Invalid_Combination();
/* no label allowed if 160k / 320k */
if ( ( (param.one==TRUE) || (param.four==TRUE) /* 360k in 1.2M drive */ ) &&
( (param.f==TRUE) || (param.t==TRUE) || (param.n==TRUE) ) )
Display_Invalid_Combination();
/* cannot combine size/track/sector override with 1-sided / 360k */
if ( ( (param.t==TRUE) && (param.n!=TRUE) ) ||
( (param.n==TRUE) && (param.t!=TRUE) ) )
{
printf("You can only give /T -and- /N or -neither- of them.\n");
Display_Invalid_Combination();
/* you must give BOTH track and sector arguments if giving either */
}
if ( (param.f==TRUE) && ( (param.t==TRUE) || (param.n==TRUE) ) )
Display_Invalid_Combination();
/* you can only give EITHER size OR track/sector arguments */
#if 0
if ( ( (param.one==TRUE) || (param.four==TRUE) ) && (param.eight==TRUE) )
Display_Invalid_Combination();
/* 360k / one-sided are both not 8 sectors per track (360k is 40x2x9) */
#endif
/* we do allow /8 to reach 160k (with /1) and 320k (with /4) */
/* it is more the other way round: we do not want 8 sector/track > 320k! */
/* ... */
if (param.one==TRUE) /* one-sided: 160k and 180k only */
{
param.sides = 1;
param.cylinders = 40;
/* *** this is actually handled in Set_Floppy_Media_Type mostly *** */
}
if (param.four==TRUE) /* 360k in 1200k drive */
{
param.cylinders = 40;
param.sectors = 9;
}
if (param.eight==TRUE) /* DOS 1.0 formats: 160k and 320k only */
{
param.sectors = 8;
}
next_disk:
/* User interaction. */
if (param.drive_type==FLOPPY && param.force_yes==FALSE)
Ask_User_To_Insert_Disk();
if (param.drive_type==HARD && param.force_yes==FALSE)
Confirm_Hard_Drive_Formatting();
if ((param.u==TRUE) && (param.q==FALSE))
{
param.existing_format = FALSE; /* do not even check */
}
else
{
/* Check to see if the media is currently formatted. */
param.existing_format = Check_For_Format();
if ((param.existing_format==TRUE) && (param.drive_type==FLOPPY))
{
found_format_sectors_per_track = sector_buffer[0x18];
found_format_heads = sector_buffer[0x1a];
}
}
/* Determine and set media parameters */
if (param.drive_type==FLOPPY)
{
Set_Floppy_Media_Type();
if ((param.existing_format == FALSE) && (param.u==FALSE))
{
/* try finding existing format again - after setting media type */
if (debug_prog==TRUE)
printf("[DEBUG] Searching for existing format again...\n");
param.existing_format = Check_For_Format();
if ((param.existing_format==TRUE) && (param.drive_type==FLOPPY))
{
found_format_sectors_per_track = sector_buffer[0x18];
found_format_heads = sector_buffer[0x1a];
}
}
if (param.existing_format == TRUE)
{
if ((drive_specs[param.media_type].sectors_per_cylinder !=
found_format_sectors_per_track) || (found_format_heads !=
drive_specs[param.media_type].number_of_heads))
{
printf("Will change size by formatting - forcing full format\n");
printf("Old: %d sectors per track, %d heads. New: %d sect. %d heads\n",
found_format_sectors_per_track, found_format_heads,
drive_specs[param.media_type].sectors_per_cylinder,
drive_specs[param.media_type].number_of_heads);
param.u = TRUE;
param.q = FALSE;
}
}
/* if no existing format, we force full format anyway */
}
else
{
Set_Hard_Drive_Media_Parameters();
Enable_Disk_Access();
}
/* *** Maybe we should have done drive setup earlier, for Check_...? *** */
if (param.existing_format == FALSE)
{
if ( (param.u!=TRUE) || (param.q!=FALSE) )
{
printf("Cannot find existing format - forcing full format\n");
}
param.u = TRUE;
param.q = FALSE;
}
/* Format Drive */
if ( (param.u==TRUE) && (param.q==FALSE) )
{
/* /U is Unconditional Format */
printf(" Full Formatting (wiping all data)\n");
Unconditional_Format();
Create_File_System();
}
if ( (param.u==TRUE) && (param.q==TRUE) )
{
/* /Q /U is Quick Unconditional format */
printf(" QuickFormatting (only flushing metadata)\n");
Create_File_System();
}
if ( (param.u==FALSE) /* && (param.q==TRUE) */ )
{
/* this is the default, so if no /U given, it is irrelevant */
/* whether /Q is given or not... Should trigger FULL format */
/* if existing filesystem has other size or disk needs format */
/* /Q is Quick Format */
/* -- is Safe Format */
/* TEMPORARILY DISABLED FOR FAT32 */
if ((param.drive_type==HARD) && (param.fat_type!=FAT32))
{
printf(" Safe QuickFormatting (trying to save UnFormat data)\n");
Save_File_System();
}
else
{
printf(" QuickFormatting (only flushing metadata)\n");
}
Create_File_System();
}
if (param.drive_type==HARD) Set_DPB_Access_Flag();
if (bad_sector_map[0]>0)
/* TEMPORARILY DISABLED FOR FAT32 */
if (param.fat_type!=FAT32)
Record_Bad_Clusters();
printf("\nFormat complete.\n");
if (param.s==TRUE)
Write_System_Files();
Display_Drive_Statistics();
/* *** ASK USER... IF YES, GOTO next_disk ... *** */
exit(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -