xref: /illumos-gate/usr/src/cmd/fdisk/fdisk.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
28*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
29*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1987, 1988 Microsoft Corporation	*/
32*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved	*/
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate /*
37*7c478bd9Sstevel@tonic-gate  * PROGRAM: fdisk(1M)
38*7c478bd9Sstevel@tonic-gate  * This program reads the partition table on the specified device and
39*7c478bd9Sstevel@tonic-gate  * also reads the drive parameters. The user can perform various
40*7c478bd9Sstevel@tonic-gate  * operations from a supplied menu or from the command line. Diagnostic
41*7c478bd9Sstevel@tonic-gate  * options are also available.
42*7c478bd9Sstevel@tonic-gate  */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include <stdio.h>
45*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
46*7c478bd9Sstevel@tonic-gate #include <string.h>
47*7c478bd9Sstevel@tonic-gate #include <unistd.h>
48*7c478bd9Sstevel@tonic-gate #include <errno.h>
49*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
50*7c478bd9Sstevel@tonic-gate #include <ctype.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/efi_partition.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/byteorder.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate #define	CLR_SCR ""
64*7c478bd9Sstevel@tonic-gate #define	CLR_LIN ""
65*7c478bd9Sstevel@tonic-gate #define	HOME "" \
66*7c478bd9Sstevel@tonic-gate 	""
67*7c478bd9Sstevel@tonic-gate #define	Q_LINE ""
68*7c478bd9Sstevel@tonic-gate #define	W_LINE ""
69*7c478bd9Sstevel@tonic-gate #define	E_LINE ""
70*7c478bd9Sstevel@tonic-gate #define	M_LINE "" \
71*7c478bd9Sstevel@tonic-gate 	""
72*7c478bd9Sstevel@tonic-gate #define	T_LINE ""
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate #define	DEFAULT_PATH	"/dev/rdsk/"
75*7c478bd9Sstevel@tonic-gate 
76*7c478bd9Sstevel@tonic-gate /* XXX - should be in fdisk.h, used by sd as well */
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate /*
79*7c478bd9Sstevel@tonic-gate  * the MAX values are the maximum usable values for BIOS chs values
80*7c478bd9Sstevel@tonic-gate  * The MAX_CYL value of 1022 is the maximum usable value
81*7c478bd9Sstevel@tonic-gate  *   the value of 1023 is a fence value,
82*7c478bd9Sstevel@tonic-gate  *   indicating no CHS geometry exists for the corresponding LBA value.
83*7c478bd9Sstevel@tonic-gate  * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
84*7c478bd9Sstevel@tonic-gate  * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
85*7c478bd9Sstevel@tonic-gate  */
86*7c478bd9Sstevel@tonic-gate #define	MAX_SECT	(63)
87*7c478bd9Sstevel@tonic-gate #define	MAX_CYL		(1022)
88*7c478bd9Sstevel@tonic-gate #define	MAX_HEAD	(254)
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate /* for clear_vtoc() */
91*7c478bd9Sstevel@tonic-gate #define	OLD		0
92*7c478bd9Sstevel@tonic-gate #define	NEW		1
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate /* readvtoc/writevtoc return codes */
95*7c478bd9Sstevel@tonic-gate #define	VTOC_OK		0	/* Good VTOC */
96*7c478bd9Sstevel@tonic-gate #define	VTOC_INVAL	1	/* invalid VTOC */
97*7c478bd9Sstevel@tonic-gate #define	VTOC_NOTSUP	2	/* operation not supported - EFI label */
98*7c478bd9Sstevel@tonic-gate #define	VTOC_RWERR	3	/* couldn't read or write VTOC */
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate /*
101*7c478bd9Sstevel@tonic-gate  * Support for fdisk(1M) on the SPARC platform
102*7c478bd9Sstevel@tonic-gate  *	In order to convert little endian values to big endian for SPARC,
103*7c478bd9Sstevel@tonic-gate  *	byte/short and long values must be swapped.
104*7c478bd9Sstevel@tonic-gate  *	These swapping macros will be used to access information in the
105*7c478bd9Sstevel@tonic-gate  *	mboot and ipart structures.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate #ifdef sparc
109*7c478bd9Sstevel@tonic-gate #define	les(val)	((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
110*7c478bd9Sstevel@tonic-gate #define	lel(val)	(((unsigned)(les((val)&0x0000FFFF))<<16) | \
111*7c478bd9Sstevel@tonic-gate 			    (les((unsigned)((val)&0xffff0000)>>16)))
112*7c478bd9Sstevel@tonic-gate #else
113*7c478bd9Sstevel@tonic-gate #define	les(val)	(val)
114*7c478bd9Sstevel@tonic-gate #define	lel(val)	(val)
115*7c478bd9Sstevel@tonic-gate #endif
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
118*7c478bd9Sstevel@tonic-gate #define	VTOC_OFFSET	512
119*7c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
120*7c478bd9Sstevel@tonic-gate #define	VTOC_OFFSET	0
121*7c478bd9Sstevel@tonic-gate #else
122*7c478bd9Sstevel@tonic-gate #error No VTOC format defined.
123*7c478bd9Sstevel@tonic-gate #endif
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate char Usage[] = "Usage: fdisk\n"
126*7c478bd9Sstevel@tonic-gate "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
127*7c478bd9Sstevel@tonic-gate "[ -b masterboot ]\n"
128*7c478bd9Sstevel@tonic-gate "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
129*7c478bd9Sstevel@tonic-gate "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
130*7c478bd9Sstevel@tonic-gate "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
131*7c478bd9Sstevel@tonic-gate "[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate char Usage1[] = "    Partition options:\n"
134*7c478bd9Sstevel@tonic-gate "	-A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
135*7c478bd9Sstevel@tonic-gate "		Create a partition with specific attributes:\n"
136*7c478bd9Sstevel@tonic-gate "		id      = system id number (fdisk.h) for the partition type\n"
137*7c478bd9Sstevel@tonic-gate "		act     = active partition flag (0 is off and 128 is on)\n"
138*7c478bd9Sstevel@tonic-gate "		bhead   = beginning head for start of partition\n"
139*7c478bd9Sstevel@tonic-gate "		bsect   = beginning sector for start of partition\n"
140*7c478bd9Sstevel@tonic-gate "		bcyl    = beginning cylinder for start of partition\n"
141*7c478bd9Sstevel@tonic-gate "		ehead   = ending head for end of partition\n"
142*7c478bd9Sstevel@tonic-gate "		esect   = ending sector for end of partition\n"
143*7c478bd9Sstevel@tonic-gate "		ecyl    = ending cylinder for end of partition\n"
144*7c478bd9Sstevel@tonic-gate "		rsect   = sector number from start of disk for\n"
145*7c478bd9Sstevel@tonic-gate "			  start of partition\n"
146*7c478bd9Sstevel@tonic-gate "		numsect = partition size in sectors\n"
147*7c478bd9Sstevel@tonic-gate "	-b master_boot\n"
148*7c478bd9Sstevel@tonic-gate "		Use master_boot as the master boot file.\n"
149*7c478bd9Sstevel@tonic-gate "	-B	Create one Solaris partition that uses the entire disk.\n"
150*7c478bd9Sstevel@tonic-gate "	-E	Create one EFI partition that uses the entire disk.\n"
151*7c478bd9Sstevel@tonic-gate "	-D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
152*7c478bd9Sstevel@tonic-gate "		Delete a partition. See attribute definitions for -A.\n"
153*7c478bd9Sstevel@tonic-gate "	-F fdisk_file\n"
154*7c478bd9Sstevel@tonic-gate "		Use fdisk_file to initialize on-line fdisk table.\n"
155*7c478bd9Sstevel@tonic-gate "	-I	Forego device checks. Generate a file image of what would go\n"
156*7c478bd9Sstevel@tonic-gate "		on a disk using the geometry specified with the -S option.\n"
157*7c478bd9Sstevel@tonic-gate "	-n	Do not run in interactive mode.\n"
158*7c478bd9Sstevel@tonic-gate "	-R	Open the disk device as read-only.\n"
159*7c478bd9Sstevel@tonic-gate "	-t	Check and adjust VTOC to be consistent with fdisk table.\n"
160*7c478bd9Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be truncated.\n"
161*7c478bd9Sstevel@tonic-gate "	-T	Check and adjust VTOC to be consistent with fdisk table.\n"
162*7c478bd9Sstevel@tonic-gate "		VTOC slices exceeding the partition size will be removed.\n"
163*7c478bd9Sstevel@tonic-gate "	-W fdisk_file\n"
164*7c478bd9Sstevel@tonic-gate "		Write on-disk table to fdisk_file.\n"
165*7c478bd9Sstevel@tonic-gate "	-W -	Write on-disk table to standard output.\n"
166*7c478bd9Sstevel@tonic-gate "	-v	Display virtual geometry. Must be used with the -W option.\n"
167*7c478bd9Sstevel@tonic-gate "    Diagnostic options:\n"
168*7c478bd9Sstevel@tonic-gate "	-d	Activate debug information about progress.\n"
169*7c478bd9Sstevel@tonic-gate "	-g	Write label geometry to standard output:\n"
170*7c478bd9Sstevel@tonic-gate "		PCYL		number of physical cylinders\n"
171*7c478bd9Sstevel@tonic-gate "		NCYL		number of usable cylinders\n"
172*7c478bd9Sstevel@tonic-gate "		ACYL		number of alternate cylinders\n"
173*7c478bd9Sstevel@tonic-gate "		BCYL		cylinder offset\n"
174*7c478bd9Sstevel@tonic-gate "		NHEADS		number of heads\n"
175*7c478bd9Sstevel@tonic-gate "		NSECTORS	number of sectors per track\n"
176*7c478bd9Sstevel@tonic-gate "		SECTSIZ		size of a sector in bytes\n"
177*7c478bd9Sstevel@tonic-gate "	-G	Write physical geometry to standard output (see -g).\n"
178*7c478bd9Sstevel@tonic-gate "	-h	Issue this verbose help message.\n"
179*7c478bd9Sstevel@tonic-gate "	-o offset\n"
180*7c478bd9Sstevel@tonic-gate "		Block offset from start of disk (default 0). Ignored if\n"
181*7c478bd9Sstevel@tonic-gate "		-P # specified.\n"
182*7c478bd9Sstevel@tonic-gate "	-P fill_patt\n"
183*7c478bd9Sstevel@tonic-gate "		Fill disk with pattern fill_patt. fill_patt can be decimal or\n"
184*7c478bd9Sstevel@tonic-gate "		hexadecimal and is used as number for constant long word\n"
185*7c478bd9Sstevel@tonic-gate "		pattern. If fill_patt is \"#\" then pattern of block #\n"
186*7c478bd9Sstevel@tonic-gate "		for each block. Pattern is put in each block as long words\n"
187*7c478bd9Sstevel@tonic-gate "		and fills each block (see -o and -s).\n"
188*7c478bd9Sstevel@tonic-gate "	-r	Read from a disk to stdout (see -o and -s).\n"
189*7c478bd9Sstevel@tonic-gate "	-s size	Number of blocks on which to perform operation (see -o).\n"
190*7c478bd9Sstevel@tonic-gate "	-S geom_file\n"
191*7c478bd9Sstevel@tonic-gate "		Use geom_file to set the label geometry (see -g).\n"
192*7c478bd9Sstevel@tonic-gate "	-w	Write to a disk from stdin (see -o and -s).";
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate char Ostr[] = "Other OS";
195*7c478bd9Sstevel@tonic-gate char Dstr[] = "DOS12";
196*7c478bd9Sstevel@tonic-gate char D16str[] = "DOS16";
197*7c478bd9Sstevel@tonic-gate char DDstr[] = "DOS-DATA";
198*7c478bd9Sstevel@tonic-gate char EDstr[] = "EXT-DOS";
199*7c478bd9Sstevel@tonic-gate char DBstr[] = "DOS-BIG";
200*7c478bd9Sstevel@tonic-gate char PCstr[] = "PCIX";
201*7c478bd9Sstevel@tonic-gate char Ustr[] = "UNIX System";
202*7c478bd9Sstevel@tonic-gate char SUstr[] = "Solaris";
203*7c478bd9Sstevel@tonic-gate char SU2str[] = "Solaris2";
204*7c478bd9Sstevel@tonic-gate char X86str[] = "x86 Boot";
205*7c478bd9Sstevel@tonic-gate char DIAGstr[] = "Diagnostic";
206*7c478bd9Sstevel@tonic-gate char IFSstr[] = "IFS: NTFS";
207*7c478bd9Sstevel@tonic-gate char AIXstr[] = "AIX Boot";
208*7c478bd9Sstevel@tonic-gate char AIXDstr[] = "AIX Data";
209*7c478bd9Sstevel@tonic-gate char OS2str[] = "OS/2 Boot";
210*7c478bd9Sstevel@tonic-gate char WINstr[] = "Win95 FAT32";
211*7c478bd9Sstevel@tonic-gate char EWINstr[] = "Ext Win95";
212*7c478bd9Sstevel@tonic-gate char FAT95str[] = "FAT16 LBA";
213*7c478bd9Sstevel@tonic-gate char EXTLstr[] = "EXT LBA";
214*7c478bd9Sstevel@tonic-gate char LINUXstr[] = "Linux";
215*7c478bd9Sstevel@tonic-gate char CPMstr[] = "CP/M";
216*7c478bd9Sstevel@tonic-gate char NOVstr[] = "Netware 3.x+";
217*7c478bd9Sstevel@tonic-gate char QNXstr[] = "QNX 4.x";
218*7c478bd9Sstevel@tonic-gate char QNX2str[] = "QNX part 2";
219*7c478bd9Sstevel@tonic-gate char QNX3str[] = "QNX part 3";
220*7c478bd9Sstevel@tonic-gate char LINNATstr[] = "Linux native";
221*7c478bd9Sstevel@tonic-gate char NTFSVOL1str[] = "NT volset 1";
222*7c478bd9Sstevel@tonic-gate char NTFSVOL2str[] = "NT volset 2";
223*7c478bd9Sstevel@tonic-gate char BSDstr[] = "BSD OS";
224*7c478bd9Sstevel@tonic-gate char NEXTSTEPstr[] = "NeXTSTEP";
225*7c478bd9Sstevel@tonic-gate char BSDIFSstr[] = "BSDI FS";
226*7c478bd9Sstevel@tonic-gate char BSDISWAPstr[] = "BSDI swap";
227*7c478bd9Sstevel@tonic-gate char Actvstr[] = "Active";
228*7c478bd9Sstevel@tonic-gate char EFIstr[] = "EFI";
229*7c478bd9Sstevel@tonic-gate char NAstr[] = "      ";
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate /* All the user options and flags */
232*7c478bd9Sstevel@tonic-gate char *Dfltdev;			/* name of fixed disk drive */
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate /* Diagnostic options */
235*7c478bd9Sstevel@tonic-gate int	io_wrt = 0;		/* write standard input to disk (-w) */
236*7c478bd9Sstevel@tonic-gate int	io_rd = 0;		/* read from disk and write to stdout (-r) */
237*7c478bd9Sstevel@tonic-gate char	*io_fatt;		/* user supplied pattern (-P pattern) */
238*7c478bd9Sstevel@tonic-gate int	io_patt = 0;		/* write a pattern to disk (-P pattern) */
239*7c478bd9Sstevel@tonic-gate int	io_lgeom = 0;		/* get label geometry (-g) */
240*7c478bd9Sstevel@tonic-gate int	io_pgeom = 0;		/* get drive physical geometry (-G) */
241*7c478bd9Sstevel@tonic-gate char	*io_sgeom = 0;		/* set label geometry (-S geom_file) */
242*7c478bd9Sstevel@tonic-gate int	io_readonly = 0;		/* do not write to disk (-R) */
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate /* The -o offset and -s size options specify the area of the disk on */
245*7c478bd9Sstevel@tonic-gate /* which to perform the particular operation; i.e., -P, -r, or -w. */
246*7c478bd9Sstevel@tonic-gate int	io_offset = 0;		/* offset sector (-o offset) */
247*7c478bd9Sstevel@tonic-gate int	io_size = 0;		/* size in sectors (-s size) */
248*7c478bd9Sstevel@tonic-gate 
249*7c478bd9Sstevel@tonic-gate /* Partition table flags */
250*7c478bd9Sstevel@tonic-gate int	v_flag = 0;		/* virtual geometry-HBA flag (-v) */
251*7c478bd9Sstevel@tonic-gate int 	stdo_flag = 0;		/* stdout flag (-W -) */
252*7c478bd9Sstevel@tonic-gate int	io_fdisk = 0;		/* do fdisk operation */
253*7c478bd9Sstevel@tonic-gate int	io_ifdisk = 0;		/* interactive partition */
254*7c478bd9Sstevel@tonic-gate int	io_nifdisk = 0;		/* non-interactive partition (-n) */
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate int	io_adjt = 0;		/* check and adjust VTOC (truncate (-t)) */
257*7c478bd9Sstevel@tonic-gate int	io_ADJT = 0;		/* check and adjust VTOC (delete (-T)) */
258*7c478bd9Sstevel@tonic-gate char	*io_ffdisk = 0;		/* name of input fdisk file (-F file) */
259*7c478bd9Sstevel@tonic-gate char	*io_Wfdisk = 0;		/* name of output fdisk file (-W file) */
260*7c478bd9Sstevel@tonic-gate char	*io_Afdisk = 0;		/* entry to add to partition table (-A) */
261*7c478bd9Sstevel@tonic-gate char	*io_Dfdisk = 0;		/* entry to delete from partition table (-D) */
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate char	*io_mboot = 0;		/* master boot record (-b boot_file) */
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate struct mboot BootCod;		/* buffer for master boot record */
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate int	io_wholedisk = 0;	/* use whole disk for Solaris partition (-B) */
268*7c478bd9Sstevel@tonic-gate int	io_EFIdisk = 0;		/* use whole disk for EFI partition (-E) */
269*7c478bd9Sstevel@tonic-gate int	io_debug = 0;		/* activate verbose mode (-d) */
270*7c478bd9Sstevel@tonic-gate int	io_image = 0;		/* create image using supplied geometry (-I) */
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate struct mboot *Bootblk;		/* pointer to cut and paste sector zero */
273*7c478bd9Sstevel@tonic-gate char	*Bootsect;		/* pointer to sector zero buffer */
274*7c478bd9Sstevel@tonic-gate char	*Nullsect;
275*7c478bd9Sstevel@tonic-gate struct vtoc	disk_vtoc;	/* verify VTOC table */
276*7c478bd9Sstevel@tonic-gate int	vt_inval = 0;
277*7c478bd9Sstevel@tonic-gate int	no_virtgeom_ioctl = 0;	/* ioctl for virtual geometry failed */
278*7c478bd9Sstevel@tonic-gate int	no_physgeom_ioctl = 0;	/* ioctl for physical geometry failed */
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate struct ipart	Table[FD_NUMPART];
281*7c478bd9Sstevel@tonic-gate struct ipart	Old_Table[FD_NUMPART];
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate /* Disk geometry information */
284*7c478bd9Sstevel@tonic-gate struct dk_geom	disk_geom;
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate int Dev;			/* fd for open device */
287*7c478bd9Sstevel@tonic-gate /* Physical geometry for the drive */
288*7c478bd9Sstevel@tonic-gate int	Numcyl;			/* number of cylinders */
289*7c478bd9Sstevel@tonic-gate int	heads;			/* number of heads */
290*7c478bd9Sstevel@tonic-gate int	sectors;		/* number of sectors per track */
291*7c478bd9Sstevel@tonic-gate int	acyl;			/* number of alternate sectors */
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate /* HBA (virtual) geometry for the drive */
294*7c478bd9Sstevel@tonic-gate int	hba_Numcyl;		/* number of cylinders */
295*7c478bd9Sstevel@tonic-gate int	hba_heads;		/* number of heads */
296*7c478bd9Sstevel@tonic-gate int	hba_sectors;		/* number of sectors per track */
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate int	sectsiz;		/* sector size */
299*7c478bd9Sstevel@tonic-gate int	drtype;			/* Type of drive; i.e., scsi, floppy, ... */
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate /* Load functions for fdisk table modification */
302*7c478bd9Sstevel@tonic-gate #define	LOADFILE	0	/* load fdisk from file */
303*7c478bd9Sstevel@tonic-gate #define	LOADDEL		1	/* delete an fdisk entry */
304*7c478bd9Sstevel@tonic-gate #define	LOADADD		2	/* add an fdisk entry */
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate #define	CBUFLEN 80
307*7c478bd9Sstevel@tonic-gate char s[CBUFLEN];
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate void		sanity_check_provided_device(char *devname, int fd);
310*7c478bd9Sstevel@tonic-gate static int	clear_vtoc(int table, int part);
311*7c478bd9Sstevel@tonic-gate static char	*get_node(char *devname);
312*7c478bd9Sstevel@tonic-gate static void	Set_Table_CHS_Values(int ti);
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate static void
315*7c478bd9Sstevel@tonic-gate update_disk_and_exit(boolean_t table_changed)
316*7c478bd9Sstevel@tonic-gate {
317*7c478bd9Sstevel@tonic-gate 	if (table_changed) {
318*7c478bd9Sstevel@tonic-gate 		/*
319*7c478bd9Sstevel@tonic-gate 		 * Copy the new table back to the sector buffer
320*7c478bd9Sstevel@tonic-gate 		 * and write it to disk
321*7c478bd9Sstevel@tonic-gate 		 */
322*7c478bd9Sstevel@tonic-gate 		copy_Table_to_Bootblk();
323*7c478bd9Sstevel@tonic-gate 		dev_mboot_write(0, Bootsect, sectsiz);
324*7c478bd9Sstevel@tonic-gate 	}
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	/* If the VTOC table is wrong fix it (truncation only) */
327*7c478bd9Sstevel@tonic-gate 	if (io_adjt)
328*7c478bd9Sstevel@tonic-gate 		fix_slice();
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	exit(0);
331*7c478bd9Sstevel@tonic-gate }
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate /*
336*7c478bd9Sstevel@tonic-gate  * main
337*7c478bd9Sstevel@tonic-gate  * Process command-line options.
338*7c478bd9Sstevel@tonic-gate  */
339*7c478bd9Sstevel@tonic-gate void
340*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[])
341*7c478bd9Sstevel@tonic-gate {
342*7c478bd9Sstevel@tonic-gate 	int c, i, j;
343*7c478bd9Sstevel@tonic-gate 	extern	int optind;
344*7c478bd9Sstevel@tonic-gate 	extern	char *optarg;
345*7c478bd9Sstevel@tonic-gate 	int	errflg = 0;
346*7c478bd9Sstevel@tonic-gate 	int	diag_cnt = 0;
347*7c478bd9Sstevel@tonic-gate 	int openmode;
348*7c478bd9Sstevel@tonic-gate 	int check_support_fdisk();
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	setbuf(stderr, 0);	/* so all output gets out on exit */
351*7c478bd9Sstevel@tonic-gate 	setbuf(stdout, 0);
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	/* Process the options. */
354*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
355*7c478bd9Sstevel@tonic-gate 	    != EOF) {
356*7c478bd9Sstevel@tonic-gate 		switch (c) {
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 			case 'o':
359*7c478bd9Sstevel@tonic-gate 				io_offset = strtoul(optarg, 0, 0);
360*7c478bd9Sstevel@tonic-gate 				continue;
361*7c478bd9Sstevel@tonic-gate 			case 's':
362*7c478bd9Sstevel@tonic-gate 				io_size = strtoul(optarg, 0, 0);
363*7c478bd9Sstevel@tonic-gate 				continue;
364*7c478bd9Sstevel@tonic-gate 			case 'P':
365*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
366*7c478bd9Sstevel@tonic-gate 				io_patt++;
367*7c478bd9Sstevel@tonic-gate 				io_fatt = optarg;
368*7c478bd9Sstevel@tonic-gate 				continue;
369*7c478bd9Sstevel@tonic-gate 			case 'w':
370*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
371*7c478bd9Sstevel@tonic-gate 				io_wrt++;
372*7c478bd9Sstevel@tonic-gate 				continue;
373*7c478bd9Sstevel@tonic-gate 			case 'r':
374*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
375*7c478bd9Sstevel@tonic-gate 				io_rd++;
376*7c478bd9Sstevel@tonic-gate 				continue;
377*7c478bd9Sstevel@tonic-gate 			case 'd':
378*7c478bd9Sstevel@tonic-gate 				io_debug++;
379*7c478bd9Sstevel@tonic-gate 				continue;
380*7c478bd9Sstevel@tonic-gate 			case 'I':
381*7c478bd9Sstevel@tonic-gate 				io_image++;
382*7c478bd9Sstevel@tonic-gate 				continue;
383*7c478bd9Sstevel@tonic-gate 			case 'R':
384*7c478bd9Sstevel@tonic-gate 				io_readonly++;
385*7c478bd9Sstevel@tonic-gate 				continue;
386*7c478bd9Sstevel@tonic-gate 			case 'S':
387*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
388*7c478bd9Sstevel@tonic-gate 				io_sgeom = optarg;
389*7c478bd9Sstevel@tonic-gate 				continue;
390*7c478bd9Sstevel@tonic-gate 			case 'T':
391*7c478bd9Sstevel@tonic-gate 				io_ADJT++;
392*7c478bd9Sstevel@tonic-gate 			case 't':
393*7c478bd9Sstevel@tonic-gate 				io_adjt++;
394*7c478bd9Sstevel@tonic-gate 				continue;
395*7c478bd9Sstevel@tonic-gate 			case 'B':
396*7c478bd9Sstevel@tonic-gate 				io_wholedisk++;
397*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
398*7c478bd9Sstevel@tonic-gate 				continue;
399*7c478bd9Sstevel@tonic-gate 			case 'E':
400*7c478bd9Sstevel@tonic-gate 				io_EFIdisk++;
401*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
402*7c478bd9Sstevel@tonic-gate 				continue;
403*7c478bd9Sstevel@tonic-gate 			case 'g':
404*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
405*7c478bd9Sstevel@tonic-gate 				io_lgeom++;
406*7c478bd9Sstevel@tonic-gate 				continue;
407*7c478bd9Sstevel@tonic-gate 			case 'G':
408*7c478bd9Sstevel@tonic-gate 				diag_cnt++;
409*7c478bd9Sstevel@tonic-gate 				io_pgeom++;
410*7c478bd9Sstevel@tonic-gate 				continue;
411*7c478bd9Sstevel@tonic-gate 			case 'n':
412*7c478bd9Sstevel@tonic-gate 				io_nifdisk++;
413*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
414*7c478bd9Sstevel@tonic-gate 				continue;
415*7c478bd9Sstevel@tonic-gate 			case 'F':
416*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
417*7c478bd9Sstevel@tonic-gate 				io_ffdisk = optarg;
418*7c478bd9Sstevel@tonic-gate 				continue;
419*7c478bd9Sstevel@tonic-gate 			case 'b':
420*7c478bd9Sstevel@tonic-gate 				io_mboot = optarg;
421*7c478bd9Sstevel@tonic-gate 				continue;
422*7c478bd9Sstevel@tonic-gate 			case 'W':
423*7c478bd9Sstevel@tonic-gate 				/*
424*7c478bd9Sstevel@tonic-gate 				 * If '-' is the -W argument, then write
425*7c478bd9Sstevel@tonic-gate 				 * to standard output, otherwise write
426*7c478bd9Sstevel@tonic-gate 				 * to the specified file.
427*7c478bd9Sstevel@tonic-gate 				 */
428*7c478bd9Sstevel@tonic-gate 				if (strncmp(optarg, "-", 1) == 0)
429*7c478bd9Sstevel@tonic-gate 					stdo_flag = 1;
430*7c478bd9Sstevel@tonic-gate 				else
431*7c478bd9Sstevel@tonic-gate 					io_Wfdisk = optarg;
432*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
433*7c478bd9Sstevel@tonic-gate 				continue;
434*7c478bd9Sstevel@tonic-gate 			case 'A':
435*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
436*7c478bd9Sstevel@tonic-gate 				io_Afdisk = optarg;
437*7c478bd9Sstevel@tonic-gate 				continue;
438*7c478bd9Sstevel@tonic-gate 			case 'D':
439*7c478bd9Sstevel@tonic-gate 				io_fdisk++;
440*7c478bd9Sstevel@tonic-gate 				io_Dfdisk = optarg;
441*7c478bd9Sstevel@tonic-gate 				continue;
442*7c478bd9Sstevel@tonic-gate 			case 'h':
443*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s\n", Usage);
444*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "%s\n", Usage1);
445*7c478bd9Sstevel@tonic-gate 				exit(0);
446*7c478bd9Sstevel@tonic-gate 			case 'v':
447*7c478bd9Sstevel@tonic-gate 				v_flag = 1;
448*7c478bd9Sstevel@tonic-gate 				continue;
449*7c478bd9Sstevel@tonic-gate 			case '?':
450*7c478bd9Sstevel@tonic-gate 				errflg++;
451*7c478bd9Sstevel@tonic-gate 				break;
452*7c478bd9Sstevel@tonic-gate 		}
453*7c478bd9Sstevel@tonic-gate 		break;
454*7c478bd9Sstevel@tonic-gate 	}
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	if (io_image && io_sgeom && diag_cnt == 1) {
457*7c478bd9Sstevel@tonic-gate 		diag_cnt = 0;
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 	/* User option checking */
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	/* By default, run in interactive mode */
463*7c478bd9Sstevel@tonic-gate 	if (!io_fdisk && !diag_cnt && !io_nifdisk) {
464*7c478bd9Sstevel@tonic-gate 		io_ifdisk++;
465*7c478bd9Sstevel@tonic-gate 		io_fdisk++;
466*7c478bd9Sstevel@tonic-gate 	}
467*7c478bd9Sstevel@tonic-gate 	if (((io_fdisk || io_adjt) && diag_cnt) || (diag_cnt > 1)) {
468*7c478bd9Sstevel@tonic-gate 		errflg++;
469*7c478bd9Sstevel@tonic-gate 	}
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 	/* Was any error detected? */
472*7c478bd9Sstevel@tonic-gate 	if (errflg || argc == optind) {
473*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%s\n", Usage);
474*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
475*7c478bd9Sstevel@tonic-gate 		    "\nDetailed help is available with the -h option.\n");
476*7c478bd9Sstevel@tonic-gate 		exit(2);
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	/* Figure out the correct device node to open */
481*7c478bd9Sstevel@tonic-gate 	Dfltdev = get_node(argv[optind]);
482*7c478bd9Sstevel@tonic-gate 
483*7c478bd9Sstevel@tonic-gate 	if (io_readonly)
484*7c478bd9Sstevel@tonic-gate 		openmode = O_RDONLY;
485*7c478bd9Sstevel@tonic-gate 	else
486*7c478bd9Sstevel@tonic-gate 		openmode = O_RDWR|O_CREAT;
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	if ((Dev = open(Dfltdev, openmode, 0666)) == -1) {
489*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "fdisk: Cannot open device %s.\n", Dfltdev);
490*7c478bd9Sstevel@tonic-gate 		exit(1);
491*7c478bd9Sstevel@tonic-gate 	}
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	/* Get the disk geometry */
494*7c478bd9Sstevel@tonic-gate 	if (!io_image) {
495*7c478bd9Sstevel@tonic-gate 		/* Get disk's HBA (virtual) geometry */
496*7c478bd9Sstevel@tonic-gate 		errno = 0;
497*7c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_VIRTGEOM, &disk_geom)) {
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 			/*
500*7c478bd9Sstevel@tonic-gate 			 * If ioctl isn't implemented on this platform, then
501*7c478bd9Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v),
502*7c478bd9Sstevel@tonic-gate 			 * otherwise use the virtual geometry.
503*7c478bd9Sstevel@tonic-gate 			 */
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 			if (errno == ENOTTY) {
506*7c478bd9Sstevel@tonic-gate 				v_flag = 0;
507*7c478bd9Sstevel@tonic-gate 				no_virtgeom_ioctl = 1;
508*7c478bd9Sstevel@tonic-gate 			} else if (errno == EINVAL) {
509*7c478bd9Sstevel@tonic-gate 				/*
510*7c478bd9Sstevel@tonic-gate 				 * This means that the ioctl exists, but
511*7c478bd9Sstevel@tonic-gate 				 * is invalid for this disk, meaning the
512*7c478bd9Sstevel@tonic-gate 				 * disk doesn't have an HBA geometry
513*7c478bd9Sstevel@tonic-gate 				 * (like, say, it's larger than 8GB).
514*7c478bd9Sstevel@tonic-gate 				 */
515*7c478bd9Sstevel@tonic-gate 				v_flag = 0;
516*7c478bd9Sstevel@tonic-gate 				hba_Numcyl = hba_heads = hba_sectors = 0;
517*7c478bd9Sstevel@tonic-gate 			} else {
518*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
519*7c478bd9Sstevel@tonic-gate 				    "%s: Cannot get virtual disk geometry.\n",
520*7c478bd9Sstevel@tonic-gate 				    argv[optind]);
521*7c478bd9Sstevel@tonic-gate 				exit(1);
522*7c478bd9Sstevel@tonic-gate 			}
523*7c478bd9Sstevel@tonic-gate 		} else {
524*7c478bd9Sstevel@tonic-gate 			/* save virtual geometry values obtained by ioctl */
525*7c478bd9Sstevel@tonic-gate 			hba_Numcyl = disk_geom.dkg_ncyl;
526*7c478bd9Sstevel@tonic-gate 			hba_heads = disk_geom.dkg_nhead;
527*7c478bd9Sstevel@tonic-gate 			hba_sectors = disk_geom.dkg_nsect;
528*7c478bd9Sstevel@tonic-gate 		}
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 		errno = 0;
531*7c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
532*7c478bd9Sstevel@tonic-gate 			if (errno == ENOTTY) {
533*7c478bd9Sstevel@tonic-gate 				no_physgeom_ioctl = 1;
534*7c478bd9Sstevel@tonic-gate 			} else {
535*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
536*7c478bd9Sstevel@tonic-gate 				    "%s: Cannot get physical disk geometry.\n",
537*7c478bd9Sstevel@tonic-gate 				    argv[optind]);
538*7c478bd9Sstevel@tonic-gate 				exit(1);
539*7c478bd9Sstevel@tonic-gate 			}
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 		}
542*7c478bd9Sstevel@tonic-gate 		/*
543*7c478bd9Sstevel@tonic-gate 		 * Call DKIOCGGEOM if the ioctls for physical and virtual
544*7c478bd9Sstevel@tonic-gate 		 * geometry fail. Get both from this generic call.
545*7c478bd9Sstevel@tonic-gate 		 */
546*7c478bd9Sstevel@tonic-gate 		if (no_virtgeom_ioctl && no_physgeom_ioctl) {
547*7c478bd9Sstevel@tonic-gate 			errno = 0;
548*7c478bd9Sstevel@tonic-gate 			if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
549*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
550*7c478bd9Sstevel@tonic-gate 				    "%s: Cannot get disk label geometry.\n",
551*7c478bd9Sstevel@tonic-gate 				    argv[optind]);
552*7c478bd9Sstevel@tonic-gate 				exit(1);
553*7c478bd9Sstevel@tonic-gate 			}
554*7c478bd9Sstevel@tonic-gate 		}
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
557*7c478bd9Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
558*7c478bd9Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
559*7c478bd9Sstevel@tonic-gate 		sectsiz = 512;
560*7c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate 		/*
563*7c478bd9Sstevel@tonic-gate 		 * if hba geometry was not set by DKIOC_VIRTGEOM
564*7c478bd9Sstevel@tonic-gate 		 * or we got an invalid hba geometry
565*7c478bd9Sstevel@tonic-gate 		 * then set hba geometry based on max values
566*7c478bd9Sstevel@tonic-gate 		 */
567*7c478bd9Sstevel@tonic-gate 		if (no_virtgeom_ioctl ||
568*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl <= 0 ||
569*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nhead <= 0 ||
570*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nsect <= 0 ||
571*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl > MAX_CYL ||
572*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nhead > MAX_HEAD ||
573*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nsect > MAX_SECT) {
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 			/*
576*7c478bd9Sstevel@tonic-gate 			 * turn off flag to print out virtual geometry (-v)
577*7c478bd9Sstevel@tonic-gate 			 */
578*7c478bd9Sstevel@tonic-gate 			v_flag = 0;
579*7c478bd9Sstevel@tonic-gate 			hba_sectors	= MAX_SECT;
580*7c478bd9Sstevel@tonic-gate 			hba_heads	= MAX_HEAD + 1;
581*7c478bd9Sstevel@tonic-gate 			hba_Numcyl	= (Numcyl * heads * sectors) /
582*7c478bd9Sstevel@tonic-gate 			    (hba_sectors * hba_heads);
583*7c478bd9Sstevel@tonic-gate 		}
584*7c478bd9Sstevel@tonic-gate 
585*7c478bd9Sstevel@tonic-gate 		if (io_debug) {
586*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Physical Geometry:\n");
587*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
588*7c478bd9Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
589*7c478bd9Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
590*7c478bd9Sstevel@tonic-gate 			    Numcyl,
591*7c478bd9Sstevel@tonic-gate 			    heads,
592*7c478bd9Sstevel@tonic-gate 			    sectors,
593*7c478bd9Sstevel@tonic-gate 			    sectsiz,
594*7c478bd9Sstevel@tonic-gate 			    Numcyl*heads*sectors,
595*7c478bd9Sstevel@tonic-gate 			    (Numcyl*heads*sectors*sectsiz)/1048576);
596*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Virtual (HBA) Geometry:\n");
597*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
598*7c478bd9Sstevel@tonic-gate 			    "  cylinders[%d] heads[%d] sectors[%d]\n"
599*7c478bd9Sstevel@tonic-gate 			    "  sector size[%d] blocks[%d] mbytes[%d]\n",
600*7c478bd9Sstevel@tonic-gate 			    hba_Numcyl,
601*7c478bd9Sstevel@tonic-gate 			    hba_heads,
602*7c478bd9Sstevel@tonic-gate 			    hba_sectors,
603*7c478bd9Sstevel@tonic-gate 			    sectsiz,
604*7c478bd9Sstevel@tonic-gate 			    hba_Numcyl*hba_heads*hba_sectors,
605*7c478bd9Sstevel@tonic-gate 			    (hba_Numcyl*hba_heads*hba_sectors*sectsiz)/1048576);
606*7c478bd9Sstevel@tonic-gate 		}
607*7c478bd9Sstevel@tonic-gate 	}
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 	/* If user has requested a geometry report just do it and exit */
610*7c478bd9Sstevel@tonic-gate 	if (io_lgeom) {
611*7c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCGGEOM, &disk_geom)) {
612*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
613*7c478bd9Sstevel@tonic-gate 			    "%s: Cannot get disk label geometry.\n",
614*7c478bd9Sstevel@tonic-gate 			    argv[optind]);
615*7c478bd9Sstevel@tonic-gate 			exit(1);
616*7c478bd9Sstevel@tonic-gate 		}
617*7c478bd9Sstevel@tonic-gate 		Numcyl = disk_geom.dkg_ncyl;
618*7c478bd9Sstevel@tonic-gate 		heads = disk_geom.dkg_nhead;
619*7c478bd9Sstevel@tonic-gate 		sectors = disk_geom.dkg_nsect;
620*7c478bd9Sstevel@tonic-gate 		sectsiz = 512;
621*7c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
622*7c478bd9Sstevel@tonic-gate 		printf("* Label geometry for device %s\n", Dfltdev);
623*7c478bd9Sstevel@tonic-gate 		printf("* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
624*7c478bd9Sstevel@tonic-gate 		    " SECSIZ\n");
625*7c478bd9Sstevel@tonic-gate 		printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
626*7c478bd9Sstevel@tonic-gate 		    Numcyl,
627*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
628*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
629*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
630*7c478bd9Sstevel@tonic-gate 		    heads,
631*7c478bd9Sstevel@tonic-gate 		    sectors,
632*7c478bd9Sstevel@tonic-gate 		    sectsiz);
633*7c478bd9Sstevel@tonic-gate 		exit(0);
634*7c478bd9Sstevel@tonic-gate 	} else if (io_pgeom) {
635*7c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCG_PHYGEOM, &disk_geom)) {
636*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
637*7c478bd9Sstevel@tonic-gate 			    "%s: Cannot get physical disk geometry.\n",
638*7c478bd9Sstevel@tonic-gate 			    argv[optind]);
639*7c478bd9Sstevel@tonic-gate 			exit(1);
640*7c478bd9Sstevel@tonic-gate 		}
641*7c478bd9Sstevel@tonic-gate 		printf("* Physical geometry for device %s\n", Dfltdev);
642*7c478bd9Sstevel@tonic-gate 		printf("* PCYL     NCYL     ACYL     BCYL     NHEAD NSECT"
643*7c478bd9Sstevel@tonic-gate 		    " SECSIZ\n");
644*7c478bd9Sstevel@tonic-gate 		printf("  %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
645*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_pcyl,
646*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_ncyl,
647*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_acyl,
648*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_bcyl,
649*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nhead,
650*7c478bd9Sstevel@tonic-gate 		    disk_geom.dkg_nsect,
651*7c478bd9Sstevel@tonic-gate 		    sectsiz);
652*7c478bd9Sstevel@tonic-gate 		exit(0);
653*7c478bd9Sstevel@tonic-gate 	} else if (io_sgeom) {
654*7c478bd9Sstevel@tonic-gate 		if (read_geom(io_sgeom)) {
655*7c478bd9Sstevel@tonic-gate 			exit(1);
656*7c478bd9Sstevel@tonic-gate 		} else if (!io_image) {
657*7c478bd9Sstevel@tonic-gate 			exit(0);
658*7c478bd9Sstevel@tonic-gate 		}
659*7c478bd9Sstevel@tonic-gate 	}
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	/* Allocate memory to hold three complete sectors */
662*7c478bd9Sstevel@tonic-gate 	Bootsect = (char *)malloc(3 * sectsiz);
663*7c478bd9Sstevel@tonic-gate 	if (Bootsect == NULL) {
664*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
665*7c478bd9Sstevel@tonic-gate 		    "fdisk: Unable to obtain enough buffer memory"
666*7c478bd9Sstevel@tonic-gate 		    " (%d bytes).\n",
667*7c478bd9Sstevel@tonic-gate 		    3*sectsiz);
668*7c478bd9Sstevel@tonic-gate 		exit(1);
669*7c478bd9Sstevel@tonic-gate 	}
670*7c478bd9Sstevel@tonic-gate 
671*7c478bd9Sstevel@tonic-gate 	Nullsect = Bootsect + sectsiz;
672*7c478bd9Sstevel@tonic-gate 	/* Zero out the "NULL" sector */
673*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < sectsiz; i++) {
674*7c478bd9Sstevel@tonic-gate 		Nullsect[i] = 0;
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	/* Find out what the user wants done */
678*7c478bd9Sstevel@tonic-gate 	if (io_rd) {		/* abs disk read */
679*7c478bd9Sstevel@tonic-gate 		abs_read();	/* will not return */
680*7c478bd9Sstevel@tonic-gate 	} else if (io_wrt && !io_readonly) {
681*7c478bd9Sstevel@tonic-gate 		abs_write();	/* will not return */
682*7c478bd9Sstevel@tonic-gate 	} else if (io_patt && !io_readonly) {
683*7c478bd9Sstevel@tonic-gate 		fill_patt();	/* will not return */
684*7c478bd9Sstevel@tonic-gate 	}
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate 
687*7c478bd9Sstevel@tonic-gate 	/* This is the fdisk edit, the real reason for the program.	*/
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate 	sanity_check_provided_device(Dfltdev, Dev);
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	/* Get the new BOOT program in case we write a new fdisk table */
692*7c478bd9Sstevel@tonic-gate 	mboot_read();
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	/* Read from disk master boot */
695*7c478bd9Sstevel@tonic-gate 	dev_mboot_read();
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	/*
698*7c478bd9Sstevel@tonic-gate 	 * Verify and copy the device's fdisk table. This will be used
699*7c478bd9Sstevel@tonic-gate 	 * as the prototype mboot if the device's mboot looks invalid.
700*7c478bd9Sstevel@tonic-gate 	 */
701*7c478bd9Sstevel@tonic-gate 	Bootblk = (struct mboot *)Bootsect;
702*7c478bd9Sstevel@tonic-gate 	copy_Bootblk_to_Table();
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 	/* save away a copy of Table in Old_Table for sensing changes */
705*7c478bd9Sstevel@tonic-gate 	copy_Table_to_Old_Table();
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	/* Load fdisk table from specified file (-F fdisk_file) */
708*7c478bd9Sstevel@tonic-gate 	if (io_ffdisk) {
709*7c478bd9Sstevel@tonic-gate 		/* Load and verify user-specified table parameters */
710*7c478bd9Sstevel@tonic-gate 		load(LOADFILE, io_ffdisk);
711*7c478bd9Sstevel@tonic-gate 	}
712*7c478bd9Sstevel@tonic-gate 
713*7c478bd9Sstevel@tonic-gate 	/* Does user want to delete or add an entry? */
714*7c478bd9Sstevel@tonic-gate 	if (io_Dfdisk) {
715*7c478bd9Sstevel@tonic-gate 		load(LOADDEL, io_Dfdisk);
716*7c478bd9Sstevel@tonic-gate 	}
717*7c478bd9Sstevel@tonic-gate 	if (io_Afdisk) {
718*7c478bd9Sstevel@tonic-gate 		load(LOADADD, io_Afdisk);
719*7c478bd9Sstevel@tonic-gate 	}
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	if (!io_ffdisk && !io_Afdisk && !io_Dfdisk) {
722*7c478bd9Sstevel@tonic-gate 		/* Check if there is no fdisk table */
723*7c478bd9Sstevel@tonic-gate 		if (Table[0].systid == UNUSED || io_wholedisk || io_EFIdisk) {
724*7c478bd9Sstevel@tonic-gate 			if (io_ifdisk && !io_wholedisk && !io_EFIdisk) {
725*7c478bd9Sstevel@tonic-gate 				printf("No fdisk table exists. The default"
726*7c478bd9Sstevel@tonic-gate 				    " partition for the disk is:\n\n");
727*7c478bd9Sstevel@tonic-gate 				printf("  a 100%% \"SOLARIS System\" "
728*7c478bd9Sstevel@tonic-gate 				    "partition\n\n");
729*7c478bd9Sstevel@tonic-gate 				printf("Type \"y\" to accept the default "
730*7c478bd9Sstevel@tonic-gate 				    "partition,  otherwise type \"n\" to "
731*7c478bd9Sstevel@tonic-gate 				    "edit the\n partition table.\n");
732*7c478bd9Sstevel@tonic-gate 			}
733*7c478bd9Sstevel@tonic-gate 
734*7c478bd9Sstevel@tonic-gate 			/* Edit the partition table as directed */
735*7c478bd9Sstevel@tonic-gate 			if (io_wholedisk ||(io_ifdisk && yesno())) {
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 				/* Default scenario */
738*7c478bd9Sstevel@tonic-gate 				nulltbl();
739*7c478bd9Sstevel@tonic-gate 
740*7c478bd9Sstevel@tonic-gate 				/* now set up UNIX System partition */
741*7c478bd9Sstevel@tonic-gate 				Table[0].bootid = ACTIVE;
742*7c478bd9Sstevel@tonic-gate 				Table[0].relsect = lel(heads * sectors);
743*7c478bd9Sstevel@tonic-gate 				Table[0].numsect = lel((long)((Numcyl-1) *
744*7c478bd9Sstevel@tonic-gate 				    heads * sectors));
745*7c478bd9Sstevel@tonic-gate 				Table[0].systid = SUNIXOS2;   /* Solaris */
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 				/* calculate CHS values for table entry 0 */
748*7c478bd9Sstevel@tonic-gate 				Set_Table_CHS_Values(0);
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
751*7c478bd9Sstevel@tonic-gate 			} else if (io_EFIdisk) {
752*7c478bd9Sstevel@tonic-gate 				/* create an EFI partition for the whole disk */
753*7c478bd9Sstevel@tonic-gate 				nulltbl();
754*7c478bd9Sstevel@tonic-gate 				i = insert_tbl(EFI_PMBR, 0, 0, 0, 0, 0, 0, 0, 1,
755*7c478bd9Sstevel@tonic-gate 				    (Numcyl * heads * sectors) - 1);
756*7c478bd9Sstevel@tonic-gate 				if (i != 0) {
757*7c478bd9Sstevel@tonic-gate 					fprintf(stderr, "Error creating EFI "
758*7c478bd9Sstevel@tonic-gate 					    "partition\n");
759*7c478bd9Sstevel@tonic-gate 					exit(1);
760*7c478bd9Sstevel@tonic-gate 				}
761*7c478bd9Sstevel@tonic-gate 				update_disk_and_exit(B_TRUE);
762*7c478bd9Sstevel@tonic-gate 			}
763*7c478bd9Sstevel@tonic-gate 		}
764*7c478bd9Sstevel@tonic-gate 	}
765*7c478bd9Sstevel@tonic-gate 
766*7c478bd9Sstevel@tonic-gate 	/* Display complete fdisk table entries for debugging purposes */
767*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
768*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Partition Table Entry Values:\n");
769*7c478bd9Sstevel@tonic-gate 		print_Table();
770*7c478bd9Sstevel@tonic-gate 		if (io_ifdisk) {
771*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "\n");
772*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Press Enter to continue.\n");
773*7c478bd9Sstevel@tonic-gate 			gets(s);
774*7c478bd9Sstevel@tonic-gate 		}
775*7c478bd9Sstevel@tonic-gate 	}
776*7c478bd9Sstevel@tonic-gate 
777*7c478bd9Sstevel@tonic-gate 	/* Interactive fdisk mode */
778*7c478bd9Sstevel@tonic-gate 	if (io_ifdisk) {
779*7c478bd9Sstevel@tonic-gate 		printf(CLR_SCR);
780*7c478bd9Sstevel@tonic-gate 		disptbl();
781*7c478bd9Sstevel@tonic-gate 		while (1) {
782*7c478bd9Sstevel@tonic-gate 			stage0(argv[1]);
783*7c478bd9Sstevel@tonic-gate 			copy_Bootblk_to_Table();
784*7c478bd9Sstevel@tonic-gate 			disptbl();
785*7c478bd9Sstevel@tonic-gate 		}
786*7c478bd9Sstevel@tonic-gate 	}
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	/* If user wants to write the table to a file, do it */
789*7c478bd9Sstevel@tonic-gate 	if (io_Wfdisk)
790*7c478bd9Sstevel@tonic-gate 		ffile_write(io_Wfdisk);
791*7c478bd9Sstevel@tonic-gate 	else if (stdo_flag)
792*7c478bd9Sstevel@tonic-gate 		ffile_write((char *)stdout);
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 	update_disk_and_exit(TableChanged() == 1);
795*7c478bd9Sstevel@tonic-gate }
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate /*
798*7c478bd9Sstevel@tonic-gate  * read_geom
799*7c478bd9Sstevel@tonic-gate  * Read geometry from specified file (-S).
800*7c478bd9Sstevel@tonic-gate  */
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate read_geom(sgeom)
803*7c478bd9Sstevel@tonic-gate char	*sgeom;
804*7c478bd9Sstevel@tonic-gate {
805*7c478bd9Sstevel@tonic-gate 	char	line[256];
806*7c478bd9Sstevel@tonic-gate 	FILE *fp;
807*7c478bd9Sstevel@tonic-gate 
808*7c478bd9Sstevel@tonic-gate 	/* open the prototype file */
809*7c478bd9Sstevel@tonic-gate 	if ((fp = fopen(sgeom, "r")) == NULL) {
810*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "fdisk: Cannot open file %s.\n",
811*7c478bd9Sstevel@tonic-gate 		    io_sgeom);
812*7c478bd9Sstevel@tonic-gate 		return (1);
813*7c478bd9Sstevel@tonic-gate 	}
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 	/* Read a line from the file */
816*7c478bd9Sstevel@tonic-gate 	while (fgets(line, sizeof (line) - 1, fp)) {
817*7c478bd9Sstevel@tonic-gate 		if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
818*7c478bd9Sstevel@tonic-gate 			continue;
819*7c478bd9Sstevel@tonic-gate 		else {
820*7c478bd9Sstevel@tonic-gate 			line[strlen(line)] = '\0';
821*7c478bd9Sstevel@tonic-gate 			if (sscanf(line, "%d %d %d %d %d %d %d",
822*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_pcyl,
823*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_ncyl,
824*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_acyl,
825*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_bcyl,
826*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_nhead,
827*7c478bd9Sstevel@tonic-gate 			    &disk_geom.dkg_nsect,
828*7c478bd9Sstevel@tonic-gate 			    &sectsiz) != 7) {
829*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
830*7c478bd9Sstevel@tonic-gate 				    "Syntax error:\n	\"%s\".\n",
831*7c478bd9Sstevel@tonic-gate 				    line);
832*7c478bd9Sstevel@tonic-gate 				return (1);
833*7c478bd9Sstevel@tonic-gate 			}
834*7c478bd9Sstevel@tonic-gate 			break;
835*7c478bd9Sstevel@tonic-gate 		} /* else */
836*7c478bd9Sstevel@tonic-gate 	} /* while (fgets(line, sizeof (line) - 1, fp)) */
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	if (!io_image) {
839*7c478bd9Sstevel@tonic-gate 		if (ioctl(Dev, DKIOCSGEOM, &disk_geom)) {
840*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
841*7c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot set label geometry.\n");
842*7c478bd9Sstevel@tonic-gate 			return (1);
843*7c478bd9Sstevel@tonic-gate 		}
844*7c478bd9Sstevel@tonic-gate 	} else {
845*7c478bd9Sstevel@tonic-gate 		Numcyl = hba_Numcyl = disk_geom.dkg_ncyl;
846*7c478bd9Sstevel@tonic-gate 		heads = hba_heads = disk_geom.dkg_nhead;
847*7c478bd9Sstevel@tonic-gate 		sectors = hba_sectors = disk_geom.dkg_nsect;
848*7c478bd9Sstevel@tonic-gate 		acyl = disk_geom.dkg_acyl;
849*7c478bd9Sstevel@tonic-gate 	}
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate 	fclose(fp);
852*7c478bd9Sstevel@tonic-gate 	return (0);
853*7c478bd9Sstevel@tonic-gate }
854*7c478bd9Sstevel@tonic-gate 
855*7c478bd9Sstevel@tonic-gate /*
856*7c478bd9Sstevel@tonic-gate  * dev_mboot_read
857*7c478bd9Sstevel@tonic-gate  * Read the master boot sector from the device.
858*7c478bd9Sstevel@tonic-gate  */
859*7c478bd9Sstevel@tonic-gate dev_mboot_read()
860*7c478bd9Sstevel@tonic-gate {
861*7c478bd9Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCGMBOOT, Bootsect) < 0) && (errno != ENOTTY)) {
862*7c478bd9Sstevel@tonic-gate 		perror("Error in ioctl DKIOCGMBOOT");
863*7c478bd9Sstevel@tonic-gate 	}
864*7c478bd9Sstevel@tonic-gate 	if (errno == 0)
865*7c478bd9Sstevel@tonic-gate 		return;
866*7c478bd9Sstevel@tonic-gate 	if (lseek(Dev, 0, SEEK_SET) == -1) {
867*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
868*7c478bd9Sstevel@tonic-gate 		    "fdisk: Error seeking to partition table on %s.\n",
869*7c478bd9Sstevel@tonic-gate 		    Dfltdev);
870*7c478bd9Sstevel@tonic-gate 		if (!io_image)
871*7c478bd9Sstevel@tonic-gate 			exit(1);
872*7c478bd9Sstevel@tonic-gate 	}
873*7c478bd9Sstevel@tonic-gate 	if (read(Dev, Bootsect, sectsiz) != sectsiz) {
874*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
875*7c478bd9Sstevel@tonic-gate 		    "fdisk: Error reading partition table from %s.\n",
876*7c478bd9Sstevel@tonic-gate 		    Dfltdev);
877*7c478bd9Sstevel@tonic-gate 		if (!io_image)
878*7c478bd9Sstevel@tonic-gate 			exit(1);
879*7c478bd9Sstevel@tonic-gate 	}
880*7c478bd9Sstevel@tonic-gate }
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate /*
883*7c478bd9Sstevel@tonic-gate  * dev_mboot_write
884*7c478bd9Sstevel@tonic-gate  * Write the master boot sector to the device.
885*7c478bd9Sstevel@tonic-gate  */
886*7c478bd9Sstevel@tonic-gate dev_mboot_write(int sect, char *buff, int bootsiz)
887*7c478bd9Sstevel@tonic-gate {
888*7c478bd9Sstevel@tonic-gate 	int 	new_pt, old_pt, error;
889*7c478bd9Sstevel@tonic-gate 	int	clr_efi = -1, old_solaris = -1, new_solaris = -1;
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 	if (io_readonly)
892*7c478bd9Sstevel@tonic-gate 		return (0);
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
895*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "About to write fdisk table:\n");
896*7c478bd9Sstevel@tonic-gate 		print_Table();
897*7c478bd9Sstevel@tonic-gate 		if (io_ifdisk) {
898*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Press Enter to continue.\n");
899*7c478bd9Sstevel@tonic-gate 			gets(s);
900*7c478bd9Sstevel@tonic-gate 		}
901*7c478bd9Sstevel@tonic-gate 	}
902*7c478bd9Sstevel@tonic-gate 
903*7c478bd9Sstevel@tonic-gate 	/* see if the old table had EFI or Solaris partitions */
904*7c478bd9Sstevel@tonic-gate 	for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
905*7c478bd9Sstevel@tonic-gate 		if (Old_Table[old_pt].systid == SUNIXOS ||
906*7c478bd9Sstevel@tonic-gate 		    Old_Table[old_pt].systid == SUNIXOS2) {
907*7c478bd9Sstevel@tonic-gate 			old_solaris = old_pt;
908*7c478bd9Sstevel@tonic-gate 		} else if (Old_Table[old_pt].systid == EFI_PMBR) {
909*7c478bd9Sstevel@tonic-gate 			clr_efi = old_pt;
910*7c478bd9Sstevel@tonic-gate 		}
911*7c478bd9Sstevel@tonic-gate 	}
912*7c478bd9Sstevel@tonic-gate 
913*7c478bd9Sstevel@tonic-gate 	/* look to see if Solaris partition changed in relsect/numsect */
914*7c478bd9Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 		/*
917*7c478bd9Sstevel@tonic-gate 		 * if this is not a Solaris partition, ignore it
918*7c478bd9Sstevel@tonic-gate 		 */
919*7c478bd9Sstevel@tonic-gate 		if (Table[new_pt].systid != SUNIXOS &&
920*7c478bd9Sstevel@tonic-gate 		    Table[new_pt].systid != SUNIXOS2)
921*7c478bd9Sstevel@tonic-gate 			continue;
922*7c478bd9Sstevel@tonic-gate 
923*7c478bd9Sstevel@tonic-gate 		/*
924*7c478bd9Sstevel@tonic-gate 		 * if there was no previous Solaris partition
925*7c478bd9Sstevel@tonic-gate 		 * or if the old partition was in a different place
926*7c478bd9Sstevel@tonic-gate 		 * or if the old partition was a different size
927*7c478bd9Sstevel@tonic-gate 		 * then this must be a new Solaris partition
928*7c478bd9Sstevel@tonic-gate 		 */
929*7c478bd9Sstevel@tonic-gate 		if (old_solaris == -1 ||
930*7c478bd9Sstevel@tonic-gate 		    Old_Table[old_solaris].relsect != Table[new_pt].relsect ||
931*7c478bd9Sstevel@tonic-gate 		    Old_Table[old_solaris].numsect != Table[new_pt].numsect) {
932*7c478bd9Sstevel@tonic-gate 			new_solaris = new_pt;
933*7c478bd9Sstevel@tonic-gate 			break;
934*7c478bd9Sstevel@tonic-gate 		}
935*7c478bd9Sstevel@tonic-gate 	}
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 	/* look to see if a EFI partition changed in relsect/numsect */
938*7c478bd9Sstevel@tonic-gate 	for (new_pt = 0; new_pt < FD_NUMPART; new_pt++) {
939*7c478bd9Sstevel@tonic-gate 		if (Table[new_pt].systid != EFI_PMBR)
940*7c478bd9Sstevel@tonic-gate 			continue;
941*7c478bd9Sstevel@tonic-gate 		for (old_pt = 0; old_pt < FD_NUMPART; old_pt++) {
942*7c478bd9Sstevel@tonic-gate 		    if ((Old_Table[old_pt].systid == Table[new_pt].systid) &&
943*7c478bd9Sstevel@tonic-gate 			(Old_Table[old_pt].relsect == Table[new_pt].relsect) &&
944*7c478bd9Sstevel@tonic-gate 			(Old_Table[old_pt].numsect == Table[new_pt].numsect))
945*7c478bd9Sstevel@tonic-gate 			    break;
946*7c478bd9Sstevel@tonic-gate 		}
947*7c478bd9Sstevel@tonic-gate 
948*7c478bd9Sstevel@tonic-gate 		/*
949*7c478bd9Sstevel@tonic-gate 		 * if EFI partition changed, set the flag to clear
950*7c478bd9Sstevel@tonic-gate 		 * the EFI GPT
951*7c478bd9Sstevel@tonic-gate 		 */
952*7c478bd9Sstevel@tonic-gate 		if (old_pt == FD_NUMPART && Table[new_pt].begcyl != 0) {
953*7c478bd9Sstevel@tonic-gate 			clr_efi = 0;
954*7c478bd9Sstevel@tonic-gate 		}
955*7c478bd9Sstevel@tonic-gate 		break;
956*7c478bd9Sstevel@tonic-gate 	}
957*7c478bd9Sstevel@tonic-gate 
958*7c478bd9Sstevel@tonic-gate 	/* clear labels if necessary */
959*7c478bd9Sstevel@tonic-gate 	if (clr_efi >= 0) {
960*7c478bd9Sstevel@tonic-gate 		if (io_debug) {
961*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Clearing EFI labels\n");
962*7c478bd9Sstevel@tonic-gate 		}
963*7c478bd9Sstevel@tonic-gate 		if ((error = clear_efi()) != 0) {
964*7c478bd9Sstevel@tonic-gate 			if (io_debug) {
965*7c478bd9Sstevel@tonic-gate 				fprintf(stderr, "\tError %d clearing EFI labels"
966*7c478bd9Sstevel@tonic-gate 				    " (probably no EFI labels exist)\n",
967*7c478bd9Sstevel@tonic-gate 				    error);
968*7c478bd9Sstevel@tonic-gate 			}
969*7c478bd9Sstevel@tonic-gate 		}
970*7c478bd9Sstevel@tonic-gate 	}
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 	if (new_solaris >= 0) {
973*7c478bd9Sstevel@tonic-gate 		if (io_debug) {
974*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "Clearing VTOC labels from NEW"
975*7c478bd9Sstevel@tonic-gate 			    " table\n");
976*7c478bd9Sstevel@tonic-gate 		}
977*7c478bd9Sstevel@tonic-gate 		clear_vtoc(NEW, new_solaris);
978*7c478bd9Sstevel@tonic-gate 	}
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	if ((ioctl(Dev, DKIOCSMBOOT, buff) == -1) && (errno != ENOTTY)) {
981*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
982*7c478bd9Sstevel@tonic-gate 		    "fdisk: Error in ioctl DKIOCSMBOOT on %s.\n",
983*7c478bd9Sstevel@tonic-gate 		    Dfltdev);
984*7c478bd9Sstevel@tonic-gate 	}
985*7c478bd9Sstevel@tonic-gate 	if (errno == 0)
986*7c478bd9Sstevel@tonic-gate 		return;
987*7c478bd9Sstevel@tonic-gate 
988*7c478bd9Sstevel@tonic-gate 	/* write to disk drive */
989*7c478bd9Sstevel@tonic-gate 	if (lseek(Dev, sect, SEEK_SET) == -1) {
990*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
991*7c478bd9Sstevel@tonic-gate 		    "fdisk: Error seeking to master boot record on %s.\n",
992*7c478bd9Sstevel@tonic-gate 		    Dfltdev);
993*7c478bd9Sstevel@tonic-gate 		exit(1);
994*7c478bd9Sstevel@tonic-gate 	}
995*7c478bd9Sstevel@tonic-gate 	if (write(Dev, buff, bootsiz) != bootsiz) {
996*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
997*7c478bd9Sstevel@tonic-gate 		    "fdisk: Error writing master boot record to %s.\n",
998*7c478bd9Sstevel@tonic-gate 		    Dfltdev);
999*7c478bd9Sstevel@tonic-gate 		exit(1);
1000*7c478bd9Sstevel@tonic-gate 	}
1001*7c478bd9Sstevel@tonic-gate }
1002*7c478bd9Sstevel@tonic-gate 
1003*7c478bd9Sstevel@tonic-gate /*
1004*7c478bd9Sstevel@tonic-gate  * mboot_read
1005*7c478bd9Sstevel@tonic-gate  * Read the prototype boot records from the files.
1006*7c478bd9Sstevel@tonic-gate  */
1007*7c478bd9Sstevel@tonic-gate mboot_read()
1008*7c478bd9Sstevel@tonic-gate {
1009*7c478bd9Sstevel@tonic-gate 	int mDev, i;
1010*7c478bd9Sstevel@tonic-gate 	struct	stat	statbuf;
1011*7c478bd9Sstevel@tonic-gate 	struct ipart *part;
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate #if defined(i386) || defined(sparc)
1014*7c478bd9Sstevel@tonic-gate 	/*
1015*7c478bd9Sstevel@tonic-gate 	 * If the master boot file hasn't been specified, use the
1016*7c478bd9Sstevel@tonic-gate 	 * implementation architecture name to generate the default one.
1017*7c478bd9Sstevel@tonic-gate 	 */
1018*7c478bd9Sstevel@tonic-gate 	if (io_mboot == (char *)0) {
1019*7c478bd9Sstevel@tonic-gate 		/*
1020*7c478bd9Sstevel@tonic-gate 		 * Bug ID 1249035:
1021*7c478bd9Sstevel@tonic-gate 		 *	The mboot file must be delivered on all platforms
1022*7c478bd9Sstevel@tonic-gate 		 *	and installed in a non-platform-dependent
1023*7c478bd9Sstevel@tonic-gate 		 *	directory; i.e., /usr/lib/fs/ufs.
1024*7c478bd9Sstevel@tonic-gate 		 */
1025*7c478bd9Sstevel@tonic-gate 		io_mboot = "/usr/lib/fs/ufs/mboot";
1026*7c478bd9Sstevel@tonic-gate 	}
1027*7c478bd9Sstevel@tonic-gate 
1028*7c478bd9Sstevel@tonic-gate 	/* First read in the master boot record */
1029*7c478bd9Sstevel@tonic-gate 
1030*7c478bd9Sstevel@tonic-gate 	/* Open the master boot proto file */
1031*7c478bd9Sstevel@tonic-gate 	if ((mDev = open(io_mboot, O_RDONLY, 0666)) == -1) {
1032*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1033*7c478bd9Sstevel@tonic-gate 		    "fdisk: Cannot open master boot file %s.\n",
1034*7c478bd9Sstevel@tonic-gate 		    io_mboot);
1035*7c478bd9Sstevel@tonic-gate 		exit(1);
1036*7c478bd9Sstevel@tonic-gate 	}
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 	/* Read the master boot program */
1039*7c478bd9Sstevel@tonic-gate 	if (read(mDev, &BootCod, sizeof (struct mboot)) != sizeof
1040*7c478bd9Sstevel@tonic-gate 	    (struct mboot)) {
1041*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1042*7c478bd9Sstevel@tonic-gate 		    "fdisk: Cannot read master boot file %s.\n",
1043*7c478bd9Sstevel@tonic-gate 		    io_mboot);
1044*7c478bd9Sstevel@tonic-gate 		exit(1);
1045*7c478bd9Sstevel@tonic-gate 	}
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate 	/* Is this really a master boot record? */
1048*7c478bd9Sstevel@tonic-gate 	if (les(BootCod.signature) != MBB_MAGIC) {
1049*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1050*7c478bd9Sstevel@tonic-gate 		    "fdisk: Invalid master boot file %s.\n", io_mboot);
1051*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Bad magic number: is %x, but should be %x.\n",
1052*7c478bd9Sstevel@tonic-gate 		    les(BootCod.signature), MBB_MAGIC);
1053*7c478bd9Sstevel@tonic-gate 		exit(1);
1054*7c478bd9Sstevel@tonic-gate 	}
1055*7c478bd9Sstevel@tonic-gate 
1056*7c478bd9Sstevel@tonic-gate 	close(mDev);
1057*7c478bd9Sstevel@tonic-gate #else
1058*7c478bd9Sstevel@tonic-gate #error	fdisk needs to be ported to new architecture
1059*7c478bd9Sstevel@tonic-gate #endif
1060*7c478bd9Sstevel@tonic-gate 
1061*7c478bd9Sstevel@tonic-gate 	/* Zero out the partitions part of this record */
1062*7c478bd9Sstevel@tonic-gate 	part = (struct ipart *)BootCod.parts;
1063*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++, part++) {
1064*7c478bd9Sstevel@tonic-gate 		memset(part, 0, sizeof (struct ipart));
1065*7c478bd9Sstevel@tonic-gate 	}
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate }
1068*7c478bd9Sstevel@tonic-gate 
1069*7c478bd9Sstevel@tonic-gate /*
1070*7c478bd9Sstevel@tonic-gate  * fill_patt
1071*7c478bd9Sstevel@tonic-gate  * Fill the disk with user/sector number pattern.
1072*7c478bd9Sstevel@tonic-gate  */
1073*7c478bd9Sstevel@tonic-gate fill_patt()
1074*7c478bd9Sstevel@tonic-gate {
1075*7c478bd9Sstevel@tonic-gate 	int	*buff_ptr, i, c;
1076*7c478bd9Sstevel@tonic-gate 	int	io_fpatt = 0;
1077*7c478bd9Sstevel@tonic-gate 	int	io_ipatt = 0;
1078*7c478bd9Sstevel@tonic-gate 
1079*7c478bd9Sstevel@tonic-gate 	if (strncmp(io_fatt, "#", 1) != 0) {
1080*7c478bd9Sstevel@tonic-gate 		io_fpatt++;
1081*7c478bd9Sstevel@tonic-gate 		io_ipatt = strtoul(io_fatt, 0, 0);
1082*7c478bd9Sstevel@tonic-gate 		buff_ptr = (int *)Bootsect;
1083*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < sectsiz; i += 4, buff_ptr++)
1084*7c478bd9Sstevel@tonic-gate 		    *buff_ptr = io_ipatt;
1085*7c478bd9Sstevel@tonic-gate 	}
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 	/*
1088*7c478bd9Sstevel@tonic-gate 	 * Fill disk with pattern based on block number.
1089*7c478bd9Sstevel@tonic-gate 	 * Write to the disk at absolute relative block io_offset
1090*7c478bd9Sstevel@tonic-gate 	 * for io_size blocks.
1091*7c478bd9Sstevel@tonic-gate 	 */
1092*7c478bd9Sstevel@tonic-gate 	while (io_size--) {
1093*7c478bd9Sstevel@tonic-gate 		buff_ptr = (int *)Bootsect;
1094*7c478bd9Sstevel@tonic-gate 		if (!io_fpatt) {
1095*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < sectsiz; i += 4, buff_ptr++)
1096*7c478bd9Sstevel@tonic-gate 				*buff_ptr = io_offset;
1097*7c478bd9Sstevel@tonic-gate 		}
1098*7c478bd9Sstevel@tonic-gate 		/* Write the data to disk */
1099*7c478bd9Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1100*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error seeking on %s.\n",
1101*7c478bd9Sstevel@tonic-gate 				Dfltdev);
1102*7c478bd9Sstevel@tonic-gate 			exit(1);
1103*7c478bd9Sstevel@tonic-gate 		}
1104*7c478bd9Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1105*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error writing %s.\n",
1106*7c478bd9Sstevel@tonic-gate 				Dfltdev);
1107*7c478bd9Sstevel@tonic-gate 			exit(1);
1108*7c478bd9Sstevel@tonic-gate 		}
1109*7c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
1110*7c478bd9Sstevel@tonic-gate }
1111*7c478bd9Sstevel@tonic-gate 
1112*7c478bd9Sstevel@tonic-gate /*
1113*7c478bd9Sstevel@tonic-gate  * abs_read
1114*7c478bd9Sstevel@tonic-gate  * Read from the disk at absolute relative block io_offset for
1115*7c478bd9Sstevel@tonic-gate  * io_size blocks. Write the data to standard ouput (-r).
1116*7c478bd9Sstevel@tonic-gate  */
1117*7c478bd9Sstevel@tonic-gate abs_read() {
1118*7c478bd9Sstevel@tonic-gate 	int c;
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate 	while (io_size--) {
1121*7c478bd9Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1122*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error seeking on %s.\n",
1123*7c478bd9Sstevel@tonic-gate 			    Dfltdev);
1124*7c478bd9Sstevel@tonic-gate 			exit(1);
1125*7c478bd9Sstevel@tonic-gate 		}
1126*7c478bd9Sstevel@tonic-gate 		if (read(Dev, Bootsect, sectsiz) != sectsiz) {
1127*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error reading %s.\n",
1128*7c478bd9Sstevel@tonic-gate 			    Dfltdev);
1129*7c478bd9Sstevel@tonic-gate 			exit(1);
1130*7c478bd9Sstevel@tonic-gate 		}
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 		/* Write to standard ouptut */
1133*7c478bd9Sstevel@tonic-gate 		if ((c = write(1, Bootsect, (unsigned)sectsiz)) != sectsiz)
1134*7c478bd9Sstevel@tonic-gate 		{
1135*7c478bd9Sstevel@tonic-gate 			if (c >= 0) {
1136*7c478bd9Sstevel@tonic-gate 				if (io_debug)
1137*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1138*7c478bd9Sstevel@tonic-gate 				    "fdisk: Output warning: %d of %d"
1139*7c478bd9Sstevel@tonic-gate 				    " characters written.\n",
1140*7c478bd9Sstevel@tonic-gate 				    c, sectsiz);
1141*7c478bd9Sstevel@tonic-gate 				exit(2);
1142*7c478bd9Sstevel@tonic-gate 			} else {
1143*7c478bd9Sstevel@tonic-gate 				perror("write error on output file.");
1144*7c478bd9Sstevel@tonic-gate 				exit(2);
1145*7c478bd9Sstevel@tonic-gate 			}
1146*7c478bd9Sstevel@tonic-gate 		} /* if ((c = write(1, Bootsect, (unsigned)sectsiz)) */
1147*7c478bd9Sstevel@tonic-gate 			/* != sectsiz) */
1148*7c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
1149*7c478bd9Sstevel@tonic-gate 	exit(0);
1150*7c478bd9Sstevel@tonic-gate }
1151*7c478bd9Sstevel@tonic-gate 
1152*7c478bd9Sstevel@tonic-gate /*
1153*7c478bd9Sstevel@tonic-gate  * abs_write
1154*7c478bd9Sstevel@tonic-gate  * Read the data from standard input. Write to the disk at
1155*7c478bd9Sstevel@tonic-gate  * absolute relative block io_offset for io_size blocks (-w).
1156*7c478bd9Sstevel@tonic-gate  */
1157*7c478bd9Sstevel@tonic-gate abs_write()
1158*7c478bd9Sstevel@tonic-gate {
1159*7c478bd9Sstevel@tonic-gate 	int c, i;
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 	while (io_size--) {
1162*7c478bd9Sstevel@tonic-gate 		int part_exit = 0;
1163*7c478bd9Sstevel@tonic-gate 		/* Read from standard input */
1164*7c478bd9Sstevel@tonic-gate 		if ((c = read(0, Bootsect, (unsigned)sectsiz)) != sectsiz) {
1165*7c478bd9Sstevel@tonic-gate 			if (c >= 0) {
1166*7c478bd9Sstevel@tonic-gate 				if (io_debug)
1167*7c478bd9Sstevel@tonic-gate 				fprintf(stderr,
1168*7c478bd9Sstevel@tonic-gate 				    "fdisk: WARNING: Incomplete read (%d of"
1169*7c478bd9Sstevel@tonic-gate 				    " %d characters read) on input file.\n",
1170*7c478bd9Sstevel@tonic-gate 					c, sectsiz);
1171*7c478bd9Sstevel@tonic-gate 				/* Fill pattern to mark partial sector in buf */
1172*7c478bd9Sstevel@tonic-gate 				for (i = c; i < sectsiz; ) {
1173*7c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x41;
1174*7c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x62;
1175*7c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0x65;
1176*7c478bd9Sstevel@tonic-gate 					Bootsect[i++] = 0;
1177*7c478bd9Sstevel@tonic-gate 				}
1178*7c478bd9Sstevel@tonic-gate 				part_exit++;
1179*7c478bd9Sstevel@tonic-gate 			} else {
1180*7c478bd9Sstevel@tonic-gate 				perror("read error on input file.");
1181*7c478bd9Sstevel@tonic-gate 				exit(2);
1182*7c478bd9Sstevel@tonic-gate 			}
1183*7c478bd9Sstevel@tonic-gate 
1184*7c478bd9Sstevel@tonic-gate 		}
1185*7c478bd9Sstevel@tonic-gate 		/* Write to disk drive */
1186*7c478bd9Sstevel@tonic-gate 		if (lseek(Dev, sectsiz * io_offset++, SEEK_SET) == -1) {
1187*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error seeking on %s.\n",
1188*7c478bd9Sstevel@tonic-gate 			    Dfltdev);
1189*7c478bd9Sstevel@tonic-gate 			exit(1);
1190*7c478bd9Sstevel@tonic-gate 		}
1191*7c478bd9Sstevel@tonic-gate 		if (write(Dev, Bootsect, sectsiz) != sectsiz) {
1192*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Error writing %s.\n",
1193*7c478bd9Sstevel@tonic-gate 			    Dfltdev);
1194*7c478bd9Sstevel@tonic-gate 			exit(1);
1195*7c478bd9Sstevel@tonic-gate 		}
1196*7c478bd9Sstevel@tonic-gate 		if (part_exit)
1197*7c478bd9Sstevel@tonic-gate 		exit(0);
1198*7c478bd9Sstevel@tonic-gate 	} /* while (--io_size); */
1199*7c478bd9Sstevel@tonic-gate 	exit(1);
1200*7c478bd9Sstevel@tonic-gate }
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate /*
1203*7c478bd9Sstevel@tonic-gate  * load
1204*7c478bd9Sstevel@tonic-gate  * Load will either read the fdisk table from a file or add or
1205*7c478bd9Sstevel@tonic-gate  * delete an entry (-A, -D, -F).
1206*7c478bd9Sstevel@tonic-gate  */
1207*7c478bd9Sstevel@tonic-gate 
1208*7c478bd9Sstevel@tonic-gate load(funct, file)
1209*7c478bd9Sstevel@tonic-gate int	funct;
1210*7c478bd9Sstevel@tonic-gate char	*file;			/* Either file name or delete/add line */
1211*7c478bd9Sstevel@tonic-gate {
1212*7c478bd9Sstevel@tonic-gate 	int	id;
1213*7c478bd9Sstevel@tonic-gate 	int	act;
1214*7c478bd9Sstevel@tonic-gate 	int	bhead;
1215*7c478bd9Sstevel@tonic-gate 	int	bsect;
1216*7c478bd9Sstevel@tonic-gate 	int	bcyl;
1217*7c478bd9Sstevel@tonic-gate 	int	ehead;
1218*7c478bd9Sstevel@tonic-gate 	int	esect;
1219*7c478bd9Sstevel@tonic-gate 	int	ecyl;
1220*7c478bd9Sstevel@tonic-gate 	int	rsect;
1221*7c478bd9Sstevel@tonic-gate 	int	numsect;
1222*7c478bd9Sstevel@tonic-gate 	char	line[256];
1223*7c478bd9Sstevel@tonic-gate 	int	i = 0;
1224*7c478bd9Sstevel@tonic-gate 	int	j;
1225*7c478bd9Sstevel@tonic-gate 	FILE *fp;
1226*7c478bd9Sstevel@tonic-gate 
1227*7c478bd9Sstevel@tonic-gate 	switch (funct) {
1228*7c478bd9Sstevel@tonic-gate 
1229*7c478bd9Sstevel@tonic-gate 	    case LOADFILE:
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate 		/*
1232*7c478bd9Sstevel@tonic-gate 		 * Zero out the table before loading it, which will
1233*7c478bd9Sstevel@tonic-gate 		 * force it to be updated on disk later (-F
1234*7c478bd9Sstevel@tonic-gate 		 * fdisk_file).
1235*7c478bd9Sstevel@tonic-gate 		 */
1236*7c478bd9Sstevel@tonic-gate 		nulltbl();
1237*7c478bd9Sstevel@tonic-gate 
1238*7c478bd9Sstevel@tonic-gate 		/* Open the prototype file */
1239*7c478bd9Sstevel@tonic-gate 		if ((fp = fopen(file, "r")) == NULL) {
1240*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1241*7c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot open prototype partition file %s.\n",
1242*7c478bd9Sstevel@tonic-gate 			    file);
1243*7c478bd9Sstevel@tonic-gate 			exit(1);
1244*7c478bd9Sstevel@tonic-gate 		}
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate 		/* Read a line from the file */
1247*7c478bd9Sstevel@tonic-gate 		while (fgets(line, sizeof (line) - 1, fp)) {
1248*7c478bd9Sstevel@tonic-gate 			if (pars_fdisk(line, &id, &act, &bhead, &bsect,
1249*7c478bd9Sstevel@tonic-gate 			    &bcyl, &ehead, &esect, &ecyl, &rsect, &numsect)) {
1250*7c478bd9Sstevel@tonic-gate 				continue;
1251*7c478bd9Sstevel@tonic-gate 			}
1252*7c478bd9Sstevel@tonic-gate 
1253*7c478bd9Sstevel@tonic-gate 			/*
1254*7c478bd9Sstevel@tonic-gate 			 * Validate the partition. It cannot start at sector
1255*7c478bd9Sstevel@tonic-gate 			 * 0 unless it is UNUSED or already exists
1256*7c478bd9Sstevel@tonic-gate 			 */
1257*7c478bd9Sstevel@tonic-gate 			if (validate_part(id, rsect, numsect) < 0) {
1258*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1259*7c478bd9Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
1260*7c478bd9Sstevel@tonic-gate 				    line);
1261*7c478bd9Sstevel@tonic-gate 				exit(1);
1262*7c478bd9Sstevel@tonic-gate 			}
1263*7c478bd9Sstevel@tonic-gate 			/*
1264*7c478bd9Sstevel@tonic-gate 			 * Find an unused entry to use and put the entry
1265*7c478bd9Sstevel@tonic-gate 			 * in table
1266*7c478bd9Sstevel@tonic-gate 			 */
1267*7c478bd9Sstevel@tonic-gate 			if (insert_tbl(id, act, bhead, bsect, bcyl, ehead,
1268*7c478bd9Sstevel@tonic-gate 			    esect, ecyl, rsect, numsect) < 0) {
1269*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1270*7c478bd9Sstevel@tonic-gate 				    "fdisk: Error on entry \"%s\".\n",
1271*7c478bd9Sstevel@tonic-gate 				    line);
1272*7c478bd9Sstevel@tonic-gate 				exit(1);
1273*7c478bd9Sstevel@tonic-gate 			}
1274*7c478bd9Sstevel@tonic-gate 		} /* while (fgets(line, sizeof (line) - 1, fp)) */
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 		if (verify_tbl() < 0) {
1277*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1278*7c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot create partition table\n");
1279*7c478bd9Sstevel@tonic-gate 			exit(1);
1280*7c478bd9Sstevel@tonic-gate 		}
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 		fclose(fp);
1283*7c478bd9Sstevel@tonic-gate 		return;
1284*7c478bd9Sstevel@tonic-gate 
1285*7c478bd9Sstevel@tonic-gate 	    case LOADDEL:
1286*7c478bd9Sstevel@tonic-gate 
1287*7c478bd9Sstevel@tonic-gate 		/* Parse the user-supplied deletion line (-D) */
1288*7c478bd9Sstevel@tonic-gate 		pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl, &ehead,
1289*7c478bd9Sstevel@tonic-gate 		    &esect, &ecyl, &rsect, &numsect);
1290*7c478bd9Sstevel@tonic-gate 
1291*7c478bd9Sstevel@tonic-gate 		/* Find the exact entry in the table */
1292*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
1293*7c478bd9Sstevel@tonic-gate 			if (Table[i].systid == id &&
1294*7c478bd9Sstevel@tonic-gate 			    Table[i].bootid == act &&
1295*7c478bd9Sstevel@tonic-gate 			    Table[i].beghead == bhead &&
1296*7c478bd9Sstevel@tonic-gate 			    Table[i].begsect == ((bsect & 0x3f) |
1297*7c478bd9Sstevel@tonic-gate 				(unsigned char)((bcyl>>2) & 0xc0)) &&
1298*7c478bd9Sstevel@tonic-gate 			    Table[i].begcyl == (unsigned char)(bcyl & 0xff) &&
1299*7c478bd9Sstevel@tonic-gate 			    Table[i].endhead == ehead &&
1300*7c478bd9Sstevel@tonic-gate 			    Table[i].endsect == ((esect & 0x3f) |
1301*7c478bd9Sstevel@tonic-gate 				(unsigned char)((ecyl>>2) & 0xc0)) &&
1302*7c478bd9Sstevel@tonic-gate 			    Table[i].endcyl == (unsigned char)(ecyl & 0xff) &&
1303*7c478bd9Sstevel@tonic-gate 			    Table[i].relsect == lel(rsect) &&
1304*7c478bd9Sstevel@tonic-gate 			    Table[i].numsect == lel(numsect)) {
1305*7c478bd9Sstevel@tonic-gate 
1306*7c478bd9Sstevel@tonic-gate 				/*
1307*7c478bd9Sstevel@tonic-gate 				 * Found the entry. Now move rest of
1308*7c478bd9Sstevel@tonic-gate 				 * entries up toward the top of the
1309*7c478bd9Sstevel@tonic-gate 				 * table, leaving available entries at
1310*7c478bd9Sstevel@tonic-gate 				 * the end of the fdisk table.
1311*7c478bd9Sstevel@tonic-gate 				 */
1312*7c478bd9Sstevel@tonic-gate 				for (j = i; j < FD_NUMPART-1; j++) {
1313*7c478bd9Sstevel@tonic-gate 					Table[j].systid = Table[j+1].systid;
1314*7c478bd9Sstevel@tonic-gate 					Table[j].bootid = Table[j+1].bootid;
1315*7c478bd9Sstevel@tonic-gate 					Table[j].beghead = Table[j+1].beghead;
1316*7c478bd9Sstevel@tonic-gate 					Table[j].begsect = Table[j+1].begsect;
1317*7c478bd9Sstevel@tonic-gate 					Table[j].begcyl = Table[j+1].begcyl;
1318*7c478bd9Sstevel@tonic-gate 					Table[j].endhead = Table[j+1].endhead;
1319*7c478bd9Sstevel@tonic-gate 					Table[j].endsect = Table[j+1].endsect;
1320*7c478bd9Sstevel@tonic-gate 					Table[j].endcyl = Table[j+1].endcyl;
1321*7c478bd9Sstevel@tonic-gate 					Table[j].relsect = Table[j+1].relsect;
1322*7c478bd9Sstevel@tonic-gate 					Table[j].numsect = Table[j+1].numsect;
1323*7c478bd9Sstevel@tonic-gate 				}
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate 				/*
1326*7c478bd9Sstevel@tonic-gate 				 * Mark the last entry as unused in case
1327*7c478bd9Sstevel@tonic-gate 				 * all table entries were in use prior
1328*7c478bd9Sstevel@tonic-gate 				 * to the deletion.
1329*7c478bd9Sstevel@tonic-gate 				 */
1330*7c478bd9Sstevel@tonic-gate 
1331*7c478bd9Sstevel@tonic-gate 				Table[FD_NUMPART-1].systid = UNUSED;
1332*7c478bd9Sstevel@tonic-gate 				Table[FD_NUMPART-1].bootid = 0;
1333*7c478bd9Sstevel@tonic-gate 				return;
1334*7c478bd9Sstevel@tonic-gate 			}
1335*7c478bd9Sstevel@tonic-gate 		}
1336*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1337*7c478bd9Sstevel@tonic-gate 		    "fdisk: Entry does not match any existing partition:\n"
1338*7c478bd9Sstevel@tonic-gate 		    "	\"%s\"\n",
1339*7c478bd9Sstevel@tonic-gate 		    file);
1340*7c478bd9Sstevel@tonic-gate 		exit(1);
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 	    case LOADADD:
1343*7c478bd9Sstevel@tonic-gate 
1344*7c478bd9Sstevel@tonic-gate 		/* Parse the user-supplied addition line (-A) */
1345*7c478bd9Sstevel@tonic-gate 		pars_fdisk(file, &id, &act, &bhead, &bsect, &bcyl, &ehead,
1346*7c478bd9Sstevel@tonic-gate 		    &esect, &ecyl, &rsect, &numsect);
1347*7c478bd9Sstevel@tonic-gate 
1348*7c478bd9Sstevel@tonic-gate 		/* Validate the partition. It cannot start at sector 0 */
1349*7c478bd9Sstevel@tonic-gate 		if (rsect == 0) {
1350*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1351*7c478bd9Sstevel@tonic-gate 			    "fdisk: New partition cannot start at sector 0:\n"
1352*7c478bd9Sstevel@tonic-gate 			    "   \"%s\".\n",
1353*7c478bd9Sstevel@tonic-gate 			    file);
1354*7c478bd9Sstevel@tonic-gate 			exit(1);
1355*7c478bd9Sstevel@tonic-gate 		}
1356*7c478bd9Sstevel@tonic-gate 
1357*7c478bd9Sstevel@tonic-gate 		/*
1358*7c478bd9Sstevel@tonic-gate 		 * if the user wishes to add an EFI partition, we need
1359*7c478bd9Sstevel@tonic-gate 		 * more extensive validation.  rsect should be 1, and
1360*7c478bd9Sstevel@tonic-gate 		 * numsect should equal the entire disk capacity - 1
1361*7c478bd9Sstevel@tonic-gate 		 */
1362*7c478bd9Sstevel@tonic-gate 
1363*7c478bd9Sstevel@tonic-gate 		if (id == EFI_PMBR) {
1364*7c478bd9Sstevel@tonic-gate 			if (rsect != 1) {
1365*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1366*7c478bd9Sstevel@tonic-gate 				    "fdisk: EFI partitions must start at sector"
1367*7c478bd9Sstevel@tonic-gate 				    " 1 (input rsect = %d)\n", rsect);
1368*7c478bd9Sstevel@tonic-gate 				exit(1);
1369*7c478bd9Sstevel@tonic-gate 			}
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 			if (numsect != ((Numcyl * heads * sectors) -1)) {
1372*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr,
1373*7c478bd9Sstevel@tonic-gate 				    "fdisk: EFI partitions must encompass the "
1374*7c478bd9Sstevel@tonic-gate 				    "entire disk\n (input numsect: %ld - avail:"
1375*7c478bd9Sstevel@tonic-gate 				    " %ld)\n", numsect,
1376*7c478bd9Sstevel@tonic-gate 				    ((Numcyl * heads * sectors) -1));
1377*7c478bd9Sstevel@tonic-gate 				exit(1);
1378*7c478bd9Sstevel@tonic-gate 			}
1379*7c478bd9Sstevel@tonic-gate 		}
1380*7c478bd9Sstevel@tonic-gate 
1381*7c478bd9Sstevel@tonic-gate 		/* Find unused entry for use and put entry in table */
1382*7c478bd9Sstevel@tonic-gate 		if (insert_tbl(id, act, bhead, bsect, bcyl, ehead, esect,
1383*7c478bd9Sstevel@tonic-gate 		    ecyl, rsect, numsect) < 0) {
1384*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
1385*7c478bd9Sstevel@tonic-gate 			    "fdisk: Invalid entry could not be inserted:\n"
1386*7c478bd9Sstevel@tonic-gate 			    "	\"%s\"\n",
1387*7c478bd9Sstevel@tonic-gate 			    file);
1388*7c478bd9Sstevel@tonic-gate 			exit(1);
1389*7c478bd9Sstevel@tonic-gate 		}
1390*7c478bd9Sstevel@tonic-gate 
1391*7c478bd9Sstevel@tonic-gate 		/* Make sure new entry does not overlap existing entry */
1392*7c478bd9Sstevel@tonic-gate 		if (verify_tbl() < 0) {
1393*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1394*7c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot create partition \"%s\",\n");
1395*7c478bd9Sstevel@tonic-gate 			exit(1);
1396*7c478bd9Sstevel@tonic-gate 		}
1397*7c478bd9Sstevel@tonic-gate 	} /* switch funct */
1398*7c478bd9Sstevel@tonic-gate }
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate /*
1401*7c478bd9Sstevel@tonic-gate  * Set_Table_CHS_Values
1402*7c478bd9Sstevel@tonic-gate  *
1403*7c478bd9Sstevel@tonic-gate  * This will calculate the CHS values for beginning and ending CHS
1404*7c478bd9Sstevel@tonic-gate  * for a single partition table entry (ti) based on the relsect
1405*7c478bd9Sstevel@tonic-gate  * and numsect values contained in the partion table entry.
1406*7c478bd9Sstevel@tonic-gate  *
1407*7c478bd9Sstevel@tonic-gate  * hba_heads and hba_sectors contain the number of heads and sectors.
1408*7c478bd9Sstevel@tonic-gate  *
1409*7c478bd9Sstevel@tonic-gate  * If the number of cylinders exceeds the MAX_CYL,
1410*7c478bd9Sstevel@tonic-gate  * then maximum values will be placed in the corresponding chs entry.
1411*7c478bd9Sstevel@tonic-gate  */
1412*7c478bd9Sstevel@tonic-gate static void
1413*7c478bd9Sstevel@tonic-gate Set_Table_CHS_Values(int ti)
1414*7c478bd9Sstevel@tonic-gate {
1415*7c478bd9Sstevel@tonic-gate 	uint32_t	lba, cy, hd, sc;
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate 	lba = (uint32_t)Table[ti].relsect;
1418*7c478bd9Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
1419*7c478bd9Sstevel@tonic-gate 		/*
1420*7c478bd9Sstevel@tonic-gate 		 * the lba address cannot be expressed in CHS value
1421*7c478bd9Sstevel@tonic-gate 		 * so store the maximum CHS field values in the CHS fields.
1422*7c478bd9Sstevel@tonic-gate 		 */
1423*7c478bd9Sstevel@tonic-gate 		cy = MAX_CYL + 1;
1424*7c478bd9Sstevel@tonic-gate 		hd = MAX_HEAD;
1425*7c478bd9Sstevel@tonic-gate 		sc = MAX_SECT;
1426*7c478bd9Sstevel@tonic-gate 	} else {
1427*7c478bd9Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
1428*7c478bd9Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
1429*7c478bd9Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
1430*7c478bd9Sstevel@tonic-gate 	}
1431*7c478bd9Sstevel@tonic-gate 	Table[ti].begcyl = cy & 0xff;
1432*7c478bd9Sstevel@tonic-gate 	Table[ti].beghead = hd;
1433*7c478bd9Sstevel@tonic-gate 	Table[ti].begsect = ((cy >> 2) & 0xc0) | sc;
1434*7c478bd9Sstevel@tonic-gate 
1435*7c478bd9Sstevel@tonic-gate 	/*
1436*7c478bd9Sstevel@tonic-gate 	 * This code is identical to the code above
1437*7c478bd9Sstevel@tonic-gate 	 * except that it works on ending CHS values
1438*7c478bd9Sstevel@tonic-gate 	 */
1439*7c478bd9Sstevel@tonic-gate 	lba = (uint32_t)(Table[ti].relsect + Table[ti].numsect - 1);
1440*7c478bd9Sstevel@tonic-gate 	if (lba >= hba_heads * hba_sectors * MAX_CYL) {
1441*7c478bd9Sstevel@tonic-gate 		cy = MAX_CYL + 1;
1442*7c478bd9Sstevel@tonic-gate 		hd = MAX_HEAD;
1443*7c478bd9Sstevel@tonic-gate 		sc = MAX_SECT;
1444*7c478bd9Sstevel@tonic-gate 	} else {
1445*7c478bd9Sstevel@tonic-gate 		cy = lba / hba_sectors / hba_heads;
1446*7c478bd9Sstevel@tonic-gate 		hd = lba / hba_sectors % hba_heads;
1447*7c478bd9Sstevel@tonic-gate 		sc = lba % hba_sectors + 1;
1448*7c478bd9Sstevel@tonic-gate 	}
1449*7c478bd9Sstevel@tonic-gate 	Table[ti].endcyl = cy & 0xff;
1450*7c478bd9Sstevel@tonic-gate 	Table[ti].endhead = hd;
1451*7c478bd9Sstevel@tonic-gate 	Table[ti].endsect = ((cy >> 2) & 0xc0) | sc;
1452*7c478bd9Sstevel@tonic-gate }
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate /*
1455*7c478bd9Sstevel@tonic-gate  * insert_tbl
1456*7c478bd9Sstevel@tonic-gate  * 	Insert entry into fdisk table. Check all user-supplied values
1457*7c478bd9Sstevel@tonic-gate  *	for the entry, but not the validity relative to other table
1458*7c478bd9Sstevel@tonic-gate  *	entries!
1459*7c478bd9Sstevel@tonic-gate  */
1460*7c478bd9Sstevel@tonic-gate insert_tbl(id, act, bhead, bsect, bcyl, ehead, esect, ecyl, rsect, numsect)
1461*7c478bd9Sstevel@tonic-gate int	id, act, bhead, bsect, bcyl, ehead, esect, ecyl, rsect, numsect;
1462*7c478bd9Sstevel@tonic-gate {
1463*7c478bd9Sstevel@tonic-gate 	int	i;
1464*7c478bd9Sstevel@tonic-gate 
1465*7c478bd9Sstevel@tonic-gate 	/* validate partition size */
1466*7c478bd9Sstevel@tonic-gate 	if (rsect+numsect > (Numcyl * heads * sectors)) {
1467*7c478bd9Sstevel@tonic-gate 		fprintf(stderr,
1468*7c478bd9Sstevel@tonic-gate 		    "fdisk: Partition table exceeds the size of the disk.\n");
1469*7c478bd9Sstevel@tonic-gate 		return (-1);
1470*7c478bd9Sstevel@tonic-gate 	}
1471*7c478bd9Sstevel@tonic-gate 
1472*7c478bd9Sstevel@tonic-gate 	/* find UNUSED partition table entry */
1473*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
1474*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
1475*7c478bd9Sstevel@tonic-gate 			break;
1476*7c478bd9Sstevel@tonic-gate 		}
1477*7c478bd9Sstevel@tonic-gate 	}
1478*7c478bd9Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
1479*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "fdisk: Partition table is full.\n");
1480*7c478bd9Sstevel@tonic-gate 		return (-1);
1481*7c478bd9Sstevel@tonic-gate 	}
1482*7c478bd9Sstevel@tonic-gate 
1483*7c478bd9Sstevel@tonic-gate 
1484*7c478bd9Sstevel@tonic-gate 	Table[i].systid = id;
1485*7c478bd9Sstevel@tonic-gate 	Table[i].bootid = act;
1486*7c478bd9Sstevel@tonic-gate 	Table[i].numsect = lel(numsect);
1487*7c478bd9Sstevel@tonic-gate 	Table[i].relsect = lel(rsect);
1488*7c478bd9Sstevel@tonic-gate 
1489*7c478bd9Sstevel@tonic-gate 	/*
1490*7c478bd9Sstevel@tonic-gate 	 * If we have been called with a valid geometry, use it
1491*7c478bd9Sstevel@tonic-gate 	 * valid means non-zero values that fit in the BIOS fields
1492*7c478bd9Sstevel@tonic-gate 	 */
1493*7c478bd9Sstevel@tonic-gate 	if (0 < bsect && bsect <= MAX_SECT &&
1494*7c478bd9Sstevel@tonic-gate 	    0 <= bhead && bhead <= MAX_HEAD &&
1495*7c478bd9Sstevel@tonic-gate 	    0 < esect && esect <= MAX_SECT &&
1496*7c478bd9Sstevel@tonic-gate 	    0 <= ehead && ehead <= MAX_HEAD) {
1497*7c478bd9Sstevel@tonic-gate 		if (bcyl > MAX_CYL)
1498*7c478bd9Sstevel@tonic-gate 			bcyl = MAX_CYL + 1;
1499*7c478bd9Sstevel@tonic-gate 		if (ecyl > MAX_CYL)
1500*7c478bd9Sstevel@tonic-gate 			ecyl = MAX_CYL + 1;
1501*7c478bd9Sstevel@tonic-gate 		Table[i].begcyl = bcyl & 0xff;
1502*7c478bd9Sstevel@tonic-gate 		Table[i].endcyl = ecyl & 0xff;
1503*7c478bd9Sstevel@tonic-gate 		Table[i].beghead = bhead;
1504*7c478bd9Sstevel@tonic-gate 		Table[i].endhead = ehead;
1505*7c478bd9Sstevel@tonic-gate 		Table[i].begsect = ((bcyl >> 2) & 0xc0) | bsect;
1506*7c478bd9Sstevel@tonic-gate 		Table[i].endsect = ((ecyl >> 2) & 0xc0) | esect;
1507*7c478bd9Sstevel@tonic-gate 	} else {
1508*7c478bd9Sstevel@tonic-gate 
1509*7c478bd9Sstevel@tonic-gate 		/*
1510*7c478bd9Sstevel@tonic-gate 		 * The specified values are invalid,
1511*7c478bd9Sstevel@tonic-gate 		 * so calculate the values based on hba_heads, hba_sectors
1512*7c478bd9Sstevel@tonic-gate 		 */
1513*7c478bd9Sstevel@tonic-gate 		Set_Table_CHS_Values(i);
1514*7c478bd9Sstevel@tonic-gate 	}
1515*7c478bd9Sstevel@tonic-gate 
1516*7c478bd9Sstevel@tonic-gate 	/*
1517*7c478bd9Sstevel@tonic-gate 	 * return partition index
1518*7c478bd9Sstevel@tonic-gate 	 */
1519*7c478bd9Sstevel@tonic-gate 	return (i);
1520*7c478bd9Sstevel@tonic-gate }
1521*7c478bd9Sstevel@tonic-gate 
1522*7c478bd9Sstevel@tonic-gate /*
1523*7c478bd9Sstevel@tonic-gate  * verify_tbl
1524*7c478bd9Sstevel@tonic-gate  * Verify that no partition entries overlap or exceed the size of
1525*7c478bd9Sstevel@tonic-gate  * the disk.
1526*7c478bd9Sstevel@tonic-gate  */
1527*7c478bd9Sstevel@tonic-gate int
1528*7c478bd9Sstevel@tonic-gate verify_tbl()
1529*7c478bd9Sstevel@tonic-gate {
1530*7c478bd9Sstevel@tonic-gate 	int	i, j, rsect, numsect;
1531*7c478bd9Sstevel@tonic-gate 	int	noMoreParts = 0;
1532*7c478bd9Sstevel@tonic-gate 	int	numParts = 0;
1533*7c478bd9Sstevel@tonic-gate 
1534*7c478bd9Sstevel@tonic-gate 	/* Make sure new entry does not overlap an existing entry */
1535*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART-1; i++) {
1536*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
1537*7c478bd9Sstevel@tonic-gate 			numParts++;
1538*7c478bd9Sstevel@tonic-gate 			/*
1539*7c478bd9Sstevel@tonic-gate 			 * No valid partitions allowed after an UNUSED  or
1540*7c478bd9Sstevel@tonic-gate 			 * EFI_PMBR part
1541*7c478bd9Sstevel@tonic-gate 			 */
1542*7c478bd9Sstevel@tonic-gate 			if (noMoreParts) {
1543*7c478bd9Sstevel@tonic-gate 				return (-1);
1544*7c478bd9Sstevel@tonic-gate 			}
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 			/*
1547*7c478bd9Sstevel@tonic-gate 			 * EFI_PMBR partitions must be the only partition
1548*7c478bd9Sstevel@tonic-gate 			 * and must be Table entry 0
1549*7c478bd9Sstevel@tonic-gate 			 */
1550*7c478bd9Sstevel@tonic-gate 			if (Table[i].systid == EFI_PMBR) {
1551*7c478bd9Sstevel@tonic-gate 				if (i == 0) {
1552*7c478bd9Sstevel@tonic-gate 					noMoreParts = 1;
1553*7c478bd9Sstevel@tonic-gate 				} else {
1554*7c478bd9Sstevel@tonic-gate 					return (-1);
1555*7c478bd9Sstevel@tonic-gate 				}
1556*7c478bd9Sstevel@tonic-gate 
1557*7c478bd9Sstevel@tonic-gate 				if (Table[i].relsect != 1) {
1558*7c478bd9Sstevel@tonic-gate 					fprintf(stderr, "ERROR: "
1559*7c478bd9Sstevel@tonic-gate 					    "Invalid starting sector "
1560*7c478bd9Sstevel@tonic-gate 					    "for EFI_PMBR partition:\n"
1561*7c478bd9Sstevel@tonic-gate 					    "relsect %d "
1562*7c478bd9Sstevel@tonic-gate 					    "(should be 1)\n",
1563*7c478bd9Sstevel@tonic-gate 					    Table[i].relsect);
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate 					return (-1);
1566*7c478bd9Sstevel@tonic-gate 				}
1567*7c478bd9Sstevel@tonic-gate 
1568*7c478bd9Sstevel@tonic-gate 				if (Table[i].numsect !=
1569*7c478bd9Sstevel@tonic-gate 				    ((Numcyl * heads * sectors) - 1)) {
1570*7c478bd9Sstevel@tonic-gate 					fprintf(stderr, "ERROR: "
1571*7c478bd9Sstevel@tonic-gate 					    "EFI_PMBR partition must "
1572*7c478bd9Sstevel@tonic-gate 					    "encompass the entire "
1573*7c478bd9Sstevel@tonic-gate 					    "disk.\n numsect %ld - "
1574*7c478bd9Sstevel@tonic-gate 					    "actual %ld\n",
1575*7c478bd9Sstevel@tonic-gate 					    Table[i].numsect,
1576*7c478bd9Sstevel@tonic-gate 					    ((Numcyl * heads * sectors) - 1));
1577*7c478bd9Sstevel@tonic-gate 
1578*7c478bd9Sstevel@tonic-gate 					return (-1);
1579*7c478bd9Sstevel@tonic-gate 				}
1580*7c478bd9Sstevel@tonic-gate 			}
1581*7c478bd9Sstevel@tonic-gate 
1582*7c478bd9Sstevel@tonic-gate 			/* make sure the partition isn't larger than the disk */
1583*7c478bd9Sstevel@tonic-gate 			rsect = lel(Table[i].relsect);
1584*7c478bd9Sstevel@tonic-gate 			numsect = lel(Table[i].numsect);
1585*7c478bd9Sstevel@tonic-gate 			if ((rsect + numsect) > (Numcyl * heads * sectors)) {
1586*7c478bd9Sstevel@tonic-gate 				return (-1);
1587*7c478bd9Sstevel@tonic-gate 			}
1588*7c478bd9Sstevel@tonic-gate 
1589*7c478bd9Sstevel@tonic-gate 			for (j = i+1; j < FD_NUMPART; j++) {
1590*7c478bd9Sstevel@tonic-gate 				if (Table[j].systid != UNUSED) {
1591*7c478bd9Sstevel@tonic-gate 					int t_relsect = lel(Table[j].relsect);
1592*7c478bd9Sstevel@tonic-gate 					int t_numsect = lel(Table[j].numsect);
1593*7c478bd9Sstevel@tonic-gate 
1594*7c478bd9Sstevel@tonic-gate 					if (noMoreParts) {
1595*7c478bd9Sstevel@tonic-gate 						fprintf(stderr,
1596*7c478bd9Sstevel@tonic-gate 						    "Cannot add partition to "
1597*7c478bd9Sstevel@tonic-gate 						    "table; no more partitions "
1598*7c478bd9Sstevel@tonic-gate 						    "allowed\n");
1599*7c478bd9Sstevel@tonic-gate 
1600*7c478bd9Sstevel@tonic-gate 						if (io_debug) {
1601*7c478bd9Sstevel@tonic-gate 							fprintf(stderr,
1602*7c478bd9Sstevel@tonic-gate 							    "DEBUG: Current "
1603*7c478bd9Sstevel@tonic-gate 							    "partition:\t"
1604*7c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
1605*7c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%ld\n"
1606*7c478bd9Sstevel@tonic-gate 							    "       Next "
1607*7c478bd9Sstevel@tonic-gate 							    "partition:\t\t"
1608*7c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%d:"
1609*7c478bd9Sstevel@tonic-gate 							    "%d:%d:%d:%d:%ld\n",
1610*7c478bd9Sstevel@tonic-gate 							    Table[i].systid,
1611*7c478bd9Sstevel@tonic-gate 							    Table[i].bootid,
1612*7c478bd9Sstevel@tonic-gate 							    Table[i].begcyl,
1613*7c478bd9Sstevel@tonic-gate 							    Table[i].beghead,
1614*7c478bd9Sstevel@tonic-gate 							    Table[i].begsect,
1615*7c478bd9Sstevel@tonic-gate 							    Table[i].endcyl,
1616*7c478bd9Sstevel@tonic-gate 							    Table[i].endhead,
1617*7c478bd9Sstevel@tonic-gate 							    Table[i].endsect,
1618*7c478bd9Sstevel@tonic-gate 							    Table[i].relsect,
1619*7c478bd9Sstevel@tonic-gate 							    Table[i].numsect,
1620*7c478bd9Sstevel@tonic-gate 							    Table[j].systid,
1621*7c478bd9Sstevel@tonic-gate 							    Table[j].bootid,
1622*7c478bd9Sstevel@tonic-gate 							    Table[j].begcyl,
1623*7c478bd9Sstevel@tonic-gate 							    Table[j].beghead,
1624*7c478bd9Sstevel@tonic-gate 							    Table[j].begsect,
1625*7c478bd9Sstevel@tonic-gate 							    Table[j].endcyl,
1626*7c478bd9Sstevel@tonic-gate 							    Table[j].endhead,
1627*7c478bd9Sstevel@tonic-gate 							    Table[j].endsect,
1628*7c478bd9Sstevel@tonic-gate 							    Table[j].relsect,
1629*7c478bd9Sstevel@tonic-gate 							    Table[j].numsect);
1630*7c478bd9Sstevel@tonic-gate 						}
1631*7c478bd9Sstevel@tonic-gate 
1632*7c478bd9Sstevel@tonic-gate 						return (-1);
1633*7c478bd9Sstevel@tonic-gate 					}
1634*7c478bd9Sstevel@tonic-gate 
1635*7c478bd9Sstevel@tonic-gate 					if ((rsect >=
1636*7c478bd9Sstevel@tonic-gate 					    (t_relsect + t_numsect)) ||
1637*7c478bd9Sstevel@tonic-gate 					    ((rsect+numsect) <= t_relsect)) {
1638*7c478bd9Sstevel@tonic-gate 						continue;
1639*7c478bd9Sstevel@tonic-gate 					} else {
1640*7c478bd9Sstevel@tonic-gate 						fprintf(stderr, "ERROR: "
1641*7c478bd9Sstevel@tonic-gate 						    "current partition overlaps"
1642*7c478bd9Sstevel@tonic-gate 						    " following partition\n");
1643*7c478bd9Sstevel@tonic-gate 
1644*7c478bd9Sstevel@tonic-gate 						return (-1);
1645*7c478bd9Sstevel@tonic-gate 					}
1646*7c478bd9Sstevel@tonic-gate 				}
1647*7c478bd9Sstevel@tonic-gate 			}
1648*7c478bd9Sstevel@tonic-gate 		} else {
1649*7c478bd9Sstevel@tonic-gate 			noMoreParts = 1;
1650*7c478bd9Sstevel@tonic-gate 		}
1651*7c478bd9Sstevel@tonic-gate 	}
1652*7c478bd9Sstevel@tonic-gate 	if (Table[i].systid != UNUSED) {
1653*7c478bd9Sstevel@tonic-gate 		if (noMoreParts ||
1654*7c478bd9Sstevel@tonic-gate 		    ((lel(Table[i].relsect) + lel(Table[i].numsect)) >
1655*7c478bd9Sstevel@tonic-gate 		    (Numcyl * heads * sectors))) {
1656*7c478bd9Sstevel@tonic-gate 			return (-1);
1657*7c478bd9Sstevel@tonic-gate 		}
1658*7c478bd9Sstevel@tonic-gate 	}
1659*7c478bd9Sstevel@tonic-gate 
1660*7c478bd9Sstevel@tonic-gate 	return (numParts);
1661*7c478bd9Sstevel@tonic-gate }
1662*7c478bd9Sstevel@tonic-gate 
1663*7c478bd9Sstevel@tonic-gate /*
1664*7c478bd9Sstevel@tonic-gate  * pars_fdisk
1665*7c478bd9Sstevel@tonic-gate  * Parse user-supplied data to set up fdisk partitions
1666*7c478bd9Sstevel@tonic-gate  * (-A, -D, -F).
1667*7c478bd9Sstevel@tonic-gate  */
1668*7c478bd9Sstevel@tonic-gate pars_fdisk(line, id, act, bhead, bsect, bcyl, ehead, esect, ecyl,
1669*7c478bd9Sstevel@tonic-gate 	rsect, numsect)
1670*7c478bd9Sstevel@tonic-gate char *line;
1671*7c478bd9Sstevel@tonic-gate char *id, *act, *bhead, *bsect, *bcyl, *ehead, *esect, *ecyl, *rsect;
1672*7c478bd9Sstevel@tonic-gate char *numsect;
1673*7c478bd9Sstevel@tonic-gate {
1674*7c478bd9Sstevel@tonic-gate 	int	i;
1675*7c478bd9Sstevel@tonic-gate 	if (line[0] == '\0' || line[0] == '\n' || line[0] == '*')
1676*7c478bd9Sstevel@tonic-gate 	    return (1);
1677*7c478bd9Sstevel@tonic-gate 	line[strlen(line)] = '\0';
1678*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < strlen(line); i++) {
1679*7c478bd9Sstevel@tonic-gate 		if (line[i] == '\0') {
1680*7c478bd9Sstevel@tonic-gate 			break;
1681*7c478bd9Sstevel@tonic-gate 		} else if (line[i] == ':') {
1682*7c478bd9Sstevel@tonic-gate 			line[i] = ' ';
1683*7c478bd9Sstevel@tonic-gate 		}
1684*7c478bd9Sstevel@tonic-gate 	}
1685*7c478bd9Sstevel@tonic-gate 	if (sscanf(line, "%d %d %d %d %d %d %d %d %ld %ld",
1686*7c478bd9Sstevel@tonic-gate 	    id, act, bhead, bsect, bcyl, ehead, esect, ecyl,
1687*7c478bd9Sstevel@tonic-gate 	    rsect, numsect) != 10) {
1688*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "Syntax error:\n	\"%s\".\n", line);
1689*7c478bd9Sstevel@tonic-gate 		exit(1);
1690*7c478bd9Sstevel@tonic-gate 	}
1691*7c478bd9Sstevel@tonic-gate 	return (0);
1692*7c478bd9Sstevel@tonic-gate }
1693*7c478bd9Sstevel@tonic-gate 
1694*7c478bd9Sstevel@tonic-gate /*
1695*7c478bd9Sstevel@tonic-gate  * validate_part
1696*7c478bd9Sstevel@tonic-gate  * Validate that a new partition does not start at sector 0. Only UNUSED
1697*7c478bd9Sstevel@tonic-gate  * partitions and previously existing partitions are allowed to start at 0.
1698*7c478bd9Sstevel@tonic-gate  */
1699*7c478bd9Sstevel@tonic-gate validate_part(id, rsect, numsect)
1700*7c478bd9Sstevel@tonic-gate int id, rsect, numsect;
1701*7c478bd9Sstevel@tonic-gate {
1702*7c478bd9Sstevel@tonic-gate 	int i;
1703*7c478bd9Sstevel@tonic-gate 	if ((id != UNUSED) && (rsect == 0)) {
1704*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
1705*7c478bd9Sstevel@tonic-gate 			if ((Old_Table[i].systid == id) &&
1706*7c478bd9Sstevel@tonic-gate 			    (Old_Table[i].relsect == lel(rsect)) &&
1707*7c478bd9Sstevel@tonic-gate 			    (Old_Table[i].numsect == lel(numsect))) return (0);
1708*7c478bd9Sstevel@tonic-gate 		}
1709*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "New partition cannot start at sector 0\n");
1710*7c478bd9Sstevel@tonic-gate 		return (-1);
1711*7c478bd9Sstevel@tonic-gate 	}
1712*7c478bd9Sstevel@tonic-gate 	return (0);
1713*7c478bd9Sstevel@tonic-gate }
1714*7c478bd9Sstevel@tonic-gate 
1715*7c478bd9Sstevel@tonic-gate /*
1716*7c478bd9Sstevel@tonic-gate  * stage0
1717*7c478bd9Sstevel@tonic-gate  * Print out interactive menu and process user input.
1718*7c478bd9Sstevel@tonic-gate  */
1719*7c478bd9Sstevel@tonic-gate stage0(file)
1720*7c478bd9Sstevel@tonic-gate char *file;
1721*7c478bd9Sstevel@tonic-gate {
1722*7c478bd9Sstevel@tonic-gate 	dispmenu(file);
1723*7c478bd9Sstevel@tonic-gate 	while (1) {
1724*7c478bd9Sstevel@tonic-gate 		printf(Q_LINE);
1725*7c478bd9Sstevel@tonic-gate 		printf("Enter Selection: ");
1726*7c478bd9Sstevel@tonic-gate 		gets(s);
1727*7c478bd9Sstevel@tonic-gate 		rm_blanks(s);
1728*7c478bd9Sstevel@tonic-gate 		while (!((s[0] > '0') && (s[0] < '7') && (s[1] == 0))) {
1729*7c478bd9Sstevel@tonic-gate 			printf(E_LINE); /* Clear any previous error */
1730*7c478bd9Sstevel@tonic-gate 			printf("Enter a one-digit number between 1 and 6.");
1731*7c478bd9Sstevel@tonic-gate 			printf(Q_LINE);
1732*7c478bd9Sstevel@tonic-gate 			printf("Enter Selection: ");
1733*7c478bd9Sstevel@tonic-gate 			gets(s);
1734*7c478bd9Sstevel@tonic-gate 			rm_blanks(s);
1735*7c478bd9Sstevel@tonic-gate 		}
1736*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
1737*7c478bd9Sstevel@tonic-gate 		switch (s[0]) {
1738*7c478bd9Sstevel@tonic-gate 			case '1':
1739*7c478bd9Sstevel@tonic-gate 				if (pcreate() == -1)
1740*7c478bd9Sstevel@tonic-gate 					return;
1741*7c478bd9Sstevel@tonic-gate 				break;
1742*7c478bd9Sstevel@tonic-gate 			case '2':
1743*7c478bd9Sstevel@tonic-gate 				if (pchange() == -1)
1744*7c478bd9Sstevel@tonic-gate 					return;
1745*7c478bd9Sstevel@tonic-gate 				break;
1746*7c478bd9Sstevel@tonic-gate 			case '3':
1747*7c478bd9Sstevel@tonic-gate 				if (pdelete() == -1)
1748*7c478bd9Sstevel@tonic-gate 					return;
1749*7c478bd9Sstevel@tonic-gate 				break;
1750*7c478bd9Sstevel@tonic-gate 			case '4':
1751*7c478bd9Sstevel@tonic-gate 				if (ppartid() == -1)
1752*7c478bd9Sstevel@tonic-gate 					return;
1753*7c478bd9Sstevel@tonic-gate 				break;
1754*7c478bd9Sstevel@tonic-gate 			case '5':
1755*7c478bd9Sstevel@tonic-gate 				/* update disk partition table, if changed */
1756*7c478bd9Sstevel@tonic-gate 				if (TableChanged() == 1) {
1757*7c478bd9Sstevel@tonic-gate 					copy_Table_to_Bootblk();
1758*7c478bd9Sstevel@tonic-gate 					dev_mboot_write(0, Bootsect, sectsiz);
1759*7c478bd9Sstevel@tonic-gate 				}
1760*7c478bd9Sstevel@tonic-gate 				/*
1761*7c478bd9Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
1762*7c478bd9Sstevel@tonic-gate 				 * (truncate only)
1763*7c478bd9Sstevel@tonic-gate 				 */
1764*7c478bd9Sstevel@tonic-gate 				if (io_adjt) {
1765*7c478bd9Sstevel@tonic-gate 					fix_slice();
1766*7c478bd9Sstevel@tonic-gate 				}
1767*7c478bd9Sstevel@tonic-gate 				close(Dev);
1768*7c478bd9Sstevel@tonic-gate 				exit(0);
1769*7c478bd9Sstevel@tonic-gate 			case '6':
1770*7c478bd9Sstevel@tonic-gate 				/*
1771*7c478bd9Sstevel@tonic-gate 				 * If the VTOC table is wrong fix it
1772*7c478bd9Sstevel@tonic-gate 				 * (truncate only)
1773*7c478bd9Sstevel@tonic-gate 				 */
1774*7c478bd9Sstevel@tonic-gate 				if (io_adjt) {
1775*7c478bd9Sstevel@tonic-gate 					fix_slice();
1776*7c478bd9Sstevel@tonic-gate 				}
1777*7c478bd9Sstevel@tonic-gate 				close(Dev);
1778*7c478bd9Sstevel@tonic-gate 				exit(0);
1779*7c478bd9Sstevel@tonic-gate 			default:
1780*7c478bd9Sstevel@tonic-gate 				break;
1781*7c478bd9Sstevel@tonic-gate 		}
1782*7c478bd9Sstevel@tonic-gate 		copy_Table_to_Bootblk();
1783*7c478bd9Sstevel@tonic-gate 		disptbl();
1784*7c478bd9Sstevel@tonic-gate 		dispmenu(file);
1785*7c478bd9Sstevel@tonic-gate 	}
1786*7c478bd9Sstevel@tonic-gate }
1787*7c478bd9Sstevel@tonic-gate 
1788*7c478bd9Sstevel@tonic-gate /*
1789*7c478bd9Sstevel@tonic-gate  * pcreate
1790*7c478bd9Sstevel@tonic-gate  * Create partition entry in the table (interactive mode).
1791*7c478bd9Sstevel@tonic-gate  */
1792*7c478bd9Sstevel@tonic-gate pcreate()
1793*7c478bd9Sstevel@tonic-gate {
1794*7c478bd9Sstevel@tonic-gate 	unsigned char tsystid = 'z';
1795*7c478bd9Sstevel@tonic-gate 	int i, j;
1796*7c478bd9Sstevel@tonic-gate 	int startcyl, endcyl;
1797*7c478bd9Sstevel@tonic-gate 	int rsect = 1;
1798*7c478bd9Sstevel@tonic-gate 	int retCode = 0;
1799*7c478bd9Sstevel@tonic-gate 
1800*7c478bd9Sstevel@tonic-gate 	i = 0;
1801*7c478bd9Sstevel@tonic-gate 	while (1) {
1802*7c478bd9Sstevel@tonic-gate 		if (i == FD_NUMPART) {
1803*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
1804*7c478bd9Sstevel@tonic-gate 			printf("The partition table is full!\n");
1805*7c478bd9Sstevel@tonic-gate 			printf("You must delete a partition before creating"
1806*7c478bd9Sstevel@tonic-gate 			    " a new one.\n");
1807*7c478bd9Sstevel@tonic-gate 			return (-1);
1808*7c478bd9Sstevel@tonic-gate 		}
1809*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
1810*7c478bd9Sstevel@tonic-gate 			break;
1811*7c478bd9Sstevel@tonic-gate 		}
1812*7c478bd9Sstevel@tonic-gate 		i++;
1813*7c478bd9Sstevel@tonic-gate 	}
1814*7c478bd9Sstevel@tonic-gate 
1815*7c478bd9Sstevel@tonic-gate 	j = 0;
1816*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
1817*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid != UNUSED) {
1818*7c478bd9Sstevel@tonic-gate 			j += lel(Table[i].numsect);
1819*7c478bd9Sstevel@tonic-gate 		}
1820*7c478bd9Sstevel@tonic-gate 		if (j >= Numcyl * heads * sectors) {
1821*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
1822*7c478bd9Sstevel@tonic-gate 			printf("There is no more room on the disk for"
1823*7c478bd9Sstevel@tonic-gate 			    " another partition.\n");
1824*7c478bd9Sstevel@tonic-gate 			printf("You must delete a partition before creating"
1825*7c478bd9Sstevel@tonic-gate 			    " a new one.\n");
1826*7c478bd9Sstevel@tonic-gate 			return (-1);
1827*7c478bd9Sstevel@tonic-gate 		}
1828*7c478bd9Sstevel@tonic-gate 	}
1829*7c478bd9Sstevel@tonic-gate 	while (tsystid == 'z') {
1830*7c478bd9Sstevel@tonic-gate 		printf(Q_LINE);
1831*7c478bd9Sstevel@tonic-gate 		printf("Select the partition type to create:\n");
1832*7c478bd9Sstevel@tonic-gate 		printf("   1=SOLARIS2  2=UNIX        3=PCIXOS     4=Other\n");
1833*7c478bd9Sstevel@tonic-gate 		printf("   5=DOS12     6=DOS16       7=DOSEXT     8=DOSBIG\n");
1834*7c478bd9Sstevel@tonic-gate 		printf("   9=DOS16LBA  A=x86 Boot    B=Diagnostic C=FAT32\n");
1835*7c478bd9Sstevel@tonic-gate 		printf("   D=FAT32LBA  E=DOSEXTLBA   F=EFI        0=Exit? ");
1836*7c478bd9Sstevel@tonic-gate 		gets(s);
1837*7c478bd9Sstevel@tonic-gate 		rm_blanks(s);
1838*7c478bd9Sstevel@tonic-gate 		if (s[1] != 0) {
1839*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
1840*7c478bd9Sstevel@tonic-gate 			printf("Invalid selection, try again.");
1841*7c478bd9Sstevel@tonic-gate 			continue;
1842*7c478bd9Sstevel@tonic-gate 		}
1843*7c478bd9Sstevel@tonic-gate 		switch (s[0]) {
1844*7c478bd9Sstevel@tonic-gate 		case '0':		/* exit */
1845*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
1846*7c478bd9Sstevel@tonic-gate 		    return (-1);
1847*7c478bd9Sstevel@tonic-gate 		case '1':		/* Solaris partition */
1848*7c478bd9Sstevel@tonic-gate 		    tsystid = SUNIXOS2;
1849*7c478bd9Sstevel@tonic-gate 		    break;
1850*7c478bd9Sstevel@tonic-gate 		case '2':		/* UNIX partition */
1851*7c478bd9Sstevel@tonic-gate 		    tsystid = UNIXOS;
1852*7c478bd9Sstevel@tonic-gate 		    break;
1853*7c478bd9Sstevel@tonic-gate 		case '3':		/* PCIXOS partition */
1854*7c478bd9Sstevel@tonic-gate 		    tsystid = PCIXOS;
1855*7c478bd9Sstevel@tonic-gate 		    break;
1856*7c478bd9Sstevel@tonic-gate 		case '4':		/* OTHEROS System partition */
1857*7c478bd9Sstevel@tonic-gate 		    tsystid = OTHEROS;
1858*7c478bd9Sstevel@tonic-gate 		    break;
1859*7c478bd9Sstevel@tonic-gate 		case '5':
1860*7c478bd9Sstevel@tonic-gate 		    tsystid = DOSOS12; /* DOS 12 bit fat */
1861*7c478bd9Sstevel@tonic-gate 		    break;
1862*7c478bd9Sstevel@tonic-gate 		case '6':
1863*7c478bd9Sstevel@tonic-gate 		    tsystid = DOSOS16; /* DOS 16 bit fat */
1864*7c478bd9Sstevel@tonic-gate 		    break;
1865*7c478bd9Sstevel@tonic-gate 		case '7':
1866*7c478bd9Sstevel@tonic-gate 		    tsystid = EXTDOS;
1867*7c478bd9Sstevel@tonic-gate 		    break;
1868*7c478bd9Sstevel@tonic-gate 		case '8':
1869*7c478bd9Sstevel@tonic-gate 		    tsystid = DOSHUGE;
1870*7c478bd9Sstevel@tonic-gate 		    break;
1871*7c478bd9Sstevel@tonic-gate 		case '9':
1872*7c478bd9Sstevel@tonic-gate 		    tsystid = FDISK_FAT95;  /* FAT16, need extended int13 */
1873*7c478bd9Sstevel@tonic-gate 		    break;
1874*7c478bd9Sstevel@tonic-gate 		case 'a':		/* x86 Boot partition */
1875*7c478bd9Sstevel@tonic-gate 		case 'A':
1876*7c478bd9Sstevel@tonic-gate 		    tsystid = X86BOOT;
1877*7c478bd9Sstevel@tonic-gate 		    break;
1878*7c478bd9Sstevel@tonic-gate 		case 'b':		/* Diagnostic boot partition */
1879*7c478bd9Sstevel@tonic-gate 		case 'B':
1880*7c478bd9Sstevel@tonic-gate 		    tsystid = DIAGPART;
1881*7c478bd9Sstevel@tonic-gate 		    break;
1882*7c478bd9Sstevel@tonic-gate 		case 'c':		/* FAT32 */
1883*7c478bd9Sstevel@tonic-gate 		case 'C':
1884*7c478bd9Sstevel@tonic-gate 		    tsystid = FDISK_WINDOWS;
1885*7c478bd9Sstevel@tonic-gate 		    break;
1886*7c478bd9Sstevel@tonic-gate 		case 'd':		/* FAT32 and need extended int13 */
1887*7c478bd9Sstevel@tonic-gate 		case 'D':
1888*7c478bd9Sstevel@tonic-gate 		    tsystid = FDISK_EXT_WIN;
1889*7c478bd9Sstevel@tonic-gate 		    break;
1890*7c478bd9Sstevel@tonic-gate 		case 'e':	/* Extended partition, need extended int13 */
1891*7c478bd9Sstevel@tonic-gate 		case 'E':
1892*7c478bd9Sstevel@tonic-gate 		    tsystid = FDISK_EXTLBA;
1893*7c478bd9Sstevel@tonic-gate 		    break;
1894*7c478bd9Sstevel@tonic-gate 		case 'f':
1895*7c478bd9Sstevel@tonic-gate 		case 'F':
1896*7c478bd9Sstevel@tonic-gate 		    tsystid = EFI_PMBR;
1897*7c478bd9Sstevel@tonic-gate 		    break;
1898*7c478bd9Sstevel@tonic-gate 		default:
1899*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
1900*7c478bd9Sstevel@tonic-gate 		    printf("Invalid selection, try again.");
1901*7c478bd9Sstevel@tonic-gate 		    continue;
1902*7c478bd9Sstevel@tonic-gate 		}
1903*7c478bd9Sstevel@tonic-gate 	}
1904*7c478bd9Sstevel@tonic-gate 
1905*7c478bd9Sstevel@tonic-gate 	printf(E_LINE);
1906*7c478bd9Sstevel@tonic-gate 
1907*7c478bd9Sstevel@tonic-gate 	if (tsystid != EFI_PMBR) {
1908*7c478bd9Sstevel@tonic-gate 		/* create the new partition */
1909*7c478bd9Sstevel@tonic-gate 		i = specify(tsystid);
1910*7c478bd9Sstevel@tonic-gate 
1911*7c478bd9Sstevel@tonic-gate 		if (i != -1) {
1912*7c478bd9Sstevel@tonic-gate 			/* see if it should be the active partition */
1913*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
1914*7c478bd9Sstevel@tonic-gate 			printf(Q_LINE);
1915*7c478bd9Sstevel@tonic-gate 
1916*7c478bd9Sstevel@tonic-gate 			printf("Should this become the active partition? If "
1917*7c478bd9Sstevel@tonic-gate 			    "yes, it  will be activated\n");
1918*7c478bd9Sstevel@tonic-gate 			printf("each time the computer is reset or turned "
1919*7c478bd9Sstevel@tonic-gate 			    "on.\n");
1920*7c478bd9Sstevel@tonic-gate 			printf("Please type \"y\" or \"n\". ");
1921*7c478bd9Sstevel@tonic-gate 
1922*7c478bd9Sstevel@tonic-gate 			if (yesno()) {
1923*7c478bd9Sstevel@tonic-gate 				printf(E_LINE);
1924*7c478bd9Sstevel@tonic-gate 				for (j = 0; j < FD_NUMPART; j++) {
1925*7c478bd9Sstevel@tonic-gate 					if (j == i) {
1926*7c478bd9Sstevel@tonic-gate 						Table[j].bootid = ACTIVE;
1927*7c478bd9Sstevel@tonic-gate 						printf(E_LINE);
1928*7c478bd9Sstevel@tonic-gate 						printf("Partition %d is now "
1929*7c478bd9Sstevel@tonic-gate 						    "the active partition.",
1930*7c478bd9Sstevel@tonic-gate 						    j+1);
1931*7c478bd9Sstevel@tonic-gate 					} else {
1932*7c478bd9Sstevel@tonic-gate 						Table[j].bootid = 0;
1933*7c478bd9Sstevel@tonic-gate 					}
1934*7c478bd9Sstevel@tonic-gate 				}
1935*7c478bd9Sstevel@tonic-gate 			} else {
1936*7c478bd9Sstevel@tonic-gate 				Table[i].bootid = 0;
1937*7c478bd9Sstevel@tonic-gate 			}
1938*7c478bd9Sstevel@tonic-gate 
1939*7c478bd9Sstevel@tonic-gate 			/* set up the return code */
1940*7c478bd9Sstevel@tonic-gate 			i = 1;
1941*7c478bd9Sstevel@tonic-gate 		}
1942*7c478bd9Sstevel@tonic-gate 	} else {
1943*7c478bd9Sstevel@tonic-gate 		/*
1944*7c478bd9Sstevel@tonic-gate 		 * partitions of type EFI_PMBR must be the only partitions in
1945*7c478bd9Sstevel@tonic-gate 		 * the table
1946*7c478bd9Sstevel@tonic-gate 		 *
1947*7c478bd9Sstevel@tonic-gate 		 * First, make sure there were no errors the table is
1948*7c478bd9Sstevel@tonic-gate 		 * empty
1949*7c478bd9Sstevel@tonic-gate 		 */
1950*7c478bd9Sstevel@tonic-gate 		retCode = verify_tbl();
1951*7c478bd9Sstevel@tonic-gate 
1952*7c478bd9Sstevel@tonic-gate 		if (retCode < 0) {
1953*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
1954*7c478bd9Sstevel@tonic-gate 			    "fdisk: Cannot create EFI partition table; \n"
1955*7c478bd9Sstevel@tonic-gate 			    "current partition table is invalid.\n");
1956*7c478bd9Sstevel@tonic-gate 			return (-1);
1957*7c478bd9Sstevel@tonic-gate 		} else if (retCode > 0) {
1958*7c478bd9Sstevel@tonic-gate 			printf("An EFI partition must be the only partition on "
1959*7c478bd9Sstevel@tonic-gate 				"disk.  You may manually delete existing\n"
1960*7c478bd9Sstevel@tonic-gate 				"partitions, or fdisk can do it.\n");
1961*7c478bd9Sstevel@tonic-gate 			printf("Do you want fdisk to destroy existing "
1962*7c478bd9Sstevel@tonic-gate 				"partitions?\n");
1963*7c478bd9Sstevel@tonic-gate 			printf("Please type \"y\" or \"n\". ");
1964*7c478bd9Sstevel@tonic-gate 
1965*7c478bd9Sstevel@tonic-gate 			if (yesno()) {
1966*7c478bd9Sstevel@tonic-gate 				nulltbl();
1967*7c478bd9Sstevel@tonic-gate 			} else {
1968*7c478bd9Sstevel@tonic-gate 				return (-1);
1969*7c478bd9Sstevel@tonic-gate 			}
1970*7c478bd9Sstevel@tonic-gate 		}
1971*7c478bd9Sstevel@tonic-gate 
1972*7c478bd9Sstevel@tonic-gate 		/* create the table entry - i should be 0 */
1973*7c478bd9Sstevel@tonic-gate 		i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, rsect,
1974*7c478bd9Sstevel@tonic-gate 			(Numcyl * heads * sectors) - rsect);
1975*7c478bd9Sstevel@tonic-gate 
1976*7c478bd9Sstevel@tonic-gate 		if (i != 0) {
1977*7c478bd9Sstevel@tonic-gate 			printf("Error creating EFI partition!!!\n");
1978*7c478bd9Sstevel@tonic-gate 			i = -1;
1979*7c478bd9Sstevel@tonic-gate 		} else {
1980*7c478bd9Sstevel@tonic-gate 
1981*7c478bd9Sstevel@tonic-gate 			/* EFI partitions are currently never active */
1982*7c478bd9Sstevel@tonic-gate 			Table[i].bootid = 0;
1983*7c478bd9Sstevel@tonic-gate 
1984*7c478bd9Sstevel@tonic-gate 			/* set up the return code */
1985*7c478bd9Sstevel@tonic-gate 			i = 1;
1986*7c478bd9Sstevel@tonic-gate 		}
1987*7c478bd9Sstevel@tonic-gate 	}
1988*7c478bd9Sstevel@tonic-gate 
1989*7c478bd9Sstevel@tonic-gate 	return (i);
1990*7c478bd9Sstevel@tonic-gate }
1991*7c478bd9Sstevel@tonic-gate 
1992*7c478bd9Sstevel@tonic-gate /*
1993*7c478bd9Sstevel@tonic-gate  * specify
1994*7c478bd9Sstevel@tonic-gate  * Query the user to specify the size of the new partition in
1995*7c478bd9Sstevel@tonic-gate  * terms of percentage of the disk or by specifying the starting
1996*7c478bd9Sstevel@tonic-gate  * cylinder and length in cylinders.
1997*7c478bd9Sstevel@tonic-gate  */
1998*7c478bd9Sstevel@tonic-gate specify(tsystid)
1999*7c478bd9Sstevel@tonic-gate unsigned char	tsystid;
2000*7c478bd9Sstevel@tonic-gate {
2001*7c478bd9Sstevel@tonic-gate 	int	i, j,
2002*7c478bd9Sstevel@tonic-gate 		percent = -1;
2003*7c478bd9Sstevel@tonic-gate 	int	cyl, cylen, first_free, size_free;
2004*7c478bd9Sstevel@tonic-gate 	struct ipart *partition[FD_NUMPART];
2005*7c478bd9Sstevel@tonic-gate 
2006*7c478bd9Sstevel@tonic-gate 	printf(Q_LINE);
2007*7c478bd9Sstevel@tonic-gate 	printf("Specify the percentage of disk to use for this partition\n");
2008*7c478bd9Sstevel@tonic-gate 	printf("(or type \"c\" to specify the size in cylinders). ");
2009*7c478bd9Sstevel@tonic-gate 	gets(s);
2010*7c478bd9Sstevel@tonic-gate 	rm_blanks(s);
2011*7c478bd9Sstevel@tonic-gate 	if (s[0] != 'c') {	/* Specify size in percentage of disk */
2012*7c478bd9Sstevel@tonic-gate 	    i = 0;
2013*7c478bd9Sstevel@tonic-gate 	    while (s[i] != '\0') {
2014*7c478bd9Sstevel@tonic-gate 		if (s[i] < '0' || s[i] > '9') {
2015*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
2016*7c478bd9Sstevel@tonic-gate 		    printf("Invalid percentage value specified; retry"
2017*7c478bd9Sstevel@tonic-gate 			" the operation.");
2018*7c478bd9Sstevel@tonic-gate 		    return (-1);
2019*7c478bd9Sstevel@tonic-gate 		}
2020*7c478bd9Sstevel@tonic-gate 		i++;
2021*7c478bd9Sstevel@tonic-gate 		if (i > 3) {
2022*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
2023*7c478bd9Sstevel@tonic-gate 		    printf("Invalid percentage value specified; retry"
2024*7c478bd9Sstevel@tonic-gate 			" the operation.");
2025*7c478bd9Sstevel@tonic-gate 		    return (-1);
2026*7c478bd9Sstevel@tonic-gate 		}
2027*7c478bd9Sstevel@tonic-gate 	    }
2028*7c478bd9Sstevel@tonic-gate 	    if ((percent = atoi(s)) > 100) {
2029*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2030*7c478bd9Sstevel@tonic-gate 		printf("Percentage value is too large. The value must be"
2031*7c478bd9Sstevel@tonic-gate 		    " between 1 and 100;\nretry the operation.\n");
2032*7c478bd9Sstevel@tonic-gate 		return (-1);
2033*7c478bd9Sstevel@tonic-gate 	    }
2034*7c478bd9Sstevel@tonic-gate 	    if (percent < 1) {
2035*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2036*7c478bd9Sstevel@tonic-gate 		printf("Percentage value is too small. The value must be"
2037*7c478bd9Sstevel@tonic-gate 		    " between 1 and 100;\nretry the operation.\n");
2038*7c478bd9Sstevel@tonic-gate 		return (-1);
2039*7c478bd9Sstevel@tonic-gate 	    }
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate 	    cylen = (Numcyl * percent) / 100;
2042*7c478bd9Sstevel@tonic-gate 	    if ((percent < 100) && (((Numcyl * percent) % 10) > 5))
2043*7c478bd9Sstevel@tonic-gate 		cylen++;
2044*7c478bd9Sstevel@tonic-gate 
2045*7c478bd9Sstevel@tonic-gate 	    /* Verify that the DOS12 partition does not exceed the maximum */
2046*7c478bd9Sstevel@tonic-gate 	    /* size of 32MB. */
2047*7c478bd9Sstevel@tonic-gate 	    if ((tsystid == DOSOS12) && ((long)((long)cylen*heads*sectors) >
2048*7c478bd9Sstevel@tonic-gate 		MAXDOS)) {
2049*7c478bd9Sstevel@tonic-gate 		int n;
2050*7c478bd9Sstevel@tonic-gate 		n = (int)(MAXDOS*100/(int)(heads*sectors)/Numcyl);
2051*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2052*7c478bd9Sstevel@tonic-gate 		printf("Maximum size for a DOS partition is %d%%;"
2053*7c478bd9Sstevel@tonic-gate 		    " retry the operation.",
2054*7c478bd9Sstevel@tonic-gate 		    n <= 100 ? n : 100);
2055*7c478bd9Sstevel@tonic-gate 		return (-1);
2056*7c478bd9Sstevel@tonic-gate 	    }
2057*7c478bd9Sstevel@tonic-gate 
2058*7c478bd9Sstevel@tonic-gate 	    /* Before searching the partitions, sort them into sector order */
2059*7c478bd9Sstevel@tonic-gate 	    /* in the partition array, note that we only need to sort */
2060*7c478bd9Sstevel@tonic-gate 	    /* NUMPART-1 entries as at least the last one must be empty */
2061*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) partition[i] = &Table[i];
2062*7c478bd9Sstevel@tonic-gate 
2063*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART-2; i++) {
2064*7c478bd9Sstevel@tonic-gate 		if (partition[i]->systid == UNUSED) break;
2065*7c478bd9Sstevel@tonic-gate 		for (j = i+1; j < FD_NUMPART-1; j++) {
2066*7c478bd9Sstevel@tonic-gate 		    if (partition[j]->systid == UNUSED) break;
2067*7c478bd9Sstevel@tonic-gate 		    if (lel(partition[j]->relsect) <
2068*7c478bd9Sstevel@tonic-gate 				lel(partition[i]->relsect)) {
2069*7c478bd9Sstevel@tonic-gate 			struct ipart *temp = partition[i];
2070*7c478bd9Sstevel@tonic-gate 			partition[i] = partition[j];
2071*7c478bd9Sstevel@tonic-gate 			partition[j] = temp;
2072*7c478bd9Sstevel@tonic-gate 		    }
2073*7c478bd9Sstevel@tonic-gate 		}
2074*7c478bd9Sstevel@tonic-gate 	    }
2075*7c478bd9Sstevel@tonic-gate 
2076*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < FD_NUMPART; i++) {
2077*7c478bd9Sstevel@tonic-gate 		    int last_ent = 0;
2078*7c478bd9Sstevel@tonic-gate 
2079*7c478bd9Sstevel@tonic-gate 		    /* Find start of current check area */
2080*7c478bd9Sstevel@tonic-gate 		    if (i) { /* Not an empty table */
2081*7c478bd9Sstevel@tonic-gate 			    first_free = lel(partition[i-1]->relsect) +
2082*7c478bd9Sstevel@tonic-gate 				lel(partition[i-1]->numsect);
2083*7c478bd9Sstevel@tonic-gate 		    } else {
2084*7c478bd9Sstevel@tonic-gate 			    first_free = heads * sectors;
2085*7c478bd9Sstevel@tonic-gate 		    }
2086*7c478bd9Sstevel@tonic-gate 
2087*7c478bd9Sstevel@tonic-gate 		    /* Determine size of current check area */
2088*7c478bd9Sstevel@tonic-gate 		    if (partition[i]->systid == UNUSED) {
2089*7c478bd9Sstevel@tonic-gate 			    /* Special case hack for whole unused disk */
2090*7c478bd9Sstevel@tonic-gate 			    if (percent == 100 && i == 0)
2091*7c478bd9Sstevel@tonic-gate 				cylen--;
2092*7c478bd9Sstevel@tonic-gate 			    size_free = (Numcyl*heads*sectors) - first_free;
2093*7c478bd9Sstevel@tonic-gate 			    last_ent++;
2094*7c478bd9Sstevel@tonic-gate 		    } else {
2095*7c478bd9Sstevel@tonic-gate 			    if (i && ((lel(partition[i-1]->relsect) +
2096*7c478bd9Sstevel@tonic-gate 				lel(partition[i-1]->numsect)) !=
2097*7c478bd9Sstevel@tonic-gate 				lel(partition[i]->relsect))) {
2098*7c478bd9Sstevel@tonic-gate 				    /* There is a hole in table */
2099*7c478bd9Sstevel@tonic-gate 				    size_free = lel(partition[i]->relsect) -
2100*7c478bd9Sstevel@tonic-gate 					(lel(partition[i-1]->relsect) +
2101*7c478bd9Sstevel@tonic-gate 					lel(partition[i-1]->numsect));
2102*7c478bd9Sstevel@tonic-gate 			    } else if (i == 0) {
2103*7c478bd9Sstevel@tonic-gate 				    size_free = lel(partition[i]->relsect) -
2104*7c478bd9Sstevel@tonic-gate 					heads*sectors;
2105*7c478bd9Sstevel@tonic-gate 			    } else {
2106*7c478bd9Sstevel@tonic-gate 				    size_free = 0;
2107*7c478bd9Sstevel@tonic-gate 			    }
2108*7c478bd9Sstevel@tonic-gate 		    }
2109*7c478bd9Sstevel@tonic-gate 
2110*7c478bd9Sstevel@tonic-gate 		    if ((cylen*heads*sectors) <= size_free) {
2111*7c478bd9Sstevel@tonic-gate 			    /* We found a place to use */
2112*7c478bd9Sstevel@tonic-gate 			    break;
2113*7c478bd9Sstevel@tonic-gate 		    } else if (last_ent) {
2114*7c478bd9Sstevel@tonic-gate 			    size_free = 0;
2115*7c478bd9Sstevel@tonic-gate 			    break;
2116*7c478bd9Sstevel@tonic-gate 		    }
2117*7c478bd9Sstevel@tonic-gate 	    }
2118*7c478bd9Sstevel@tonic-gate 	    if (i < FD_NUMPART && size_free) {
2119*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
2120*7c478bd9Sstevel@tonic-gate 		    if ((i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0,
2121*7c478bd9Sstevel@tonic-gate 			first_free, cylen*heads*sectors)) < 0)  {
2122*7c478bd9Sstevel@tonic-gate 			    fprintf(stderr,
2123*7c478bd9Sstevel@tonic-gate 				"fdisk: Partition entry too big.\n");
2124*7c478bd9Sstevel@tonic-gate 			    return (-1);
2125*7c478bd9Sstevel@tonic-gate 		    }
2126*7c478bd9Sstevel@tonic-gate 	    } else {
2127*7c478bd9Sstevel@tonic-gate 		    printf(E_LINE);
2128*7c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "fdisk: Partition entry too big.\n");
2129*7c478bd9Sstevel@tonic-gate 		    i = -1;
2130*7c478bd9Sstevel@tonic-gate 	    }
2131*7c478bd9Sstevel@tonic-gate 	    return (i);
2132*7c478bd9Sstevel@tonic-gate 	} else {	/* Specifying size in cylinders */
2133*7c478bd9Sstevel@tonic-gate 
2134*7c478bd9Sstevel@tonic-gate 	    printf(E_LINE);
2135*7c478bd9Sstevel@tonic-gate 	    printf(Q_LINE);
2136*7c478bd9Sstevel@tonic-gate 	    printf("Enter starting cylinder number: ");
2137*7c478bd9Sstevel@tonic-gate 	    if ((cyl = getcyl()) == -1) {
2138*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2139*7c478bd9Sstevel@tonic-gate 		printf("Invalid number; retry the operation.");
2140*7c478bd9Sstevel@tonic-gate 		return (-1);
2141*7c478bd9Sstevel@tonic-gate 	    }
2142*7c478bd9Sstevel@tonic-gate 	    if (cyl == 0) {
2143*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2144*7c478bd9Sstevel@tonic-gate 		printf("New partition cannot start at cylinder 0.\n");
2145*7c478bd9Sstevel@tonic-gate 		return (-1);
2146*7c478bd9Sstevel@tonic-gate 	    }
2147*7c478bd9Sstevel@tonic-gate 	    if (cyl >= (unsigned int)Numcyl) {
2148*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2149*7c478bd9Sstevel@tonic-gate 		printf("Cylinder %d is out of bounds, the maximum is %d.\n",
2150*7c478bd9Sstevel@tonic-gate 		    cyl, Numcyl - 1);
2151*7c478bd9Sstevel@tonic-gate 		return (-1);
2152*7c478bd9Sstevel@tonic-gate 	    }
2153*7c478bd9Sstevel@tonic-gate 	    printf(Q_LINE);
2154*7c478bd9Sstevel@tonic-gate 	    printf("Enter partition size in cylinders: ");
2155*7c478bd9Sstevel@tonic-gate 	    if ((cylen = getcyl()) == -1) {
2156*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2157*7c478bd9Sstevel@tonic-gate 		printf("Invalid number, retry the operation.");
2158*7c478bd9Sstevel@tonic-gate 		return (-1);
2159*7c478bd9Sstevel@tonic-gate 	    }
2160*7c478bd9Sstevel@tonic-gate 
2161*7c478bd9Sstevel@tonic-gate 	    /* Verify that the DOS12 partition does not exceed the maximum */
2162*7c478bd9Sstevel@tonic-gate 	    /* size of 32MB. */
2163*7c478bd9Sstevel@tonic-gate 	    if ((tsystid == DOSOS12) &&
2164*7c478bd9Sstevel@tonic-gate 		((long)((long)cylen*heads*sectors) > MAXDOS)) {
2165*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2166*7c478bd9Sstevel@tonic-gate 		printf("Maximum size for a %s partition is %ld cylinders;"
2167*7c478bd9Sstevel@tonic-gate 		    "\nretry the operation.",
2168*7c478bd9Sstevel@tonic-gate 		    Dstr, MAXDOS/(int)(heads*sectors));
2169*7c478bd9Sstevel@tonic-gate 		return (-1);
2170*7c478bd9Sstevel@tonic-gate 	    }
2171*7c478bd9Sstevel@tonic-gate 
2172*7c478bd9Sstevel@tonic-gate 	    i = insert_tbl(tsystid, 0, 0, 0, 0, 0, 0, 0, cyl*heads*sectors,
2173*7c478bd9Sstevel@tonic-gate 		cylen*heads*sectors);
2174*7c478bd9Sstevel@tonic-gate 
2175*7c478bd9Sstevel@tonic-gate 	    if (verify_tbl() < 0) {
2176*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2177*7c478bd9Sstevel@tonic-gate 		printf("fdisk: Cannot create partition table\n");
2178*7c478bd9Sstevel@tonic-gate 		return (-1);
2179*7c478bd9Sstevel@tonic-gate 	    }
2180*7c478bd9Sstevel@tonic-gate 
2181*7c478bd9Sstevel@tonic-gate 	    return (i);
2182*7c478bd9Sstevel@tonic-gate 	}
2183*7c478bd9Sstevel@tonic-gate }
2184*7c478bd9Sstevel@tonic-gate 
2185*7c478bd9Sstevel@tonic-gate /*
2186*7c478bd9Sstevel@tonic-gate  * dispmenu
2187*7c478bd9Sstevel@tonic-gate  * Display command menu (interactive mode).
2188*7c478bd9Sstevel@tonic-gate  */
2189*7c478bd9Sstevel@tonic-gate dispmenu(file)
2190*7c478bd9Sstevel@tonic-gate char *file;
2191*7c478bd9Sstevel@tonic-gate {
2192*7c478bd9Sstevel@tonic-gate 	printf(M_LINE);
2193*7c478bd9Sstevel@tonic-gate 	printf("SELECT ONE OF THE FOLLOWING:\n");
2194*7c478bd9Sstevel@tonic-gate 	printf("   1. Create a partition\n");
2195*7c478bd9Sstevel@tonic-gate 	printf("   2. Specify the active partition\n");
2196*7c478bd9Sstevel@tonic-gate 	printf("   3. Delete a partition\n");
2197*7c478bd9Sstevel@tonic-gate 	printf("   4. Change between Solaris and Solaris2 Partition IDs\n");
2198*7c478bd9Sstevel@tonic-gate 	printf("   5. Exit (update disk configuration and exit)\n");
2199*7c478bd9Sstevel@tonic-gate 	printf("   6. Cancel (exit without updating disk configuration)\n");
2200*7c478bd9Sstevel@tonic-gate }
2201*7c478bd9Sstevel@tonic-gate 
2202*7c478bd9Sstevel@tonic-gate /*
2203*7c478bd9Sstevel@tonic-gate  * pchange
2204*7c478bd9Sstevel@tonic-gate  * Change the ACTIVE designation of a partition.
2205*7c478bd9Sstevel@tonic-gate  */
2206*7c478bd9Sstevel@tonic-gate pchange()
2207*7c478bd9Sstevel@tonic-gate {
2208*7c478bd9Sstevel@tonic-gate 	char s[80];
2209*7c478bd9Sstevel@tonic-gate 	int i, j;
2210*7c478bd9Sstevel@tonic-gate 
2211*7c478bd9Sstevel@tonic-gate 	while (1) {
2212*7c478bd9Sstevel@tonic-gate 		printf(Q_LINE);
2213*7c478bd9Sstevel@tonic-gate 			{
2214*7c478bd9Sstevel@tonic-gate 			printf("Specify the partition number to boot from"
2215*7c478bd9Sstevel@tonic-gate 			    " (or specify 0 for none): ");
2216*7c478bd9Sstevel@tonic-gate 			}
2217*7c478bd9Sstevel@tonic-gate 		gets(s);
2218*7c478bd9Sstevel@tonic-gate 		rm_blanks(s);
2219*7c478bd9Sstevel@tonic-gate 		if ((s[1] != 0) || (s[0] < '0') || (s[0] > '4')) {
2220*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
2221*7c478bd9Sstevel@tonic-gate 			printf("Invalid response, please specify a number"
2222*7c478bd9Sstevel@tonic-gate 			    " between 0 and 4.\n");
2223*7c478bd9Sstevel@tonic-gate 		} else {
2224*7c478bd9Sstevel@tonic-gate 			break;
2225*7c478bd9Sstevel@tonic-gate 		}
2226*7c478bd9Sstevel@tonic-gate 	}
2227*7c478bd9Sstevel@tonic-gate 	if (s[0] == '0') {	/* No active partitions */
2228*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < FD_NUMPART; i++) {
2229*7c478bd9Sstevel@tonic-gate 			if (Table[i].systid != UNUSED &&
2230*7c478bd9Sstevel@tonic-gate 			    Table[i].bootid == ACTIVE)
2231*7c478bd9Sstevel@tonic-gate 				Table[i].bootid = 0;
2232*7c478bd9Sstevel@tonic-gate 		}
2233*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2234*7c478bd9Sstevel@tonic-gate 			printf("No partition is currently marked as active.");
2235*7c478bd9Sstevel@tonic-gate 		return (0);
2236*7c478bd9Sstevel@tonic-gate 	} else {	/* User has selected a partition to be active */
2237*7c478bd9Sstevel@tonic-gate 		i = s[0] - '1';
2238*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
2239*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
2240*7c478bd9Sstevel@tonic-gate 			printf("Partition does not exist.");
2241*7c478bd9Sstevel@tonic-gate 			return (-1);
2242*7c478bd9Sstevel@tonic-gate 		}
2243*7c478bd9Sstevel@tonic-gate 		/* a DOS-DATA or EXT-DOS partition cannot be active */
2244*7c478bd9Sstevel@tonic-gate 		else if ((Table[i].systid == DOSDATA) ||
2245*7c478bd9Sstevel@tonic-gate 		    (Table[i].systid == EXTDOS) ||
2246*7c478bd9Sstevel@tonic-gate 		    (Table[i].systid == FDISK_EXTLBA)) {
2247*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
2248*7c478bd9Sstevel@tonic-gate 			printf("DOS-DATA, EXT_DOS and EXT_DOS_LBA partitions "
2249*7c478bd9Sstevel@tonic-gate 			    "cannot be made active.\n");
2250*7c478bd9Sstevel@tonic-gate 			printf("Select another partition.");
2251*7c478bd9Sstevel@tonic-gate 			return (-1);
2252*7c478bd9Sstevel@tonic-gate 		}
2253*7c478bd9Sstevel@tonic-gate 		Table[i].bootid = ACTIVE;
2254*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < FD_NUMPART; j++) {
2255*7c478bd9Sstevel@tonic-gate 			if (j != i)
2256*7c478bd9Sstevel@tonic-gate 			Table[j].bootid = 0;
2257*7c478bd9Sstevel@tonic-gate 		}
2258*7c478bd9Sstevel@tonic-gate 	}
2259*7c478bd9Sstevel@tonic-gate 	printf(E_LINE);
2260*7c478bd9Sstevel@tonic-gate 		{
2261*7c478bd9Sstevel@tonic-gate 		printf("Partition %d is now active. The system will start up"
2262*7c478bd9Sstevel@tonic-gate 		    " from this\n", i+1);
2263*7c478bd9Sstevel@tonic-gate 		printf("partition after the next reboot.");
2264*7c478bd9Sstevel@tonic-gate 		}
2265*7c478bd9Sstevel@tonic-gate 	return (1);
2266*7c478bd9Sstevel@tonic-gate }
2267*7c478bd9Sstevel@tonic-gate 
2268*7c478bd9Sstevel@tonic-gate /*
2269*7c478bd9Sstevel@tonic-gate  * Change between SOLARIS and SOLARIS2 partition id
2270*7c478bd9Sstevel@tonic-gate  */
2271*7c478bd9Sstevel@tonic-gate ppartid()
2272*7c478bd9Sstevel@tonic-gate {
2273*7c478bd9Sstevel@tonic-gate 	char	*p, s[80];
2274*7c478bd9Sstevel@tonic-gate 	int	i;
2275*7c478bd9Sstevel@tonic-gate 
2276*7c478bd9Sstevel@tonic-gate 	for (;;) {
2277*7c478bd9Sstevel@tonic-gate 		printf(Q_LINE);
2278*7c478bd9Sstevel@tonic-gate 		printf("Specify the partition number to change"
2279*7c478bd9Sstevel@tonic-gate 			" (or enter 0 to exit): ");
2280*7c478bd9Sstevel@tonic-gate 		fgets(s, sizeof (s), stdin);
2281*7c478bd9Sstevel@tonic-gate 		i = strtol(s, &p, 10);
2282*7c478bd9Sstevel@tonic-gate 
2283*7c478bd9Sstevel@tonic-gate 		if (*p != '\n' || i < 0 || i > FD_NUMPART) {
2284*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
2285*7c478bd9Sstevel@tonic-gate 			printf("Invalid response, retry the operation.\n");
2286*7c478bd9Sstevel@tonic-gate 			continue;
2287*7c478bd9Sstevel@tonic-gate 		}
2288*7c478bd9Sstevel@tonic-gate 
2289*7c478bd9Sstevel@tonic-gate 		if (i == 0) {
2290*7c478bd9Sstevel@tonic-gate 			/* exit delete command */
2291*7c478bd9Sstevel@tonic-gate 			printf(E_LINE); /* clear error message */
2292*7c478bd9Sstevel@tonic-gate 			return (1);
2293*7c478bd9Sstevel@tonic-gate 		}
2294*7c478bd9Sstevel@tonic-gate 
2295*7c478bd9Sstevel@tonic-gate 		i -= 1;
2296*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS) {
2297*7c478bd9Sstevel@tonic-gate 			Table[i].systid = SUNIXOS2;
2298*7c478bd9Sstevel@tonic-gate 		} else if (Table[i].systid == SUNIXOS2) {
2299*7c478bd9Sstevel@tonic-gate 			Table[i].systid = SUNIXOS;
2300*7c478bd9Sstevel@tonic-gate 		} else {
2301*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
2302*7c478bd9Sstevel@tonic-gate 			printf("Partition %d is not a Solaris partition.",
2303*7c478bd9Sstevel@tonic-gate 			    i + 1);
2304*7c478bd9Sstevel@tonic-gate 			continue;
2305*7c478bd9Sstevel@tonic-gate 		}
2306*7c478bd9Sstevel@tonic-gate 
2307*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2308*7c478bd9Sstevel@tonic-gate 		printf("Partition %d has been changed.", i + 1);
2309*7c478bd9Sstevel@tonic-gate 		return (1);
2310*7c478bd9Sstevel@tonic-gate 	}
2311*7c478bd9Sstevel@tonic-gate }
2312*7c478bd9Sstevel@tonic-gate 
2313*7c478bd9Sstevel@tonic-gate /*
2314*7c478bd9Sstevel@tonic-gate  * pdelete
2315*7c478bd9Sstevel@tonic-gate  * Remove partition entry from the table (interactive mode).
2316*7c478bd9Sstevel@tonic-gate  */
2317*7c478bd9Sstevel@tonic-gate pdelete()
2318*7c478bd9Sstevel@tonic-gate {
2319*7c478bd9Sstevel@tonic-gate 	char s[80];
2320*7c478bd9Sstevel@tonic-gate 	int i, j;
2321*7c478bd9Sstevel@tonic-gate 	char pactive;
2322*7c478bd9Sstevel@tonic-gate 
2323*7c478bd9Sstevel@tonic-gate DEL1:	printf(Q_LINE);
2324*7c478bd9Sstevel@tonic-gate 	printf("Specify the partition number to delete"
2325*7c478bd9Sstevel@tonic-gate 	    " (or enter 0 to exit): ");
2326*7c478bd9Sstevel@tonic-gate 	gets(s);
2327*7c478bd9Sstevel@tonic-gate 	rm_blanks(s);
2328*7c478bd9Sstevel@tonic-gate 	if ((s[0] == '0')) {	/* exit delete command */
2329*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);	/* clear error message */
2330*7c478bd9Sstevel@tonic-gate 		return (1);
2331*7c478bd9Sstevel@tonic-gate 	}
2332*7c478bd9Sstevel@tonic-gate 	/* Accept only a single digit between 1 and 4 */
2333*7c478bd9Sstevel@tonic-gate 	if (s[1] != 0 || (i = atoi(s)) < 1 || i > FD_NUMPART) {
2334*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2335*7c478bd9Sstevel@tonic-gate 		printf("Invalid response, retry the operation.\n");
2336*7c478bd9Sstevel@tonic-gate 		goto DEL1;
2337*7c478bd9Sstevel@tonic-gate 	} else {		/* Found a digit between 1 and 4 */
2338*7c478bd9Sstevel@tonic-gate 		--i;	/* Structure begins with element 0 */
2339*7c478bd9Sstevel@tonic-gate 	}
2340*7c478bd9Sstevel@tonic-gate 
2341*7c478bd9Sstevel@tonic-gate 	if (Table[i].systid == UNUSED) {
2342*7c478bd9Sstevel@tonic-gate 		printf(E_LINE);
2343*7c478bd9Sstevel@tonic-gate 		printf("Partition %d does not exist.", i+1);
2344*7c478bd9Sstevel@tonic-gate 		return (-1);
2345*7c478bd9Sstevel@tonic-gate 	}
2346*7c478bd9Sstevel@tonic-gate 
2347*7c478bd9Sstevel@tonic-gate 	printf(Q_LINE);
2348*7c478bd9Sstevel@tonic-gate 	printf("Are you sure you want to delete partition %d?"
2349*7c478bd9Sstevel@tonic-gate 	    " This will make all files and \n", i+1);
2350*7c478bd9Sstevel@tonic-gate 	printf("programs in this partition inaccessible (type"
2351*7c478bd9Sstevel@tonic-gate 	    " \"y\" or \"n\"). ");
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate 	printf(E_LINE);
2354*7c478bd9Sstevel@tonic-gate 	if (! yesno()) {
2355*7c478bd9Sstevel@tonic-gate 		return (1);
2356*7c478bd9Sstevel@tonic-gate 	}
2357*7c478bd9Sstevel@tonic-gate 
2358*7c478bd9Sstevel@tonic-gate 	if (Table[i].bootid == ACTIVE) {
2359*7c478bd9Sstevel@tonic-gate 		pactive = 1;
2360*7c478bd9Sstevel@tonic-gate 	} else {
2361*7c478bd9Sstevel@tonic-gate 		pactive = 0;
2362*7c478bd9Sstevel@tonic-gate 	}
2363*7c478bd9Sstevel@tonic-gate 
2364*7c478bd9Sstevel@tonic-gate 	for (j = i; j < FD_NUMPART - 1; j++) {
2365*7c478bd9Sstevel@tonic-gate 	    Table[j] = Table[j+1];
2366*7c478bd9Sstevel@tonic-gate 	}
2367*7c478bd9Sstevel@tonic-gate 
2368*7c478bd9Sstevel@tonic-gate 	Table[j].systid = UNUSED;
2369*7c478bd9Sstevel@tonic-gate 	Table[j].numsect = 0;
2370*7c478bd9Sstevel@tonic-gate 	Table[j].relsect = 0;
2371*7c478bd9Sstevel@tonic-gate 	Table[j].bootid = 0;
2372*7c478bd9Sstevel@tonic-gate 	printf(E_LINE);
2373*7c478bd9Sstevel@tonic-gate 	printf("Partition %d has been deleted.", i+1);
2374*7c478bd9Sstevel@tonic-gate 
2375*7c478bd9Sstevel@tonic-gate 	if (pactive) {
2376*7c478bd9Sstevel@tonic-gate 	    printf(" This was the active partition.");
2377*7c478bd9Sstevel@tonic-gate 	}
2378*7c478bd9Sstevel@tonic-gate 
2379*7c478bd9Sstevel@tonic-gate 	return (1);
2380*7c478bd9Sstevel@tonic-gate }
2381*7c478bd9Sstevel@tonic-gate 
2382*7c478bd9Sstevel@tonic-gate /*
2383*7c478bd9Sstevel@tonic-gate  * rm_blanks
2384*7c478bd9Sstevel@tonic-gate  * Remove blanks from strings of user responses.
2385*7c478bd9Sstevel@tonic-gate  */
2386*7c478bd9Sstevel@tonic-gate rm_blanks(s)
2387*7c478bd9Sstevel@tonic-gate char *s;
2388*7c478bd9Sstevel@tonic-gate {
2389*7c478bd9Sstevel@tonic-gate 	register int i, j;
2390*7c478bd9Sstevel@tonic-gate 
2391*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < CBUFLEN; i++) {
2392*7c478bd9Sstevel@tonic-gate 		if ((s[i] == ' ') || (s[i] == '\t'))
2393*7c478bd9Sstevel@tonic-gate 			continue;
2394*7c478bd9Sstevel@tonic-gate 		else
2395*7c478bd9Sstevel@tonic-gate 			/* Found first non-blank character of the string */
2396*7c478bd9Sstevel@tonic-gate 			break;
2397*7c478bd9Sstevel@tonic-gate 	}
2398*7c478bd9Sstevel@tonic-gate 	for (j = 0; i < CBUFLEN; j++, i++) {
2399*7c478bd9Sstevel@tonic-gate 		if ((s[j] = s[i]) == '\0') {
2400*7c478bd9Sstevel@tonic-gate 			/* Reached end of string */
2401*7c478bd9Sstevel@tonic-gate 			return;
2402*7c478bd9Sstevel@tonic-gate 		}
2403*7c478bd9Sstevel@tonic-gate 	}
2404*7c478bd9Sstevel@tonic-gate }
2405*7c478bd9Sstevel@tonic-gate 
2406*7c478bd9Sstevel@tonic-gate /*
2407*7c478bd9Sstevel@tonic-gate  * getcyl
2408*7c478bd9Sstevel@tonic-gate  * Take the user-specified cylinder number and convert it from a
2409*7c478bd9Sstevel@tonic-gate  * string to a decimal value.
2410*7c478bd9Sstevel@tonic-gate  */
2411*7c478bd9Sstevel@tonic-gate getcyl()
2412*7c478bd9Sstevel@tonic-gate {
2413*7c478bd9Sstevel@tonic-gate int slen, i, j;
2414*7c478bd9Sstevel@tonic-gate unsigned int cyl;
2415*7c478bd9Sstevel@tonic-gate 	gets(s);
2416*7c478bd9Sstevel@tonic-gate 	rm_blanks(s);
2417*7c478bd9Sstevel@tonic-gate 	slen = strlen(s);
2418*7c478bd9Sstevel@tonic-gate 	j = 1;
2419*7c478bd9Sstevel@tonic-gate 	cyl = 0;
2420*7c478bd9Sstevel@tonic-gate 	for (i = slen-1; i >= 0; i--) {
2421*7c478bd9Sstevel@tonic-gate 		if (s[i] < '0' || s[i] > '9') {
2422*7c478bd9Sstevel@tonic-gate 			return (-1);
2423*7c478bd9Sstevel@tonic-gate 		}
2424*7c478bd9Sstevel@tonic-gate 		cyl += (j*(s[i]-'0'));
2425*7c478bd9Sstevel@tonic-gate 		j *= 10;
2426*7c478bd9Sstevel@tonic-gate 	}
2427*7c478bd9Sstevel@tonic-gate 	return (cyl);
2428*7c478bd9Sstevel@tonic-gate }
2429*7c478bd9Sstevel@tonic-gate 
2430*7c478bd9Sstevel@tonic-gate /*
2431*7c478bd9Sstevel@tonic-gate  * disptbl
2432*7c478bd9Sstevel@tonic-gate  * Display the current fdisk table; determine percentage
2433*7c478bd9Sstevel@tonic-gate  * of the disk used for each partition.
2434*7c478bd9Sstevel@tonic-gate  */
2435*7c478bd9Sstevel@tonic-gate disptbl()
2436*7c478bd9Sstevel@tonic-gate {
2437*7c478bd9Sstevel@tonic-gate 	int i;
2438*7c478bd9Sstevel@tonic-gate 	unsigned int startcyl, endcyl, length, percent, remainder;
2439*7c478bd9Sstevel@tonic-gate 	char *stat, *type;
2440*7c478bd9Sstevel@tonic-gate 	unsigned char *t;
2441*7c478bd9Sstevel@tonic-gate 
2442*7c478bd9Sstevel@tonic-gate 	if ((heads == 0) || (sectors == 0)) {
2443*7c478bd9Sstevel@tonic-gate 		printf("WARNING: critical disk geometry information"
2444*7c478bd9Sstevel@tonic-gate 			" missing!\n");
2445*7c478bd9Sstevel@tonic-gate 		printf("\theads = %d, sectors = %d\n", heads, sectors);
2446*7c478bd9Sstevel@tonic-gate 		exit(1);
2447*7c478bd9Sstevel@tonic-gate 	}
2448*7c478bd9Sstevel@tonic-gate 
2449*7c478bd9Sstevel@tonic-gate 	printf(HOME);
2450*7c478bd9Sstevel@tonic-gate 	printf(T_LINE);
2451*7c478bd9Sstevel@tonic-gate 	printf("             Total disk size is %d cylinders\n", Numcyl);
2452*7c478bd9Sstevel@tonic-gate 	printf("             Cylinder size is %d (512 byte) blocks\n\n",
2453*7c478bd9Sstevel@tonic-gate 	    heads*sectors);
2454*7c478bd9Sstevel@tonic-gate 	printf("                                               Cylinders\n");
2455*7c478bd9Sstevel@tonic-gate 	printf("      Partition   Status    Type          Start   End   Length"
2456*7c478bd9Sstevel@tonic-gate 	    "    %%\n");
2457*7c478bd9Sstevel@tonic-gate 	printf("      =========   ======    ============  =====   ===   ======"
2458*7c478bd9Sstevel@tonic-gate 	    "   ===");
2459*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2460*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == UNUSED) {
2461*7c478bd9Sstevel@tonic-gate 			printf("\n");
2462*7c478bd9Sstevel@tonic-gate 			printf(CLR_LIN);
2463*7c478bd9Sstevel@tonic-gate 			continue;
2464*7c478bd9Sstevel@tonic-gate 		}
2465*7c478bd9Sstevel@tonic-gate 		if (Table[i].bootid == ACTIVE)
2466*7c478bd9Sstevel@tonic-gate 		    stat = Actvstr;
2467*7c478bd9Sstevel@tonic-gate 		else
2468*7c478bd9Sstevel@tonic-gate 		    stat = NAstr;
2469*7c478bd9Sstevel@tonic-gate 		switch (Table[i].systid) {
2470*7c478bd9Sstevel@tonic-gate 		case UNIXOS:
2471*7c478bd9Sstevel@tonic-gate 		    type = Ustr;
2472*7c478bd9Sstevel@tonic-gate 		    break;
2473*7c478bd9Sstevel@tonic-gate 		case SUNIXOS:
2474*7c478bd9Sstevel@tonic-gate 		    type = SUstr;
2475*7c478bd9Sstevel@tonic-gate 		    break;
2476*7c478bd9Sstevel@tonic-gate 		case SUNIXOS2:
2477*7c478bd9Sstevel@tonic-gate 		    type = SU2str;
2478*7c478bd9Sstevel@tonic-gate 		    break;
2479*7c478bd9Sstevel@tonic-gate 		case X86BOOT:
2480*7c478bd9Sstevel@tonic-gate 		    type = X86str;
2481*7c478bd9Sstevel@tonic-gate 		    break;
2482*7c478bd9Sstevel@tonic-gate 		case DOSOS12:
2483*7c478bd9Sstevel@tonic-gate 		    type = Dstr;
2484*7c478bd9Sstevel@tonic-gate 		    break;
2485*7c478bd9Sstevel@tonic-gate 		case DOSOS16:
2486*7c478bd9Sstevel@tonic-gate 		    type = D16str;
2487*7c478bd9Sstevel@tonic-gate 		    break;
2488*7c478bd9Sstevel@tonic-gate 		case EXTDOS:
2489*7c478bd9Sstevel@tonic-gate 		    type = EDstr;
2490*7c478bd9Sstevel@tonic-gate 		    break;
2491*7c478bd9Sstevel@tonic-gate 		case DOSDATA:
2492*7c478bd9Sstevel@tonic-gate 		    type = DDstr;
2493*7c478bd9Sstevel@tonic-gate 		    break;
2494*7c478bd9Sstevel@tonic-gate 		case DOSHUGE:
2495*7c478bd9Sstevel@tonic-gate 		    type = DBstr;
2496*7c478bd9Sstevel@tonic-gate 		    break;
2497*7c478bd9Sstevel@tonic-gate 		case PCIXOS:
2498*7c478bd9Sstevel@tonic-gate 		    type = PCstr;
2499*7c478bd9Sstevel@tonic-gate 		    break;
2500*7c478bd9Sstevel@tonic-gate 		case DIAGPART:
2501*7c478bd9Sstevel@tonic-gate 		    type = DIAGstr;
2502*7c478bd9Sstevel@tonic-gate 		    break;
2503*7c478bd9Sstevel@tonic-gate 		case FDISK_IFS:
2504*7c478bd9Sstevel@tonic-gate 		    type = IFSstr;
2505*7c478bd9Sstevel@tonic-gate 		    break;
2506*7c478bd9Sstevel@tonic-gate 		case FDISK_AIXBOOT:
2507*7c478bd9Sstevel@tonic-gate 		    type = AIXstr;
2508*7c478bd9Sstevel@tonic-gate 		    break;
2509*7c478bd9Sstevel@tonic-gate 		case FDISK_AIXDATA:
2510*7c478bd9Sstevel@tonic-gate 		    type = AIXDstr;
2511*7c478bd9Sstevel@tonic-gate 		    break;
2512*7c478bd9Sstevel@tonic-gate 		case FDISK_OS2BOOT:
2513*7c478bd9Sstevel@tonic-gate 		    type = OS2str;
2514*7c478bd9Sstevel@tonic-gate 		    break;
2515*7c478bd9Sstevel@tonic-gate 		case FDISK_WINDOWS:
2516*7c478bd9Sstevel@tonic-gate 		    type = WINstr;
2517*7c478bd9Sstevel@tonic-gate 		    break;
2518*7c478bd9Sstevel@tonic-gate 		case FDISK_EXT_WIN:
2519*7c478bd9Sstevel@tonic-gate 		    type = EWINstr;
2520*7c478bd9Sstevel@tonic-gate 		    break;
2521*7c478bd9Sstevel@tonic-gate 		case FDISK_FAT95:
2522*7c478bd9Sstevel@tonic-gate 		    type = FAT95str;
2523*7c478bd9Sstevel@tonic-gate 		    break;
2524*7c478bd9Sstevel@tonic-gate 		case FDISK_EXTLBA:
2525*7c478bd9Sstevel@tonic-gate 		    type = EXTLstr;
2526*7c478bd9Sstevel@tonic-gate 		    break;
2527*7c478bd9Sstevel@tonic-gate 		case FDISK_LINUX:
2528*7c478bd9Sstevel@tonic-gate 		    type = LINUXstr;
2529*7c478bd9Sstevel@tonic-gate 		    break;
2530*7c478bd9Sstevel@tonic-gate 		case FDISK_CPM:
2531*7c478bd9Sstevel@tonic-gate 		    type = CPMstr;
2532*7c478bd9Sstevel@tonic-gate 		    break;
2533*7c478bd9Sstevel@tonic-gate 		case FDISK_NOVELL3:
2534*7c478bd9Sstevel@tonic-gate 		    type = NOVstr;
2535*7c478bd9Sstevel@tonic-gate 		    break;
2536*7c478bd9Sstevel@tonic-gate 		case FDISK_QNX4:
2537*7c478bd9Sstevel@tonic-gate 		    type = QNXstr;
2538*7c478bd9Sstevel@tonic-gate 		    break;
2539*7c478bd9Sstevel@tonic-gate 		case FDISK_QNX42:
2540*7c478bd9Sstevel@tonic-gate 		    type = QNX2str;
2541*7c478bd9Sstevel@tonic-gate 		    break;
2542*7c478bd9Sstevel@tonic-gate 		case FDISK_QNX43:
2543*7c478bd9Sstevel@tonic-gate 		    type = QNX3str;
2544*7c478bd9Sstevel@tonic-gate 		    break;
2545*7c478bd9Sstevel@tonic-gate 		case FDISK_LINUXNAT:
2546*7c478bd9Sstevel@tonic-gate 		    type = LINNATstr;
2547*7c478bd9Sstevel@tonic-gate 		    break;
2548*7c478bd9Sstevel@tonic-gate 		case FDISK_NTFSVOL1:
2549*7c478bd9Sstevel@tonic-gate 		    type = NTFSVOL1str;
2550*7c478bd9Sstevel@tonic-gate 		    break;
2551*7c478bd9Sstevel@tonic-gate 		case FDISK_NTFSVOL2:
2552*7c478bd9Sstevel@tonic-gate 		    type = NTFSVOL2str;
2553*7c478bd9Sstevel@tonic-gate 		    break;
2554*7c478bd9Sstevel@tonic-gate 		case FDISK_BSD:
2555*7c478bd9Sstevel@tonic-gate 		    type = BSDstr;
2556*7c478bd9Sstevel@tonic-gate 		    break;
2557*7c478bd9Sstevel@tonic-gate 		case FDISK_NEXTSTEP:
2558*7c478bd9Sstevel@tonic-gate 		    type = NEXTSTEPstr;
2559*7c478bd9Sstevel@tonic-gate 		    break;
2560*7c478bd9Sstevel@tonic-gate 		case FDISK_BSDIFS:
2561*7c478bd9Sstevel@tonic-gate 		    type = BSDIFSstr;
2562*7c478bd9Sstevel@tonic-gate 		    break;
2563*7c478bd9Sstevel@tonic-gate 		case FDISK_BSDISWAP:
2564*7c478bd9Sstevel@tonic-gate 		    type = BSDISWAPstr;
2565*7c478bd9Sstevel@tonic-gate 		    break;
2566*7c478bd9Sstevel@tonic-gate 		case EFI_PMBR:
2567*7c478bd9Sstevel@tonic-gate 		    type = EFIstr;
2568*7c478bd9Sstevel@tonic-gate 		    break;
2569*7c478bd9Sstevel@tonic-gate 		default:
2570*7c478bd9Sstevel@tonic-gate 		    type = Ostr;
2571*7c478bd9Sstevel@tonic-gate 		    break;
2572*7c478bd9Sstevel@tonic-gate 		}
2573*7c478bd9Sstevel@tonic-gate 		t = &Table[i].bootid;
2574*7c478bd9Sstevel@tonic-gate 		startcyl = lel(Table[i].relsect)/(heads*sectors);
2575*7c478bd9Sstevel@tonic-gate 		length = lel(Table[i].numsect) / (long)(heads * sectors);
2576*7c478bd9Sstevel@tonic-gate 		if (lel(Table[i].numsect) % (long)(heads * sectors))
2577*7c478bd9Sstevel@tonic-gate 			length++;
2578*7c478bd9Sstevel@tonic-gate 		endcyl = startcyl + length - 1;
2579*7c478bd9Sstevel@tonic-gate 		percent = length * 100 / Numcyl;
2580*7c478bd9Sstevel@tonic-gate 		if ((remainder = (length*100 % Numcyl)) != 0) {
2581*7c478bd9Sstevel@tonic-gate 			if ((remainder * 100 / Numcyl) > 50) {
2582*7c478bd9Sstevel@tonic-gate 				/* round up */
2583*7c478bd9Sstevel@tonic-gate 				percent++;
2584*7c478bd9Sstevel@tonic-gate 			}
2585*7c478bd9Sstevel@tonic-gate 			/* Else leave the percent as is since it's already */
2586*7c478bd9Sstevel@tonic-gate 			/* rounded down */
2587*7c478bd9Sstevel@tonic-gate 		}
2588*7c478bd9Sstevel@tonic-gate 		if (percent > 100)
2589*7c478bd9Sstevel@tonic-gate 			percent = 100;
2590*7c478bd9Sstevel@tonic-gate 		printf("\n          %d       %s    %-12.12s   %4d  %4d    %4d"
2591*7c478bd9Sstevel@tonic-gate 		    "    %3d", i+1, stat, type, startcyl, endcyl, length,
2592*7c478bd9Sstevel@tonic-gate 			percent);
2593*7c478bd9Sstevel@tonic-gate 	}
2594*7c478bd9Sstevel@tonic-gate 	/* Print warning message if table is empty */
2595*7c478bd9Sstevel@tonic-gate 	if (Table[0].systid == UNUSED) {
2596*7c478bd9Sstevel@tonic-gate 		printf(W_LINE);
2597*7c478bd9Sstevel@tonic-gate 		printf("WARNING: no partitions are defined!");
2598*7c478bd9Sstevel@tonic-gate 	} else {
2599*7c478bd9Sstevel@tonic-gate 		/* Clear the warning line */
2600*7c478bd9Sstevel@tonic-gate 		printf(W_LINE);
2601*7c478bd9Sstevel@tonic-gate 	}
2602*7c478bd9Sstevel@tonic-gate }
2603*7c478bd9Sstevel@tonic-gate 
2604*7c478bd9Sstevel@tonic-gate /*
2605*7c478bd9Sstevel@tonic-gate  * print_Table
2606*7c478bd9Sstevel@tonic-gate  * Write the detailed fdisk table to standard error for
2607*7c478bd9Sstevel@tonic-gate  * the selected disk device.
2608*7c478bd9Sstevel@tonic-gate  */
2609*7c478bd9Sstevel@tonic-gate print_Table() {
2610*7c478bd9Sstevel@tonic-gate 	int i;
2611*7c478bd9Sstevel@tonic-gate 
2612*7c478bd9Sstevel@tonic-gate 	fprintf(stderr,
2613*7c478bd9Sstevel@tonic-gate 	    "  SYSID ACT BHEAD BSECT BEGCYL   EHEAD ESECT ENDCYL   RELSECT"
2614*7c478bd9Sstevel@tonic-gate 	    "   NUMSECT\n");
2615*7c478bd9Sstevel@tonic-gate 
2616*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2617*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "  %-5d ", Table[i].systid);
2618*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-3d ", Table[i].bootid);
2619*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-5d ", Table[i].beghead);
2620*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-5d ", Table[i].begsect & 0x3f);
2621*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-8d ", (((uint_t)Table[i].begsect &
2622*7c478bd9Sstevel@tonic-gate 			0xc0) << 2) + Table[i].begcyl);
2623*7c478bd9Sstevel@tonic-gate 
2624*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-5d ", Table[i].endhead);
2625*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-5d ", Table[i].endsect & 0x3f);
2626*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-8d ", (((uint_t)Table[i].endsect &
2627*7c478bd9Sstevel@tonic-gate 			0xc0) << 2) + Table[i].endcyl);
2628*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-9d ", lel(Table[i].relsect));
2629*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "%-9d\n", lel(Table[i].numsect));
2630*7c478bd9Sstevel@tonic-gate 
2631*7c478bd9Sstevel@tonic-gate 	}
2632*7c478bd9Sstevel@tonic-gate }
2633*7c478bd9Sstevel@tonic-gate 
2634*7c478bd9Sstevel@tonic-gate /*
2635*7c478bd9Sstevel@tonic-gate  * copy_Table_to_Old_Table
2636*7c478bd9Sstevel@tonic-gate  * Copy Table into Old_Table. The function only copies the systid,
2637*7c478bd9Sstevel@tonic-gate  * numsect, relsect, and bootid values because they are the only
2638*7c478bd9Sstevel@tonic-gate  * ones compared when determining if Table has changed.
2639*7c478bd9Sstevel@tonic-gate  */
2640*7c478bd9Sstevel@tonic-gate copy_Table_to_Old_Table()
2641*7c478bd9Sstevel@tonic-gate {
2642*7c478bd9Sstevel@tonic-gate 	int i;
2643*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
2644*7c478bd9Sstevel@tonic-gate 	    memcpy(&Old_Table[i], &Table[i], sizeof (Table[0]));
2645*7c478bd9Sstevel@tonic-gate 	}
2646*7c478bd9Sstevel@tonic-gate }
2647*7c478bd9Sstevel@tonic-gate 
2648*7c478bd9Sstevel@tonic-gate /*
2649*7c478bd9Sstevel@tonic-gate  * nulltbl
2650*7c478bd9Sstevel@tonic-gate  * Zero out the systid, numsect, relsect, and bootid values in the
2651*7c478bd9Sstevel@tonic-gate  * fdisk table.
2652*7c478bd9Sstevel@tonic-gate  */
2653*7c478bd9Sstevel@tonic-gate nulltbl()
2654*7c478bd9Sstevel@tonic-gate {
2655*7c478bd9Sstevel@tonic-gate 	int i;
2656*7c478bd9Sstevel@tonic-gate 
2657*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++)  {
2658*7c478bd9Sstevel@tonic-gate 	    Table[i].systid = UNUSED;
2659*7c478bd9Sstevel@tonic-gate 	    Table[i].numsect = lel(UNUSED);
2660*7c478bd9Sstevel@tonic-gate 	    Table[i].relsect = lel(UNUSED);
2661*7c478bd9Sstevel@tonic-gate 	    Table[i].bootid = 0;
2662*7c478bd9Sstevel@tonic-gate 	}
2663*7c478bd9Sstevel@tonic-gate }
2664*7c478bd9Sstevel@tonic-gate 
2665*7c478bd9Sstevel@tonic-gate /*
2666*7c478bd9Sstevel@tonic-gate  * copy_Bootblk_to_Table
2667*7c478bd9Sstevel@tonic-gate  * Copy the bytes from the boot record to an internal "Table".
2668*7c478bd9Sstevel@tonic-gate  * All unused are padded with zeros starting at offset 446.
2669*7c478bd9Sstevel@tonic-gate  */
2670*7c478bd9Sstevel@tonic-gate copy_Bootblk_to_Table()
2671*7c478bd9Sstevel@tonic-gate {
2672*7c478bd9Sstevel@tonic-gate 	int i, j;
2673*7c478bd9Sstevel@tonic-gate 	char *bootptr;
2674*7c478bd9Sstevel@tonic-gate 	unsigned char *tbl_ptr;
2675*7c478bd9Sstevel@tonic-gate 	int tblpos;
2676*7c478bd9Sstevel@tonic-gate 	void fill_ipart(char *, struct ipart *);
2677*7c478bd9Sstevel@tonic-gate 	struct ipart iparts[FD_NUMPART];
2678*7c478bd9Sstevel@tonic-gate 
2679*7c478bd9Sstevel@tonic-gate 	/* Get an aligned copy of the partition tables */
2680*7c478bd9Sstevel@tonic-gate 	memcpy(iparts, Bootblk->parts, sizeof (iparts));
2681*7c478bd9Sstevel@tonic-gate 	tbl_ptr = &Table[0].bootid;
2682*7c478bd9Sstevel@tonic-gate 	bootptr = (char *)iparts;	/* Points to start of partition table */
2683*7c478bd9Sstevel@tonic-gate 	if (les(Bootblk->signature) != MBB_MAGIC)  {
2684*7c478bd9Sstevel@tonic-gate 		/* Signature is missing */
2685*7c478bd9Sstevel@tonic-gate 		nulltbl();
2686*7c478bd9Sstevel@tonic-gate 		memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
2687*7c478bd9Sstevel@tonic-gate 		return;
2688*7c478bd9Sstevel@tonic-gate 	}
2689*7c478bd9Sstevel@tonic-gate 	/*
2690*7c478bd9Sstevel@tonic-gate 	 * When the DOS fdisk command deletes a partition, it is not
2691*7c478bd9Sstevel@tonic-gate 	 * recognized by the old algorithm.  The algorithm that
2692*7c478bd9Sstevel@tonic-gate 	 * follows looks at each entry in the Bootrec and copies all
2693*7c478bd9Sstevel@tonic-gate 	 * those that are valid.
2694*7c478bd9Sstevel@tonic-gate 	 */
2695*7c478bd9Sstevel@tonic-gate 	j = 0;
2696*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2697*7c478bd9Sstevel@tonic-gate 		if (iparts[i].systid == 0) {
2698*7c478bd9Sstevel@tonic-gate 			/* Null entry */
2699*7c478bd9Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
2700*7c478bd9Sstevel@tonic-gate 		} else {
2701*7c478bd9Sstevel@tonic-gate 			(void) fill_ipart(bootptr, &Table[j]);
2702*7c478bd9Sstevel@tonic-gate 			j++;
2703*7c478bd9Sstevel@tonic-gate 			bootptr += sizeof (struct ipart);
2704*7c478bd9Sstevel@tonic-gate 		}
2705*7c478bd9Sstevel@tonic-gate 	}
2706*7c478bd9Sstevel@tonic-gate 	for (i = j; i < FD_NUMPART; i++) {
2707*7c478bd9Sstevel@tonic-gate 		Table[i].systid = UNUSED;
2708*7c478bd9Sstevel@tonic-gate 		Table[i].numsect = lel(UNUSED);
2709*7c478bd9Sstevel@tonic-gate 		Table[i].relsect = lel(UNUSED);
2710*7c478bd9Sstevel@tonic-gate 		Table[i].bootid = 0;
2711*7c478bd9Sstevel@tonic-gate 
2712*7c478bd9Sstevel@tonic-gate 	}
2713*7c478bd9Sstevel@tonic-gate 	/* For now, always replace the bootcode with ours */
2714*7c478bd9Sstevel@tonic-gate 	memcpy(Bootblk->bootinst, &BootCod, BOOTSZ);
2715*7c478bd9Sstevel@tonic-gate 	copy_Table_to_Bootblk();
2716*7c478bd9Sstevel@tonic-gate }
2717*7c478bd9Sstevel@tonic-gate 
2718*7c478bd9Sstevel@tonic-gate /*
2719*7c478bd9Sstevel@tonic-gate  * fill_ipart
2720*7c478bd9Sstevel@tonic-gate  * Initialize ipart structure values.
2721*7c478bd9Sstevel@tonic-gate  */
2722*7c478bd9Sstevel@tonic-gate void
2723*7c478bd9Sstevel@tonic-gate fill_ipart(char *bootptr, struct ipart *partp)
2724*7c478bd9Sstevel@tonic-gate {
2725*7c478bd9Sstevel@tonic-gate #ifdef sparc
2726*7c478bd9Sstevel@tonic-gate 	/* Packing struct ipart for Sparc */
2727*7c478bd9Sstevel@tonic-gate 	partp->bootid = getbyte(&bootptr);
2728*7c478bd9Sstevel@tonic-gate 	partp->beghead = getbyte(&bootptr);
2729*7c478bd9Sstevel@tonic-gate 	partp->begsect = getbyte(&bootptr);
2730*7c478bd9Sstevel@tonic-gate 	partp->begcyl = getbyte(&bootptr);
2731*7c478bd9Sstevel@tonic-gate 	partp->systid = getbyte(&bootptr);
2732*7c478bd9Sstevel@tonic-gate 	partp->endhead = getbyte(&bootptr);
2733*7c478bd9Sstevel@tonic-gate 	partp->endsect = getbyte(&bootptr);
2734*7c478bd9Sstevel@tonic-gate 	partp->endcyl = getbyte(&bootptr);
2735*7c478bd9Sstevel@tonic-gate 	partp->relsect = getlong(&bootptr);
2736*7c478bd9Sstevel@tonic-gate 	partp->numsect = getlong(&bootptr);
2737*7c478bd9Sstevel@tonic-gate #else
2738*7c478bd9Sstevel@tonic-gate 	*partp = *(struct ipart *)bootptr;
2739*7c478bd9Sstevel@tonic-gate #endif
2740*7c478bd9Sstevel@tonic-gate }
2741*7c478bd9Sstevel@tonic-gate 
2742*7c478bd9Sstevel@tonic-gate /*
2743*7c478bd9Sstevel@tonic-gate  * getbyte, getshort, getlong
2744*7c478bd9Sstevel@tonic-gate  * 	Get a byte, a short, or a long (SPARC only).
2745*7c478bd9Sstevel@tonic-gate  */
2746*7c478bd9Sstevel@tonic-gate #ifdef sparc
2747*7c478bd9Sstevel@tonic-gate getbyte(uchar_t **bp)
2748*7c478bd9Sstevel@tonic-gate {
2749*7c478bd9Sstevel@tonic-gate 	int	b;
2750*7c478bd9Sstevel@tonic-gate 
2751*7c478bd9Sstevel@tonic-gate 	b = **bp;
2752*7c478bd9Sstevel@tonic-gate 	*bp = *bp + 1;
2753*7c478bd9Sstevel@tonic-gate 	return (b);
2754*7c478bd9Sstevel@tonic-gate }
2755*7c478bd9Sstevel@tonic-gate 
2756*7c478bd9Sstevel@tonic-gate getshort(uchar_t **bp)
2757*7c478bd9Sstevel@tonic-gate {
2758*7c478bd9Sstevel@tonic-gate 	int	b;
2759*7c478bd9Sstevel@tonic-gate 
2760*7c478bd9Sstevel@tonic-gate 	b = ((**bp) << 8) | *(*bp + 1);
2761*7c478bd9Sstevel@tonic-gate 	*bp += 2;
2762*7c478bd9Sstevel@tonic-gate 	return (b);
2763*7c478bd9Sstevel@tonic-gate }
2764*7c478bd9Sstevel@tonic-gate 
2765*7c478bd9Sstevel@tonic-gate getlong(uchar_t **bp)
2766*7c478bd9Sstevel@tonic-gate {
2767*7c478bd9Sstevel@tonic-gate 	int	b, bh, bl;
2768*7c478bd9Sstevel@tonic-gate 
2769*7c478bd9Sstevel@tonic-gate 	bh = ((**bp) << 8) | *(*bp + 1);
2770*7c478bd9Sstevel@tonic-gate 	*bp += 2;
2771*7c478bd9Sstevel@tonic-gate 	bl = ((**bp) << 8) | *(*bp + 1);
2772*7c478bd9Sstevel@tonic-gate 	*bp += 2;
2773*7c478bd9Sstevel@tonic-gate 
2774*7c478bd9Sstevel@tonic-gate 	b = (bh << 16) | bl;
2775*7c478bd9Sstevel@tonic-gate 	return (b);
2776*7c478bd9Sstevel@tonic-gate }
2777*7c478bd9Sstevel@tonic-gate #endif
2778*7c478bd9Sstevel@tonic-gate 
2779*7c478bd9Sstevel@tonic-gate /*
2780*7c478bd9Sstevel@tonic-gate  * copy_Table_to_Bootblk
2781*7c478bd9Sstevel@tonic-gate  * Copy the table into the 512 boot record. Note that the unused
2782*7c478bd9Sstevel@tonic-gate  * entries will always be the last ones in the table and they are
2783*7c478bd9Sstevel@tonic-gate  * marked with 100 in sysind. The the unused portion of the table
2784*7c478bd9Sstevel@tonic-gate  * is padded with zeros in the bytes after the used entries.
2785*7c478bd9Sstevel@tonic-gate  */
2786*7c478bd9Sstevel@tonic-gate copy_Table_to_Bootblk()
2787*7c478bd9Sstevel@tonic-gate {
2788*7c478bd9Sstevel@tonic-gate 	struct ipart *boot_ptr, *tbl_ptr;
2789*7c478bd9Sstevel@tonic-gate 
2790*7c478bd9Sstevel@tonic-gate 	boot_ptr = (struct ipart *)Bootblk->parts;
2791*7c478bd9Sstevel@tonic-gate 	tbl_ptr = (struct ipart *)&Table[0].bootid;
2792*7c478bd9Sstevel@tonic-gate 	for (; tbl_ptr < (struct ipart *)&Table[FD_NUMPART].bootid;
2793*7c478bd9Sstevel@tonic-gate 	    tbl_ptr++, boot_ptr++) {
2794*7c478bd9Sstevel@tonic-gate 	    if (tbl_ptr->systid == UNUSED)
2795*7c478bd9Sstevel@tonic-gate 		memset(boot_ptr, 0, sizeof (struct ipart));
2796*7c478bd9Sstevel@tonic-gate 	    else
2797*7c478bd9Sstevel@tonic-gate 		memcpy(boot_ptr, tbl_ptr, sizeof (struct ipart));
2798*7c478bd9Sstevel@tonic-gate 	}
2799*7c478bd9Sstevel@tonic-gate 	Bootblk->signature = les(MBB_MAGIC);
2800*7c478bd9Sstevel@tonic-gate }
2801*7c478bd9Sstevel@tonic-gate 
2802*7c478bd9Sstevel@tonic-gate /*
2803*7c478bd9Sstevel@tonic-gate  * TableChanged
2804*7c478bd9Sstevel@tonic-gate  * 	Check for any changes in the partition table.
2805*7c478bd9Sstevel@tonic-gate  */
2806*7c478bd9Sstevel@tonic-gate TableChanged()
2807*7c478bd9Sstevel@tonic-gate {
2808*7c478bd9Sstevel@tonic-gate 	int i, changed;
2809*7c478bd9Sstevel@tonic-gate 
2810*7c478bd9Sstevel@tonic-gate 	changed = 0;
2811*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2812*7c478bd9Sstevel@tonic-gate 	    if (memcmp(&Old_Table[i], &Table[i], sizeof (Table[0])) != 0) {
2813*7c478bd9Sstevel@tonic-gate 		/* Partition table changed, write back to disk */
2814*7c478bd9Sstevel@tonic-gate 		changed = 1;
2815*7c478bd9Sstevel@tonic-gate 	    }
2816*7c478bd9Sstevel@tonic-gate 	}
2817*7c478bd9Sstevel@tonic-gate 
2818*7c478bd9Sstevel@tonic-gate 	return (changed);
2819*7c478bd9Sstevel@tonic-gate }
2820*7c478bd9Sstevel@tonic-gate 
2821*7c478bd9Sstevel@tonic-gate /*
2822*7c478bd9Sstevel@tonic-gate  * ffile_write
2823*7c478bd9Sstevel@tonic-gate  * 	Display contents of partition table to standard output or
2824*7c478bd9Sstevel@tonic-gate  *	another file name without writing it to the disk (-W file).
2825*7c478bd9Sstevel@tonic-gate  */
2826*7c478bd9Sstevel@tonic-gate ffile_write(file)
2827*7c478bd9Sstevel@tonic-gate char	*file;
2828*7c478bd9Sstevel@tonic-gate {
2829*7c478bd9Sstevel@tonic-gate 	register int	i;
2830*7c478bd9Sstevel@tonic-gate 	register int	c;
2831*7c478bd9Sstevel@tonic-gate 	FILE *fp;
2832*7c478bd9Sstevel@tonic-gate 
2833*7c478bd9Sstevel@tonic-gate 	/*
2834*7c478bd9Sstevel@tonic-gate 	 * If file isn't standard output, then it's a file name.
2835*7c478bd9Sstevel@tonic-gate 	 * Open file and write it.
2836*7c478bd9Sstevel@tonic-gate 	 */
2837*7c478bd9Sstevel@tonic-gate 	if (file != (char *)stdout) {
2838*7c478bd9Sstevel@tonic-gate 	    if ((fp = fopen(file, "w")) == NULL) {
2839*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "fdisk: Cannot open output file %s.\n",
2840*7c478bd9Sstevel@tonic-gate 		    file);
2841*7c478bd9Sstevel@tonic-gate 		exit(1);
2842*7c478bd9Sstevel@tonic-gate 	    }
2843*7c478bd9Sstevel@tonic-gate 	}
2844*7c478bd9Sstevel@tonic-gate 	else
2845*7c478bd9Sstevel@tonic-gate 	    fp = stdout;
2846*7c478bd9Sstevel@tonic-gate 
2847*7c478bd9Sstevel@tonic-gate 	/*
2848*7c478bd9Sstevel@tonic-gate 	 * Write the fdisk table information
2849*7c478bd9Sstevel@tonic-gate 	 */
2850*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "\n* %s default fdisk table\n", Dfltdev);
2851*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "* Dimensions:\n");
2852*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
2853*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   %4d sectors/track\n", sectors);
2854*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   %4d tracks/cylinder\n", heads);
2855*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   %4d cylinders\n", Numcyl);
2856*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*\n");
2857*7c478bd9Sstevel@tonic-gate 	/* Write virtual (HBA) geometry, if required	*/
2858*7c478bd9Sstevel@tonic-gate 	if (v_flag) {
2859*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "* HBA Dimensions:\n");
2860*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "*   %4d bytes/sector\n", sectsiz);
2861*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "*   %4d sectors/track\n", hba_sectors);
2862*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "*   %4d tracks/cylinder\n", hba_heads);
2863*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "*   %4d cylinders\n", hba_Numcyl);
2864*7c478bd9Sstevel@tonic-gate 		fprintf(fp, "*\n");
2865*7c478bd9Sstevel@tonic-gate 	}
2866*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "* systid:\n");
2867*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    1: DOSOS12\n");
2868*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    2: PCIXOS\n");
2869*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    4: DOSOS16\n");
2870*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    5: EXTDOS\n");
2871*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    6: DOSBIG\n");
2872*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    7: FDISK_IFS\n");
2873*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    8: FDISK_AIXBOOT\n");
2874*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*    9: FDISK_AIXDATA\n");
2875*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   10: FDISK_0S2BOOT\n");
2876*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   11: FDISK_WINDOWS\n");
2877*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   12: FDISK_EXT_WIN\n");
2878*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   14: FDISK_FAT95\n");
2879*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   15: FDISK_EXTLBA\n");
2880*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   18: DIAGPART\n");
2881*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   65: FDISK_LINUX\n");
2882*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   82: FDISK_CPM\n");
2883*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   86: DOSDATA\n");
2884*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   98: OTHEROS\n");
2885*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*   99: UNIXOS\n");
2886*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  101: FDISK_NOVELL3\n");
2887*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  119: FDISK_QNX4\n");
2888*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  120: FDISK_QNX42\n");
2889*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  121: FDISK_QNX43\n");
2890*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  130: SUNIXOS\n");
2891*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  131: FDISK_LINUXNAT\n");
2892*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  134: FDISK_NTFSVOL1\n");
2893*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  135: FDISK_NTFSVOL2\n");
2894*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  165: FDISK_BSD\n");
2895*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  167: FDISK_NEXTSTEP\n");
2896*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  183: FDISK_BSDIFS\n");
2897*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  184: FDISK_BSDISWAP\n");
2898*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  190: X86BOOT\n");
2899*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  191: SUNIXOS2\n");
2900*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  238: EFI_PMBR\n");
2901*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*  239: EFI_FS\n");
2902*7c478bd9Sstevel@tonic-gate 	fprintf(fp, "*\n");
2903*7c478bd9Sstevel@tonic-gate 	fprintf(fp,
2904*7c478bd9Sstevel@tonic-gate 	    "\n* Id    Act  Bhead  Bsect  Bcyl    Ehead  Esect  Ecyl"
2905*7c478bd9Sstevel@tonic-gate 	    "    Rsect    Numsect\n");
2906*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2907*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid != UNUSED)
2908*7c478bd9Sstevel@tonic-gate 			fprintf(fp,
2909*7c478bd9Sstevel@tonic-gate 			    "  %-5d %-4d %-6d %-6d %-7d %-6d %-6d %-7d %-8d"
2910*7c478bd9Sstevel@tonic-gate 			    " %-8d\n",
2911*7c478bd9Sstevel@tonic-gate 			    Table[i].systid,
2912*7c478bd9Sstevel@tonic-gate 			    Table[i].bootid,
2913*7c478bd9Sstevel@tonic-gate 			    Table[i].beghead,
2914*7c478bd9Sstevel@tonic-gate 			    Table[i].begsect & 0x3f,
2915*7c478bd9Sstevel@tonic-gate 			    ((Table[i].begcyl & 0xff) | ((Table[i].begsect &
2916*7c478bd9Sstevel@tonic-gate 				0xc0) << 2)),
2917*7c478bd9Sstevel@tonic-gate 			    Table[i].endhead,
2918*7c478bd9Sstevel@tonic-gate 			    Table[i].endsect & 0x3f,
2919*7c478bd9Sstevel@tonic-gate 			    ((Table[i].endcyl & 0xff) | ((Table[i].endsect &
2920*7c478bd9Sstevel@tonic-gate 				0xc0) << 2)),
2921*7c478bd9Sstevel@tonic-gate 			    lel(Table[i].relsect),
2922*7c478bd9Sstevel@tonic-gate 			    lel(Table[i].numsect));
2923*7c478bd9Sstevel@tonic-gate 	}
2924*7c478bd9Sstevel@tonic-gate 	if (fp != stdout)
2925*7c478bd9Sstevel@tonic-gate 		fclose(fp);
2926*7c478bd9Sstevel@tonic-gate }
2927*7c478bd9Sstevel@tonic-gate 
2928*7c478bd9Sstevel@tonic-gate /*
2929*7c478bd9Sstevel@tonic-gate  * fix_slice
2930*7c478bd9Sstevel@tonic-gate  * 	Read the VTOC table on the Solaris partition and check that no
2931*7c478bd9Sstevel@tonic-gate  *	slices exist that extend past the end of the Solaris partition.
2932*7c478bd9Sstevel@tonic-gate  *	If no Solaris partition exists, nothing is done.
2933*7c478bd9Sstevel@tonic-gate  */
2934*7c478bd9Sstevel@tonic-gate fix_slice()
2935*7c478bd9Sstevel@tonic-gate {
2936*7c478bd9Sstevel@tonic-gate 	int	i;
2937*7c478bd9Sstevel@tonic-gate 	int	ret;
2938*7c478bd9Sstevel@tonic-gate 	int	numsect;
2939*7c478bd9Sstevel@tonic-gate 
2940*7c478bd9Sstevel@tonic-gate 	if (io_image) {
2941*7c478bd9Sstevel@tonic-gate 		return (0);
2942*7c478bd9Sstevel@tonic-gate 	}
2943*7c478bd9Sstevel@tonic-gate 
2944*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < FD_NUMPART; i++) {
2945*7c478bd9Sstevel@tonic-gate 		if (Table[i].systid == SUNIXOS || Table[i].systid == SUNIXOS2) {
2946*7c478bd9Sstevel@tonic-gate 			/*
2947*7c478bd9Sstevel@tonic-gate 			 * Only the size matters (not starting point), since
2948*7c478bd9Sstevel@tonic-gate 			 * VTOC entries are relative to the start of
2949*7c478bd9Sstevel@tonic-gate 			 * the partition.
2950*7c478bd9Sstevel@tonic-gate 			 */
2951*7c478bd9Sstevel@tonic-gate 			numsect = lel(Table[i].numsect);
2952*7c478bd9Sstevel@tonic-gate 			break;
2953*7c478bd9Sstevel@tonic-gate 		}
2954*7c478bd9Sstevel@tonic-gate 	}
2955*7c478bd9Sstevel@tonic-gate 
2956*7c478bd9Sstevel@tonic-gate 	if (i >= FD_NUMPART) {
2957*7c478bd9Sstevel@tonic-gate 		if (!io_nifdisk) {
2958*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
2959*7c478bd9Sstevel@tonic-gate 			    "fdisk: No Solaris partition found - VTOC not"
2960*7c478bd9Sstevel@tonic-gate 			    " checked.\n");
2961*7c478bd9Sstevel@tonic-gate 		}
2962*7c478bd9Sstevel@tonic-gate 		return (1);
2963*7c478bd9Sstevel@tonic-gate 	}
2964*7c478bd9Sstevel@tonic-gate 
2965*7c478bd9Sstevel@tonic-gate 	if ((ret = readvtoc()) != VTOC_OK) {
2966*7c478bd9Sstevel@tonic-gate 		exit(1);		/* Failed to read the VTOC */
2967*7c478bd9Sstevel@tonic-gate 	} else {
2968*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < V_NUMPAR; i++) {
2969*7c478bd9Sstevel@tonic-gate 			/* Special case for slice two (entire disk) */
2970*7c478bd9Sstevel@tonic-gate 			if (i == 2) {
2971*7c478bd9Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_start != 0) {
2972*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
2973*7c478bd9Sstevel@tonic-gate 					    "slice %d starts at %d, is not at"
2974*7c478bd9Sstevel@tonic-gate 					    " start of partition",
2975*7c478bd9Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start);
2976*7c478bd9Sstevel@tonic-gate 					if (!io_nifdisk) {
2977*7c478bd9Sstevel@tonic-gate 					    printf(" adjust ?:");
2978*7c478bd9Sstevel@tonic-gate 					    if (yesno())
2979*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
2980*7c478bd9Sstevel@tonic-gate 					} else {
2981*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_start = 0;
2982*7c478bd9Sstevel@tonic-gate 					    (void) fprintf(stderr,
2983*7c478bd9Sstevel@tonic-gate 						" adjusted!\n");
2984*7c478bd9Sstevel@tonic-gate 					}
2985*7c478bd9Sstevel@tonic-gate 
2986*7c478bd9Sstevel@tonic-gate 				}
2987*7c478bd9Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_size != numsect) {
2988*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
2989*7c478bd9Sstevel@tonic-gate 					    "slice %d size %d does not cover"
2990*7c478bd9Sstevel@tonic-gate 					    " complete partition",
2991*7c478bd9Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_size);
2992*7c478bd9Sstevel@tonic-gate 					if (!io_nifdisk) {
2993*7c478bd9Sstevel@tonic-gate 					    printf(" adjust ?:");
2994*7c478bd9Sstevel@tonic-gate 					    if (yesno())
2995*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size =
2996*7c478bd9Sstevel@tonic-gate 						    numsect;
2997*7c478bd9Sstevel@tonic-gate 					} else {
2998*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_size =
2999*7c478bd9Sstevel@tonic-gate 						numsect;
3000*7c478bd9Sstevel@tonic-gate 					    (void) fprintf(stderr,
3001*7c478bd9Sstevel@tonic-gate 						" adjusted!\n");
3002*7c478bd9Sstevel@tonic-gate 					}
3003*7c478bd9Sstevel@tonic-gate 				}
3004*7c478bd9Sstevel@tonic-gate 				if (disk_vtoc.v_part[i].p_tag != V_BACKUP) {
3005*7c478bd9Sstevel@tonic-gate 				    (void) fprintf(stderr,
3006*7c478bd9Sstevel@tonic-gate 					"slice %d tag was %d should be %d",
3007*7c478bd9Sstevel@tonic-gate 					i, disk_vtoc.v_part[i].p_tag,
3008*7c478bd9Sstevel@tonic-gate 					V_BACKUP);
3009*7c478bd9Sstevel@tonic-gate 				    if (!io_nifdisk) {
3010*7c478bd9Sstevel@tonic-gate 					printf(" fix ?:");
3011*7c478bd9Sstevel@tonic-gate 					    if (yesno())
3012*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag =
3013*7c478bd9Sstevel@tonic-gate 						    V_BACKUP;
3014*7c478bd9Sstevel@tonic-gate 				    } else {
3015*7c478bd9Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_tag = V_BACKUP;
3016*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr, " fixed!\n");
3017*7c478bd9Sstevel@tonic-gate 					}
3018*7c478bd9Sstevel@tonic-gate 				}
3019*7c478bd9Sstevel@tonic-gate 			} else {
3020*7c478bd9Sstevel@tonic-gate 				if (io_ADJT) {
3021*7c478bd9Sstevel@tonic-gate 				    if (disk_vtoc.v_part[i].p_start > numsect ||
3022*7c478bd9Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_start +
3023*7c478bd9Sstevel@tonic-gate 					disk_vtoc.v_part[i].p_size > numsect) {
3024*7c478bd9Sstevel@tonic-gate 					    (void) fprintf(stderr,
3025*7c478bd9Sstevel@tonic-gate 						"slice %d (start %d, end %d) is"
3026*7c478bd9Sstevel@tonic-gate 						" larger than the partition",
3027*7c478bd9Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start,
3028*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start +
3029*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size);
3030*7c478bd9Sstevel@tonic-gate 					    if (!io_nifdisk) {
3031*7c478bd9Sstevel@tonic-gate 						printf(" remove ?:");
3032*7c478bd9Sstevel@tonic-gate 						if (yesno()) {
3033*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size =
3034*7c478bd9Sstevel@tonic-gate 							0;
3035*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_start
3036*7c478bd9Sstevel@tonic-gate 							= 0;
3037*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_tag =
3038*7c478bd9Sstevel@tonic-gate 							0;
3039*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_flag =
3040*7c478bd9Sstevel@tonic-gate 							0;
3041*7c478bd9Sstevel@tonic-gate 						}
3042*7c478bd9Sstevel@tonic-gate 					    } else {
3043*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size = 0;
3044*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start = 0;
3045*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag = 0;
3046*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_flag = 0;
3047*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
3048*7c478bd9Sstevel@tonic-gate 						    " removed!\n");
3049*7c478bd9Sstevel@tonic-gate 						}
3050*7c478bd9Sstevel@tonic-gate 					}
3051*7c478bd9Sstevel@tonic-gate 				} else {
3052*7c478bd9Sstevel@tonic-gate 				    if (disk_vtoc.v_part[i].p_start >
3053*7c478bd9Sstevel@tonic-gate 					numsect) {
3054*7c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
3055*7c478bd9Sstevel@tonic-gate 					    "slice %d (start %d) is larger"
3056*7c478bd9Sstevel@tonic-gate 					    " than the partition",
3057*7c478bd9Sstevel@tonic-gate 						i, disk_vtoc.v_part[i].p_start);
3058*7c478bd9Sstevel@tonic-gate 					if (!io_nifdisk) {
3059*7c478bd9Sstevel@tonic-gate 					    printf(" remove ?:");
3060*7c478bd9Sstevel@tonic-gate 					    if (yesno()) {
3061*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size = 0;
3062*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start =
3063*7c478bd9Sstevel@tonic-gate 						    0;
3064*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_tag = 0;
3065*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_flag = 0;
3066*7c478bd9Sstevel@tonic-gate 					    }
3067*7c478bd9Sstevel@tonic-gate 					} else {
3068*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_size = 0;
3069*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_start = 0;
3070*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_tag = 0;
3071*7c478bd9Sstevel@tonic-gate 					    disk_vtoc.v_part[i].p_flag = 0;
3072*7c478bd9Sstevel@tonic-gate 					    (void) fprintf(stderr,
3073*7c478bd9Sstevel@tonic-gate 						" removed!\n");
3074*7c478bd9Sstevel@tonic-gate 					    }
3075*7c478bd9Sstevel@tonic-gate 					} else if (disk_vtoc.v_part[i].p_start
3076*7c478bd9Sstevel@tonic-gate 					    + disk_vtoc.v_part[i].p_size >
3077*7c478bd9Sstevel@tonic-gate 					    numsect) {
3078*7c478bd9Sstevel@tonic-gate 					    (void) fprintf(stderr,
3079*7c478bd9Sstevel@tonic-gate 						"slice %d (end %d) is larger"
3080*7c478bd9Sstevel@tonic-gate 						" than the partition",
3081*7c478bd9Sstevel@tonic-gate 						i,
3082*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_start +
3083*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size);
3084*7c478bd9Sstevel@tonic-gate 					    if (!io_nifdisk) {
3085*7c478bd9Sstevel@tonic-gate 						printf(" adjust ?:");
3086*7c478bd9Sstevel@tonic-gate 						if (yesno()) {
3087*7c478bd9Sstevel@tonic-gate 						    disk_vtoc.v_part[i].p_size
3088*7c478bd9Sstevel@tonic-gate 							= numsect;
3089*7c478bd9Sstevel@tonic-gate 						}
3090*7c478bd9Sstevel@tonic-gate 					    } else {
3091*7c478bd9Sstevel@tonic-gate 						disk_vtoc.v_part[i].p_size =
3092*7c478bd9Sstevel@tonic-gate 						    numsect;
3093*7c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
3094*7c478bd9Sstevel@tonic-gate 						    " adjusted!\n");
3095*7c478bd9Sstevel@tonic-gate 						}
3096*7c478bd9Sstevel@tonic-gate 					}
3097*7c478bd9Sstevel@tonic-gate 				}
3098*7c478bd9Sstevel@tonic-gate 			}
3099*7c478bd9Sstevel@tonic-gate 		}
3100*7c478bd9Sstevel@tonic-gate 	}
3101*7c478bd9Sstevel@tonic-gate #if 1		/* bh for now */
3102*7c478bd9Sstevel@tonic-gate 	/* Make the VTOC look sane - ha ha */
3103*7c478bd9Sstevel@tonic-gate 	disk_vtoc.v_version = V_VERSION;
3104*7c478bd9Sstevel@tonic-gate 	disk_vtoc.v_sanity = VTOC_SANE;
3105*7c478bd9Sstevel@tonic-gate 	disk_vtoc.v_nparts = V_NUMPAR;
3106*7c478bd9Sstevel@tonic-gate 	if (disk_vtoc.v_sectorsz == 0)
3107*7c478bd9Sstevel@tonic-gate 		disk_vtoc.v_sectorsz = NBPSCTR;
3108*7c478bd9Sstevel@tonic-gate #endif
3109*7c478bd9Sstevel@tonic-gate 
3110*7c478bd9Sstevel@tonic-gate 	/* Write the VTOC back to the disk */
3111*7c478bd9Sstevel@tonic-gate 	if (!io_readonly)
3112*7c478bd9Sstevel@tonic-gate 		writevtoc();
3113*7c478bd9Sstevel@tonic-gate }
3114*7c478bd9Sstevel@tonic-gate 
3115*7c478bd9Sstevel@tonic-gate /*
3116*7c478bd9Sstevel@tonic-gate  * yesno
3117*7c478bd9Sstevel@tonic-gate  * Get yes or no answer. Return 1 for yes and 0 for no.
3118*7c478bd9Sstevel@tonic-gate  */
3119*7c478bd9Sstevel@tonic-gate 
3120*7c478bd9Sstevel@tonic-gate yesno()
3121*7c478bd9Sstevel@tonic-gate {
3122*7c478bd9Sstevel@tonic-gate 	char	s[80];
3123*7c478bd9Sstevel@tonic-gate 
3124*7c478bd9Sstevel@tonic-gate 	for (;;) {
3125*7c478bd9Sstevel@tonic-gate 		gets(s);
3126*7c478bd9Sstevel@tonic-gate 		rm_blanks(s);
3127*7c478bd9Sstevel@tonic-gate 		if ((s[1] != 0) || ((s[0] != 'y') && (s[0] != 'n'))) {
3128*7c478bd9Sstevel@tonic-gate 			printf(E_LINE);
3129*7c478bd9Sstevel@tonic-gate 			printf("Please answer with \"y\" or \"n\": ");
3130*7c478bd9Sstevel@tonic-gate 			continue;
3131*7c478bd9Sstevel@tonic-gate 		}
3132*7c478bd9Sstevel@tonic-gate 		if (s[0] == 'y')
3133*7c478bd9Sstevel@tonic-gate 			return (1);
3134*7c478bd9Sstevel@tonic-gate 		else
3135*7c478bd9Sstevel@tonic-gate 			return (0);
3136*7c478bd9Sstevel@tonic-gate 	}
3137*7c478bd9Sstevel@tonic-gate }
3138*7c478bd9Sstevel@tonic-gate 
3139*7c478bd9Sstevel@tonic-gate /*
3140*7c478bd9Sstevel@tonic-gate  * readvtoc
3141*7c478bd9Sstevel@tonic-gate  * 	Read the VTOC from the Solaris partition of the device.
3142*7c478bd9Sstevel@tonic-gate  */
3143*7c478bd9Sstevel@tonic-gate readvtoc()
3144*7c478bd9Sstevel@tonic-gate {
3145*7c478bd9Sstevel@tonic-gate 	int	i;
3146*7c478bd9Sstevel@tonic-gate 	int	retval = VTOC_OK;
3147*7c478bd9Sstevel@tonic-gate 
3148*7c478bd9Sstevel@tonic-gate 	if ((i = read_vtoc(Dev, &disk_vtoc)) < VTOC_OK) {
3149*7c478bd9Sstevel@tonic-gate 		if (i == VT_EINVAL) {
3150*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Invalid VTOC.\n");
3151*7c478bd9Sstevel@tonic-gate 			vt_inval++;
3152*7c478bd9Sstevel@tonic-gate 			retval = VTOC_INVAL;
3153*7c478bd9Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
3154*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
3155*7c478bd9Sstevel@tonic-gate 				"GPT\n");
3156*7c478bd9Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
3157*7c478bd9Sstevel@tonic-gate 		} else {
3158*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot read VTOC.\n");
3159*7c478bd9Sstevel@tonic-gate 			retval = VTOC_RWERR;
3160*7c478bd9Sstevel@tonic-gate 		}
3161*7c478bd9Sstevel@tonic-gate 	}
3162*7c478bd9Sstevel@tonic-gate 	return (retval);
3163*7c478bd9Sstevel@tonic-gate }
3164*7c478bd9Sstevel@tonic-gate 
3165*7c478bd9Sstevel@tonic-gate /*
3166*7c478bd9Sstevel@tonic-gate  * writevtoc
3167*7c478bd9Sstevel@tonic-gate  * 	Write the VTOC to the Solaris partition on the device.
3168*7c478bd9Sstevel@tonic-gate  */
3169*7c478bd9Sstevel@tonic-gate writevtoc()
3170*7c478bd9Sstevel@tonic-gate {
3171*7c478bd9Sstevel@tonic-gate 	int	i;
3172*7c478bd9Sstevel@tonic-gate 	int	retval = 0;
3173*7c478bd9Sstevel@tonic-gate 
3174*7c478bd9Sstevel@tonic-gate 	if ((i = write_vtoc(Dev, &disk_vtoc)) != 0) {
3175*7c478bd9Sstevel@tonic-gate 		if (i == VT_EINVAL) {
3176*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
3177*7c478bd9Sstevel@tonic-gate 			    "fdisk: Invalid entry exists in VTOC.\n");
3178*7c478bd9Sstevel@tonic-gate 			retval = VTOC_INVAL;
3179*7c478bd9Sstevel@tonic-gate 		} else if (i == VT_ENOTSUP) {
3180*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: partition may have EFI "
3181*7c478bd9Sstevel@tonic-gate 				"GPT\n");
3182*7c478bd9Sstevel@tonic-gate 			retval = VTOC_NOTSUP;
3183*7c478bd9Sstevel@tonic-gate 		} else {
3184*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "fdisk: Cannot write VTOC.\n");
3185*7c478bd9Sstevel@tonic-gate 			retval = VTOC_RWERR;
3186*7c478bd9Sstevel@tonic-gate 		}
3187*7c478bd9Sstevel@tonic-gate 	}
3188*7c478bd9Sstevel@tonic-gate 	return (retval);
3189*7c478bd9Sstevel@tonic-gate }
3190*7c478bd9Sstevel@tonic-gate 
3191*7c478bd9Sstevel@tonic-gate /*
3192*7c478bd9Sstevel@tonic-gate  * efi_ioctl
3193*7c478bd9Sstevel@tonic-gate  * issues DKIOCSETEFI IOCTL
3194*7c478bd9Sstevel@tonic-gate  * (duplicate of private efi_ioctl() in rdwr_efi.c
3195*7c478bd9Sstevel@tonic-gate  */
3196*7c478bd9Sstevel@tonic-gate static int
3197*7c478bd9Sstevel@tonic-gate efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
3198*7c478bd9Sstevel@tonic-gate {
3199*7c478bd9Sstevel@tonic-gate 	void *data = dk_ioc->dki_data;
3200*7c478bd9Sstevel@tonic-gate 	int error;
3201*7c478bd9Sstevel@tonic-gate 
3202*7c478bd9Sstevel@tonic-gate 	dk_ioc->dki_data_64 = (uintptr_t)data;
3203*7c478bd9Sstevel@tonic-gate 	error = ioctl(fd, cmd, (void *)dk_ioc);
3204*7c478bd9Sstevel@tonic-gate 
3205*7c478bd9Sstevel@tonic-gate 	return (error);
3206*7c478bd9Sstevel@tonic-gate }
3207*7c478bd9Sstevel@tonic-gate 
3208*7c478bd9Sstevel@tonic-gate /*
3209*7c478bd9Sstevel@tonic-gate  * clear_efi
3210*7c478bd9Sstevel@tonic-gate  * Clear EFI labels from the EFI_PMBR partition on the device
3211*7c478bd9Sstevel@tonic-gate  * This function is modeled on the libefi(3LIB) call efi_write()
3212*7c478bd9Sstevel@tonic-gate  */
3213*7c478bd9Sstevel@tonic-gate int
3214*7c478bd9Sstevel@tonic-gate clear_efi()
3215*7c478bd9Sstevel@tonic-gate {
3216*7c478bd9Sstevel@tonic-gate 	struct dk_gpt	*efi_vtoc;
3217*7c478bd9Sstevel@tonic-gate 	dk_efi_t	dk_ioc;
3218*7c478bd9Sstevel@tonic-gate 
3219*7c478bd9Sstevel@tonic-gate 	/*
3220*7c478bd9Sstevel@tonic-gate 	 * see if we can read the EFI label
3221*7c478bd9Sstevel@tonic-gate 	 */
3222*7c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_read(Dev, &efi_vtoc) < 0) {
3223*7c478bd9Sstevel@tonic-gate 		return (VT_ERROR);
3224*7c478bd9Sstevel@tonic-gate 	}
3225*7c478bd9Sstevel@tonic-gate 
3226*7c478bd9Sstevel@tonic-gate 	/*
3227*7c478bd9Sstevel@tonic-gate 	 * set up the dk_ioc structure for writing
3228*7c478bd9Sstevel@tonic-gate 	 */
3229*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = 1;
3230*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length = EFI_MIN_ARRAY_SIZE + efi_vtoc->efi_lbasize;
3231*7c478bd9Sstevel@tonic-gate 
3232*7c478bd9Sstevel@tonic-gate 	if ((dk_ioc.dki_data = calloc(dk_ioc.dki_length, 1)) == NULL) {
3233*7c478bd9Sstevel@tonic-gate 		return (VT_ERROR);
3234*7c478bd9Sstevel@tonic-gate 	}
3235*7c478bd9Sstevel@tonic-gate 
3236*7c478bd9Sstevel@tonic-gate 	/*
3237*7c478bd9Sstevel@tonic-gate 	 * clear the primary label
3238*7c478bd9Sstevel@tonic-gate 	 */
3239*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
3240*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tClearing primary EFI label at block "
3241*7c478bd9Sstevel@tonic-gate 		    "%d\n", dk_ioc.dki_lba);
3242*7c478bd9Sstevel@tonic-gate 	}
3243*7c478bd9Sstevel@tonic-gate 
3244*7c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
3245*7c478bd9Sstevel@tonic-gate 		free(dk_ioc.dki_data);
3246*7c478bd9Sstevel@tonic-gate 		switch (errno) {
3247*7c478bd9Sstevel@tonic-gate 			case EIO:
3248*7c478bd9Sstevel@tonic-gate 				return (VT_EIO);
3249*7c478bd9Sstevel@tonic-gate 			case EINVAL:
3250*7c478bd9Sstevel@tonic-gate 				return (VT_EINVAL);
3251*7c478bd9Sstevel@tonic-gate 			default:
3252*7c478bd9Sstevel@tonic-gate 				return (VT_ERROR);
3253*7c478bd9Sstevel@tonic-gate 		}
3254*7c478bd9Sstevel@tonic-gate 	}
3255*7c478bd9Sstevel@tonic-gate 
3256*7c478bd9Sstevel@tonic-gate 	/*
3257*7c478bd9Sstevel@tonic-gate 	 * clear the backup partition table
3258*7c478bd9Sstevel@tonic-gate 	 */
3259*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_u_lba + 1;
3260*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length -= efi_vtoc->efi_lbasize;
3261*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_data++;
3262*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
3263*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tClearing backup partition table at block "
3264*7c478bd9Sstevel@tonic-gate 		    "%d\n", dk_ioc.dki_lba);
3265*7c478bd9Sstevel@tonic-gate 	}
3266*7c478bd9Sstevel@tonic-gate 
3267*7c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
3268*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\tUnable to clear backup EFI label at "
3269*7c478bd9Sstevel@tonic-gate 			"block %llu; errno %d\n", efi_vtoc->efi_last_u_lba + 1,
3270*7c478bd9Sstevel@tonic-gate 			errno);
3271*7c478bd9Sstevel@tonic-gate 	}
3272*7c478bd9Sstevel@tonic-gate 
3273*7c478bd9Sstevel@tonic-gate 	/*
3274*7c478bd9Sstevel@tonic-gate 	 * clear the backup label
3275*7c478bd9Sstevel@tonic-gate 	 */
3276*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_lba = efi_vtoc->efi_last_lba;
3277*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_length = efi_vtoc->efi_lbasize;
3278*7c478bd9Sstevel@tonic-gate 	dk_ioc.dki_data--;
3279*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
3280*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tClearing backup label at block "
3281*7c478bd9Sstevel@tonic-gate 		    "%d\n", dk_ioc.dki_lba);
3282*7c478bd9Sstevel@tonic-gate 	}
3283*7c478bd9Sstevel@tonic-gate 
3284*7c478bd9Sstevel@tonic-gate 	if (efi_ioctl(Dev, DKIOCSETEFI, &dk_ioc) == -1) {
3285*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "\tUnable to clear backup EFI label at "
3286*7c478bd9Sstevel@tonic-gate 			"block %llu; errno %d\n", efi_vtoc->efi_last_lba,
3287*7c478bd9Sstevel@tonic-gate 			errno);
3288*7c478bd9Sstevel@tonic-gate 	}
3289*7c478bd9Sstevel@tonic-gate 
3290*7c478bd9Sstevel@tonic-gate 	free(dk_ioc.dki_data);
3291*7c478bd9Sstevel@tonic-gate 	efi_free(efi_vtoc);
3292*7c478bd9Sstevel@tonic-gate 
3293*7c478bd9Sstevel@tonic-gate 	return (0);
3294*7c478bd9Sstevel@tonic-gate }
3295*7c478bd9Sstevel@tonic-gate 
3296*7c478bd9Sstevel@tonic-gate /*
3297*7c478bd9Sstevel@tonic-gate  * clear_vtoc
3298*7c478bd9Sstevel@tonic-gate  * 	Clear the VTOC from the current or previous Solaris partition on the
3299*7c478bd9Sstevel@tonic-gate  *      device.
3300*7c478bd9Sstevel@tonic-gate  */
3301*7c478bd9Sstevel@tonic-gate int
3302*7c478bd9Sstevel@tonic-gate clear_vtoc(int table, int part)
3303*7c478bd9Sstevel@tonic-gate {
3304*7c478bd9Sstevel@tonic-gate 	struct ipart *clr_table;
3305*7c478bd9Sstevel@tonic-gate 	struct dk_label disk_label;
3306*7c478bd9Sstevel@tonic-gate 	int pcyl, ncyl, backup_block, solaris_offset, count, bytes, seek_byte;
3307*7c478bd9Sstevel@tonic-gate 
3308*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
3309*7c478bd9Sstevel@tonic-gate 	struct dk_label	read_label;
3310*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3311*7c478bd9Sstevel@tonic-gate 
3312*7c478bd9Sstevel@tonic-gate 	if (table == OLD) {
3313*7c478bd9Sstevel@tonic-gate 		clr_table = &Old_Table[part];
3314*7c478bd9Sstevel@tonic-gate 	} else {
3315*7c478bd9Sstevel@tonic-gate 		clr_table = &Table[part];
3316*7c478bd9Sstevel@tonic-gate 	}
3317*7c478bd9Sstevel@tonic-gate 
3318*7c478bd9Sstevel@tonic-gate 	if (memset(&disk_label, 0, sizeof (struct dk_label)) == NULL) {
3319*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tError zeroing dk_label structure\n");
3320*7c478bd9Sstevel@tonic-gate 	}
3321*7c478bd9Sstevel@tonic-gate 
3322*7c478bd9Sstevel@tonic-gate 	seek_byte = (lel(clr_table->relsect) * sectsiz) + VTOC_OFFSET;
3323*7c478bd9Sstevel@tonic-gate 
3324*7c478bd9Sstevel@tonic-gate 	if (io_debug) {
3325*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tClearing primary VTOC at byte %d\n",
3326*7c478bd9Sstevel@tonic-gate 		    seek_byte);
3327*7c478bd9Sstevel@tonic-gate 	}
3328*7c478bd9Sstevel@tonic-gate 
3329*7c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3330*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tError seeking to primary label at byte %d\n",
3331*7c478bd9Sstevel@tonic-gate 		    seek_byte);
3332*7c478bd9Sstevel@tonic-gate 		return (0);
3333*7c478bd9Sstevel@tonic-gate 	}
3334*7c478bd9Sstevel@tonic-gate 
3335*7c478bd9Sstevel@tonic-gate 	bytes = write(Dev, &disk_label, sizeof (struct dk_label));
3336*7c478bd9Sstevel@tonic-gate 
3337*7c478bd9Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3338*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "\tWarning: only %d bytes written to clear"
3339*7c478bd9Sstevel@tonic-gate 		    " primary VTOC!\n", bytes);
3340*7c478bd9Sstevel@tonic-gate 	}
3341*7c478bd9Sstevel@tonic-gate 
3342*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
3343*7c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3344*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Error seeking to primary label at byte "
3345*7c478bd9Sstevel@tonic-gate 		    "%d\n", seek_byte);
3346*7c478bd9Sstevel@tonic-gate 		return (0);
3347*7c478bd9Sstevel@tonic-gate 	} else {
3348*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Successful lseek() to byte %d\n",
3349*7c478bd9Sstevel@tonic-gate 		    seek_byte);
3350*7c478bd9Sstevel@tonic-gate 	}
3351*7c478bd9Sstevel@tonic-gate 
3352*7c478bd9Sstevel@tonic-gate 	bytes = read(Dev, &read_label, sizeof (struct dk_label));
3353*7c478bd9Sstevel@tonic-gate 
3354*7c478bd9Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3355*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Warning: only %d bytes read of label\n",
3356*7c478bd9Sstevel@tonic-gate 		    bytes);
3357*7c478bd9Sstevel@tonic-gate 	}
3358*7c478bd9Sstevel@tonic-gate 
3359*7c478bd9Sstevel@tonic-gate 	if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) {
3360*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Warning: disk_label and read_label "
3361*7c478bd9Sstevel@tonic-gate 		    "differ!!!\n");
3362*7c478bd9Sstevel@tonic-gate 	} else {
3363*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG Good compare of disk_label and "
3364*7c478bd9Sstevel@tonic-gate 		    "read_label\n");
3365*7c478bd9Sstevel@tonic-gate 	}
3366*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3367*7c478bd9Sstevel@tonic-gate 
3368*7c478bd9Sstevel@tonic-gate 	/* Clear backup label */
3369*7c478bd9Sstevel@tonic-gate 	pcyl = lel(clr_table->numsect) / (heads * sectors);
3370*7c478bd9Sstevel@tonic-gate 	solaris_offset = lel(clr_table->relsect);
3371*7c478bd9Sstevel@tonic-gate 	ncyl = pcyl - acyl;
3372*7c478bd9Sstevel@tonic-gate 
3373*7c478bd9Sstevel@tonic-gate 	backup_block = ((ncyl + acyl - 1) *
3374*7c478bd9Sstevel@tonic-gate 	    (heads * sectors)) + ((heads - 1) * sectors) + 1;
3375*7c478bd9Sstevel@tonic-gate 
3376*7c478bd9Sstevel@tonic-gate 	for (count = 1; count < 6; count++) {
3377*7c478bd9Sstevel@tonic-gate 		seek_byte = (solaris_offset + backup_block) * 512;
3378*7c478bd9Sstevel@tonic-gate 
3379*7c478bd9Sstevel@tonic-gate 		if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3380*7c478bd9Sstevel@tonic-gate 			fprintf(stderr,
3381*7c478bd9Sstevel@tonic-gate 			    "\tError seeking to backup label at byte %d on "
3382*7c478bd9Sstevel@tonic-gate 			    "%s.\n", seek_byte, Dfltdev);
3383*7c478bd9Sstevel@tonic-gate 			return (0);
3384*7c478bd9Sstevel@tonic-gate 		}
3385*7c478bd9Sstevel@tonic-gate 
3386*7c478bd9Sstevel@tonic-gate 		if (io_debug) {
3387*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "\tClearing backup VTOC at"
3388*7c478bd9Sstevel@tonic-gate 			    " byte %d (block %d)\n",
3389*7c478bd9Sstevel@tonic-gate 			    (solaris_offset + backup_block) * 512,
3390*7c478bd9Sstevel@tonic-gate 			    (solaris_offset + backup_block));
3391*7c478bd9Sstevel@tonic-gate 		}
3392*7c478bd9Sstevel@tonic-gate 
3393*7c478bd9Sstevel@tonic-gate 		bytes = write(Dev, &disk_label, sizeof (struct dk_label));
3394*7c478bd9Sstevel@tonic-gate 
3395*7c478bd9Sstevel@tonic-gate 		if (bytes != sizeof (struct dk_label)) {
3396*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "\t\tWarning: only %d bytes written to "
3397*7c478bd9Sstevel@tonic-gate 			    "clear backup VTOC at block %d!\n", bytes,
3398*7c478bd9Sstevel@tonic-gate 			    (solaris_offset + backup_block));
3399*7c478bd9Sstevel@tonic-gate 		}
3400*7c478bd9Sstevel@tonic-gate 
3401*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
3402*7c478bd9Sstevel@tonic-gate 	if (lseek(Dev, seek_byte, SEEK_SET) == -1) {
3403*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Error seeking to backup label at byte "
3404*7c478bd9Sstevel@tonic-gate 		    "%d\n", seek_byte);
3405*7c478bd9Sstevel@tonic-gate 		return (0);
3406*7c478bd9Sstevel@tonic-gate 	} else {
3407*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Successful lseek() to byte %d\n",
3408*7c478bd9Sstevel@tonic-gate 		    seek_byte);
3409*7c478bd9Sstevel@tonic-gate 	}
3410*7c478bd9Sstevel@tonic-gate 
3411*7c478bd9Sstevel@tonic-gate 	bytes = read(Dev, &read_label, sizeof (struct dk_label));
3412*7c478bd9Sstevel@tonic-gate 
3413*7c478bd9Sstevel@tonic-gate 	if (bytes != sizeof (struct dk_label)) {
3414*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Warning: only %d bytes read of backup "
3415*7c478bd9Sstevel@tonic-gate 		    "label\n", bytes);
3416*7c478bd9Sstevel@tonic-gate 	}
3417*7c478bd9Sstevel@tonic-gate 
3418*7c478bd9Sstevel@tonic-gate 	if (memcmp(&disk_label, &read_label, sizeof (struct dk_label)) != 0) {
3419*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Warning: disk_label and read_label "
3420*7c478bd9Sstevel@tonic-gate 		    "differ!!!\n");
3421*7c478bd9Sstevel@tonic-gate 	} else {
3422*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "DEBUG: Good compare of disk_label and backup "
3423*7c478bd9Sstevel@tonic-gate 		    "read_label\n");
3424*7c478bd9Sstevel@tonic-gate 	}
3425*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
3426*7c478bd9Sstevel@tonic-gate 
3427*7c478bd9Sstevel@tonic-gate 		backup_block += 2;
3428*7c478bd9Sstevel@tonic-gate 	}
3429*7c478bd9Sstevel@tonic-gate 
3430*7c478bd9Sstevel@tonic-gate 	return (0);
3431*7c478bd9Sstevel@tonic-gate }
3432*7c478bd9Sstevel@tonic-gate 
3433*7c478bd9Sstevel@tonic-gate #define	FDISK_STANDARD_LECTURE \
3434*7c478bd9Sstevel@tonic-gate 	"Fdisk is normally used with the device that " \
3435*7c478bd9Sstevel@tonic-gate 	"represents the entire fixed disk.\n" \
3436*7c478bd9Sstevel@tonic-gate 	"(For example, /dev/rdsk/c0d0p0 on x86 or " \
3437*7c478bd9Sstevel@tonic-gate 	"/dev/rdsk/c0t5d0s2 on sparc).\n"
3438*7c478bd9Sstevel@tonic-gate 
3439*7c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_SECTOR_ZERO \
3440*7c478bd9Sstevel@tonic-gate 	"The device does not appear to include absolute\n" \
3441*7c478bd9Sstevel@tonic-gate 	"sector 0 of the PHYSICAL disk " \
3442*7c478bd9Sstevel@tonic-gate 	"(the normal location for an fdisk table).\n"
3443*7c478bd9Sstevel@tonic-gate 
3444*7c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NOT_FULL \
3445*7c478bd9Sstevel@tonic-gate 	"The device does not appear to encompass the entire PHYSICAL disk.\n"
3446*7c478bd9Sstevel@tonic-gate 
3447*7c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NO_VTOC \
3448*7c478bd9Sstevel@tonic-gate 	"Unable to find a volume table of contents.\n" \
3449*7c478bd9Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
3450*7c478bd9Sstevel@tonic-gate 
3451*7c478bd9Sstevel@tonic-gate #define	FDISK_LECTURE_NO_GEOM \
3452*7c478bd9Sstevel@tonic-gate 	"Unable to get geometry from device.\n" \
3453*7c478bd9Sstevel@tonic-gate 	"Cannot verify the device encompasses the full PHYSICAL disk.\n"
3454*7c478bd9Sstevel@tonic-gate 
3455*7c478bd9Sstevel@tonic-gate #define	FDISK_SHALL_I_CONTINUE \
3456*7c478bd9Sstevel@tonic-gate 	"Are you sure you want to continue? (y/n) "
3457*7c478bd9Sstevel@tonic-gate 
3458*7c478bd9Sstevel@tonic-gate /*
3459*7c478bd9Sstevel@tonic-gate  *  lecture_and_query
3460*7c478bd9Sstevel@tonic-gate  *	Called when a sanity check fails.  This routine gives a warning
3461*7c478bd9Sstevel@tonic-gate  *	specific to the check that fails, followed by a generic lecture
3462*7c478bd9Sstevel@tonic-gate  *	about the "right" device to supply as input.  Then, if appropriate,
3463*7c478bd9Sstevel@tonic-gate  *	it will prompt the user on whether or not they want to continue.
3464*7c478bd9Sstevel@tonic-gate  *	Inappropriate times for prompting are when the user has selected
3465*7c478bd9Sstevel@tonic-gate  *	non-interactive mode or read-only mode.
3466*7c478bd9Sstevel@tonic-gate  */
3467*7c478bd9Sstevel@tonic-gate int
3468*7c478bd9Sstevel@tonic-gate lecture_and_query(char *warning, char *devname)
3469*7c478bd9Sstevel@tonic-gate {
3470*7c478bd9Sstevel@tonic-gate 	if (io_nifdisk)
3471*7c478bd9Sstevel@tonic-gate 		return (0);
3472*7c478bd9Sstevel@tonic-gate 
3473*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "WARNING: Device %s: \n", devname);
3474*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "%s", warning);
3475*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, FDISK_STANDARD_LECTURE);
3476*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, FDISK_SHALL_I_CONTINUE);
3477*7c478bd9Sstevel@tonic-gate 
3478*7c478bd9Sstevel@tonic-gate 	return (yesno());
3479*7c478bd9Sstevel@tonic-gate }
3480*7c478bd9Sstevel@tonic-gate 
3481*7c478bd9Sstevel@tonic-gate void
3482*7c478bd9Sstevel@tonic-gate sanity_check_provided_device(char *devname, int fd)
3483*7c478bd9Sstevel@tonic-gate {
3484*7c478bd9Sstevel@tonic-gate 	struct vtoc v;
3485*7c478bd9Sstevel@tonic-gate 	struct dk_geom d;
3486*7c478bd9Sstevel@tonic-gate 	struct part_info pi;
3487*7c478bd9Sstevel@tonic-gate 	long totsize;
3488*7c478bd9Sstevel@tonic-gate 	int idx = -1;
3489*7c478bd9Sstevel@tonic-gate 
3490*7c478bd9Sstevel@tonic-gate 	/*
3491*7c478bd9Sstevel@tonic-gate 	 *  First try the PARTINFO ioctl.  If it works, we will be able
3492*7c478bd9Sstevel@tonic-gate 	 *  to tell if they've specified the full disk partition by checking
3493*7c478bd9Sstevel@tonic-gate 	 *  to see if they've specified a partition that starts at sector 0.
3494*7c478bd9Sstevel@tonic-gate 	 */
3495*7c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCPARTINFO, &pi) != -1) {
3496*7c478bd9Sstevel@tonic-gate 		if (pi.p_start != 0) {
3497*7c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO,
3498*7c478bd9Sstevel@tonic-gate 			    devname)) {
3499*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
3500*7c478bd9Sstevel@tonic-gate 				exit(1);
3501*7c478bd9Sstevel@tonic-gate 			}
3502*7c478bd9Sstevel@tonic-gate 		}
3503*7c478bd9Sstevel@tonic-gate 	} else {
3504*7c478bd9Sstevel@tonic-gate 		if ((idx = read_vtoc(fd, &v)) < 0) {
3505*7c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_VTOC,
3506*7c478bd9Sstevel@tonic-gate 			    devname)) {
3507*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
3508*7c478bd9Sstevel@tonic-gate 				exit(1);
3509*7c478bd9Sstevel@tonic-gate 			}
3510*7c478bd9Sstevel@tonic-gate 			return;
3511*7c478bd9Sstevel@tonic-gate 		}
3512*7c478bd9Sstevel@tonic-gate 		if (ioctl(fd, DKIOCGGEOM, &d) == -1) {
3513*7c478bd9Sstevel@tonic-gate 			perror(devname);
3514*7c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NO_GEOM,
3515*7c478bd9Sstevel@tonic-gate 			    devname)) {
3516*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
3517*7c478bd9Sstevel@tonic-gate 				exit(1);
3518*7c478bd9Sstevel@tonic-gate 			}
3519*7c478bd9Sstevel@tonic-gate 			return;
3520*7c478bd9Sstevel@tonic-gate 		}
3521*7c478bd9Sstevel@tonic-gate 		totsize = d.dkg_ncyl * d.dkg_nhead * d.dkg_nsect;
3522*7c478bd9Sstevel@tonic-gate 		if (v.v_part[idx].p_size != totsize) {
3523*7c478bd9Sstevel@tonic-gate 			if (!lecture_and_query(FDISK_LECTURE_NOT_FULL,
3524*7c478bd9Sstevel@tonic-gate 			    devname)) {
3525*7c478bd9Sstevel@tonic-gate 				(void) close(fd);
3526*7c478bd9Sstevel@tonic-gate 				exit(1);
3527*7c478bd9Sstevel@tonic-gate 			}
3528*7c478bd9Sstevel@tonic-gate 		}
3529*7c478bd9Sstevel@tonic-gate 	}
3530*7c478bd9Sstevel@tonic-gate }
3531*7c478bd9Sstevel@tonic-gate 
3532*7c478bd9Sstevel@tonic-gate 
3533*7c478bd9Sstevel@tonic-gate /*
3534*7c478bd9Sstevel@tonic-gate  * get_node
3535*7c478bd9Sstevel@tonic-gate  * Called from main to construct the name of the device node to open.
3536*7c478bd9Sstevel@tonic-gate  * Initially tries to stat the node exactly as provided, if that fails
3537*7c478bd9Sstevel@tonic-gate  * we prepend the default path (/dev/rdsk/).
3538*7c478bd9Sstevel@tonic-gate  */
3539*7c478bd9Sstevel@tonic-gate static char *
3540*7c478bd9Sstevel@tonic-gate get_node(char *devname)
3541*7c478bd9Sstevel@tonic-gate {
3542*7c478bd9Sstevel@tonic-gate 	char *node;
3543*7c478bd9Sstevel@tonic-gate 	struct stat statbuf;
3544*7c478bd9Sstevel@tonic-gate 	size_t space;
3545*7c478bd9Sstevel@tonic-gate 
3546*7c478bd9Sstevel@tonic-gate 	/* Don't do anything if we are skipping device checks */
3547*7c478bd9Sstevel@tonic-gate 	if (io_image)
3548*7c478bd9Sstevel@tonic-gate 		return (devname);
3549*7c478bd9Sstevel@tonic-gate 
3550*7c478bd9Sstevel@tonic-gate 	node = devname;
3551*7c478bd9Sstevel@tonic-gate 
3552*7c478bd9Sstevel@tonic-gate 	/* Try the node as provided first */
3553*7c478bd9Sstevel@tonic-gate 	if (stat(node, (struct stat *)&statbuf) == -1) {
3554*7c478bd9Sstevel@tonic-gate 		/*
3555*7c478bd9Sstevel@tonic-gate 		 * Copy the passed in string to a new buffer, prepend the
3556*7c478bd9Sstevel@tonic-gate 		 * default path and try again.
3557*7c478bd9Sstevel@tonic-gate 		 */
3558*7c478bd9Sstevel@tonic-gate 		space = strlen(DEFAULT_PATH) + strlen(devname) + 1;
3559*7c478bd9Sstevel@tonic-gate 
3560*7c478bd9Sstevel@tonic-gate 		if ((node = malloc(space)) == NULL) {
3561*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Unable to obtain memory "
3562*7c478bd9Sstevel@tonic-gate 			    "for device node.\n");
3563*7c478bd9Sstevel@tonic-gate 			exit(1);
3564*7c478bd9Sstevel@tonic-gate 		}
3565*7c478bd9Sstevel@tonic-gate 
3566*7c478bd9Sstevel@tonic-gate 		/* Copy over the default path and the provided node */
3567*7c478bd9Sstevel@tonic-gate 		(void) strncpy(node, DEFAULT_PATH, strlen(DEFAULT_PATH));
3568*7c478bd9Sstevel@tonic-gate 		space -= strlen(DEFAULT_PATH);
3569*7c478bd9Sstevel@tonic-gate 		(void) strlcpy(node + strlen(DEFAULT_PATH), devname, space);
3570*7c478bd9Sstevel@tonic-gate 
3571*7c478bd9Sstevel@tonic-gate 		/* Try to stat it again */
3572*7c478bd9Sstevel@tonic-gate 		if (stat(node, (struct stat *)&statbuf) == -1) {
3573*7c478bd9Sstevel@tonic-gate 			/* Failed all options, give up */
3574*7c478bd9Sstevel@tonic-gate 			fprintf(stderr, "fdisk: Cannot stat device %s.\n",
3575*7c478bd9Sstevel@tonic-gate 			    devname);
3576*7c478bd9Sstevel@tonic-gate 			exit(1);
3577*7c478bd9Sstevel@tonic-gate 		}
3578*7c478bd9Sstevel@tonic-gate 	}
3579*7c478bd9Sstevel@tonic-gate 
3580*7c478bd9Sstevel@tonic-gate 	/* Make sure the device specified is the raw device */
3581*7c478bd9Sstevel@tonic-gate 	if ((statbuf.st_mode & S_IFMT) != S_IFCHR) {
3582*7c478bd9Sstevel@tonic-gate 		fprintf(stderr, "fdisk: %s must be a raw device.\n", node);
3583*7c478bd9Sstevel@tonic-gate 		exit(1);
3584*7c478bd9Sstevel@tonic-gate 	}
3585*7c478bd9Sstevel@tonic-gate 
3586*7c478bd9Sstevel@tonic-gate 	return (node);
3587*7c478bd9Sstevel@tonic-gate }
3588