Allow fdisk to be driven from a configuration file, making a 3rd-party
utility for front-ending its operation more of a possibility. 2.2-RELEASE candiate. Closes PR#1960 Submitted-By: Darryl Okahata <darrylo@hpnmhjw.sr.hp.com>
This commit is contained in:
parent
ebd0f7884d
commit
f46af50517
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19459
@ -1,4 +1,4 @@
|
||||
.Dd April 4, 1993
|
||||
.Dd October 4, 1996
|
||||
.Dt FDISK 8
|
||||
.\".Os BSD 4
|
||||
.Sh NAME
|
||||
@ -10,32 +10,14 @@
|
||||
.Op Fl u
|
||||
.Op Fl a
|
||||
.Op Fl 0123
|
||||
.Op disk
|
||||
.Op Ar disk
|
||||
.Bl -tag -width time
|
||||
.It Fl u
|
||||
Is used for updating (editing) sector 0 of the disk.
|
||||
.It Fl i
|
||||
Initializes sector 0 of the disk. This implies
|
||||
.Fl u .
|
||||
.It Fl a
|
||||
Change the active partition only.
|
||||
.It Fl 0123
|
||||
Operate on a single fdisk entry only.
|
||||
.El
|
||||
.Pp
|
||||
The final disk name can be provided as a
|
||||
.Sq bare
|
||||
disk name only, e.g.
|
||||
.Ql sd0 ,
|
||||
or as a fully qualified device node under
|
||||
.Pa /dev .
|
||||
If omitted, the disks
|
||||
.Ql wd0 ,
|
||||
.Ql sd0 ,
|
||||
and
|
||||
.Ql od0
|
||||
are being searched in that order, until one is
|
||||
being found responding.
|
||||
.Nm fdisk
|
||||
.Op Fl f Ar configfile
|
||||
.Op Fl i
|
||||
.Op Fl v
|
||||
.Op Fl t
|
||||
.Op Ar disk
|
||||
.Sh PROLOGUE
|
||||
In order for the BIOS to boot the kernel,
|
||||
certain conventions must be adhered to.
|
||||
@ -60,9 +42,84 @@ The DOS
|
||||
program can be used to divide space on the disk into partitions and set one
|
||||
.Em active.
|
||||
.Sh DESCRIPTION
|
||||
.Pp
|
||||
The FreeBSD program
|
||||
.Nm
|
||||
serves a similar purpose to the DOS program.
|
||||
serves a similar purpose to the DOS program. The first form is used to
|
||||
display partition information or to interactively edit the partition
|
||||
table. The second is used to write a partition table using a
|
||||
.Ar configfile
|
||||
and is designed to be used by other scripts/programs.
|
||||
.Pp
|
||||
Options are:
|
||||
.It Fl u
|
||||
Is used for updating (editing) sector 0 of the disk. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl i
|
||||
Initializes sector 0 of the disk. This implies
|
||||
.Fl u ,
|
||||
unless
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl a
|
||||
Change the active partition only. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl 0123
|
||||
Operate on a single fdisk entry only. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl f Ar configfile
|
||||
Set partition values using the file
|
||||
.Ar configfile .
|
||||
The
|
||||
.Ar configfile
|
||||
always modifies existing partitions, unless
|
||||
.Fl i
|
||||
is also given, in which case all existing partitions are deleted (marked
|
||||
as "unused") before the
|
||||
.Ar configfile
|
||||
is read. The
|
||||
.Ar configfile
|
||||
can be "-", in which case
|
||||
.Ar stdin
|
||||
is read. See
|
||||
.Em CONFIGURATION FILE ,
|
||||
below, for file syntax.
|
||||
.Pp
|
||||
.Em WARNING:
|
||||
when
|
||||
.Fl f
|
||||
is used, you are not asked if you really want to write the partition
|
||||
table (as you are in the interactive mode). Use with caution!
|
||||
.It Fl t
|
||||
Test mode; do not write partition values. Generally used with the
|
||||
.Fl f
|
||||
option to see what would be written to the partition table. Implies
|
||||
.Fl v .
|
||||
.It Fl v
|
||||
Be verbose. When
|
||||
.Fl f
|
||||
is used,
|
||||
.Nm
|
||||
prints out the partition table that is written to the disk.
|
||||
.El
|
||||
.Pp
|
||||
The final disk name can be provided as a
|
||||
.Sq bare
|
||||
disk name only, e.g.
|
||||
.Ql sd0 ,
|
||||
or as a fully qualified device node under
|
||||
.Pa /dev .
|
||||
If omitted, the disks
|
||||
.Ql wd0 ,
|
||||
.Ql sd0 ,
|
||||
and
|
||||
.Ql od0
|
||||
are being searched in that order, until one is
|
||||
being found responding.
|
||||
.Pp
|
||||
When called with no arguments, it prints the sector 0 partition table.
|
||||
An example follows:
|
||||
|
||||
@ -119,8 +176,11 @@ The flags
|
||||
.Fl i
|
||||
or
|
||||
.Fl u
|
||||
are used to indicate that the partition data is to be updated.
|
||||
The
|
||||
are used to indicate that the partition data is to be updated, unless the
|
||||
.Fl f
|
||||
option is used. If the
|
||||
.Fl f
|
||||
option is not used, the
|
||||
.Nm
|
||||
program will enter a conversational mode.
|
||||
This mode is designed not to change any data unless you explicitly tell it to.
|
||||
@ -188,11 +248,151 @@ A number of decisions made later may assume this.
|
||||
Editing an existing partition will most likely cause you to
|
||||
lose all the data in that partition.
|
||||
.Pp
|
||||
You should run this program interactively once or twice to see how it works.
|
||||
This is completely safe as long as you answer the last question in the negative.
|
||||
There are subtleties
|
||||
that the program detects
|
||||
that are not fully explained in this manual page.
|
||||
You should run this program interactively once or twice to see how it
|
||||
works. This is completely safe as long as you answer the last question
|
||||
in the negative. There are subtleties that the program detects that are
|
||||
not fully explained in this manual page.
|
||||
.Sh CONFIGURATION FILE
|
||||
.Pp
|
||||
When the
|
||||
.Fl f
|
||||
option is given, a disk's partition table can be written using values
|
||||
from a
|
||||
.Ar configfile .
|
||||
The syntax of this file is very simple. Each line is either a comment or
|
||||
a specification, and whitespace (except for newlines) are ignored:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Ic #
|
||||
.No Ar comment ...
|
||||
.Xc
|
||||
Lines beginning with a "#" are comments and are ignored.
|
||||
.It Xo
|
||||
.Ic g
|
||||
.No Ar spec1
|
||||
.No Ar spec2
|
||||
.No Ar spec3
|
||||
.Xc
|
||||
Set the BIOS geometry used in partition calculations. There must be
|
||||
three values specfied, with a letter preceding each number:
|
||||
.Bl -tag -width Ds
|
||||
.Sm off
|
||||
.It Cm c No Ar num
|
||||
.Sm on
|
||||
Set the number of cylinders to
|
||||
.Ar num .
|
||||
.Sm off
|
||||
.It Cm h No Ar num
|
||||
.Sm on
|
||||
Set the number of heads to
|
||||
.Ar num .
|
||||
.Sm off
|
||||
.It Cm s No Ar num
|
||||
.Sm on
|
||||
Set the number of sectors/track to
|
||||
.Ar num .
|
||||
.El
|
||||
.Pp
|
||||
These specs can occur in any order, as the leading letter determines
|
||||
which value is which; however, all three must be specified.
|
||||
.Pp
|
||||
This line must occur before any lines that specify partition
|
||||
information.
|
||||
.Pp
|
||||
It is an error if the following is not true:
|
||||
.Pp
|
||||
.nf
|
||||
1 <= number of cylinders
|
||||
1 <= number of heads <= 256
|
||||
1 <= number of sectors/track < 64
|
||||
.fi
|
||||
.Pp
|
||||
The number of cylinders should be less than or equal to 1024, but this
|
||||
is not enforced, although a warning will be output. Note that bootable
|
||||
FreeBSD partitions (the "/" filesystem) must lie completely within the
|
||||
first 1024 cylinders; if this is not true, booting may fail.
|
||||
Non-bootable partitions do not have this restriction.
|
||||
.Pp
|
||||
Example (all of these are equivalent), for a disk with 1019 cylinders,
|
||||
39 heads, and 63 sectors:
|
||||
.Pp
|
||||
.nf
|
||||
g c1019 h39 s63
|
||||
g h39 c1019 s63
|
||||
g s63 h39 c1019
|
||||
.fi
|
||||
.It Xo
|
||||
.Ic p
|
||||
.No Ar partition
|
||||
.No Ar type
|
||||
.No Ar start
|
||||
.No Ar length
|
||||
.Xc
|
||||
Set the partition given by
|
||||
.Ar partition
|
||||
(0-3) to type
|
||||
.Ar type ,
|
||||
starting at sector
|
||||
.Ar start
|
||||
for
|
||||
.Ar length
|
||||
sectors.
|
||||
.Pp
|
||||
Only those partitions explicitly mentioned by these lines are modified;
|
||||
any partition not referenced by a "p" line will not be modified.
|
||||
However, if an invalid partition table is present, or the
|
||||
.Fl i
|
||||
option is specified, all existing partition entries will be cleared
|
||||
(marked as unused), and these "p" lines will have to be used to
|
||||
explicitly set partition information. If multiple partitions need to be
|
||||
set, multiple "p" lines must be specified; one for each partition.
|
||||
.Pp
|
||||
These partition lines must occur after any geometry specification lines,
|
||||
if one is present.
|
||||
.Pp
|
||||
The
|
||||
.Ar type
|
||||
is 165 for FreeBSD partitions. Specifying a partition type of zero is
|
||||
the same as clearing the partition and marking it as unused; however,
|
||||
dummy values (such as "0") must still be specified for
|
||||
.Ar start
|
||||
and
|
||||
.Ar length .
|
||||
.Pp
|
||||
Note: the start offset will be rounded upwards to a head boundary if
|
||||
necessary, and the end offset will be rounded downwards to a cylinder
|
||||
boundary if necessary.
|
||||
.Pp
|
||||
Example: to clear partition 3 and mark it as unused:
|
||||
.Pp
|
||||
.nf
|
||||
p 3 0 0 0
|
||||
.fi
|
||||
.Pp
|
||||
Example: to set partition 0 to a FreeBSD partition, starting at sector 1
|
||||
for 2503871 sectors (note: these numbers will be rounded upwards and
|
||||
downwards to correspond to head and cylinder boundaries):
|
||||
.Pp
|
||||
.nf
|
||||
p 0 165 1 2503871
|
||||
.fi
|
||||
.It Xo
|
||||
.Ic a
|
||||
.No Ar partition
|
||||
.Xc
|
||||
Make
|
||||
.Ar partition
|
||||
the active partition. Can occur anywhere in the config file, but only
|
||||
one must be present.
|
||||
.Pp
|
||||
Example: to make partition 0 the active partition:
|
||||
.Pp
|
||||
.nf
|
||||
a 0
|
||||
.fi
|
||||
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr disklabel 8
|
||||
.Sh BUGS
|
||||
@ -203,3 +403,7 @@ Throughout this man page, the term
|
||||
is used where it should actually be
|
||||
.Sq slice ,
|
||||
in order to conform with the terms used elsewhere.
|
||||
.Pp
|
||||
You cannot use this command to completely dedicate a disk to FreeBSD. The
|
||||
.Xr disklabel 8
|
||||
command must be used for this.
|
||||
|
@ -90,9 +90,31 @@ int dos_cylsecs;
|
||||
static int partition = -1;
|
||||
|
||||
|
||||
#define MAX_ARGS 10
|
||||
|
||||
static int current_line_number;
|
||||
|
||||
static int geom_processed = 0;
|
||||
static int part_processed = 0;
|
||||
static int active_processed = 0;
|
||||
|
||||
|
||||
typedef struct cmd {
|
||||
char cmd;
|
||||
int n_args;
|
||||
struct arg {
|
||||
char argtype;
|
||||
int arg_val;
|
||||
} args[MAX_ARGS];
|
||||
} CMD;
|
||||
|
||||
|
||||
static int a_flag = 0; /* set active partition */
|
||||
static int i_flag = 0; /* replace partition data */
|
||||
static int u_flag = 0; /* update partition data */
|
||||
static int t_flag = 0; /* test only, if f_flag is given */
|
||||
static char *f_flag = NULL; /* Read config info from file */
|
||||
static int v_flag = 0; /* Be verbose */
|
||||
|
||||
static unsigned char bootcode[] = {
|
||||
0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
|
||||
@ -179,6 +201,7 @@ struct part_type
|
||||
static void print_s0(int which);
|
||||
static void print_part(int i);
|
||||
static void init_sector0(unsigned long start);
|
||||
static void init_boot(void);
|
||||
static void change_part(int i);
|
||||
static void print_params();
|
||||
static void change_active(int which);
|
||||
@ -194,6 +217,8 @@ static int write_s0();
|
||||
static int ok(char *str);
|
||||
static int decimal(char *str, int *num, int deflt);
|
||||
static char *get_type(int type);
|
||||
static int read_config(char *config_file);
|
||||
static void reset_boot(void);
|
||||
#if 0
|
||||
static int hex(char *str, int *num, int deflt);
|
||||
static int string(char *str, char **ans);
|
||||
@ -231,11 +256,37 @@ main(int argc, char *argv[])
|
||||
case 'a':
|
||||
a_flag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (*token)
|
||||
{
|
||||
f_flag = token;
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
--argc;
|
||||
f_flag = *++argv;
|
||||
}
|
||||
/*
|
||||
* u_flag is needed, because we're
|
||||
* writing to the disk.
|
||||
*/
|
||||
u_flag = 1;
|
||||
break;
|
||||
case 'i':
|
||||
i_flag = 1;
|
||||
case 'u':
|
||||
u_flag = 1;
|
||||
break;
|
||||
case 't':
|
||||
t_flag = 1;
|
||||
case 'v':
|
||||
v_flag = 1;
|
||||
break;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
@ -281,41 +332,75 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
printf("******* Working on device %s *******\n",disk);
|
||||
if(u_flag)
|
||||
|
||||
if (f_flag)
|
||||
{
|
||||
get_params_to_use();
|
||||
if (read_s0() || i_flag)
|
||||
{
|
||||
reset_boot();
|
||||
}
|
||||
|
||||
if (!read_config(f_flag))
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
if (v_flag)
|
||||
{
|
||||
print_s0(-1);
|
||||
}
|
||||
if (!t_flag)
|
||||
{
|
||||
write_s0();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(u_flag)
|
||||
{
|
||||
get_params_to_use();
|
||||
}
|
||||
else
|
||||
{
|
||||
print_params();
|
||||
}
|
||||
}
|
||||
|
||||
if (read_s0())
|
||||
if (read_s0())
|
||||
init_sector0(1);
|
||||
|
||||
printf("Warning: BIOS sector numbering starts with sector 1\n");
|
||||
printf("Information from DOS bootblock is:\n");
|
||||
if (partition == -1)
|
||||
printf("Warning: BIOS sector numbering starts with sector 1\n");
|
||||
printf("Information from DOS bootblock is:\n");
|
||||
if (partition == -1)
|
||||
for (i = 0; i < NDOSPART; i++)
|
||||
change_part(i);
|
||||
else
|
||||
change_part(i);
|
||||
else
|
||||
change_part(partition);
|
||||
|
||||
if (u_flag || a_flag)
|
||||
if (u_flag || a_flag)
|
||||
change_active(partition);
|
||||
|
||||
if (u_flag || a_flag) {
|
||||
printf("\nWe haven't changed the partition table yet. ");
|
||||
printf("This is your last chance.\n");
|
||||
if (u_flag || a_flag) {
|
||||
if (!t_flag)
|
||||
{
|
||||
printf("\nWe haven't changed the partition table yet. ");
|
||||
printf("This is your last chance.\n");
|
||||
}
|
||||
print_s0(-1);
|
||||
if (ok("Should we write new partition table?"))
|
||||
if (!t_flag)
|
||||
{
|
||||
if (ok("Should we write new partition table?"))
|
||||
write_s0();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n-t flag specified -- partition table not written.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
usage:
|
||||
printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n");
|
||||
printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{0,1,2,3}] [disk]\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -359,14 +444,22 @@ struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
|
||||
,partp->dp_ehd);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_boot(void)
|
||||
{
|
||||
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
|
||||
mboot.signature = BOOT_MAGIC;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_sector0(unsigned long start)
|
||||
{
|
||||
struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
|
||||
unsigned long size = disksecs - start;
|
||||
|
||||
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
|
||||
mboot.signature = BOOT_MAGIC;
|
||||
init_boot();
|
||||
|
||||
partp->dp_typ = DOSPTYP_386BSD;
|
||||
partp->dp_flag = ACTIVE;
|
||||
@ -490,6 +583,7 @@ get_params_to_use()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************\
|
||||
* Change real numbers into strange dos numbers *
|
||||
\***********************************************/
|
||||
@ -779,3 +873,425 @@ get_type(int type)
|
||||
}
|
||||
return("unknown");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_config_line(line, command)
|
||||
char *line;
|
||||
CMD *command;
|
||||
{
|
||||
char *cp, *end;
|
||||
|
||||
cp = line;
|
||||
while (1) /* dirty trick used to insure one exit point for this
|
||||
function */
|
||||
{
|
||||
memset(command, 0, sizeof(*command));
|
||||
|
||||
while (isspace(*cp)) ++cp;
|
||||
if (*cp == '\0' || *cp == '#')
|
||||
{
|
||||
break;
|
||||
}
|
||||
command->cmd = *cp++;
|
||||
|
||||
/*
|
||||
* Parse args
|
||||
*/
|
||||
while (1)
|
||||
{
|
||||
while (isspace(*cp)) ++cp;
|
||||
if (*cp == '#')
|
||||
{
|
||||
break; /* found comment */
|
||||
}
|
||||
if (isalpha(*cp))
|
||||
{
|
||||
command->args[command->n_args].argtype = *cp++;
|
||||
}
|
||||
if (!isdigit(*cp))
|
||||
{
|
||||
break; /* assume end of line */
|
||||
}
|
||||
end = NULL;
|
||||
command->args[command->n_args].arg_val = strtol(cp, &end, 0);
|
||||
if (cp == end)
|
||||
{
|
||||
break; /* couldn't parse number */
|
||||
}
|
||||
cp = end;
|
||||
command->n_args++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_geometry(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 1, i;
|
||||
|
||||
while (1)
|
||||
{
|
||||
geom_processed = 1;
|
||||
if (part_processed)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: the geometry specification line must occur before\n\
|
||||
all partition specifications.\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
if (command->n_args != 3)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of geometry args\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
dos_cyls = -1;
|
||||
dos_heads = -1;
|
||||
dos_sectors = -1;
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
switch (command->args[i].argtype)
|
||||
{
|
||||
case 'c':
|
||||
dos_cyls = command->args[i].arg_val;
|
||||
break;
|
||||
case 'h':
|
||||
dos_heads = command->args[i].arg_val;
|
||||
break;
|
||||
case 's':
|
||||
dos_sectors = command->args[i].arg_val;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
|
||||
name, current_line_number, command->args[i].argtype,
|
||||
command->args[i].argtype);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
dos_cylsecs = dos_heads * dos_sectors;
|
||||
|
||||
/*
|
||||
* Do sanity checks on parameter values
|
||||
*/
|
||||
if (dos_cyls < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of cylinders not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
if (dos_cyls == 0 || dos_cyls > 1024)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
|
||||
(must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
|
||||
is dedicated to FreeBSD).\n",
|
||||
name, current_line_number, dos_cyls);
|
||||
}
|
||||
|
||||
if (dos_heads < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of heads not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
else if (dos_heads < 1 || dos_heads > 256)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of heads must be within (1-256)\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (dos_sectors < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
else if (dos_sectors < 1 || dos_sectors > 63)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of sectors must be within (1-63)\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_partition(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 0, partition;
|
||||
unsigned long chunks, adj_size, max_end;
|
||||
struct dos_partition *partp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
part_processed = 1;
|
||||
if (command->n_args != 4)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of partition args\n",
|
||||
name, current_line_number);
|
||||
break;
|
||||
}
|
||||
partition = command->args[0].arg_val;
|
||||
if (partition < 0 || partition > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
partp = ((struct dos_partition *) &mboot.parts) + partition;
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
partp->dp_typ = command->args[1].arg_val;
|
||||
partp->dp_start = command->args[2].arg_val;
|
||||
partp->dp_size = command->args[3].arg_val;
|
||||
max_end = partp->dp_start + partp->dp_size;
|
||||
|
||||
if (partp->dp_typ == 0)
|
||||
{
|
||||
/*
|
||||
* Get out, the partition is marked as unused.
|
||||
*/
|
||||
/*
|
||||
* Insure that it's unused.
|
||||
*/
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust start upwards, if necessary, to fall on an head boundary.
|
||||
*/
|
||||
if (partp->dp_start % dos_sectors != 0)
|
||||
{
|
||||
adj_size =
|
||||
(partp->dp_start / dos_sectors + 1) * dos_sectors;
|
||||
if (adj_size > max_end)
|
||||
{
|
||||
/*
|
||||
* Can't go past end of partition
|
||||
*/
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
|
||||
a cylinder boundary.\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"%s: WARNING: adjusting start offset of partition '%d' from %d\n\
|
||||
to %d, to round to an head boundary.\n",
|
||||
name, partition, partp->dp_start, adj_size);
|
||||
partp->dp_start = adj_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust size downwards, if necessary, to fall on a cylinder
|
||||
* boundary.
|
||||
*/
|
||||
chunks =
|
||||
((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
|
||||
adj_size = chunks - partp->dp_start;
|
||||
if (adj_size != partp->dp_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
|
||||
to round to a cylinder boundary.\n",
|
||||
name, partition, partp->dp_size, adj_size);
|
||||
if (chunks > 0)
|
||||
{
|
||||
partp->dp_size = adj_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
partp->dp_size = 0;
|
||||
}
|
||||
}
|
||||
if (partp->dp_size < 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: size for partition '%d' is zero.\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
|
||||
dos(partp->dp_start, partp->dp_size,
|
||||
&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
|
||||
dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
|
||||
&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_active(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 0, partition, i;
|
||||
struct dos_partition *partp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
active_processed = 1;
|
||||
if (command->n_args != 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of active args\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
partition = command->args[0].arg_val;
|
||||
if (partition < 0 || partition > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Reset active partition
|
||||
*/
|
||||
partp = ((struct dos_partition *) &mboot.parts);
|
||||
for (i = 0; i < NDOSPART; i++)
|
||||
partp[i].dp_flag = 0;
|
||||
partp[partition].dp_flag = ACTIVE;
|
||||
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_line(line)
|
||||
char *line;
|
||||
{
|
||||
CMD command;
|
||||
int status = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
parse_config_line(line, &command);
|
||||
switch (command.cmd)
|
||||
{
|
||||
case 0:
|
||||
/*
|
||||
* Comment or blank line
|
||||
*/
|
||||
break;
|
||||
case 'g':
|
||||
/*
|
||||
* Set geometry
|
||||
*/
|
||||
status = process_geometry(&command);
|
||||
break;
|
||||
case 'p':
|
||||
status = process_partition(&command);
|
||||
break;
|
||||
case 'a':
|
||||
status = process_active(&command);
|
||||
break;
|
||||
default:
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_config(config_file)
|
||||
char *config_file;
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int status = 1;
|
||||
char buf[1010];
|
||||
|
||||
while (1) /* dirty trick used to insure one exit point for this
|
||||
function */
|
||||
{
|
||||
if (strcmp(config_file, "-") != 0)
|
||||
{
|
||||
/*
|
||||
* We're not reading from stdin
|
||||
*/
|
||||
if ((fp = fopen(config_file, "r")) == NULL)
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = stdin;
|
||||
}
|
||||
current_line_number = 0;
|
||||
while (!feof(fp))
|
||||
{
|
||||
if (fgets(buf, sizeof(buf), fp) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++current_line_number;
|
||||
status = process_line(buf);
|
||||
if (status == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fp)
|
||||
{
|
||||
/*
|
||||
* It doesn't matter if we're reading from stdin, as we've reached EOF
|
||||
*/
|
||||
fclose(fp);
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reset_boot(void)
|
||||
{
|
||||
int i;
|
||||
struct dos_partition *partp;
|
||||
|
||||
init_boot();
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
partp = ((struct dos_partition *) &mboot.parts) + i;
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
.Dd April 4, 1993
|
||||
.Dd October 4, 1996
|
||||
.Dt FDISK 8
|
||||
.\".Os BSD 4
|
||||
.Sh NAME
|
||||
@ -10,32 +10,14 @@
|
||||
.Op Fl u
|
||||
.Op Fl a
|
||||
.Op Fl 0123
|
||||
.Op disk
|
||||
.Op Ar disk
|
||||
.Bl -tag -width time
|
||||
.It Fl u
|
||||
Is used for updating (editing) sector 0 of the disk.
|
||||
.It Fl i
|
||||
Initializes sector 0 of the disk. This implies
|
||||
.Fl u .
|
||||
.It Fl a
|
||||
Change the active partition only.
|
||||
.It Fl 0123
|
||||
Operate on a single fdisk entry only.
|
||||
.El
|
||||
.Pp
|
||||
The final disk name can be provided as a
|
||||
.Sq bare
|
||||
disk name only, e.g.
|
||||
.Ql sd0 ,
|
||||
or as a fully qualified device node under
|
||||
.Pa /dev .
|
||||
If omitted, the disks
|
||||
.Ql wd0 ,
|
||||
.Ql sd0 ,
|
||||
and
|
||||
.Ql od0
|
||||
are being searched in that order, until one is
|
||||
being found responding.
|
||||
.Nm fdisk
|
||||
.Op Fl f Ar configfile
|
||||
.Op Fl i
|
||||
.Op Fl v
|
||||
.Op Fl t
|
||||
.Op Ar disk
|
||||
.Sh PROLOGUE
|
||||
In order for the BIOS to boot the kernel,
|
||||
certain conventions must be adhered to.
|
||||
@ -60,9 +42,84 @@ The DOS
|
||||
program can be used to divide space on the disk into partitions and set one
|
||||
.Em active.
|
||||
.Sh DESCRIPTION
|
||||
.Pp
|
||||
The FreeBSD program
|
||||
.Nm
|
||||
serves a similar purpose to the DOS program.
|
||||
serves a similar purpose to the DOS program. The first form is used to
|
||||
display partition information or to interactively edit the partition
|
||||
table. The second is used to write a partition table using a
|
||||
.Ar configfile
|
||||
and is designed to be used by other scripts/programs.
|
||||
.Pp
|
||||
Options are:
|
||||
.It Fl u
|
||||
Is used for updating (editing) sector 0 of the disk. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl i
|
||||
Initializes sector 0 of the disk. This implies
|
||||
.Fl u ,
|
||||
unless
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl a
|
||||
Change the active partition only. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl 0123
|
||||
Operate on a single fdisk entry only. Ignored if
|
||||
.Fl f
|
||||
is given.
|
||||
.It Fl f Ar configfile
|
||||
Set partition values using the file
|
||||
.Ar configfile .
|
||||
The
|
||||
.Ar configfile
|
||||
always modifies existing partitions, unless
|
||||
.Fl i
|
||||
is also given, in which case all existing partitions are deleted (marked
|
||||
as "unused") before the
|
||||
.Ar configfile
|
||||
is read. The
|
||||
.Ar configfile
|
||||
can be "-", in which case
|
||||
.Ar stdin
|
||||
is read. See
|
||||
.Em CONFIGURATION FILE ,
|
||||
below, for file syntax.
|
||||
.Pp
|
||||
.Em WARNING:
|
||||
when
|
||||
.Fl f
|
||||
is used, you are not asked if you really want to write the partition
|
||||
table (as you are in the interactive mode). Use with caution!
|
||||
.It Fl t
|
||||
Test mode; do not write partition values. Generally used with the
|
||||
.Fl f
|
||||
option to see what would be written to the partition table. Implies
|
||||
.Fl v .
|
||||
.It Fl v
|
||||
Be verbose. When
|
||||
.Fl f
|
||||
is used,
|
||||
.Nm
|
||||
prints out the partition table that is written to the disk.
|
||||
.El
|
||||
.Pp
|
||||
The final disk name can be provided as a
|
||||
.Sq bare
|
||||
disk name only, e.g.
|
||||
.Ql sd0 ,
|
||||
or as a fully qualified device node under
|
||||
.Pa /dev .
|
||||
If omitted, the disks
|
||||
.Ql wd0 ,
|
||||
.Ql sd0 ,
|
||||
and
|
||||
.Ql od0
|
||||
are being searched in that order, until one is
|
||||
being found responding.
|
||||
.Pp
|
||||
When called with no arguments, it prints the sector 0 partition table.
|
||||
An example follows:
|
||||
|
||||
@ -119,8 +176,11 @@ The flags
|
||||
.Fl i
|
||||
or
|
||||
.Fl u
|
||||
are used to indicate that the partition data is to be updated.
|
||||
The
|
||||
are used to indicate that the partition data is to be updated, unless the
|
||||
.Fl f
|
||||
option is used. If the
|
||||
.Fl f
|
||||
option is not used, the
|
||||
.Nm
|
||||
program will enter a conversational mode.
|
||||
This mode is designed not to change any data unless you explicitly tell it to.
|
||||
@ -188,11 +248,151 @@ A number of decisions made later may assume this.
|
||||
Editing an existing partition will most likely cause you to
|
||||
lose all the data in that partition.
|
||||
.Pp
|
||||
You should run this program interactively once or twice to see how it works.
|
||||
This is completely safe as long as you answer the last question in the negative.
|
||||
There are subtleties
|
||||
that the program detects
|
||||
that are not fully explained in this manual page.
|
||||
You should run this program interactively once or twice to see how it
|
||||
works. This is completely safe as long as you answer the last question
|
||||
in the negative. There are subtleties that the program detects that are
|
||||
not fully explained in this manual page.
|
||||
.Sh CONFIGURATION FILE
|
||||
.Pp
|
||||
When the
|
||||
.Fl f
|
||||
option is given, a disk's partition table can be written using values
|
||||
from a
|
||||
.Ar configfile .
|
||||
The syntax of this file is very simple. Each line is either a comment or
|
||||
a specification, and whitespace (except for newlines) are ignored:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo
|
||||
.Ic #
|
||||
.No Ar comment ...
|
||||
.Xc
|
||||
Lines beginning with a "#" are comments and are ignored.
|
||||
.It Xo
|
||||
.Ic g
|
||||
.No Ar spec1
|
||||
.No Ar spec2
|
||||
.No Ar spec3
|
||||
.Xc
|
||||
Set the BIOS geometry used in partition calculations. There must be
|
||||
three values specfied, with a letter preceding each number:
|
||||
.Bl -tag -width Ds
|
||||
.Sm off
|
||||
.It Cm c No Ar num
|
||||
.Sm on
|
||||
Set the number of cylinders to
|
||||
.Ar num .
|
||||
.Sm off
|
||||
.It Cm h No Ar num
|
||||
.Sm on
|
||||
Set the number of heads to
|
||||
.Ar num .
|
||||
.Sm off
|
||||
.It Cm s No Ar num
|
||||
.Sm on
|
||||
Set the number of sectors/track to
|
||||
.Ar num .
|
||||
.El
|
||||
.Pp
|
||||
These specs can occur in any order, as the leading letter determines
|
||||
which value is which; however, all three must be specified.
|
||||
.Pp
|
||||
This line must occur before any lines that specify partition
|
||||
information.
|
||||
.Pp
|
||||
It is an error if the following is not true:
|
||||
.Pp
|
||||
.nf
|
||||
1 <= number of cylinders
|
||||
1 <= number of heads <= 256
|
||||
1 <= number of sectors/track < 64
|
||||
.fi
|
||||
.Pp
|
||||
The number of cylinders should be less than or equal to 1024, but this
|
||||
is not enforced, although a warning will be output. Note that bootable
|
||||
FreeBSD partitions (the "/" filesystem) must lie completely within the
|
||||
first 1024 cylinders; if this is not true, booting may fail.
|
||||
Non-bootable partitions do not have this restriction.
|
||||
.Pp
|
||||
Example (all of these are equivalent), for a disk with 1019 cylinders,
|
||||
39 heads, and 63 sectors:
|
||||
.Pp
|
||||
.nf
|
||||
g c1019 h39 s63
|
||||
g h39 c1019 s63
|
||||
g s63 h39 c1019
|
||||
.fi
|
||||
.It Xo
|
||||
.Ic p
|
||||
.No Ar partition
|
||||
.No Ar type
|
||||
.No Ar start
|
||||
.No Ar length
|
||||
.Xc
|
||||
Set the partition given by
|
||||
.Ar partition
|
||||
(0-3) to type
|
||||
.Ar type ,
|
||||
starting at sector
|
||||
.Ar start
|
||||
for
|
||||
.Ar length
|
||||
sectors.
|
||||
.Pp
|
||||
Only those partitions explicitly mentioned by these lines are modified;
|
||||
any partition not referenced by a "p" line will not be modified.
|
||||
However, if an invalid partition table is present, or the
|
||||
.Fl i
|
||||
option is specified, all existing partition entries will be cleared
|
||||
(marked as unused), and these "p" lines will have to be used to
|
||||
explicitly set partition information. If multiple partitions need to be
|
||||
set, multiple "p" lines must be specified; one for each partition.
|
||||
.Pp
|
||||
These partition lines must occur after any geometry specification lines,
|
||||
if one is present.
|
||||
.Pp
|
||||
The
|
||||
.Ar type
|
||||
is 165 for FreeBSD partitions. Specifying a partition type of zero is
|
||||
the same as clearing the partition and marking it as unused; however,
|
||||
dummy values (such as "0") must still be specified for
|
||||
.Ar start
|
||||
and
|
||||
.Ar length .
|
||||
.Pp
|
||||
Note: the start offset will be rounded upwards to a head boundary if
|
||||
necessary, and the end offset will be rounded downwards to a cylinder
|
||||
boundary if necessary.
|
||||
.Pp
|
||||
Example: to clear partition 3 and mark it as unused:
|
||||
.Pp
|
||||
.nf
|
||||
p 3 0 0 0
|
||||
.fi
|
||||
.Pp
|
||||
Example: to set partition 0 to a FreeBSD partition, starting at sector 1
|
||||
for 2503871 sectors (note: these numbers will be rounded upwards and
|
||||
downwards to correspond to head and cylinder boundaries):
|
||||
.Pp
|
||||
.nf
|
||||
p 0 165 1 2503871
|
||||
.fi
|
||||
.It Xo
|
||||
.Ic a
|
||||
.No Ar partition
|
||||
.Xc
|
||||
Make
|
||||
.Ar partition
|
||||
the active partition. Can occur anywhere in the config file, but only
|
||||
one must be present.
|
||||
.Pp
|
||||
Example: to make partition 0 the active partition:
|
||||
.Pp
|
||||
.nf
|
||||
a 0
|
||||
.fi
|
||||
|
||||
.El
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr disklabel 8
|
||||
.Sh BUGS
|
||||
@ -203,3 +403,7 @@ Throughout this man page, the term
|
||||
is used where it should actually be
|
||||
.Sq slice ,
|
||||
in order to conform with the terms used elsewhere.
|
||||
.Pp
|
||||
You cannot use this command to completely dedicate a disk to FreeBSD. The
|
||||
.Xr disklabel 8
|
||||
command must be used for this.
|
||||
|
@ -90,9 +90,31 @@ int dos_cylsecs;
|
||||
static int partition = -1;
|
||||
|
||||
|
||||
#define MAX_ARGS 10
|
||||
|
||||
static int current_line_number;
|
||||
|
||||
static int geom_processed = 0;
|
||||
static int part_processed = 0;
|
||||
static int active_processed = 0;
|
||||
|
||||
|
||||
typedef struct cmd {
|
||||
char cmd;
|
||||
int n_args;
|
||||
struct arg {
|
||||
char argtype;
|
||||
int arg_val;
|
||||
} args[MAX_ARGS];
|
||||
} CMD;
|
||||
|
||||
|
||||
static int a_flag = 0; /* set active partition */
|
||||
static int i_flag = 0; /* replace partition data */
|
||||
static int u_flag = 0; /* update partition data */
|
||||
static int t_flag = 0; /* test only, if f_flag is given */
|
||||
static char *f_flag = NULL; /* Read config info from file */
|
||||
static int v_flag = 0; /* Be verbose */
|
||||
|
||||
static unsigned char bootcode[] = {
|
||||
0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
|
||||
@ -179,6 +201,7 @@ struct part_type
|
||||
static void print_s0(int which);
|
||||
static void print_part(int i);
|
||||
static void init_sector0(unsigned long start);
|
||||
static void init_boot(void);
|
||||
static void change_part(int i);
|
||||
static void print_params();
|
||||
static void change_active(int which);
|
||||
@ -194,6 +217,8 @@ static int write_s0();
|
||||
static int ok(char *str);
|
||||
static int decimal(char *str, int *num, int deflt);
|
||||
static char *get_type(int type);
|
||||
static int read_config(char *config_file);
|
||||
static void reset_boot(void);
|
||||
#if 0
|
||||
static int hex(char *str, int *num, int deflt);
|
||||
static int string(char *str, char **ans);
|
||||
@ -231,11 +256,37 @@ main(int argc, char *argv[])
|
||||
case 'a':
|
||||
a_flag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
if (*token)
|
||||
{
|
||||
f_flag = token;
|
||||
token = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
--argc;
|
||||
f_flag = *++argv;
|
||||
}
|
||||
/*
|
||||
* u_flag is needed, because we're
|
||||
* writing to the disk.
|
||||
*/
|
||||
u_flag = 1;
|
||||
break;
|
||||
case 'i':
|
||||
i_flag = 1;
|
||||
case 'u':
|
||||
u_flag = 1;
|
||||
break;
|
||||
case 't':
|
||||
t_flag = 1;
|
||||
case 'v':
|
||||
v_flag = 1;
|
||||
break;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
@ -281,41 +332,75 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
printf("******* Working on device %s *******\n",disk);
|
||||
if(u_flag)
|
||||
|
||||
if (f_flag)
|
||||
{
|
||||
get_params_to_use();
|
||||
if (read_s0() || i_flag)
|
||||
{
|
||||
reset_boot();
|
||||
}
|
||||
|
||||
if (!read_config(f_flag))
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
if (v_flag)
|
||||
{
|
||||
print_s0(-1);
|
||||
}
|
||||
if (!t_flag)
|
||||
{
|
||||
write_s0();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(u_flag)
|
||||
{
|
||||
get_params_to_use();
|
||||
}
|
||||
else
|
||||
{
|
||||
print_params();
|
||||
}
|
||||
}
|
||||
|
||||
if (read_s0())
|
||||
if (read_s0())
|
||||
init_sector0(1);
|
||||
|
||||
printf("Warning: BIOS sector numbering starts with sector 1\n");
|
||||
printf("Information from DOS bootblock is:\n");
|
||||
if (partition == -1)
|
||||
printf("Warning: BIOS sector numbering starts with sector 1\n");
|
||||
printf("Information from DOS bootblock is:\n");
|
||||
if (partition == -1)
|
||||
for (i = 0; i < NDOSPART; i++)
|
||||
change_part(i);
|
||||
else
|
||||
change_part(i);
|
||||
else
|
||||
change_part(partition);
|
||||
|
||||
if (u_flag || a_flag)
|
||||
if (u_flag || a_flag)
|
||||
change_active(partition);
|
||||
|
||||
if (u_flag || a_flag) {
|
||||
printf("\nWe haven't changed the partition table yet. ");
|
||||
printf("This is your last chance.\n");
|
||||
if (u_flag || a_flag) {
|
||||
if (!t_flag)
|
||||
{
|
||||
printf("\nWe haven't changed the partition table yet. ");
|
||||
printf("This is your last chance.\n");
|
||||
}
|
||||
print_s0(-1);
|
||||
if (ok("Should we write new partition table?"))
|
||||
if (!t_flag)
|
||||
{
|
||||
if (ok("Should we write new partition table?"))
|
||||
write_s0();
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n-t flag specified -- partition table not written.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
usage:
|
||||
printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n");
|
||||
printf("fdisk {-a|-i|-u} [-f <config file> [-t] [-v]] [-{0,1,2,3}] [disk]\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -359,14 +444,22 @@ struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
|
||||
,partp->dp_ehd);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_boot(void)
|
||||
{
|
||||
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
|
||||
mboot.signature = BOOT_MAGIC;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_sector0(unsigned long start)
|
||||
{
|
||||
struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
|
||||
unsigned long size = disksecs - start;
|
||||
|
||||
memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
|
||||
mboot.signature = BOOT_MAGIC;
|
||||
init_boot();
|
||||
|
||||
partp->dp_typ = DOSPTYP_386BSD;
|
||||
partp->dp_flag = ACTIVE;
|
||||
@ -490,6 +583,7 @@ get_params_to_use()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************\
|
||||
* Change real numbers into strange dos numbers *
|
||||
\***********************************************/
|
||||
@ -779,3 +873,425 @@ get_type(int type)
|
||||
}
|
||||
return("unknown");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
parse_config_line(line, command)
|
||||
char *line;
|
||||
CMD *command;
|
||||
{
|
||||
char *cp, *end;
|
||||
|
||||
cp = line;
|
||||
while (1) /* dirty trick used to insure one exit point for this
|
||||
function */
|
||||
{
|
||||
memset(command, 0, sizeof(*command));
|
||||
|
||||
while (isspace(*cp)) ++cp;
|
||||
if (*cp == '\0' || *cp == '#')
|
||||
{
|
||||
break;
|
||||
}
|
||||
command->cmd = *cp++;
|
||||
|
||||
/*
|
||||
* Parse args
|
||||
*/
|
||||
while (1)
|
||||
{
|
||||
while (isspace(*cp)) ++cp;
|
||||
if (*cp == '#')
|
||||
{
|
||||
break; /* found comment */
|
||||
}
|
||||
if (isalpha(*cp))
|
||||
{
|
||||
command->args[command->n_args].argtype = *cp++;
|
||||
}
|
||||
if (!isdigit(*cp))
|
||||
{
|
||||
break; /* assume end of line */
|
||||
}
|
||||
end = NULL;
|
||||
command->args[command->n_args].arg_val = strtol(cp, &end, 0);
|
||||
if (cp == end)
|
||||
{
|
||||
break; /* couldn't parse number */
|
||||
}
|
||||
cp = end;
|
||||
command->n_args++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_geometry(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 1, i;
|
||||
|
||||
while (1)
|
||||
{
|
||||
geom_processed = 1;
|
||||
if (part_processed)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: the geometry specification line must occur before\n\
|
||||
all partition specifications.\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
if (command->n_args != 3)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of geometry args\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
dos_cyls = -1;
|
||||
dos_heads = -1;
|
||||
dos_sectors = -1;
|
||||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
switch (command->args[i].argtype)
|
||||
{
|
||||
case 'c':
|
||||
dos_cyls = command->args[i].arg_val;
|
||||
break;
|
||||
case 'h':
|
||||
dos_heads = command->args[i].arg_val;
|
||||
break;
|
||||
case 's':
|
||||
dos_sectors = command->args[i].arg_val;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: unknown geometry arg type: '%c' (0x%02x)\n",
|
||||
name, current_line_number, command->args[i].argtype,
|
||||
command->args[i].argtype);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
dos_cylsecs = dos_heads * dos_sectors;
|
||||
|
||||
/*
|
||||
* Do sanity checks on parameter values
|
||||
*/
|
||||
if (dos_cyls < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of cylinders not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
if (dos_cyls == 0 || dos_cyls > 1024)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: WARNING line %d: number of cylinders (%d) may be out-of-range\n\
|
||||
(must be within 1-1024 for normal BIOS operation, unless the entire disk\n\
|
||||
is dedicated to FreeBSD).\n",
|
||||
name, current_line_number, dos_cyls);
|
||||
}
|
||||
|
||||
if (dos_heads < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of heads not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
else if (dos_heads < 1 || dos_heads > 256)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of heads must be within (1-256)\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (dos_sectors < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: number of sectors not specified\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
else if (dos_sectors < 1 || dos_sectors > 63)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: number of sectors must be within (1-63)\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_partition(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 0, partition;
|
||||
unsigned long chunks, adj_size, max_end;
|
||||
struct dos_partition *partp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
part_processed = 1;
|
||||
if (command->n_args != 4)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of partition args\n",
|
||||
name, current_line_number);
|
||||
break;
|
||||
}
|
||||
partition = command->args[0].arg_val;
|
||||
if (partition < 0 || partition > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
partp = ((struct dos_partition *) &mboot.parts) + partition;
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
partp->dp_typ = command->args[1].arg_val;
|
||||
partp->dp_start = command->args[2].arg_val;
|
||||
partp->dp_size = command->args[3].arg_val;
|
||||
max_end = partp->dp_start + partp->dp_size;
|
||||
|
||||
if (partp->dp_typ == 0)
|
||||
{
|
||||
/*
|
||||
* Get out, the partition is marked as unused.
|
||||
*/
|
||||
/*
|
||||
* Insure that it's unused.
|
||||
*/
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust start upwards, if necessary, to fall on an head boundary.
|
||||
*/
|
||||
if (partp->dp_start % dos_sectors != 0)
|
||||
{
|
||||
adj_size =
|
||||
(partp->dp_start / dos_sectors + 1) * dos_sectors;
|
||||
if (adj_size > max_end)
|
||||
{
|
||||
/*
|
||||
* Can't go past end of partition
|
||||
*/
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: unable to adjust start of partition %d to fall on\n\
|
||||
a cylinder boundary.\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"%s: WARNING: adjusting start offset of partition '%d' from %d\n\
|
||||
to %d, to round to an head boundary.\n",
|
||||
name, partition, partp->dp_start, adj_size);
|
||||
partp->dp_start = adj_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust size downwards, if necessary, to fall on a cylinder
|
||||
* boundary.
|
||||
*/
|
||||
chunks =
|
||||
((partp->dp_start + partp->dp_size) / dos_cylsecs) * dos_cylsecs;
|
||||
adj_size = chunks - partp->dp_start;
|
||||
if (adj_size != partp->dp_size)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: WARNING: adjusting size of partition '%d' from %d to %d,\n\
|
||||
to round to a cylinder boundary.\n",
|
||||
name, partition, partp->dp_size, adj_size);
|
||||
if (chunks > 0)
|
||||
{
|
||||
partp->dp_size = adj_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
partp->dp_size = 0;
|
||||
}
|
||||
}
|
||||
if (partp->dp_size < 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: size for partition '%d' is zero.\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
|
||||
dos(partp->dp_start, partp->dp_size,
|
||||
&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
|
||||
dos(partp->dp_start+partp->dp_size - 1, partp->dp_size,
|
||||
&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_active(command)
|
||||
CMD *command;
|
||||
{
|
||||
int status = 0, partition, i;
|
||||
struct dos_partition *partp;
|
||||
|
||||
while (1)
|
||||
{
|
||||
active_processed = 1;
|
||||
if (command->n_args != 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"%s: ERROR line %d: incorrect number of active args\n",
|
||||
name, current_line_number);
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
partition = command->args[0].arg_val;
|
||||
if (partition < 0 || partition > 3)
|
||||
{
|
||||
fprintf(stderr, "%s: ERROR line %d: invalid partition number %d\n",
|
||||
name, current_line_number, partition);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Reset active partition
|
||||
*/
|
||||
partp = ((struct dos_partition *) &mboot.parts);
|
||||
for (i = 0; i < NDOSPART; i++)
|
||||
partp[i].dp_flag = 0;
|
||||
partp[partition].dp_flag = ACTIVE;
|
||||
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
process_line(line)
|
||||
char *line;
|
||||
{
|
||||
CMD command;
|
||||
int status = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
parse_config_line(line, &command);
|
||||
switch (command.cmd)
|
||||
{
|
||||
case 0:
|
||||
/*
|
||||
* Comment or blank line
|
||||
*/
|
||||
break;
|
||||
case 'g':
|
||||
/*
|
||||
* Set geometry
|
||||
*/
|
||||
status = process_geometry(&command);
|
||||
break;
|
||||
case 'p':
|
||||
status = process_partition(&command);
|
||||
break;
|
||||
case 'a':
|
||||
status = process_active(&command);
|
||||
break;
|
||||
default:
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
read_config(config_file)
|
||||
char *config_file;
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int status = 1;
|
||||
char buf[1010];
|
||||
|
||||
while (1) /* dirty trick used to insure one exit point for this
|
||||
function */
|
||||
{
|
||||
if (strcmp(config_file, "-") != 0)
|
||||
{
|
||||
/*
|
||||
* We're not reading from stdin
|
||||
*/
|
||||
if ((fp = fopen(config_file, "r")) == NULL)
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = stdin;
|
||||
}
|
||||
current_line_number = 0;
|
||||
while (!feof(fp))
|
||||
{
|
||||
if (fgets(buf, sizeof(buf), fp) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
++current_line_number;
|
||||
status = process_line(buf);
|
||||
if (status == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fp)
|
||||
{
|
||||
/*
|
||||
* It doesn't matter if we're reading from stdin, as we've reached EOF
|
||||
*/
|
||||
fclose(fp);
|
||||
}
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
reset_boot(void)
|
||||
{
|
||||
int i;
|
||||
struct dos_partition *partp;
|
||||
|
||||
init_boot();
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
partp = ((struct dos_partition *) &mboot.parts) + i;
|
||||
bzero((char *)partp, sizeof (struct dos_partition));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user