1 /* vi: set sw=4 ts=4: */
2 /* fdisk.c -- Partition table manipulator for Linux.
4 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
10 #ifndef _LARGEFILE64_SOURCE
12 #define _LARGEFILE64_SOURCE
14 #include <assert.h> /* assert */
17 /* Looks like someone forgot to add this to config system */
18 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
19 # define ENABLE_FEATURE_FDISK_BLKSIZE 0
20 # define USE_FEATURE_FDISK_BLKSIZE(a)
23 #define DEFAULT_SECTOR_SIZE 512
24 #define MAX_SECTOR_SIZE 2048
25 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
26 #define MAXIMUM_PARTS 60
28 #define ACTIVE_FLAG 0x80
31 #define WIN98_EXTENDED 0x0f
32 #define LINUX_PARTITION 0x81
33 #define LINUX_SWAP 0x82
34 #define LINUX_NATIVE 0x83
35 #define LINUX_EXTENDED 0x85
36 #define LINUX_LVM 0x8e
37 #define LINUX_RAID 0xfd
39 /* Used for sector numbers. Today's disk sizes make it necessary */
40 typedef unsigned long long ullong;
44 unsigned char sectors;
45 unsigned short cylinders;
49 #define HDIO_GETGEO 0x0301 /* get device geometry */
51 static const char msg_building_new_label[] =
52 "Building a new %s. Changes will remain in memory only,\n"
53 "until you decide to write them. After that the previous content\n"
54 "won't be recoverable.\n\n";
56 static const char msg_part_already_defined[] =
57 "Partition %d is already defined, delete it before re-adding\n";
60 static unsigned sector_size = DEFAULT_SECTOR_SIZE;
61 static unsigned user_set_sector_size;
62 static unsigned sector_offset = 1;
64 #if ENABLE_FEATURE_OSF_LABEL
65 static int possibly_osf_label;
68 static unsigned heads, sectors, cylinders;
69 static void update_units(void);
73 unsigned char boot_ind; /* 0x80 - active */
74 unsigned char head; /* starting head */
75 unsigned char sector; /* starting sector */
76 unsigned char cyl; /* starting cylinder */
77 unsigned char sys_ind; /* What partition type */
78 unsigned char end_head; /* end head */
79 unsigned char end_sector; /* end sector */
80 unsigned char end_cyl; /* end cylinder */
81 unsigned char start4[4]; /* starting sector counting from 0 */
82 unsigned char size4[4]; /* nr of sectors in partition */
85 static const char unable_to_open[] = "cannot open %s";
86 static const char unable_to_read[] = "cannot read from %s";
87 static const char unable_to_seek[] = "cannot seek on %s";
88 static const char unable_to_write[] = "cannot write to %s";
89 static const char ioctl_error[] = "BLKGETSIZE ioctl failed on %s";
90 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
93 label_dos, label_sun, label_sgi, label_aix, label_osf
96 #define LABEL_IS_DOS (label_dos == current_label_type)
98 #if ENABLE_FEATURE_SUN_LABEL
99 #define LABEL_IS_SUN (label_sun == current_label_type)
100 #define STATIC_SUN static
102 #define LABEL_IS_SUN 0
103 #define STATIC_SUN extern
106 #if ENABLE_FEATURE_SGI_LABEL
107 #define LABEL_IS_SGI (label_sgi == current_label_type)
108 #define STATIC_SGI static
110 #define LABEL_IS_SGI 0
111 #define STATIC_SGI extern
114 #if ENABLE_FEATURE_AIX_LABEL
115 #define LABEL_IS_AIX (label_aix == current_label_type)
116 #define STATIC_AIX static
118 #define LABEL_IS_AIX 0
119 #define STATIC_AIX extern
122 #if ENABLE_FEATURE_OSF_LABEL
123 #define LABEL_IS_OSF (label_osf == current_label_type)
124 #define STATIC_OSF static
126 #define LABEL_IS_OSF 0
127 #define STATIC_OSF extern
130 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
132 static enum label_type current_label_type;
134 static const char *disk_device;
135 static int fd; /* the disk */
136 static int partitions = 4; /* maximum partition + 1 */
137 static int display_in_cyl_units = 1;
138 static unsigned units_per_sector = 1;
139 #if ENABLE_FEATURE_FDISK_WRITABLE
140 static void change_units(void);
141 static void reread_partition_table(int leave);
142 static void delete_partition(int i);
143 static int get_partition(int warn, int max);
144 static void list_types(const char *const *sys);
145 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
147 static const char *partition_type(unsigned char type);
148 static void get_geometry(void);
149 static int get_boot(enum action what);
154 static unsigned get_start_sect(const struct partition *p);
155 static unsigned get_nr_sects(const struct partition *p);
158 * per partition table entry data
160 * The four primary partitions have the same sectorbuffer (MBRbuffer)
161 * and have NULL ext_pointer.
162 * Each logical partition table entry has two pointers, one for the
163 * partition and one link to the next one.
166 struct partition *part_table; /* points into sectorbuffer */
167 struct partition *ext_pointer; /* points into sectorbuffer */
168 ullong offset; /* disk sector number */
169 char *sectorbuffer; /* disk sector contents */
170 #if ENABLE_FEATURE_FDISK_WRITABLE
171 char changed; /* boolean */
175 /* DOS partition types */
177 static const char *const i386_sys_types[] = {
181 "\x05" "Extended", /* DOS 3.3+ extended partition */
182 "\x06" "FAT16", /* DOS 16-bit >=32M */
183 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
184 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
185 "\x0b" "Win95 FAT32",
186 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
187 "\x0e" "Win95 FAT16 (LBA)",
188 "\x0f" "Win95 Ext'd (LBA)",
189 "\x11" "Hidden FAT12",
190 "\x12" "Compaq diagnostics",
191 "\x14" "Hidden FAT16 <32M",
192 "\x16" "Hidden FAT16",
193 "\x17" "Hidden HPFS/NTFS",
194 "\x1b" "Hidden Win95 FAT32",
195 "\x1c" "Hidden W95 FAT32 (LBA)",
196 "\x1e" "Hidden W95 FAT16 (LBA)",
197 "\x3c" "Part.Magic recovery",
198 "\x41" "PPC PReP Boot",
200 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
201 "\x80" "Old Minix", /* Minix 1.4a and earlier */
202 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
203 "\x82" "Linux swap", /* also Solaris */
205 "\x84" "OS/2 hidden C: drive",
206 "\x85" "Linux extended",
207 "\x86" "NTFS volume set",
208 "\x87" "NTFS volume set",
210 "\x9f" "BSD/OS", /* BSDI */
211 "\xa0" "Thinkpad hibernation",
212 "\xa5" "FreeBSD", /* various BSD flavours */
216 "\xab" "Darwin boot",
219 "\xbe" "Solaris boot",
221 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
222 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
223 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
224 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
225 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
226 autodetect using persistent
228 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
231 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
232 "\x09" "AIX bootable", /* AIX data or Coherent */
234 "\x18" "AST SmartSleep",
237 "\x40" "Venix 80286",
239 "\x4e" "QNX4.x 2nd part",
240 "\x4f" "QNX4.x 3rd part",
242 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
243 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
244 "\x53" "OnTrack DM6 Aux3",
248 "\x5c" "Priam Edisk",
250 "\x64" "Novell Netware 286",
251 "\x65" "Novell Netware 386",
252 "\x70" "DiskSecure Multi-Boot",
255 "\x94" "Amoeba BBT", /* (bad block table) */
257 "\xbb" "Boot Wizard hidden",
258 "\xc1" "DRDOS/sec (FAT-12)",
259 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
260 "\xc6" "DRDOS/sec (FAT-16)",
262 "\xda" "Non-FS data",
263 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
264 Concurrent DOS or CTOS */
265 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
266 "\xdf" "BootIt", /* BootIt EMBRM */
267 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
268 extended partition */
269 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
270 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
271 partition < 1024 cyl. */
273 "\xf4" "SpeedStor", /* SpeedStor large partition */
274 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
275 "\xff" "BBT", /* Xenix Bad Block Table */
285 char line_buffer[80];
286 char partname_buffer[80];
288 /* Raw disk label. For DOS-type partition tables the MBR,
289 * with descriptions of the primary partitions. */
290 char MBRbuffer[MAX_SECTOR_SIZE];
291 /* Partition tables */
292 struct pte ptes[MAXIMUM_PARTS];
294 /* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
295 #define G (*ptr_to_globals)
297 #define line_ptr (G.line_ptr)
298 #define listingbuf (G.listingbuf)
299 #define line_buffer (G.line_buffer)
300 #define partname_buffer (G.partname_buffer)
301 #define MBRbuffer (G.MBRbuffer)
302 #define ptes (G.ptes)
307 #define IS_EXTENDED(i) \
308 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
310 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
312 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
314 #define pt_offset(b, n) \
315 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
317 #define sector(s) ((s) & 0x3f)
319 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
321 #define hsc2sector(h,s,c) \
322 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
324 #define set_hsc(h,s,c,sector) \
326 s = sector % sectors + 1; \
328 h = sector % heads; \
331 s |= (sector >> 2) & 0xc0; \
334 #if ENABLE_FEATURE_FDISK_WRITABLE
335 /* read line; return 0 or first printable char */
337 read_line(const char *prompt)
341 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
343 exit(0); /* Ctrl-D or Ctrl-C */
345 if (line_buffer[sz-1] == '\n')
346 line_buffer[--sz] = '\0';
348 line_ptr = line_buffer;
349 while (*line_ptr && !isgraph(*line_ptr))
356 * return partition name - uses static storage
359 partname(const char *dev, int pno, int lth)
366 bufp = partname_buffer;
367 bufsiz = sizeof(partname_buffer);
372 if (isdigit(dev[w-1]))
375 /* devfs kludge - note: fdisk partition names are not supposed
376 to equal kernel names, so there is no reason to do this */
377 if (strcmp(dev + w - 4, "disc") == 0) {
385 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
386 lth-wp-2, w, dev, p, pno);
388 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
393 #if ENABLE_FEATURE_FDISK_WRITABLE
395 set_all_unchanged(void)
399 for (i = 0; i < MAXIMUM_PARTS; i++)
403 static ALWAYS_INLINE void
408 #endif /* FEATURE_FDISK_WRITABLE */
410 static ALWAYS_INLINE struct partition *
411 get_part_table(int i)
413 return ptes[i].part_table;
418 { /* n==1: use singular */
420 return display_in_cyl_units ? "cylinder" : "sector";
421 return display_in_cyl_units ? "cylinders" : "sectors";
425 valid_part_table_flag(const char *mbuffer)
427 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
430 #if ENABLE_FEATURE_FDISK_WRITABLE
431 static ALWAYS_INLINE void
432 write_part_table_flag(char *b)
439 read_nonempty(const char *mesg)
441 while (!read_line(mesg)) /* repeat */;
446 read_maybe_empty(const char *mesg)
448 if (!read_line(mesg)) {
449 line_ptr = line_buffer;
457 read_hex(const char *const *sys)
461 read_nonempty("Hex code (type L to list codes): ");
462 if (*line_ptr == 'l' || *line_ptr == 'L') {
466 v = bb_strtoul(line_ptr, NULL, 16);
468 /* Bad input also triggers this */
473 #endif /* FEATURE_FDISK_WRITABLE */
475 #include "fdisk_aix.c"
478 unsigned char info[128]; /* Informative text string */
479 unsigned char spare0[14];
481 unsigned char spare1;
483 unsigned char spare2;
486 unsigned char spare1[246]; /* Boot information etc. */
487 unsigned short rspeed; /* Disk rotational speed */
488 unsigned short pcylcount; /* Physical cylinder count */
489 unsigned short sparecyl; /* extra sects per cylinder */
490 unsigned char spare2[4]; /* More magic... */
491 unsigned short ilfact; /* Interleave factor */
492 unsigned short ncyl; /* Data cylinder count */
493 unsigned short nacyl; /* Alt. cylinder count */
494 unsigned short ntrks; /* Tracks per cylinder */
495 unsigned short nsect; /* Sectors per track */
496 unsigned char spare3[4]; /* Even more magic... */
497 struct sun_partinfo {
498 uint32_t start_cylinder;
499 uint32_t num_sectors;
501 unsigned short magic; /* Magic number */
502 unsigned short csum; /* Label xor'd checksum */
504 #define sunlabel ((sun_partition *)MBRbuffer)
505 STATIC_OSF void bsd_select(void);
506 STATIC_OSF void xbsd_print_disklabel(int);
507 #include "fdisk_osf.c"
509 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
511 fdisk_swap16(uint16_t x)
513 return (x << 8) | (x >> 8);
517 fdisk_swap32(uint32_t x)
520 ((x & 0xFF00) << 8) |
521 ((x & 0xFF0000) >> 8) |
526 STATIC_SGI const char *const sgi_sys_types[];
527 STATIC_SGI unsigned sgi_get_num_sectors(int i);
528 STATIC_SGI int sgi_get_sysid(int i);
529 STATIC_SGI void sgi_delete_partition(int i);
530 STATIC_SGI void sgi_change_sysid(int i, int sys);
531 STATIC_SGI void sgi_list_table(int xtra);
532 #if ENABLE_FEATURE_FDISK_ADVANCED
533 STATIC_SGI void sgi_set_xcyl(void);
535 STATIC_SGI int verify_sgi(int verbose);
536 STATIC_SGI void sgi_add_partition(int n, int sys);
537 STATIC_SGI void sgi_set_swappartition(int i);
538 STATIC_SGI const char *sgi_get_bootfile(void);
539 STATIC_SGI void sgi_set_bootfile(const char* aFile);
540 STATIC_SGI void create_sgiinfo(void);
541 STATIC_SGI void sgi_write_table(void);
542 STATIC_SGI void sgi_set_bootpartition(int i);
543 #include "fdisk_sgi.c"
545 STATIC_SUN const char *const sun_sys_types[];
546 STATIC_SUN void sun_delete_partition(int i);
547 STATIC_SUN void sun_change_sysid(int i, int sys);
548 STATIC_SUN void sun_list_table(int xtra);
549 STATIC_SUN void add_sun_partition(int n, int sys);
550 #if ENABLE_FEATURE_FDISK_ADVANCED
551 STATIC_SUN void sun_set_alt_cyl(void);
552 STATIC_SUN void sun_set_ncyl(int cyl);
553 STATIC_SUN void sun_set_xcyl(void);
554 STATIC_SUN void sun_set_ilfact(void);
555 STATIC_SUN void sun_set_rspeed(void);
556 STATIC_SUN void sun_set_pcylcount(void);
558 STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
559 STATIC_SUN void verify_sun(void);
560 STATIC_SUN void sun_write_table(void);
561 #include "fdisk_sun.c"
563 #if ENABLE_FEATURE_FDISK_WRITABLE
564 /* start_sect and nr_sects are stored little endian on all machines */
565 /* moreover, they are not aligned correctly */
567 store4_little_endian(unsigned char *cp, unsigned val)
574 #endif /* FEATURE_FDISK_WRITABLE */
577 read4_little_endian(const unsigned char *cp)
579 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
582 #if ENABLE_FEATURE_FDISK_WRITABLE
584 set_start_sect(struct partition *p, unsigned start_sect)
586 store4_little_endian(p->start4, start_sect);
591 get_start_sect(const struct partition *p)
593 return read4_little_endian(p->start4);
596 #if ENABLE_FEATURE_FDISK_WRITABLE
598 set_nr_sects(struct partition *p, unsigned nr_sects)
600 store4_little_endian(p->size4, nr_sects);
605 get_nr_sects(const struct partition *p)
607 return read4_little_endian(p->size4);
610 /* normally O_RDWR, -l option gives O_RDONLY */
611 static int type_open = O_RDWR;
613 static int ext_index; /* the prime extended partition */
614 static int listing; /* no aborts for fdisk -l */
615 static int dos_compatible_flag = ~0;
616 #if ENABLE_FEATURE_FDISK_WRITABLE
617 static int dos_changed;
618 static int nowarn; /* no warnings for fdisk -l/-s */
621 static unsigned user_cylinders, user_heads, user_sectors;
622 static unsigned pt_heads, pt_sectors;
623 static unsigned kern_heads, kern_sectors;
625 static ullong extended_offset; /* offset of link pointers */
626 static ullong total_number_of_sectors;
628 static void fdisk_fatal(const char *why)
632 longjmp(listingbuf, 1);
634 bb_error_msg_and_die(why, disk_device);
638 seek_sector(ullong secno)
640 secno *= sector_size;
641 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
642 fdisk_fatal(unable_to_seek);
645 #if ENABLE_FEATURE_FDISK_WRITABLE
647 write_sector(ullong secno, char *buf)
650 if (write(fd, buf, sector_size) != sector_size)
651 fdisk_fatal(unable_to_write);
655 /* Allocate a buffer and read a partition table sector */
657 read_pte(struct pte *pe, ullong offset)
660 pe->sectorbuffer = xmalloc(sector_size);
662 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
663 fdisk_fatal(unable_to_read);
664 #if ENABLE_FEATURE_FDISK_WRITABLE
667 pe->part_table = pe->ext_pointer = NULL;
671 get_partition_start(const struct pte *pe)
673 return pe->offset + get_start_sect(pe->part_table);
676 #if ENABLE_FEATURE_FDISK_WRITABLE
678 * Avoid warning about DOS partitions when no DOS partition was changed.
679 * Here a heuristic "is probably dos partition".
680 * We might also do the opposite and warn in all cases except
681 * for "is probably nondos partition".
684 is_dos_partition(int t)
686 return (t == 1 || t == 4 || t == 6 ||
687 t == 0x0b || t == 0x0c || t == 0x0e ||
688 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
689 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
690 t == 0xc1 || t == 0xc4 || t == 0xc6);
696 puts("Command Action");
698 puts("a\ttoggle a read only flag"); /* sun */
699 puts("b\tedit bsd disklabel");
700 puts("c\ttoggle the mountable flag"); /* sun */
701 puts("d\tdelete a partition");
702 puts("l\tlist known partition types");
703 puts("n\tadd a new partition");
704 puts("o\tcreate a new empty DOS partition table");
705 puts("p\tprint the partition table");
706 puts("q\tquit without saving changes");
707 puts("s\tcreate a new empty Sun disklabel"); /* sun */
708 puts("t\tchange a partition's system id");
709 puts("u\tchange display/entry units");
710 puts("v\tverify the partition table");
711 puts("w\twrite table to disk and exit");
712 #if ENABLE_FEATURE_FDISK_ADVANCED
713 puts("x\textra functionality (experts only)");
715 } else if (LABEL_IS_SGI) {
716 puts("a\tselect bootable partition"); /* sgi flavour */
717 puts("b\tedit bootfile entry"); /* sgi */
718 puts("c\tselect sgi swap partition"); /* sgi flavour */
719 puts("d\tdelete a partition");
720 puts("l\tlist known partition types");
721 puts("n\tadd a new partition");
722 puts("o\tcreate a new empty DOS partition table");
723 puts("p\tprint the partition table");
724 puts("q\tquit without saving changes");
725 puts("s\tcreate a new empty Sun disklabel"); /* sun */
726 puts("t\tchange a partition's system id");
727 puts("u\tchange display/entry units");
728 puts("v\tverify the partition table");
729 puts("w\twrite table to disk and exit");
730 } else if (LABEL_IS_AIX) {
731 puts("o\tcreate a new empty DOS partition table");
732 puts("q\tquit without saving changes");
733 puts("s\tcreate a new empty Sun disklabel"); /* sun */
735 puts("a\ttoggle a bootable flag");
736 puts("b\tedit bsd disklabel");
737 puts("c\ttoggle the dos compatibility flag");
738 puts("d\tdelete a partition");
739 puts("l\tlist known partition types");
740 puts("n\tadd a new partition");
741 puts("o\tcreate a new empty DOS partition table");
742 puts("p\tprint the partition table");
743 puts("q\tquit without saving changes");
744 puts("s\tcreate a new empty Sun disklabel"); /* sun */
745 puts("t\tchange a partition's system id");
746 puts("u\tchange display/entry units");
747 puts("v\tverify the partition table");
748 puts("w\twrite table to disk and exit");
749 #if ENABLE_FEATURE_FDISK_ADVANCED
750 puts("x\textra functionality (experts only)");
754 #endif /* FEATURE_FDISK_WRITABLE */
757 #if ENABLE_FEATURE_FDISK_ADVANCED
761 puts("Command Action");
763 puts("a\tchange number of alternate cylinders"); /*sun*/
764 puts("c\tchange number of cylinders");
765 puts("d\tprint the raw data in the partition table");
766 puts("e\tchange number of extra sectors per cylinder");/*sun*/
767 puts("h\tchange number of heads");
768 puts("i\tchange interleave factor"); /*sun*/
769 puts("o\tchange rotation speed (rpm)"); /*sun*/
770 puts("p\tprint the partition table");
771 puts("q\tquit without saving changes");
772 puts("r\treturn to main menu");
773 puts("s\tchange number of sectors/track");
774 puts("v\tverify the partition table");
775 puts("w\twrite table to disk and exit");
776 puts("y\tchange number of physical cylinders"); /*sun*/
777 } else if (LABEL_IS_SGI) {
778 puts("b\tmove beginning of data in a partition"); /* !sun */
779 puts("c\tchange number of cylinders");
780 puts("d\tprint the raw data in the partition table");
781 puts("e\tlist extended partitions"); /* !sun */
782 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
783 puts("h\tchange number of heads");
784 puts("p\tprint the partition table");
785 puts("q\tquit without saving changes");
786 puts("r\treturn to main menu");
787 puts("s\tchange number of sectors/track");
788 puts("v\tverify the partition table");
789 puts("w\twrite table to disk and exit");
790 } else if (LABEL_IS_AIX) {
791 puts("b\tmove beginning of data in a partition"); /* !sun */
792 puts("c\tchange number of cylinders");
793 puts("d\tprint the raw data in the partition table");
794 puts("e\tlist extended partitions"); /* !sun */
795 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
796 puts("h\tchange number of heads");
797 puts("p\tprint the partition table");
798 puts("q\tquit without saving changes");
799 puts("r\treturn to main menu");
800 puts("s\tchange number of sectors/track");
801 puts("v\tverify the partition table");
802 puts("w\twrite table to disk and exit");
804 puts("b\tmove beginning of data in a partition"); /* !sun */
805 puts("c\tchange number of cylinders");
806 puts("d\tprint the raw data in the partition table");
807 puts("e\tlist extended partitions"); /* !sun */
808 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
809 #if ENABLE_FEATURE_SGI_LABEL
810 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
812 puts("h\tchange number of heads");
813 puts("p\tprint the partition table");
814 puts("q\tquit without saving changes");
815 puts("r\treturn to main menu");
816 puts("s\tchange number of sectors/track");
817 puts("v\tverify the partition table");
818 puts("w\twrite table to disk and exit");
821 #endif /* ADVANCED mode */
823 #if ENABLE_FEATURE_FDISK_WRITABLE
824 static const char *const *
828 LABEL_IS_SUN ? sun_sys_types :
829 LABEL_IS_SGI ? sgi_sys_types :
833 #define get_sys_types() i386_sys_types
834 #endif /* FEATURE_FDISK_WRITABLE */
837 partition_type(unsigned char type)
840 const char *const *types = get_sys_types();
842 for (i = 0; types[i]; i++)
843 if ((unsigned char)types[i][0] == type)
850 #if ENABLE_FEATURE_FDISK_WRITABLE
854 return LABEL_IS_SUN ? sunlabel->infos[i].id :
855 (LABEL_IS_SGI ? sgi_get_sysid(i) :
856 ptes[i].part_table->sys_ind);
860 list_types(const char *const *sys)
865 unsigned done, next, size;
868 for (size = 0; sys[size]; size++) /* */;
871 for (i = COLS-1; i >= 0; i--) {
872 done += (size + i - done) / (i + 1);
873 last[COLS-1 - i] = done;
878 printf("%c%2x %-22.22s", i ? ' ' : '\n',
879 (unsigned char)sys[next][0],
881 next = last[i++] + done;
882 if (i >= COLS || next >= last[i]) {
886 } while (done < last[0]);
889 #endif /* FEATURE_FDISK_WRITABLE */
892 is_cleared_partition(const struct partition *p)
894 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
895 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
896 get_start_sect(p) || get_nr_sects(p));
900 clear_partition(struct partition *p)
904 memset(p, 0, sizeof(struct partition));
907 #if ENABLE_FEATURE_FDISK_WRITABLE
909 set_partition(int i, int doext, ullong start, ullong stop, int sysid)
915 p = ptes[i].ext_pointer;
916 offset = extended_offset;
918 p = ptes[i].part_table;
919 offset = ptes[i].offset;
923 set_start_sect(p, start - offset);
924 set_nr_sects(p, stop - start + 1);
925 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
926 start = heads*sectors*1024 - 1;
927 set_hsc(p->head, p->sector, p->cyl, start);
928 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
929 stop = heads*sectors*1024 - 1;
930 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
938 if (heads && sectors && cylinders)
941 printf("Unknown value(s) for:");
947 printf(" cylinders");
949 #if ENABLE_FEATURE_FDISK_WRITABLE
950 " (settable in the extra functions menu)"
959 int cyl_units = heads * sectors;
961 if (display_in_cyl_units && cyl_units)
962 units_per_sector = cyl_units;
964 units_per_sector = 1; /* in sectors */
967 #if ENABLE_FEATURE_FDISK_WRITABLE
971 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
973 "The number of cylinders for this disk is set to %d.\n"
974 "There is nothing wrong with that, but this is larger than 1024,\n"
975 "and could in certain setups cause problems with:\n"
976 "1) software that runs at boot time (e.g., old versions of LILO)\n"
977 "2) booting and partitioning software from other OSs\n"
978 " (e.g., DOS FDISK, OS/2 FDISK)\n",
984 read_extended(int ext)
988 struct partition *p, *q;
992 pex->ext_pointer = pex->part_table;
995 if (!get_start_sect(p)) {
996 printf("Bad offset in primary extended partition\n");
1000 while (IS_EXTENDED(p->sys_ind)) {
1001 struct pte *pe = &ptes[partitions];
1003 if (partitions >= MAXIMUM_PARTS) {
1004 /* This is not a Linux restriction, but
1005 this program uses arrays of size MAXIMUM_PARTS.
1006 Do not try to 'improve' this test. */
1007 struct pte *pre = &ptes[partitions-1];
1008 #if ENABLE_FEATURE_FDISK_WRITABLE
1009 printf("Warning: deleting partitions after %d\n",
1013 clear_partition(pre->ext_pointer);
1017 read_pte(pe, extended_offset + get_start_sect(p));
1019 if (!extended_offset)
1020 extended_offset = get_start_sect(p);
1022 q = p = pt_offset(pe->sectorbuffer, 0);
1023 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1024 if (IS_EXTENDED(p->sys_ind)) {
1025 if (pe->ext_pointer)
1026 printf("Warning: extra link "
1027 "pointer in partition table"
1028 " %d\n", partitions + 1);
1030 pe->ext_pointer = p;
1031 } else if (p->sys_ind) {
1033 printf("Warning: ignoring extra "
1034 "data in partition table"
1035 " %d\n", partitions + 1);
1041 /* very strange code here... */
1042 if (!pe->part_table) {
1043 if (q != pe->ext_pointer)
1046 pe->part_table = q + 1;
1048 if (!pe->ext_pointer) {
1049 if (q != pe->part_table)
1050 pe->ext_pointer = q;
1052 pe->ext_pointer = q + 1;
1055 p = pe->ext_pointer;
1059 #if ENABLE_FEATURE_FDISK_WRITABLE
1060 /* remove empty links */
1062 for (i = 4; i < partitions; i++) {
1063 struct pte *pe = &ptes[i];
1065 if (!get_nr_sects(pe->part_table)
1066 && (partitions > 5 || ptes[4].part_table->sys_ind)
1068 printf("Omitting empty partition (%d)\n", i+1);
1069 delete_partition(i);
1070 goto remove; /* numbering changed */
1076 #if ENABLE_FEATURE_FDISK_WRITABLE
1078 create_doslabel(void)
1082 printf(msg_building_new_label, "DOS disklabel");
1084 current_label_type = label_dos;
1086 #if ENABLE_FEATURE_OSF_LABEL
1087 possibly_osf_label = 0;
1091 for (i = 510-64; i < 510; i++)
1093 write_part_table_flag(MBRbuffer);
1094 extended_offset = 0;
1095 set_all_unchanged();
1097 get_boot(create_empty_dos);
1099 #endif /* FEATURE_FDISK_WRITABLE */
1102 get_sectorsize(void)
1104 if (!user_set_sector_size) {
1106 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1108 if (sector_size != DEFAULT_SECTOR_SIZE)
1109 printf("Note: sector size is %d (not %d)\n",
1110 sector_size, DEFAULT_SECTOR_SIZE);
1115 get_kernel_geometry(void)
1117 struct hd_geometry geometry;
1119 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1120 kern_heads = geometry.heads;
1121 kern_sectors = geometry.sectors;
1122 /* never use geometry.cylinders - it is truncated */
1127 get_partition_table_geometry(void)
1129 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1130 struct partition *p;
1131 int i, h, s, hh, ss;
1135 if (!(valid_part_table_flag((char*)bufp)))
1139 for (i = 0; i < 4; i++) {
1140 p = pt_offset(bufp, i);
1141 if (p->sys_ind != 0) {
1142 h = p->end_head + 1;
1143 s = (p->end_sector & 077);
1148 } else if (hh != h || ss != s)
1153 if (!first && !bad) {
1166 sec_fac = sector_size / 512;
1167 #if ENABLE_FEATURE_SUN_LABEL
1168 guess_device_type();
1170 heads = cylinders = sectors = 0;
1171 kern_heads = kern_sectors = 0;
1172 pt_heads = pt_sectors = 0;
1174 get_kernel_geometry();
1175 get_partition_table_geometry();
1177 heads = user_heads ? user_heads :
1178 pt_heads ? pt_heads :
1179 kern_heads ? kern_heads : 255;
1180 sectors = user_sectors ? user_sectors :
1181 pt_sectors ? pt_sectors :
1182 kern_sectors ? kern_sectors : 63;
1183 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1184 /* got bytes, convert to 512 byte sectors */
1185 total_number_of_sectors = (v64 >> 9);
1187 unsigned long longsectors; /* need temp of type long */
1188 if (ioctl(fd, BLKGETSIZE, &longsectors))
1190 total_number_of_sectors = longsectors;
1194 if (dos_compatible_flag)
1195 sector_offset = sectors;
1197 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
1199 cylinders = user_cylinders;
1203 * Read MBR. Returns:
1204 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1205 * 0: found or created label
1209 get_boot(enum action what)
1215 for (i = 0; i < 4; i++) {
1216 struct pte *pe = &ptes[i];
1218 pe->part_table = pt_offset(MBRbuffer, i);
1219 pe->ext_pointer = NULL;
1221 pe->sectorbuffer = MBRbuffer;
1222 #if ENABLE_FEATURE_FDISK_WRITABLE
1223 pe->changed = (what == create_empty_dos);
1227 #if ENABLE_FEATURE_SUN_LABEL
1228 if (what == create_empty_sun && check_sun_label())
1232 memset(MBRbuffer, 0, 512);
1234 #if ENABLE_FEATURE_FDISK_WRITABLE
1235 if (what == create_empty_dos)
1236 goto got_dos_table; /* skip reading disk */
1238 fd = open(disk_device, type_open);
1240 fd = open(disk_device, O_RDONLY);
1242 if (what == try_only)
1244 fdisk_fatal(unable_to_open);
1246 printf("You will not be able to write "
1247 "the partition table\n");
1250 if (512 != read(fd, MBRbuffer, 512)) {
1251 if (what == try_only)
1253 fdisk_fatal(unable_to_read);
1256 fd = open(disk_device, O_RDONLY);
1259 if (512 != read(fd, MBRbuffer, 512))
1267 #if ENABLE_FEATURE_SUN_LABEL
1268 if (check_sun_label())
1272 #if ENABLE_FEATURE_SGI_LABEL
1273 if (check_sgi_label())
1277 #if ENABLE_FEATURE_AIX_LABEL
1278 if (check_aix_label())
1282 #if ENABLE_FEATURE_OSF_LABEL
1283 if (check_osf_label()) {
1284 possibly_osf_label = 1;
1285 if (!valid_part_table_flag(MBRbuffer)) {
1286 current_label_type = label_osf;
1289 printf("This disk has both DOS and BSD magic.\n"
1290 "Give the 'b' command to go to BSD mode.\n");
1294 #if ENABLE_FEATURE_FDISK_WRITABLE
1298 if (!valid_part_table_flag(MBRbuffer)) {
1299 #if !ENABLE_FEATURE_FDISK_WRITABLE
1304 printf("Device contains neither a valid DOS "
1305 "partition table, nor Sun, SGI or OSF "
1308 #if ENABLE_FEATURE_SUN_LABEL
1317 case create_empty_dos:
1318 #if ENABLE_FEATURE_SUN_LABEL
1319 case create_empty_sun:
1323 bb_error_msg_and_die("internal error");
1325 #endif /* FEATURE_FDISK_WRITABLE */
1328 #if ENABLE_FEATURE_FDISK_WRITABLE
1333 for (i = 0; i < 4; i++) {
1334 struct pte *pe = &ptes[i];
1336 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1337 if (partitions != 4)
1338 printf("Ignoring extra extended "
1339 "partition %d\n", i + 1);
1345 for (i = 3; i < partitions; i++) {
1346 struct pte *pe = &ptes[i];
1348 if (!valid_part_table_flag(pe->sectorbuffer)) {
1349 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1350 "table %d will be corrected by w(rite)\n",
1351 pe->sectorbuffer[510],
1352 pe->sectorbuffer[511],
1354 #if ENABLE_FEATURE_FDISK_WRITABLE
1363 #if ENABLE_FEATURE_FDISK_WRITABLE
1365 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1366 * If the user hits Enter, DFLT is returned.
1367 * Answers like +10 are interpreted as offsets from BASE.
1369 * There is no default if DFLT is not between LOW and HIGH.
1372 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1376 const char *fmt = "%s (%u-%u, default %u): ";
1378 if (dflt < low || dflt > high) {
1379 fmt = "%s (%u-%u): ";
1384 int use_default = default_ok;
1386 /* ask question and read answer */
1388 printf(fmt, mesg, low, high, dflt);
1389 read_maybe_empty("");
1390 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1391 && *line_ptr != '-' && *line_ptr != '+');
1393 if (*line_ptr == '+' || *line_ptr == '-') {
1394 int minus = (*line_ptr == '-');
1397 i = atoi(line_ptr + 1);
1399 while (isdigit(*++line_ptr))
1402 switch (*line_ptr) {
1405 if (!display_in_cyl_units)
1406 i *= heads * sectors;
1420 absolute = 1000000000;
1429 bytes = (ullong) i * absolute;
1430 unit = sector_size * units_per_sector;
1431 bytes += unit/2; /* round */
1440 while (isdigit(*line_ptr)) {
1447 printf("Using default value %u\n", i);
1449 if (i >= low && i <= high)
1451 printf("Value is out of range\n");
1457 get_partition(int warn, int max)
1462 i = read_int(1, 0, max, 0, "Partition number") - 1;
1466 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1467 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1468 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1470 printf("Warning: partition %d has empty type\n", i+1);
1477 get_existing_partition(int warn, int max)
1482 for (i = 0; i < max; i++) {
1483 struct pte *pe = &ptes[i];
1484 struct partition *p = pe->part_table;
1486 if (p && !is_cleared_partition(p)) {
1493 printf("Selected partition %d\n", pno+1);
1496 printf("No partition is defined yet!\n");
1500 return get_partition(warn, max);
1504 get_nonexisting_partition(int warn, int max)
1509 for (i = 0; i < max; i++) {
1510 struct pte *pe = &ptes[i];
1511 struct partition *p = pe->part_table;
1513 if (p && is_cleared_partition(p)) {
1520 printf("Selected partition %d\n", pno+1);
1523 printf("All primary partitions have been defined already!\n");
1527 return get_partition(warn, max);
1534 display_in_cyl_units = !display_in_cyl_units;
1536 printf("Changing display/entry units to %s\n",
1541 toggle_active(int i)
1543 struct pte *pe = &ptes[i];
1544 struct partition *p = pe->part_table;
1546 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1547 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1548 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1553 toggle_dos_compatibility_flag(void)
1555 dos_compatible_flag = ~dos_compatible_flag;
1556 if (dos_compatible_flag) {
1557 sector_offset = sectors;
1558 printf("DOS Compatibility flag is set\n");
1561 printf("DOS Compatibility flag is not set\n");
1566 delete_partition(int i)
1568 struct pte *pe = &ptes[i];
1569 struct partition *p = pe->part_table;
1570 struct partition *q = pe->ext_pointer;
1572 /* Note that for the fifth partition (i == 4) we don't actually
1573 * decrement partitions.
1576 if (warn_geometry())
1577 return; /* C/H/S not set */
1581 sun_delete_partition(i);
1585 sgi_delete_partition(i);
1590 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1592 ptes[ext_index].ext_pointer = NULL;
1593 extended_offset = 0;
1599 if (!q->sys_ind && i > 4) {
1600 /* the last one in the chain - just delete */
1603 clear_partition(ptes[i].ext_pointer);
1604 ptes[i].changed = 1;
1606 /* not the last one - further ones will be moved down */
1608 /* delete this link in the chain */
1609 p = ptes[i-1].ext_pointer;
1611 set_start_sect(p, get_start_sect(q));
1612 set_nr_sects(p, get_nr_sects(q));
1613 ptes[i-1].changed = 1;
1614 } else if (partitions > 5) { /* 5 will be moved to 4 */
1615 /* the first logical in a longer chain */
1618 if (pe->part_table) /* prevent SEGFAULT */
1619 set_start_sect(pe->part_table,
1620 get_partition_start(pe) -
1622 pe->offset = extended_offset;
1626 if (partitions > 5) {
1628 while (i < partitions) {
1629 ptes[i] = ptes[i+1];
1633 /* the only logical: clear only */
1634 clear_partition(ptes[i].part_table);
1641 int i, sys, origsys;
1642 struct partition *p;
1644 /* If sgi_label then don't use get_existing_partition,
1645 let the user select a partition, since get_existing_partition()
1646 only works for Linux like partition tables. */
1647 if (!LABEL_IS_SGI) {
1648 i = get_existing_partition(0, partitions);
1650 i = get_partition(0, partitions);
1654 p = ptes[i].part_table;
1655 origsys = sys = get_sysid(i);
1657 /* if changing types T to 0 is allowed, then
1658 the reverse change must be allowed, too */
1659 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1660 printf("Partition %d does not exist yet!\n", i + 1);
1664 sys = read_hex(get_sys_types());
1666 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1667 printf("Type 0 means free space to many systems\n"
1668 "(but not to Linux). Having partitions of\n"
1669 "type 0 is probably unwise.\n");
1673 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1674 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1675 printf("You cannot change a partition into"
1676 " an extended one or vice versa\n");
1682 #if ENABLE_FEATURE_SUN_LABEL
1683 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1684 printf("Consider leaving partition 3 "
1685 "as Whole disk (5),\n"
1686 "as SunOS/Solaris expects it and "
1687 "even Linux likes it\n\n");
1689 #if ENABLE_FEATURE_SGI_LABEL
1692 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1693 (i == 8 && sys != 0)
1696 printf("Consider leaving partition 9 "
1697 "as volume header (0),\nand "
1698 "partition 11 as entire volume (6)"
1699 "as IRIX expects it\n\n");
1705 sun_change_sysid(i, sys);
1706 } else if (LABEL_IS_SGI) {
1707 sgi_change_sysid(i, sys);
1711 printf("Changed system type of partition %d "
1712 "to %x (%s)\n", i + 1, sys,
1713 partition_type(sys));
1714 ptes[i].changed = 1;
1715 if (is_dos_partition(origsys) ||
1716 is_dos_partition(sys))
1722 #endif /* FEATURE_FDISK_WRITABLE */
1725 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1726 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1727 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1728 * Lubkin Oct. 1991). */
1731 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1733 int spc = heads * sectors;
1738 *s = ls % sectors + 1; /* sectors count from 1 */
1742 check_consistency(const struct partition *p, int partition)
1744 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1745 unsigned pec, peh, pes; /* physical ending c, h, s */
1746 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1747 unsigned lec, leh, les; /* logical ending c, h, s */
1749 if (!heads || !sectors || (partition >= 4))
1750 return; /* do not check extended partitions */
1752 /* physical beginning c, h, s */
1753 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1755 pbs = p->sector & 0x3f;
1757 /* physical ending c, h, s */
1758 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1760 pes = p->end_sector & 0x3f;
1762 /* compute logical beginning (c, h, s) */
1763 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1765 /* compute logical ending (c, h, s) */
1766 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1768 /* Same physical / logical beginning? */
1769 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1770 printf("Partition %d has different physical/logical "
1771 "beginnings (non-Linux?):\n", partition + 1);
1772 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1773 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1776 /* Same physical / logical ending? */
1777 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1778 printf("Partition %d has different physical/logical "
1779 "endings:\n", partition + 1);
1780 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1781 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1784 /* Ending on cylinder boundary? */
1785 if (peh != (heads - 1) || pes != sectors) {
1786 printf("Partition %i does not end on cylinder boundary\n",
1792 list_disk_geometry(void)
1794 long long bytes = (total_number_of_sectors << 9);
1795 long megabytes = bytes/1000000;
1797 if (megabytes < 10000)
1798 printf("\nDisk %s: %ld MB, %lld bytes\n",
1799 disk_device, megabytes, bytes);
1801 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1802 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1803 printf("%d heads, %d sectors/track, %d cylinders",
1804 heads, sectors, cylinders);
1805 if (units_per_sector == 1)
1806 printf(", total %llu sectors",
1807 total_number_of_sectors / (sector_size/512));
1808 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1810 units_per_sector, sector_size, units_per_sector * sector_size);
1814 * Check whether partition entries are ordered by their starting positions.
1815 * Return 0 if OK. Return i if partition i should have been earlier.
1816 * Two separate checks: primary and logical partitions.
1819 wrong_p_order(int *prev)
1821 const struct pte *pe;
1822 const struct partition *p;
1823 ullong last_p_start_pos = 0, p_start_pos;
1826 for (i = 0 ; i < partitions; i++) {
1829 last_p_start_pos = 0;
1832 if ((p = pe->part_table)->sys_ind) {
1833 p_start_pos = get_partition_start(pe);
1835 if (last_p_start_pos > p_start_pos) {
1841 last_p_start_pos = p_start_pos;
1848 #if ENABLE_FEATURE_FDISK_ADVANCED
1850 * Fix the chain of logicals.
1851 * extended_offset is unchanged, the set of sectors used is unchanged
1852 * The chain is sorted so that sectors increase, and so that
1853 * starting sectors increase.
1855 * After this it may still be that cfdisk doesnt like the table.
1856 * (This is because cfdisk considers expanded parts, from link to
1857 * end of partition, and these may still overlap.)
1859 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1863 fix_chain_of_logicals(void)
1865 int j, oj, ojj, sj, sjj;
1866 struct partition *pj,*pjj,tmp;
1868 /* Stage 1: sort sectors but leave sector of part 4 */
1869 /* (Its sector is the global extended_offset.) */
1871 for (j = 5; j < partitions-1; j++) {
1872 oj = ptes[j].offset;
1873 ojj = ptes[j+1].offset;
1875 ptes[j].offset = ojj;
1876 ptes[j+1].offset = oj;
1877 pj = ptes[j].part_table;
1878 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1879 pjj = ptes[j+1].part_table;
1880 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1881 set_start_sect(ptes[j-1].ext_pointer,
1882 ojj-extended_offset);
1883 set_start_sect(ptes[j].ext_pointer,
1884 oj-extended_offset);
1889 /* Stage 2: sort starting sectors */
1891 for (j = 4; j < partitions-1; j++) {
1892 pj = ptes[j].part_table;
1893 pjj = ptes[j+1].part_table;
1894 sj = get_start_sect(pj);
1895 sjj = get_start_sect(pjj);
1896 oj = ptes[j].offset;
1897 ojj = ptes[j+1].offset;
1898 if (oj+sj > ojj+sjj) {
1902 set_start_sect(pj, ojj+sjj-oj);
1903 set_start_sect(pjj, oj+sj-ojj);
1908 /* Probably something was changed */
1909 for (j = 4; j < partitions; j++)
1910 ptes[j].changed = 1;
1915 fix_partition_table_order(void)
1917 struct pte *pei, *pek;
1920 if (!wrong_p_order(NULL)) {
1921 printf("Ordering is already correct\n\n");
1925 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1926 /* partition i should have come earlier, move it */
1927 /* We have to move data in the MBR */
1928 struct partition *pi, *pk, *pe, pbuf;
1932 pe = pei->ext_pointer;
1933 pei->ext_pointer = pek->ext_pointer;
1934 pek->ext_pointer = pe;
1936 pi = pei->part_table;
1937 pk = pek->part_table;
1939 memmove(&pbuf, pi, sizeof(struct partition));
1940 memmove(pi, pk, sizeof(struct partition));
1941 memmove(pk, &pbuf, sizeof(struct partition));
1943 pei->changed = pek->changed = 1;
1947 fix_chain_of_logicals();
1955 list_table(int xtra)
1957 const struct partition *p;
1961 sun_list_table(xtra);
1965 sgi_list_table(xtra);
1969 list_disk_geometry();
1972 xbsd_print_disklabel(xtra);
1976 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1977 but if the device name ends in a digit, say /dev/foo1,
1978 then the partition is called /dev/foo1p3. */
1979 w = strlen(disk_device);
1980 if (w && isdigit(disk_device[w-1]))
1985 // 1 12345678901 12345678901 12345678901 12
1986 printf("%*s Boot Start End Blocks Id System\n",
1989 for (i = 0; i < partitions; i++) {
1990 const struct pte *pe = &ptes[i];
1996 if (!p || is_cleared_partition(p))
1999 psects = get_nr_sects(p);
2003 if (sector_size < 1024) {
2004 pblocks /= (1024 / sector_size);
2005 podd = psects % (1024 / sector_size);
2007 if (sector_size > 1024)
2008 pblocks *= (sector_size / 1024);
2010 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2011 partname(disk_device, i+1, w+2),
2012 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2014 (ullong) cround(get_partition_start(pe)), /* start */
2015 (ullong) cround(get_partition_start(pe) + psects /* end */
2016 - (psects ? 1 : 0)),
2017 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
2018 p->sys_ind, /* type id */
2019 partition_type(p->sys_ind)); /* type name */
2021 check_consistency(p, i);
2024 /* Is partition table in disk order? It need not be, but... */
2025 /* partition table entries are not checked for correct order if this
2026 is a sgi, sun or aix labeled disk... */
2027 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2029 printf("\nPartition table entries are not in disk order\n");
2033 #if ENABLE_FEATURE_FDISK_ADVANCED
2035 x_list_table(int extend)
2037 const struct pte *pe;
2038 const struct partition *p;
2041 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2042 disk_device, heads, sectors, cylinders);
2043 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2044 for (i = 0 ; i < partitions; i++) {
2046 p = (extend ? pe->ext_pointer : pe->part_table);
2048 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2049 i + 1, p->boot_ind, p->head,
2051 cylinder(p->sector, p->cyl), p->end_head,
2052 sector(p->end_sector),
2053 cylinder(p->end_sector, p->end_cyl),
2054 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2056 check_consistency(p, i);
2062 #if ENABLE_FEATURE_FDISK_WRITABLE
2064 fill_bounds(ullong *first, ullong *last)
2067 const struct pte *pe = &ptes[0];
2068 const struct partition *p;
2070 for (i = 0; i < partitions; pe++,i++) {
2072 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2073 first[i] = 0xffffffff;
2076 first[i] = get_partition_start(pe);
2077 last[i] = first[i] + get_nr_sects(p) - 1;
2083 check(int n, unsigned h, unsigned s, unsigned c, ullong start)
2085 ullong total, real_s, real_c;
2087 real_s = sector(s) - 1;
2088 real_c = cylinder(s, c);
2089 total = (real_c * sectors + real_s) * heads + h;
2091 printf("Partition %d contains sector 0\n", n);
2093 printf("Partition %d: head %d greater than maximum %d\n",
2095 if (real_s >= sectors)
2096 printf("Partition %d: sector %d greater than "
2097 "maximum %d\n", n, s, sectors);
2098 if (real_c >= cylinders)
2099 printf("Partition %d: cylinder %llu greater than "
2100 "maximum %d\n", n, real_c + 1, cylinders);
2101 if (cylinders <= 1024 && start != total)
2102 printf("Partition %d: previous sectors %llu disagrees with "
2103 "total %llu\n", n, start, total);
2111 ullong first[partitions], last[partitions];
2112 struct partition *p;
2114 if (warn_geometry())
2126 fill_bounds(first, last);
2127 for (i = 0; i < partitions; i++) {
2128 struct pte *pe = &ptes[i];
2131 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2132 check_consistency(p, i);
2133 if (get_partition_start(pe) < first[i])
2134 printf("Warning: bad start-of-data in "
2135 "partition %d\n", i + 1);
2136 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2138 total += last[i] + 1 - first[i];
2139 for (j = 0; j < i; j++) {
2140 if ((first[i] >= first[j] && first[i] <= last[j])
2141 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2142 printf("Warning: partition %d overlaps "
2143 "partition %d\n", j + 1, i + 1);
2144 total += first[i] >= first[j] ?
2145 first[i] : first[j];
2146 total -= last[i] <= last[j] ?
2153 if (extended_offset) {
2154 struct pte *pex = &ptes[ext_index];
2155 ullong e_last = get_start_sect(pex->part_table) +
2156 get_nr_sects(pex->part_table) - 1;
2158 for (i = 4; i < partitions; i++) {
2160 p = ptes[i].part_table;
2162 if (i != 4 || i + 1 < partitions)
2163 printf("Warning: partition %d "
2164 "is empty\n", i + 1);
2165 } else if (first[i] < extended_offset || last[i] > e_last) {
2166 printf("Logical partition %d not entirely in "
2167 "partition %d\n", i + 1, ext_index + 1);
2172 if (total > heads * sectors * cylinders)
2173 printf("Total allocated sectors %d greater than the maximum "
2174 "%d\n", total, heads * sectors * cylinders);
2176 total = heads * sectors * cylinders - total;
2178 printf("%d unallocated sectors\n", total);
2183 add_partition(int n, int sys)
2185 char mesg[256]; /* 48 does not suffice in Japanese */
2186 int i, num_read = 0;
2187 struct partition *p = ptes[n].part_table;
2188 struct partition *q = ptes[ext_index].part_table;
2190 ullong start, stop = 0;
2191 ullong first[partitions], last[partitions];
2193 if (p && p->sys_ind) {
2194 printf(msg_part_already_defined, n + 1);
2197 fill_bounds(first, last);
2199 start = sector_offset;
2200 if (display_in_cyl_units || !total_number_of_sectors)
2201 limit = (ullong) heads * sectors * cylinders - 1;
2203 limit = total_number_of_sectors - 1;
2204 if (extended_offset) {
2205 first[ext_index] = extended_offset;
2206 last[ext_index] = get_start_sect(q) +
2207 get_nr_sects(q) - 1;
2210 start = extended_offset + sector_offset;
2211 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2213 if (display_in_cyl_units)
2214 for (i = 0; i < partitions; i++)
2215 first[i] = (cround(first[i]) - 1) * units_per_sector;
2217 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2220 for (i = 0; i < partitions; i++) {
2223 if (start == ptes[i].offset)
2224 start += sector_offset;
2225 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2226 if (start >= first[i] && start <= lastplusoff)
2227 start = lastplusoff + 1;
2231 if (start >= temp+units_per_sector && num_read) {
2232 printf("Sector %lld is already allocated\n", temp);
2236 if (!num_read && start == temp) {
2239 saved_start = start;
2240 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2242 if (display_in_cyl_units) {
2243 start = (start - 1) * units_per_sector;
2244 if (start < saved_start) start = saved_start;
2248 } while (start != temp || !num_read);
2249 if (n > 4) { /* NOT for fifth partition */
2250 struct pte *pe = &ptes[n];
2252 pe->offset = start - sector_offset;
2253 if (pe->offset == extended_offset) { /* must be corrected */
2255 if (sector_offset == 1)
2260 for (i = 0; i < partitions; i++) {
2261 struct pte *pe = &ptes[i];
2263 if (start < pe->offset && limit >= pe->offset)
2264 limit = pe->offset - 1;
2265 if (start < first[i] && limit >= first[i])
2266 limit = first[i] - 1;
2268 if (start > limit) {
2269 printf("No free sectors available\n");
2274 if (cround(start) == cround(limit)) {
2277 snprintf(mesg, sizeof(mesg),
2278 "Last %s or +size or +sizeM or +sizeK",
2279 str_units(SINGULAR));
2280 stop = read_int(cround(start), cround(limit), cround(limit),
2281 cround(start), mesg);
2282 if (display_in_cyl_units) {
2283 stop = stop * units_per_sector - 1;
2289 set_partition(n, 0, start, stop, sys);
2291 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2293 if (IS_EXTENDED(sys)) {
2294 struct pte *pe4 = &ptes[4];
2295 struct pte *pen = &ptes[n];
2298 pen->ext_pointer = p;
2299 pe4->offset = extended_offset = start;
2300 pe4->sectorbuffer = xzalloc(sector_size);
2301 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2302 pe4->ext_pointer = pe4->part_table + 1;
2311 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2312 struct pte *pe = &ptes[partitions];
2314 pe->sectorbuffer = xzalloc(sector_size);
2315 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2316 pe->ext_pointer = pe->part_table + 1;
2321 add_partition(partitions - 1, LINUX_NATIVE);
2327 int i, free_primary = 0;
2329 if (warn_geometry())
2333 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2337 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2341 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2342 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2343 "table first (use 'o'). This will destroy the present disk contents.\n");
2347 for (i = 0; i < 4; i++)
2348 free_primary += !ptes[i].part_table->sys_ind;
2350 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2351 printf("The maximum number of partitions has been created\n");
2355 if (!free_primary) {
2356 if (extended_offset)
2359 printf("You must delete some partition and add "
2360 "an extended partition first\n");
2363 snprintf(line, sizeof(line),
2366 " p primary partition (1-4)\n",
2368 "l logical (5 or over)" : "e extended"));
2370 c = read_nonempty(line);
2371 if (c == 'p' || c == 'P') {
2372 i = get_nonexisting_partition(0, 4);
2374 add_partition(i, LINUX_NATIVE);
2377 if (c == 'l' && extended_offset) {
2381 if (c == 'e' && !extended_offset) {
2382 i = get_nonexisting_partition(0, 4);
2384 add_partition(i, EXTENDED);
2387 printf("Invalid partition number "
2388 "for type '%c'\n", c);
2399 for (i = 0; i < 3; i++)
2400 if (ptes[i].changed)
2401 ptes[3].changed = 1;
2402 for (i = 3; i < partitions; i++) {
2403 struct pte *pe = &ptes[i];
2406 write_part_table_flag(pe->sectorbuffer);
2407 write_sector(pe->offset, pe->sectorbuffer);
2411 else if (LABEL_IS_SGI) {
2412 /* no test on change? the printf below might be mistaken */
2415 else if (LABEL_IS_SUN) {
2418 for (i = 0; i < 8; i++)
2419 if (ptes[i].changed)
2425 printf("The partition table has been altered!\n\n");
2426 reread_partition_table(1);
2430 reread_partition_table(int leave)
2434 printf("Calling ioctl() to re-read partition table\n");
2436 /* sleep(2); Huh? */
2437 i = ioctl_or_perror(fd, BLKRRPART, NULL,
2438 "WARNING: rereading partition table "
2439 "failed, kernel still uses old table");
2443 "\nWARNING: If you have created or modified any DOS 6.x\n"
2444 "partitions, please see the fdisk manual page for additional\n"
2449 if (ENABLE_FEATURE_CLEAN_UP)
2454 #endif /* FEATURE_FDISK_WRITABLE */
2456 #if ENABLE_FEATURE_FDISK_ADVANCED
2457 #define MAX_PER_LINE 16
2459 print_buffer(char *pbuffer)
2463 for (i = 0, l = 0; i < sector_size; i++, l++) {
2465 printf("0x%03X:", i);
2466 printf(" %02X", (unsigned char) pbuffer[i]);
2467 if (l == MAX_PER_LINE - 1) {
2482 printf("Device: %s\n", disk_device);
2483 if (LABEL_IS_SGI || LABEL_IS_SUN)
2484 print_buffer(MBRbuffer);
2486 for (i = 3; i < partitions; i++)
2487 print_buffer(ptes[i].sectorbuffer);
2494 struct pte *pe = &ptes[i];
2495 struct partition *p = pe->part_table;
2498 if (warn_geometry())
2500 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2501 printf("Partition %d has no data area\n", i + 1);
2504 first = get_partition_start(pe);
2505 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2506 "New beginning of data") - pe->offset;
2508 if (new != get_nr_sects(p)) {
2509 first = get_nr_sects(p) + get_start_sect(p) - new;
2510 set_nr_sects(p, first);
2511 set_start_sect(p, new);
2523 c = tolower(read_nonempty("Expert command (m for help): "));
2531 move_begin(get_partition(0, partitions));
2534 user_cylinders = cylinders =
2535 read_int(1, cylinders, 1048576, 0,
2536 "Number of cylinders");
2538 sun_set_ncyl(cylinders);
2548 else if (LABEL_IS_SUN)
2550 else if (LABEL_IS_DOS)
2555 fix_partition_table_order();
2558 #if ENABLE_FEATURE_SGI_LABEL
2563 user_heads = heads = read_int(1, heads, 256, 0,
2588 user_sectors = sectors = read_int(1, sectors, 63, 0,
2589 "Number of sectors");
2590 if (dos_compatible_flag) {
2591 sector_offset = sectors;
2592 printf("Warning: setting sector offset for DOS "
2601 write_table(); /* does not return */
2605 sun_set_pcylcount();
2612 #endif /* ADVANCED mode */
2615 is_ide_cdrom_or_tape(const char *device)
2619 struct stat statbuf;
2622 /* No device was given explicitly, and we are trying some
2623 likely things. But opening /dev/hdc may produce errors like
2624 "hdc: tray open or drive not ready"
2625 if it happens to be a CD-ROM drive. It even happens that
2626 the process hangs on the attempt to read a music CD.
2627 So try to be careful. This only works since 2.1.73. */
2629 if (strncmp("/dev/hd", device, 7))
2632 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2633 procf = fopen(buf, "r");
2634 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2635 is_ide = (!strncmp(buf, "cdrom", 5) ||
2636 !strncmp(buf, "tape", 4));
2638 /* Now when this proc file does not exist, skip the
2639 device when it is read-only. */
2640 if (stat(device, &statbuf) == 0)
2641 is_ide = ((statbuf.st_mode & 0222) == 0);
2650 trydev(const char *device, int user_specified)
2654 disk_device = device;
2655 if (setjmp(listingbuf))
2657 if (!user_specified)
2658 if (is_ide_cdrom_or_tape(device))
2660 fd = open(disk_device, type_open);
2662 gb = get_boot(try_only);
2663 if (gb > 0) { /* I/O error */
2665 } else if (gb < 0) { /* no DOS signature */
2666 list_disk_geometry();
2670 #if ENABLE_FEATURE_OSF_LABEL
2671 if (bsd_trydev(device) < 0)
2673 printf("Disk %s doesn't contain a valid "
2674 "partition table\n", device);
2679 #if ENABLE_FEATURE_FDISK_WRITABLE
2680 if (!LABEL_IS_SUN && partitions > 4){
2681 delete_partition(ext_index);
2686 /* Ignore other errors, since we try IDE
2687 and SCSI hard disks which may not be
2688 installed on the system. */
2689 if (errno == EACCES) {
2690 printf("Cannot open %s\n", device);
2696 /* for fdisk -l: try all things in /proc/partitions
2697 that look like a partition name (do not end in a digit) */
2702 char line[100], ptname[100], devname[120], *s;
2705 procpt = fopen_or_warn("/proc/partitions", "r");
2707 while (fgets(line, sizeof(line), procpt)) {
2708 if (sscanf(line, " %d %d %d %[^\n ]",
2709 &ma, &mi, &sz, ptname) != 4)
2711 for (s = ptname; *s; s++);
2714 sprintf(devname, "/dev/%s", ptname);
2717 #if ENABLE_FEATURE_CLEAN_UP
2722 #if ENABLE_FEATURE_FDISK_WRITABLE
2724 unknown_command(int c)
2726 printf("%c: unknown command\n", c);
2730 int fdisk_main(int argc, char **argv);
2731 int fdisk_main(int argc, char **argv)
2733 char *str_b, *str_C, *str_H, *str_S;
2737 * fdisk -l [-b sectorsize] [-u] device ...
2738 * fdisk -s [partition] ...
2739 * fdisk [-b sectorsize] [-u] device
2741 * Options -C, -H, -S set the geometry.
2750 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2753 PTR_TO_GLOBALS = xzalloc(sizeof(G));
2755 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2756 &str_b, &str_C, &str_H, &str_S);
2759 if (opt & OPT_b) { // -b
2760 /* Ugly: this sector size is really per device,
2761 so cannot be combined with multiple disks,
2762 and the same goes for the C/H/S options.
2764 sector_size = xatoi_u(str_b);
2765 if (sector_size != 512 && sector_size != 1024 &&
2766 sector_size != 2048)
2769 user_set_sector_size = 1;
2771 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2772 if (opt & OPT_H) { // -H
2773 user_heads = xatoi_u(str_H);
2774 if (user_heads <= 0 || user_heads >= 256)
2777 //if (opt & OPT_l) // -l
2778 if (opt & OPT_S) { // -S
2779 user_sectors = xatoi_u(str_S);
2780 if (user_sectors <= 0 || user_sectors >= 64)
2783 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2784 //if (opt & OPT_s) // -s
2786 if (user_set_sector_size && argc != 1)
2787 printf("Warning: the -b (set sector size) option should"
2788 " be used with one specified device\n");
2790 #if ENABLE_FEATURE_FDISK_WRITABLE
2794 type_open = O_RDONLY;
2797 #if defined(__GNUC__)
2798 /* avoid gcc warning:
2799 variable `k' might be clobbered by `longjmp' */
2803 for (k = 0; k < argc; k++)
2806 /* we no longer have default device names */
2807 /* but, we can use /proc/partitions instead */
2811 #if ENABLE_FEATURE_FDISK_WRITABLE
2815 #if ENABLE_FEATURE_FDISK_BLKSIZE
2821 type_open = O_RDONLY;
2826 for (j = 0; j < argc; j++) {
2827 disk_device = argv[j];
2828 fd = open(disk_device, type_open);
2830 fdisk_fatal(unable_to_open);
2831 if (ioctl(fd, BLKGETSIZE, &size))
2832 fdisk_fatal(ioctl_error);
2835 printf("%ld\n", size/2);
2837 printf("%s: %ld\n", argv[j], size/2);
2843 #if ENABLE_FEATURE_FDISK_WRITABLE
2847 disk_device = argv[0];
2851 /* OSF label, and no DOS label */
2852 printf("Detected an OSF/1 disklabel on %s, entering "
2853 "disklabel mode\n", disk_device);
2855 /*Why do we do this? It seems to be counter-intuitive*/
2856 current_label_type = label_dos;
2857 /* If we return we may want to make an empty DOS label? */
2863 c = tolower(read_nonempty("Command (m for help): "));
2867 toggle_active(get_partition(1, partitions));
2868 else if (LABEL_IS_SUN)
2869 toggle_sunflags(get_partition(1, partitions),
2871 else if (LABEL_IS_SGI)
2872 sgi_set_bootpartition(
2873 get_partition(1, partitions));
2879 printf("\nThe current boot file is: %s\n",
2880 sgi_get_bootfile());
2881 if (read_maybe_empty("Please enter the name of the "
2882 "new boot file: ") == '\n')
2883 printf("Boot file unchanged\n");
2885 sgi_set_bootfile(line_ptr);
2887 #if ENABLE_FEATURE_OSF_LABEL
2894 toggle_dos_compatibility_flag();
2895 else if (LABEL_IS_SUN)
2896 toggle_sunflags(get_partition(1, partitions),
2898 else if (LABEL_IS_SGI)
2899 sgi_set_swappartition(
2900 get_partition(1, partitions));
2907 /* If sgi_label then don't use get_existing_partition,
2908 let the user select a partition, since
2909 get_existing_partition() only works for Linux-like
2911 if (!LABEL_IS_SGI) {
2912 j = get_existing_partition(1, partitions);
2914 j = get_partition(1, partitions);
2917 delete_partition(j);
2926 list_types(get_sys_types());
2945 #if ENABLE_FEATURE_SUN_LABEL
2959 write_table(); /* does not return */
2961 #if ENABLE_FEATURE_FDISK_ADVANCED
2964 printf("\n\tSorry, no experts menu for SGI "
2965 "partition tables available\n\n");
2976 #endif /* FEATURE_FDISK_WRITABLE */