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[] ALIGN1 =
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[] ALIGN1 =
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[] ALIGN1 = "cannot open %s";
86 static const char unable_to_read[] ALIGN1 = "cannot read from %s";
87 static const char unable_to_seek[] ALIGN1 = "cannot seek on %s";
88 static const char unable_to_write[] ALIGN1 = "cannot write to %s";
89 static const char ioctl_error[] ALIGN1 = "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 ENABLE_FDISK_SUPPORT_LARGE_DISKS
642 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
643 fdisk_fatal(unable_to_seek);
645 if (secno > MAXINT(off_t)
646 || lseek(fd, (off_t)secno, SEEK_SET) == (off_t) -1
648 fdisk_fatal(unable_to_seek);
653 #if ENABLE_FEATURE_FDISK_WRITABLE
655 write_sector(ullong secno, char *buf)
658 if (write(fd, buf, sector_size) != sector_size)
659 fdisk_fatal(unable_to_write);
663 /* Allocate a buffer and read a partition table sector */
665 read_pte(struct pte *pe, ullong offset)
668 pe->sectorbuffer = xmalloc(sector_size);
670 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
671 fdisk_fatal(unable_to_read);
672 #if ENABLE_FEATURE_FDISK_WRITABLE
675 pe->part_table = pe->ext_pointer = NULL;
679 get_partition_start(const struct pte *pe)
681 return pe->offset + get_start_sect(pe->part_table);
684 #if ENABLE_FEATURE_FDISK_WRITABLE
686 * Avoid warning about DOS partitions when no DOS partition was changed.
687 * Here a heuristic "is probably dos partition".
688 * We might also do the opposite and warn in all cases except
689 * for "is probably nondos partition".
692 is_dos_partition(int t)
694 return (t == 1 || t == 4 || t == 6 ||
695 t == 0x0b || t == 0x0c || t == 0x0e ||
696 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
697 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
698 t == 0xc1 || t == 0xc4 || t == 0xc6);
704 puts("Command Action");
706 puts("a\ttoggle a read only flag"); /* sun */
707 puts("b\tedit bsd disklabel");
708 puts("c\ttoggle the mountable flag"); /* sun */
709 puts("d\tdelete a partition");
710 puts("l\tlist known partition types");
711 puts("n\tadd a new partition");
712 puts("o\tcreate a new empty DOS partition table");
713 puts("p\tprint the partition table");
714 puts("q\tquit without saving changes");
715 puts("s\tcreate a new empty Sun disklabel"); /* sun */
716 puts("t\tchange a partition's system id");
717 puts("u\tchange display/entry units");
718 puts("v\tverify the partition table");
719 puts("w\twrite table to disk and exit");
720 #if ENABLE_FEATURE_FDISK_ADVANCED
721 puts("x\textra functionality (experts only)");
723 } else if (LABEL_IS_SGI) {
724 puts("a\tselect bootable partition"); /* sgi flavour */
725 puts("b\tedit bootfile entry"); /* sgi */
726 puts("c\tselect sgi swap partition"); /* sgi flavour */
727 puts("d\tdelete a partition");
728 puts("l\tlist known partition types");
729 puts("n\tadd a new partition");
730 puts("o\tcreate a new empty DOS partition table");
731 puts("p\tprint the partition table");
732 puts("q\tquit without saving changes");
733 puts("s\tcreate a new empty Sun disklabel"); /* sun */
734 puts("t\tchange a partition's system id");
735 puts("u\tchange display/entry units");
736 puts("v\tverify the partition table");
737 puts("w\twrite table to disk and exit");
738 } else if (LABEL_IS_AIX) {
739 puts("o\tcreate a new empty DOS partition table");
740 puts("q\tquit without saving changes");
741 puts("s\tcreate a new empty Sun disklabel"); /* sun */
743 puts("a\ttoggle a bootable flag");
744 puts("b\tedit bsd disklabel");
745 puts("c\ttoggle the dos compatibility flag");
746 puts("d\tdelete a partition");
747 puts("l\tlist known partition types");
748 puts("n\tadd a new partition");
749 puts("o\tcreate a new empty DOS partition table");
750 puts("p\tprint the partition table");
751 puts("q\tquit without saving changes");
752 puts("s\tcreate a new empty Sun disklabel"); /* sun */
753 puts("t\tchange a partition's system id");
754 puts("u\tchange display/entry units");
755 puts("v\tverify the partition table");
756 puts("w\twrite table to disk and exit");
757 #if ENABLE_FEATURE_FDISK_ADVANCED
758 puts("x\textra functionality (experts only)");
762 #endif /* FEATURE_FDISK_WRITABLE */
765 #if ENABLE_FEATURE_FDISK_ADVANCED
769 puts("Command Action");
771 puts("a\tchange number of alternate cylinders"); /*sun*/
772 puts("c\tchange number of cylinders");
773 puts("d\tprint the raw data in the partition table");
774 puts("e\tchange number of extra sectors per cylinder");/*sun*/
775 puts("h\tchange number of heads");
776 puts("i\tchange interleave factor"); /*sun*/
777 puts("o\tchange rotation speed (rpm)"); /*sun*/
778 puts("p\tprint the partition table");
779 puts("q\tquit without saving changes");
780 puts("r\treturn to main menu");
781 puts("s\tchange number of sectors/track");
782 puts("v\tverify the partition table");
783 puts("w\twrite table to disk and exit");
784 puts("y\tchange number of physical cylinders"); /*sun*/
785 } else if (LABEL_IS_SGI) {
786 puts("b\tmove beginning of data in a partition"); /* !sun */
787 puts("c\tchange number of cylinders");
788 puts("d\tprint the raw data in the partition table");
789 puts("e\tlist extended partitions"); /* !sun */
790 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
791 puts("h\tchange number of heads");
792 puts("p\tprint the partition table");
793 puts("q\tquit without saving changes");
794 puts("r\treturn to main menu");
795 puts("s\tchange number of sectors/track");
796 puts("v\tverify the partition table");
797 puts("w\twrite table to disk and exit");
798 } else if (LABEL_IS_AIX) {
799 puts("b\tmove beginning of data in a partition"); /* !sun */
800 puts("c\tchange number of cylinders");
801 puts("d\tprint the raw data in the partition table");
802 puts("e\tlist extended partitions"); /* !sun */
803 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
804 puts("h\tchange number of heads");
805 puts("p\tprint the partition table");
806 puts("q\tquit without saving changes");
807 puts("r\treturn to main menu");
808 puts("s\tchange number of sectors/track");
809 puts("v\tverify the partition table");
810 puts("w\twrite table to disk and exit");
812 puts("b\tmove beginning of data in a partition"); /* !sun */
813 puts("c\tchange number of cylinders");
814 puts("d\tprint the raw data in the partition table");
815 puts("e\tlist extended partitions"); /* !sun */
816 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
817 #if ENABLE_FEATURE_SGI_LABEL
818 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
820 puts("h\tchange number of heads");
821 puts("p\tprint the partition table");
822 puts("q\tquit without saving changes");
823 puts("r\treturn to main menu");
824 puts("s\tchange number of sectors/track");
825 puts("v\tverify the partition table");
826 puts("w\twrite table to disk and exit");
829 #endif /* ADVANCED mode */
831 #if ENABLE_FEATURE_FDISK_WRITABLE
832 static const char *const *
836 LABEL_IS_SUN ? sun_sys_types :
837 LABEL_IS_SGI ? sgi_sys_types :
841 #define get_sys_types() i386_sys_types
842 #endif /* FEATURE_FDISK_WRITABLE */
845 partition_type(unsigned char type)
848 const char *const *types = get_sys_types();
850 for (i = 0; types[i]; i++)
851 if ((unsigned char)types[i][0] == type)
858 #if ENABLE_FEATURE_FDISK_WRITABLE
862 return LABEL_IS_SUN ? sunlabel->infos[i].id :
863 (LABEL_IS_SGI ? sgi_get_sysid(i) :
864 ptes[i].part_table->sys_ind);
868 list_types(const char *const *sys)
873 unsigned done, next, size;
876 for (size = 0; sys[size]; size++) /* */;
879 for (i = COLS-1; i >= 0; i--) {
880 done += (size + i - done) / (i + 1);
881 last[COLS-1 - i] = done;
886 printf("%c%2x %-22.22s", i ? ' ' : '\n',
887 (unsigned char)sys[next][0],
889 next = last[i++] + done;
890 if (i >= COLS || next >= last[i]) {
894 } while (done < last[0]);
897 #endif /* FEATURE_FDISK_WRITABLE */
900 is_cleared_partition(const struct partition *p)
902 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
903 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
904 get_start_sect(p) || get_nr_sects(p));
908 clear_partition(struct partition *p)
912 memset(p, 0, sizeof(struct partition));
915 #if ENABLE_FEATURE_FDISK_WRITABLE
917 set_partition(int i, int doext, ullong start, ullong stop, int sysid)
923 p = ptes[i].ext_pointer;
924 offset = extended_offset;
926 p = ptes[i].part_table;
927 offset = ptes[i].offset;
931 set_start_sect(p, start - offset);
932 set_nr_sects(p, stop - start + 1);
933 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
934 start = heads*sectors*1024 - 1;
935 set_hsc(p->head, p->sector, p->cyl, start);
936 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
937 stop = heads*sectors*1024 - 1;
938 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
946 if (heads && sectors && cylinders)
949 printf("Unknown value(s) for:");
955 printf(" cylinders");
957 #if ENABLE_FEATURE_FDISK_WRITABLE
958 " (settable in the extra functions menu)"
967 int cyl_units = heads * sectors;
969 if (display_in_cyl_units && cyl_units)
970 units_per_sector = cyl_units;
972 units_per_sector = 1; /* in sectors */
975 #if ENABLE_FEATURE_FDISK_WRITABLE
979 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
981 "The number of cylinders for this disk is set to %d.\n"
982 "There is nothing wrong with that, but this is larger than 1024,\n"
983 "and could in certain setups cause problems with:\n"
984 "1) software that runs at boot time (e.g., old versions of LILO)\n"
985 "2) booting and partitioning software from other OSs\n"
986 " (e.g., DOS FDISK, OS/2 FDISK)\n",
992 read_extended(int ext)
996 struct partition *p, *q;
1000 pex->ext_pointer = pex->part_table;
1002 p = pex->part_table;
1003 if (!get_start_sect(p)) {
1004 printf("Bad offset in primary extended partition\n");
1008 while (IS_EXTENDED(p->sys_ind)) {
1009 struct pte *pe = &ptes[partitions];
1011 if (partitions >= MAXIMUM_PARTS) {
1012 /* This is not a Linux restriction, but
1013 this program uses arrays of size MAXIMUM_PARTS.
1014 Do not try to 'improve' this test. */
1015 struct pte *pre = &ptes[partitions-1];
1016 #if ENABLE_FEATURE_FDISK_WRITABLE
1017 printf("Warning: deleting partitions after %d\n",
1021 clear_partition(pre->ext_pointer);
1025 read_pte(pe, extended_offset + get_start_sect(p));
1027 if (!extended_offset)
1028 extended_offset = get_start_sect(p);
1030 q = p = pt_offset(pe->sectorbuffer, 0);
1031 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1032 if (IS_EXTENDED(p->sys_ind)) {
1033 if (pe->ext_pointer)
1034 printf("Warning: extra link "
1035 "pointer in partition table"
1036 " %d\n", partitions + 1);
1038 pe->ext_pointer = p;
1039 } else if (p->sys_ind) {
1041 printf("Warning: ignoring extra "
1042 "data in partition table"
1043 " %d\n", partitions + 1);
1049 /* very strange code here... */
1050 if (!pe->part_table) {
1051 if (q != pe->ext_pointer)
1054 pe->part_table = q + 1;
1056 if (!pe->ext_pointer) {
1057 if (q != pe->part_table)
1058 pe->ext_pointer = q;
1060 pe->ext_pointer = q + 1;
1063 p = pe->ext_pointer;
1067 #if ENABLE_FEATURE_FDISK_WRITABLE
1068 /* remove empty links */
1070 for (i = 4; i < partitions; i++) {
1071 struct pte *pe = &ptes[i];
1073 if (!get_nr_sects(pe->part_table)
1074 && (partitions > 5 || ptes[4].part_table->sys_ind)
1076 printf("Omitting empty partition (%d)\n", i+1);
1077 delete_partition(i);
1078 goto remove; /* numbering changed */
1084 #if ENABLE_FEATURE_FDISK_WRITABLE
1086 create_doslabel(void)
1090 printf(msg_building_new_label, "DOS disklabel");
1092 current_label_type = label_dos;
1094 #if ENABLE_FEATURE_OSF_LABEL
1095 possibly_osf_label = 0;
1099 for (i = 510-64; i < 510; i++)
1101 write_part_table_flag(MBRbuffer);
1102 extended_offset = 0;
1103 set_all_unchanged();
1105 get_boot(create_empty_dos);
1107 #endif /* FEATURE_FDISK_WRITABLE */
1110 get_sectorsize(void)
1112 if (!user_set_sector_size) {
1114 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1116 if (sector_size != DEFAULT_SECTOR_SIZE)
1117 printf("Note: sector size is %d (not %d)\n",
1118 sector_size, DEFAULT_SECTOR_SIZE);
1123 get_kernel_geometry(void)
1125 struct hd_geometry geometry;
1127 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1128 kern_heads = geometry.heads;
1129 kern_sectors = geometry.sectors;
1130 /* never use geometry.cylinders - it is truncated */
1135 get_partition_table_geometry(void)
1137 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1138 struct partition *p;
1139 int i, h, s, hh, ss;
1143 if (!(valid_part_table_flag((char*)bufp)))
1147 for (i = 0; i < 4; i++) {
1148 p = pt_offset(bufp, i);
1149 if (p->sys_ind != 0) {
1150 h = p->end_head + 1;
1151 s = (p->end_sector & 077);
1156 } else if (hh != h || ss != s)
1161 if (!first && !bad) {
1174 sec_fac = sector_size / 512;
1175 #if ENABLE_FEATURE_SUN_LABEL
1176 guess_device_type();
1178 heads = cylinders = sectors = 0;
1179 kern_heads = kern_sectors = 0;
1180 pt_heads = pt_sectors = 0;
1182 get_kernel_geometry();
1183 get_partition_table_geometry();
1185 heads = user_heads ? user_heads :
1186 pt_heads ? pt_heads :
1187 kern_heads ? kern_heads : 255;
1188 sectors = user_sectors ? user_sectors :
1189 pt_sectors ? pt_sectors :
1190 kern_sectors ? kern_sectors : 63;
1191 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1192 /* got bytes, convert to 512 byte sectors */
1193 total_number_of_sectors = (v64 >> 9);
1195 unsigned long longsectors; /* need temp of type long */
1196 if (ioctl(fd, BLKGETSIZE, &longsectors))
1198 total_number_of_sectors = longsectors;
1202 if (dos_compatible_flag)
1203 sector_offset = sectors;
1205 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
1207 cylinders = user_cylinders;
1211 * Read MBR. Returns:
1212 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1213 * 0: found or created label
1217 get_boot(enum action what)
1223 for (i = 0; i < 4; i++) {
1224 struct pte *pe = &ptes[i];
1226 pe->part_table = pt_offset(MBRbuffer, i);
1227 pe->ext_pointer = NULL;
1229 pe->sectorbuffer = MBRbuffer;
1230 #if ENABLE_FEATURE_FDISK_WRITABLE
1231 pe->changed = (what == create_empty_dos);
1235 #if ENABLE_FEATURE_SUN_LABEL
1236 if (what == create_empty_sun && check_sun_label())
1240 memset(MBRbuffer, 0, 512);
1242 #if ENABLE_FEATURE_FDISK_WRITABLE
1243 if (what == create_empty_dos)
1244 goto got_dos_table; /* skip reading disk */
1246 fd = open(disk_device, type_open);
1248 fd = open(disk_device, O_RDONLY);
1250 if (what == try_only)
1252 fdisk_fatal(unable_to_open);
1254 printf("You will not be able to write "
1255 "the partition table\n");
1258 if (512 != read(fd, MBRbuffer, 512)) {
1259 if (what == try_only)
1261 fdisk_fatal(unable_to_read);
1264 fd = open(disk_device, O_RDONLY);
1267 if (512 != read(fd, MBRbuffer, 512))
1275 #if ENABLE_FEATURE_SUN_LABEL
1276 if (check_sun_label())
1280 #if ENABLE_FEATURE_SGI_LABEL
1281 if (check_sgi_label())
1285 #if ENABLE_FEATURE_AIX_LABEL
1286 if (check_aix_label())
1290 #if ENABLE_FEATURE_OSF_LABEL
1291 if (check_osf_label()) {
1292 possibly_osf_label = 1;
1293 if (!valid_part_table_flag(MBRbuffer)) {
1294 current_label_type = label_osf;
1297 printf("This disk has both DOS and BSD magic.\n"
1298 "Give the 'b' command to go to BSD mode.\n");
1302 #if ENABLE_FEATURE_FDISK_WRITABLE
1306 if (!valid_part_table_flag(MBRbuffer)) {
1307 #if !ENABLE_FEATURE_FDISK_WRITABLE
1312 printf("Device contains neither a valid DOS "
1313 "partition table, nor Sun, SGI or OSF "
1316 #if ENABLE_FEATURE_SUN_LABEL
1325 case create_empty_dos:
1326 #if ENABLE_FEATURE_SUN_LABEL
1327 case create_empty_sun:
1331 bb_error_msg_and_die("internal error");
1333 #endif /* FEATURE_FDISK_WRITABLE */
1336 #if ENABLE_FEATURE_FDISK_WRITABLE
1341 for (i = 0; i < 4; i++) {
1342 struct pte *pe = &ptes[i];
1344 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1345 if (partitions != 4)
1346 printf("Ignoring extra extended "
1347 "partition %d\n", i + 1);
1353 for (i = 3; i < partitions; i++) {
1354 struct pte *pe = &ptes[i];
1356 if (!valid_part_table_flag(pe->sectorbuffer)) {
1357 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1358 "table %d will be corrected by w(rite)\n",
1359 pe->sectorbuffer[510],
1360 pe->sectorbuffer[511],
1362 #if ENABLE_FEATURE_FDISK_WRITABLE
1371 #if ENABLE_FEATURE_FDISK_WRITABLE
1373 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1374 * If the user hits Enter, DFLT is returned.
1375 * Answers like +10 are interpreted as offsets from BASE.
1377 * There is no default if DFLT is not between LOW and HIGH.
1380 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1384 const char *fmt = "%s (%u-%u, default %u): ";
1386 if (dflt < low || dflt > high) {
1387 fmt = "%s (%u-%u): ";
1392 int use_default = default_ok;
1394 /* ask question and read answer */
1396 printf(fmt, mesg, low, high, dflt);
1397 read_maybe_empty("");
1398 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1399 && *line_ptr != '-' && *line_ptr != '+');
1401 if (*line_ptr == '+' || *line_ptr == '-') {
1402 int minus = (*line_ptr == '-');
1405 i = atoi(line_ptr + 1);
1407 while (isdigit(*++line_ptr))
1410 switch (*line_ptr) {
1413 if (!display_in_cyl_units)
1414 i *= heads * sectors;
1428 absolute = 1000000000;
1437 bytes = (ullong) i * absolute;
1438 unit = sector_size * units_per_sector;
1439 bytes += unit/2; /* round */
1448 while (isdigit(*line_ptr)) {
1455 printf("Using default value %u\n", i);
1457 if (i >= low && i <= high)
1459 printf("Value is out of range\n");
1465 get_partition(int warn, int max)
1470 i = read_int(1, 0, max, 0, "Partition number") - 1;
1474 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1475 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1476 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1478 printf("Warning: partition %d has empty type\n", i+1);
1485 get_existing_partition(int warn, int max)
1490 for (i = 0; i < max; i++) {
1491 struct pte *pe = &ptes[i];
1492 struct partition *p = pe->part_table;
1494 if (p && !is_cleared_partition(p)) {
1501 printf("Selected partition %d\n", pno+1);
1504 printf("No partition is defined yet!\n");
1508 return get_partition(warn, max);
1512 get_nonexisting_partition(int warn, int max)
1517 for (i = 0; i < max; i++) {
1518 struct pte *pe = &ptes[i];
1519 struct partition *p = pe->part_table;
1521 if (p && is_cleared_partition(p)) {
1528 printf("Selected partition %d\n", pno+1);
1531 printf("All primary partitions have been defined already!\n");
1535 return get_partition(warn, max);
1542 display_in_cyl_units = !display_in_cyl_units;
1544 printf("Changing display/entry units to %s\n",
1549 toggle_active(int i)
1551 struct pte *pe = &ptes[i];
1552 struct partition *p = pe->part_table;
1554 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1555 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1556 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1561 toggle_dos_compatibility_flag(void)
1563 dos_compatible_flag = ~dos_compatible_flag;
1564 if (dos_compatible_flag) {
1565 sector_offset = sectors;
1566 printf("DOS Compatibility flag is set\n");
1569 printf("DOS Compatibility flag is not set\n");
1574 delete_partition(int i)
1576 struct pte *pe = &ptes[i];
1577 struct partition *p = pe->part_table;
1578 struct partition *q = pe->ext_pointer;
1580 /* Note that for the fifth partition (i == 4) we don't actually
1581 * decrement partitions.
1584 if (warn_geometry())
1585 return; /* C/H/S not set */
1589 sun_delete_partition(i);
1593 sgi_delete_partition(i);
1598 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1600 ptes[ext_index].ext_pointer = NULL;
1601 extended_offset = 0;
1607 if (!q->sys_ind && i > 4) {
1608 /* the last one in the chain - just delete */
1611 clear_partition(ptes[i].ext_pointer);
1612 ptes[i].changed = 1;
1614 /* not the last one - further ones will be moved down */
1616 /* delete this link in the chain */
1617 p = ptes[i-1].ext_pointer;
1619 set_start_sect(p, get_start_sect(q));
1620 set_nr_sects(p, get_nr_sects(q));
1621 ptes[i-1].changed = 1;
1622 } else if (partitions > 5) { /* 5 will be moved to 4 */
1623 /* the first logical in a longer chain */
1626 if (pe->part_table) /* prevent SEGFAULT */
1627 set_start_sect(pe->part_table,
1628 get_partition_start(pe) -
1630 pe->offset = extended_offset;
1634 if (partitions > 5) {
1636 while (i < partitions) {
1637 ptes[i] = ptes[i+1];
1641 /* the only logical: clear only */
1642 clear_partition(ptes[i].part_table);
1649 int i, sys, origsys;
1650 struct partition *p;
1652 /* If sgi_label then don't use get_existing_partition,
1653 let the user select a partition, since get_existing_partition()
1654 only works for Linux like partition tables. */
1655 if (!LABEL_IS_SGI) {
1656 i = get_existing_partition(0, partitions);
1658 i = get_partition(0, partitions);
1662 p = ptes[i].part_table;
1663 origsys = sys = get_sysid(i);
1665 /* if changing types T to 0 is allowed, then
1666 the reverse change must be allowed, too */
1667 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1668 printf("Partition %d does not exist yet!\n", i + 1);
1672 sys = read_hex(get_sys_types());
1674 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1675 printf("Type 0 means free space to many systems\n"
1676 "(but not to Linux). Having partitions of\n"
1677 "type 0 is probably unwise.\n");
1681 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1682 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1683 printf("You cannot change a partition into"
1684 " an extended one or vice versa\n");
1690 #if ENABLE_FEATURE_SUN_LABEL
1691 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1692 printf("Consider leaving partition 3 "
1693 "as Whole disk (5),\n"
1694 "as SunOS/Solaris expects it and "
1695 "even Linux likes it\n\n");
1697 #if ENABLE_FEATURE_SGI_LABEL
1700 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1701 (i == 8 && sys != 0)
1704 printf("Consider leaving partition 9 "
1705 "as volume header (0),\nand "
1706 "partition 11 as entire volume (6)"
1707 "as IRIX expects it\n\n");
1713 sun_change_sysid(i, sys);
1714 } else if (LABEL_IS_SGI) {
1715 sgi_change_sysid(i, sys);
1719 printf("Changed system type of partition %d "
1720 "to %x (%s)\n", i + 1, sys,
1721 partition_type(sys));
1722 ptes[i].changed = 1;
1723 if (is_dos_partition(origsys) ||
1724 is_dos_partition(sys))
1730 #endif /* FEATURE_FDISK_WRITABLE */
1733 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1734 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1735 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1736 * Lubkin Oct. 1991). */
1739 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1741 int spc = heads * sectors;
1746 *s = ls % sectors + 1; /* sectors count from 1 */
1750 check_consistency(const struct partition *p, int partition)
1752 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1753 unsigned pec, peh, pes; /* physical ending c, h, s */
1754 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1755 unsigned lec, leh, les; /* logical ending c, h, s */
1757 if (!heads || !sectors || (partition >= 4))
1758 return; /* do not check extended partitions */
1760 /* physical beginning c, h, s */
1761 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1763 pbs = p->sector & 0x3f;
1765 /* physical ending c, h, s */
1766 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1768 pes = p->end_sector & 0x3f;
1770 /* compute logical beginning (c, h, s) */
1771 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1773 /* compute logical ending (c, h, s) */
1774 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1776 /* Same physical / logical beginning? */
1777 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1778 printf("Partition %d has different physical/logical "
1779 "beginnings (non-Linux?):\n", partition + 1);
1780 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1781 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1784 /* Same physical / logical ending? */
1785 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1786 printf("Partition %d has different physical/logical "
1787 "endings:\n", partition + 1);
1788 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1789 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1792 /* Ending on cylinder boundary? */
1793 if (peh != (heads - 1) || pes != sectors) {
1794 printf("Partition %i does not end on cylinder boundary\n",
1800 list_disk_geometry(void)
1802 long long bytes = (total_number_of_sectors << 9);
1803 long megabytes = bytes/1000000;
1805 if (megabytes < 10000)
1806 printf("\nDisk %s: %ld MB, %lld bytes\n",
1807 disk_device, megabytes, bytes);
1809 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1810 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1811 printf("%d heads, %d sectors/track, %d cylinders",
1812 heads, sectors, cylinders);
1813 if (units_per_sector == 1)
1814 printf(", total %llu sectors",
1815 total_number_of_sectors / (sector_size/512));
1816 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1818 units_per_sector, sector_size, units_per_sector * sector_size);
1822 * Check whether partition entries are ordered by their starting positions.
1823 * Return 0 if OK. Return i if partition i should have been earlier.
1824 * Two separate checks: primary and logical partitions.
1827 wrong_p_order(int *prev)
1829 const struct pte *pe;
1830 const struct partition *p;
1831 ullong last_p_start_pos = 0, p_start_pos;
1834 for (i = 0; i < partitions; i++) {
1837 last_p_start_pos = 0;
1840 if ((p = pe->part_table)->sys_ind) {
1841 p_start_pos = get_partition_start(pe);
1843 if (last_p_start_pos > p_start_pos) {
1849 last_p_start_pos = p_start_pos;
1856 #if ENABLE_FEATURE_FDISK_ADVANCED
1858 * Fix the chain of logicals.
1859 * extended_offset is unchanged, the set of sectors used is unchanged
1860 * The chain is sorted so that sectors increase, and so that
1861 * starting sectors increase.
1863 * After this it may still be that cfdisk doesnt like the table.
1864 * (This is because cfdisk considers expanded parts, from link to
1865 * end of partition, and these may still overlap.)
1867 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1871 fix_chain_of_logicals(void)
1873 int j, oj, ojj, sj, sjj;
1874 struct partition *pj,*pjj,tmp;
1876 /* Stage 1: sort sectors but leave sector of part 4 */
1877 /* (Its sector is the global extended_offset.) */
1879 for (j = 5; j < partitions-1; j++) {
1880 oj = ptes[j].offset;
1881 ojj = ptes[j+1].offset;
1883 ptes[j].offset = ojj;
1884 ptes[j+1].offset = oj;
1885 pj = ptes[j].part_table;
1886 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1887 pjj = ptes[j+1].part_table;
1888 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1889 set_start_sect(ptes[j-1].ext_pointer,
1890 ojj-extended_offset);
1891 set_start_sect(ptes[j].ext_pointer,
1892 oj-extended_offset);
1897 /* Stage 2: sort starting sectors */
1899 for (j = 4; j < partitions-1; j++) {
1900 pj = ptes[j].part_table;
1901 pjj = ptes[j+1].part_table;
1902 sj = get_start_sect(pj);
1903 sjj = get_start_sect(pjj);
1904 oj = ptes[j].offset;
1905 ojj = ptes[j+1].offset;
1906 if (oj+sj > ojj+sjj) {
1910 set_start_sect(pj, ojj+sjj-oj);
1911 set_start_sect(pjj, oj+sj-ojj);
1916 /* Probably something was changed */
1917 for (j = 4; j < partitions; j++)
1918 ptes[j].changed = 1;
1923 fix_partition_table_order(void)
1925 struct pte *pei, *pek;
1928 if (!wrong_p_order(NULL)) {
1929 printf("Ordering is already correct\n\n");
1933 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1934 /* partition i should have come earlier, move it */
1935 /* We have to move data in the MBR */
1936 struct partition *pi, *pk, *pe, pbuf;
1940 pe = pei->ext_pointer;
1941 pei->ext_pointer = pek->ext_pointer;
1942 pek->ext_pointer = pe;
1944 pi = pei->part_table;
1945 pk = pek->part_table;
1947 memmove(&pbuf, pi, sizeof(struct partition));
1948 memmove(pi, pk, sizeof(struct partition));
1949 memmove(pk, &pbuf, sizeof(struct partition));
1951 pei->changed = pek->changed = 1;
1955 fix_chain_of_logicals();
1963 list_table(int xtra)
1965 const struct partition *p;
1969 sun_list_table(xtra);
1973 sgi_list_table(xtra);
1977 list_disk_geometry();
1980 xbsd_print_disklabel(xtra);
1984 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1985 but if the device name ends in a digit, say /dev/foo1,
1986 then the partition is called /dev/foo1p3. */
1987 w = strlen(disk_device);
1988 if (w && isdigit(disk_device[w-1]))
1993 // 1 12345678901 12345678901 12345678901 12
1994 printf("%*s Boot Start End Blocks Id System\n",
1997 for (i = 0; i < partitions; i++) {
1998 const struct pte *pe = &ptes[i];
2004 if (!p || is_cleared_partition(p))
2007 psects = get_nr_sects(p);
2011 if (sector_size < 1024) {
2012 pblocks /= (1024 / sector_size);
2013 podd = psects % (1024 / sector_size);
2015 if (sector_size > 1024)
2016 pblocks *= (sector_size / 1024);
2018 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2019 partname(disk_device, i+1, w+2),
2020 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2022 (ullong) cround(get_partition_start(pe)), /* start */
2023 (ullong) cround(get_partition_start(pe) + psects /* end */
2024 - (psects ? 1 : 0)),
2025 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
2026 p->sys_ind, /* type id */
2027 partition_type(p->sys_ind)); /* type name */
2029 check_consistency(p, i);
2032 /* Is partition table in disk order? It need not be, but... */
2033 /* partition table entries are not checked for correct order if this
2034 is a sgi, sun or aix labeled disk... */
2035 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2037 printf("\nPartition table entries are not in disk order\n");
2041 #if ENABLE_FEATURE_FDISK_ADVANCED
2043 x_list_table(int extend)
2045 const struct pte *pe;
2046 const struct partition *p;
2049 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2050 disk_device, heads, sectors, cylinders);
2051 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2052 for (i = 0; i < partitions; i++) {
2054 p = (extend ? pe->ext_pointer : pe->part_table);
2056 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2057 i + 1, p->boot_ind, p->head,
2059 cylinder(p->sector, p->cyl), p->end_head,
2060 sector(p->end_sector),
2061 cylinder(p->end_sector, p->end_cyl),
2062 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2064 check_consistency(p, i);
2070 #if ENABLE_FEATURE_FDISK_WRITABLE
2072 fill_bounds(ullong *first, ullong *last)
2075 const struct pte *pe = &ptes[0];
2076 const struct partition *p;
2078 for (i = 0; i < partitions; pe++,i++) {
2080 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2081 first[i] = 0xffffffff;
2084 first[i] = get_partition_start(pe);
2085 last[i] = first[i] + get_nr_sects(p) - 1;
2091 check(int n, unsigned h, unsigned s, unsigned c, ullong start)
2093 ullong total, real_s, real_c;
2095 real_s = sector(s) - 1;
2096 real_c = cylinder(s, c);
2097 total = (real_c * sectors + real_s) * heads + h;
2099 printf("Partition %d contains sector 0\n", n);
2101 printf("Partition %d: head %d greater than maximum %d\n",
2103 if (real_s >= sectors)
2104 printf("Partition %d: sector %d greater than "
2105 "maximum %d\n", n, s, sectors);
2106 if (real_c >= cylinders)
2107 printf("Partition %d: cylinder %llu greater than "
2108 "maximum %d\n", n, real_c + 1, cylinders);
2109 if (cylinders <= 1024 && start != total)
2110 printf("Partition %d: previous sectors %llu disagrees with "
2111 "total %llu\n", n, start, total);
2119 ullong first[partitions], last[partitions];
2120 struct partition *p;
2122 if (warn_geometry())
2134 fill_bounds(first, last);
2135 for (i = 0; i < partitions; i++) {
2136 struct pte *pe = &ptes[i];
2139 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2140 check_consistency(p, i);
2141 if (get_partition_start(pe) < first[i])
2142 printf("Warning: bad start-of-data in "
2143 "partition %d\n", i + 1);
2144 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2146 total += last[i] + 1 - first[i];
2147 for (j = 0; j < i; j++) {
2148 if ((first[i] >= first[j] && first[i] <= last[j])
2149 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2150 printf("Warning: partition %d overlaps "
2151 "partition %d\n", j + 1, i + 1);
2152 total += first[i] >= first[j] ?
2153 first[i] : first[j];
2154 total -= last[i] <= last[j] ?
2161 if (extended_offset) {
2162 struct pte *pex = &ptes[ext_index];
2163 ullong e_last = get_start_sect(pex->part_table) +
2164 get_nr_sects(pex->part_table) - 1;
2166 for (i = 4; i < partitions; i++) {
2168 p = ptes[i].part_table;
2170 if (i != 4 || i + 1 < partitions)
2171 printf("Warning: partition %d "
2172 "is empty\n", i + 1);
2173 } else if (first[i] < extended_offset || last[i] > e_last) {
2174 printf("Logical partition %d not entirely in "
2175 "partition %d\n", i + 1, ext_index + 1);
2180 if (total > heads * sectors * cylinders)
2181 printf("Total allocated sectors %d greater than the maximum "
2182 "%d\n", total, heads * sectors * cylinders);
2184 total = heads * sectors * cylinders - total;
2186 printf("%d unallocated sectors\n", total);
2191 add_partition(int n, int sys)
2193 char mesg[256]; /* 48 does not suffice in Japanese */
2194 int i, num_read = 0;
2195 struct partition *p = ptes[n].part_table;
2196 struct partition *q = ptes[ext_index].part_table;
2198 ullong start, stop = 0;
2199 ullong first[partitions], last[partitions];
2201 if (p && p->sys_ind) {
2202 printf(msg_part_already_defined, n + 1);
2205 fill_bounds(first, last);
2207 start = sector_offset;
2208 if (display_in_cyl_units || !total_number_of_sectors)
2209 limit = (ullong) heads * sectors * cylinders - 1;
2211 limit = total_number_of_sectors - 1;
2212 if (extended_offset) {
2213 first[ext_index] = extended_offset;
2214 last[ext_index] = get_start_sect(q) +
2215 get_nr_sects(q) - 1;
2218 start = extended_offset + sector_offset;
2219 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2221 if (display_in_cyl_units)
2222 for (i = 0; i < partitions; i++)
2223 first[i] = (cround(first[i]) - 1) * units_per_sector;
2225 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2228 for (i = 0; i < partitions; i++) {
2231 if (start == ptes[i].offset)
2232 start += sector_offset;
2233 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2234 if (start >= first[i] && start <= lastplusoff)
2235 start = lastplusoff + 1;
2239 if (start >= temp+units_per_sector && num_read) {
2240 printf("Sector %lld is already allocated\n", temp);
2244 if (!num_read && start == temp) {
2247 saved_start = start;
2248 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2250 if (display_in_cyl_units) {
2251 start = (start - 1) * units_per_sector;
2252 if (start < saved_start) start = saved_start;
2256 } while (start != temp || !num_read);
2257 if (n > 4) { /* NOT for fifth partition */
2258 struct pte *pe = &ptes[n];
2260 pe->offset = start - sector_offset;
2261 if (pe->offset == extended_offset) { /* must be corrected */
2263 if (sector_offset == 1)
2268 for (i = 0; i < partitions; i++) {
2269 struct pte *pe = &ptes[i];
2271 if (start < pe->offset && limit >= pe->offset)
2272 limit = pe->offset - 1;
2273 if (start < first[i] && limit >= first[i])
2274 limit = first[i] - 1;
2276 if (start > limit) {
2277 printf("No free sectors available\n");
2282 if (cround(start) == cround(limit)) {
2285 snprintf(mesg, sizeof(mesg),
2286 "Last %s or +size or +sizeM or +sizeK",
2287 str_units(SINGULAR));
2288 stop = read_int(cround(start), cround(limit), cround(limit),
2289 cround(start), mesg);
2290 if (display_in_cyl_units) {
2291 stop = stop * units_per_sector - 1;
2297 set_partition(n, 0, start, stop, sys);
2299 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2301 if (IS_EXTENDED(sys)) {
2302 struct pte *pe4 = &ptes[4];
2303 struct pte *pen = &ptes[n];
2306 pen->ext_pointer = p;
2307 pe4->offset = extended_offset = start;
2308 pe4->sectorbuffer = xzalloc(sector_size);
2309 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2310 pe4->ext_pointer = pe4->part_table + 1;
2319 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2320 struct pte *pe = &ptes[partitions];
2322 pe->sectorbuffer = xzalloc(sector_size);
2323 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2324 pe->ext_pointer = pe->part_table + 1;
2329 add_partition(partitions - 1, LINUX_NATIVE);
2335 int i, free_primary = 0;
2337 if (warn_geometry())
2341 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2345 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2349 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2350 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2351 "table first (use 'o'). This will destroy the present disk contents.\n");
2355 for (i = 0; i < 4; i++)
2356 free_primary += !ptes[i].part_table->sys_ind;
2358 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2359 printf("The maximum number of partitions has been created\n");
2363 if (!free_primary) {
2364 if (extended_offset)
2367 printf("You must delete some partition and add "
2368 "an extended partition first\n");
2371 snprintf(line, sizeof(line),
2374 " p primary partition (1-4)\n",
2376 "l logical (5 or over)" : "e extended"));
2378 c = read_nonempty(line);
2379 if (c == 'p' || c == 'P') {
2380 i = get_nonexisting_partition(0, 4);
2382 add_partition(i, LINUX_NATIVE);
2385 if (c == 'l' && extended_offset) {
2389 if (c == 'e' && !extended_offset) {
2390 i = get_nonexisting_partition(0, 4);
2392 add_partition(i, EXTENDED);
2395 printf("Invalid partition number "
2396 "for type '%c'\n", c);
2407 for (i = 0; i < 3; i++)
2408 if (ptes[i].changed)
2409 ptes[3].changed = 1;
2410 for (i = 3; i < partitions; i++) {
2411 struct pte *pe = &ptes[i];
2414 write_part_table_flag(pe->sectorbuffer);
2415 write_sector(pe->offset, pe->sectorbuffer);
2419 else if (LABEL_IS_SGI) {
2420 /* no test on change? the printf below might be mistaken */
2423 else if (LABEL_IS_SUN) {
2426 for (i = 0; i < 8; i++)
2427 if (ptes[i].changed)
2433 printf("The partition table has been altered!\n\n");
2434 reread_partition_table(1);
2438 reread_partition_table(int leave)
2442 printf("Calling ioctl() to re-read partition table\n");
2444 /* sleep(2); Huh? */
2445 i = ioctl_or_perror(fd, BLKRRPART, NULL,
2446 "WARNING: rereading partition table "
2447 "failed, kernel still uses old table");
2451 "\nWARNING: If you have created or modified any DOS 6.x\n"
2452 "partitions, please see the fdisk manual page for additional\n"
2457 if (ENABLE_FEATURE_CLEAN_UP)
2462 #endif /* FEATURE_FDISK_WRITABLE */
2464 #if ENABLE_FEATURE_FDISK_ADVANCED
2465 #define MAX_PER_LINE 16
2467 print_buffer(char *pbuffer)
2471 for (i = 0, l = 0; i < sector_size; i++, l++) {
2473 printf("0x%03X:", i);
2474 printf(" %02X", (unsigned char) pbuffer[i]);
2475 if (l == MAX_PER_LINE - 1) {
2490 printf("Device: %s\n", disk_device);
2491 if (LABEL_IS_SGI || LABEL_IS_SUN)
2492 print_buffer(MBRbuffer);
2494 for (i = 3; i < partitions; i++)
2495 print_buffer(ptes[i].sectorbuffer);
2502 struct pte *pe = &ptes[i];
2503 struct partition *p = pe->part_table;
2506 if (warn_geometry())
2508 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2509 printf("Partition %d has no data area\n", i + 1);
2512 first = get_partition_start(pe);
2513 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2514 "New beginning of data") - pe->offset;
2516 if (new != get_nr_sects(p)) {
2517 first = get_nr_sects(p) + get_start_sect(p) - new;
2518 set_nr_sects(p, first);
2519 set_start_sect(p, new);
2531 c = tolower(read_nonempty("Expert command (m for help): "));
2539 move_begin(get_partition(0, partitions));
2542 user_cylinders = cylinders =
2543 read_int(1, cylinders, 1048576, 0,
2544 "Number of cylinders");
2546 sun_set_ncyl(cylinders);
2556 else if (LABEL_IS_SUN)
2558 else if (LABEL_IS_DOS)
2563 fix_partition_table_order();
2566 #if ENABLE_FEATURE_SGI_LABEL
2571 user_heads = heads = read_int(1, heads, 256, 0,
2596 user_sectors = sectors = read_int(1, sectors, 63, 0,
2597 "Number of sectors");
2598 if (dos_compatible_flag) {
2599 sector_offset = sectors;
2600 printf("Warning: setting sector offset for DOS "
2609 write_table(); /* does not return */
2613 sun_set_pcylcount();
2620 #endif /* ADVANCED mode */
2623 is_ide_cdrom_or_tape(const char *device)
2627 struct stat statbuf;
2630 /* No device was given explicitly, and we are trying some
2631 likely things. But opening /dev/hdc may produce errors like
2632 "hdc: tray open or drive not ready"
2633 if it happens to be a CD-ROM drive. It even happens that
2634 the process hangs on the attempt to read a music CD.
2635 So try to be careful. This only works since 2.1.73. */
2637 if (strncmp("/dev/hd", device, 7))
2640 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2641 procf = fopen(buf, "r");
2642 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2643 is_ide = (!strncmp(buf, "cdrom", 5) ||
2644 !strncmp(buf, "tape", 4));
2646 /* Now when this proc file does not exist, skip the
2647 device when it is read-only. */
2648 if (stat(device, &statbuf) == 0)
2649 is_ide = ((statbuf.st_mode & 0222) == 0);
2658 trydev(const char *device, int user_specified)
2662 disk_device = device;
2663 if (setjmp(listingbuf))
2665 if (!user_specified)
2666 if (is_ide_cdrom_or_tape(device))
2668 fd = open(disk_device, type_open);
2670 gb = get_boot(try_only);
2671 if (gb > 0) { /* I/O error */
2673 } else if (gb < 0) { /* no DOS signature */
2674 list_disk_geometry();
2678 #if ENABLE_FEATURE_OSF_LABEL
2679 if (bsd_trydev(device) < 0)
2681 printf("Disk %s doesn't contain a valid "
2682 "partition table\n", device);
2687 #if ENABLE_FEATURE_FDISK_WRITABLE
2688 if (!LABEL_IS_SUN && partitions > 4){
2689 delete_partition(ext_index);
2694 /* Ignore other errors, since we try IDE
2695 and SCSI hard disks which may not be
2696 installed on the system. */
2697 if (errno == EACCES) {
2698 printf("Cannot open %s\n", device);
2704 /* for fdisk -l: try all things in /proc/partitions
2705 that look like a partition name (do not end in a digit) */
2710 char line[100], ptname[100], devname[120], *s;
2713 procpt = fopen_or_warn("/proc/partitions", "r");
2715 while (fgets(line, sizeof(line), procpt)) {
2716 if (sscanf(line, " %d %d %d %[^\n ]",
2717 &ma, &mi, &sz, ptname) != 4)
2719 for (s = ptname; *s; s++);
2722 sprintf(devname, "/dev/%s", ptname);
2725 #if ENABLE_FEATURE_CLEAN_UP
2730 #if ENABLE_FEATURE_FDISK_WRITABLE
2732 unknown_command(int c)
2734 printf("%c: unknown command\n", c);
2738 int fdisk_main(int argc, char **argv);
2739 int fdisk_main(int argc, char **argv)
2741 char *str_b, *str_C, *str_H, *str_S;
2745 * fdisk -l [-b sectorsize] [-u] device ...
2746 * fdisk -s [partition] ...
2747 * fdisk [-b sectorsize] [-u] device
2749 * Options -C, -H, -S set the geometry.
2758 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2761 PTR_TO_GLOBALS = xzalloc(sizeof(G));
2763 opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2764 &str_b, &str_C, &str_H, &str_S);
2767 if (opt & OPT_b) { // -b
2768 /* Ugly: this sector size is really per device,
2769 so cannot be combined with multiple disks,
2770 and the same goes for the C/H/S options.
2772 sector_size = xatoi_u(str_b);
2773 if (sector_size != 512 && sector_size != 1024 &&
2774 sector_size != 2048)
2777 user_set_sector_size = 1;
2779 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2780 if (opt & OPT_H) { // -H
2781 user_heads = xatoi_u(str_H);
2782 if (user_heads <= 0 || user_heads >= 256)
2785 //if (opt & OPT_l) // -l
2786 if (opt & OPT_S) { // -S
2787 user_sectors = xatoi_u(str_S);
2788 if (user_sectors <= 0 || user_sectors >= 64)
2791 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2792 //if (opt & OPT_s) // -s
2794 if (user_set_sector_size && argc != 1)
2795 printf("Warning: the -b (set sector size) option should"
2796 " be used with one specified device\n");
2798 #if ENABLE_FEATURE_FDISK_WRITABLE
2802 type_open = O_RDONLY;
2805 #if defined(__GNUC__)
2806 /* avoid gcc warning:
2807 variable `k' might be clobbered by `longjmp' */
2811 for (k = 0; k < argc; k++)
2814 /* we no longer have default device names */
2815 /* but, we can use /proc/partitions instead */
2819 #if ENABLE_FEATURE_FDISK_WRITABLE
2823 #if ENABLE_FEATURE_FDISK_BLKSIZE
2829 type_open = O_RDONLY;
2834 for (j = 0; j < argc; j++) {
2835 disk_device = argv[j];
2836 fd = open(disk_device, type_open);
2838 fdisk_fatal(unable_to_open);
2839 if (ioctl(fd, BLKGETSIZE, &size))
2840 fdisk_fatal(ioctl_error);
2843 printf("%ld\n", size/2);
2845 printf("%s: %ld\n", argv[j], size/2);
2851 #if ENABLE_FEATURE_FDISK_WRITABLE
2855 disk_device = argv[0];
2859 /* OSF label, and no DOS label */
2860 printf("Detected an OSF/1 disklabel on %s, entering "
2861 "disklabel mode\n", disk_device);
2863 /*Why do we do this? It seems to be counter-intuitive*/
2864 current_label_type = label_dos;
2865 /* If we return we may want to make an empty DOS label? */
2871 c = tolower(read_nonempty("Command (m for help): "));
2875 toggle_active(get_partition(1, partitions));
2876 else if (LABEL_IS_SUN)
2877 toggle_sunflags(get_partition(1, partitions),
2879 else if (LABEL_IS_SGI)
2880 sgi_set_bootpartition(
2881 get_partition(1, partitions));
2887 printf("\nThe current boot file is: %s\n",
2888 sgi_get_bootfile());
2889 if (read_maybe_empty("Please enter the name of the "
2890 "new boot file: ") == '\n')
2891 printf("Boot file unchanged\n");
2893 sgi_set_bootfile(line_ptr);
2895 #if ENABLE_FEATURE_OSF_LABEL
2902 toggle_dos_compatibility_flag();
2903 else if (LABEL_IS_SUN)
2904 toggle_sunflags(get_partition(1, partitions),
2906 else if (LABEL_IS_SGI)
2907 sgi_set_swappartition(
2908 get_partition(1, partitions));
2915 /* If sgi_label then don't use get_existing_partition,
2916 let the user select a partition, since
2917 get_existing_partition() only works for Linux-like
2919 if (!LABEL_IS_SGI) {
2920 j = get_existing_partition(1, partitions);
2922 j = get_partition(1, partitions);
2925 delete_partition(j);
2934 list_types(get_sys_types());
2953 #if ENABLE_FEATURE_SUN_LABEL
2967 write_table(); /* does not return */
2969 #if ENABLE_FEATURE_FDISK_ADVANCED
2972 printf("\n\tSorry, no experts menu for SGI "
2973 "partition tables available\n\n");
2984 #endif /* FEATURE_FDISK_WRITABLE */