17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5af007057Syl  * Common Development and Distribution License (the "License").
6af007057Syl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
223a5b922fSbo zhou - Sun Microsystems - Beijing China  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * This file contains functions to implement the partition menu commands.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate #include "global.h"
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "partition.h"
337c478bd9Sstevel@tonic-gate #include "menu_partition.h"
347c478bd9Sstevel@tonic-gate #include "menu_command.h"
357c478bd9Sstevel@tonic-gate #include "misc.h"
367c478bd9Sstevel@tonic-gate #include "param.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate static void	nspaces(int);
397c478bd9Sstevel@tonic-gate static int	ndigits(uint64_t);
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate /*
427c478bd9Sstevel@tonic-gate  * This routine implements the 'a' command.  It changes the 'a' partition.
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate int
p_apart(void)45edbad4feSToomas Soome p_apart(void)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	change_partition(0);
497c478bd9Sstevel@tonic-gate 	return (0);
507c478bd9Sstevel@tonic-gate }
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * This routine implements the 'b' command.  It changes the 'b' partition.
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate int
p_bpart(void)56edbad4feSToomas Soome p_bpart(void)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	change_partition(1);
607c478bd9Sstevel@tonic-gate 	return (0);
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate  * This routine implements the 'c' command.  It changes the 'c' partition.
657c478bd9Sstevel@tonic-gate  */
667c478bd9Sstevel@tonic-gate int
p_cpart(void)67edbad4feSToomas Soome p_cpart(void)
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	change_partition(2);
717c478bd9Sstevel@tonic-gate 	return (0);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * This routine implements the 'd' command.  It changes the 'd' partition.
767c478bd9Sstevel@tonic-gate  */
777c478bd9Sstevel@tonic-gate int
p_dpart(void)78edbad4feSToomas Soome p_dpart(void)
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	change_partition(3);
827c478bd9Sstevel@tonic-gate 	return (0);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate  * This routine implements the 'e' command.  It changes the 'e' partition.
877c478bd9Sstevel@tonic-gate  */
887c478bd9Sstevel@tonic-gate int
p_epart(void)89edbad4feSToomas Soome p_epart(void)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	change_partition(4);
937c478bd9Sstevel@tonic-gate 	return (0);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * This routine implements the 'f' command.  It changes the 'f' partition.
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate int
p_fpart(void)100edbad4feSToomas Soome p_fpart(void)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	change_partition(5);
1047c478bd9Sstevel@tonic-gate 	return (0);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * This routine implements the 'g' command.  It changes the 'g' partition.
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate int
p_gpart(void)111edbad4feSToomas Soome p_gpart(void)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	change_partition(6);
1157c478bd9Sstevel@tonic-gate 	return (0);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate  * This routine implements the 'h' command.  It changes the 'h' partition.
1207c478bd9Sstevel@tonic-gate  */
1217c478bd9Sstevel@tonic-gate int
p_hpart(void)122edbad4feSToomas Soome p_hpart(void)
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	change_partition(7);
1267c478bd9Sstevel@tonic-gate 	return (0);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate  * This routine implements the 'i' command. It is valid only for EFI
1317c478bd9Sstevel@tonic-gate  * labeled disks. This can be used only in expert mode.
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate int
p_ipart(void)134edbad4feSToomas Soome p_ipart(void)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	change_partition(8);
1377c478bd9Sstevel@tonic-gate 	return (0);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate #if defined(i386)
1417c478bd9Sstevel@tonic-gate /*
1427c478bd9Sstevel@tonic-gate  * This routine implements the 'j' command.  It changes the 'j' partition.
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@tonic-gate int
p_jpart(void)145edbad4feSToomas Soome p_jpart(void)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	change_partition(9);
1497c478bd9Sstevel@tonic-gate 	return (0);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate #endif	/* defined(i386) */
1527c478bd9Sstevel@tonic-gate 
153af007057Syl int
p_expand(void)154edbad4feSToomas Soome p_expand(void)
155af007057Syl {
156af007057Syl 	uint64_t delta;
157af007057Syl 	uint_t nparts;
158af007057Syl 	struct dk_gpt *efi_label = cur_parts->etoc;
159af007057Syl 
160af007057Syl 	if (cur_parts->etoc->efi_altern_lba == 1 ||
161af007057Syl 	    (cur_parts->etoc->efi_altern_lba >=
162af007057Syl 	    cur_parts->etoc->efi_last_lba)) {
163af007057Syl 		err_print("Warning: No expanded capacity is found.\n");
164af007057Syl 		return (0);
165af007057Syl 	}
166af007057Syl 
167af007057Syl 	delta = efi_label->efi_last_lba - efi_label->efi_altern_lba;
168af007057Syl 	nparts = efi_label->efi_nparts;
169af007057Syl 
170af007057Syl 	enter_critical();
171af007057Syl 	efi_label->efi_parts[nparts - 1].p_start += delta;
172af007057Syl 	efi_label->efi_last_u_lba += delta;
173af007057Syl 	efi_label->efi_altern_lba = cur_parts->etoc->efi_last_lba;
174af007057Syl 	exit_critical();
175af007057Syl 
176af007057Syl 	fmt_print("The expanded capacity is added to the unallocated space.\n");
177af007057Syl 	return (0);
178af007057Syl }
179af007057Syl 
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate  * This routine implements the 'select' command.  It allows the user
1827c478bd9Sstevel@tonic-gate  * to make a pre-defined partition map the current map.
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate int
p_select(void)185edbad4feSToomas Soome p_select(void)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	struct partition_info	*pptr, *parts;
1887c478bd9Sstevel@tonic-gate 	u_ioparam_t		ioparam;
1897c478bd9Sstevel@tonic-gate 	int			i, index, deflt, *defltptr = NULL;
190342440ecSPrasad Singamsetty 	blkaddr_t		b_cylno;
1917c478bd9Sstevel@tonic-gate #if defined(i386)
192342440ecSPrasad Singamsetty 	blkaddr_t		cyl_offset;
1937c478bd9Sstevel@tonic-gate #endif
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	parts = cur_dtype->dtype_plist;
1967c478bd9Sstevel@tonic-gate 	/*
1977c478bd9Sstevel@tonic-gate 	 * If there are no pre-defined maps for this disk type, it's
1987c478bd9Sstevel@tonic-gate 	 * an error.
1997c478bd9Sstevel@tonic-gate 	 */
2007c478bd9Sstevel@tonic-gate 	if (parts == NULL) {
2017c478bd9Sstevel@tonic-gate 		err_print("No defined partition tables.\n");
2027c478bd9Sstevel@tonic-gate 		return (-1);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/*
2067c478bd9Sstevel@tonic-gate 	 * Loop through the pre-defined maps and list them by name.  If
2077c478bd9Sstevel@tonic-gate 	 * the current map is one of them, make it the default.  If any
2087c478bd9Sstevel@tonic-gate 	 * the maps are unnamed, label them as such.
2097c478bd9Sstevel@tonic-gate 	 */
2107c478bd9Sstevel@tonic-gate 	for (i = 0, pptr = parts; pptr != NULL; pptr = pptr->pinfo_next) {
2117c478bd9Sstevel@tonic-gate 		if (cur_parts == pptr) {
2127c478bd9Sstevel@tonic-gate 			deflt = i;
2137c478bd9Sstevel@tonic-gate 			defltptr = &deflt;
2147c478bd9Sstevel@tonic-gate 		}
2157c478bd9Sstevel@tonic-gate 		if (pptr->pinfo_name == NULL)
2167c478bd9Sstevel@tonic-gate 			fmt_print("        %d. unnamed\n", i++);
2177c478bd9Sstevel@tonic-gate 		else
2187c478bd9Sstevel@tonic-gate 			fmt_print("        %d. %s\n", i++, pptr->pinfo_name);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.lower = 0;
2217c478bd9Sstevel@tonic-gate 	ioparam.io_bounds.upper = i - 1;
2227c478bd9Sstevel@tonic-gate 	/*
2237c478bd9Sstevel@tonic-gate 	 * Ask which map should be made current.
2247c478bd9Sstevel@tonic-gate 	 */
2257c478bd9Sstevel@tonic-gate 	index = input(FIO_INT, "Specify table (enter its number)", ':',
2267c478bd9Sstevel@tonic-gate 	    &ioparam, defltptr, DATA_INPUT);
2277c478bd9Sstevel@tonic-gate 	for (i = 0, pptr = parts; i < index; i++, pptr = pptr->pinfo_next)
2287c478bd9Sstevel@tonic-gate 		;
2297c478bd9Sstevel@tonic-gate 	if (cur_label == L_TYPE_EFI) {
2307c478bd9Sstevel@tonic-gate 		enter_critical();
2317c478bd9Sstevel@tonic-gate 		cur_disk->disk_parts = cur_parts = pptr;
2327c478bd9Sstevel@tonic-gate 		exit_critical();
2337c478bd9Sstevel@tonic-gate 		fmt_print("\n");
2347c478bd9Sstevel@tonic-gate 		return (0);
2357c478bd9Sstevel@tonic-gate 	}
2367c478bd9Sstevel@tonic-gate #if defined(i386)
2377c478bd9Sstevel@tonic-gate 	/*
2387c478bd9Sstevel@tonic-gate 	 * Adjust for the boot and alternate sectors partition - assuming that
2397c478bd9Sstevel@tonic-gate 	 * the alternate sectors partition physical location follows
2407c478bd9Sstevel@tonic-gate 	 * immediately the boot partition and partition sizes are
2417c478bd9Sstevel@tonic-gate 	 * expressed in multiple of cylinder size.
2427c478bd9Sstevel@tonic-gate 	 */
2437c478bd9Sstevel@tonic-gate 	cyl_offset = pptr->pinfo_map[I_PARTITION].dkl_cylno + 1;
2447c478bd9Sstevel@tonic-gate 	if (pptr->pinfo_map[J_PARTITION].dkl_nblk != 0) {
2457c478bd9Sstevel@tonic-gate 		cyl_offset = pptr->pinfo_map[J_PARTITION].dkl_cylno +
246edbad4feSToomas Soome 		    ((pptr->pinfo_map[J_PARTITION].dkl_nblk +
247edbad4feSToomas Soome 		    (spc() - 1)) / spc());
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate #else	/* !defined(i386) */
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	b_cylno = 0;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate #endif	/* defined(i386) */
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	/*
2567c478bd9Sstevel@tonic-gate 	 * Before we blow the current map away, do some limits checking.
2577c478bd9Sstevel@tonic-gate 	 */
2587c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++)  {
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate #if defined(i386)
2617c478bd9Sstevel@tonic-gate 		if (i == I_PARTITION || i == J_PARTITION || i == C_PARTITION) {
2627c478bd9Sstevel@tonic-gate 			b_cylno = 0;
2637c478bd9Sstevel@tonic-gate 		} else if (pptr->pinfo_map[i].dkl_nblk == 0) {
2647c478bd9Sstevel@tonic-gate 			/*
2657c478bd9Sstevel@tonic-gate 			 * Always accept starting cyl 0 if the size is 0 also
2667c478bd9Sstevel@tonic-gate 			 */
2677c478bd9Sstevel@tonic-gate 			b_cylno = 0;
2687c478bd9Sstevel@tonic-gate 		} else {
2697c478bd9Sstevel@tonic-gate 			b_cylno = cyl_offset;
2707c478bd9Sstevel@tonic-gate 		}
2717c478bd9Sstevel@tonic-gate #endif		/* defined(i386) */
2727c478bd9Sstevel@tonic-gate 		if (pptr->pinfo_map[i].dkl_cylno < b_cylno ||
273edbad4feSToomas Soome 		    pptr->pinfo_map[i].dkl_cylno > (ncyl-1)) {
274edbad4feSToomas Soome 			err_print("partition %c: starting cylinder %d is out "
275edbad4feSToomas Soome 			    "of range\n", (PARTITION_BASE + i),
276edbad4feSToomas Soome 			    pptr->pinfo_map[i].dkl_cylno);
2777c478bd9Sstevel@tonic-gate 			return (0);
2787c478bd9Sstevel@tonic-gate 		}
279ec74a236Syu, larry liu - Sun Microsystems - Beijing China 		if (pptr->pinfo_map[i].dkl_nblk > ((ncyl -
280ec74a236Syu, larry liu - Sun Microsystems - Beijing China 		    pptr->pinfo_map[i].dkl_cylno) * spc())) {
2817c478bd9Sstevel@tonic-gate 			err_print(
282342440ecSPrasad Singamsetty 			    "partition %c: specified # of blocks, %u, "
283342440ecSPrasad Singamsetty 			    "is out of range\n",
284342440ecSPrasad Singamsetty 			    (PARTITION_BASE+i),
285342440ecSPrasad Singamsetty 			    pptr->pinfo_map[i].dkl_nblk);
2867c478bd9Sstevel@tonic-gate 			return (0);
2877c478bd9Sstevel@tonic-gate 		}
2887c478bd9Sstevel@tonic-gate 	}
2897c478bd9Sstevel@tonic-gate 	/*
2907c478bd9Sstevel@tonic-gate 	 * Lock out interrupts so the lists don't get mangled.
2917c478bd9Sstevel@tonic-gate 	 */
2927c478bd9Sstevel@tonic-gate 	enter_critical();
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * If the old current map is unnamed, delete it.
2957c478bd9Sstevel@tonic-gate 	 */
2967c478bd9Sstevel@tonic-gate 	if (cur_parts != NULL && cur_parts != pptr &&
2977c478bd9Sstevel@tonic-gate 	    cur_parts->pinfo_name == NULL)
2987c478bd9Sstevel@tonic-gate 		delete_partition(cur_parts);
2997c478bd9Sstevel@tonic-gate 	/*
3007c478bd9Sstevel@tonic-gate 	 * Make the selected map current.
3017c478bd9Sstevel@tonic-gate 	 */
3027c478bd9Sstevel@tonic-gate 	cur_disk->disk_parts = cur_parts = pptr;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
3057c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++)  {
3067c478bd9Sstevel@tonic-gate 		cur_parts->vtoc.v_part[i].p_start =
307342440ecSPrasad Singamsetty 		    (blkaddr_t)(cur_parts->pinfo_map[i].dkl_cylno *
3087c478bd9Sstevel@tonic-gate 		    (nhead * nsect));
3097c478bd9Sstevel@tonic-gate 		cur_parts->vtoc.v_part[i].p_size =
310342440ecSPrasad Singamsetty 		    (blkaddr_t)cur_parts->pinfo_map[i].dkl_nblk;
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_16) */
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	exit_critical();
3157c478bd9Sstevel@tonic-gate 	fmt_print("\n");
3167c478bd9Sstevel@tonic-gate 	return (0);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate  * This routine implements the 'name' command.  It allows the user
3217c478bd9Sstevel@tonic-gate  * to name the current partition map.  If the map was already named,
3227c478bd9Sstevel@tonic-gate  * the name is changed.  Once a map is named, the values of the partitions
3237c478bd9Sstevel@tonic-gate  * cannot be changed.  Attempts to change them will cause another map
3247c478bd9Sstevel@tonic-gate  * to be created.
3257c478bd9Sstevel@tonic-gate  */
3267c478bd9Sstevel@tonic-gate int
p_name(void)327edbad4feSToomas Soome p_name(void)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	char	*name;
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	/*
3327c478bd9Sstevel@tonic-gate 	 * check if there exists a partition table for the disk.
3337c478bd9Sstevel@tonic-gate 	 */
3347c478bd9Sstevel@tonic-gate 	if (cur_parts == NULL) {
3357c478bd9Sstevel@tonic-gate 		err_print("Current Disk has no partition table.\n");
3367c478bd9Sstevel@tonic-gate 		return (-1);
3377c478bd9Sstevel@tonic-gate 	}
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	/*
3417c478bd9Sstevel@tonic-gate 	 * Ask for the name.  Note that the input routine will malloc
3427c478bd9Sstevel@tonic-gate 	 * space for the name since we are using the OSTR input type.
3437c478bd9Sstevel@tonic-gate 	 */
344052b6e8aSbg 	name = (char *)(uintptr_t)input(FIO_OSTR,
345052b6e8aSbg 	    "Enter table name (remember quotes)",
346*b12aaafbSToomas Soome 	    ':', NULL, NULL, DATA_INPUT);
3477c478bd9Sstevel@tonic-gate 	/*
3487c478bd9Sstevel@tonic-gate 	 * Lock out interrupts.
3497c478bd9Sstevel@tonic-gate 	 */
3507c478bd9Sstevel@tonic-gate 	enter_critical();
3517c478bd9Sstevel@tonic-gate 	/*
3527c478bd9Sstevel@tonic-gate 	 * If it was already named, destroy the old name.
3537c478bd9Sstevel@tonic-gate 	 */
3547c478bd9Sstevel@tonic-gate 	if (cur_parts->pinfo_name != NULL)
3557c478bd9Sstevel@tonic-gate 		destroy_data(cur_parts->pinfo_name);
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * Set the name.
3587c478bd9Sstevel@tonic-gate 	 */
3597c478bd9Sstevel@tonic-gate 	cur_parts->pinfo_name = name;
3607c478bd9Sstevel@tonic-gate 	exit_critical();
3617c478bd9Sstevel@tonic-gate 	fmt_print("\n");
3627c478bd9Sstevel@tonic-gate 	return (0);
3637c478bd9Sstevel@tonic-gate }
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate  * This routine implements the 'print' command.  It lists the values
3687c478bd9Sstevel@tonic-gate  * for all the partitions in the current partition map.
3697c478bd9Sstevel@tonic-gate  */
3707c478bd9Sstevel@tonic-gate int
p_print(void)37132a71e42SToomas Soome p_print(void)
3727c478bd9Sstevel@tonic-gate {
3737c478bd9Sstevel@tonic-gate 	/*
3747c478bd9Sstevel@tonic-gate 	 * check if there exists a partition table for the disk.
3757c478bd9Sstevel@tonic-gate 	 */
3767c478bd9Sstevel@tonic-gate 	if (cur_parts == NULL) {
3777c478bd9Sstevel@tonic-gate 		err_print("Current Disk has no partition table.\n");
3787c478bd9Sstevel@tonic-gate 		return (-1);
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	/*
3827c478bd9Sstevel@tonic-gate 	 * Print the volume name, if it appears to be set
3837c478bd9Sstevel@tonic-gate 	 */
3847c478bd9Sstevel@tonic-gate 	if (chk_volname(cur_disk)) {
3857c478bd9Sstevel@tonic-gate 		fmt_print("Volume:  ");
3867c478bd9Sstevel@tonic-gate 		print_volname(cur_disk);
3877c478bd9Sstevel@tonic-gate 		fmt_print("\n");
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * Print the name of the current map.
3917c478bd9Sstevel@tonic-gate 	 */
3927c478bd9Sstevel@tonic-gate 	if ((cur_parts->pinfo_name != NULL) && (cur_label == L_TYPE_SOLARIS)) {
3937c478bd9Sstevel@tonic-gate 		fmt_print("Current partition table (%s):\n",
3947c478bd9Sstevel@tonic-gate 		    cur_parts->pinfo_name);
3953a5b922fSbo zhou - Sun Microsystems - Beijing China 		fmt_print("Total disk cylinders available: %d + %d "
3963a5b922fSbo zhou - Sun Microsystems - Beijing China 		    "(reserved cylinders)\n\n", ncyl, acyl);
3977c478bd9Sstevel@tonic-gate 	} else if (cur_label == L_TYPE_SOLARIS) {
3987c478bd9Sstevel@tonic-gate 		fmt_print("Current partition table (unnamed):\n");
3993a5b922fSbo zhou - Sun Microsystems - Beijing China 		fmt_print("Total disk cylinders available: %d + %d "
4003a5b922fSbo zhou - Sun Microsystems - Beijing China 		    "(reserved cylinders)\n\n", ncyl, acyl);
4017c478bd9Sstevel@tonic-gate 	} else if (cur_label == L_TYPE_EFI) {
40232a71e42SToomas Soome 		unsigned reserved;
40332a71e42SToomas Soome 
40432a71e42SToomas Soome 		reserved = efi_reserved_sectors(cur_parts->etoc);
4053a5b922fSbo zhou - Sun Microsystems - Beijing China 		fmt_print("Current partition table (%s):\n",
4063a5b922fSbo zhou - Sun Microsystems - Beijing China 		    cur_parts->pinfo_name != NULL ?
4073a5b922fSbo zhou - Sun Microsystems - Beijing China 		    cur_parts->pinfo_name : "unnamed");
40832a71e42SToomas Soome 		fmt_print("Total disk sectors available: %llu + %u "
4093a5b922fSbo zhou - Sun Microsystems - Beijing China 		    "(reserved sectors)\n\n",
41032a71e42SToomas Soome 		    cur_parts->etoc->efi_last_u_lba - reserved -
41132a71e42SToomas Soome 		    cur_parts->etoc->efi_first_u_lba + 1, reserved);
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/*
4167c478bd9Sstevel@tonic-gate 	 * Print the partition map itself
4177c478bd9Sstevel@tonic-gate 	 */
4187c478bd9Sstevel@tonic-gate 	print_map(cur_parts);
4197c478bd9Sstevel@tonic-gate 	return (0);
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate  * Print a partition map
4257c478bd9Sstevel@tonic-gate  */
4267c478bd9Sstevel@tonic-gate void
print_map(struct partition_info * map)4277c478bd9Sstevel@tonic-gate print_map(struct partition_info *map)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	int	i;
4307c478bd9Sstevel@tonic-gate 	int	want_header;
4317c478bd9Sstevel@tonic-gate 	struct	dk_gpt *vtoc64;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (cur_label == L_TYPE_EFI) {
4347c478bd9Sstevel@tonic-gate 		vtoc64 = map->etoc;
4357c478bd9Sstevel@tonic-gate 		want_header = 1;
4367c478bd9Sstevel@tonic-gate 		for (i = 0; i < vtoc64->efi_nparts; i++) {
4377c478bd9Sstevel@tonic-gate 		/*
4387c478bd9Sstevel@tonic-gate 		 * we want to print partitions above 7 in expert mode only
4397c478bd9Sstevel@tonic-gate 		 * or if the partition is reserved
4407c478bd9Sstevel@tonic-gate 		 */
4417c478bd9Sstevel@tonic-gate 			if (i >= 7 && !expert_mode &&
4427c478bd9Sstevel@tonic-gate 			    ((int)vtoc64->efi_parts[i].p_tag !=
4437c478bd9Sstevel@tonic-gate 			    V_RESERVED)) {
4447c478bd9Sstevel@tonic-gate 				continue;
4457c478bd9Sstevel@tonic-gate 			}
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 			print_efi_partition(vtoc64, i, want_header);
4487c478bd9Sstevel@tonic-gate 			want_header = 0;
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 		fmt_print("\n");
4517c478bd9Sstevel@tonic-gate 		return;
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * Loop through each partition, printing the header
4557c478bd9Sstevel@tonic-gate 	 * the first time.
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 	want_header = 1;
4587c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
4597c478bd9Sstevel@tonic-gate 		if (i > 9) {
4607c478bd9Sstevel@tonic-gate 			break;
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 		print_partition(map, i, want_header);
4637c478bd9Sstevel@tonic-gate 		want_header = 0;
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	fmt_print("\n");
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate /*
4707c478bd9Sstevel@tonic-gate  * Print out one line of partition information,
4717c478bd9Sstevel@tonic-gate  * with optional header for EFI type disks.
4727c478bd9Sstevel@tonic-gate  */
4737c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4747c478bd9Sstevel@tonic-gate void
print_efi_partition(struct dk_gpt * map,int partnum,int want_header)4757c478bd9Sstevel@tonic-gate print_efi_partition(struct dk_gpt *map, int partnum, int want_header)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate 	int		ncyl2_digits = 0;
4787c478bd9Sstevel@tonic-gate 	float		scaled;
4797c478bd9Sstevel@tonic-gate 	char		*s;
4807c478bd9Sstevel@tonic-gate 	uint64_t	secsize;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	ncyl2_digits = ndigits(map->efi_last_u_lba);
4837c478bd9Sstevel@tonic-gate 	if (want_header) {
484edbad4feSToomas Soome 		fmt_print("Part      ");
485edbad4feSToomas Soome 		fmt_print("Tag    Flag     ");
486edbad4feSToomas Soome 		fmt_print("First Sector");
487edbad4feSToomas Soome 		nspaces(ncyl2_digits);
488edbad4feSToomas Soome 		fmt_print("Size");
489edbad4feSToomas Soome 		nspaces(ncyl2_digits);
490edbad4feSToomas Soome 		fmt_print("Last Sector\n");
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	fmt_print("  %d ", partnum);
494edbad4feSToomas Soome 	s = find_string(ptag_choices, (int)map->efi_parts[partnum].p_tag);
495*b12aaafbSToomas Soome 	if (s == NULL)
4967c478bd9Sstevel@tonic-gate 		s = "-";
4977c478bd9Sstevel@tonic-gate 	nspaces(10 - (int)strlen(s));
4987c478bd9Sstevel@tonic-gate 	fmt_print("%s", s);
4997c478bd9Sstevel@tonic-gate 
500edbad4feSToomas Soome 	s = find_string(pflag_choices, (int)map->efi_parts[partnum].p_flag);
501*b12aaafbSToomas Soome 	if (s == NULL)
5027c478bd9Sstevel@tonic-gate 		s = "-";
5037c478bd9Sstevel@tonic-gate 	nspaces(6 - (int)strlen(s));
5047c478bd9Sstevel@tonic-gate 	fmt_print("%s", s);
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	nspaces(2);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	secsize = map->efi_parts[partnum].p_size;
5097c478bd9Sstevel@tonic-gate 	if (secsize == 0) {
510edbad4feSToomas Soome 		fmt_print("%16llu", map->efi_parts[partnum].p_start);
511edbad4feSToomas Soome 		nspaces(ncyl2_digits);
512edbad4feSToomas Soome 		fmt_print("  0     ");
5137c478bd9Sstevel@tonic-gate 	} else {
514edbad4feSToomas Soome 		fmt_print("%16llu", map->efi_parts[partnum].p_start);
515edbad4feSToomas Soome 		scaled = bn2mb(secsize);
516edbad4feSToomas Soome 		nspaces(ncyl2_digits - 5);
517edbad4feSToomas Soome 		if (scaled >= (float)1024.0 * 1024) {
518edbad4feSToomas Soome 			fmt_print("%8.2fTB", scaled/((float)1024.0 * 1024));
519edbad4feSToomas Soome 		} else if (scaled >= (float)1024.0) {
520edbad4feSToomas Soome 			fmt_print("%8.2fGB", scaled/(float)1024.0);
521edbad4feSToomas Soome 		} else {
522edbad4feSToomas Soome 			fmt_print("%8.2fMB", scaled);
523edbad4feSToomas Soome 		}
5247c478bd9Sstevel@tonic-gate 	}
5257c478bd9Sstevel@tonic-gate 	nspaces(ncyl2_digits);
526edbad4feSToomas Soome 	if ((map->efi_parts[partnum].p_start + secsize - 1) == UINT_MAX64) {
527edbad4feSToomas Soome 		fmt_print(" 0    \n");
5287c478bd9Sstevel@tonic-gate 	} else {
529edbad4feSToomas Soome 		fmt_print(" %llu    \n",
530edbad4feSToomas Soome 		    map->efi_parts[partnum].p_start + secsize - 1);
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate  * Print out one line of partition information,
5367c478bd9Sstevel@tonic-gate  * with optional header.
5377c478bd9Sstevel@tonic-gate  */
5387c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5397c478bd9Sstevel@tonic-gate void
print_partition(struct partition_info * pinfo,int partnum,int want_header)5407c478bd9Sstevel@tonic-gate print_partition(struct partition_info *pinfo, int partnum, int want_header)
5417c478bd9Sstevel@tonic-gate {
5427c478bd9Sstevel@tonic-gate 	int		i;
543342440ecSPrasad Singamsetty 	blkaddr_t	nblks;
5447c478bd9Sstevel@tonic-gate 	int		cyl1;
5457c478bd9Sstevel@tonic-gate 	int		cyl2;
5467c478bd9Sstevel@tonic-gate 	float		scaled;
5477c478bd9Sstevel@tonic-gate 	int		maxcyl2;
5487c478bd9Sstevel@tonic-gate 	int		ncyl2_digits;
5497c478bd9Sstevel@tonic-gate 	char		*s;
550342440ecSPrasad Singamsetty 	blkaddr_t	maxnblks = 0;
551342440ecSPrasad Singamsetty 	blkaddr_t	len;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * To align things nicely, we need to know the maximum
5557c478bd9Sstevel@tonic-gate 	 * width of the number of cylinders field.
5567c478bd9Sstevel@tonic-gate 	 */
5577c478bd9Sstevel@tonic-gate 	maxcyl2 = 0;
5587c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
5597c478bd9Sstevel@tonic-gate 		nblks	= (uint_t)pinfo->pinfo_map[i].dkl_nblk;
5607c478bd9Sstevel@tonic-gate 		cyl1	= pinfo->pinfo_map[i].dkl_cylno;
5617c478bd9Sstevel@tonic-gate 		cyl2	= cyl1 + (nblks / spc()) - 1;
5627c478bd9Sstevel@tonic-gate 		if (nblks > 0) {
5637c478bd9Sstevel@tonic-gate 			maxcyl2 = max(cyl2, maxcyl2);
5647c478bd9Sstevel@tonic-gate 			maxnblks = max(nblks, maxnblks);
5657c478bd9Sstevel@tonic-gate 		}
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 	/*
5687c478bd9Sstevel@tonic-gate 	 * Get the number of digits required
5697c478bd9Sstevel@tonic-gate 	 */
5707c478bd9Sstevel@tonic-gate 	ncyl2_digits = ndigits(maxcyl2);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	/*
5737c478bd9Sstevel@tonic-gate 	 * Print the header, if necessary
5747c478bd9Sstevel@tonic-gate 	 */
5757c478bd9Sstevel@tonic-gate 	if (want_header) {
5767c478bd9Sstevel@tonic-gate 		fmt_print("Part      ");
5777c478bd9Sstevel@tonic-gate 		fmt_print("Tag    Flag     ");
5787c478bd9Sstevel@tonic-gate 		fmt_print("Cylinders");
5797c478bd9Sstevel@tonic-gate 		nspaces(ncyl2_digits);
5807c478bd9Sstevel@tonic-gate 		fmt_print("    Size            Blocks\n");
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	/*
5847c478bd9Sstevel@tonic-gate 	 * Print the partition information
5857c478bd9Sstevel@tonic-gate 	 */
5867c478bd9Sstevel@tonic-gate 	nblks	= pinfo->pinfo_map[partnum].dkl_nblk;
5877c478bd9Sstevel@tonic-gate 	cyl1	= pinfo->pinfo_map[partnum].dkl_cylno;
5887c478bd9Sstevel@tonic-gate 	cyl2	= cyl1 + (nblks / spc()) - 1;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	fmt_print("  %x ", partnum);
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	/*
5937c478bd9Sstevel@tonic-gate 	 * Print the partition tag.  If invalid, print -
5947c478bd9Sstevel@tonic-gate 	 */
595edbad4feSToomas Soome 	s = find_string(ptag_choices, (int)pinfo->vtoc.v_part[partnum].p_tag);
596*b12aaafbSToomas Soome 	if (s == NULL)
5977c478bd9Sstevel@tonic-gate 		s = "-";
5987c478bd9Sstevel@tonic-gate 	nspaces(10 - (int)strlen(s));
5997c478bd9Sstevel@tonic-gate 	fmt_print("%s", s);
6007c478bd9Sstevel@tonic-gate 
6017c478bd9Sstevel@tonic-gate 	/*
6027c478bd9Sstevel@tonic-gate 	 * Print the partition flag.  If invalid print -
6037c478bd9Sstevel@tonic-gate 	 */
604edbad4feSToomas Soome 	s = find_string(pflag_choices, (int)pinfo->vtoc.v_part[partnum].p_flag);
605edbad4feSToomas Soome 	if (s == NULL)
6067c478bd9Sstevel@tonic-gate 		s = "-";
6077c478bd9Sstevel@tonic-gate 	nspaces(6 - (int)strlen(s));
6087c478bd9Sstevel@tonic-gate 	fmt_print("%s", s);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	nspaces(2);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	if (nblks == 0) {
6137c478bd9Sstevel@tonic-gate 		fmt_print("%6d      ", cyl1);
6147c478bd9Sstevel@tonic-gate 		nspaces(ncyl2_digits);
6157c478bd9Sstevel@tonic-gate 		fmt_print("     0         ");
6167c478bd9Sstevel@tonic-gate 	} else {
6177c478bd9Sstevel@tonic-gate 		fmt_print("%6d - ", cyl1);
6187c478bd9Sstevel@tonic-gate 		nspaces(ncyl2_digits - ndigits(cyl2));
6197c478bd9Sstevel@tonic-gate 		fmt_print("%d    ", cyl2);
6207c478bd9Sstevel@tonic-gate 		scaled = bn2mb(nblks);
6217c478bd9Sstevel@tonic-gate 		if (scaled > (float)1024.0 * 1024.0) {
6227c478bd9Sstevel@tonic-gate 			fmt_print("%8.2fTB    ",
623edbad4feSToomas Soome 			    scaled/((float)1024.0 * 1024.0));
6247c478bd9Sstevel@tonic-gate 		} else if (scaled > (float)1024.0) {
6257c478bd9Sstevel@tonic-gate 			fmt_print("%8.2fGB    ", scaled/(float)1024.0);
6267c478bd9Sstevel@tonic-gate 		} else {
6277c478bd9Sstevel@tonic-gate 			fmt_print("%8.2fMB    ", scaled);
6287c478bd9Sstevel@tonic-gate 		}
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 	fmt_print("(");
6317c478bd9Sstevel@tonic-gate 	pr_dblock(fmt_print, nblks);
6327c478bd9Sstevel@tonic-gate 	fmt_print(")");
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	nspaces(ndigits(maxnblks/spc()) - ndigits(nblks/spc()));
6357c478bd9Sstevel@tonic-gate 	/*
6367c478bd9Sstevel@tonic-gate 	 * Allocates size of the printf format string.
6377c478bd9Sstevel@tonic-gate 	 * ndigits(ndigits(maxblks)) gives the byte size of
6387c478bd9Sstevel@tonic-gate 	 * the printf width field for maxnblks.
6397c478bd9Sstevel@tonic-gate 	 */
6407c478bd9Sstevel@tonic-gate 	len = strlen(" %") + ndigits(ndigits(maxnblks)) + strlen("d\n") + 1;
6417c478bd9Sstevel@tonic-gate 	s = zalloc(len);
642342440ecSPrasad Singamsetty 	(void) snprintf(s, len, "%s%u%s", " %", ndigits(maxnblks), "u\n");
6437c478bd9Sstevel@tonic-gate 	fmt_print(s, nblks);
6447c478bd9Sstevel@tonic-gate 	(void) free(s);
6457c478bd9Sstevel@tonic-gate }
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate /*
6497c478bd9Sstevel@tonic-gate  * Return true if a disk has a volume name
6507c478bd9Sstevel@tonic-gate  */
6517c478bd9Sstevel@tonic-gate int
chk_volname(struct disk_info * disk)652edbad4feSToomas Soome chk_volname(struct disk_info *disk)
6537c478bd9Sstevel@tonic-gate {
6547c478bd9Sstevel@tonic-gate 	return (disk->v_volume[0] != 0);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate  * Print the volume name, if it appears to be set
6607c478bd9Sstevel@tonic-gate  */
6617c478bd9Sstevel@tonic-gate void
print_volname(struct disk_info * disk)662edbad4feSToomas Soome print_volname(struct disk_info *disk)
6637c478bd9Sstevel@tonic-gate {
6647c478bd9Sstevel@tonic-gate 	int	i;
6657c478bd9Sstevel@tonic-gate 	char	*p;
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	p = disk->v_volume;
6687c478bd9Sstevel@tonic-gate 	for (i = 0; i < LEN_DKL_VVOL; i++, p++) {
6697c478bd9Sstevel@tonic-gate 		if (*p == 0)
6707c478bd9Sstevel@tonic-gate 			break;
6717c478bd9Sstevel@tonic-gate 		fmt_print("%c", *p);
6727c478bd9Sstevel@tonic-gate 	}
6737c478bd9Sstevel@tonic-gate }
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate  * Print a number of spaces
6787c478bd9Sstevel@tonic-gate  */
6797c478bd9Sstevel@tonic-gate static void
nspaces(int n)680edbad4feSToomas Soome nspaces(int n)
6817c478bd9Sstevel@tonic-gate {
6827c478bd9Sstevel@tonic-gate 	while (n-- > 0)
6837c478bd9Sstevel@tonic-gate 		fmt_print(" ");
6847c478bd9Sstevel@tonic-gate }
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate /*
6877c478bd9Sstevel@tonic-gate  * Return the number of digits required to print a number
6887c478bd9Sstevel@tonic-gate  */
6897c478bd9Sstevel@tonic-gate static int
ndigits(uint64_t n)690edbad4feSToomas Soome ndigits(uint64_t n)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate 	int	i;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	i = 0;
6957c478bd9Sstevel@tonic-gate 	while (n > 0) {
6967c478bd9Sstevel@tonic-gate 		n /= 10;
6977c478bd9Sstevel@tonic-gate 		i++;
6987c478bd9Sstevel@tonic-gate 	}
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	return (i == 0 ? 1 : i);
7017c478bd9Sstevel@tonic-gate }
702