#include "global.h"
#include <stdlib.h>
#include <string.h>
#include "partition.h"
#include "menu_partition.h"
#include "menu_command.h"
#include "misc.h"
#include "param.h"
static void nspaces(int);
static int ndigits(uint64_t);
int
p_apart(void)
{
change_partition(0);
return (0);
}
int
p_bpart(void)
{
change_partition(1);
return (0);
}
int
p_cpart(void)
{
change_partition(2);
return (0);
}
int
p_dpart(void)
{
change_partition(3);
return (0);
}
int
p_epart(void)
{
change_partition(4);
return (0);
}
int
p_fpart(void)
{
change_partition(5);
return (0);
}
int
p_gpart(void)
{
change_partition(6);
return (0);
}
int
p_hpart(void)
{
change_partition(7);
return (0);
}
int
p_ipart(void)
{
change_partition(8);
return (0);
}
#if defined(i386)
int
p_jpart(void)
{
change_partition(9);
return (0);
}
#endif
int
p_expand(void)
{
uint64_t delta;
uint_t nparts;
struct dk_gpt *efi_label = cur_parts->etoc;
if (cur_parts->etoc->efi_altern_lba == 1 ||
(cur_parts->etoc->efi_altern_lba >=
cur_parts->etoc->efi_last_lba)) {
err_print("Warning: No expanded capacity is found.\n");
return (0);
}
delta = efi_label->efi_last_lba - efi_label->efi_altern_lba;
nparts = efi_label->efi_nparts;
enter_critical();
efi_label->efi_parts[nparts - 1].p_start += delta;
efi_label->efi_last_u_lba += delta;
efi_label->efi_altern_lba = cur_parts->etoc->efi_last_lba;
exit_critical();
fmt_print("The expanded capacity is added to the unallocated space.\n");
return (0);
}
int
p_select(void)
{
struct partition_info *pptr, *parts;
u_ioparam_t ioparam;
int i, index, deflt, *defltptr = NULL;
blkaddr_t b_cylno;
#if defined(i386)
blkaddr_t cyl_offset;
#endif
parts = cur_dtype->dtype_plist;
if (parts == NULL) {
err_print("No defined partition tables.\n");
return (-1);
}
for (i = 0, pptr = parts; pptr != NULL; pptr = pptr->pinfo_next) {
if (cur_parts == pptr) {
deflt = i;
defltptr = &deflt;
}
if (pptr->pinfo_name == NULL)
fmt_print(" %d. unnamed\n", i++);
else
fmt_print(" %d. %s\n", i++, pptr->pinfo_name);
}
ioparam.io_bounds.lower = 0;
ioparam.io_bounds.upper = i - 1;
index = input(FIO_INT, "Specify table (enter its number)", ':',
&ioparam, defltptr, DATA_INPUT);
for (i = 0, pptr = parts; i < index; i++, pptr = pptr->pinfo_next)
;
if (cur_label == L_TYPE_EFI) {
enter_critical();
cur_disk->disk_parts = cur_parts = pptr;
exit_critical();
fmt_print("\n");
return (0);
}
#if defined(i386)
cyl_offset = pptr->pinfo_map[I_PARTITION].dkl_cylno + 1;
if (pptr->pinfo_map[J_PARTITION].dkl_nblk != 0) {
cyl_offset = pptr->pinfo_map[J_PARTITION].dkl_cylno +
((pptr->pinfo_map[J_PARTITION].dkl_nblk +
(spc() - 1)) / spc());
}
#else
b_cylno = 0;
#endif
for (i = 0; i < NDKMAP; i++) {
#if defined(i386)
if (i == I_PARTITION || i == J_PARTITION || i == C_PARTITION) {
b_cylno = 0;
} else if (pptr->pinfo_map[i].dkl_nblk == 0) {
b_cylno = 0;
} else {
b_cylno = cyl_offset;
}
#endif
if (pptr->pinfo_map[i].dkl_cylno < b_cylno ||
pptr->pinfo_map[i].dkl_cylno > (ncyl-1)) {
err_print("partition %c: starting cylinder %d is out "
"of range\n", (PARTITION_BASE + i),
pptr->pinfo_map[i].dkl_cylno);
return (0);
}
if (pptr->pinfo_map[i].dkl_nblk > ((ncyl -
pptr->pinfo_map[i].dkl_cylno) * spc())) {
err_print(
"partition %c: specified # of blocks, %u, "
"is out of range\n",
(PARTITION_BASE+i),
pptr->pinfo_map[i].dkl_nblk);
return (0);
}
}
enter_critical();
if (cur_parts != NULL && cur_parts != pptr &&
cur_parts->pinfo_name == NULL)
delete_partition(cur_parts);
cur_disk->disk_parts = cur_parts = pptr;
#if defined(_SUNOS_VTOC_16)
for (i = 0; i < NDKMAP; i++) {
cur_parts->vtoc.v_part[i].p_start =
(blkaddr_t)(cur_parts->pinfo_map[i].dkl_cylno *
(nhead * nsect));
cur_parts->vtoc.v_part[i].p_size =
(blkaddr_t)cur_parts->pinfo_map[i].dkl_nblk;
}
#endif
exit_critical();
fmt_print("\n");
return (0);
}
int
p_name(void)
{
char *name;
if (cur_parts == NULL) {
err_print("Current Disk has no partition table.\n");
return (-1);
}
name = (char *)(uintptr_t)input(FIO_OSTR,
"Enter table name (remember quotes)",
':', NULL, NULL, DATA_INPUT);
enter_critical();
if (cur_parts->pinfo_name != NULL)
destroy_data(cur_parts->pinfo_name);
cur_parts->pinfo_name = name;
exit_critical();
fmt_print("\n");
return (0);
}
int
p_print(void)
{
if (cur_parts == NULL) {
err_print("Current Disk has no partition table.\n");
return (-1);
}
if (chk_volname(cur_disk)) {
fmt_print("Volume: ");
print_volname(cur_disk);
fmt_print("\n");
}
if ((cur_parts->pinfo_name != NULL) && (cur_label == L_TYPE_SOLARIS)) {
fmt_print("Current partition table (%s):\n",
cur_parts->pinfo_name);
fmt_print("Total disk cylinders available: %d + %d "
"(reserved cylinders)\n\n", ncyl, acyl);
} else if (cur_label == L_TYPE_SOLARIS) {
fmt_print("Current partition table (unnamed):\n");
fmt_print("Total disk cylinders available: %d + %d "
"(reserved cylinders)\n\n", ncyl, acyl);
} else if (cur_label == L_TYPE_EFI) {
unsigned reserved;
reserved = efi_reserved_sectors(cur_parts->etoc);
fmt_print("Current partition table (%s):\n",
cur_parts->pinfo_name != NULL ?
cur_parts->pinfo_name : "unnamed");
fmt_print("Total disk sectors available: %llu + %u "
"(reserved sectors)\n\n",
cur_parts->etoc->efi_last_u_lba - reserved -
cur_parts->etoc->efi_first_u_lba + 1, reserved);
}
print_map(cur_parts);
return (0);
}
void
print_map(struct partition_info *map)
{
int i;
int want_header;
struct dk_gpt *vtoc64;
if (cur_label == L_TYPE_EFI) {
vtoc64 = map->etoc;
want_header = 1;
for (i = 0; i < vtoc64->efi_nparts; i++) {
if (i >= 7 && !expert_mode &&
((int)vtoc64->efi_parts[i].p_tag !=
V_RESERVED)) {
continue;
}
print_efi_partition(vtoc64, i, want_header);
want_header = 0;
}
fmt_print("\n");
return;
}
want_header = 1;
for (i = 0; i < NDKMAP; i++) {
if (i > 9) {
break;
}
print_partition(map, i, want_header);
want_header = 0;
}
fmt_print("\n");
}
void
print_efi_partition(struct dk_gpt *map, int partnum, int want_header)
{
int ncyl2_digits = 0;
float scaled;
char *s;
uint64_t secsize;
ncyl2_digits = ndigits(map->efi_last_u_lba);
if (want_header) {
fmt_print("Part ");
fmt_print("Tag Flag ");
fmt_print("First Sector");
nspaces(ncyl2_digits);
fmt_print("Size");
nspaces(ncyl2_digits);
fmt_print("Last Sector\n");
}
fmt_print(" %d ", partnum);
s = find_string(ptag_choices, (int)map->efi_parts[partnum].p_tag);
if (s == NULL)
s = "-";
nspaces(10 - (int)strlen(s));
fmt_print("%s", s);
s = find_string(pflag_choices, (int)map->efi_parts[partnum].p_flag);
if (s == NULL)
s = "-";
nspaces(6 - (int)strlen(s));
fmt_print("%s", s);
nspaces(2);
secsize = map->efi_parts[partnum].p_size;
if (secsize == 0) {
fmt_print("%16llu", map->efi_parts[partnum].p_start);
nspaces(ncyl2_digits);
fmt_print(" 0 ");
} else {
fmt_print("%16llu", map->efi_parts[partnum].p_start);
scaled = bn2mb(secsize);
nspaces(ncyl2_digits - 5);
if (scaled >= (float)1024.0 * 1024) {
fmt_print("%8.2fTB", scaled/((float)1024.0 * 1024));
} else if (scaled >= (float)1024.0) {
fmt_print("%8.2fGB", scaled/(float)1024.0);
} else {
fmt_print("%8.2fMB", scaled);
}
}
nspaces(ncyl2_digits);
if ((map->efi_parts[partnum].p_start + secsize - 1) == UINT_MAX64) {
fmt_print(" 0 \n");
} else {
fmt_print(" %llu \n",
map->efi_parts[partnum].p_start + secsize - 1);
}
}
void
print_partition(struct partition_info *pinfo, int partnum, int want_header)
{
int i;
blkaddr_t nblks;
int cyl1;
int cyl2;
float scaled;
int maxcyl2;
int ncyl2_digits;
char *s;
blkaddr_t maxnblks = 0;
blkaddr_t len;
maxcyl2 = 0;
for (i = 0; i < NDKMAP; i++) {
nblks = (uint_t)pinfo->pinfo_map[i].dkl_nblk;
cyl1 = pinfo->pinfo_map[i].dkl_cylno;
cyl2 = cyl1 + (nblks / spc()) - 1;
if (nblks > 0) {
maxcyl2 = max(cyl2, maxcyl2);
maxnblks = max(nblks, maxnblks);
}
}
ncyl2_digits = ndigits(maxcyl2);
if (want_header) {
fmt_print("Part ");
fmt_print("Tag Flag ");
fmt_print("Cylinders");
nspaces(ncyl2_digits);
fmt_print(" Size Blocks\n");
}
nblks = pinfo->pinfo_map[partnum].dkl_nblk;
cyl1 = pinfo->pinfo_map[partnum].dkl_cylno;
cyl2 = cyl1 + (nblks / spc()) - 1;
fmt_print(" %x ", partnum);
s = find_string(ptag_choices, (int)pinfo->vtoc.v_part[partnum].p_tag);
if (s == NULL)
s = "-";
nspaces(10 - (int)strlen(s));
fmt_print("%s", s);
s = find_string(pflag_choices, (int)pinfo->vtoc.v_part[partnum].p_flag);
if (s == NULL)
s = "-";
nspaces(6 - (int)strlen(s));
fmt_print("%s", s);
nspaces(2);
if (nblks == 0) {
fmt_print("%6d ", cyl1);
nspaces(ncyl2_digits);
fmt_print(" 0 ");
} else {
fmt_print("%6d - ", cyl1);
nspaces(ncyl2_digits - ndigits(cyl2));
fmt_print("%d ", cyl2);
scaled = bn2mb(nblks);
if (scaled > (float)1024.0 * 1024.0) {
fmt_print("%8.2fTB ",
scaled/((float)1024.0 * 1024.0));
} else if (scaled > (float)1024.0) {
fmt_print("%8.2fGB ", scaled/(float)1024.0);
} else {
fmt_print("%8.2fMB ", scaled);
}
}
fmt_print("(");
pr_dblock(fmt_print, nblks);
fmt_print(")");
nspaces(ndigits(maxnblks/spc()) - ndigits(nblks/spc()));
len = strlen(" %") + ndigits(ndigits(maxnblks)) + strlen("d\n") + 1;
s = zalloc(len);
(void) snprintf(s, len, "%s%u%s", " %", ndigits(maxnblks), "u\n");
fmt_print(s, nblks);
(void) free(s);
}
int
chk_volname(struct disk_info *disk)
{
return (disk->v_volume[0] != 0);
}
void
print_volname(struct disk_info *disk)
{
int i;
char *p;
p = disk->v_volume;
for (i = 0; i < LEN_DKL_VVOL; i++, p++) {
if (*p == 0)
break;
fmt_print("%c", *p);
}
}
static void
nspaces(int n)
{
while (n-- > 0)
fmt_print(" ");
}
static int
ndigits(uint64_t n)
{
int i;
i = 0;
while (n > 0) {
n /= 10;
i++;
}
return (i == 0 ? 1 : i);
}