404 lines
8.6 KiB
C
Executable File
404 lines
8.6 KiB
C
Executable File
|
|
#ifndef lint
|
|
#pragma ident "@(#)modify_partition.c 1.12 95/04/10 SMI"
|
|
#endif lint
|
|
|
|
/*
|
|
* Copyright (c) 1991 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
* This file contains functions to implement the partition menu commands.
|
|
*/
|
|
#include "global.h"
|
|
#include "partition.h"
|
|
#include "menu_partition.h"
|
|
#include "menu_command.h"
|
|
#include "modify_partition.h"
|
|
#include "checkmount.h"
|
|
#include "misc.h"
|
|
#include "label.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
char *partn_list[] = { "0", "1", "2", "3", "4", "5", "6", "7", NULL };
|
|
|
|
char *sel_list[] = { "0", "1", "2", "3", NULL };
|
|
|
|
|
|
/*
|
|
* Mnemonics for the partitions we recognize
|
|
*/
|
|
#define A_PARTITION 0
|
|
#define B_PARTITION 1
|
|
#define C_PARTITION 2
|
|
#define D_PARTITION 3
|
|
#define E_PARTITION 4
|
|
#define F_PARTITION 5
|
|
#define G_PARTITION 6
|
|
#define H_PARTITION 7
|
|
#define I_PARTITION 8
|
|
#define J_PARTITION 9
|
|
|
|
|
|
#define MBYTE (1024*1024)
|
|
|
|
|
|
/*
|
|
* Modify/Create a predefined partition table.
|
|
*/
|
|
int
|
|
p_modify()
|
|
{
|
|
struct partition_info tmp_pinfo[1];
|
|
struct dk_map *map = tmp_pinfo->pinfo_map;
|
|
u_ioparam_t ioparam;
|
|
int inpt_dflt = 0;
|
|
int free_hog = -1;
|
|
int i;
|
|
char tmpstr[80];
|
|
char tmpstr2[300];
|
|
int sel_type = 0;
|
|
|
|
/*
|
|
* There must be a current disk type (and therefore a current disk).
|
|
*/
|
|
if (cur_dtype == NULL) {
|
|
err_print("Current Disk Type is not set.\n");
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* If the disk has mounted partitions, cannot modify
|
|
*/
|
|
if (checkmount((daddr_t)-1, (daddr_t)-1)) {
|
|
err_print(
|
|
"Cannot modify disk partitions while it has mounted partitions.\n\n");
|
|
return (-1);
|
|
}
|
|
/*
|
|
* prompt user for a partition table base
|
|
*/
|
|
if (cur_parts->pinfo_name != NULL) {
|
|
(void) sprintf(tmpstr,
|
|
"\t0. Current partition table (%s)",
|
|
cur_parts->pinfo_name);
|
|
} else {
|
|
(void) sprintf(tmpstr,
|
|
"\t0. Current partition table (unnamed)");
|
|
}
|
|
|
|
(void) sprintf(tmpstr2,
|
|
"Select partitioning base:\n%s\n"
|
|
"\t1. All Free Hog\n"
|
|
"Choose base (enter number) ",
|
|
tmpstr);
|
|
|
|
ioparam.io_charlist = sel_list;
|
|
sel_type = input(FIO_MSTR, tmpstr2, '?', &ioparam,
|
|
&sel_type, DATA_INPUT);
|
|
|
|
if (sel_type == 0) {
|
|
/*
|
|
* Check for invalid parameters but do
|
|
* not modify the table.
|
|
*/
|
|
if (check_map(cur_parts->pinfo_map)) {
|
|
err_print("\
|
|
Warning: Fix, or select a different partition table.\n");
|
|
return (0);
|
|
}
|
|
/*
|
|
* Create partition map from existing map
|
|
*/
|
|
tmp_pinfo->vtoc = cur_parts->vtoc;
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
map[i].dkl_nblk = cur_parts->pinfo_map[i].dkl_nblk;
|
|
map[i].dkl_cylno = cur_parts->pinfo_map[i].dkl_cylno;
|
|
}
|
|
} else {
|
|
/*
|
|
* Make an empty partition map, with all the space
|
|
* in the c partition.
|
|
*/
|
|
set_vtoc_defaults(tmp_pinfo);
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
map[i].dkl_nblk = 0;
|
|
map[i].dkl_cylno = 0;
|
|
}
|
|
map[C_PARTITION].dkl_nblk = ncyl * spc();
|
|
#ifdef i386
|
|
/*
|
|
* Adjust for the boot and possibly alternates partitions
|
|
*/
|
|
map[I_PARTITION].dkl_nblk = spc();
|
|
map[I_PARTITION].dkl_cylno = 0;
|
|
if (cur_ctype->ctype_ctype != DKC_SCSI_CCS) {
|
|
map[J_PARTITION].dkl_nblk = 2 * spc();
|
|
map[J_PARTITION].dkl_cylno = spc() / spc();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
fmt_print("\n");
|
|
print_map(tmp_pinfo);
|
|
|
|
ioparam.io_charlist = confirm_list;
|
|
if (input(FIO_MSTR,
|
|
"Do you wish to continue creating a new partition\ntable based on above table",
|
|
'?', &ioparam, &inpt_dflt, DATA_INPUT)) {
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* get Free Hog partition
|
|
*/
|
|
inpt_dflt = 1;
|
|
while (free_hog < 0) {
|
|
free_hog = G_PARTITION; /* default to g partition */
|
|
ioparam.io_charlist = partn_list;
|
|
free_hog = input(FIO_MSTR, "Free Hog partition", '?',
|
|
&ioparam, &free_hog, DATA_INPUT);
|
|
/* disallow c partition */
|
|
if (free_hog == C_PARTITION) {
|
|
fmt_print("'%c' cannot be the 'Free Hog' partition.\n",
|
|
C_PARTITION + PARTITION_BASE);
|
|
free_hog = -1;
|
|
continue;
|
|
}
|
|
/*
|
|
* If user selected all float set the
|
|
* float to be the whole disk.
|
|
*/
|
|
if (sel_type == 1) {
|
|
map[free_hog].dkl_nblk = map[C_PARTITION].dkl_nblk;
|
|
#ifdef i386
|
|
map[free_hog].dkl_nblk -= map[I_PARTITION].dkl_nblk;
|
|
if (cur_ctype->ctype_ctype != DKC_SCSI_CCS) {
|
|
map[free_hog].dkl_nblk -=
|
|
map[J_PARTITION].dkl_nblk;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
/*
|
|
* Warn the user if there is no free space in
|
|
* the float partition.
|
|
*/
|
|
if (map[free_hog].dkl_nblk == 0) {
|
|
err_print("\
|
|
Warning: No space available from Free Hog partition.\n");
|
|
ioparam.io_charlist = confirm_list;
|
|
if (input(FIO_MSTR, "Continue", '?',
|
|
&ioparam, &inpt_dflt, DATA_INPUT)) {
|
|
free_hog = -1;
|
|
}
|
|
}
|
|
}
|
|
inpt_dflt = 0;
|
|
|
|
/*
|
|
* get user modified partition table
|
|
*/
|
|
get_user_map(map, free_hog);
|
|
|
|
/*
|
|
* Update cylno offsets
|
|
*/
|
|
adj_cyl_offset(map);
|
|
|
|
fmt_print("\n");
|
|
print_map(tmp_pinfo);
|
|
|
|
ioparam.io_charlist = confirm_list;
|
|
if (input(FIO_MSTR, "\
|
|
Okay to make this the current partition table", '?',
|
|
&ioparam, &inpt_dflt, DATA_INPUT)) {
|
|
return (0);
|
|
} else {
|
|
make_partition();
|
|
/*
|
|
* Update new partition map
|
|
*/
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
cur_parts->pinfo_map[i].dkl_nblk = map[i].dkl_nblk;
|
|
cur_parts->pinfo_map[i].dkl_cylno = map[i].dkl_cylno;
|
|
#ifdef i386
|
|
cur_parts->vtoc.v_part[i].p_start =
|
|
map[i].dkl_cylno * nhead * nsect;
|
|
cur_parts->vtoc.v_part[i].p_size =
|
|
map[i].dkl_nblk;
|
|
#endif
|
|
}
|
|
(void) p_name();
|
|
|
|
/*
|
|
* Label the disk now
|
|
*/
|
|
if (check("Ready to label disk, continue")) {
|
|
return (-1);
|
|
}
|
|
fmt_print("\n");
|
|
if (write_label()) {
|
|
err_print("Writing label failed\n");
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Adjust cylinder offsets
|
|
*/
|
|
void
|
|
adj_cyl_offset(map)
|
|
struct dk_map *map;
|
|
{
|
|
int i;
|
|
int cyloffset = 0;
|
|
|
|
|
|
/*
|
|
* Update cylno offsets
|
|
*/
|
|
#ifdef i386
|
|
/*
|
|
* Correct cylinder allocation for having the boot and alternates
|
|
* slice in the beginning of the disk
|
|
*/
|
|
for (i = NDKMAP/2; i < NDKMAP; i++) {
|
|
if (i != C_PARTITION && map[i].dkl_nblk) {
|
|
map[i].dkl_cylno = cyloffset;
|
|
cyloffset += (map[i].dkl_nblk + (spc()-1))/spc();
|
|
} else if (map[i].dkl_nblk == 0) {
|
|
map[i].dkl_cylno = 0;
|
|
}
|
|
}
|
|
for (i = 0; i < NDKMAP/2; i++) {
|
|
#else
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
#endif
|
|
if (i != C_PARTITION && map[i].dkl_nblk) {
|
|
map[i].dkl_cylno = cyloffset;
|
|
cyloffset += (map[i].dkl_nblk + (spc()-1))/spc();
|
|
} else if (map[i].dkl_nblk == 0) {
|
|
map[i].dkl_cylno = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Check partition table
|
|
*/
|
|
int
|
|
check_map(map)
|
|
struct dk_map *map;
|
|
{
|
|
int i;
|
|
int cyloffset = 0;
|
|
int tot_blks = 0;
|
|
|
|
#ifdef i386
|
|
/*
|
|
* On x86, we must account for the boot and alternates
|
|
*/
|
|
cyloffset = map[0].dkl_cylno;
|
|
tot_blks = map[0].dkl_nblk;
|
|
#endif
|
|
|
|
/*
|
|
* Do some checks for invalid parameters but do
|
|
* not modify the table.
|
|
*/
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
if (map[i].dkl_cylno < 0 ||
|
|
map[i].dkl_cylno > (daddr_t)ncyl-1) {
|
|
err_print("\
|
|
Warning: Partition %c starting cylinder %d is out of range.\n",
|
|
(PARTITION_BASE+i), map[i].dkl_cylno);
|
|
return (-1);
|
|
}
|
|
if (map[i].dkl_nblk < 0 || map[i].dkl_nblk > (daddr_t)(ncyl -
|
|
map[i].dkl_cylno) * spc()) {
|
|
err_print("\
|
|
Warning: Partition %c, specified # of blocks, %d, is out of range.\n",
|
|
(PARTITION_BASE+i), map[i].dkl_nblk);
|
|
return (-1);
|
|
}
|
|
if (i != C_PARTITION && map[i].dkl_nblk) {
|
|
#ifdef i386
|
|
if (i == I_PARTITION || i == J_PARTITION)
|
|
continue;
|
|
#endif
|
|
if (map[i].dkl_cylno < cyloffset) {
|
|
err_print(
|
|
"Warning: Overlapping partition (%c) in table.\n", PARTITION_BASE+i);
|
|
return (-1);
|
|
} else if (map[i].dkl_cylno > cyloffset) {
|
|
err_print(
|
|
"Warning: Non-contiguous partition (%c) in table.\n", PARTITION_BASE+i);
|
|
}
|
|
cyloffset += (map[i].dkl_nblk + (spc()-1))/spc();
|
|
tot_blks = map[i].dkl_nblk;
|
|
}
|
|
}
|
|
if (tot_blks > map[C_PARTITION].dkl_nblk) {
|
|
err_print("\
|
|
Warning: Total blocks used is greater than number of blocks in '%c'\n\
|
|
\tpartition.\n", C_PARTITION + PARTITION_BASE);
|
|
return (-1);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* get user defined partitions
|
|
*/
|
|
void
|
|
get_user_map(map, float_part)
|
|
struct dk_map *map;
|
|
int float_part;
|
|
{
|
|
int i;
|
|
int newsize;
|
|
int deflt;
|
|
char tmpstr[80];
|
|
u_ioparam_t ioparam;
|
|
|
|
/*
|
|
* Get partition sizes
|
|
*/
|
|
for (i = 0; i < NDKMAP; i++) {
|
|
if (partn_list[i] == NULL)
|
|
break;
|
|
if ((i == C_PARTITION) || (i == float_part))
|
|
continue;
|
|
else {
|
|
ioparam.io_bounds.lower = 0;
|
|
ioparam.io_bounds.upper = map[i].dkl_nblk +
|
|
map[float_part].dkl_nblk;
|
|
deflt = map[i].dkl_nblk;
|
|
if (ioparam.io_bounds.upper == 0) {
|
|
err_print("\
|
|
Warning: no space available for '%s' from Free Hog partition\n",
|
|
partn_list[i]);
|
|
continue;
|
|
}
|
|
(void) sprintf(tmpstr,
|
|
"Enter size of partition '%s' ",
|
|
partn_list[i]);
|
|
newsize = input(FIO_CYL, tmpstr, ':',
|
|
&ioparam, &deflt, DATA_INPUT);
|
|
map[float_part].dkl_nblk -= (newsize - map[i].dkl_nblk);
|
|
map[i].dkl_nblk = newsize;
|
|
}
|
|
}
|
|
}
|