#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 #include 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; } } }