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