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 SIZE(a) (sizeof(a)/sizeof((a)[0]))
25 #define DEFAULT_SECTOR_SIZE 512
26 #define MAX_SECTOR_SIZE 2048
27 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
28 #define MAXIMUM_PARTS 60
30 #define ACTIVE_FLAG 0x80
33 #define WIN98_EXTENDED 0x0f
34 #define LINUX_PARTITION 0x81
35 #define LINUX_SWAP 0x82
36 #define LINUX_NATIVE 0x83
37 #define LINUX_EXTENDED 0x85
38 #define LINUX_LVM 0x8e
39 #define LINUX_RAID 0xfd
41 /* Used for sector numbers. Today's disk sizes make it necessary */
42 typedef unsigned long long ullong;
46 unsigned char sectors;
47 unsigned short cylinders;
51 #define HDIO_GETGEO 0x0301 /* get device geometry */
53 static const char msg_building_new_label[] =
54 "Building a new %s. Changes will remain in memory only,\n"
55 "until you decide to write them. After that the previous content\n"
56 "won't be recoverable.\n\n";
58 static const char msg_part_already_defined[] =
59 "Partition %d is already defined, delete it before re-adding\n";
62 static unsigned sector_size = DEFAULT_SECTOR_SIZE;
63 static unsigned user_set_sector_size;
64 static unsigned sector_offset = 1;
66 #if ENABLE_FEATURE_OSF_LABEL
67 static int possibly_osf_label;
70 static unsigned heads, sectors, cylinders;
71 static void update_units(void);
75 unsigned char boot_ind; /* 0x80 - active */
76 unsigned char head; /* starting head */
77 unsigned char sector; /* starting sector */
78 unsigned char cyl; /* starting cylinder */
79 unsigned char sys_ind; /* What partition type */
80 unsigned char end_head; /* end head */
81 unsigned char end_sector; /* end sector */
82 unsigned char end_cyl; /* end cylinder */
83 unsigned char start4[4]; /* starting sector counting from 0 */
84 unsigned char size4[4]; /* nr of sectors in partition */
87 static const char unable_to_open[] = "cannot open %s";
88 static const char unable_to_read[] = "cannot read from %s";
89 static const char unable_to_seek[] = "cannot seek on %s";
90 static const char unable_to_write[] = "cannot write to %s";
91 static const char ioctl_error[] = "BLKGETSIZE ioctl failed on %s";
92 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
95 label_dos, label_sun, label_sgi, label_aix, label_osf
98 #define LABEL_IS_DOS (label_dos == current_label_type)
100 #if ENABLE_FEATURE_SUN_LABEL
101 #define LABEL_IS_SUN (label_sun == current_label_type)
102 #define STATIC_SUN static
104 #define LABEL_IS_SUN 0
105 #define STATIC_SUN extern
108 #if ENABLE_FEATURE_SGI_LABEL
109 #define LABEL_IS_SGI (label_sgi == current_label_type)
110 #define STATIC_SGI static
112 #define LABEL_IS_SGI 0
113 #define STATIC_SGI extern
116 #if ENABLE_FEATURE_AIX_LABEL
117 #define LABEL_IS_AIX (label_aix == current_label_type)
118 #define STATIC_AIX static
120 #define LABEL_IS_AIX 0
121 #define STATIC_AIX extern
124 #if ENABLE_FEATURE_OSF_LABEL
125 #define LABEL_IS_OSF (label_osf == current_label_type)
126 #define STATIC_OSF static
128 #define LABEL_IS_OSF 0
129 #define STATIC_OSF extern
132 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
134 static enum label_type current_label_type;
136 static const char *disk_device;
137 static int fd; /* the disk */
138 static int partitions = 4; /* maximum partition + 1 */
139 static int display_in_cyl_units = 1;
140 static unsigned units_per_sector = 1;
141 #if ENABLE_FEATURE_FDISK_WRITABLE
142 static void change_units(void);
143 static void reread_partition_table(int leave);
144 static void delete_partition(int i);
145 static int get_partition(int warn, int max);
146 static void list_types(const char *const *sys);
147 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
149 static const char *partition_type(unsigned char type);
150 static void get_geometry(void);
151 static int get_boot(enum action what);
156 static unsigned get_start_sect(const struct partition *p);
157 static unsigned get_nr_sects(const struct partition *p);
160 * per partition table entry data
162 * The four primary partitions have the same sectorbuffer (MBRbuffer)
163 * and have NULL ext_pointer.
164 * Each logical partition table entry has two pointers, one for the
165 * partition and one link to the next one.
168 struct partition *part_table; /* points into sectorbuffer */
169 struct partition *ext_pointer; /* points into sectorbuffer */
170 ullong offset; /* disk sector number */
171 char *sectorbuffer; /* disk sector contents */
172 #if ENABLE_FEATURE_FDISK_WRITABLE
173 char changed; /* boolean */
177 /* DOS partition types */
179 static const char *const i386_sys_types[] = {
183 "\x05" "Extended", /* DOS 3.3+ extended partition */
184 "\x06" "FAT16", /* DOS 16-bit >=32M */
185 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
186 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
187 "\x0b" "Win95 FAT32",
188 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
189 "\x0e" "Win95 FAT16 (LBA)",
190 "\x0f" "Win95 Ext'd (LBA)",
191 "\x11" "Hidden FAT12",
192 "\x12" "Compaq diagnostics",
193 "\x14" "Hidden FAT16 <32M",
194 "\x16" "Hidden FAT16",
195 "\x17" "Hidden HPFS/NTFS",
196 "\x1b" "Hidden Win95 FAT32",
197 "\x1c" "Hidden W95 FAT32 (LBA)",
198 "\x1e" "Hidden W95 FAT16 (LBA)",
199 "\x3c" "Part.Magic recovery",
200 "\x41" "PPC PReP Boot",
202 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
203 "\x80" "Old Minix", /* Minix 1.4a and earlier */
204 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
205 "\x82" "Linux swap", /* also Solaris */
207 "\x84" "OS/2 hidden C: drive",
208 "\x85" "Linux extended",
209 "\x86" "NTFS volume set",
210 "\x87" "NTFS volume set",
212 "\x9f" "BSD/OS", /* BSDI */
213 "\xa0" "Thinkpad hibernation",
214 "\xa5" "FreeBSD", /* various BSD flavours */
218 "\xab" "Darwin boot",
221 "\xbe" "Solaris boot",
223 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
224 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
225 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
226 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
227 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
228 autodetect using persistent
230 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
233 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
234 "\x09" "AIX bootable", /* AIX data or Coherent */
236 "\x18" "AST SmartSleep",
239 "\x40" "Venix 80286",
241 "\x4e" "QNX4.x 2nd part",
242 "\x4f" "QNX4.x 3rd part",
244 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
245 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
246 "\x53" "OnTrack DM6 Aux3",
250 "\x5c" "Priam Edisk",
252 "\x64" "Novell Netware 286",
253 "\x65" "Novell Netware 386",
254 "\x70" "DiskSecure Multi-Boot",
257 "\x94" "Amoeba BBT", /* (bad block table) */
259 "\xbb" "Boot Wizard hidden",
260 "\xc1" "DRDOS/sec (FAT-12)",
261 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
262 "\xc6" "DRDOS/sec (FAT-16)",
264 "\xda" "Non-FS data",
265 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
266 Concurrent DOS or CTOS */
267 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
268 "\xdf" "BootIt", /* BootIt EMBRM */
269 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
270 extended partition */
271 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
272 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
273 partition < 1024 cyl. */
275 "\xf4" "SpeedStor", /* SpeedStor large partition */
276 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
277 "\xff" "BBT", /* Xenix Bad Block Table */
287 char line_buffer[80];
288 char partname_buffer[80];
290 /* Raw disk label. For DOS-type partition tables the MBR,
291 * with descriptions of the primary partitions. */
292 char MBRbuffer[MAX_SECTOR_SIZE];
293 /* Partition tables */
294 struct pte ptes[MAXIMUM_PARTS];
296 /* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
297 #define G (*ptr_to_globals)
299 #define line_ptr (G.line_ptr)
300 #define listingbuf (G.listingbuf)
301 #define line_buffer (G.line_buffer)
302 #define partname_buffer (G.partname_buffer)
303 #define MBRbuffer (G.MBRbuffer)
304 #define ptes (G.ptes)
309 #define IS_EXTENDED(i) \
310 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
312 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
314 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
316 #define pt_offset(b, n) \
317 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
319 #define sector(s) ((s) & 0x3f)
321 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
323 #define hsc2sector(h,s,c) \
324 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
326 #define set_hsc(h,s,c,sector) \
328 s = sector % sectors + 1; \
330 h = sector % heads; \
333 s |= (sector >> 2) & 0xc0; \
336 #if ENABLE_FEATURE_FDISK_WRITABLE
337 /* read line; return 0 or first printable char */
339 read_line(const char *prompt)
343 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
345 exit(0); /* Ctrl-D or Ctrl-C */
347 if (line_buffer[sz-1] == '\n')
348 line_buffer[--sz] = '\0';
350 line_ptr = line_buffer;
351 while (*line_ptr && !isgraph(*line_ptr))
358 * return partition name - uses static storage
361 partname(const char *dev, int pno, int lth)
368 bufp = partname_buffer;
369 bufsiz = sizeof(partname_buffer);
374 if (isdigit(dev[w-1]))
377 /* devfs kludge - note: fdisk partition names are not supposed
378 to equal kernel names, so there is no reason to do this */
379 if (strcmp(dev + w - 4, "disc") == 0) {
387 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
388 lth-wp-2, w, dev, p, pno);
390 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
395 #if ENABLE_FEATURE_FDISK_WRITABLE
397 set_all_unchanged(void)
401 for (i = 0; i < MAXIMUM_PARTS; i++)
405 static ATTRIBUTE_ALWAYS_INLINE void
410 #endif /* FEATURE_FDISK_WRITABLE */
412 static ATTRIBUTE_ALWAYS_INLINE struct partition *
413 get_part_table(int i)
415 return ptes[i].part_table;
420 { /* n==1: use singular */
422 return display_in_cyl_units ? "cylinder" : "sector";
423 return display_in_cyl_units ? "cylinders" : "sectors";
427 valid_part_table_flag(const char *mbuffer)
429 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
432 #if ENABLE_FEATURE_FDISK_WRITABLE
433 static ATTRIBUTE_ALWAYS_INLINE void
434 write_part_table_flag(char *b)
441 read_nonempty(const char *mesg)
443 while (!read_line(mesg)) /* repeat */;
448 read_maybe_empty(const char *mesg)
450 if (!read_line(mesg)) {
451 line_ptr = line_buffer;
459 read_hex(const char *const *sys)
463 read_nonempty("Hex code (type L to list codes): ");
464 if (*line_ptr == 'l' || *line_ptr == 'L') {
468 v = bb_strtoul(line_ptr, NULL, 16);
470 /* Bad input also triggers this */
475 #endif /* FEATURE_FDISK_WRITABLE */
477 #include "fdisk_aix.c"
480 unsigned char info[128]; /* Informative text string */
481 unsigned char spare0[14];
483 unsigned char spare1;
485 unsigned char spare2;
488 unsigned char spare1[246]; /* Boot information etc. */
489 unsigned short rspeed; /* Disk rotational speed */
490 unsigned short pcylcount; /* Physical cylinder count */
491 unsigned short sparecyl; /* extra sects per cylinder */
492 unsigned char spare2[4]; /* More magic... */
493 unsigned short ilfact; /* Interleave factor */
494 unsigned short ncyl; /* Data cylinder count */
495 unsigned short nacyl; /* Alt. cylinder count */
496 unsigned short ntrks; /* Tracks per cylinder */
497 unsigned short nsect; /* Sectors per track */
498 unsigned char spare3[4]; /* Even more magic... */
499 struct sun_partinfo {
500 uint32_t start_cylinder;
501 uint32_t num_sectors;
503 unsigned short magic; /* Magic number */
504 unsigned short csum; /* Label xor'd checksum */
506 #define sunlabel ((sun_partition *)MBRbuffer)
507 STATIC_OSF void bsd_select(void);
508 STATIC_OSF void xbsd_print_disklabel(int);
509 #include "fdisk_osf.c"
511 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
513 fdisk_swap16(uint16_t x)
515 return (x << 8) | (x >> 8);
519 fdisk_swap32(uint32_t x)
522 ((x & 0xFF00) << 8) |
523 ((x & 0xFF0000) >> 8) |
528 STATIC_SGI const char *const sgi_sys_types[];
529 STATIC_SGI unsigned sgi_get_num_sectors(int i);
530 STATIC_SGI int sgi_get_sysid(int i);
531 STATIC_SGI void sgi_delete_partition(int i);
532 STATIC_SGI void sgi_change_sysid(int i, int sys);
533 STATIC_SGI void sgi_list_table(int xtra);
534 #if ENABLE_FEATURE_FDISK_ADVANCED
535 STATIC_SGI void sgi_set_xcyl(void);
537 STATIC_SGI int verify_sgi(int verbose);
538 STATIC_SGI void sgi_add_partition(int n, int sys);
539 STATIC_SGI void sgi_set_swappartition(int i);
540 STATIC_SGI const char *sgi_get_bootfile(void);
541 STATIC_SGI void sgi_set_bootfile(const char* aFile);
542 STATIC_SGI void create_sgiinfo(void);
543 STATIC_SGI void sgi_write_table(void);
544 STATIC_SGI void sgi_set_bootpartition(int i);
545 #include "fdisk_sgi.c"
547 STATIC_SUN const char *const sun_sys_types[];
548 STATIC_SUN void sun_delete_partition(int i);
549 STATIC_SUN void sun_change_sysid(int i, int sys);
550 STATIC_SUN void sun_list_table(int xtra);
551 STATIC_SUN void add_sun_partition(int n, int sys);
552 #if ENABLE_FEATURE_FDISK_ADVANCED
553 STATIC_SUN void sun_set_alt_cyl(void);
554 STATIC_SUN void sun_set_ncyl(int cyl);
555 STATIC_SUN void sun_set_xcyl(void);
556 STATIC_SUN void sun_set_ilfact(void);
557 STATIC_SUN void sun_set_rspeed(void);
558 STATIC_SUN void sun_set_pcylcount(void);
560 STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
561 STATIC_SUN void verify_sun(void);
562 STATIC_SUN void sun_write_table(void);
563 #include "fdisk_sun.c"
565 #if ENABLE_FEATURE_FDISK_WRITABLE
566 /* start_sect and nr_sects are stored little endian on all machines */
567 /* moreover, they are not aligned correctly */
569 store4_little_endian(unsigned char *cp, unsigned val)
576 #endif /* FEATURE_FDISK_WRITABLE */
579 read4_little_endian(const unsigned char *cp)
581 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
584 #if ENABLE_FEATURE_FDISK_WRITABLE
586 set_start_sect(struct partition *p, unsigned start_sect)
588 store4_little_endian(p->start4, start_sect);
593 get_start_sect(const struct partition *p)
595 return read4_little_endian(p->start4);
598 #if ENABLE_FEATURE_FDISK_WRITABLE
600 set_nr_sects(struct partition *p, unsigned nr_sects)
602 store4_little_endian(p->size4, nr_sects);
607 get_nr_sects(const struct partition *p)
609 return read4_little_endian(p->size4);
612 /* normally O_RDWR, -l option gives O_RDONLY */
613 static int type_open = O_RDWR;
615 static int ext_index; /* the prime extended partition */
616 static int listing; /* no aborts for fdisk -l */
617 static int dos_compatible_flag = ~0;
618 #if ENABLE_FEATURE_FDISK_WRITABLE
619 static int dos_changed;
620 static int nowarn; /* no warnings for fdisk -l/-s */
623 static unsigned user_cylinders, user_heads, user_sectors;
624 static unsigned pt_heads, pt_sectors;
625 static unsigned kern_heads, kern_sectors;
627 static ullong extended_offset; /* offset of link pointers */
628 static ullong total_number_of_sectors;
630 static void fdisk_fatal(const char *why)
634 longjmp(listingbuf, 1);
636 bb_error_msg_and_die(why, disk_device);
640 seek_sector(ullong secno)
642 secno *= sector_size;
643 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
644 fdisk_fatal(unable_to_seek);
647 #if ENABLE_FEATURE_FDISK_WRITABLE
649 write_sector(ullong secno, char *buf)
652 if (write(fd, buf, sector_size) != sector_size)
653 fdisk_fatal(unable_to_write);
657 /* Allocate a buffer and read a partition table sector */
659 read_pte(struct pte *pe, ullong offset)
662 pe->sectorbuffer = xmalloc(sector_size);
664 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
665 fdisk_fatal(unable_to_read);
666 #if ENABLE_FEATURE_FDISK_WRITABLE
669 pe->part_table = pe->ext_pointer = NULL;
673 get_partition_start(const struct pte *pe)
675 return pe->offset + get_start_sect(pe->part_table);
678 #if ENABLE_FEATURE_FDISK_WRITABLE
680 * Avoid warning about DOS partitions when no DOS partition was changed.
681 * Here a heuristic "is probably dos partition".
682 * We might also do the opposite and warn in all cases except
683 * for "is probably nondos partition".
686 is_dos_partition(int t)
688 return (t == 1 || t == 4 || t == 6 ||
689 t == 0x0b || t == 0x0c || t == 0x0e ||
690 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
691 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
692 t == 0xc1 || t == 0xc4 || t == 0xc6);
698 puts("Command Action");
700 puts("a\ttoggle a read only flag"); /* sun */
701 puts("b\tedit bsd disklabel");
702 puts("c\ttoggle the mountable flag"); /* sun */
703 puts("d\tdelete a partition");
704 puts("l\tlist known partition types");
705 puts("n\tadd a new partition");
706 puts("o\tcreate a new empty DOS partition table");
707 puts("p\tprint the partition table");
708 puts("q\tquit without saving changes");
709 puts("s\tcreate a new empty Sun disklabel"); /* sun */
710 puts("t\tchange a partition's system id");
711 puts("u\tchange display/entry units");
712 puts("v\tverify the partition table");
713 puts("w\twrite table to disk and exit");
714 #if ENABLE_FEATURE_FDISK_ADVANCED
715 puts("x\textra functionality (experts only)");
717 } else if (LABEL_IS_SGI) {
718 puts("a\tselect bootable partition"); /* sgi flavour */
719 puts("b\tedit bootfile entry"); /* sgi */
720 puts("c\tselect sgi swap partition"); /* sgi flavour */
721 puts("d\tdelete a partition");
722 puts("l\tlist known partition types");
723 puts("n\tadd a new partition");
724 puts("o\tcreate a new empty DOS partition table");
725 puts("p\tprint the partition table");
726 puts("q\tquit without saving changes");
727 puts("s\tcreate a new empty Sun disklabel"); /* sun */
728 puts("t\tchange a partition's system id");
729 puts("u\tchange display/entry units");
730 puts("v\tverify the partition table");
731 puts("w\twrite table to disk and exit");
732 } else if (LABEL_IS_AIX) {
733 puts("o\tcreate a new empty DOS partition table");
734 puts("q\tquit without saving changes");
735 puts("s\tcreate a new empty Sun disklabel"); /* sun */
737 puts("a\ttoggle a bootable flag");
738 puts("b\tedit bsd disklabel");
739 puts("c\ttoggle the dos compatibility flag");
740 puts("d\tdelete a partition");
741 puts("l\tlist known partition types");
742 puts("n\tadd a new partition");
743 puts("o\tcreate a new empty DOS partition table");
744 puts("p\tprint the partition table");
745 puts("q\tquit without saving changes");
746 puts("s\tcreate a new empty Sun disklabel"); /* sun */
747 puts("t\tchange a partition's system id");
748 puts("u\tchange display/entry units");
749 puts("v\tverify the partition table");
750 puts("w\twrite table to disk and exit");
751 #if ENABLE_FEATURE_FDISK_ADVANCED
752 puts("x\textra functionality (experts only)");
756 #endif /* FEATURE_FDISK_WRITABLE */
759 #if ENABLE_FEATURE_FDISK_ADVANCED
763 puts("Command Action");
765 puts("a\tchange number of alternate cylinders"); /*sun*/
766 puts("c\tchange number of cylinders");
767 puts("d\tprint the raw data in the partition table");
768 puts("e\tchange number of extra sectors per cylinder");/*sun*/
769 puts("h\tchange number of heads");
770 puts("i\tchange interleave factor"); /*sun*/
771 puts("o\tchange rotation speed (rpm)"); /*sun*/
772 puts("p\tprint the partition table");
773 puts("q\tquit without saving changes");
774 puts("r\treturn to main menu");
775 puts("s\tchange number of sectors/track");
776 puts("v\tverify the partition table");
777 puts("w\twrite table to disk and exit");
778 puts("y\tchange number of physical cylinders"); /*sun*/
779 } else if (LABEL_IS_SGI) {
780 puts("b\tmove beginning of data in a partition"); /* !sun */
781 puts("c\tchange number of cylinders");
782 puts("d\tprint the raw data in the partition table");
783 puts("e\tlist extended partitions"); /* !sun */
784 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
785 puts("h\tchange number of heads");
786 puts("p\tprint the partition table");
787 puts("q\tquit without saving changes");
788 puts("r\treturn to main menu");
789 puts("s\tchange number of sectors/track");
790 puts("v\tverify the partition table");
791 puts("w\twrite table to disk and exit");
792 } else if (LABEL_IS_AIX) {
793 puts("b\tmove beginning of data in a partition"); /* !sun */
794 puts("c\tchange number of cylinders");
795 puts("d\tprint the raw data in the partition table");
796 puts("e\tlist extended partitions"); /* !sun */
797 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
798 puts("h\tchange number of heads");
799 puts("p\tprint the partition table");
800 puts("q\tquit without saving changes");
801 puts("r\treturn to main menu");
802 puts("s\tchange number of sectors/track");
803 puts("v\tverify the partition table");
804 puts("w\twrite table to disk and exit");
806 puts("b\tmove beginning of data in a partition"); /* !sun */
807 puts("c\tchange number of cylinders");
808 puts("d\tprint the raw data in the partition table");
809 puts("e\tlist extended partitions"); /* !sun */
810 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
811 #if ENABLE_FEATURE_SGI_LABEL
812 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
814 puts("h\tchange number of heads");
815 puts("p\tprint the partition table");
816 puts("q\tquit without saving changes");
817 puts("r\treturn to main menu");
818 puts("s\tchange number of sectors/track");
819 puts("v\tverify the partition table");
820 puts("w\twrite table to disk and exit");
823 #endif /* ADVANCED mode */
825 #if ENABLE_FEATURE_FDISK_WRITABLE
826 static const char *const *
830 LABEL_IS_SUN ? sun_sys_types :
831 LABEL_IS_SGI ? sgi_sys_types :
835 #define get_sys_types() i386_sys_types
836 #endif /* FEATURE_FDISK_WRITABLE */
839 partition_type(unsigned char type)
842 const char *const *types = get_sys_types();
844 for (i = 0; types[i]; i++)
845 if ((unsigned char)types[i][0] == type)
852 #if ENABLE_FEATURE_FDISK_WRITABLE
856 return LABEL_IS_SUN ? sunlabel->infos[i].id :
857 (LABEL_IS_SGI ? sgi_get_sysid(i) :
858 ptes[i].part_table->sys_ind);
862 list_types(const char *const *sys)
867 unsigned done, next, size;
870 for (size = 0; sys[size]; size++) /* */;
873 for (i = COLS-1; i >= 0; i--) {
874 done += (size + i - done) / (i + 1);
875 last[COLS-1 - i] = done;
880 printf("%c%2x %-22.22s", i ? ' ' : '\n',
881 (unsigned char)sys[next][0],
883 next = last[i++] + done;
884 if (i >= COLS || next >= last[i]) {
888 } while (done < last[0]);
891 #endif /* FEATURE_FDISK_WRITABLE */
894 is_cleared_partition(const struct partition *p)
896 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
897 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
898 get_start_sect(p) || get_nr_sects(p));
902 clear_partition(struct partition *p)
906 memset(p, 0, sizeof(struct partition));
909 #if ENABLE_FEATURE_FDISK_WRITABLE
911 set_partition(int i, int doext, ullong start, ullong stop, int sysid)
917 p = ptes[i].ext_pointer;
918 offset = extended_offset;
920 p = ptes[i].part_table;
921 offset = ptes[i].offset;
925 set_start_sect(p, start - offset);
926 set_nr_sects(p, stop - start + 1);
927 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
928 start = heads*sectors*1024 - 1;
929 set_hsc(p->head, p->sector, p->cyl, start);
930 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
931 stop = heads*sectors*1024 - 1;
932 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
940 if (heads && sectors && cylinders)
943 printf("Unknown value(s) for:");
949 printf(" cylinders");
951 #if ENABLE_FEATURE_FDISK_WRITABLE
952 " (settable in the extra functions menu)"
961 int cyl_units = heads * sectors;
963 if (display_in_cyl_units && cyl_units)
964 units_per_sector = cyl_units;
966 units_per_sector = 1; /* in sectors */
969 #if ENABLE_FEATURE_FDISK_WRITABLE
973 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
975 "The number of cylinders for this disk is set to %d.\n"
976 "There is nothing wrong with that, but this is larger than 1024,\n"
977 "and could in certain setups cause problems with:\n"
978 "1) software that runs at boot time (e.g., old versions of LILO)\n"
979 "2) booting and partitioning software from other OSs\n"
980 " (e.g., DOS FDISK, OS/2 FDISK)\n",
986 read_extended(int ext)
990 struct partition *p, *q;
994 pex->ext_pointer = pex->part_table;
997 if (!get_start_sect(p)) {
998 printf("Bad offset in primary extended partition\n");
1002 while (IS_EXTENDED(p->sys_ind)) {
1003 struct pte *pe = &ptes[partitions];
1005 if (partitions >= MAXIMUM_PARTS) {
1006 /* This is not a Linux restriction, but
1007 this program uses arrays of size MAXIMUM_PARTS.
1008 Do not try to 'improve' this test. */
1009 struct pte *pre = &ptes[partitions-1];
1010 #if ENABLE_FEATURE_FDISK_WRITABLE
1011 printf("Warning: deleting partitions after %d\n",
1015 clear_partition(pre->ext_pointer);
1019 read_pte(pe, extended_offset + get_start_sect(p));
1021 if (!extended_offset)
1022 extended_offset = get_start_sect(p);
1024 q = p = pt_offset(pe->sectorbuffer, 0);
1025 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1026 if (IS_EXTENDED(p->sys_ind)) {
1027 if (pe->ext_pointer)
1028 printf("Warning: extra link "
1029 "pointer in partition table"
1030 " %d\n", partitions + 1);
1032 pe->ext_pointer = p;
1033 } else if (p->sys_ind) {
1035 printf("Warning: ignoring extra "
1036 "data in partition table"
1037 " %d\n", partitions + 1);
1043 /* very strange code here... */
1044 if (!pe->part_table) {
1045 if (q != pe->ext_pointer)
1048 pe->part_table = q + 1;
1050 if (!pe->ext_pointer) {
1051 if (q != pe->part_table)
1052 pe->ext_pointer = q;
1054 pe->ext_pointer = q + 1;
1057 p = pe->ext_pointer;
1061 #if ENABLE_FEATURE_FDISK_WRITABLE
1062 /* remove empty links */
1064 for (i = 4; i < partitions; i++) {
1065 struct pte *pe = &ptes[i];
1067 if (!get_nr_sects(pe->part_table)
1068 && (partitions > 5 || ptes[4].part_table->sys_ind)
1070 printf("Omitting empty partition (%d)\n", i+1);
1071 delete_partition(i);
1072 goto remove; /* numbering changed */
1078 #if ENABLE_FEATURE_FDISK_WRITABLE
1080 create_doslabel(void)
1084 printf(msg_building_new_label, "DOS disklabel");
1086 current_label_type = label_dos;
1088 #if ENABLE_FEATURE_OSF_LABEL
1089 possibly_osf_label = 0;
1093 for (i = 510-64; i < 510; i++)
1095 write_part_table_flag(MBRbuffer);
1096 extended_offset = 0;
1097 set_all_unchanged();
1099 get_boot(create_empty_dos);
1101 #endif /* FEATURE_FDISK_WRITABLE */
1104 get_sectorsize(void)
1106 if (!user_set_sector_size) {
1108 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1110 if (sector_size != DEFAULT_SECTOR_SIZE)
1111 printf("Note: sector size is %d (not %d)\n",
1112 sector_size, DEFAULT_SECTOR_SIZE);
1117 get_kernel_geometry(void)
1119 struct hd_geometry geometry;
1121 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1122 kern_heads = geometry.heads;
1123 kern_sectors = geometry.sectors;
1124 /* never use geometry.cylinders - it is truncated */
1129 get_partition_table_geometry(void)
1131 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1132 struct partition *p;
1133 int i, h, s, hh, ss;
1137 if (!(valid_part_table_flag((char*)bufp)))
1141 for (i = 0; i < 4; i++) {
1142 p = pt_offset(bufp, i);
1143 if (p->sys_ind != 0) {
1144 h = p->end_head + 1;
1145 s = (p->end_sector & 077);
1150 } else if (hh != h || ss != s)
1155 if (!first && !bad) {
1168 sec_fac = sector_size / 512;
1169 #if ENABLE_FEATURE_SUN_LABEL
1170 guess_device_type();
1172 heads = cylinders = sectors = 0;
1173 kern_heads = kern_sectors = 0;
1174 pt_heads = pt_sectors = 0;
1176 get_kernel_geometry();
1177 get_partition_table_geometry();
1179 heads = user_heads ? user_heads :
1180 pt_heads ? pt_heads :
1181 kern_heads ? kern_heads : 255;
1182 sectors = user_sectors ? user_sectors :
1183 pt_sectors ? pt_sectors :
1184 kern_sectors ? kern_sectors : 63;
1185 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1186 /* got bytes, convert to 512 byte sectors */
1187 total_number_of_sectors = (v64 >> 9);
1189 unsigned long longsectors; /* need temp of type long */
1190 if (ioctl(fd, BLKGETSIZE, &longsectors))
1192 total_number_of_sectors = longsectors;
1196 if (dos_compatible_flag)
1197 sector_offset = sectors;
1199 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
1201 cylinders = user_cylinders;
1205 * Read MBR. Returns:
1206 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1207 * 0: found or created label
1211 get_boot(enum action what)
1217 for (i = 0; i < 4; i++) {
1218 struct pte *pe = &ptes[i];
1220 pe->part_table = pt_offset(MBRbuffer, i);
1221 pe->ext_pointer = NULL;
1223 pe->sectorbuffer = MBRbuffer;
1224 #if ENABLE_FEATURE_FDISK_WRITABLE
1225 pe->changed = (what == create_empty_dos);
1229 #if ENABLE_FEATURE_SUN_LABEL
1230 if (what == create_empty_sun && check_sun_label())
1234 memset(MBRbuffer, 0, 512);
1236 #if ENABLE_FEATURE_FDISK_WRITABLE
1237 if (what == create_empty_dos)
1238 goto got_dos_table; /* skip reading disk */
1240 fd = open(disk_device, type_open);
1242 fd = open(disk_device, O_RDONLY);
1244 if (what == try_only)
1246 fdisk_fatal(unable_to_open);
1248 printf("You will not be able to write "
1249 "the partition table\n");
1252 if (512 != read(fd, MBRbuffer, 512)) {
1253 if (what == try_only)
1255 fdisk_fatal(unable_to_read);
1258 fd = open(disk_device, O_RDONLY);
1261 if (512 != read(fd, MBRbuffer, 512))
1269 #if ENABLE_FEATURE_SUN_LABEL
1270 if (check_sun_label())
1274 #if ENABLE_FEATURE_SGI_LABEL
1275 if (check_sgi_label())
1279 #if ENABLE_FEATURE_AIX_LABEL
1280 if (check_aix_label())
1284 #if ENABLE_FEATURE_OSF_LABEL
1285 if (check_osf_label()) {
1286 possibly_osf_label = 1;
1287 if (!valid_part_table_flag(MBRbuffer)) {
1288 current_label_type = label_osf;
1291 printf("This disk has both DOS and BSD magic.\n"
1292 "Give the 'b' command to go to BSD mode.\n");
1296 #if ENABLE_FEATURE_FDISK_WRITABLE
1300 if (!valid_part_table_flag(MBRbuffer)) {
1301 #if !ENABLE_FEATURE_FDISK_WRITABLE
1306 printf("Device contains neither a valid DOS "
1307 "partition table, nor Sun, SGI or OSF "
1310 #if ENABLE_FEATURE_SUN_LABEL
1319 case create_empty_dos:
1320 #if ENABLE_FEATURE_SUN_LABEL
1321 case create_empty_sun:
1325 bb_error_msg_and_die("internal error");
1327 #endif /* FEATURE_FDISK_WRITABLE */
1330 #if ENABLE_FEATURE_FDISK_WRITABLE
1335 for (i = 0; i < 4; i++) {
1336 struct pte *pe = &ptes[i];
1338 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1339 if (partitions != 4)
1340 printf("Ignoring extra extended "
1341 "partition %d\n", i + 1);
1347 for (i = 3; i < partitions; i++) {
1348 struct pte *pe = &ptes[i];
1350 if (!valid_part_table_flag(pe->sectorbuffer)) {
1351 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1352 "table %d will be corrected by w(rite)\n",
1353 pe->sectorbuffer[510],
1354 pe->sectorbuffer[511],
1356 #if ENABLE_FEATURE_FDISK_WRITABLE
1365 #if ENABLE_FEATURE_FDISK_WRITABLE
1367 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1368 * If the user hits Enter, DFLT is returned.
1369 * Answers like +10 are interpreted as offsets from BASE.
1371 * There is no default if DFLT is not between LOW and HIGH.
1374 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1378 const char *fmt = "%s (%u-%u, default %u): ";
1380 if (dflt < low || dflt > high) {
1381 fmt = "%s (%u-%u): ";
1386 int use_default = default_ok;
1388 /* ask question and read answer */
1390 printf(fmt, mesg, low, high, dflt);
1391 read_maybe_empty("");
1392 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1393 && *line_ptr != '-' && *line_ptr != '+');
1395 if (*line_ptr == '+' || *line_ptr == '-') {
1396 int minus = (*line_ptr == '-');
1399 i = atoi(line_ptr + 1);
1401 while (isdigit(*++line_ptr))
1404 switch (*line_ptr) {
1407 if (!display_in_cyl_units)
1408 i *= heads * sectors;
1422 absolute = 1000000000;
1431 bytes = (ullong) i * absolute;
1432 unit = sector_size * units_per_sector;
1433 bytes += unit/2; /* round */
1442 while (isdigit(*line_ptr)) {
1449 printf("Using default value %u\n", i);
1451 if (i >= low && i <= high)
1453 printf("Value is out of range\n");
1459 get_partition(int warn, int max)
1464 i = read_int(1, 0, max, 0, "Partition number") - 1;
1468 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1469 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1470 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1472 printf("Warning: partition %d has empty type\n", i+1);
1479 get_existing_partition(int warn, int max)
1484 for (i = 0; i < max; i++) {
1485 struct pte *pe = &ptes[i];
1486 struct partition *p = pe->part_table;
1488 if (p && !is_cleared_partition(p)) {
1495 printf("Selected partition %d\n", pno+1);
1498 printf("No partition is defined yet!\n");
1502 return get_partition(warn, max);
1506 get_nonexisting_partition(int warn, int max)
1511 for (i = 0; i < max; i++) {
1512 struct pte *pe = &ptes[i];
1513 struct partition *p = pe->part_table;
1515 if (p && is_cleared_partition(p)) {
1522 printf("Selected partition %d\n", pno+1);
1525 printf("All primary partitions have been defined already!\n");
1529 return get_partition(warn, max);
1536 display_in_cyl_units = !display_in_cyl_units;
1538 printf("Changing display/entry units to %s\n",
1543 toggle_active(int i)
1545 struct pte *pe = &ptes[i];
1546 struct partition *p = pe->part_table;
1548 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1549 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1550 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1555 toggle_dos_compatibility_flag(void)
1557 dos_compatible_flag = ~dos_compatible_flag;
1558 if (dos_compatible_flag) {
1559 sector_offset = sectors;
1560 printf("DOS Compatibility flag is set\n");
1563 printf("DOS Compatibility flag is not set\n");
1568 delete_partition(int i)
1570 struct pte *pe = &ptes[i];
1571 struct partition *p = pe->part_table;
1572 struct partition *q = pe->ext_pointer;
1574 /* Note that for the fifth partition (i == 4) we don't actually
1575 * decrement partitions.
1578 if (warn_geometry())
1579 return; /* C/H/S not set */
1583 sun_delete_partition(i);
1587 sgi_delete_partition(i);
1592 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1594 ptes[ext_index].ext_pointer = NULL;
1595 extended_offset = 0;
1601 if (!q->sys_ind && i > 4) {
1602 /* the last one in the chain - just delete */
1605 clear_partition(ptes[i].ext_pointer);
1606 ptes[i].changed = 1;
1608 /* not the last one - further ones will be moved down */
1610 /* delete this link in the chain */
1611 p = ptes[i-1].ext_pointer;
1613 set_start_sect(p, get_start_sect(q));
1614 set_nr_sects(p, get_nr_sects(q));
1615 ptes[i-1].changed = 1;
1616 } else if (partitions > 5) { /* 5 will be moved to 4 */
1617 /* the first logical in a longer chain */
1620 if (pe->part_table) /* prevent SEGFAULT */
1621 set_start_sect(pe->part_table,
1622 get_partition_start(pe) -
1624 pe->offset = extended_offset;
1628 if (partitions > 5) {
1630 while (i < partitions) {
1631 ptes[i] = ptes[i+1];
1635 /* the only logical: clear only */
1636 clear_partition(ptes[i].part_table);
1643 int i, sys, origsys;
1644 struct partition *p;
1646 /* If sgi_label then don't use get_existing_partition,
1647 let the user select a partition, since get_existing_partition()
1648 only works for Linux like partition tables. */
1649 if (!LABEL_IS_SGI) {
1650 i = get_existing_partition(0, partitions);
1652 i = get_partition(0, partitions);
1656 p = ptes[i].part_table;
1657 origsys = sys = get_sysid(i);
1659 /* if changing types T to 0 is allowed, then
1660 the reverse change must be allowed, too */
1661 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1662 printf("Partition %d does not exist yet!\n", i + 1);
1666 sys = read_hex(get_sys_types());
1668 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1669 printf("Type 0 means free space to many systems\n"
1670 "(but not to Linux). Having partitions of\n"
1671 "type 0 is probably unwise.\n");
1675 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1676 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1677 printf("You cannot change a partition into"
1678 " an extended one or vice versa\n");
1684 #if ENABLE_FEATURE_SUN_LABEL
1685 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1686 printf("Consider leaving partition 3 "
1687 "as Whole disk (5),\n"
1688 "as SunOS/Solaris expects it and "
1689 "even Linux likes it\n\n");
1691 #if ENABLE_FEATURE_SGI_LABEL
1694 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1695 (i == 8 && sys != 0)
1698 printf("Consider leaving partition 9 "
1699 "as volume header (0),\nand "
1700 "partition 11 as entire volume (6)"
1701 "as IRIX expects it\n\n");
1707 sun_change_sysid(i, sys);
1708 } else if (LABEL_IS_SGI) {
1709 sgi_change_sysid(i, sys);
1713 printf("Changed system type of partition %d "
1714 "to %x (%s)\n", i + 1, sys,
1715 partition_type(sys));
1716 ptes[i].changed = 1;
1717 if (is_dos_partition(origsys) ||
1718 is_dos_partition(sys))
1724 #endif /* FEATURE_FDISK_WRITABLE */
1727 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1728 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1729 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1730 * Lubkin Oct. 1991). */
1733 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1735 int spc = heads * sectors;
1740 *s = ls % sectors + 1; /* sectors count from 1 */
1744 check_consistency(const struct partition *p, int partition)
1746 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1747 unsigned pec, peh, pes; /* physical ending c, h, s */
1748 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1749 unsigned lec, leh, les; /* logical ending c, h, s */
1751 if (!heads || !sectors || (partition >= 4))
1752 return; /* do not check extended partitions */
1754 /* physical beginning c, h, s */
1755 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1757 pbs = p->sector & 0x3f;
1759 /* physical ending c, h, s */
1760 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1762 pes = p->end_sector & 0x3f;
1764 /* compute logical beginning (c, h, s) */
1765 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1767 /* compute logical ending (c, h, s) */
1768 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1770 /* Same physical / logical beginning? */
1771 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1772 printf("Partition %d has different physical/logical "
1773 "beginnings (non-Linux?):\n", partition + 1);
1774 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1775 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1778 /* Same physical / logical ending? */
1779 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1780 printf("Partition %d has different physical/logical "
1781 "endings:\n", partition + 1);
1782 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1783 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1786 /* Ending on cylinder boundary? */
1787 if (peh != (heads - 1) || pes != sectors) {
1788 printf("Partition %i does not end on cylinder boundary\n",
1794 list_disk_geometry(void)
1796 long long bytes = (total_number_of_sectors << 9);
1797 long megabytes = bytes/1000000;
1799 if (megabytes < 10000)
1800 printf("\nDisk %s: %ld MB, %lld bytes\n",
1801 disk_device, megabytes, bytes);
1803 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1804 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1805 printf("%d heads, %d sectors/track, %d cylinders",
1806 heads, sectors, cylinders);
1807 if (units_per_sector == 1)
1808 printf(", total %llu sectors",
1809 total_number_of_sectors / (sector_size/512));
1810 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1812 units_per_sector, sector_size, units_per_sector * sector_size);
1816 * Check whether partition entries are ordered by their starting positions.
1817 * Return 0 if OK. Return i if partition i should have been earlier.
1818 * Two separate checks: primary and logical partitions.
1821 wrong_p_order(int *prev)
1823 const struct pte *pe;
1824 const struct partition *p;
1825 ullong last_p_start_pos = 0, p_start_pos;
1828 for (i = 0 ; i < partitions; i++) {
1831 last_p_start_pos = 0;
1834 if ((p = pe->part_table)->sys_ind) {
1835 p_start_pos = get_partition_start(pe);
1837 if (last_p_start_pos > p_start_pos) {
1843 last_p_start_pos = p_start_pos;
1850 #if ENABLE_FEATURE_FDISK_ADVANCED
1852 * Fix the chain of logicals.
1853 * extended_offset is unchanged, the set of sectors used is unchanged
1854 * The chain is sorted so that sectors increase, and so that
1855 * starting sectors increase.
1857 * After this it may still be that cfdisk doesnt like the table.
1858 * (This is because cfdisk considers expanded parts, from link to
1859 * end of partition, and these may still overlap.)
1861 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1865 fix_chain_of_logicals(void)
1867 int j, oj, ojj, sj, sjj;
1868 struct partition *pj,*pjj,tmp;
1870 /* Stage 1: sort sectors but leave sector of part 4 */
1871 /* (Its sector is the global extended_offset.) */
1873 for (j = 5; j < partitions-1; j++) {
1874 oj = ptes[j].offset;
1875 ojj = ptes[j+1].offset;
1877 ptes[j].offset = ojj;
1878 ptes[j+1].offset = oj;
1879 pj = ptes[j].part_table;
1880 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1881 pjj = ptes[j+1].part_table;
1882 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1883 set_start_sect(ptes[j-1].ext_pointer,
1884 ojj-extended_offset);
1885 set_start_sect(ptes[j].ext_pointer,
1886 oj-extended_offset);
1891 /* Stage 2: sort starting sectors */
1893 for (j = 4; j < partitions-1; j++) {
1894 pj = ptes[j].part_table;
1895 pjj = ptes[j+1].part_table;
1896 sj = get_start_sect(pj);
1897 sjj = get_start_sect(pjj);
1898 oj = ptes[j].offset;
1899 ojj = ptes[j+1].offset;
1900 if (oj+sj > ojj+sjj) {
1904 set_start_sect(pj, ojj+sjj-oj);
1905 set_start_sect(pjj, oj+sj-ojj);
1910 /* Probably something was changed */
1911 for (j = 4; j < partitions; j++)
1912 ptes[j].changed = 1;
1917 fix_partition_table_order(void)
1919 struct pte *pei, *pek;
1922 if (!wrong_p_order(NULL)) {
1923 printf("Ordering is already correct\n\n");
1927 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1928 /* partition i should have come earlier, move it */
1929 /* We have to move data in the MBR */
1930 struct partition *pi, *pk, *pe, pbuf;
1934 pe = pei->ext_pointer;
1935 pei->ext_pointer = pek->ext_pointer;
1936 pek->ext_pointer = pe;
1938 pi = pei->part_table;
1939 pk = pek->part_table;
1941 memmove(&pbuf, pi, sizeof(struct partition));
1942 memmove(pi, pk, sizeof(struct partition));
1943 memmove(pk, &pbuf, sizeof(struct partition));
1945 pei->changed = pek->changed = 1;
1949 fix_chain_of_logicals();
1957 list_table(int xtra)
1959 const struct partition *p;
1963 sun_list_table(xtra);
1967 sgi_list_table(xtra);
1971 list_disk_geometry();
1974 xbsd_print_disklabel(xtra);
1978 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1979 but if the device name ends in a digit, say /dev/foo1,
1980 then the partition is called /dev/foo1p3. */
1981 w = strlen(disk_device);
1982 if (w && isdigit(disk_device[w-1]))
1987 // 1 12345678901 12345678901 12345678901 12
1988 printf("%*s Boot Start End Blocks Id System\n",
1991 for (i = 0; i < partitions; i++) {
1992 const struct pte *pe = &ptes[i];
1998 if (!p || is_cleared_partition(p))
2001 psects = get_nr_sects(p);
2005 if (sector_size < 1024) {
2006 pblocks /= (1024 / sector_size);
2007 podd = psects % (1024 / sector_size);
2009 if (sector_size > 1024)
2010 pblocks *= (sector_size / 1024);
2012 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2013 partname(disk_device, i+1, w+2),
2014 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2016 (ullong) cround(get_partition_start(pe)), /* start */
2017 (ullong) cround(get_partition_start(pe) + psects /* end */
2018 - (psects ? 1 : 0)),
2019 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
2020 p->sys_ind, /* type id */
2021 partition_type(p->sys_ind)); /* type name */
2023 check_consistency(p, i);
2026 /* Is partition table in disk order? It need not be, but... */
2027 /* partition table entries are not checked for correct order if this
2028 is a sgi, sun or aix labeled disk... */
2029 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2031 printf("\nPartition table entries are not in disk order\n");
2035 #if ENABLE_FEATURE_FDISK_ADVANCED
2037 x_list_table(int extend)
2039 const struct pte *pe;
2040 const struct partition *p;
2043 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2044 disk_device, heads, sectors, cylinders);
2045 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2046 for (i = 0 ; i < partitions; i++) {
2048 p = (extend ? pe->ext_pointer : pe->part_table);
2050 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2051 i + 1, p->boot_ind, p->head,
2053 cylinder(p->sector, p->cyl), p->end_head,
2054 sector(p->end_sector),
2055 cylinder(p->end_sector, p->end_cyl),
2056 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2058 check_consistency(p, i);
2064 #if ENABLE_FEATURE_FDISK_WRITABLE
2066 fill_bounds(ullong *first, ullong *last)
2069 const struct pte *pe = &ptes[0];
2070 const struct partition *p;
2072 for (i = 0; i < partitions; pe++,i++) {
2074 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2075 first[i] = 0xffffffff;
2078 first[i] = get_partition_start(pe);
2079 last[i] = first[i] + get_nr_sects(p) - 1;
2085 check(int n, unsigned h, unsigned s, unsigned c, ullong start)
2087 ullong total, real_s, real_c;
2089 real_s = sector(s) - 1;
2090 real_c = cylinder(s, c);
2091 total = (real_c * sectors + real_s) * heads + h;
2093 printf("Partition %d contains sector 0\n", n);
2095 printf("Partition %d: head %d greater than maximum %d\n",
2097 if (real_s >= sectors)
2098 printf("Partition %d: sector %d greater than "
2099 "maximum %d\n", n, s, sectors);
2100 if (real_c >= cylinders)
2101 printf("Partition %d: cylinder %llu greater than "
2102 "maximum %d\n", n, real_c + 1, cylinders);
2103 if (cylinders <= 1024 && start != total)
2104 printf("Partition %d: previous sectors %llu disagrees with "
2105 "total %llu\n", n, start, total);
2113 ullong first[partitions], last[partitions];
2114 struct partition *p;
2116 if (warn_geometry())
2128 fill_bounds(first, last);
2129 for (i = 0; i < partitions; i++) {
2130 struct pte *pe = &ptes[i];
2133 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2134 check_consistency(p, i);
2135 if (get_partition_start(pe) < first[i])
2136 printf("Warning: bad start-of-data in "
2137 "partition %d\n", i + 1);
2138 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2140 total += last[i] + 1 - first[i];
2141 for (j = 0; j < i; j++) {
2142 if ((first[i] >= first[j] && first[i] <= last[j])
2143 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2144 printf("Warning: partition %d overlaps "
2145 "partition %d\n", j + 1, i + 1);
2146 total += first[i] >= first[j] ?
2147 first[i] : first[j];
2148 total -= last[i] <= last[j] ?
2155 if (extended_offset) {
2156 struct pte *pex = &ptes[ext_index];
2157 ullong e_last = get_start_sect(pex->part_table) +
2158 get_nr_sects(pex->part_table) - 1;
2160 for (i = 4; i < partitions; i++) {
2162 p = ptes[i].part_table;
2164 if (i != 4 || i + 1 < partitions)
2165 printf("Warning: partition %d "
2166 "is empty\n", i + 1);
2167 } else if (first[i] < extended_offset || last[i] > e_last) {
2168 printf("Logical partition %d not entirely in "
2169 "partition %d\n", i + 1, ext_index + 1);
2174 if (total > heads * sectors * cylinders)
2175 printf("Total allocated sectors %d greater than the maximum "
2176 "%d\n", total, heads * sectors * cylinders);
2178 total = heads * sectors * cylinders - total;
2180 printf("%d unallocated sectors\n", total);
2185 add_partition(int n, int sys)
2187 char mesg[256]; /* 48 does not suffice in Japanese */
2188 int i, num_read = 0;
2189 struct partition *p = ptes[n].part_table;
2190 struct partition *q = ptes[ext_index].part_table;
2192 ullong start, stop = 0;
2193 ullong first[partitions], last[partitions];
2195 if (p && p->sys_ind) {
2196 printf(msg_part_already_defined, n + 1);
2199 fill_bounds(first, last);
2201 start = sector_offset;
2202 if (display_in_cyl_units || !total_number_of_sectors)
2203 limit = (ullong) heads * sectors * cylinders - 1;
2205 limit = total_number_of_sectors - 1;
2206 if (extended_offset) {
2207 first[ext_index] = extended_offset;
2208 last[ext_index] = get_start_sect(q) +
2209 get_nr_sects(q) - 1;
2212 start = extended_offset + sector_offset;
2213 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2215 if (display_in_cyl_units)
2216 for (i = 0; i < partitions; i++)
2217 first[i] = (cround(first[i]) - 1) * units_per_sector;
2219 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2222 for (i = 0; i < partitions; i++) {
2225 if (start == ptes[i].offset)
2226 start += sector_offset;
2227 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2228 if (start >= first[i] && start <= lastplusoff)
2229 start = lastplusoff + 1;
2233 if (start >= temp+units_per_sector && num_read) {
2234 printf("Sector %lld is already allocated\n", temp);
2238 if (!num_read && start == temp) {
2241 saved_start = start;
2242 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2244 if (display_in_cyl_units) {
2245 start = (start - 1) * units_per_sector;
2246 if (start < saved_start) start = saved_start;
2250 } while (start != temp || !num_read);
2251 if (n > 4) { /* NOT for fifth partition */
2252 struct pte *pe = &ptes[n];
2254 pe->offset = start - sector_offset;
2255 if (pe->offset == extended_offset) { /* must be corrected */
2257 if (sector_offset == 1)
2262 for (i = 0; i < partitions; i++) {
2263 struct pte *pe = &ptes[i];
2265 if (start < pe->offset && limit >= pe->offset)
2266 limit = pe->offset - 1;
2267 if (start < first[i] && limit >= first[i])
2268 limit = first[i] - 1;
2270 if (start > limit) {
2271 printf("No free sectors available\n");
2276 if (cround(start) == cround(limit)) {
2279 snprintf(mesg, sizeof(mesg),
2280 "Last %s or +size or +sizeM or +sizeK",
2281 str_units(SINGULAR));
2282 stop = read_int(cround(start), cround(limit), cround(limit),
2283 cround(start), mesg);
2284 if (display_in_cyl_units) {
2285 stop = stop * units_per_sector - 1;
2291 set_partition(n, 0, start, stop, sys);
2293 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2295 if (IS_EXTENDED(sys)) {
2296 struct pte *pe4 = &ptes[4];
2297 struct pte *pen = &ptes[n];
2300 pen->ext_pointer = p;
2301 pe4->offset = extended_offset = start;
2302 pe4->sectorbuffer = xzalloc(sector_size);
2303 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2304 pe4->ext_pointer = pe4->part_table + 1;
2313 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2314 struct pte *pe = &ptes[partitions];
2316 pe->sectorbuffer = xzalloc(sector_size);
2317 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2318 pe->ext_pointer = pe->part_table + 1;
2323 add_partition(partitions - 1, LINUX_NATIVE);
2329 int i, free_primary = 0;
2331 if (warn_geometry())
2335 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2339 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2343 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2344 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2345 "table first (use 'o'). This will destroy the present disk contents.\n");
2349 for (i = 0; i < 4; i++)
2350 free_primary += !ptes[i].part_table->sys_ind;
2352 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2353 printf("The maximum number of partitions has been created\n");
2357 if (!free_primary) {
2358 if (extended_offset)
2361 printf("You must delete some partition and add "
2362 "an extended partition first\n");
2365 snprintf(line, sizeof(line),
2368 " p primary partition (1-4)\n",
2370 "l logical (5 or over)" : "e extended"));
2372 c = read_nonempty(line);
2373 if (c == 'p' || c == 'P') {
2374 i = get_nonexisting_partition(0, 4);
2376 add_partition(i, LINUX_NATIVE);
2379 if (c == 'l' && extended_offset) {
2383 if (c == 'e' && !extended_offset) {
2384 i = get_nonexisting_partition(0, 4);
2386 add_partition(i, EXTENDED);
2389 printf("Invalid partition number "
2390 "for type '%c'\n", c);
2401 for (i = 0; i < 3; i++)
2402 if (ptes[i].changed)
2403 ptes[3].changed = 1;
2404 for (i = 3; i < partitions; i++) {
2405 struct pte *pe = &ptes[i];
2408 write_part_table_flag(pe->sectorbuffer);
2409 write_sector(pe->offset, pe->sectorbuffer);
2413 else if (LABEL_IS_SGI) {
2414 /* no test on change? the printf below might be mistaken */
2417 else if (LABEL_IS_SUN) {
2420 for (i = 0; i < 8; i++)
2421 if (ptes[i].changed)
2427 printf("The partition table has been altered!\n\n");
2428 reread_partition_table(1);
2432 reread_partition_table(int leave)
2436 printf("Calling ioctl() to re-read partition table\n");
2438 /* sleep(2); Huh? */
2439 i = ioctl(fd, BLKRRPART);
2442 /* some kernel versions (1.2.x) seem to have trouble
2443 rereading the partition table, but if asked to do it
2444 twice, the second time works. - biro@yggdrasil.com */
2447 i = ioctl(fd, BLKRRPART);
2452 bb_perror_msg("WARNING: rereading partition table "
2453 "failed, kernel still uses old table");
2459 "\nWARNING: If you have created or modified any DOS 6.x\n"
2460 "partitions, please see the fdisk manual page for additional\n"
2465 if (ENABLE_FEATURE_CLEAN_UP)
2470 #endif /* FEATURE_FDISK_WRITABLE */
2472 #if ENABLE_FEATURE_FDISK_ADVANCED
2473 #define MAX_PER_LINE 16
2475 print_buffer(char *pbuffer)
2479 for (i = 0, l = 0; i < sector_size; i++, l++) {
2481 printf("0x%03X:", i);
2482 printf(" %02X", (unsigned char) pbuffer[i]);
2483 if (l == MAX_PER_LINE - 1) {
2498 printf("Device: %s\n", disk_device);
2499 if (LABEL_IS_SGI || LABEL_IS_SUN)
2500 print_buffer(MBRbuffer);
2502 for (i = 3; i < partitions; i++)
2503 print_buffer(ptes[i].sectorbuffer);
2510 struct pte *pe = &ptes[i];
2511 struct partition *p = pe->part_table;
2514 if (warn_geometry())
2516 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2517 printf("Partition %d has no data area\n", i + 1);
2520 first = get_partition_start(pe);
2521 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2522 "New beginning of data") - pe->offset;
2524 if (new != get_nr_sects(p)) {
2525 first = get_nr_sects(p) + get_start_sect(p) - new;
2526 set_nr_sects(p, first);
2527 set_start_sect(p, new);
2539 c = tolower(read_nonempty("Expert command (m for help): "));
2547 move_begin(get_partition(0, partitions));
2550 user_cylinders = cylinders =
2551 read_int(1, cylinders, 1048576, 0,
2552 "Number of cylinders");
2554 sun_set_ncyl(cylinders);
2564 else if (LABEL_IS_SUN)
2566 else if (LABEL_IS_DOS)
2571 fix_partition_table_order();
2574 #if ENABLE_FEATURE_SGI_LABEL
2579 user_heads = heads = read_int(1, heads, 256, 0,
2604 user_sectors = sectors = read_int(1, sectors, 63, 0,
2605 "Number of sectors");
2606 if (dos_compatible_flag) {
2607 sector_offset = sectors;
2608 printf("Warning: setting sector offset for DOS "
2617 write_table(); /* does not return */
2621 sun_set_pcylcount();
2628 #endif /* ADVANCED mode */
2631 is_ide_cdrom_or_tape(const char *device)
2635 struct stat statbuf;
2638 /* No device was given explicitly, and we are trying some
2639 likely things. But opening /dev/hdc may produce errors like
2640 "hdc: tray open or drive not ready"
2641 if it happens to be a CD-ROM drive. It even happens that
2642 the process hangs on the attempt to read a music CD.
2643 So try to be careful. This only works since 2.1.73. */
2645 if (strncmp("/dev/hd", device, 7))
2648 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2649 procf = fopen(buf, "r");
2650 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2651 is_ide = (!strncmp(buf, "cdrom", 5) ||
2652 !strncmp(buf, "tape", 4));
2654 /* Now when this proc file does not exist, skip the
2655 device when it is read-only. */
2656 if (stat(device, &statbuf) == 0)
2657 is_ide = ((statbuf.st_mode & 0222) == 0);
2666 trydev(const char *device, int user_specified)
2670 disk_device = device;
2671 if (setjmp(listingbuf))
2673 if (!user_specified)
2674 if (is_ide_cdrom_or_tape(device))
2676 fd = open(disk_device, type_open);
2678 gb = get_boot(try_only);
2679 if (gb > 0) { /* I/O error */
2681 } else if (gb < 0) { /* no DOS signature */
2682 list_disk_geometry();
2686 #if ENABLE_FEATURE_OSF_LABEL
2687 if (bsd_trydev(device) < 0)
2689 printf("Disk %s doesn't contain a valid "
2690 "partition table\n", device);
2695 #if ENABLE_FEATURE_FDISK_WRITABLE
2696 if (!LABEL_IS_SUN && partitions > 4){
2697 delete_partition(ext_index);
2702 /* Ignore other errors, since we try IDE
2703 and SCSI hard disks which may not be
2704 installed on the system. */
2705 if (errno == EACCES) {
2706 printf("Cannot open %s\n", device);
2712 /* for fdisk -l: try all things in /proc/partitions
2713 that look like a partition name (do not end in a digit) */
2718 char line[100], ptname[100], devname[120], *s;
2721 procpt = fopen_or_warn("/proc/partitions", "r");
2723 while (fgets(line, sizeof(line), procpt)) {
2724 if (sscanf(line, " %d %d %d %[^\n ]",
2725 &ma, &mi, &sz, ptname) != 4)
2727 for (s = ptname; *s; s++);
2730 sprintf(devname, "/dev/%s", ptname);
2733 #if ENABLE_FEATURE_CLEAN_UP
2738 #if ENABLE_FEATURE_FDISK_WRITABLE
2740 unknown_command(int c)
2742 printf("%c: unknown command\n", c);
2746 int fdisk_main(int argc, char **argv);
2747 int fdisk_main(int argc, char **argv)
2749 char *str_b, *str_C, *str_H, *str_S;
2753 * fdisk -l [-b sectorsize] [-u] device ...
2754 * fdisk -s [partition] ...
2755 * fdisk [-b sectorsize] [-u] device
2757 * Options -C, -H, -S set the geometry.
2766 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2769 PTR_TO_GLOBALS = xzalloc(sizeof(G));
2771 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2772 &str_b, &str_C, &str_H, &str_S);
2775 if (opt & OPT_b) { // -b
2776 /* Ugly: this sector size is really per device,
2777 so cannot be combined with multiple disks,
2778 and the same goes for the C/H/S options.
2780 sector_size = xatoi_u(str_b);
2781 if (sector_size != 512 && sector_size != 1024 &&
2782 sector_size != 2048)
2785 user_set_sector_size = 1;
2787 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2788 if (opt & OPT_H) { // -H
2789 user_heads = xatoi_u(str_H);
2790 if (user_heads <= 0 || user_heads >= 256)
2793 //if (opt & OPT_l) // -l
2794 if (opt & OPT_S) { // -S
2795 user_sectors = xatoi_u(str_S);
2796 if (user_sectors <= 0 || user_sectors >= 64)
2799 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2800 //if (opt & OPT_s) // -s
2802 if (user_set_sector_size && argc != 1)
2803 printf("Warning: the -b (set sector size) option should"
2804 " be used with one specified device\n");
2806 #if ENABLE_FEATURE_FDISK_WRITABLE
2810 type_open = O_RDONLY;
2813 #if defined(__GNUC__)
2814 /* avoid gcc warning:
2815 variable `k' might be clobbered by `longjmp' */
2819 for (k = 0; k < argc; k++)
2822 /* we no longer have default device names */
2823 /* but, we can use /proc/partitions instead */
2827 #if ENABLE_FEATURE_FDISK_WRITABLE
2831 #if ENABLE_FEATURE_FDISK_BLKSIZE
2837 type_open = O_RDONLY;
2842 for (j = 0; j < argc; j++) {
2843 disk_device = argv[j];
2844 fd = open(disk_device, type_open);
2846 fdisk_fatal(unable_to_open);
2847 if (ioctl(fd, BLKGETSIZE, &size))
2848 fdisk_fatal(ioctl_error);
2851 printf("%ld\n", size/2);
2853 printf("%s: %ld\n", argv[j], size/2);
2859 #if ENABLE_FEATURE_FDISK_WRITABLE
2863 disk_device = argv[0];
2867 /* OSF label, and no DOS label */
2868 printf("Detected an OSF/1 disklabel on %s, entering "
2869 "disklabel mode\n", disk_device);
2871 /*Why do we do this? It seems to be counter-intuitive*/
2872 current_label_type = label_dos;
2873 /* If we return we may want to make an empty DOS label? */
2879 c = tolower(read_nonempty("Command (m for help): "));
2883 toggle_active(get_partition(1, partitions));
2884 else if (LABEL_IS_SUN)
2885 toggle_sunflags(get_partition(1, partitions),
2887 else if (LABEL_IS_SGI)
2888 sgi_set_bootpartition(
2889 get_partition(1, partitions));
2895 printf("\nThe current boot file is: %s\n",
2896 sgi_get_bootfile());
2897 if (read_maybe_empty("Please enter the name of the "
2898 "new boot file: ") == '\n')
2899 printf("Boot file unchanged\n");
2901 sgi_set_bootfile(line_ptr);
2903 #if ENABLE_FEATURE_OSF_LABEL
2910 toggle_dos_compatibility_flag();
2911 else if (LABEL_IS_SUN)
2912 toggle_sunflags(get_partition(1, partitions),
2914 else if (LABEL_IS_SGI)
2915 sgi_set_swappartition(
2916 get_partition(1, partitions));
2923 /* If sgi_label then don't use get_existing_partition,
2924 let the user select a partition, since
2925 get_existing_partition() only works for Linux-like
2927 if (!LABEL_IS_SGI) {
2928 j = get_existing_partition(1, partitions);
2930 j = get_partition(1, partitions);
2933 delete_partition(j);
2942 list_types(get_sys_types());
2961 #if ENABLE_FEATURE_SUN_LABEL
2975 write_table(); /* does not return */
2977 #if ENABLE_FEATURE_FDISK_ADVANCED
2980 printf("\n\tSorry, no experts menu for SGI "
2981 "partition tables available\n\n");
2992 #endif /* FEATURE_FDISK_WRITABLE */