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
5af007057Syl194034 * Common Development and Distribution License (the "License").
6af007057Syl194034 * 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 /*
22*3a5b922fSbo 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 #ifdef __STDC__
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate /* Function prototypes for ANSI C Compilers */
417c478bd9Sstevel@tonic-gate static void nspaces(int);
427c478bd9Sstevel@tonic-gate static int ndigits(uint64_t);
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate #else /* __STDC__ */
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /* Function prototypes for non-ANSI C Compilers */
477c478bd9Sstevel@tonic-gate static void nspaces();
487c478bd9Sstevel@tonic-gate static int ndigits();
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate #endif /* __STDC__ */
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * This routine implements the 'a' command. It changes the 'a' partition.
547c478bd9Sstevel@tonic-gate */
557c478bd9Sstevel@tonic-gate int
p_apart()567c478bd9Sstevel@tonic-gate p_apart()
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate change_partition(0);
607c478bd9Sstevel@tonic-gate return (0);
617c478bd9Sstevel@tonic-gate }
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * This routine implements the 'b' command. It changes the 'b' partition.
657c478bd9Sstevel@tonic-gate */
667c478bd9Sstevel@tonic-gate int
p_bpart()677c478bd9Sstevel@tonic-gate p_bpart()
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate change_partition(1);
717c478bd9Sstevel@tonic-gate return (0);
727c478bd9Sstevel@tonic-gate }
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate * This routine implements the 'c' command. It changes the 'c' partition.
767c478bd9Sstevel@tonic-gate */
777c478bd9Sstevel@tonic-gate int
p_cpart()787c478bd9Sstevel@tonic-gate p_cpart()
797c478bd9Sstevel@tonic-gate {
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate change_partition(2);
827c478bd9Sstevel@tonic-gate return (0);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /*
867c478bd9Sstevel@tonic-gate * This routine implements the 'd' command. It changes the 'd' partition.
877c478bd9Sstevel@tonic-gate */
887c478bd9Sstevel@tonic-gate int
p_dpart()897c478bd9Sstevel@tonic-gate p_dpart()
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate change_partition(3);
937c478bd9Sstevel@tonic-gate return (0);
947c478bd9Sstevel@tonic-gate }
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate * This routine implements the 'e' command. It changes the 'e' partition.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate int
p_epart()1007c478bd9Sstevel@tonic-gate p_epart()
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate change_partition(4);
1047c478bd9Sstevel@tonic-gate return (0);
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate * This routine implements the 'f' command. It changes the 'f' partition.
1097c478bd9Sstevel@tonic-gate */
1107c478bd9Sstevel@tonic-gate int
p_fpart()1117c478bd9Sstevel@tonic-gate p_fpart()
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate change_partition(5);
1157c478bd9Sstevel@tonic-gate return (0);
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate /*
1197c478bd9Sstevel@tonic-gate * This routine implements the 'g' command. It changes the 'g' partition.
1207c478bd9Sstevel@tonic-gate */
1217c478bd9Sstevel@tonic-gate int
p_gpart()1227c478bd9Sstevel@tonic-gate p_gpart()
1237c478bd9Sstevel@tonic-gate {
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate change_partition(6);
1267c478bd9Sstevel@tonic-gate return (0);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate * This routine implements the 'h' command. It changes the 'h' partition.
1317c478bd9Sstevel@tonic-gate */
1327c478bd9Sstevel@tonic-gate int
p_hpart()1337c478bd9Sstevel@tonic-gate p_hpart()
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate change_partition(7);
1377c478bd9Sstevel@tonic-gate return (0);
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate /*
1417c478bd9Sstevel@tonic-gate * This routine implements the 'i' command. It is valid only for EFI
1427c478bd9Sstevel@tonic-gate * labeled disks. This can be used only in expert mode.
1437c478bd9Sstevel@tonic-gate */
1447c478bd9Sstevel@tonic-gate int
p_ipart()1457c478bd9Sstevel@tonic-gate p_ipart()
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate change_partition(8);
1487c478bd9Sstevel@tonic-gate return (0);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate #if defined(i386)
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * This routine implements the 'j' command. It changes the 'j' partition.
1547c478bd9Sstevel@tonic-gate */
1557c478bd9Sstevel@tonic-gate int
p_jpart()1567c478bd9Sstevel@tonic-gate p_jpart()
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate change_partition(9);
1607c478bd9Sstevel@tonic-gate return (0);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate #endif /* defined(i386) */
1637c478bd9Sstevel@tonic-gate
164af007057Syl194034 int
p_expand()165af007057Syl194034 p_expand()
166af007057Syl194034 {
167af007057Syl194034 uint64_t delta;
168af007057Syl194034 uint_t nparts;
169af007057Syl194034 struct dk_gpt *efi_label = cur_parts->etoc;
170af007057Syl194034
171af007057Syl194034 if (cur_parts->etoc->efi_altern_lba == 1 ||
172af007057Syl194034 (cur_parts->etoc->efi_altern_lba >=
173af007057Syl194034 cur_parts->etoc->efi_last_lba)) {
174af007057Syl194034 err_print("Warning: No expanded capacity is found.\n");
175af007057Syl194034 return (0);
176af007057Syl194034 }
177af007057Syl194034
178af007057Syl194034 delta = efi_label->efi_last_lba - efi_label->efi_altern_lba;
179af007057Syl194034 nparts = efi_label->efi_nparts;
180af007057Syl194034
181af007057Syl194034 enter_critical();
182af007057Syl194034 efi_label->efi_parts[nparts - 1].p_start += delta;
183af007057Syl194034 efi_label->efi_last_u_lba += delta;
184af007057Syl194034 efi_label->efi_altern_lba = cur_parts->etoc->efi_last_lba;
185af007057Syl194034 exit_critical();
186af007057Syl194034
187af007057Syl194034 fmt_print("The expanded capacity is added to the unallocated space.\n");
188af007057Syl194034 return (0);
189af007057Syl194034 }
190af007057Syl194034
1917c478bd9Sstevel@tonic-gate /*
1927c478bd9Sstevel@tonic-gate * This routine implements the 'select' command. It allows the user
1937c478bd9Sstevel@tonic-gate * to make a pre-defined partition map the current map.
1947c478bd9Sstevel@tonic-gate */
1957c478bd9Sstevel@tonic-gate int
p_select()1967c478bd9Sstevel@tonic-gate p_select()
1977c478bd9Sstevel@tonic-gate {
1987c478bd9Sstevel@tonic-gate struct partition_info *pptr, *parts;
1997c478bd9Sstevel@tonic-gate u_ioparam_t ioparam;
2007c478bd9Sstevel@tonic-gate int i, index, deflt, *defltptr = NULL;
201342440ecSPrasad Singamsetty blkaddr_t b_cylno;
2027c478bd9Sstevel@tonic-gate #if defined(i386)
203342440ecSPrasad Singamsetty blkaddr_t cyl_offset;
2047c478bd9Sstevel@tonic-gate #endif
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate parts = cur_dtype->dtype_plist;
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate * If there are no pre-defined maps for this disk type, it's
2097c478bd9Sstevel@tonic-gate * an error.
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate if (parts == NULL) {
2127c478bd9Sstevel@tonic-gate err_print("No defined partition tables.\n");
2137c478bd9Sstevel@tonic-gate return (-1);
2147c478bd9Sstevel@tonic-gate }
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate /*
2177c478bd9Sstevel@tonic-gate * Loop through the pre-defined maps and list them by name. If
2187c478bd9Sstevel@tonic-gate * the current map is one of them, make it the default. If any
2197c478bd9Sstevel@tonic-gate * the maps are unnamed, label them as such.
2207c478bd9Sstevel@tonic-gate */
2217c478bd9Sstevel@tonic-gate for (i = 0, pptr = parts; pptr != NULL; pptr = pptr->pinfo_next) {
2227c478bd9Sstevel@tonic-gate if (cur_parts == pptr) {
2237c478bd9Sstevel@tonic-gate deflt = i;
2247c478bd9Sstevel@tonic-gate defltptr = &deflt;
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate if (pptr->pinfo_name == NULL)
2277c478bd9Sstevel@tonic-gate fmt_print(" %d. unnamed\n", i++);
2287c478bd9Sstevel@tonic-gate else
2297c478bd9Sstevel@tonic-gate fmt_print(" %d. %s\n", i++, pptr->pinfo_name);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = 0;
2327c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = i - 1;
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate * Ask which map should be made current.
2357c478bd9Sstevel@tonic-gate */
2367c478bd9Sstevel@tonic-gate index = input(FIO_INT, "Specify table (enter its number)", ':',
2377c478bd9Sstevel@tonic-gate &ioparam, defltptr, DATA_INPUT);
2387c478bd9Sstevel@tonic-gate for (i = 0, pptr = parts; i < index; i++, pptr = pptr->pinfo_next)
2397c478bd9Sstevel@tonic-gate ;
2407c478bd9Sstevel@tonic-gate if (cur_label == L_TYPE_EFI) {
2417c478bd9Sstevel@tonic-gate enter_critical();
2427c478bd9Sstevel@tonic-gate cur_disk->disk_parts = cur_parts = pptr;
2437c478bd9Sstevel@tonic-gate exit_critical();
2447c478bd9Sstevel@tonic-gate fmt_print("\n");
2457c478bd9Sstevel@tonic-gate return (0);
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate #if defined(i386)
2487c478bd9Sstevel@tonic-gate /*
2497c478bd9Sstevel@tonic-gate * Adjust for the boot and alternate sectors partition - assuming that
2507c478bd9Sstevel@tonic-gate * the alternate sectors partition physical location follows
2517c478bd9Sstevel@tonic-gate * immediately the boot partition and partition sizes are
2527c478bd9Sstevel@tonic-gate * expressed in multiple of cylinder size.
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate cyl_offset = pptr->pinfo_map[I_PARTITION].dkl_cylno + 1;
2557c478bd9Sstevel@tonic-gate if (pptr->pinfo_map[J_PARTITION].dkl_nblk != 0) {
2567c478bd9Sstevel@tonic-gate cyl_offset = pptr->pinfo_map[J_PARTITION].dkl_cylno +
2577c478bd9Sstevel@tonic-gate ((pptr->pinfo_map[J_PARTITION].dkl_nblk +
2587c478bd9Sstevel@tonic-gate (spc() - 1)) / spc());
2597c478bd9Sstevel@tonic-gate }
2607c478bd9Sstevel@tonic-gate #else /* !defined(i386) */
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate b_cylno = 0;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate #endif /* defined(i386) */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Before we blow the current map away, do some limits checking.
2687c478bd9Sstevel@tonic-gate */
2697c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate #if defined(i386)
2727c478bd9Sstevel@tonic-gate if (i == I_PARTITION || i == J_PARTITION || i == C_PARTITION) {
2737c478bd9Sstevel@tonic-gate b_cylno = 0;
2747c478bd9Sstevel@tonic-gate } else if (pptr->pinfo_map[i].dkl_nblk == 0) {
2757c478bd9Sstevel@tonic-gate /*
2767c478bd9Sstevel@tonic-gate * Always accept starting cyl 0 if the size is 0 also
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate b_cylno = 0;
2797c478bd9Sstevel@tonic-gate } else {
2807c478bd9Sstevel@tonic-gate b_cylno = cyl_offset;
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate #endif /* defined(i386) */
2837c478bd9Sstevel@tonic-gate if (pptr->pinfo_map[i].dkl_cylno < b_cylno ||
2847c478bd9Sstevel@tonic-gate pptr->pinfo_map[i].dkl_cylno > (ncyl-1)) {
2857c478bd9Sstevel@tonic-gate err_print(
2867c478bd9Sstevel@tonic-gate "partition %c: starting cylinder %d is out of range\n",
2877c478bd9Sstevel@tonic-gate (PARTITION_BASE+i),
2887c478bd9Sstevel@tonic-gate pptr->pinfo_map[i].dkl_cylno);
2897c478bd9Sstevel@tonic-gate return (0);
2907c478bd9Sstevel@tonic-gate }
291ec74a236Syu, larry liu - Sun Microsystems - Beijing China if (pptr->pinfo_map[i].dkl_nblk > ((ncyl -
2927c478bd9Sstevel@tonic-gate pptr->pinfo_map[i].dkl_cylno) * spc())) {
2937c478bd9Sstevel@tonic-gate err_print(
294342440ecSPrasad Singamsetty "partition %c: specified # of blocks, %u, "
295342440ecSPrasad Singamsetty "is out of range\n",
2967c478bd9Sstevel@tonic-gate (PARTITION_BASE+i),
2977c478bd9Sstevel@tonic-gate pptr->pinfo_map[i].dkl_nblk);
2987c478bd9Sstevel@tonic-gate return (0);
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate /*
3027c478bd9Sstevel@tonic-gate * Lock out interrupts so the lists don't get mangled.
3037c478bd9Sstevel@tonic-gate */
3047c478bd9Sstevel@tonic-gate enter_critical();
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate * If the old current map is unnamed, delete it.
3077c478bd9Sstevel@tonic-gate */
3087c478bd9Sstevel@tonic-gate if (cur_parts != NULL && cur_parts != pptr &&
3097c478bd9Sstevel@tonic-gate cur_parts->pinfo_name == NULL)
3107c478bd9Sstevel@tonic-gate delete_partition(cur_parts);
3117c478bd9Sstevel@tonic-gate /*
3127c478bd9Sstevel@tonic-gate * Make the selected map current.
3137c478bd9Sstevel@tonic-gate */
3147c478bd9Sstevel@tonic-gate cur_disk->disk_parts = cur_parts = pptr;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
3177c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
3187c478bd9Sstevel@tonic-gate cur_parts->vtoc.v_part[i].p_start =
319342440ecSPrasad Singamsetty (blkaddr_t)(cur_parts->pinfo_map[i].dkl_cylno *
3207c478bd9Sstevel@tonic-gate (nhead * nsect));
3217c478bd9Sstevel@tonic-gate cur_parts->vtoc.v_part[i].p_size =
322342440ecSPrasad Singamsetty (blkaddr_t)cur_parts->pinfo_map[i].dkl_nblk;
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate exit_critical();
3277c478bd9Sstevel@tonic-gate fmt_print("\n");
3287c478bd9Sstevel@tonic-gate return (0);
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate /*
3327c478bd9Sstevel@tonic-gate * This routine implements the 'name' command. It allows the user
3337c478bd9Sstevel@tonic-gate * to name the current partition map. If the map was already named,
3347c478bd9Sstevel@tonic-gate * the name is changed. Once a map is named, the values of the partitions
3357c478bd9Sstevel@tonic-gate * cannot be changed. Attempts to change them will cause another map
3367c478bd9Sstevel@tonic-gate * to be created.
3377c478bd9Sstevel@tonic-gate */
3387c478bd9Sstevel@tonic-gate int
p_name()3397c478bd9Sstevel@tonic-gate p_name()
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate char *name;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate /*
3447c478bd9Sstevel@tonic-gate * check if there exists a partition table for the disk.
3457c478bd9Sstevel@tonic-gate */
3467c478bd9Sstevel@tonic-gate if (cur_parts == NULL) {
3477c478bd9Sstevel@tonic-gate err_print("Current Disk has no partition table.\n");
3487c478bd9Sstevel@tonic-gate return (-1);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate * Ask for the name. Note that the input routine will malloc
3547c478bd9Sstevel@tonic-gate * space for the name since we are using the OSTR input type.
3557c478bd9Sstevel@tonic-gate */
356052b6e8aSbg159949 name = (char *)(uintptr_t)input(FIO_OSTR,
357052b6e8aSbg159949 "Enter table name (remember quotes)",
3587c478bd9Sstevel@tonic-gate ':', (u_ioparam_t *)NULL, (int *)NULL, DATA_INPUT);
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate * Lock out interrupts.
3617c478bd9Sstevel@tonic-gate */
3627c478bd9Sstevel@tonic-gate enter_critical();
3637c478bd9Sstevel@tonic-gate /*
3647c478bd9Sstevel@tonic-gate * If it was already named, destroy the old name.
3657c478bd9Sstevel@tonic-gate */
3667c478bd9Sstevel@tonic-gate if (cur_parts->pinfo_name != NULL)
3677c478bd9Sstevel@tonic-gate destroy_data(cur_parts->pinfo_name);
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate * Set the name.
3707c478bd9Sstevel@tonic-gate */
3717c478bd9Sstevel@tonic-gate cur_parts->pinfo_name = name;
3727c478bd9Sstevel@tonic-gate exit_critical();
3737c478bd9Sstevel@tonic-gate fmt_print("\n");
3747c478bd9Sstevel@tonic-gate return (0);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate * This routine implements the 'print' command. It lists the values
3807c478bd9Sstevel@tonic-gate * for all the partitions in the current partition map.
3817c478bd9Sstevel@tonic-gate */
3827c478bd9Sstevel@tonic-gate int
p_print()3837c478bd9Sstevel@tonic-gate p_print()
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate /*
3867c478bd9Sstevel@tonic-gate * check if there exists a partition table for the disk.
3877c478bd9Sstevel@tonic-gate */
3887c478bd9Sstevel@tonic-gate if (cur_parts == NULL) {
3897c478bd9Sstevel@tonic-gate err_print("Current Disk has no partition table.\n");
3907c478bd9Sstevel@tonic-gate return (-1);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate /*
3947c478bd9Sstevel@tonic-gate * Print the volume name, if it appears to be set
3957c478bd9Sstevel@tonic-gate */
3967c478bd9Sstevel@tonic-gate if (chk_volname(cur_disk)) {
3977c478bd9Sstevel@tonic-gate fmt_print("Volume: ");
3987c478bd9Sstevel@tonic-gate print_volname(cur_disk);
3997c478bd9Sstevel@tonic-gate fmt_print("\n");
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate * Print the name of the current map.
4037c478bd9Sstevel@tonic-gate */
4047c478bd9Sstevel@tonic-gate if ((cur_parts->pinfo_name != NULL) && (cur_label == L_TYPE_SOLARIS)) {
4057c478bd9Sstevel@tonic-gate fmt_print("Current partition table (%s):\n",
4067c478bd9Sstevel@tonic-gate cur_parts->pinfo_name);
407*3a5b922fSbo zhou - Sun Microsystems - Beijing China fmt_print("Total disk cylinders available: %d + %d "
408*3a5b922fSbo zhou - Sun Microsystems - Beijing China "(reserved cylinders)\n\n", ncyl, acyl);
4097c478bd9Sstevel@tonic-gate } else if (cur_label == L_TYPE_SOLARIS) {
4107c478bd9Sstevel@tonic-gate fmt_print("Current partition table (unnamed):\n");
411*3a5b922fSbo zhou - Sun Microsystems - Beijing China fmt_print("Total disk cylinders available: %d + %d "
412*3a5b922fSbo zhou - Sun Microsystems - Beijing China "(reserved cylinders)\n\n", ncyl, acyl);
4137c478bd9Sstevel@tonic-gate } else if (cur_label == L_TYPE_EFI) {
414*3a5b922fSbo zhou - Sun Microsystems - Beijing China fmt_print("Current partition table (%s):\n",
415*3a5b922fSbo zhou - Sun Microsystems - Beijing China cur_parts->pinfo_name != NULL ?
416*3a5b922fSbo zhou - Sun Microsystems - Beijing China cur_parts->pinfo_name : "unnamed");
417*3a5b922fSbo zhou - Sun Microsystems - Beijing China fmt_print("Total disk sectors available: %llu + %d "
418*3a5b922fSbo zhou - Sun Microsystems - Beijing China "(reserved sectors)\n\n",
419*3a5b922fSbo zhou - Sun Microsystems - Beijing China cur_parts->etoc->efi_last_u_lba - EFI_MIN_RESV_SIZE -
420*3a5b922fSbo zhou - Sun Microsystems - Beijing China cur_parts->etoc->efi_first_u_lba + 1, EFI_MIN_RESV_SIZE);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate /*
4257c478bd9Sstevel@tonic-gate * Print the partition map itself
4267c478bd9Sstevel@tonic-gate */
4277c478bd9Sstevel@tonic-gate print_map(cur_parts);
4287c478bd9Sstevel@tonic-gate return (0);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate /*
4337c478bd9Sstevel@tonic-gate * Print a partition map
4347c478bd9Sstevel@tonic-gate */
4357c478bd9Sstevel@tonic-gate void
print_map(struct partition_info * map)4367c478bd9Sstevel@tonic-gate print_map(struct partition_info *map)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate int i;
4397c478bd9Sstevel@tonic-gate int want_header;
4407c478bd9Sstevel@tonic-gate struct dk_gpt *vtoc64;
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate if (cur_label == L_TYPE_EFI) {
4437c478bd9Sstevel@tonic-gate vtoc64 = map->etoc;
4447c478bd9Sstevel@tonic-gate want_header = 1;
4457c478bd9Sstevel@tonic-gate for (i = 0; i < vtoc64->efi_nparts; i++) {
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate * we want to print partitions above 7 in expert mode only
4487c478bd9Sstevel@tonic-gate * or if the partition is reserved
4497c478bd9Sstevel@tonic-gate */
4507c478bd9Sstevel@tonic-gate if (i >= 7 && !expert_mode &&
4517c478bd9Sstevel@tonic-gate ((int)vtoc64->efi_parts[i].p_tag !=
4527c478bd9Sstevel@tonic-gate V_RESERVED)) {
4537c478bd9Sstevel@tonic-gate continue;
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate print_efi_partition(vtoc64, i, want_header);
4577c478bd9Sstevel@tonic-gate want_header = 0;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate fmt_print("\n");
4607c478bd9Sstevel@tonic-gate return;
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate * Loop through each partition, printing the header
4647c478bd9Sstevel@tonic-gate * the first time.
4657c478bd9Sstevel@tonic-gate */
4667c478bd9Sstevel@tonic-gate want_header = 1;
4677c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
4687c478bd9Sstevel@tonic-gate if (i > 9) {
4697c478bd9Sstevel@tonic-gate break;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate print_partition(map, i, want_header);
4727c478bd9Sstevel@tonic-gate want_header = 0;
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate fmt_print("\n");
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
4787c478bd9Sstevel@tonic-gate /*
4797c478bd9Sstevel@tonic-gate * Print out one line of partition information,
4807c478bd9Sstevel@tonic-gate * with optional header for EFI type disks.
4817c478bd9Sstevel@tonic-gate */
4827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4837c478bd9Sstevel@tonic-gate void
print_efi_partition(struct dk_gpt * map,int partnum,int want_header)4847c478bd9Sstevel@tonic-gate print_efi_partition(struct dk_gpt *map, int partnum, int want_header)
4857c478bd9Sstevel@tonic-gate {
4867c478bd9Sstevel@tonic-gate int ncyl2_digits = 0;
4877c478bd9Sstevel@tonic-gate float scaled;
4887c478bd9Sstevel@tonic-gate char *s;
4897c478bd9Sstevel@tonic-gate uint64_t secsize;
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate ncyl2_digits = ndigits(map->efi_last_u_lba);
4927c478bd9Sstevel@tonic-gate if (want_header) {
4937c478bd9Sstevel@tonic-gate fmt_print("Part ");
4947c478bd9Sstevel@tonic-gate fmt_print("Tag Flag ");
4957c478bd9Sstevel@tonic-gate fmt_print("First Sector");
4967c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
4977c478bd9Sstevel@tonic-gate fmt_print("Size");
4987c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
4997c478bd9Sstevel@tonic-gate fmt_print("Last Sector\n");
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate fmt_print(" %d ", partnum);
5037c478bd9Sstevel@tonic-gate s = find_string(ptag_choices,
5047c478bd9Sstevel@tonic-gate (int)map->efi_parts[partnum].p_tag);
5057c478bd9Sstevel@tonic-gate if (s == (char *)NULL)
5067c478bd9Sstevel@tonic-gate s = "-";
5077c478bd9Sstevel@tonic-gate nspaces(10 - (int)strlen(s));
5087c478bd9Sstevel@tonic-gate fmt_print("%s", s);
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate s = find_string(pflag_choices,
5117c478bd9Sstevel@tonic-gate (int)map->efi_parts[partnum].p_flag);
5127c478bd9Sstevel@tonic-gate if (s == (char *)NULL)
5137c478bd9Sstevel@tonic-gate s = "-";
5147c478bd9Sstevel@tonic-gate nspaces(6 - (int)strlen(s));
5157c478bd9Sstevel@tonic-gate fmt_print("%s", s);
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate nspaces(2);
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate secsize = map->efi_parts[partnum].p_size;
5207c478bd9Sstevel@tonic-gate if (secsize == 0) {
5217c478bd9Sstevel@tonic-gate fmt_print("%16llu", map->efi_parts[partnum].p_start);
5227c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
5237c478bd9Sstevel@tonic-gate fmt_print(" 0 ");
5247c478bd9Sstevel@tonic-gate } else {
5257c478bd9Sstevel@tonic-gate fmt_print("%16llu", map->efi_parts[partnum].p_start);
5267c478bd9Sstevel@tonic-gate scaled = bn2mb(secsize);
5277c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits - 5);
5287c478bd9Sstevel@tonic-gate if (scaled >= (float)1024.0 * 1024) {
5297c478bd9Sstevel@tonic-gate fmt_print("%8.2fTB", scaled/((float)1024.0 * 1024));
5307c478bd9Sstevel@tonic-gate } else if (scaled >= (float)1024.0) {
5317c478bd9Sstevel@tonic-gate fmt_print("%8.2fGB", scaled/(float)1024.0);
5327c478bd9Sstevel@tonic-gate } else {
5337c478bd9Sstevel@tonic-gate fmt_print("%8.2fMB", scaled);
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
5377c478bd9Sstevel@tonic-gate if ((map->efi_parts[partnum].p_start+secsize - 1) ==
5387c478bd9Sstevel@tonic-gate UINT_MAX64) {
5397c478bd9Sstevel@tonic-gate fmt_print(" 0 \n");
5407c478bd9Sstevel@tonic-gate } else {
5417c478bd9Sstevel@tonic-gate fmt_print(" %llu \n",
5427c478bd9Sstevel@tonic-gate map->efi_parts[partnum].p_start+secsize - 1);
5437c478bd9Sstevel@tonic-gate }
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * Print out one line of partition information,
5487c478bd9Sstevel@tonic-gate * with optional header.
5497c478bd9Sstevel@tonic-gate */
5507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5517c478bd9Sstevel@tonic-gate void
print_partition(struct partition_info * pinfo,int partnum,int want_header)5527c478bd9Sstevel@tonic-gate print_partition(struct partition_info *pinfo, int partnum, int want_header)
5537c478bd9Sstevel@tonic-gate {
5547c478bd9Sstevel@tonic-gate int i;
555342440ecSPrasad Singamsetty blkaddr_t nblks;
5567c478bd9Sstevel@tonic-gate int cyl1;
5577c478bd9Sstevel@tonic-gate int cyl2;
5587c478bd9Sstevel@tonic-gate float scaled;
5597c478bd9Sstevel@tonic-gate int maxcyl2;
5607c478bd9Sstevel@tonic-gate int ncyl2_digits;
5617c478bd9Sstevel@tonic-gate char *s;
562342440ecSPrasad Singamsetty blkaddr_t maxnblks = 0;
563342440ecSPrasad Singamsetty blkaddr_t len;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate /*
5667c478bd9Sstevel@tonic-gate * To align things nicely, we need to know the maximum
5677c478bd9Sstevel@tonic-gate * width of the number of cylinders field.
5687c478bd9Sstevel@tonic-gate */
5697c478bd9Sstevel@tonic-gate maxcyl2 = 0;
5707c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
5717c478bd9Sstevel@tonic-gate nblks = (uint_t)pinfo->pinfo_map[i].dkl_nblk;
5727c478bd9Sstevel@tonic-gate cyl1 = pinfo->pinfo_map[i].dkl_cylno;
5737c478bd9Sstevel@tonic-gate cyl2 = cyl1 + (nblks / spc()) - 1;
5747c478bd9Sstevel@tonic-gate if (nblks > 0) {
5757c478bd9Sstevel@tonic-gate maxcyl2 = max(cyl2, maxcyl2);
5767c478bd9Sstevel@tonic-gate maxnblks = max(nblks, maxnblks);
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate }
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate * Get the number of digits required
5817c478bd9Sstevel@tonic-gate */
5827c478bd9Sstevel@tonic-gate ncyl2_digits = ndigits(maxcyl2);
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate /*
5857c478bd9Sstevel@tonic-gate * Print the header, if necessary
5867c478bd9Sstevel@tonic-gate */
5877c478bd9Sstevel@tonic-gate if (want_header) {
5887c478bd9Sstevel@tonic-gate fmt_print("Part ");
5897c478bd9Sstevel@tonic-gate fmt_print("Tag Flag ");
5907c478bd9Sstevel@tonic-gate fmt_print("Cylinders");
5917c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
5927c478bd9Sstevel@tonic-gate fmt_print(" Size Blocks\n");
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate
5957c478bd9Sstevel@tonic-gate /*
5967c478bd9Sstevel@tonic-gate * Print the partition information
5977c478bd9Sstevel@tonic-gate */
5987c478bd9Sstevel@tonic-gate nblks = pinfo->pinfo_map[partnum].dkl_nblk;
5997c478bd9Sstevel@tonic-gate cyl1 = pinfo->pinfo_map[partnum].dkl_cylno;
6007c478bd9Sstevel@tonic-gate cyl2 = cyl1 + (nblks / spc()) - 1;
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate fmt_print(" %x ", partnum);
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate /*
6057c478bd9Sstevel@tonic-gate * Print the partition tag. If invalid, print -
6067c478bd9Sstevel@tonic-gate */
6077c478bd9Sstevel@tonic-gate s = find_string(ptag_choices,
6087c478bd9Sstevel@tonic-gate (int)pinfo->vtoc.v_part[partnum].p_tag);
6097c478bd9Sstevel@tonic-gate if (s == (char *)NULL)
6107c478bd9Sstevel@tonic-gate s = "-";
6117c478bd9Sstevel@tonic-gate nspaces(10 - (int)strlen(s));
6127c478bd9Sstevel@tonic-gate fmt_print("%s", s);
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate * Print the partition flag. If invalid print -
6167c478bd9Sstevel@tonic-gate */
6177c478bd9Sstevel@tonic-gate s = find_string(pflag_choices,
6187c478bd9Sstevel@tonic-gate (int)pinfo->vtoc.v_part[partnum].p_flag);
6197c478bd9Sstevel@tonic-gate if (s == (char *)NULL)
6207c478bd9Sstevel@tonic-gate s = "-";
6217c478bd9Sstevel@tonic-gate nspaces(6 - (int)strlen(s));
6227c478bd9Sstevel@tonic-gate fmt_print("%s", s);
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate nspaces(2);
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate if (nblks == 0) {
6277c478bd9Sstevel@tonic-gate fmt_print("%6d ", cyl1);
6287c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits);
6297c478bd9Sstevel@tonic-gate fmt_print(" 0 ");
6307c478bd9Sstevel@tonic-gate } else {
6317c478bd9Sstevel@tonic-gate fmt_print("%6d - ", cyl1);
6327c478bd9Sstevel@tonic-gate nspaces(ncyl2_digits - ndigits(cyl2));
6337c478bd9Sstevel@tonic-gate fmt_print("%d ", cyl2);
6347c478bd9Sstevel@tonic-gate scaled = bn2mb(nblks);
6357c478bd9Sstevel@tonic-gate if (scaled > (float)1024.0 * 1024.0) {
6367c478bd9Sstevel@tonic-gate fmt_print("%8.2fTB ",
6377c478bd9Sstevel@tonic-gate scaled/((float)1024.0 * 1024.0));
6387c478bd9Sstevel@tonic-gate } else if (scaled > (float)1024.0) {
6397c478bd9Sstevel@tonic-gate fmt_print("%8.2fGB ", scaled/(float)1024.0);
6407c478bd9Sstevel@tonic-gate } else {
6417c478bd9Sstevel@tonic-gate fmt_print("%8.2fMB ", scaled);
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate fmt_print("(");
6457c478bd9Sstevel@tonic-gate pr_dblock(fmt_print, nblks);
6467c478bd9Sstevel@tonic-gate fmt_print(")");
6477c478bd9Sstevel@tonic-gate
6487c478bd9Sstevel@tonic-gate nspaces(ndigits(maxnblks/spc()) - ndigits(nblks/spc()));
6497c478bd9Sstevel@tonic-gate /*
6507c478bd9Sstevel@tonic-gate * Allocates size of the printf format string.
6517c478bd9Sstevel@tonic-gate * ndigits(ndigits(maxblks)) gives the byte size of
6527c478bd9Sstevel@tonic-gate * the printf width field for maxnblks.
6537c478bd9Sstevel@tonic-gate */
6547c478bd9Sstevel@tonic-gate len = strlen(" %") + ndigits(ndigits(maxnblks)) + strlen("d\n") + 1;
6557c478bd9Sstevel@tonic-gate s = zalloc(len);
656342440ecSPrasad Singamsetty (void) snprintf(s, len, "%s%u%s", " %", ndigits(maxnblks), "u\n");
6577c478bd9Sstevel@tonic-gate fmt_print(s, nblks);
6587c478bd9Sstevel@tonic-gate (void) free(s);
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate /*
6637c478bd9Sstevel@tonic-gate * Return true if a disk has a volume name
6647c478bd9Sstevel@tonic-gate */
6657c478bd9Sstevel@tonic-gate int
chk_volname(disk)6667c478bd9Sstevel@tonic-gate chk_volname(disk)
6677c478bd9Sstevel@tonic-gate struct disk_info *disk;
6687c478bd9Sstevel@tonic-gate {
6697c478bd9Sstevel@tonic-gate return (disk->v_volume[0] != 0);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate
6737c478bd9Sstevel@tonic-gate /*
6747c478bd9Sstevel@tonic-gate * Print the volume name, if it appears to be set
6757c478bd9Sstevel@tonic-gate */
6767c478bd9Sstevel@tonic-gate void
print_volname(disk)6777c478bd9Sstevel@tonic-gate print_volname(disk)
6787c478bd9Sstevel@tonic-gate struct disk_info *disk;
6797c478bd9Sstevel@tonic-gate {
6807c478bd9Sstevel@tonic-gate int i;
6817c478bd9Sstevel@tonic-gate char *p;
6827c478bd9Sstevel@tonic-gate
6837c478bd9Sstevel@tonic-gate p = disk->v_volume;
6847c478bd9Sstevel@tonic-gate for (i = 0; i < LEN_DKL_VVOL; i++, p++) {
6857c478bd9Sstevel@tonic-gate if (*p == 0)
6867c478bd9Sstevel@tonic-gate break;
6877c478bd9Sstevel@tonic-gate fmt_print("%c", *p);
6887c478bd9Sstevel@tonic-gate }
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate /*
6937c478bd9Sstevel@tonic-gate * Print a number of spaces
6947c478bd9Sstevel@tonic-gate */
6957c478bd9Sstevel@tonic-gate static void
nspaces(n)6967c478bd9Sstevel@tonic-gate nspaces(n)
6977c478bd9Sstevel@tonic-gate int n;
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate while (n-- > 0)
7007c478bd9Sstevel@tonic-gate fmt_print(" ");
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate /*
7047c478bd9Sstevel@tonic-gate * Return the number of digits required to print a number
7057c478bd9Sstevel@tonic-gate */
7067c478bd9Sstevel@tonic-gate static int
ndigits(n)7077c478bd9Sstevel@tonic-gate ndigits(n)
7087c478bd9Sstevel@tonic-gate uint64_t n;
7097c478bd9Sstevel@tonic-gate {
7107c478bd9Sstevel@tonic-gate int i;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate i = 0;
7137c478bd9Sstevel@tonic-gate while (n > 0) {
7147c478bd9Sstevel@tonic-gate n /= 10;
7157c478bd9Sstevel@tonic-gate i++;
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate return (i == 0 ? 1 : i);
7197c478bd9Sstevel@tonic-gate }
720