4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T */
28 /* All Rights Reserved */
30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 /* All Rights Reserved */
35 * This program reads the partition table on the specified device and
36 * also reads the drive parameters. The user can perform various
37 * operations from a supplied menu or from the command line. Diagnostic
38 * options are also available.
48 #include <sys/types.h>
50 #include <sys/param.h>
51 #include <sys/systeminfo.h>
52 #include <sys/efi_partition.h>
53 #include <sys/byteorder.h>
54 #include <sys/systeminfo.h>
56 #include <sys/dktp/fdisk.h>
64 #define CLR_SCR "\e[1;1H\e[0J"
65 #define CLR_LIN "\e[0K"
66 #define HOME "\e[1;1H\e[0K\e[2;1H\e[0K\e[3;1H\e[0K\e[4;1H\e[0K\e[5;1H\e[0K" \
67 "\e[6;1H\e[0K\e[7;1H\e[0K\e[8;1H\e[0K\e[9;1H\e[0K\e[10;1H\e[0K\e[1;1H"
68 #define Q_LINE "\e[22;1H\e[0K\e[21;1H\e[0K\e[20;1H\e[0K"
71 #define W_LINE "\e[11;1H\e[0K"
73 #define W_LINE "\e[12;1H\e[0K\e[11;1H\e[0K"
76 #define E_LINE "\e[24;1H\e[0K\e[23;1H\e[0K"
79 #define M_LINE "\e[12;1H\e[0K\e[13;1H\e[0K\e[14;1H\e[0K\e[15;1H\e[0K" \
80 "\e[16;1H\e[0K\e[17;1H\e[0K\e[18;1H\e[0K\e[19;1H\e[0K\e[12;1H"
82 #define M_LINE "\e[13;1H\e[0K\e[14;1H\e[0K\e[15;1H\e[0K\e[16;1H\e[0K\e[17;1H" \
83 "\e[0K\e[18;1H\e[0K\e[19;1H\e[0K\e[13;1H"
86 #define T_LINE "\e[1;1H\e[0K"
88 #define DEFAULT_PATH "/dev/rdsk/"
90 /* XXX - should be in fdisk.h, used by sd as well */
93 * the MAX values are the maximum usable values for BIOS chs values
94 * The MAX_CYL value of 1022 is the maximum usable value
95 * the value of 1023 is a fence value,
96 * indicating no CHS geometry exists for the corresponding LBA value.
97 * HEAD range [ 0 .. MAX_HEAD ], so number of heads is (MAX_HEAD + 1)
98 * SECT range [ 1 .. MAX_SECT ], so number of sectors is (MAX_SECT)
100 #define MAX_SECT (63)
101 #define MAX_CYL (1022)
102 #define MAX_HEAD (254)
104 #define DK_MAX_2TB UINT32_MAX /* Max # of sectors in 2TB */
106 /* for clear_vtoc() */
110 /* readvtoc/writevtoc return codes */
111 #define VTOC_OK 0 /* Good VTOC */
112 #define VTOC_INVAL 1 /* invalid VTOC */
113 #define VTOC_NOTSUP 2 /* operation not supported - EFI label */
114 #define VTOC_RWERR 3 /* couldn't read or write VTOC */
117 * Support for fdisk(1M) on the SPARC platform
118 * In order to convert little endian values to big endian for SPARC,
119 * byte/short and long values must be swapped.
120 * These swapping macros will be used to access information in the
121 * mboot and ipart structures.
125 #define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF))
126 #define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \
127 (les((unsigned)((val)&0xffff0000)>>16)))
129 #define les(val) (val)
130 #define lel(val) (val)
133 #if defined(_SUNOS_VTOC_16)
134 #define VTOC_OFFSET 1
135 #elif defined(_SUNOS_VTOC_8)
136 #define VTOC_OFFSET 0
138 #error No VTOC format defined.
142 #define FDISK_KB (1024)
143 #define FDISK_MB (FDISK_KB * 1024)
144 #define FDISK_GB (FDISK_MB * 1024)
147 #define FDISK_MAX_VALID_PART_ID 255
148 #define FDISK_MAX_VALID_PART_NUM_DIGITS 2
149 #define FDISK_MAX_VALID_PART_ID_DIGITS 3
151 /* Maximum number of digits for a valid partition size */
152 #define FDISK_MAX_VALID_CYL_NUM_DIGITS 10
154 /* Minimum partition size in cylinders */
155 #define FDISK_MIN_PART_SIZE 1
158 static char Usage
[] = "Usage: fdisk\n"
159 "[ -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
160 "[ -b masterboot ]\n"
161 "[ -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect ]\n"
162 "[ -F fdisk_file ] [ -h ] [ -o offset ] [ -P fill_patt ] [ -s size ]\n"
163 "[ -S geom_file ] [ [ -v ] -W { creat_fdisk_file | - } ]\n"
164 "[ -w | r | d | n | I | B | E | g | G | R | t | T ] rdevice";
166 static char Usage1
[] = " Partition options:\n"
167 " -A id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
168 " Create a partition with specific attributes:\n"
169 " id = system id number (fdisk.h) for the partition type\n"
170 " act = active partition flag (0 is off and 128 is on)\n"
171 " bhead = beginning head for start of partition\n"
172 " bsect = beginning sector for start of partition\n"
173 " bcyl = beginning cylinder for start of partition\n"
174 " ehead = ending head for end of partition\n"
175 " esect = ending sector for end of partition\n"
176 " ecyl = ending cylinder for end of partition\n"
177 " rsect = sector number from start of disk for\n"
178 " start of partition\n"
179 " numsect = partition size in sectors\n"
181 " Use master_boot as the master boot file.\n"
182 " -B Create one Solaris partition that uses the entire disk.\n"
183 " -E Create one EFI partition that uses the entire disk.\n"
184 " -D id:act:bhead:bsect:bcyl:ehead:esect:ecyl:rsect:numsect\n"
185 " Delete a partition. See attribute definitions for -A.\n"
187 " Use fdisk_file to initialize on-line fdisk table.\n"
188 " -I Forego device checks. Generate a file image of what would go\n"
189 " on a disk using the geometry specified with the -S option.\n"
190 " -n Do not run in interactive mode.\n"
191 " -R Open the disk device as read-only.\n"
192 " -t Check and adjust VTOC to be consistent with fdisk table.\n"
193 " VTOC slices exceeding the partition size will be truncated.\n"
194 " -T Check and adjust VTOC to be consistent with fdisk table.\n"
195 " VTOC slices exceeding the partition size will be removed.\n"
197 " Write on-disk table to fdisk_file.\n"
198 " -W - Write on-disk table to standard output.\n"
199 " -v Display virtual geometry. Must be used with the -W option.\n"
200 " Diagnostic options:\n"
201 " -d Activate debug information about progress.\n"
202 " -g Write label geometry to standard output:\n"
203 " PCYL number of physical cylinders\n"
204 " NCYL number of usable cylinders\n"
205 " ACYL number of alternate cylinders\n"
206 " BCYL cylinder offset\n"
207 " NHEADS number of heads\n"
208 " NSECTORS number of sectors per track\n"
209 " SECTSIZ size of a sector in bytes\n"
210 " -G Write physical geometry to standard output (see -g).\n"
211 " -h Issue this verbose help message.\n"
213 " Block offset from start of disk (default 0). Ignored if\n"
216 " Fill disk with pattern fill_patt. fill_patt can be decimal or\n"
217 " hexadecimal and is used as number for constant long word\n"
218 " pattern. If fill_patt is \"#\" then pattern of block #\n"
219 " for each block. Pattern is put in each block as long words\n"
220 " and fills each block (see -o and -s).\n"
221 " -r Read from a disk to stdout (see -o and -s).\n"
222 " -s size Number of blocks on which to perform operation (see -o).\n"
224 " Use geom_file to set the label geometry (see -g).\n"
225 " -w Write to a disk from stdin (see -o and -s).";
227 static char Ostr
[] = "Other OS";
228 static char Dstr
[] = "DOS12";
229 static char D16str
[] = "DOS16";
230 static char DDstr
[] = "DOS-DATA";
231 static char EDstr
[] = "EXT-DOS";
232 static char DBstr
[] = "DOS-BIG";
233 static char PCstr
[] = "PCIX";
234 static char Ustr
[] = "UNIX System";
235 static char SUstr
[] = "Solaris";
236 static char SU2str
[] = "Solaris2";
237 static char X86str
[] = "x86 Boot";
238 static char DIAGstr
[] = "Diagnostic";
239 static char IFSstr
[] = "IFS: NTFS";
240 static char AIXstr
[] = "AIX Boot";
241 static char AIXDstr
[] = "AIX Data";
242 static char OS2str
[] = "OS/2 Boot";
243 static char WINstr
[] = "Win95 FAT32";
244 static char EWINstr
[] = "Ext Win95";
245 static char FAT95str
[] = "FAT16 LBA";
246 static char EXTLstr
[] = "EXT LBA";
247 static char LINUXstr
[] = "Linux";
248 static char CPMstr
[] = "CP/M";
249 static char NOV2str
[] = "Netware 286";
250 static char NOVstr
[] = "Netware 3.x+";
251 static char QNXstr
[] = "QNX 4.x";
252 static char QNX2str
[] = "QNX part 2";
253 static char QNX3str
[] = "QNX part 3";
254 static char LINNATstr
[] = "Linux native";
256 static char LINSWAPstr
[] = "Linux swap";
258 static char NTFSVOL1str
[] = "NT volset 1";
259 static char NTFSVOL2str
[] = "NT volset 2";
260 static char BSDstr
[] = "BSD OS";
261 static char NEXTSTEPstr
[] = "NeXTSTEP";
262 static char BSDIFSstr
[] = "BSDI FS";
263 static char BSDISWAPstr
[] = "BSDI swap";
264 static char Actvstr
[] = "Active";
265 static char EFIstr
[] = "EFI";
266 static char NAstr
[] = " ";
268 /* All the user options and flags */
269 static char *Dfltdev
; /* name of fixed disk drive */
271 /* Diagnostic options */
272 static int io_wrt
= 0; /* write stdin to disk (-w) */
273 static int io_rd
= 0; /* read disk and write stdout (-r) */
274 static char *io_fatt
; /* user supplied pattern (-P pattern) */
275 static int io_patt
= 0; /* write pattern to disk (-P pattern) */
276 static int io_lgeom
= 0; /* get label geometry (-g) */
277 static int io_pgeom
= 0; /* get drive physical geometry (-G) */
278 static char *io_sgeom
= 0; /* set label geometry (-S geom_file) */
279 static int io_readonly
= 0; /* do not write to disk (-R) */
281 /* The -o offset and -s size options specify the area of the disk on */
282 /* which to perform the particular operation; i.e., -P, -r, or -w. */
283 static off_t io_offset
= 0; /* offset sector (-o offset) */
284 static off_t io_size
= 0; /* size in sectors (-s size) */
286 /* Partition table flags */
287 static int v_flag
= 0; /* virtual geometry-HBA flag (-v) */
288 static int stdo_flag
= 0; /* stdout flag (-W -) */
289 static int io_fdisk
= 0; /* do fdisk operation */
290 static int io_ifdisk
= 0; /* interactive partition */
291 static int io_nifdisk
= 0; /* non-interactive partition (-n) */
293 static int io_adjt
= 0; /* check/adjust VTOC (truncate (-t)) */
294 static int io_ADJT
= 0; /* check/adjust VTOC (delete (-T)) */
295 static char *io_ffdisk
= 0; /* input fdisk file name (-F file) */
296 static char *io_Wfdisk
= 0; /* output fdisk file name (-W file) */
297 static char *io_Afdisk
= 0; /* add entry to partition table (-A) */
298 static char *io_Dfdisk
= 0; /* delete entry from part. table (-D) */
300 static char *io_mboot
= 0; /* master boot record (-b boot_file) */
302 static struct mboot BootCod
; /* buffer for master boot record */
304 static int io_wholedisk
= 0; /* use whole disk for Solaris (-B) */
305 static int io_EFIdisk
= 0; /* use whole disk for EFI (-E) */
306 static int io_debug
= 0; /* activate verbose mode (-d) */
307 static int io_image
= 0; /* create image using geometry (-I) */
309 static struct mboot
*Bootblk
; /* pointer to cut/paste sector zero */
310 static char *Bootsect
; /* pointer to sector zero buffer */
311 static char *Nullsect
;
312 static struct extvtoc disk_vtoc
; /* verify VTOC table */
313 static int vt_inval
= 0;
314 static int no_virtgeom_ioctl
= 0; /* ioctl for virtual geometry failed */
315 static int no_physgeom_ioctl
= 0; /* ioctl for physical geometry failed */
317 static struct ipart Table
[FD_NUMPART
];
318 static struct ipart Old_Table
[FD_NUMPART
];
319 static int skip_verify
[FD_NUMPART
]; /* special case skip sz chk */
321 /* Disk geometry information */
322 static struct dk_minfo minfo
;
323 static struct dk_geom disk_geom
;
325 static int Dev
; /* fd for open device */
327 static diskaddr_t dev_capacity
; /* number of blocks on device */
328 static diskaddr_t chs_capacity
; /* Numcyl_usable * heads * sectors */
330 static int Numcyl_usable
; /* Number of usable cylinders */
331 /* used to limit fdisk to 2TB */
333 /* Physical geometry for the drive */
334 static int Numcyl
; /* number of cylinders */
335 static int heads
; /* number of heads */
336 static int sectors
; /* number of sectors per track */
337 static int acyl
; /* number of alternate sectors */
339 /* HBA (virtual) geometry for the drive */
340 static int hba_Numcyl
; /* number of cylinders */
341 static int hba_heads
; /* number of heads */
342 static int hba_sectors
; /* number of sectors per track */
344 static int sectsiz
; /* sector size */
346 /* Load functions for fdisk table modification */
347 #define LOADFILE 0 /* load fdisk from file */
348 #define LOADDEL 1 /* delete an fdisk entry */
349 #define LOADADD 2 /* add an fdisk entry */
352 static char s
[CBUFLEN
];
356 * Complete list of all the 255 partition types. Some are unknown types
357 * and some entries are known to be unused.
359 * Courtesy of http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
361 char *fdisk_part_types
[] = {
365 "XENIX /usr", /* 3 */
366 "FAT16 (Upto 32M)", /* 4 */
367 "DOS Extended", /* 5 */
368 "FAT16 (>32M, HUGEDOS)", /* 6 */
370 "AIX Boot/QNX(qny)", /* 8 */
371 "AIX Data/QNX(qnz)", /* 9 */
372 "OS/2 Boot/Coherent swap", /* 10 */
373 "WIN95 FAT32(Upto 2047GB)", /* 11 */
374 "WIN95 FAT32(LBA)", /* 12 */
376 "WIN95 FAT16(LBA)", /* 14 */
377 "WIN95 Extended(LBA)", /* 15 */
379 "Hidden FAT12", /* 17 */
380 "Diagnostic", /* 18 */
382 "Hidden FAT16(Upto 32M)", /* 20 */
384 "Hidden FAT16(>=32M)", /* 22 */
385 "Hidden IFS: HPFS", /* 23 */
386 "AST SmartSleep Partition", /* 24 */
387 "Unused/Willowtech Photon", /* 25 */
389 "Hidden FAT32", /* 27 */
390 "Hidden FAT32(LBA)", /* 28 */
392 "Hidden FAT16(LBA)", /* 30 */
394 "Unused/OSF1", /* 32 */
395 "Reserved/FSo2(Oxygen FS)", /* 33 */
396 "Unused/(Oxygen EXT)", /* 34 */
398 "NEC DOS 3.x", /* 36 */
404 "AtheOS File System", /* 42 */
405 "SyllableSecure", /* 43 */
415 "JFS on OS/2", /* 53 */
418 "THEOS 3.2 2GB", /* 56 */
419 "Plan9/THEOS 4", /* 57 */
420 "THEOS 4 4GB", /* 58 */
421 "THEOS 4 Extended", /* 59 */
422 "PartitionMagic Recovery", /* 60 */
423 "Hidden NetWare", /* 61 */
426 "Venix 80286", /* 64 */
427 "MINIX/PPC PReP Boot", /* 65 */
428 "Win2K Dynamic Disk/SFS(DOS)", /* 66 */
429 "Linux+DRDOS shared", /* 67 */
430 "GoBack partition", /* 68 */
431 "Boot-US boot manager", /* 69 */
432 "EUMEL/Elan", /* 70 */
433 "EUMEL/Elan", /* 71 */
434 "EUMEL/Elan", /* 72 */
436 "ALFS/THIN FS for DOS", /* 74 */
438 "Oberon partition", /* 76 */
440 "QNX 4,x 2nd Part", /* 78 */
441 "QNX 4,x 3rd Part", /* 79 */
442 "OnTrack DM R/O, Lynx RTOS", /* 80 */
443 "OnTrack DM R/W, Novell", /* 81 */
445 "Disk Manager 6.0 Aux3", /* 83 */
446 "Disk Manager 6.0 DDO", /* 84 */
448 "Golden Bow VFeature/AT&T MS-DOS", /* 86 */
454 "Priam EDisk", /* 92 */
459 "SpeedStor", /* 97 */
461 "Unix SysV, Mach, GNU Hurd", /* 99 */
462 "PC-ARMOUR, Netware 286", /* 100 */
463 "Netware 386", /* 101 */
464 "Netware SMS", /* 102 */
467 "Netware NSS", /* 105 */
474 "DiskSecure Multi-Boot", /* 112 */
475 "Reserved", /* 113 */
477 "Reserved", /* 115 */
478 "Scramdisk partition", /* 116 */
479 "IBM PC/IX", /* 117 */
480 "Reserved", /* 118 */
481 "M2FS/M2CS,Netware VNDI", /* 119 */
490 "MINIX until 1.4a", /* 128 */
491 "MINIX since 1.4b, early Linux", /* 129 */
492 "Solaris/Linux swap", /* 130 */
493 "Linux native", /* 131 */
494 "OS/2 hidden,Win Hibernation", /* 132 */
495 "Linux extended", /* 133 */
496 "Old Linux RAID,NT FAT16 RAID", /* 134 */
497 "NTFS volume set", /* 135 */
498 "Linux plaintext part table", /* 136 */
500 "Linux Kernel Partition", /* 138 */
501 "Fault Tolerant FAT32 volume", /* 139 */
502 "Fault Tolerant FAT32 volume", /* 140 */
503 "Free FDISK hidden PDOS FAT12", /* 141 */
504 "Linux LVM partition", /* 142 */
506 "Free FDISK hidden PDOS FAT16", /* 144 */
507 "Free FDISK hidden DOS EXT", /* 145 */
508 "Free FDISK hidden FAT16 Large", /* 146 */
509 "Hidden Linux native, Amoeba", /* 147 */
510 "Amoeba Bad Block Table", /* 148 */
511 "MIT EXOPC Native", /* 149 */
513 "Free FDISK hidden PDOS FAT32", /* 151 */
514 "Free FDISK hidden FAT32 LBA", /* 152 */
515 "DCE376 logical drive", /* 153 */
516 "Free FDISK hidden FAT16 LBA", /* 154 */
517 "Free FDISK hidden DOS EXT", /* 155 */
522 "Laptop hibernation", /* 160 */
523 "Laptop hibernate,HP SpeedStor", /* 161 */
525 "HP SpeedStor", /* 163 */
526 "HP SpeedStor", /* 164 */
527 "BSD/386,386BSD,NetBSD,FreeBSD", /* 165 */
528 "OpenBSD,HP SpeedStor", /* 166 */
529 "NeXTStep", /* 167 */
530 "Mac OS-X", /* 168 */
532 "Olivetti FAT12 1.44MB Service", /* 170 */
533 "Mac OS-X Boot", /* 171 */
536 "ShagOS filesystem", /* 174 */
537 "ShagOS swap", /* 175 */
538 "BootStar Dummy", /* 176 */
539 "HP SpeedStor", /* 177 */
541 "HP SpeedStor", /* 179 */
542 "HP SpeedStor", /* 180 */
544 "Corrupted FAT16 NT Mirror Set", /* 182 */
545 "Corrupted NTFS NT Mirror Set", /* 183 */
546 "Old BSDI BSD/386 swap", /* 184 */
549 "Boot Wizard hidden", /* 187 */
552 "Solaris x86 boot", /* 190 */
553 "Solaris2", /* 191 */
554 "REAL/32 or Novell DOS secured", /* 192 */
555 "DRDOS/secured(FAT12)", /* 193 */
556 "Hidden Linux", /* 194 */
557 "Hidden Linux swap", /* 195 */
558 "DRDOS/secured(FAT16,< 32M)", /* 196 */
559 "DRDOS/secured(Extended)", /* 197 */
560 "NT corrupted FAT16 volume", /* 198 */
561 "NT corrupted NTFS volume", /* 199 */
562 "DRDOS8.0+", /* 200 */
563 "DRDOS8.0+", /* 201 */
564 "DRDOS8.0+", /* 202 */
565 "DRDOS7.04+ secured FAT32(CHS)", /* 203 */
566 "DRDOS7.04+ secured FAT32(LBA)", /* 204 */
567 "CTOS Memdump", /* 205 */
568 "DRDOS7.04+ FAT16X(LBA)", /* 206 */
569 "DRDOS7.04+ secure EXT DOS(LBA)", /* 207 */
570 "REAL/32 secure big, MDOS", /* 208 */
571 "Old MDOS secure FAT12", /* 209 */
574 "Old MDOS secure FAT16 <32M", /* 212 */
575 "Old MDOS secure EXT", /* 213 */
576 "Old MDOS secure FAT16 >=32M", /* 214 */
580 "Non-FS Data", /* 218 */
581 "CP/M,Concurrent DOS,CTOS", /* 219 */
583 "Hidden CTOS memdump", /* 221 */
584 "Dell PowerEdge utilities(FAT)", /* 222 */
585 "DG/UX virtual disk manager", /* 223 */
586 "ST AVFS(STMicroelectronics)", /* 224 */
587 "SpeedStor 12-bit FAT EXT", /* 225 */
589 "SpeedStor", /* 227 */
590 "SpeedStor 16-bit FAT EXT", /* 228 */
591 "Tandy MSDOS", /* 229 */
592 "Storage Dimensions SpeedStor", /* 230 */
597 "BeOS BFS", /* 235 */
598 "SkyOS SkyFS", /* 236 */
600 "EFI Header Indicator", /* 238 */
601 "EFI Filesystem", /* 239 */
602 "Linux/PA-RISC boot loader", /* 240 */
603 "SpeedStor", /* 241 */
604 "DOS 3.3+ secondary", /* 242 */
605 "SpeedStor Reserved", /* 243 */
606 "SpeedStor Large", /* 244 */
607 "Prologue multi-volume", /* 245 */
608 "SpeedStor", /* 246 */
613 "VMware File System", /* 251 */
614 "VMware swap", /* 252 */
615 "Linux raid autodetect", /* 253 */
616 "NT Disk Administrator hidden", /* 254 */
617 "Xenix Bad Block Table" /* 255 */
620 /* Allowed extended partition menu options */
621 static char ext_part_menu_opts
[] = "adhipr";
624 * Structure holding all information about the extended partition
625 * NOTE : As of now, there will be just one instance of ext_part_t, since most
626 * known systems allow only one extended dos partition per disk.
628 static ext_part_t
*epp
;
631 static void update_disk_and_exit(boolean_t table_changed
);
632 int main(int argc
, char *argv
[]);
633 static int read_geom(char *sgeom
);
634 static void dev_mboot_read(void);
635 static void dev_mboot_write(off_t sect
, char *buff
, int bootsiz
);
636 static void mboot_read(void);
637 static void fill_patt(void);
638 static void abs_read(void);
639 static void abs_write(void);
640 static void load(int funct
, char *file
);
641 static void Set_Table_CHS_Values(int ti
);
642 static int nopartdefined();
643 static int insert_tbl(int id
, int act
,
644 int bhead
, int bsect
, int bcyl
,
645 int ehead
, int esect
, int ecyl
,
646 uint32_t rsect
, uint32_t numsect
, int startindex
);
647 static int entry_from_old_table(int id
, int act
,
648 int bhead
, int bsect
, int bcyl
,
649 int ehead
, int esect
, int ecyl
,
650 uint32_t rsect
, uint32_t numsect
, int startindex
);
651 static int verify_tbl(void);
652 static int pars_fdisk(char *line
,
654 int *bhead
, int *bsect
, int *bcyl
,
655 int *ehead
, int *esect
, int *ecyl
,
656 uint32_t *rsect
, uint32_t *numsect
);
657 static int validate_part(int id
, uint32_t rsect
, uint32_t numsect
);
658 static void stage0(void);
659 static int pcreate(void);
660 static int specify(uchar_t tsystid
);
661 static void dispmenu(void);
662 static int pchange(void);
663 static int ppartid(void);
664 static char pdelete(void);
665 static void rm_blanks(char *s
);
666 static int getcyl(void);
667 static void disptbl(void);
668 static void print_Table(void);
669 static void copy_Table_to_Old_Table(void);
670 static void nulltbl(void);
671 static void copy_Bootblk_to_Table(void);
672 static void fill_ipart(char *bootptr
, struct ipart
*partp
);
674 uchar_t
getbyte(char **bp
);
675 uint32_t getlong(char **bp
);
677 static void copy_Table_to_Bootblk(void);
678 static int TableChanged(void);
679 static void ffile_write(char *file
);
680 static void fix_slice(void);
681 static int yesno(void);
682 static int readvtoc(void);
683 static int writevtoc(void);
684 static int efi_ioctl(int fd
, int cmd
, dk_efi_t
*dk_ioc
);
685 static int clear_efi(void);
686 static void clear_vtoc(int table
, int part
);
687 static int lecture_and_query(char *warning
, char *devname
);
688 static void sanity_check_provided_device(char *devname
, int fd
);
689 static char *get_node(char *devname
);
692 static void id_to_name(uchar_t sysid
, char *buffer
);
693 static void ext_read_input(char *buf
);
694 static int ext_read_options(char *buf
);
695 static int ext_invalid_option(char ch
);
696 static void ext_read_valid_part_num(int *pno
);
697 static void ext_read_valid_part_id(uchar_t
*partid
);
698 static int ext_read_valid_partition_start(uint32_t *begsec
);
699 static void ext_read_valid_partition_size(uint32_t begsec
, uint32_t *endsec
);
700 static void ext_part_menu();
701 static void add_logical_drive();
702 static void delete_logical_drive();
703 static void ext_print_help_menu();
704 static void ext_change_logical_drive_id();
705 static void ext_print_part_types();
706 static void ext_print_logical_drive_layout();
707 static void preach_and_continue();
709 static void ext_print_logdrive_layout_debug();
714 * This function is called only during the non-interactive mode.
715 * It is touchy and does not tolerate any errors. If there are
716 * mounted logical drives, changes to the partition table
720 update_disk_and_exit(boolean_t table_changed
)
727 * Copy the new table back to the sector buffer
728 * and write it to disk
730 copy_Table_to_Bootblk();
731 dev_mboot_write(0, Bootsect
, sectsiz
);
734 /* If the VTOC table is wrong fix it (truncation only) */
740 rval
= fdisk_commit_ext_part(epp
);
745 case FDISK_ENOEXTPART
:
749 (void) fprintf(stderr
, "Error in"
750 " fdisk_commit_ext_part\n");
761 * Process command-line options.
764 main(int argc
, char *argv
[])
777 setbuf(stderr
, 0); /* so all output gets out on exit */
780 /* Process the options. */
781 while ((c
= getopt(argc
, argv
, "o:s:P:F:b:A:D:W:S:tTIhwvrndgGRBE"))
786 io_offset
= (off_t
)strtoull(optarg
, 0, 0);
789 io_size
= (off_t
)strtoull(optarg
, 0, 0);
852 * If '-' is the -W argument, then write
853 * to standard output, otherwise write
854 * to the specified file.
856 if (strncmp(optarg
, "-", 1) == 0)
871 (void) fprintf(stderr
, "%s\n", Usage
);
872 (void) fprintf(stderr
, "%s\n", Usage1
);
885 if (io_image
&& io_sgeom
&& diag_cnt
== 1) {
889 /* User option checking */
891 /* By default, run in interactive mode */
892 if (!io_fdisk
&& !diag_cnt
&& !io_nifdisk
) {
896 if (((io_fdisk
|| io_adjt
) && diag_cnt
) || (diag_cnt
> 1)) {
900 /* Was any error detected? */
901 if (errflg
|| argc
== optind
) {
902 (void) fprintf(stderr
, "%s\n", Usage
);
903 (void) fprintf(stderr
,
904 "\nDetailed help is available with the -h option.\n");
909 /* Figure out the correct device node to open */
910 Dfltdev
= get_node(argv
[optind
]);
915 openmode
= O_RDWR
|O_CREAT
;
917 if ((Dev
= open(Dfltdev
, openmode
, 0666)) == -1) {
918 (void) fprintf(stderr
,
919 "fdisk: Cannot open device %s.\n",
924 * not all disk (or disklike) drivers support DKIOCGMEDIAINFO
925 * in that case leave the minfo structure zeroed
927 if (ioctl(Dev
, DKIOCGMEDIAINFO
, &minfo
)) {
928 (void) memset(&minfo
, 0, sizeof (minfo
));
931 /* Get the disk geometry */
933 /* Get disk's HBA (virtual) geometry */
935 if (ioctl(Dev
, DKIOCG_VIRTGEOM
, &disk_geom
)) {
938 * If ioctl isn't implemented on this platform, then
939 * turn off flag to print out virtual geometry (-v),
940 * otherwise use the virtual geometry.
943 if (errno
== ENOTTY
) {
945 no_virtgeom_ioctl
= 1;
946 } else if (errno
== EINVAL
) {
948 * This means that the ioctl exists, but
949 * is invalid for this disk, meaning the
950 * disk doesn't have an HBA geometry
951 * (like, say, it's larger than 8GB).
954 hba_Numcyl
= hba_heads
= hba_sectors
= 0;
956 (void) fprintf(stderr
,
957 "%s: Cannot get virtual disk geometry.\n",
962 /* save virtual geometry values obtained by ioctl */
963 hba_Numcyl
= disk_geom
.dkg_ncyl
;
964 hba_heads
= disk_geom
.dkg_nhead
;
965 hba_sectors
= disk_geom
.dkg_nsect
;
969 if (ioctl(Dev
, DKIOCG_PHYGEOM
, &disk_geom
)) {
970 if (errno
== ENOTTY
) {
971 no_physgeom_ioctl
= 1;
973 (void) fprintf(stderr
,
974 "%s: Cannot get physical disk geometry.\n",
981 * Call DKIOCGGEOM if the ioctls for physical and virtual
982 * geometry fail. Get both from this generic call.
984 if (no_virtgeom_ioctl
&& no_physgeom_ioctl
) {
986 if (ioctl(Dev
, DKIOCGGEOM
, &disk_geom
)) {
987 (void) fprintf(stderr
,
988 "%s: Cannot get disk label geometry.\n",
994 Numcyl
= disk_geom
.dkg_ncyl
;
995 heads
= disk_geom
.dkg_nhead
;
996 sectors
= disk_geom
.dkg_nsect
;
998 if (minfo
.dki_lbsize
!= 0)
999 sectsiz
= minfo
.dki_lbsize
;
1003 acyl
= disk_geom
.dkg_acyl
;
1006 * if hba geometry was not set by DKIOC_VIRTGEOM
1007 * or we got an invalid hba geometry
1008 * then set hba geometry based on max values
1010 if (no_virtgeom_ioctl
||
1011 disk_geom
.dkg_ncyl
== 0 ||
1012 disk_geom
.dkg_nhead
== 0 ||
1013 disk_geom
.dkg_nsect
== 0 ||
1014 disk_geom
.dkg_ncyl
> MAX_CYL
||
1015 disk_geom
.dkg_nhead
> MAX_HEAD
||
1016 disk_geom
.dkg_nsect
> MAX_SECT
) {
1019 * turn off flag to print out virtual geometry (-v)
1022 hba_sectors
= MAX_SECT
;
1023 hba_heads
= MAX_HEAD
+ 1;
1024 hba_Numcyl
= (Numcyl
* heads
* sectors
) /
1025 (hba_sectors
* hba_heads
);
1029 (void) fprintf(stderr
, "Physical Geometry:\n");
1030 (void) fprintf(stderr
,
1031 " cylinders[%d] heads[%d] sectors[%d]\n"
1032 " sector size[%d] blocks[%d] mbytes[%d]\n",
1037 Numcyl
* heads
* sectors
,
1038 (Numcyl
* heads
* sectors
* sectsiz
) / 1048576);
1039 (void) fprintf(stderr
, "Virtual (HBA) Geometry:\n");
1040 (void) fprintf(stderr
,
1041 " cylinders[%d] heads[%d] sectors[%d]\n"
1042 " sector size[%d] blocks[%d] mbytes[%d]\n",
1047 hba_Numcyl
* hba_heads
* hba_sectors
,
1048 (hba_Numcyl
* hba_heads
* hba_sectors
* sectsiz
) /
1053 /* If user has requested a geometry report just do it and exit */
1055 if (ioctl(Dev
, DKIOCGGEOM
, &disk_geom
)) {
1056 (void) fprintf(stderr
,
1057 "%s: Cannot get disk label geometry.\n",
1061 Numcyl
= disk_geom
.dkg_ncyl
;
1062 heads
= disk_geom
.dkg_nhead
;
1063 sectors
= disk_geom
.dkg_nsect
;
1064 if (minfo
.dki_lbsize
!= 0)
1065 sectsiz
= minfo
.dki_lbsize
;
1069 acyl
= disk_geom
.dkg_acyl
;
1070 (void) printf("* Label geometry for device %s\n", Dfltdev
);
1072 "* PCYL NCYL ACYL BCYL NHEAD NSECT"
1074 (void) printf(" %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
1083 } else if (io_pgeom
) {
1084 if (ioctl(Dev
, DKIOCG_PHYGEOM
, &disk_geom
)) {
1085 (void) fprintf(stderr
,
1086 "%s: Cannot get physical disk geometry.\n",
1090 (void) printf("* Physical geometry for device %s\n", Dfltdev
);
1092 "* PCYL NCYL ACYL BCYL NHEAD NSECT"
1094 (void) printf(" %-8d %-8d %-8d %-8d %-5d %-5d %-6d\n",
1099 disk_geom
.dkg_nhead
,
1100 disk_geom
.dkg_nsect
,
1103 } else if (io_sgeom
) {
1104 if (read_geom(io_sgeom
)) {
1106 } else if (!io_image
) {
1112 * some drivers may not support DKIOCGMEDIAINFO
1113 * in that case use CHS
1115 chs_capacity
= (diskaddr_t
)Numcyl
* heads
* sectors
;
1116 dev_capacity
= chs_capacity
;
1117 Numcyl_usable
= Numcyl
;
1119 if (chs_capacity
> DK_MAX_2TB
) {
1121 Numcyl_usable
= DK_MAX_2TB
/ (heads
* sectors
);
1122 chs_capacity
= (diskaddr_t
)Numcyl_usable
* heads
* sectors
;
1125 if (minfo
.dki_capacity
> 0)
1126 dev_capacity
= minfo
.dki_capacity
;
1128 /* Allocate memory to hold three complete sectors */
1129 Bootsect
= (char *)calloc(3 * sectsiz
, 1);
1130 if (Bootsect
== NULL
) {
1131 (void) fprintf(stderr
,
1132 "fdisk: Unable to obtain enough buffer memory"
1138 Nullsect
= Bootsect
+ sectsiz
;
1139 /* Zero out the "NULL" sector */
1140 for (i
= 0; i
< sectsiz
; i
++) {
1144 /* Find out what the user wants done */
1145 if (io_rd
) { /* abs disk read */
1146 abs_read(); /* will not return */
1147 } else if (io_wrt
&& !io_readonly
) {
1148 abs_write(); /* will not return */
1149 } else if (io_patt
&& !io_readonly
) {
1150 fill_patt(); /* will not return */
1154 /* This is the fdisk edit, the real reason for the program. */
1156 sanity_check_provided_device(Dfltdev
, Dev
);
1158 /* Get the new BOOT program in case we write a new fdisk table */
1161 /* Read from disk master boot */
1165 * Verify and copy the device's fdisk table. This will be used
1166 * as the prototype mboot if the device's mboot looks invalid.
1168 Bootblk
= (struct mboot
*)Bootsect
;
1169 copy_Bootblk_to_Table();
1171 /* save away a copy of Table in Old_Table for sensing changes */
1172 copy_Table_to_Old_Table();
1176 * Read extended partition only when the fdisk table is not
1177 * supplied from a file
1180 lf_op_flag
|= FDISK_READ_DISK
;
1182 if ((rval
= libfdisk_init(&epp
, Dfltdev
, &Table
[0], lf_op_flag
))
1186 * FDISK_EBADLOGDRIVE, FDISK_ENOLOGDRIVE and
1187 * FDISK_EBADMAGIC can be considered as
1188 * soft errors and hence we do not exit
1190 case FDISK_EBADLOGDRIVE
:
1192 case FDISK_ENOLOGDRIVE
:
1194 case FDISK_EBADMAGIC
:
1196 case FDISK_ENOVGEOM
:
1197 (void) fprintf(stderr
, "Could not get virtual"
1198 " geometry for this device\n");
1201 case FDISK_ENOPGEOM
:
1202 (void) fprintf(stderr
, "Could not get physical"
1203 " geometry for this device\n");
1206 case FDISK_ENOLGEOM
:
1207 (void) fprintf(stderr
, "Could not get label"
1208 " geometry for this device\n");
1212 perror("Failed to initialise libfdisk.\n");
1219 /* Load fdisk table from specified file (-F fdisk_file) */
1221 /* Load and verify user-specified table parameters */
1222 load(LOADFILE
, io_ffdisk
);
1225 /* Does user want to delete or add an entry? */
1227 load(LOADDEL
, io_Dfdisk
);
1230 load(LOADADD
, io_Afdisk
);
1233 if (!io_ffdisk
&& !io_Afdisk
&& !io_Dfdisk
) {
1234 /* Check if there is no fdisk table */
1235 if (nopartdefined() || io_wholedisk
|| io_EFIdisk
) {
1236 if (io_ifdisk
&& !io_wholedisk
&& !io_EFIdisk
) {
1238 "No fdisk table exists. The default"
1239 " partition for the disk is:\n\n"
1240 " a 100%% \"SOLARIS System\" "
1242 "Type \"y\" to accept the default "
1243 "partition, otherwise type \"n\" to "
1244 "edit the\n partition table.\n");
1246 if (Numcyl
> Numcyl_usable
)
1247 (void) printf("WARNING: Disk is larger"
1248 " than 2TB. Solaris partition will"
1249 " be limited to 2 TB.\n");
1252 /* Edit the partition table as directed */
1253 if (io_wholedisk
||(io_ifdisk
&& yesno())) {
1255 /* Default scenario */
1257 /* now set up UNIX System partition */
1258 Table
[0].bootid
= ACTIVE
;
1259 Table
[0].relsect
= LE_32(heads
* sectors
);
1262 LE_32((ulong_t
)((Numcyl_usable
- 1) *
1265 Table
[0].systid
= SUNIXOS2
; /* Solaris */
1267 /* calculate CHS values for table entry 0 */
1268 Set_Table_CHS_Values(0);
1269 update_disk_and_exit(B_TRUE
);
1270 } else if (io_EFIdisk
) {
1271 /* create an EFI partition for the whole disk */
1273 i
= insert_tbl(EFI_PMBR
, 0, 0, 0, 0, 0, 0, 0, 1,
1274 (dev_capacity
> DK_MAX_2TB
) ? DK_MAX_2TB
:
1275 (dev_capacity
- 1), 0);
1277 (void) fprintf(stderr
,
1278 "Error creating EFI partition\n");
1281 update_disk_and_exit(B_TRUE
);
1286 /* Display complete fdisk table entries for debugging purposes */
1288 (void) fprintf(stderr
, "Partition Table Entry Values:\n");
1291 (void) fprintf(stderr
, "\n");
1292 (void) fprintf(stderr
, "Press Enter to continue.\n");
1293 (void) fgets(s
, sizeof (s
), stdin
);
1297 /* Interactive fdisk mode */
1299 (void) printf(CLR_SCR
);
1303 copy_Bootblk_to_Table();
1308 /* If user wants to write the table to a file, do it */
1310 ffile_write(io_Wfdisk
);
1312 ffile_write((char *)stdout
);
1314 update_disk_and_exit(TableChanged() == 1);
1320 * Read geometry from specified file (-S).
1324 read_geom(char *sgeom
)
1329 /* open the prototype file */
1330 if ((fp
= fopen(sgeom
, "r")) == NULL
) {
1331 (void) fprintf(stderr
, "fdisk: Cannot open file %s.\n",
1336 /* Read a line from the file */
1337 while (fgets(line
, sizeof (line
) - 1, fp
)) {
1338 if (line
[0] == '\0' || line
[0] == '\n' || line
[0] == '*')
1341 line
[strlen(line
)] = '\0';
1342 if (sscanf(line
, "%hu %hu %hu %hu %hu %hu %d",
1343 &disk_geom
.dkg_pcyl
,
1344 &disk_geom
.dkg_ncyl
,
1345 &disk_geom
.dkg_acyl
,
1346 &disk_geom
.dkg_bcyl
,
1347 &disk_geom
.dkg_nhead
,
1348 &disk_geom
.dkg_nsect
,
1350 (void) fprintf(stderr
,
1351 "Syntax error:\n \"%s\".\n",
1357 } /* while (fgets(line, sizeof (line) - 1, fp)) */
1360 if (ioctl(Dev
, DKIOCSGEOM
, &disk_geom
)) {
1361 (void) fprintf(stderr
,
1362 "fdisk: Cannot set label geometry.\n");
1366 Numcyl
= hba_Numcyl
= disk_geom
.dkg_ncyl
;
1367 heads
= hba_heads
= disk_geom
.dkg_nhead
;
1368 sectors
= hba_sectors
= disk_geom
.dkg_nsect
;
1369 acyl
= disk_geom
.dkg_acyl
;
1378 * Read the master boot sector from the device.
1381 dev_mboot_read(void)
1383 if ((ioctl(Dev
, DKIOCGMBOOT
, Bootsect
) < 0) && (errno
!= ENOTTY
)) {
1384 perror("Error in ioctl DKIOCGMBOOT");
1388 if (lseek(Dev
, 0, SEEK_SET
) == -1) {
1389 (void) fprintf(stderr
,
1390 "fdisk: Error seeking to partition table on %s.\n",
1395 if (read(Dev
, Bootsect
, sectsiz
) != sectsiz
) {
1396 (void) fprintf(stderr
,
1397 "fdisk: Error reading partition table from %s.\n",
1406 * Write the master boot sector to the device.
1409 dev_mboot_write(off_t sect
, char *buff
, int bootsiz
)
1411 int new_pt
, old_pt
, error
;
1418 (void) fprintf(stderr
, "About to write fdisk table:\n");
1421 (void) fprintf(stderr
, "Press Enter to continue.\n");
1422 (void) fgets(s
, sizeof (s
), stdin
);
1427 * If the new table has any Solaris partitions and the old
1428 * table does not have an entry that describes it
1429 * exactly then clear the old vtoc (if any).
1431 for (new_pt
= 0; new_pt
< FD_NUMPART
; new_pt
++) {
1433 /* We only care about potential Solaris parts. */
1434 if (Table
[new_pt
].systid
!= SUNIXOS
&&
1435 Table
[new_pt
].systid
!= SUNIXOS2
)
1438 /* Does the old table have an exact entry for the new entry? */
1439 for (old_pt
= 0; old_pt
< FD_NUMPART
; old_pt
++) {
1441 /* We only care about old Solaris partitions. */
1442 if ((Old_Table
[old_pt
].systid
== SUNIXOS
) ||
1443 (Old_Table
[old_pt
].systid
== SUNIXOS2
)) {
1445 /* Is this old one the same as a new one? */
1446 if ((Old_Table
[old_pt
].relsect
==
1447 Table
[new_pt
].relsect
) &&
1448 (Old_Table
[old_pt
].numsect
==
1449 Table
[new_pt
].numsect
))
1454 /* Did a solaris partition change location or size? */
1455 if (old_pt
>= FD_NUMPART
) {
1456 /* Yes clear old vtoc */
1458 (void) fprintf(stderr
,
1459 "Clearing VTOC labels from NEW"
1462 clear_vtoc(NEW
, new_pt
);
1467 /* see if the old table had EFI */
1468 for (old_pt
= 0; old_pt
< FD_NUMPART
; old_pt
++) {
1469 if (Old_Table
[old_pt
].systid
== EFI_PMBR
) {
1474 /* look to see if a EFI partition changed in relsect/numsect */
1475 for (new_pt
= 0; new_pt
< FD_NUMPART
; new_pt
++) {
1476 if (Table
[new_pt
].systid
!= EFI_PMBR
)
1478 for (old_pt
= 0; old_pt
< FD_NUMPART
; old_pt
++) {
1479 if ((Old_Table
[old_pt
].systid
==
1480 Table
[new_pt
].systid
) &&
1481 (Old_Table
[old_pt
].relsect
==
1482 Table
[new_pt
].relsect
) &&
1483 (Old_Table
[old_pt
].numsect
==
1484 Table
[new_pt
].numsect
))
1489 * if EFI partition changed, set the flag to clear
1492 if (old_pt
== FD_NUMPART
&& Table
[new_pt
].begcyl
!= 0) {
1498 /* clear labels if necessary */
1501 (void) fprintf(stderr
, "Clearing EFI labels\n");
1503 if ((error
= clear_efi()) != 0) {
1505 (void) fprintf(stderr
,
1506 "\tError %d clearing EFI labels"
1507 " (probably no EFI labels exist)\n",
1513 if ((ioctl(Dev
, DKIOCSMBOOT
, buff
) == -1) && (errno
!= ENOTTY
)) {
1514 (void) fprintf(stderr
,
1515 "fdisk: Error in ioctl DKIOCSMBOOT on %s.\n",
1521 /* write to disk drive */
1522 if (lseek(Dev
, sect
, SEEK_SET
) == -1) {
1523 (void) fprintf(stderr
,
1524 "fdisk: Error seeking to master boot record on %s.\n",
1528 if (write(Dev
, buff
, bootsiz
) != bootsiz
) {
1529 (void) fprintf(stderr
,
1530 "fdisk: Error writing master boot record to %s.\n",
1538 * Read the prototype boot records from the files.
1546 #if defined(i386) || defined(sparc)
1548 * If the master boot file hasn't been specified, use the
1549 * implementation architecture name to generate the default one.
1551 if (io_mboot
== (char *)0) {
1554 * The mboot file must be delivered on all platforms
1555 * and installed in a non-platform-dependent
1556 * directory; i.e., /usr/lib/fs/ufs.
1558 io_mboot
= "/usr/lib/fs/ufs/mboot";
1561 /* First read in the master boot record */
1563 /* Open the master boot proto file */
1564 if ((mDev
= open(io_mboot
, O_RDONLY
, 0666)) == -1) {
1565 (void) fprintf(stderr
,
1566 "fdisk: Cannot open master boot file %s.\n",
1571 /* Read the master boot program */
1572 if (read(mDev
, &BootCod
, sizeof (struct mboot
)) != sizeof
1574 (void) fprintf(stderr
,
1575 "fdisk: Cannot read master boot file %s.\n",
1580 /* Is this really a master boot record? */
1581 if (LE_16(BootCod
.signature
) != MBB_MAGIC
) {
1582 (void) fprintf(stderr
,
1583 "fdisk: Invalid master boot file %s.\n", io_mboot
);
1584 (void) fprintf(stderr
,
1585 "Bad magic number: is %x, but should be %x.\n",
1586 LE_16(BootCod
.signature
), MBB_MAGIC
);
1592 #error fdisk needs to be ported to new architecture
1595 /* Zero out the partitions part of this record */
1596 part
= (struct ipart
*)BootCod
.parts
;
1597 for (i
= 0; i
< FD_NUMPART
; i
++, part
++) {
1598 (void) memset(part
, 0, sizeof (struct ipart
));
1605 * Fill the disk with user/sector number pattern.
1615 if (strncmp(io_fatt
, "#", 1) != 0) {
1617 io_ipatt
= strtoul(io_fatt
, 0, 0);
1618 buff_ptr
= (int *)Bootsect
;
1619 for (i
= 0; i
< sectsiz
; i
+= 4, buff_ptr
++)
1620 *buff_ptr
= io_ipatt
;
1624 * Fill disk with pattern based on block number.
1625 * Write to the disk at absolute relative block io_offset
1626 * for io_size blocks.
1629 off_ptr
= (off_t
*)Bootsect
;
1631 for (i
= 0; i
< sectsiz
;
1632 i
+= sizeof (off_t
), off_ptr
++)
1633 *off_ptr
= io_offset
;
1635 /* Write the data to disk */
1636 if (lseek(Dev
, (off_t
)(sectsiz
* io_offset
++),
1638 (void) fprintf(stderr
, "fdisk: Error seeking on %s.\n",
1642 if (write(Dev
, Bootsect
, sectsiz
) != sectsiz
) {
1643 (void) fprintf(stderr
, "fdisk: Error writing %s.\n",
1647 } /* while (--io_size); */
1652 * Read from the disk at absolute relative block io_offset for
1653 * io_size blocks. Write the data to standard ouput (-r).
1661 if (lseek(Dev
, (off_t
)(sectsiz
* io_offset
++),
1663 (void) fprintf(stderr
, "fdisk: Error seeking on %s.\n",
1667 if (read(Dev
, Bootsect
, sectsiz
) != sectsiz
) {
1668 (void) fprintf(stderr
, "fdisk: Error reading %s.\n",
1673 /* Write to standard ouptut */
1674 if ((c
= write(1, Bootsect
, (unsigned)sectsiz
)) != sectsiz
) {
1677 (void) fprintf(stderr
,
1678 "fdisk: Output warning: %d of %d"
1679 " characters written.\n",
1683 perror("write error on output file.");
1686 } /* if ((c = write(1, Bootsect, (unsigned)sectsiz)) */
1688 } /* while (--io_size); */
1694 * Read the data from standard input. Write to the disk at
1695 * absolute relative block io_offset for io_size blocks (-w).
1704 /* Read from standard input */
1705 if ((c
= read(0, Bootsect
, (unsigned)sectsiz
)) != sectsiz
) {
1708 (void) fprintf(stderr
,
1709 "fdisk: WARNING: Incomplete read (%d of"
1710 " %d characters read) on input file.\n",
1712 /* Fill pattern to mark partial sector in buf */
1713 for (i
= c
; i
< sectsiz
; ) {
1714 Bootsect
[i
++] = 0x41;
1715 Bootsect
[i
++] = 0x62;
1716 Bootsect
[i
++] = 0x65;
1721 perror("read error on input file.");
1726 /* Write to disk drive */
1727 if (lseek(Dev
, (off_t
)(sectsiz
* io_offset
++),
1729 (void) fprintf(stderr
, "fdisk: Error seeking on %s.\n",
1733 if (write(Dev
, Bootsect
, sectsiz
) != sectsiz
) {
1734 (void) fprintf(stderr
, "fdisk: Error writing %s.\n",
1740 } /* while (--io_size); */
1747 * Load will either read the fdisk table from a file or add or
1748 * delete an entry (-A, -D, -F).
1752 load(int funct
, char *file
)
1770 int ext_part_present
= 0;
1771 uint32_t begsec
, endsec
, relsect
;
1772 logical_drive_t
*temp
;
1773 int part_count
= 0, ldcnt
= 0;
1774 uint32_t ext_beg_sec
;
1775 uint32_t old_ext_beg_sec
= 0, old_ext_num_sec
= 0;
1776 uint32_t new_ext_beg_sec
= 0, new_ext_num_sec
= 0;
1777 int ext_part_inited
= 0;
1786 * Zero out the table before loading it, which will
1787 * force it to be updated on disk later (-F
1792 /* Open the prototype file */
1793 if ((fp
= fopen(file
, "r")) == NULL
) {
1794 (void) fprintf(stderr
,
1795 "fdisk: Cannot open prototype partition file %s.\n",
1800 /* Read a line from the file */
1801 while (fgets(line
, sizeof (line
) - 1, fp
)) {
1802 if (pars_fdisk(line
, &id
, &act
, &bhead
, &bsect
,
1803 &bcyl
, &ehead
, &esect
, &ecyl
, &rsect
, &numsect
)) {
1809 if (fdisk_is_dos_extended((uchar_t
)id
)) {
1810 if (ext_part_present
) {
1811 (void) fprintf(stderr
,
1812 "Extended partition"
1813 " already exists\n");
1814 (void) fprintf(stderr
, "fdisk: Error on"
1815 " entry \"%s\".\n", line
);
1818 ext_part_present
= 1;
1820 * If the existing extended partition's start
1821 * and size matches the new one, do not
1822 * initialize the extended partition EBR
1823 * (Extended Boot Record) because there could
1824 * be existing logical drives.
1826 for (i
= 0; i
< FD_NUMPART
; i
++) {
1827 systid
= Old_Table
[i
].systid
;
1828 if (fdisk_is_dos_extended(systid
)) {
1830 Old_Table
[i
].relsect
;
1832 Old_Table
[i
].numsect
;
1836 new_ext_beg_sec
= rsect
;
1837 new_ext_num_sec
= numsect
;
1838 if ((old_ext_beg_sec
!= new_ext_beg_sec
) ||
1839 (old_ext_num_sec
!= new_ext_num_sec
)) {
1840 (void) fdisk_init_ext_part(epp
,
1841 new_ext_beg_sec
, new_ext_num_sec
);
1842 ext_part_inited
= 1;
1846 if (part_count
> FD_NUMPART
) {
1847 /* This line should be logical drive info */
1848 int offset
= MAX_LOGDRIVE_OFFSET
;
1849 if (!ext_part_present
) {
1850 /* Erroneous input file */
1851 (void) fprintf(stderr
,
1852 "More than 4 primary"
1853 " partitions found in input\n");
1854 (void) fprintf(stderr
, "Exiting...\n");
1863 * If the start and size of the existing
1864 * extended partition matches the new one and
1865 * new logical drives are being defined via
1866 * the input file, initialize the EBR.
1868 if (!ext_part_inited
) {
1869 (void) fdisk_init_ext_part(epp
,
1870 new_ext_beg_sec
, new_ext_num_sec
);
1871 ext_part_inited
= 1;
1874 begsec
= rsect
- offset
;
1876 fdisk_get_logical_drive_count(epp
)) == 0) {
1877 /* Adding the first logical drive */
1879 * Make sure that begsec doesnt wrap
1880 * around. This can happen if rsect is
1883 if (rsect
< offset
) {
1884 (void) fprintf(stderr
,
1886 "63 free sectors required "
1887 "before the beginning of "
1888 "a logical drive.");
1892 * Check if the first logical drive
1893 * is out of order. In that case, do
1894 * not subtract MAX_LOGDRIVE_OFFSET
1895 * from the given start of partition.
1897 if (begsec
!= new_ext_beg_sec
) {
1902 if (ldcnt
>= MAX_EXT_PARTS
) {
1903 (void) fprintf(stderr
,
1904 "\nError : Number of "
1905 "logical drives exceeds limit of "
1906 "%d.\n", MAX_EXT_PARTS
);
1910 if (id
> FDISK_MAX_VALID_PART_ID
) {
1911 (void) fprintf(stderr
,
1912 "Invalid partition ID\n");
1913 (void) fprintf(stderr
, "fdisk: Error on"
1914 " entry \"%s\".\n", line
);
1918 endsec
= rsect
+ numsect
- 1;
1919 if (fdisk_validate_logical_drive(epp
,
1920 begsec
, offset
, numsect
) == 0) {
1921 if (id
== EFI_PMBR
) {
1922 (void) fprintf(stderr
, "EFI "
1923 "partitions not supported "
1928 fdisk_add_logical_drive(epp
, begsec
,
1932 (void) fprintf(stderr
, "fdisk: Error on"
1933 " entry \"%s\".\n", line
);
1940 * Validate the partition. It cannot start at sector
1941 * 0 unless it is UNUSED or already exists
1943 if (validate_part(id
, rsect
, numsect
) < 0) {
1944 (void) fprintf(stderr
,
1945 "fdisk: Error on entry \"%s\".\n",
1950 if ((tmpindex
= entry_from_old_table(id
, act
, bhead
,
1951 bsect
, bcyl
, ehead
, esect
, ecyl
, rsect
, numsect
,
1952 startindex
)) != -1) {
1954 * If we got here it means we copied an
1955 * unmodified entry. So there is no need
1956 * to insert it in the table or do any
1957 * checks against disk size.
1959 * This is a work around on the following
1960 * situation (for IDE disks, at least):
1961 * Different operation systems calculate
1962 * disk size different ways, of which there
1963 * are two main ways.
1965 * The first, rounds the disk size to modulo
1966 * cylinder size (virtual made-up cylinder
1967 * usually based on maximum number of heads
1968 * and sectors in partition table fields).
1969 * Our OS's (for IDE) and most other "Unix"
1970 * type OS's do this.
1972 * The second, uses every single block
1973 * on the disk (to maximize available space).
1974 * Since disk manufactures do not know about
1975 * "virtual cylinders", there are some number
1976 * of blocks that make up a partial cylinder
1977 * at the end of the disk.
1979 * The difference between these two methods
1980 * is where the problem is. When one
1981 * tries to install Solaris/OpenSolaris on
1982 * a disk that has another OS using that
1983 * "partial cylinder", install fails. It fails
1984 * since fdisk thinks its asked to create a
1985 * partition with the -F option that contains
1986 * a partition that runs off the end of the
1989 startindex
= tmpindex
+ 1;
1994 * Find an unused entry to use and put the entry
1997 if ((startindex
= insert_tbl(id
, act
, bhead
, bsect
,
1998 bcyl
, ehead
, esect
, ecyl
, rsect
, numsect
,
2000 (void) fprintf(stderr
,
2001 "fdisk: Error on entry \"%s\".\n",
2006 } /* while (fgets(line, sizeof (line) - 1, fp)) */
2008 if (verify_tbl() < 0) {
2009 (void) fprintf(stderr
,
2010 "fdisk: Cannot create partition table\n");
2019 /* Parse the user-supplied deletion line (-D) */
2020 if (pars_fdisk(file
, &id
, &act
, &bhead
, &bsect
, &bcyl
,
2021 &ehead
, &esect
, &ecyl
, &rsect
, &numsect
)) {
2022 (void) fprintf(stderr
,
2023 "fdisk: Syntax error \"%s\"\n", file
);
2027 /* Find the exact entry in the table */
2028 for (i
= 0; i
< FD_NUMPART
; i
++) {
2029 if (Table
[i
].systid
== id
&&
2030 Table
[i
].bootid
== act
&&
2031 Table
[i
].beghead
== bhead
&&
2032 Table
[i
].begsect
== ((bsect
& 0x3f) |
2033 (uchar_t
)((bcyl
>>2) & 0xc0)) &&
2034 Table
[i
].begcyl
== (uchar_t
)(bcyl
& 0xff) &&
2035 Table
[i
].endhead
== ehead
&&
2036 Table
[i
].endsect
== ((esect
& 0x3f) |
2037 (uchar_t
)((ecyl
>>2) & 0xc0)) &&
2038 Table
[i
].endcyl
== (uchar_t
)(ecyl
& 0xff) &&
2039 Table
[i
].relsect
== LE_32(rsect
) &&
2040 Table
[i
].numsect
== LE_32(numsect
)) {
2042 (void) memset(&Table
[i
], 0,
2043 sizeof (struct ipart
));
2045 if (fdisk_is_dos_extended(id
)) {
2046 (void) fdisk_delete_ext_part(epp
);
2054 ldcnt
= FD_NUMPART
+ 1;
2055 for (temp
= fdisk_get_ld_head(epp
); temp
!= NULL
;
2056 temp
= temp
->next
) {
2057 relsect
= temp
->abs_secnum
+ temp
->logdrive_offset
;
2058 if (temp
->parts
[0].systid
== id
&&
2059 temp
->parts
[0].bootid
== act
&&
2060 temp
->parts
[0].beghead
== bhead
&&
2061 temp
->parts
[0].begsect
== ((bsect
& 0x3f) |
2062 (uchar_t
)((bcyl
>>2) & 0xc0)) &&
2063 temp
->parts
[0].begcyl
== (uchar_t
)(bcyl
& 0xff) &&
2064 temp
->parts
[0].endhead
== ehead
&&
2065 temp
->parts
[0].endsect
== ((esect
& 0x3f) |
2066 (uchar_t
)((ecyl
>>2) & 0xc0)) &&
2067 temp
->parts
[0].endcyl
== (uchar_t
)(ecyl
& 0xff) &&
2068 relsect
== LE_32(rsect
) &&
2069 temp
->parts
[0].numsect
== LE_32(numsect
)) {
2070 fdisk_delete_logical_drive(epp
, ldcnt
);
2077 (void) fprintf(stderr
,
2078 "fdisk: Entry does not match any existing partition:\n"
2086 /* Parse the user-supplied addition line (-A) */
2087 if (pars_fdisk(file
, &id
, &act
, &bhead
, &bsect
, &bcyl
, &ehead
,
2088 &esect
, &ecyl
, &rsect
, &numsect
)) {
2089 (void) fprintf(stderr
,
2090 "fdisk: Syntax error \"%s\"\n", file
);
2094 /* Validate the partition. It cannot start at sector 0 */
2096 (void) fprintf(stderr
,
2097 "fdisk: New partition cannot start at sector 0:\n"
2104 * if the user wishes to add an EFI partition, we need
2105 * more extensive validation. rsect should be 1, and
2106 * numsect should equal the entire disk capacity - 1
2109 if (id
== EFI_PMBR
) {
2111 (void) fprintf(stderr
,
2112 "fdisk: EFI partitions must start at sector"
2113 " 1 (input rsect = %d)\n", rsect
);
2118 if (dev_capacity
> DK_MAX_2TB
) {
2119 if (numsect
!= DK_MAX_2TB
) {
2120 (void) fprintf(stderr
,
2121 "fdisk: EFI partitions must "
2122 "encompass the entire maximum 2 TB "
2123 "(input numsect: %u - max: %llu)\n",
2124 numsect
, (diskaddr_t
)DK_MAX_2TB
);
2127 } else if (numsect
!= dev_capacity
- 1) {
2128 (void) fprintf(stderr
,
2129 "fdisk: EFI partitions must encompass the "
2131 "(input numsect: %u - avail: %llu)\n",
2139 if (id
> FDISK_MAX_VALID_PART_ID
) {
2140 (void) printf("Invalid partition ID\n");
2144 if ((fdisk_ext_part_exists(epp
)) &&
2145 (fdisk_is_dos_extended(id
))) {
2146 (void) fprintf(stderr
,
2147 "Extended partition already exists.\n");
2148 (void) fprintf(stderr
,
2149 "fdisk: Invalid entry could not be "
2150 "inserted:\n \"%s\"\n", file
);
2154 if (fdisk_ext_part_exists(epp
) &&
2155 (rsect
>= (ext_beg_sec
= fdisk_get_ext_beg_sec(epp
))) &&
2156 (rsect
<= (fdisk_get_ext_end_sec(epp
)))) {
2157 int offset
= MAX_LOGDRIVE_OFFSET
;
2160 * Make sure that begsec doesnt wrap around.
2161 * This can happen if rsect is less than offset
2163 if (rsect
< offset
) {
2166 begsec
= rsect
- offset
;
2167 if ((ldcnt
= fdisk_get_logical_drive_count(epp
)) == 0) {
2169 * Adding the first logical drive
2170 * Check if the first logical drive
2171 * is out of order. In that case, do
2172 * not subtract MAX_LOGDRIVE_OFFSET
2173 * from the given start of partition.
2175 if (begsec
!= ext_beg_sec
) {
2181 if (ldcnt
>= MAX_EXT_PARTS
) {
2182 (void) printf("\nNumber of logical drives "
2183 "exceeds limit of %d.\n", MAX_EXT_PARTS
);
2184 (void) printf("Failing further additions.\n");
2189 (void) fprintf(stderr
,
2190 "fdisk: Partition size cannot be zero:\n"
2195 endsec
= rsect
+ numsect
- 1;
2196 if (fdisk_validate_logical_drive(epp
, begsec
,
2197 offset
, numsect
) == 0) {
2198 /* Valid logical drive */
2199 fdisk_add_logical_drive(epp
, begsec
, endsec
,
2203 (void) fprintf(stderr
,
2204 "fdisk: Invalid entry could not be "
2205 "inserted:\n \"%s\"\n", file
);
2211 /* Find unused entry for use and put entry in table */
2212 if (insert_tbl(id
, act
, bhead
, bsect
, bcyl
, ehead
, esect
,
2213 ecyl
, rsect
, numsect
, 0) < 0) {
2214 (void) fprintf(stderr
,
2215 "fdisk: Invalid entry could not be inserted:\n"
2221 /* Make sure new entry does not overlap existing entry */
2222 if (verify_tbl() < 0) {
2223 (void) fprintf(stderr
,
2224 "fdisk: Cannot create partition \"%s\"\n", file
);
2227 } /* switch funct */
2231 * Set_Table_CHS_Values
2233 * This will calculate the CHS values for beginning and ending CHS
2234 * for a single partition table entry (ti) based on the relsect
2235 * and numsect values contained in the partion table entry.
2237 * hba_heads and hba_sectors contain the number of heads and sectors.
2239 * If the number of cylinders exceeds the MAX_CYL,
2240 * then maximum values will be placed in the corresponding chs entry.
2243 Set_Table_CHS_Values(int ti
)
2245 uint32_t lba
, cy
, hd
, sc
;
2247 lba
= (uint32_t)Table
[ti
].relsect
;
2248 if (lba
>= hba_heads
* hba_sectors
* MAX_CYL
) {
2250 * the lba address cannot be expressed in CHS value
2251 * so store the maximum CHS field values in the CHS fields.
2257 cy
= lba
/ hba_sectors
/ hba_heads
;
2258 hd
= lba
/ hba_sectors
% hba_heads
;
2259 sc
= lba
% hba_sectors
+ 1;
2261 Table
[ti
].begcyl
= cy
& 0xff;
2262 Table
[ti
].beghead
= (uchar_t
)hd
;
2263 Table
[ti
].begsect
= (uchar_t
)(((cy
>> 2) & 0xc0) | sc
);
2266 * This code is identical to the code above
2267 * except that it works on ending CHS values
2269 lba
= (uint32_t)(Table
[ti
].relsect
+ Table
[ti
].numsect
- 1);
2270 if (lba
>= hba_heads
* hba_sectors
* MAX_CYL
) {
2275 cy
= lba
/ hba_sectors
/ hba_heads
;
2276 hd
= lba
/ hba_sectors
% hba_heads
;
2277 sc
= lba
% hba_sectors
+ 1;
2279 Table
[ti
].endcyl
= cy
& 0xff;
2280 Table
[ti
].endhead
= (uchar_t
)hd
;
2281 Table
[ti
].endsect
= (uchar_t
)(((cy
>> 2) & 0xc0) | sc
);
2286 * Insert entry into fdisk table. Check all user-supplied values
2287 * for the entry, but not the validity relative to other table
2293 int bhead
, int bsect
, int bcyl
,
2294 int ehead
, int esect
, int ecyl
,
2295 uint32_t rsect
, uint32_t numsect
, int startindex
)
2299 /* validate partition size */
2300 if (((diskaddr_t
)rsect
+ numsect
) > dev_capacity
) {
2301 (void) fprintf(stderr
,
2302 "fdisk: Partition table exceeds the size of the disk.\n");
2307 /* find UNUSED partition table entry */
2308 for (i
= startindex
; i
< FD_NUMPART
; i
++) {
2309 if (Table
[i
].systid
== UNUSED
) {
2313 if (i
>= FD_NUMPART
) {
2314 (void) fprintf(stderr
, "fdisk: Partition table is full.\n");
2319 Table
[i
].systid
= (uchar_t
)id
;
2320 Table
[i
].bootid
= (uchar_t
)act
;
2321 Table
[i
].numsect
= LE_32(numsect
);
2322 Table
[i
].relsect
= LE_32(rsect
);
2325 (void) memset(&Table
[i
], 0, sizeof (struct ipart
));
2326 } else if (0 < bsect
&& bsect
<= MAX_SECT
&&
2327 0 <= bhead
&& bhead
<= MAX_HEAD
&&
2328 0 < esect
&& esect
<= MAX_SECT
&&
2329 0 <= ehead
&& ehead
<= MAX_HEAD
) {
2332 * If we have been called with a valid geometry, use it
2333 * valid means non-zero values that fit in the BIOS fields
2339 Table
[i
].begcyl
= bcyl
& 0xff;
2340 Table
[i
].endcyl
= ecyl
& 0xff;
2341 Table
[i
].beghead
= (uchar_t
)bhead
;
2342 Table
[i
].endhead
= (uchar_t
)ehead
;
2343 Table
[i
].begsect
= (uchar_t
)(((bcyl
>> 2) & 0xc0) | bsect
);
2344 Table
[i
].endsect
= ((ecyl
>> 2) & 0xc0) | esect
;
2348 * The specified values are invalid,
2349 * so calculate the values based on hba_heads, hba_sectors
2351 Set_Table_CHS_Values(i
);
2355 * return partition index
2361 * entry_from_old_table
2362 * If the specified entry is in the old table and is not a Solaris entry
2363 * then insert same entry into new fdisk table. If we do this then
2364 * all checks are skipped for that entry!
2367 entry_from_old_table(
2369 int bhead
, int bsect
, int bcyl
,
2370 int ehead
, int esect
, int ecyl
,
2371 uint32_t rsect
, uint32_t numsect
, int startindex
)
2375 if (id
== SUNIXOS
|| id
== SUNIXOS2
|| id
== UNUSED
)
2377 for (i
= 0; i
< FD_NUMPART
; i
++) {
2378 if (Old_Table
[i
].systid
== id
&&
2379 Old_Table
[i
].bootid
== act
&&
2380 Old_Table
[i
].beghead
== bhead
&&
2381 Old_Table
[i
].begsect
== ((bsect
& 0x3f) |
2382 (uchar_t
)((bcyl
>>2) & 0xc0)) &&
2383 Old_Table
[i
].begcyl
== (uchar_t
)(bcyl
& 0xff) &&
2384 Old_Table
[i
].endhead
== ehead
&&
2385 Old_Table
[i
].endsect
== ((esect
& 0x3f) |
2386 (uchar_t
)((ecyl
>>2) & 0xc0)) &&
2387 Old_Table
[i
].endcyl
== (uchar_t
)(ecyl
& 0xff) &&
2388 Old_Table
[i
].relsect
== lel(rsect
) &&
2389 Old_Table
[i
].numsect
== lel(numsect
)) {
2390 /* find UNUSED partition table entry */
2391 for (j
= startindex
; j
< FD_NUMPART
; j
++) {
2392 if (Table
[j
].systid
== UNUSED
) {
2393 (void) memcpy(&Table
[j
], &Old_Table
[i
],
2409 * Verify that no partition entries overlap or exceed the size of
2415 uint32_t i
, j
, rsect
, numsect
;
2416 int noMoreParts
= 0;
2419 /* Make sure new entry does not overlap an existing entry */
2420 for (i
= 0; i
< FD_NUMPART
- 1; i
++) {
2421 if (Table
[i
].systid
!= UNUSED
) {
2424 * No valid partitions allowed after EFI_PMBR part
2430 if (Table
[i
].systid
== EFI_PMBR
) {
2432 * EFI_PMBR partition must be the only
2437 if (Table
[i
].relsect
!= 1) {
2438 (void) fprintf(stderr
, "ERROR: "
2439 "Invalid starting sector "
2440 "for EFI_PMBR partition:\n"
2448 if (Table
[i
].numsect
!=
2449 ((dev_capacity
> DK_MAX_2TB
) ? DK_MAX_2TB
:
2450 (dev_capacity
- 1))) {
2452 (void) fprintf(stderr
, "ERROR: "
2453 "EFI_PMBR partition must "
2454 "encompass the entire");
2456 if (dev_capacity
> DK_MAX_2TB
)
2457 (void) fprintf(stderr
,
2462 (diskaddr_t
)DK_MAX_2TB
);
2465 (void) fprintf(stderr
,
2466 "disk.\n numsect %u - "
2475 /* make sure the partition isn't larger than the disk */
2476 rsect
= LE_32(Table
[i
].relsect
);
2477 numsect
= LE_32(Table
[i
].numsect
);
2479 if ((((diskaddr_t
)rsect
+ numsect
) > dev_capacity
) ||
2480 (((diskaddr_t
)rsect
+ numsect
) > DK_MAX_2TB
)) {
2481 if (!skip_verify
[i
])
2485 for (j
= i
+ 1; j
< FD_NUMPART
; j
++) {
2486 if (Table
[j
].systid
!= UNUSED
) {
2487 uint32_t t_relsect
=
2488 LE_32(Table
[j
].relsect
);
2489 uint32_t t_numsect
=
2490 LE_32(Table
[j
].numsect
);
2493 (void) fprintf(stderr
,
2494 "Cannot add partition to "
2495 "table; no more partitions "
2499 (void) fprintf(stderr
,
2533 (t_relsect
+ t_numsect
)) ||
2534 ((rsect
+ numsect
) <= t_relsect
)) {
2537 (void) fprintf(stderr
, "ERROR: "
2538 "current partition overlaps"
2539 " following partition\n");
2547 if (Table
[i
].systid
!= UNUSED
) {
2550 if (!skip_verify
[i
] &&
2551 ((((diskaddr_t
)lel(Table
[i
].relsect
) +
2552 lel(Table
[i
].numsect
)) > dev_capacity
) ||
2553 (((diskaddr_t
)lel(Table
[i
].relsect
) +
2554 lel(Table
[i
].numsect
)) > DK_MAX_2TB
))) {
2564 * Parse user-supplied data to set up fdisk partitions
2571 int *bhead
, int *bsect
, int *bcyl
,
2572 int *ehead
, int *esect
, int *ecyl
,
2573 uint32_t *rsect
, uint32_t *numsect
)
2580 if (line
[0] == '\0' || line
[0] == '\n' || line
[0] == '*')
2582 line
[strlen(line
)] = '\0';
2583 for (i
= 0; i
< strlen(line
); i
++) {
2584 if (line
[i
] == '\0') {
2586 } else if (line
[i
] == ':') {
2590 (void) strncpy(buf
, line
, 256);
2592 tok
= strtok(buf
, ": \t\n");
2593 while (tok
!= NULL
) {
2594 for (p
= tok
; *p
!= '\0'; p
++) {
2596 (void) printf("Invalid input %s in line %s.\n",
2602 test
= strtoll(tok
, (char **)NULL
, 10);
2603 if ((test
< 0) || (test
> 0xFFFFFFFF) || (errno
!= 0)) {
2604 (void) printf("Invalid input %s in line %s.\n", tok
,
2608 tok
= strtok(NULL
, ": \t\n");
2610 if (sscanf(line
, "%d %d %d %d %d %d %d %d %u %u",
2611 id
, act
, bhead
, bsect
, bcyl
, ehead
, esect
, ecyl
,
2612 rsect
, numsect
) != 10) {
2613 (void) fprintf(stderr
, "Syntax error:\n \"%s\".\n", line
);
2621 * Validate that a new partition does not start at sector 0. Only UNUSED
2622 * partitions and previously existing partitions are allowed to start at 0.
2625 validate_part(int id
, uint32_t rsect
, uint32_t numsect
)
2628 if ((id
!= UNUSED
) && (rsect
== 0)) {
2629 for (i
= 0; i
< FD_NUMPART
; i
++) {
2630 if ((Old_Table
[i
].systid
== id
) &&
2631 (Old_Table
[i
].relsect
== LE_32(rsect
)) &&
2632 (Old_Table
[i
].numsect
== LE_32(numsect
)))
2635 (void) fprintf(stderr
,
2636 "New partition cannot start at sector 0\n");
2640 if (id
> FDISK_MAX_VALID_PART_ID
) {
2641 (void) fprintf(stderr
, "Invalid partition ID\n");
2650 * Print out interactive menu and process user input.
2660 (void) printf(Q_LINE
);
2661 (void) printf("Enter Selection: ");
2662 (void) fgets(s
, sizeof (s
), stdin
);
2665 while (!((s
[0] > '0') && (s
[0] < '8') &&
2666 ((s
[1] == '\0') || (s
[1] == '\n')))) {
2668 while (!((s
[0] > '0') && (s
[0] < '7') &&
2669 ((s
[1] == '\0') || (s
[1] == '\n')))) {
2671 (void) printf(E_LINE
); /* Clear any previous error */
2674 "\aEnter a one-digit number between 1 and 7.");
2677 "\aEnter a one-digit number between 1 and 6.");
2679 (void) printf(Q_LINE
);
2680 (void) printf("Enter Selection: ");
2681 (void) fgets(s
, sizeof (s
), stdin
);
2684 (void) printf(E_LINE
);
2687 if (pcreate() == -1)
2691 if (pchange() == -1)
2695 if (pdelete() == -1)
2699 if (ppartid() == -1)
2704 if (fdisk_ext_part_exists(epp
)) {
2707 (void) printf(Q_LINE
);
2708 (void) printf("\nNo extended partition"
2710 (void) printf("Press enter to "
2716 /* update disk partition table, if changed */
2717 if (TableChanged() == 1) {
2718 copy_Table_to_Bootblk();
2719 dev_mboot_write(0, Bootsect
, sectsiz
);
2723 * If the VTOC table is wrong fix it
2730 rval
= fdisk_commit_ext_part(epp
);
2735 case FDISK_ENOEXTPART
:
2738 case FDISK_EMOUNTED
:
2739 (void) printf(Q_LINE
);
2740 preach_and_continue();
2743 perror("Commit failed");
2746 libfdisk_fini(&epp
);
2753 /* update disk partition table, if changed */
2754 if (TableChanged() == 1) {
2755 copy_Table_to_Bootblk();
2756 dev_mboot_write(0, Bootsect
, sectsiz
);
2759 * If the VTOC table is wrong fix it
2775 * If the VTOC table is wrong fix it
2787 copy_Table_to_Bootblk();
2795 * Create partition entry in the table (interactive mode).
2800 uchar_t tsystid
= 'z';
2805 int ext_part_present
= 0;
2810 if (i
== FD_NUMPART
) {
2811 (void) printf(E_LINE
);
2813 "\aThe partition table is full!\n"
2814 "You must delete a partition before creating"
2818 if (Table
[i
].systid
== UNUSED
) {
2825 for (i
= 0; i
< FD_NUMPART
; i
++) {
2826 if (Table
[i
].systid
!= UNUSED
) {
2827 numsect
+= LE_32(Table
[i
].numsect
);
2830 /* Check if an extended partition already exists */
2831 if (fdisk_is_dos_extended(Table
[i
].systid
)) {
2832 ext_part_present
= 1;
2835 if (numsect
>= chs_capacity
) {
2836 (void) printf(E_LINE
);
2837 (void) printf("\aThere is no more room on the disk for"
2838 " another partition.\n");
2840 "You must delete a partition before creating"
2845 while (tsystid
== 'z') {
2848 * The question here is expanding to more than what is
2849 * allocated for question lines (Q_LINE) which garbles
2850 * at least warning line. Clearing warning line as workaround
2854 (void) printf(W_LINE
);
2855 (void) printf(Q_LINE
);
2857 "Select the partition type to create:\n"
2858 " 1=SOLARIS2 2=UNIX 3=PCIXOS 4=Other\n"
2859 " 5=DOS12 6=DOS16 7=DOSEXT 8=DOSBIG\n"
2860 " 9=DOS16LBA A=x86 Boot B=Diagnostic C=FAT32\n"
2861 " D=FAT32LBA E=DOSEXTLBA F=EFI 0=Exit? ");
2862 (void) fgets(s
, sizeof (s
), stdin
);
2864 if ((s
[1] != '\0') && (s
[1] != '\n')) {
2865 (void) printf(E_LINE
);
2866 (void) printf("Invalid selection, try again.");
2870 case '0': /* exit */
2871 (void) printf(E_LINE
);
2873 case '1': /* Solaris partition */
2876 case '2': /* UNIX partition */
2879 case '3': /* PCIXOS partition */
2882 case '4': /* OTHEROS System partition */
2886 tsystid
= DOSOS12
; /* DOS 12 bit fat */
2889 tsystid
= DOSOS16
; /* DOS 16 bit fat */
2893 if (ext_part_present
) {
2894 (void) printf(Q_LINE
);
2895 (void) printf(E_LINE
);
2896 (void) fprintf(stderr
,
2897 "Extended partition already exists\n");
2898 (void) fprintf(stderr
,
2899 "Press enter to continue\n");
2910 tsystid
= FDISK_FAT95
; /* FAT16, need extended int13 */
2912 case 'a': /* x86 Boot partition */
2916 case 'b': /* Diagnostic boot partition */
2920 case 'c': /* FAT32 */
2922 tsystid
= FDISK_WINDOWS
;
2924 case 'd': /* FAT32 and need extended int13 */
2926 tsystid
= FDISK_EXT_WIN
;
2928 case 'e': /* Extended partition, need extended int13 */
2931 if (ext_part_present
) {
2932 (void) printf(Q_LINE
);
2933 (void) printf(E_LINE
);
2934 (void) fprintf(stderr
,
2935 "Extended partition already exists\n");
2936 (void) fprintf(stderr
,
2937 "Press enter to continue\n");
2942 tsystid
= FDISK_EXTLBA
;
2949 (void) printf(E_LINE
);
2950 (void) printf("Invalid selection, try again.");
2955 (void) printf(E_LINE
);
2957 if (tsystid
!= EFI_PMBR
) {
2958 (void) printf(W_LINE
);
2959 if ((dev_capacity
> DK_MAX_2TB
))
2960 (void) printf("WARNING: Disk is larger than 2 TB. "
2961 "Upper limit is 2 TB for non-EFI partition ID\n");
2963 /* create the new partition */
2964 i
= specify(tsystid
);
2967 /* see if it should be the active partition */
2968 (void) printf(E_LINE
);
2969 (void) printf(Q_LINE
);
2972 "Should this become the active partition? If "
2973 "yes, it will be activated\n"
2974 "each time the computer is reset or turned on.\n"
2975 "Please type \"y\" or \"n\". ");
2978 (void) printf(E_LINE
);
2979 for (j
= 0; j
< FD_NUMPART
; j
++) {
2981 Table
[j
].bootid
= ACTIVE
;
2982 (void) printf(E_LINE
);
2984 "Partition %d is now "
2985 "the active partition.",
2988 Table
[j
].bootid
= 0;
2992 Table
[i
].bootid
= 0;
2997 * If partition created is an extended partition, null
2998 * out the first sector of the first cylinder of the
2999 * extended partition
3001 if (fdisk_is_dos_extended(Table
[i
].systid
)) {
3002 (void) fdisk_init_ext_part(epp
,
3003 LE_32(Table
[i
].relsect
),
3004 LE_32(Table
[i
].numsect
));
3007 /* set up the return code */
3012 * partitions of type EFI_PMBR must be the only partitions in
3015 * First, make sure there were no errors the table is
3018 retCode
= verify_tbl();
3021 (void) fprintf(stderr
,
3022 "fdisk: Cannot create EFI partition table; \n"
3023 "current partition table is invalid.\n");
3025 } else if (retCode
> 0) {
3027 "An EFI partition must be the only partition on "
3028 "disk. You may manually delete existing\n"
3029 "partitions, or fdisk can do it.\n"
3030 "Do you want fdisk to destroy existing "
3032 "Please type \"y\" or \"n\". ");
3041 /* create the table entry - i should be 0 */
3042 i
= insert_tbl(tsystid
, 0, 0, 0, 0, 0, 0, 0, 1,
3043 (dev_capacity
> DK_MAX_2TB
) ? DK_MAX_2TB
:
3044 (dev_capacity
- 1), 0);
3047 (void) printf("Error creating EFI partition!!!\n");
3051 /* EFI partitions are currently never active */
3052 Table
[i
].bootid
= 0;
3054 /* set up the return code */
3064 * Query the user to specify the size of the new partition in
3065 * terms of percentage of the disk or by specifying the starting
3066 * cylinder and length in cylinders.
3069 specify(uchar_t tsystid
)
3071 int i
, j
, percent
= -1;
3073 diskaddr_t first_free
, size_free
;
3074 diskaddr_t max_free
;
3076 struct ipart
*partition
[FD_NUMPART
];
3077 struct ipart localpart
[FD_NUMPART
];
3079 cyl_size
= heads
* sectors
;
3082 * make a local copy of the partition table
3083 * and sort it into relsect order
3087 for (i
= 0, j
= 0; i
< FD_NUMPART
; i
++) {
3088 if (Table
[i
].systid
!= UNUSED
) {
3089 localpart
[j
] = Table
[i
];
3094 while (j
< FD_NUMPART
) {
3095 (void) memset(&localpart
[j
], 0, sizeof (struct ipart
));
3099 for (i
= 0; i
< FD_NUMPART
; i
++)
3100 partition
[i
] = &localpart
[i
];
3102 for (i
= 0; i
< FD_NUMPART
- 1; i
++) {
3103 if (partition
[i
]->systid
== UNUSED
)
3105 for (j
= i
+ 1; j
< FD_NUMPART
; j
++) {
3106 if (partition
[j
]->systid
== UNUSED
)
3108 if (LE_32(partition
[j
]->relsect
) <
3109 LE_32(partition
[i
]->relsect
)) {
3110 struct ipart
*temp
= partition
[i
];
3111 partition
[i
] = partition
[j
];
3112 partition
[j
] = temp
;
3118 (void) printf(Q_LINE
);
3120 "Specify the percentage of disk to use for this partition\n"
3121 "(or type \"c\" to specify the size in cylinders). ");
3122 (void) fgets(s
, sizeof (s
), stdin
);
3124 if (s
[0] != 'c') { /* Specify size in percentage of disk */
3126 while ((s
[i
] != '\0') && (s
[i
] != '\n')) {
3127 if (s
[i
] < '0' || s
[i
] > '9') {
3128 (void) printf(E_LINE
);
3129 (void) printf("\aInvalid percentage value "
3130 "specified; retry the operation.");
3135 (void) printf(E_LINE
);
3136 (void) printf("\aInvalid percentage value "
3137 "specified; retry the operation.");
3141 if ((percent
= atoi(s
)) > 100) {
3142 (void) printf(E_LINE
);
3144 "\aPercentage value is too large. The value must be"
3145 " between 1 and 100;\nretry the operation.\n");
3149 (void) printf(E_LINE
);
3151 "\aPercentage value is too small. The value must be"
3152 " between 1 and 100;\nretry the operation.\n");
3157 cylen
= Numcyl_usable
- 1;
3159 cylen
= (Numcyl_usable
* percent
) / 100;
3161 /* Verify DOS12 partition doesn't exceed max size of 32MB. */
3162 if ((tsystid
== DOSOS12
) &&
3163 ((long)((long)cylen
* cyl_size
) > MAXDOS
)) {
3165 n
= MAXDOS
* 100 / (int)(cyl_size
) / Numcyl_usable
;
3166 (void) printf(E_LINE
);
3167 (void) printf("\aMaximum size for a DOS partition "
3168 "is %d%%; retry the operation.",
3169 n
<= 100 ? n
: 100);
3175 for (i
= 0; i
< FD_NUMPART
; i
++) {
3178 * check for free space before partition i
3179 * where i varies from 0 to 3
3181 * freespace after partition 3 is unusable
3182 * because there are no free partitions
3184 * freespace begins at the end of previous partition
3188 /* Not an empty table */
3189 first_free
= LE_32(partition
[i
- 1]->relsect
) +
3190 LE_32(partition
[i
- 1]->numsect
);
3192 first_free
= cyl_size
;
3196 * freespace ends before the current partition
3197 * or the end of the disk (chs end)
3199 if (partition
[i
]->systid
== UNUSED
) {
3200 size_free
= chs_capacity
- first_free
;
3203 * Partition might start before cylinder 1.
3204 * Make sure free space is not negative.
3207 (LE_32(partition
[i
]->relsect
> first_free
))
3208 ? (LE_32(partition
[i
]->relsect
) -
3212 /* save largest free space */
3213 if (max_free
< size_free
)
3214 max_free
= size_free
;
3216 if (((uint64_t)cylen
* cyl_size
) <= size_free
) {
3217 /* We found a place to use */
3220 if (partition
[i
]->systid
== UNUSED
) {
3221 (void) printf(E_LINE
);
3222 max_free
/= (cyl_size
);
3223 (void) fprintf(stderr
, "fdisk: "
3224 "Maximum percentage available is %lld\n",
3225 100 * max_free
/ Numcyl_usable
);
3230 (void) printf(E_LINE
);
3231 if (i
>= FD_NUMPART
) {
3232 (void) fprintf(stderr
,
3233 "fdisk: Partition table is full.\n");
3237 if ((i
= insert_tbl(tsystid
, 0, 0, 0, 0, 0, 0, 0,
3238 first_free
, cylen
* cyl_size
, 0)) >= 0) {
3244 /* Specifying size in cylinders */
3245 (void) printf(E_LINE
);
3246 (void) printf(Q_LINE
);
3247 (void) printf("Enter starting cylinder number: ");
3248 if ((cyl
= getcyl()) == -1) {
3249 (void) printf(E_LINE
);
3250 (void) printf("Invalid number; retry the operation.");
3254 (void) printf(E_LINE
);
3256 "\aNew partition cannot start at cylinder 0.\n");
3261 if (cyl
>= Numcyl_usable
) {
3262 (void) printf(E_LINE
);
3264 "\aCylinder %d is out of bounds, "
3265 "the maximum is %d.\n",
3266 cyl
, Numcyl_usable
- 1);
3270 (void) printf(Q_LINE
);
3271 (void) printf("Enter partition size in cylinders: ");
3272 if ((cylen
= getcyl()) == -1) {
3273 (void) printf(E_LINE
);
3274 (void) printf("Invalid number, retry the operation.");
3278 for (i
= 0; i
< FD_NUMPART
; i
++) {
3279 uint32_t t_relsect
, t_numsect
;
3281 if (partition
[i
]->systid
== UNUSED
)
3283 t_relsect
= LE_32(partition
[i
]->relsect
);
3284 t_numsect
= LE_32(partition
[i
]->numsect
);
3286 if (cyl
* cyl_size
>= t_relsect
&&
3287 cyl
* cyl_size
< t_relsect
+ t_numsect
) {
3288 (void) printf(E_LINE
);
3290 "Cylinder %d is already allocated"
3291 "\nretry the operation.",
3296 if (cyl
* cyl_size
< t_relsect
&&
3297 (cyl
+ cylen
- 1) * cyl_size
> t_relsect
) {
3298 (void) printf(E_LINE
);
3300 "Maximum size for partition is %u cylinders"
3301 "\nretry the operation.",
3302 (t_relsect
- cyl
* cyl_size
) / cyl_size
);
3307 /* Verify partition doesn't exceed disk size or 2 TB */
3308 if (cyl
+ cylen
> Numcyl_usable
) {
3309 (void) printf(E_LINE
);
3310 if (Numcyl
> Numcyl_usable
) {
3312 "Maximum size for partition is %d "
3313 "cylinders; \nretry the operation.",
3314 Numcyl_usable
- cyl
);
3317 "Maximum size for partition is %d "
3318 "cylinders; \nretry the operation.",
3319 Numcyl_usable
- cyl
);
3324 /* Verify DOS12 partition doesn't exceed max size of 32MB. */
3325 if ((tsystid
== DOSOS12
) &&
3326 ((long)((long)cylen
* cyl_size
) > MAXDOS
)) {
3327 (void) printf(E_LINE
);
3329 "Maximum size for a %s partition is %ld cylinders;"
3330 "\nretry the operation.",
3331 Dstr
, MAXDOS
/ (int)(cyl_size
));
3335 (void) printf(E_LINE
);
3336 i
= insert_tbl(tsystid
, 0, 0, 0, 0, 0, 0, 0,
3337 cyl
* cyl_size
, cylen
* cyl_size
, 0);
3341 if (verify_tbl() < 0) {
3342 (void) printf(E_LINE
);
3343 (void) printf("fdisk: Cannot create partition table\n");
3353 * Display command menu (interactive mode).
3358 (void) printf(M_LINE
);
3361 "SELECT ONE OF THE FOLLOWING:\n"
3362 " 1. Create a partition\n"
3363 " 2. Specify the active partition\n"
3364 " 3. Delete a partition\n"
3365 " 4. Change between Solaris and Solaris2 Partition IDs\n"
3366 " 5. Edit/View extended partitions\n"
3367 " 6. Exit (update disk configuration and exit)\n"
3368 " 7. Cancel (exit without updating disk configuration)\n");
3371 "SELECT ONE OF THE FOLLOWING:\n"
3372 " 1. Create a partition\n"
3373 " 2. Specify the active partition\n"
3374 " 3. Delete a partition\n"
3375 " 4. Change between Solaris and Solaris2 Partition IDs\n"
3376 " 5. Exit (update disk configuration and exit)\n"
3377 " 6. Cancel (exit without updating disk configuration)\n");
3383 * Change the ACTIVE designation of a partition.
3392 (void) printf(Q_LINE
);
3395 "Specify the partition number to boot from"
3396 " (or specify 0 for none): ");
3398 (void) fgets(s
, sizeof (s
), stdin
);
3400 if (((s
[1] != '\0') && (s
[1] != '\n')) ||
3401 (s
[0] < '0') || (s
[0] > '4')) {
3402 (void) printf(E_LINE
);
3404 "\aInvalid response, please specify a number"
3405 " between 0 and 4.\n");
3410 if (s
[0] == '0') { /* No active partitions */
3411 for (i
= 0; i
< FD_NUMPART
; i
++) {
3412 if (Table
[i
].systid
!= UNUSED
&&
3413 Table
[i
].bootid
== ACTIVE
)
3414 Table
[i
].bootid
= 0;
3416 (void) printf(E_LINE
);
3418 "\aNo partition is currently marked as active.");
3420 } else { /* User has selected a partition to be active */
3424 if (Table
[i
].systid
== UNUSED
) {
3425 (void) printf(E_LINE
);
3426 (void) printf("\aPartition does not exist.");
3429 /* a DOS-DATA or EXT-DOS partition cannot be active */
3430 else if ((Table
[i
].systid
== DOSDATA
) ||
3431 (Table
[i
].systid
== EXTDOS
) ||
3432 (Table
[i
].systid
== FDISK_EXTLBA
)) {
3433 (void) printf(E_LINE
);
3435 "DOS-DATA, EXT_DOS and EXT_DOS_LBA partitions "
3436 "cannot be made active.\n");
3437 (void) printf("Select another partition.");
3440 Table
[i
].bootid
= ACTIVE
;
3441 for (j
= 0; j
< FD_NUMPART
; j
++) {
3443 Table
[j
].bootid
= 0;
3446 (void) printf(E_LINE
);
3449 "Partition %d is now active. The system will start up"
3450 " from this\n", i
+ 1);
3451 (void) printf("partition after the next reboot.");
3457 * Change between SOLARIS and SOLARIS2 partition id
3466 (void) printf(Q_LINE
);
3467 (void) printf("Specify the partition number to change"
3468 " (or enter 0 to exit): ");
3469 if (!fgets(s
, sizeof (s
), stdin
))
3471 i
= strtol(s
, &p
, 10);
3473 if (*p
!= '\n' || i
< 0 || i
> FD_NUMPART
) {
3474 (void) printf(E_LINE
);
3476 "Invalid response, retry the operation.\n");
3481 /* exit delete command */
3482 (void) printf(E_LINE
); /* clear error message */
3488 if (Table
[i
].systid
== SUNIXOS
) {
3489 Table
[i
].systid
= SUNIXOS2
;
3490 } else if (Table
[i
].systid
== SUNIXOS2
) {
3491 Table
[i
].systid
= SUNIXOS
;
3493 (void) printf(E_LINE
);
3495 "Partition %d is not a Solaris partition.",
3500 (void) printf(E_LINE
);
3501 (void) printf("Partition %d has been changed.", i
+ 1);
3508 * Remove partition entry from the table (interactive mode).
3517 DEL1
: (void) printf(Q_LINE
);
3518 (void) printf("Specify the partition number to delete"
3519 " (or enter 0 to exit): ");
3520 (void) fgets(s
, sizeof (s
), stdin
);
3522 if ((s
[0] == '0')) { /* exit delete command */
3523 (void) printf(E_LINE
); /* clear error message */
3526 /* Accept only a single digit between 1 and 4 */
3527 if (((s
[1] != '\0') && (s
[1] != '\n')) ||
3528 (i
= atoi(s
)) < 1 || i
> FD_NUMPART
) {
3529 (void) printf(E_LINE
);
3530 (void) printf("Invalid response, retry the operation.\n");
3532 } else { /* Found a digit between 1 and 4 */
3533 --i
; /* Structure begins with element 0 */
3536 if (Table
[i
].systid
== UNUSED
) {
3537 (void) printf(E_LINE
);
3538 (void) printf("\aPartition %d does not exist.", i
+ 1);
3543 if (fdisk_is_dos_extended(Table
[i
].systid
) &&
3544 (Table
[i
].relsect
== fdisk_get_ext_beg_sec(epp
)) &&
3545 fdisk_get_logical_drive_count(epp
)) {
3546 (void) printf(Q_LINE
);
3547 (void) printf("There are logical drives inside the"
3548 " extended partition\n");
3549 (void) printf("Are you sure of proceeding with deletion ?"
3550 " (type \"y\" or \"n\") ");
3552 (void) printf(E_LINE
);
3556 if (fdisk_mounted_logical_drives(epp
) == FDISK_EMOUNTED
) {
3557 (void) printf(Q_LINE
);
3558 (void) printf("There are mounted logical drives. "
3559 "Committing changes now can cause data loss or "
3560 "corruption. Unmount all logical drives and then "
3561 "try committing the changes again.\n");
3562 (void) printf("Press enter to continue.\n");
3566 (void) fdisk_delete_ext_part(epp
);
3569 (void) printf(Q_LINE
);
3570 (void) printf("Are you sure you want to delete partition %d?"
3571 " This will make all files and \n", i
+ 1);
3572 (void) printf("programs in this partition inaccessible (type"
3573 " \"y\" or \"n\"). ");
3575 (void) printf(E_LINE
);
3583 if (Table
[i
].bootid
== ACTIVE
) {
3589 (void) memset(&Table
[i
], 0, sizeof (struct ipart
));
3591 (void) printf(E_LINE
);
3592 (void) printf("Partition %d has been deleted.", i
+ 1);
3595 (void) printf(" This was the active partition.");
3603 * Remove blanks from strings of user responses.
3610 for (i
= 0; i
< CBUFLEN
; i
++) {
3611 if ((s
[i
] == ' ') || (s
[i
] == '\t'))
3614 /* Found first non-blank character of the string */
3617 for (j
= 0; i
< CBUFLEN
; j
++, i
++) {
3618 if ((s
[j
] = s
[i
]) == '\0') {
3619 /* Reached end of string */
3627 * Take the user-specified cylinder number and convert it from a
3628 * string to a decimal value.
3635 (void) fgets(s
, sizeof (s
), stdin
);
3638 if (s
[slen
- 1] == '\n')
3642 for (i
= slen
- 1; i
>= 0; i
--) {
3643 if (s
[i
] < '0' || s
[i
] > '9') {
3646 cyl
+= (j
* (s
[i
] - '0'));
3654 * Display the current fdisk table; determine percentage
3655 * of the disk used for each partition.
3661 unsigned int startcyl
, endcyl
, length
, percent
, remainder
;
3665 if ((heads
== 0) || (sectors
== 0)) {
3666 (void) printf("WARNING: critical disk geometry information"
3668 (void) printf("\theads = %d, sectors = %d\n", heads
, sectors
);
3672 (void) printf(HOME
);
3673 (void) printf(T_LINE
);
3674 (void) printf(" Total disk size is %d cylinders\n", Numcyl
);
3675 (void) printf(" Cylinder size is %d (%d byte) blocks\n\n",
3676 heads
* sectors
, sectsiz
);
3680 " Partition Status Type Start End Length"
3683 " ========= ====== ============ ===== === ======"
3687 for (i
= 0; i
< FD_NUMPART
; i
++) {
3689 if (Table
[i
].systid
== UNUSED
) {
3693 if (Table
[i
].bootid
== ACTIVE
)
3697 switch (Table
[i
].systid
) {
3704 if (fdisk_is_linux_swap(epp
, Table
[i
].relsect
,
3781 case FDISK_LINUXNAT
:
3784 case FDISK_NTFSVOL1
:
3787 case FDISK_NTFSVOL2
:
3793 case FDISK_NEXTSTEP
:
3799 case FDISK_BSDISWAP
:
3804 if (LE_32(Table
[i
].numsect
) == DK_MAX_2TB
)
3812 startcyl
= LE_32(Table
[i
].relsect
) /
3813 (unsigned long)(heads
* sectors
);
3815 if (LE_32(Table
[i
].numsect
) == DK_MAX_2TB
) {
3816 endcyl
= Numcyl
- 1;
3817 length
= endcyl
- startcyl
+ 1;
3819 length
= LE_32(Table
[i
].numsect
) /
3820 (unsigned long)(heads
* sectors
);
3821 if (LE_32(Table
[i
].numsect
) %
3822 (unsigned long)(heads
* sectors
))
3824 endcyl
= startcyl
+ length
- 1;
3827 percent
= length
* 100 / Numcyl_usable
;
3828 if ((remainder
= (length
* 100 % Numcyl_usable
)) != 0) {
3829 if ((remainder
* 100 / Numcyl_usable
) > 50) {
3833 /* Else leave the percent as is since it's already */
3839 "\n %d %s %-12.12s %4d %4d %4d"
3841 i
+ 1, stat
, type
, startcyl
, endcyl
, length
, percent
);
3844 /* Print warning message if table is empty */
3845 if (nopartdefined()) {
3846 (void) printf(W_LINE
);
3847 (void) printf("WARNING: no partitions are defined!");
3849 /* Clear the warning line */
3850 (void) printf(W_LINE
);
3852 /* Print warning if disk > 2TB and is not EFI PMBR */
3853 if (!is_pmbr
&& (dev_capacity
> DK_MAX_2TB
))
3854 (void) printf("WARNING: Disk is larger than 2 TB. "
3855 "Upper limit is 2 TB for non-EFI partition ID\n");
3861 * Write the detailed fdisk table to standard error for
3862 * the selected disk device.
3869 (void) fprintf(stderr
,
3870 " SYSID ACT BHEAD BSECT BEGCYL EHEAD ESECT ENDCYL RELSECT"
3873 for (i
= 0; i
< FD_NUMPART
; i
++) {
3874 (void) fprintf(stderr
, " %-5d ", Table
[i
].systid
);
3875 (void) fprintf(stderr
, "%-3d ", Table
[i
].bootid
);
3876 (void) fprintf(stderr
, "%-5d ", Table
[i
].beghead
);
3877 (void) fprintf(stderr
, "%-5d ", Table
[i
].begsect
& 0x3f);
3878 (void) fprintf(stderr
, "%-8d ",
3879 (((uint_t
)Table
[i
].begsect
& 0xc0) << 2) + Table
[i
].begcyl
);
3881 (void) fprintf(stderr
, "%-5d ", Table
[i
].endhead
);
3882 (void) fprintf(stderr
, "%-5d ", Table
[i
].endsect
& 0x3f);
3883 (void) fprintf(stderr
, "%-8d ",
3884 (((uint_t
)Table
[i
].endsect
& 0xc0) << 2) + Table
[i
].endcyl
);
3885 (void) fprintf(stderr
, "%-10u ", LE_32(Table
[i
].relsect
));
3886 (void) fprintf(stderr
, "%-10u\n", LE_32(Table
[i
].numsect
));
3892 * copy_Table_to_Old_Table
3893 * Copy Table into Old_Table. The function only copies the systid,
3894 * numsect, relsect, and bootid values because they are the only
3895 * ones compared when determining if Table has changed.
3898 copy_Table_to_Old_Table(void)
3901 for (i
= 0; i
< FD_NUMPART
; i
++) {
3902 (void) memcpy(&Old_Table
[i
], &Table
[i
], sizeof (Table
[0]));
3908 * Zero out the systid, numsect, relsect, and bootid values in the
3916 for (i
= 0; i
< FD_NUMPART
; i
++) {
3917 Table
[i
].systid
= UNUSED
;
3918 Table
[i
].numsect
= LE_32(UNUSED
);
3919 Table
[i
].relsect
= LE_32(UNUSED
);
3920 Table
[i
].bootid
= 0;
3926 * copy_Bootblk_to_Table
3927 * Copy the bytes from the boot record to an internal "Table".
3928 * All unused are padded with zeros starting at offset 446.
3931 copy_Bootblk_to_Table(void)
3935 struct ipart iparts
[FD_NUMPART
];
3937 /* Get an aligned copy of the partition tables */
3938 (void) memcpy(iparts
, Bootblk
->parts
, sizeof (iparts
));
3939 bootptr
= (char *)iparts
; /* Points to start of partition table */
3940 if (LE_16(Bootblk
->signature
) != MBB_MAGIC
) {
3941 /* Signature is missing */
3943 (void) memcpy(Bootblk
->bootinst
, &BootCod
, BOOTSZ
);
3947 * When the DOS fdisk command deletes a partition, it is not
3948 * recognized by the old algorithm. The algorithm that
3949 * follows looks at each entry in the Bootrec and copies all
3950 * those that are valid.
3952 for (i
= 0; i
< FD_NUMPART
; i
++) {
3953 if (iparts
[i
].systid
== 0) {
3955 (void) memset(&Table
[i
], 0, sizeof (struct ipart
));
3957 fill_ipart(bootptr
, &Table
[i
]);
3959 bootptr
+= sizeof (struct ipart
);
3962 /* For now, always replace the bootcode with ours */
3963 (void) memcpy(Bootblk
->bootinst
, &BootCod
, BOOTSZ
);
3964 copy_Table_to_Bootblk();
3969 * Initialize ipart structure values.
3972 fill_ipart(char *bootptr
, struct ipart
*partp
)
3975 /* Packing struct ipart for Sparc */
3976 partp
->bootid
= getbyte(&bootptr
);
3977 partp
->beghead
= getbyte(&bootptr
);
3978 partp
->begsect
= getbyte(&bootptr
);
3979 partp
->begcyl
= getbyte(&bootptr
);
3980 partp
->systid
= getbyte(&bootptr
);
3981 partp
->endhead
= getbyte(&bootptr
);
3982 partp
->endsect
= getbyte(&bootptr
);
3983 partp
->endcyl
= getbyte(&bootptr
);
3984 partp
->relsect
= (int32_t)getlong(&bootptr
);
3985 partp
->numsect
= (int32_t)getlong(&bootptr
);
3987 *partp
= *(struct ipart
*)bootptr
;
3993 * Get a byte, a short, or a long (SPARC only).
4011 bh
= ((**bp
) << 8) | *(*bp
+ 1);
4013 bl
= ((**bp
) << 8) | *(*bp
+ 1);
4016 b
= (bh
<< 16) | bl
;
4017 return ((uint32_t)b
);
4022 * copy_Table_to_Bootblk
4023 * Copy the table into the boot record. Note that the unused
4024 * entries will always be the last ones in the table and they are
4025 * marked with 100 in sysind. The the unused portion of the table
4026 * is padded with zeros in the bytes after the used entries.
4029 copy_Table_to_Bootblk(void)
4031 struct ipart
*boot_ptr
, *tbl_ptr
;
4033 boot_ptr
= (struct ipart
*)Bootblk
->parts
;
4034 tbl_ptr
= (struct ipart
*)&Table
[0].bootid
;
4035 for (; tbl_ptr
< (struct ipart
*)&Table
[FD_NUMPART
].bootid
;
4036 tbl_ptr
++, boot_ptr
++) {
4037 if (tbl_ptr
->systid
== UNUSED
)
4038 (void) memset(boot_ptr
, 0, sizeof (struct ipart
));
4040 (void) memcpy(boot_ptr
, tbl_ptr
, sizeof (struct ipart
));
4042 Bootblk
->signature
= LE_16(MBB_MAGIC
);
4047 * Check for any changes in the partition table.
4055 for (i
= 0; i
< FD_NUMPART
; i
++) {
4056 if (memcmp(&Old_Table
[i
], &Table
[i
], sizeof (Table
[0])) != 0) {
4057 /* Partition table changed, write back to disk */
4067 * Display contents of partition table to standard output or
4068 * another file name without writing it to the disk (-W file).
4071 ffile_write(char *file
)
4077 * If file isn't standard output, then it's a file name.
4078 * Open file and write it.
4080 if (file
!= (char *)stdout
) {
4081 if ((fp
= fopen(file
, "w")) == NULL
) {
4082 (void) fprintf(stderr
,
4083 "fdisk: Cannot open output file %s.\n",
4092 * Write the fdisk table information
4094 (void) fprintf(fp
, "\n* %s default fdisk table\n", Dfltdev
);
4095 (void) fprintf(fp
, "* Dimensions:\n");
4096 (void) fprintf(fp
, "* %4d bytes/sector\n", sectsiz
);
4097 (void) fprintf(fp
, "* %4d sectors/track\n", sectors
);
4098 (void) fprintf(fp
, "* %4d tracks/cylinder\n", heads
);
4099 (void) fprintf(fp
, "* %4d cylinders\n", Numcyl
);
4100 (void) fprintf(fp
, "*\n");
4101 /* Write virtual (HBA) geometry, if required */
4103 (void) fprintf(fp
, "* HBA Dimensions:\n");
4104 (void) fprintf(fp
, "* %4d bytes/sector\n", sectsiz
);
4105 (void) fprintf(fp
, "* %4d sectors/track\n", hba_sectors
);
4106 (void) fprintf(fp
, "* %4d tracks/cylinder\n", hba_heads
);
4107 (void) fprintf(fp
, "* %4d cylinders\n", hba_Numcyl
);
4108 (void) fprintf(fp
, "*\n");
4110 (void) fprintf(fp
, "* systid:\n");
4111 (void) fprintf(fp
, "* 1: DOSOS12\n");
4112 (void) fprintf(fp
, "* 2: PCIXOS\n");
4113 (void) fprintf(fp
, "* 4: DOSOS16\n");
4114 (void) fprintf(fp
, "* 5: EXTDOS\n");
4115 (void) fprintf(fp
, "* 6: DOSBIG\n");
4116 (void) fprintf(fp
, "* 7: FDISK_IFS\n");
4117 (void) fprintf(fp
, "* 8: FDISK_AIXBOOT\n");
4118 (void) fprintf(fp
, "* 9: FDISK_AIXDATA\n");
4119 (void) fprintf(fp
, "* 10: FDISK_0S2BOOT\n");
4120 (void) fprintf(fp
, "* 11: FDISK_WINDOWS\n");
4121 (void) fprintf(fp
, "* 12: FDISK_EXT_WIN\n");
4122 (void) fprintf(fp
, "* 14: FDISK_FAT95\n");
4123 (void) fprintf(fp
, "* 15: FDISK_EXTLBA\n");
4124 (void) fprintf(fp
, "* 18: DIAGPART\n");
4125 (void) fprintf(fp
, "* 65: FDISK_LINUX\n");
4126 (void) fprintf(fp
, "* 82: FDISK_CPM\n");
4127 (void) fprintf(fp
, "* 86: DOSDATA\n");
4128 (void) fprintf(fp
, "* 98: OTHEROS\n");
4129 (void) fprintf(fp
, "* 99: UNIXOS\n");
4130 (void) fprintf(fp
, "* 100: FDISK_NOVELL2\n");
4131 (void) fprintf(fp
, "* 101: FDISK_NOVELL3\n");
4132 (void) fprintf(fp
, "* 119: FDISK_QNX4\n");
4133 (void) fprintf(fp
, "* 120: FDISK_QNX42\n");
4134 (void) fprintf(fp
, "* 121: FDISK_QNX43\n");
4135 (void) fprintf(fp
, "* 130: SUNIXOS\n");
4136 (void) fprintf(fp
, "* 131: FDISK_LINUXNAT\n");
4137 (void) fprintf(fp
, "* 134: FDISK_NTFSVOL1\n");
4138 (void) fprintf(fp
, "* 135: FDISK_NTFSVOL2\n");
4139 (void) fprintf(fp
, "* 165: FDISK_BSD\n");
4140 (void) fprintf(fp
, "* 167: FDISK_NEXTSTEP\n");
4141 (void) fprintf(fp
, "* 183: FDISK_BSDIFS\n");
4142 (void) fprintf(fp
, "* 184: FDISK_BSDISWAP\n");
4143 (void) fprintf(fp
, "* 190: X86BOOT\n");
4144 (void) fprintf(fp
, "* 191: SUNIXOS2\n");
4145 (void) fprintf(fp
, "* 238: EFI_PMBR\n");
4146 (void) fprintf(fp
, "* 239: EFI_FS\n");
4147 (void) fprintf(fp
, "*\n");
4149 "\n* Id Act Bhead Bsect Bcyl Ehead Esect Ecyl"
4150 " Rsect Numsect\n");
4152 for (i
= 0; i
< FD_NUMPART
; i
++) {
4154 " %-5d %-4d %-6d %-6d %-7d %-6d %-6d %-7d %-10u"
4159 Table
[i
].begsect
& 0x3f,
4160 ((Table
[i
].begcyl
& 0xff) | ((Table
[i
].begsect
&
4163 Table
[i
].endsect
& 0x3f,
4164 ((Table
[i
].endcyl
& 0xff) | ((Table
[i
].endsect
&
4166 LE_32(Table
[i
].relsect
),
4167 LE_32(Table
[i
].numsect
));
4170 if (fdisk_ext_part_exists(epp
)) {
4171 struct ipart ext_tab
;
4172 logical_drive_t
*temp
;
4173 uint32_t rsect
, numsect
, tempsect
= 0;
4174 for (temp
= fdisk_get_ld_head(epp
); temp
!= NULL
;
4175 temp
= temp
->next
) {
4176 ext_tab
= temp
->parts
[0];
4177 rsect
= tempsect
+ LE_32(ext_tab
.relsect
) +
4178 fdisk_get_ext_beg_sec(epp
);
4179 numsect
= LE_32(ext_tab
.numsect
);
4180 tempsect
= LE_32(temp
->parts
[1].relsect
);
4182 " %-5d %-4d %-6d %-6d %-7d %-6d %-6d "
4187 ext_tab
.begsect
& 0x3f,
4188 ((ext_tab
.begcyl
& 0xff) |
4189 ((ext_tab
.begsect
& 0xc0) << 2)),
4191 ext_tab
.endsect
& 0x3f,
4192 ((ext_tab
.endcyl
& 0xff) |
4193 ((ext_tab
.endsect
& 0xc0) << 2)),
4206 * Read the VTOC table on the Solaris partition and check that no
4207 * slices exist that extend past the end of the Solaris partition.
4208 * If no Solaris partition exists, nothing is done.
4220 for (i
= 0; i
< FD_NUMPART
; i
++) {
4221 if (Table
[i
].systid
== SUNIXOS
|| Table
[i
].systid
== SUNIXOS2
) {
4223 * Only the size matters (not starting point), since
4224 * VTOC entries are relative to the start of
4227 numsect
= LE_32(Table
[i
].numsect
);
4232 if (i
>= FD_NUMPART
) {
4234 (void) fprintf(stderr
,
4235 "fdisk: No Solaris partition found - VTOC not"
4241 if (readvtoc() != VTOC_OK
) {
4242 exit(1); /* Failed to read the VTOC */
4244 for (i
= 0; i
< V_NUMPAR
; i
++) {
4245 /* Special case for slice two (entire disk) */
4247 if (disk_vtoc
.v_part
[i
].p_start
!= 0) {
4248 (void) fprintf(stderr
,
4249 "slice %d starts at %llu, is not at"
4250 " start of partition",
4251 i
, disk_vtoc
.v_part
[i
].p_start
);
4253 (void) printf(" adjust ?:");
4255 disk_vtoc
.v_part
[i
].p_start
= 0;
4257 disk_vtoc
.v_part
[i
].p_start
= 0;
4258 (void) fprintf(stderr
, " adjusted!\n");
4262 if (disk_vtoc
.v_part
[i
].p_size
!= numsect
) {
4263 (void) fprintf(stderr
,
4264 "slice %d size %llu does not cover"
4265 " complete partition",
4266 i
, disk_vtoc
.v_part
[i
].p_size
);
4268 (void) printf(" adjust ?:");
4270 disk_vtoc
.v_part
[i
].p_size
=
4273 disk_vtoc
.v_part
[i
].p_size
= numsect
;
4274 (void) fprintf(stderr
, " adjusted!\n");
4277 if (disk_vtoc
.v_part
[i
].p_tag
!= V_BACKUP
) {
4278 (void) fprintf(stderr
,
4279 "slice %d tag was %d should be %d",
4280 i
, disk_vtoc
.v_part
[i
].p_tag
,
4283 (void) printf(" fix ?:");
4285 disk_vtoc
.v_part
[i
].p_tag
=
4288 disk_vtoc
.v_part
[i
].p_tag
= V_BACKUP
;
4289 (void) fprintf(stderr
, " fixed!\n");
4295 if (disk_vtoc
.v_part
[i
].p_start
> numsect
||
4296 disk_vtoc
.v_part
[i
].p_start
+
4297 disk_vtoc
.v_part
[i
].p_size
> numsect
) {
4298 (void) fprintf(stderr
,
4299 "slice %d (start %llu, end %llu)"
4300 " is larger than the partition",
4301 i
, disk_vtoc
.v_part
[i
].p_start
,
4302 disk_vtoc
.v_part
[i
].p_start
+
4303 disk_vtoc
.v_part
[i
].p_size
);
4305 (void) printf(" remove ?:");
4307 disk_vtoc
.v_part
[i
].p_size
= 0;
4308 disk_vtoc
.v_part
[i
].p_start
= 0;
4309 disk_vtoc
.v_part
[i
].p_tag
= 0;
4310 disk_vtoc
.v_part
[i
].p_flag
= 0;
4313 disk_vtoc
.v_part
[i
].p_size
= 0;
4314 disk_vtoc
.v_part
[i
].p_start
= 0;
4315 disk_vtoc
.v_part
[i
].p_tag
= 0;
4316 disk_vtoc
.v_part
[i
].p_flag
= 0;
4317 (void) fprintf(stderr
,
4323 if (disk_vtoc
.v_part
[i
].p_start
> numsect
) {
4324 (void) fprintf(stderr
,
4325 "slice %d (start %llu) is larger than the "
4326 "partition", i
, disk_vtoc
.v_part
[i
].p_start
);
4328 (void) printf(" remove ?:");
4330 disk_vtoc
.v_part
[i
].p_size
= 0;
4331 disk_vtoc
.v_part
[i
].p_start
= 0;
4332 disk_vtoc
.v_part
[i
].p_tag
= 0;
4333 disk_vtoc
.v_part
[i
].p_flag
= 0;
4336 disk_vtoc
.v_part
[i
].p_size
= 0;
4337 disk_vtoc
.v_part
[i
].p_start
= 0;
4338 disk_vtoc
.v_part
[i
].p_tag
= 0;
4339 disk_vtoc
.v_part
[i
].p_flag
= 0;
4340 (void) fprintf(stderr
,
4343 } else if (disk_vtoc
.v_part
[i
].p_start
4344 + disk_vtoc
.v_part
[i
].p_size
> numsect
) {
4345 (void) fprintf(stderr
,
4346 "slice %d (end %llu) is larger"
4347 " than the partition",
4349 disk_vtoc
.v_part
[i
].p_start
+
4350 disk_vtoc
.v_part
[i
].p_size
);
4352 (void) printf(" adjust ?:");
4354 disk_vtoc
.v_part
[i
].p_size
= numsect
;
4357 disk_vtoc
.v_part
[i
].p_size
= numsect
;
4358 (void) fprintf(stderr
, " adjusted!\n");
4362 #if 1 /* bh for now */
4363 /* Make the VTOC look sane - ha ha */
4364 disk_vtoc
.v_version
= V_VERSION
;
4365 disk_vtoc
.v_sanity
= VTOC_SANE
;
4366 disk_vtoc
.v_nparts
= V_NUMPAR
;
4367 if (disk_vtoc
.v_sectorsz
== 0)
4368 disk_vtoc
.v_sectorsz
= NBPSCTR
;
4371 /* Write the VTOC back to the disk */
4378 * Get yes or no answer. Return 1 for yes and 0 for no.
4387 (void) fgets(s
, sizeof (s
), stdin
);
4389 if (((s
[1] != '\0') && (s
[1] != '\n')) ||
4390 ((s
[0] != 'y') && (s
[0] != 'n'))) {
4391 (void) printf(E_LINE
);
4392 (void) printf("Please answer with \"y\" or \"n\": ");
4404 * Read the VTOC from the Solaris partition of the device.
4410 int retval
= VTOC_OK
;
4412 if ((i
= read_extvtoc(Dev
, &disk_vtoc
)) < VTOC_OK
) {
4413 if (i
== VT_EINVAL
) {
4414 (void) fprintf(stderr
, "fdisk: Invalid VTOC.\n");
4416 retval
= VTOC_INVAL
;
4417 } else if (i
== VT_ENOTSUP
) {
4418 (void) fprintf(stderr
, "fdisk: partition may have EFI "
4420 retval
= VTOC_NOTSUP
;
4422 (void) fprintf(stderr
, "fdisk: Cannot read VTOC.\n");
4423 retval
= VTOC_RWERR
;
4431 * Write the VTOC to the Solaris partition on the device.
4439 if ((i
= write_extvtoc(Dev
, &disk_vtoc
)) != 0) {
4440 if (i
== VT_EINVAL
) {
4441 (void) fprintf(stderr
,
4442 "fdisk: Invalid entry exists in VTOC.\n");
4443 retval
= VTOC_INVAL
;
4444 } else if (i
== VT_ENOTSUP
) {
4445 (void) fprintf(stderr
, "fdisk: partition may have EFI "
4447 retval
= VTOC_NOTSUP
;
4449 (void) fprintf(stderr
, "fdisk: Cannot write VTOC.\n");
4450 retval
= VTOC_RWERR
;
4458 * issues DKIOCSETEFI IOCTL
4459 * (duplicate of private efi_ioctl() in rdwr_efi.c
4462 efi_ioctl(int fd
, int cmd
, dk_efi_t
*dk_ioc
)
4464 void *data
= dk_ioc
->dki_data
;
4467 dk_ioc
->dki_data_64
= (uintptr_t)data
;
4468 error
= ioctl(fd
, cmd
, (void *)dk_ioc
);
4475 * Clear EFI labels from the EFI_PMBR partition on the device
4476 * This function is modeled on the libefi(3LIB) call efi_write()
4481 struct dk_gpt
*efi_vtoc
;
4485 * see if we can read the EFI label
4487 if (efi_alloc_and_read(Dev
, &efi_vtoc
) < 0) {
4492 * set up the dk_ioc structure for writing
4495 dk_ioc
.dki_length
= EFI_MIN_ARRAY_SIZE
+ efi_vtoc
->efi_lbasize
;
4497 if ((dk_ioc
.dki_data
= calloc(dk_ioc
.dki_length
, 1)) == NULL
) {
4502 * clear the primary label
4505 (void) fprintf(stderr
,
4506 "\tClearing primary EFI label at block %lld\n",
4510 if (efi_ioctl(Dev
, DKIOCSETEFI
, &dk_ioc
) == -1) {
4511 free(dk_ioc
.dki_data
);
4523 * clear the backup partition table
4525 dk_ioc
.dki_lba
= efi_vtoc
->efi_last_u_lba
+ 1;
4526 dk_ioc
.dki_length
-= efi_vtoc
->efi_lbasize
;
4527 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
+
4528 efi_vtoc
->efi_lbasize
);
4530 (void) fprintf(stderr
,
4531 "\tClearing backup partition table at block %lld\n",
4535 if (efi_ioctl(Dev
, DKIOCSETEFI
, &dk_ioc
) == -1) {
4536 (void) fprintf(stderr
, "\tUnable to clear backup EFI label at "
4537 "block %llu; errno %d\n", efi_vtoc
->efi_last_u_lba
+ 1,
4542 * clear the backup label
4544 dk_ioc
.dki_lba
= efi_vtoc
->efi_last_lba
;
4545 dk_ioc
.dki_length
= efi_vtoc
->efi_lbasize
;
4546 dk_ioc
.dki_data
= (efi_gpt_t
*)((char *)dk_ioc
.dki_data
-
4547 efi_vtoc
->efi_lbasize
);
4549 (void) fprintf(stderr
, "\tClearing backup label at block "
4550 "%lld\n", dk_ioc
.dki_lba
);
4553 if (efi_ioctl(Dev
, DKIOCSETEFI
, &dk_ioc
) == -1) {
4554 (void) fprintf(stderr
,
4555 "\tUnable to clear backup EFI label at "
4556 "block %llu; errno %d\n",
4557 efi_vtoc
->efi_last_lba
,
4561 free(dk_ioc
.dki_data
);
4569 * Clear the VTOC from the current or previous Solaris partition on the
4573 clear_vtoc(int table
, int part
)
4575 struct ipart
*clr_table
;
4577 uint32_t pcyl
, ncyl
, count
;
4578 diskaddr_t backup_block
, solaris_offset
;
4587 clr_table
= &Old_Table
[part
];
4589 clr_table
= &Table
[part
];
4592 disk_label
= (char *)calloc(sectsiz
, 1);
4593 if (disk_label
== NULL
) {
4597 seek_byte
= (off_t
)(LE_32(clr_table
->relsect
) + VTOC_OFFSET
) * sectsiz
;
4600 (void) fprintf(stderr
,
4601 "\tClearing primary VTOC at byte %llu (block %llu)\n",
4602 (uint64_t)seek_byte
,
4603 (uint64_t)(LE_32(clr_table
->relsect
) + VTOC_OFFSET
));
4606 if (lseek(Dev
, seek_byte
, SEEK_SET
) == -1) {
4607 (void) fprintf(stderr
,
4608 "\tError seeking to primary label at byte %llu\n",
4609 (uint64_t)seek_byte
);
4614 bytes
= write(Dev
, disk_label
, sectsiz
);
4616 if (bytes
!= sectsiz
) {
4617 (void) fprintf(stderr
,
4618 "\tWarning: only %d bytes written to clear primary"
4623 if (lseek(Dev
, seek_byte
, SEEK_SET
) == -1) {
4624 (void) fprintf(stderr
,
4625 "DEBUG: Error seeking to primary label at byte %llu\n",
4626 (uint64_t)seek_byte
);
4630 (void) fprintf(stderr
,
4631 "DEBUG: Successful lseek() to byte %llu\n",
4632 (uint64_t)seek_byte
);
4635 read_label
= (char *)calloc(sectsiz
, 1);
4636 if (read_label
== NULL
) {
4641 bytes
= read(Dev
, read_label
, sectsiz
);
4643 if (bytes
!= sectsiz
) {
4644 (void) fprintf(stderr
,
4645 "DEBUG: Warning: only %d bytes read of label\n",
4649 if (memcmp(disk_label
, read_label
, sectsiz
) != 0) {
4650 (void) fprintf(stderr
,
4651 "DEBUG: Warning: disk_label and read_label differ!!!\n");
4653 (void) fprintf(stderr
, "DEBUG Good compare of disk_label and "
4658 /* Clear backup label */
4659 pcyl
= LE_32(clr_table
->numsect
) / (heads
* sectors
);
4660 solaris_offset
= LE_32(clr_table
->relsect
);
4663 backup_block
= ((ncyl
+ acyl
- 1) *
4664 (heads
* sectors
)) + ((heads
- 1) * sectors
) + 1;
4666 for (count
= 1; count
< 6; count
++) {
4667 seek_byte
= (off_t
)(solaris_offset
+ backup_block
) * sectsiz
;
4669 if (lseek(Dev
, seek_byte
, SEEK_SET
) == -1) {
4670 (void) fprintf(stderr
,
4671 "\tError seeking to backup label at byte %llu on "
4672 "%s.\n", (uint64_t)seek_byte
, Dfltdev
);
4681 (void) fprintf(stderr
, "\tClearing backup VTOC at"
4682 " byte %llu (block %llu)\n",
4683 (uint64_t)seek_byte
,
4684 (uint64_t)(solaris_offset
+ backup_block
));
4687 bytes
= write(Dev
, disk_label
, sectsiz
);
4689 if (bytes
!= sectsiz
) {
4690 (void) fprintf(stderr
,
4691 "\t\tWarning: only %d bytes written to "
4692 "clear backup VTOC at block %llu!\n", bytes
,
4693 (uint64_t)(solaris_offset
+ backup_block
));
4697 if (lseek(Dev
, seek_byte
, SEEK_SET
) == -1) {
4698 (void) fprintf(stderr
,
4699 "DEBUG: Error seeking to backup label at byte %llu\n",
4700 (uint64_t)seek_byte
);
4705 (void) fprintf(stderr
,
4706 "DEBUG: Successful lseek() to byte %llu\n",
4707 (uint64_t)seek_byte
);
4710 bytes
= read(Dev
, read_label
, sectsiz
);
4712 if (bytes
!= sectsiz
) {
4713 (void) fprintf(stderr
,
4714 "DEBUG: Warning: only %d bytes read of backup label\n",
4718 if (memcmp(disk_label
, read_label
, sectsiz
) != 0) {
4719 (void) fprintf(stderr
,
4720 "DEBUG: Warning: disk_label and read_label differ!!!\n");
4722 (void) fprintf(stderr
,
4723 "DEBUG: Good compare of disk_label and backup "
4738 #define FDISK_STANDARD_LECTURE \
4739 "Fdisk is normally used with the device that " \
4740 "represents the entire fixed disk.\n" \
4741 "(For example, /dev/rdsk/c0d0p0 on x86 or " \
4742 "/dev/rdsk/c0t5d0s2 on sparc).\n"
4744 #define FDISK_LECTURE_NOT_SECTOR_ZERO \
4745 "The device does not appear to include absolute\n" \
4746 "sector 0 of the PHYSICAL disk " \
4747 "(the normal location for an fdisk table).\n"
4749 #define FDISK_LECTURE_NOT_FULL \
4750 "The device does not appear to encompass the entire PHYSICAL disk.\n"
4752 #define FDISK_LECTURE_NO_VTOC \
4753 "Unable to find a volume table of contents.\n" \
4754 "Cannot verify the device encompasses the full PHYSICAL disk.\n"
4756 #define FDISK_LECTURE_NO_GEOM \
4757 "Unable to get geometry from device.\n" \
4758 "Cannot verify the device encompasses the full PHYSICAL disk.\n"
4760 #define FDISK_SHALL_I_CONTINUE \
4761 "Are you sure you want to continue? (y/n) "
4765 * Called when a sanity check fails. This routine gives a warning
4766 * specific to the check that fails, followed by a generic lecture
4767 * about the "right" device to supply as input. Then, if appropriate,
4768 * it will prompt the user on whether or not they want to continue.
4769 * Inappropriate times for prompting are when the user has selected
4770 * non-interactive mode or read-only mode.
4773 lecture_and_query(char *warning
, char *devname
)
4778 (void) fprintf(stderr
, "WARNING: Device %s: \n", devname
);
4779 (void) fprintf(stderr
, "%s", warning
);
4780 (void) fprintf(stderr
, FDISK_STANDARD_LECTURE
);
4781 (void) fprintf(stderr
, FDISK_SHALL_I_CONTINUE
);
4787 sanity_check_provided_device(char *devname
, int fd
)
4791 struct part_info pi
;
4792 struct extpart_info extpi
;
4797 * First try the PARTINFO ioctl. If it works, we will be able
4798 * to tell if they've specified the full disk partition by checking
4799 * to see if they've specified a partition that starts at sector 0.
4801 if (ioctl(fd
, DKIOCEXTPARTINFO
, &extpi
) != -1) {
4802 if (extpi
.p_start
!= 0) {
4803 if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO
,
4809 } else if (ioctl(fd
, DKIOCPARTINFO
, &pi
) != -1) {
4810 if (pi
.p_start
!= 0) {
4811 if (!lecture_and_query(FDISK_LECTURE_NOT_SECTOR_ZERO
,
4818 if ((idx
= read_extvtoc(fd
, &v
)) < 0) {
4819 if (!lecture_and_query(FDISK_LECTURE_NO_VTOC
,
4826 if (ioctl(fd
, DKIOCGGEOM
, &d
) == -1) {
4828 if (!lecture_and_query(FDISK_LECTURE_NO_GEOM
,
4835 totsize
= (diskaddr_t
)d
.dkg_ncyl
* d
.dkg_nhead
* d
.dkg_nsect
;
4836 if (v
.v_part
[idx
].p_size
!= totsize
) {
4837 if (!lecture_and_query(FDISK_LECTURE_NOT_FULL
,
4849 * Called from main to construct the name of the device node to open.
4850 * Initially tries to stat the node exactly as provided, if that fails
4851 * we prepend the default path (/dev/rdsk/).
4854 get_node(char *devname
)
4857 struct stat statbuf
;
4860 /* Don't do anything if we are skipping device checks */
4866 /* Try the node as provided first */
4867 if (stat(node
, (struct stat
*)&statbuf
) == -1) {
4869 * Copy the passed in string to a new buffer, prepend the
4870 * default path and try again.
4872 space
= strlen(DEFAULT_PATH
) + strlen(devname
) + 1;
4874 if ((node
= malloc(space
)) == NULL
) {
4875 (void) fprintf(stderr
, "fdisk: Unable to obtain memory "
4876 "for device node.\n");
4880 /* Copy over the default path and the provided node */
4881 (void) strncpy(node
, DEFAULT_PATH
, strlen(DEFAULT_PATH
));
4882 space
-= strlen(DEFAULT_PATH
);
4883 (void) strlcpy(node
+ strlen(DEFAULT_PATH
), devname
, space
);
4885 /* Try to stat it again */
4886 if (stat(node
, (struct stat
*)&statbuf
) == -1) {
4887 /* Failed all options, give up */
4888 (void) fprintf(stderr
,
4889 "fdisk: Cannot stat device %s.\n",
4895 /* Make sure the device specified is the raw device */
4896 if ((statbuf
.st_mode
& S_IFMT
) != S_IFCHR
) {
4897 (void) fprintf(stderr
,
4898 "fdisk: %s must be a raw device.\n", node
);
4907 preach_and_continue()
4909 (void) fprintf(stderr
, "There are mounted logical drives. Committing "
4910 "changes now can lead to inconsistancy in internal system state "
4911 "which can eventually cause data loss or corruption. Unmount all "
4912 "logical drives and try committing the changes again.\n");
4917 * Convert a given partition ID to an descriptive string.
4918 * Just an index into the partition types table.
4921 id_to_name(uchar_t sysid
, char *buffer
)
4923 (void) strcpy(buffer
, fdisk_part_types
[sysid
]);
4927 * Procedure to check the validity of the extended partition menu option
4928 * entered by the user
4931 ext_invalid_option(char ch
)
4935 p
= strchr(ext_part_menu_opts
, tolower(ch
));
4944 * Read 16 bytes of the input (assuming that no valid user input spans more
4945 * than that). Flush the input stream, so that the next read does not reap
4946 * stale data from the previous input that was not processed.
4947 * Note that fgets also reads the trailing '\n'
4950 ext_read_input(char *buf
)
4952 (void) fgets(buf
, 16, stdin
);
4953 (void) fflush(stdin
);
4957 * Procedure to read and validate the user option at the extended partition menu
4960 ext_read_options(char *buf
)
4962 ext_read_input(buf
);
4963 if ((strlen(buf
) != 2) || (ext_invalid_option(buf
[0]))) {
4964 (void) printf("\nUnknown Command\n");
4971 * Procedure to print the list of known partition types and their IDs
4974 ext_print_part_types()
4976 int i
, rowmax
, rowcount
= 1;
4980 /* Get the current window dimensions */
4981 if (ioctl(STDIN_FILENO
, TIOCGWINSZ
, &ws
) < 0) {
4986 * Accommodate the initial headings by reducing the number of
4987 * partition IDs being printed.
4989 rowmax
= ws
.ws_row
- 5;
4993 (void) fprintf(stderr
, "Window size too small."
4994 " Try resizing the window\n");
4998 (void) printf("List of known partition types : \n");
4999 (void) printf("PartID Partition Type\n");
5000 (void) printf("====== ==============\n");
5001 for (i
= 0; i
<= FDISK_MAX_VALID_PART_ID
; i
++) {
5002 (void) printf("%-3d %s\n", i
, fdisk_part_types
[i
]);
5004 if (rowcount
== rowmax
) {
5006 * After the initial screen, use all the rows for
5007 * printing the partition IDs, but one.
5009 rowmax
= ws
.ws_row
- 1;
5010 (void) fprintf(stderr
, "\nPress enter to see next "
5011 "page or 'q' to quit : ");
5012 ext_read_input(buf
);
5013 if ((strlen(buf
) == 2) && (tolower(buf
[0]) == 'q')) {
5022 ext_read_valid_part_num(int *pno
)
5028 (void) printf("Enter the partition number : ");
5029 ext_read_input(buf
);
5033 /* Check length of the input */
5034 if ((len
< 2) || (len
> (FDISK_MAX_VALID_PART_NUM_DIGITS
+1))) {
5035 goto print_error_and_continue
;
5038 /* Check if there is a non-digit in the input */
5039 for (i
= 0; i
< len
-1; i
++) {
5040 if (!isdigit(buf
[i
])) {
5041 goto print_error_and_continue
;
5047 if ((*pno
<= FD_NUMPART
) ||
5048 *pno
> (fdisk_get_logical_drive_count(epp
) + FD_NUMPART
)) {
5049 goto print_error_and_continue
;
5053 print_error_and_continue
:
5054 (void) printf("Invalid partition number\n");
5060 ext_read_valid_part_id(uchar_t
*partid
)
5066 (void) printf("Enter the ID ( Type I for list of "
5067 "partition IDs ) : ");
5068 ext_read_input(buf
);
5071 if ((len
< 2) || (len
> (FDISK_MAX_VALID_PART_ID_DIGITS
+ 1))) {
5072 (void) printf("Invalid partition ID\n");
5076 if ((len
== 2) && (toupper(buf
[0]) == 'I')) {
5077 ext_print_part_types();
5081 /* Check if there is a non-digit in the input */
5082 for (i
= 0; i
< len
-1; i
++) {
5083 if (!isdigit(buf
[i
])) {
5084 (void) printf("Invalid partition ID\n");
5093 /* Check if the (now) valid number is greater than the limit */
5094 if ((id
= atoi(buf
)) > FDISK_MAX_VALID_PART_ID
) {
5095 (void) printf("Invalid partition ID\n");
5099 *partid
= (uchar_t
)id
;
5101 /* Disallow multiple extended partitions */
5102 if (fdisk_is_dos_extended(*partid
)) {
5103 (void) printf("Multiple extended partitions not "
5108 /* Disallow EFI partitions within extended partition */
5109 if (*partid
== EFI_PMBR
) {
5110 (void) printf("EFI partitions within an extended "
5111 "partition is not allowed\n");
5115 return; /* Valid partition ID is in partid */
5120 delete_logical_drive()
5124 if (!fdisk_get_logical_drive_count(epp
)) {
5125 (void) printf("\nNo logical drives defined.\n");
5129 (void) printf("\n");
5130 ext_read_valid_part_num(&pno
);
5131 fdisk_delete_logical_drive(epp
, pno
);
5132 (void) printf("Partition %d deleted\n", pno
);
5136 ext_read_valid_partition_start(uint32_t *begsec
)
5141 uint32_t first_free_cyl
;
5142 uint32_t first_free_sec
;
5144 ret
= fdisk_ext_find_first_free_sec(epp
, &first_free_sec
);
5145 if (ret
!= FDISK_SUCCESS
) {
5149 first_free_cyl
= FDISK_SECT_TO_CYL(epp
, first_free_sec
);
5151 (void) printf("Enter the beginning cylinder (Default - %d) : ",
5153 ext_read_input(buf
);
5155 if (len
== 1) { /* User accepted the default value */
5156 *begsec
= first_free_sec
;
5157 return (FDISK_SUCCESS
);
5160 if (len
> (FDISK_MAX_VALID_CYL_NUM_DIGITS
+ 1)) {
5161 (void) printf("Input too long\n");
5162 (void) printf("Invalid beginning cylinder number\n");
5165 /* Check if there is a non-digit in the input */
5166 for (i
= 0; i
< len
- 1; i
++) {
5167 if (!isdigit(buf
[i
])) {
5168 (void) printf("Invalid beginning cylinder "
5178 ret
= fdisk_ext_validate_part_start(epp
, begcyl
, begsec
);
5183 * Valid beginning sector is in begsec
5187 case FDISK_EOVERLAP
:
5188 (void) printf("Partition boundary overlaps "
5190 (void) printf("existing partitions\n");
5191 (void) printf("Invalid beginning cylinder "
5195 case FDISK_EOOBOUND
:
5196 (void) printf("Cylinder boundary beyond the "
5198 (void) printf("Invalid beginning cylinder "
5202 return (FDISK_SUCCESS
);
5208 * 1. Check if the first character is a +
5209 * a) If yes, check if the last character is 'k', 'm' or 'g'
5210 * 2. If not, check if there are any non-digits
5211 * 3. Check for the length of the numeral string
5212 * 4. atoi the numeral string
5213 * 5. In case of data entered in KB, MB or GB, convert it to number of cylinders
5214 * a) Adjust size to be cylinder boundary aligned
5215 * 6. If size specifies is zero, flag error
5216 * 7. Check if the size is less than 1 cylinder
5217 * a) If yes, default the size FDISK_MIN_PART_SIZE
5218 * b) If no, Check if the size is within endcyl - begcyl
5221 ext_read_valid_partition_size(uint32_t begsec
, uint32_t *endsec
)
5224 uint32_t last_free_sec
;
5225 uint32_t last_free_cyl
;
5226 int i
, len
, ch
, mbgb
= 0, scale
= FDISK_SECTS_PER_CYL(epp
);
5229 char numbuf
[FDISK_MAX_VALID_CYL_NUM_DIGITS
+ 1];
5230 int sectsize
= fdisk_get_disk_geom(epp
, PHYSGEOM
, SSIZE
);
5231 uint32_t remdr
, spc
, poss_end
;
5233 if (sectsize
== EINVAL
) {
5234 (void) fprintf(stderr
, "Unsupported geometry statistics.\n");
5238 last_free_sec
= fdisk_ext_find_last_free_sec(epp
, begsec
);
5239 last_free_cyl
= FDISK_SECT_TO_CYL(epp
, last_free_sec
);
5242 (void) printf("Enter the size in cylinders (Default End "
5244 (void) printf(" %u)\n", last_free_cyl
);
5245 (void) printf("Type +<size>K, +<size>M or +<size>G to enter "
5247 (void) printf("KB, MB or GB : ");
5248 ext_read_input(buf
);
5251 scale
= FDISK_SECTS_PER_CYL(epp
);
5253 if (len
== 1) { /* User accepted the default value */
5254 *endsec
= last_free_sec
;
5260 if ((buf
[0] == '+') && (isdigit(buf
[1]))) {
5262 if ((ch
= toupper(buf
[len
- 2])) == 'B') {
5263 ch
= toupper(buf
[len
- 3]);
5267 if (!((ch
== 'K') || (ch
== 'M') || (ch
== 'G'))) {
5268 (void) printf("Invalid partition size\n");
5274 scale
= ((ch
== 'K') ? FDISK_KB
:
5275 ((ch
== 'M') ? FDISK_MB
: FDISK_GB
));
5278 if (copy_len
> FDISK_MAX_VALID_CYL_NUM_DIGITS
) {
5279 (void) printf("Input too long\n");
5280 (void) printf("Invalid partition size\n");
5284 (void) strncpy(numbuf
, &buf
[mbgb
], copy_len
);
5285 numbuf
[copy_len
] = '\0';
5287 for (i
= mbgb
; i
< copy_len
+ mbgb
; i
++) {
5288 if (!isdigit(buf
[i
])) {
5293 if (i
< copy_len
+ mbgb
) {
5294 (void) printf("Invalid partition size\n");
5298 size
= (atoll(numbuf
) * (scale
));
5301 (void) printf("Zero size is invalid\n");
5302 (void) printf("Invalid partition size\n");
5310 if (size
> (last_free_sec
- begsec
+ 1)) {
5311 (void) printf("Cylinder boundary beyond the limits");
5312 (void) printf(" or overlaps with existing");
5313 (void) printf(" partitions\n");
5314 (void) printf("Invalid partition size\n");
5319 * Adjust the ending sector such that there are no partial
5320 * cylinders allocated. But at the same time, make sure it
5321 * doesn't over shoot boundaries.
5323 spc
= FDISK_SECTS_PER_CYL(epp
);
5324 poss_end
= begsec
+ size
- 1;
5325 if ((remdr
= (poss_end
% spc
)) != 0) {
5326 poss_end
+= spc
- remdr
- 1;
5328 *endsec
= (poss_end
> last_free_sec
) ? last_free_sec
:
5337 * 1. Get the starting and ending sectors/cylinder of the extended partition.
5338 * 2. Keep track of the first free sector/cylinder
5339 * 3. Allow the user to specify the beginning cylinder of the new partition
5340 * 4. Check for the validity of the entered data
5341 * a) If it is non-numeric
5342 * b) If it is beyond the extended partition limits
5343 * c) If it overlaps with the current logical drives
5344 * 5. Allow the user to specify the size in cylinders/ human readable form
5345 * 6. Check for the validity of the entered data
5346 * a) If it is non-numeric
5347 * b) If it is beyond the extended partition limits
5348 * c) If it overlaps with the current logical drives
5349 * d) If it is a number lesser than the starting cylinder
5350 * 7. Request partition ID for the new partition.
5351 * 8. Update the first free cylinder available
5352 * 9. Display Success message
5358 uint32_t begsec
, endsec
;
5363 if (fdisk_get_logical_drive_count(epp
) >= MAX_EXT_PARTS
) {
5364 (void) printf("\nNumber of logical drives exceeds limit of "
5365 "%d.\n", MAX_EXT_PARTS
);
5366 (void) printf("Command did not succeed. Press enter to "
5368 ext_read_input(buf
);
5372 (void) printf("\n");
5373 rval
= ext_read_valid_partition_start(&begsec
);
5378 case FDISK_EOOBOUND
:
5379 (void) printf("\nNo space left in the extended "
5381 (void) printf("Press enter to continue\n");
5382 ext_read_input(buf
);
5386 ext_read_valid_partition_size(begsec
, &endsec
);
5387 ext_read_valid_part_id(&partid
);
5388 fdisk_add_logical_drive(epp
, begsec
, endsec
, partid
);
5390 (void) printf("New partition with ID %d added\n", partid
);
5394 ext_change_logical_drive_id()
5399 if (!fdisk_get_logical_drive_count(epp
)) {
5400 (void) printf("\nNo logical drives defined.\n");
5404 (void) printf("\n");
5405 ext_read_valid_part_num(&pno
);
5406 ext_read_valid_part_id(&partid
);
5407 fdisk_change_logical_drive_id(epp
, pno
, partid
);
5409 (void) printf("Partition ID of partition %d changed to %d\n", pno
,
5415 ext_print_logdrive_layout_debug()
5419 logical_drive_t
*head
= fdisk_get_ld_head(epp
);
5420 logical_drive_t
*temp
;
5422 if (!fdisk_get_logical_drive_count(epp
)) {
5423 (void) printf("\nNo logical drives defined.\n");
5427 (void) printf("\n\n");
5428 puts("# start block end block abs start abs end OSType");
5429 for (temp
= head
, pno
= 5; temp
!= NULL
; temp
= temp
->next
, pno
++) {
5430 /* Print the logical drive details */
5431 id_to_name(temp
->parts
[0].systid
, namebuff
);
5432 (void) printf("%d: %.10u %.10u %.10u %.10u",
5434 LE_32(temp
->parts
[0].relsect
),
5435 LE_32(temp
->parts
[0].numsect
),
5437 temp
->abs_secnum
+ temp
->numsect
- 1 +
5438 MAX_LOGDRIVE_OFFSET
);
5439 (void) printf(" %s\n", namebuff
);
5441 * Print the second entry in the EBR which is information
5442 * about the location and the size of the next extended
5445 id_to_name(temp
->parts
[1].systid
, namebuff
);
5446 (void) printf("%d: %.10u %.10u %.10s %.10s",
5448 LE_32(temp
->parts
[1].relsect
),
5449 LE_32(temp
->parts
[1].numsect
),
5451 (void) printf(" %s\n", namebuff
);
5457 ext_print_logical_drive_layout()
5460 unsigned int startcyl
, endcyl
, length
, percent
, remainder
;
5461 logical_drive_t
*temp
;
5462 uint32_t part_start
;
5463 struct ipart
*fpart
;
5465 int numcyl
= fdisk_get_disk_geom(epp
, PHYSGEOM
, NCYL
);
5468 if (numcyl
== EINVAL
) {
5469 (void) fprintf(stderr
, "Unsupported geometry statistics.\n");
5473 if (!fdisk_get_logical_drive_count(epp
)) {
5474 (void) printf("\nNo logical drives defined.\n");
5478 (void) printf("\n");
5479 (void) printf("Number of cylinders in disk : %u\n",
5481 (void) printf("Beginning cylinder of extended partition : %u\n",
5482 fdisk_get_ext_beg_cyl(epp
));
5483 (void) printf("Ending cylinder of extended partition : %u\n",
5484 fdisk_get_ext_end_cyl(epp
));
5485 (void) printf("\n");
5486 (void) printf("Part# StartCyl EndCyl Length %% "
5487 "Part ID (Type)\n");
5488 (void) printf("===== ======== ======== ======= ==="
5489 " ==============\n");
5490 for (temp
= fdisk_get_ld_head(epp
), pno
= 5; temp
!= NULL
;
5491 temp
= temp
->next
, pno
++) {
5492 /* Print the logical drive details */
5493 fpart
= &temp
->parts
[0];
5494 sysid
= fpart
->systid
;
5496 * Check if partition id 0x82 is Solaris
5497 * or a Linux swap. Print the string
5500 if (sysid
== SUNIXOS
) {
5501 part_start
= temp
->abs_secnum
+
5502 temp
->logdrive_offset
;
5503 if (fdisk_is_linux_swap(epp
, part_start
,
5505 (void) strcpy(namebuff
, LINSWAPstr
);
5507 (void) strcpy(namebuff
, SUstr
);
5509 id_to_name(sysid
, namebuff
);
5511 startcyl
= temp
->begcyl
;
5512 endcyl
= temp
->endcyl
;
5513 if (startcyl
== endcyl
) {
5516 length
= endcyl
- startcyl
+ 1;
5518 percent
= length
* 100 / numcyl
;
5519 if ((remainder
= (length
* 100 % numcyl
)) != 0) {
5520 if ((remainder
* 100 / numcyl
) > 50) {
5524 /* Else leave the percent as is since it's already */
5527 if (percent
> 100) {
5530 (void) printf("%-5d %-8u %-8u %-7u %-3d "
5532 pno
, startcyl
, endcyl
, length
, percent
, sysid
, namebuff
);
5535 ext_print_logdrive_layout_debug();
5537 (void) printf("\n");
5541 ext_print_help_menu()
5543 (void) printf("\n");
5544 (void) printf("a Add a logical drive\n");
5545 (void) printf("d Delete a logical drive\n");
5546 (void) printf("h Print this help menu\n");
5547 (void) printf("i Change the id of the logical drive\n");
5548 (void) printf("p Print the logical drive layout\n");
5549 (void) printf("r Return to the main fdisk menu\n");
5550 (void) printf(" (To commit or cancel the changes)\n");
5551 (void) printf("\n");
5559 static int bbsig_disp_flag
= 1;
5563 (void) printf(CLR_SCR
);
5565 if (fdisk_corrupt_logical_drives(epp
)) {
5566 (void) printf("One or more logical drives seem to be "
5568 (void) printf("Displaying only sane logical drives.\n");
5571 if (bbsig_disp_flag
&& fdisk_invalid_bb_sig(epp
, &bbsigp
)) {
5572 (void) printf("The following logical drives have a wrong "
5573 "boot block signature :\n\n");
5574 for (i
= 0; bbsigp
[i
]; i
++) {
5575 (void) printf("%d ", bbsigp
[i
]);
5577 (void) printf("\n\n");
5578 (void) printf("They will be corrected when you choose to "
5580 bbsig_disp_flag
= 0;
5583 (void) printf("Extended partition menu\n");
5586 (void) printf("\nEnter Command (Type h for help) : ");
5587 if ((ext_read_options(buf
)) < 0) {
5588 (void) printf("\nCommand Options : \n");
5589 ext_print_help_menu();
5594 add_logical_drive();
5597 delete_logical_drive();
5600 ext_print_help_menu();
5603 ext_change_logical_drive_id();
5606 ext_print_logical_drive_layout();
5609 (void) printf(CLR_SCR
);
5611 default : /* NOTREACHED */
5623 for (i
= 0; i
< FD_NUMPART
; i
++)
5624 if (Table
[i
].systid
!= UNUSED
)