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 #include <assert.h> /* assert */
13 /* Looks like someone forgot to add this to config system */
14 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
15 # define ENABLE_FEATURE_FDISK_BLKSIZE 0
16 # define USE_FEATURE_FDISK_BLKSIZE(a)
19 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
21 #define DEFAULT_SECTOR_SIZE 512
22 #define MAX_SECTOR_SIZE 2048
23 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
24 #define MAXIMUM_PARTS 60
26 #define ACTIVE_FLAG 0x80
29 #define WIN98_EXTENDED 0x0f
30 #define LINUX_PARTITION 0x81
31 #define LINUX_SWAP 0x82
32 #define LINUX_NATIVE 0x83
33 #define LINUX_EXTENDED 0x85
34 #define LINUX_LVM 0x8e
35 #define LINUX_RAID 0xfd
39 unsigned char sectors;
40 unsigned short cylinders;
44 #define HDIO_GETGEO 0x0301 /* get device geometry */
46 static const char msg_building_new_label[] =
47 "Building a new %s. Changes will remain in memory only,\n"
48 "until you decide to write them. After that the previous content\n"
49 "won't be recoverable.\n\n";
51 static const char msg_part_already_defined[] =
52 "Partition %d is already defined, delete it before re-adding\n";
55 static unsigned sector_size = DEFAULT_SECTOR_SIZE;
56 static unsigned user_set_sector_size;
57 static unsigned sector_offset = 1;
59 #if ENABLE_FEATURE_OSF_LABEL
60 static int possibly_osf_label;
63 static unsigned heads, sectors, cylinders;
64 static void update_units(void);
68 unsigned char boot_ind; /* 0x80 - active */
69 unsigned char head; /* starting head */
70 unsigned char sector; /* starting sector */
71 unsigned char cyl; /* starting cylinder */
72 unsigned char sys_ind; /* What partition type */
73 unsigned char end_head; /* end head */
74 unsigned char end_sector; /* end sector */
75 unsigned char end_cyl; /* end cylinder */
76 unsigned char start4[4]; /* starting sector counting from 0 */
77 unsigned char size4[4]; /* nr of sectors in partition */
81 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
86 label_dos, label_sun, label_sgi, label_aix, label_osf
89 #define LABEL_IS_DOS (label_dos == current_label_type)
91 #if ENABLE_FEATURE_SUN_LABEL
92 #define LABEL_IS_SUN (label_sun == current_label_type)
93 #define STATIC_SUN static
95 #define LABEL_IS_SUN 0
96 #define STATIC_SUN extern
99 #if ENABLE_FEATURE_SGI_LABEL
100 #define LABEL_IS_SGI (label_sgi == current_label_type)
101 #define STATIC_SGI static
103 #define LABEL_IS_SGI 0
104 #define STATIC_SGI extern
107 #if ENABLE_FEATURE_AIX_LABEL
108 #define LABEL_IS_AIX (label_aix == current_label_type)
109 #define STATIC_AIX static
111 #define LABEL_IS_AIX 0
112 #define STATIC_AIX extern
115 #if ENABLE_FEATURE_OSF_LABEL
116 #define LABEL_IS_OSF (label_osf == current_label_type)
117 #define STATIC_OSF static
119 #define LABEL_IS_OSF 0
120 #define STATIC_OSF extern
123 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
125 static enum label_type current_label_type;
127 static const char *disk_device;
128 static int fd; /* the disk */
129 static int partitions = 4; /* maximum partition + 1 */
130 static int display_in_cyl_units = 1;
131 static unsigned units_per_sector = 1;
132 #if ENABLE_FEATURE_FDISK_WRITABLE
133 static void change_units(void);
134 static void reread_partition_table(int leave);
135 static void delete_partition(int i);
136 static int get_partition(int warn, int max);
137 static void list_types(const char *const *sys);
138 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
140 static const char *partition_type(unsigned char type);
141 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
142 static void get_geometry(void);
143 static int get_boot(enum action what);
148 static unsigned get_start_sect(const struct partition *p);
149 static unsigned get_nr_sects(const struct partition *p);
152 * per partition table entry data
154 * The four primary partitions have the same sectorbuffer (MBRbuffer)
155 * and have NULL ext_pointer.
156 * Each logical partition table entry has two pointers, one for the
157 * partition and one link to the next one.
160 struct partition *part_table; /* points into sectorbuffer */
161 struct partition *ext_pointer; /* points into sectorbuffer */
162 off_t offset; /* disk sector number */
163 char *sectorbuffer; /* disk sector contents */
164 #if ENABLE_FEATURE_FDISK_WRITABLE
165 char changed; /* boolean */
169 /* DOS partition types */
171 static const char *const i386_sys_types[] = {
175 "\x05" "Extended", /* DOS 3.3+ extended partition */
176 "\x06" "FAT16", /* DOS 16-bit >=32M */
177 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
178 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
179 "\x0b" "Win95 FAT32",
180 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
181 "\x0e" "Win95 FAT16 (LBA)",
182 "\x0f" "Win95 Ext'd (LBA)",
183 "\x11" "Hidden FAT12",
184 "\x12" "Compaq diagnostics",
185 "\x14" "Hidden FAT16 <32M",
186 "\x16" "Hidden FAT16",
187 "\x17" "Hidden HPFS/NTFS",
188 "\x1b" "Hidden Win95 FAT32",
189 "\x1c" "Hidden W95 FAT32 (LBA)",
190 "\x1e" "Hidden W95 FAT16 (LBA)",
191 "\x3c" "Part.Magic recovery",
192 "\x41" "PPC PReP Boot",
194 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
195 "\x80" "Old Minix", /* Minix 1.4a and earlier */
196 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
197 "\x82" "Linux swap", /* also Solaris */
199 "\x84" "OS/2 hidden C: drive",
200 "\x85" "Linux extended",
201 "\x86" "NTFS volume set",
202 "\x87" "NTFS volume set",
204 "\x9f" "BSD/OS", /* BSDI */
205 "\xa0" "Thinkpad hibernation",
206 "\xa5" "FreeBSD", /* various BSD flavours */
210 "\xab" "Darwin boot",
213 "\xbe" "Solaris boot",
215 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
216 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
217 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
218 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
219 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
220 autodetect using persistent
222 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
225 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
226 "\x09" "AIX bootable", /* AIX data or Coherent */
228 "\x18" "AST SmartSleep",
231 "\x40" "Venix 80286",
233 "\x4e" "QNX4.x 2nd part",
234 "\x4f" "QNX4.x 3rd part",
236 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
237 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
238 "\x53" "OnTrack DM6 Aux3",
242 "\x5c" "Priam Edisk",
244 "\x64" "Novell Netware 286",
245 "\x65" "Novell Netware 386",
246 "\x70" "DiskSecure Multi-Boot",
249 "\x94" "Amoeba BBT", /* (bad block table) */
251 "\xbb" "Boot Wizard hidden",
252 "\xc1" "DRDOS/sec (FAT-12)",
253 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
254 "\xc6" "DRDOS/sec (FAT-16)",
256 "\xda" "Non-FS data",
257 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
258 Concurrent DOS or CTOS */
259 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
260 "\xdf" "BootIt", /* BootIt EMBRM */
261 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
262 extended partition */
263 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
264 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
265 partition < 1024 cyl. */
267 "\xf4" "SpeedStor", /* SpeedStor large partition */
268 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
269 "\xff" "BBT", /* Xenix Bad Block Table */
279 char line_buffer[80];
280 char partname_buffer[80];
282 /* Raw disk label. For DOS-type partition tables the MBR,
283 * with descriptions of the primary partitions. */
284 char MBRbuffer[MAX_SECTOR_SIZE];
285 /* Partition tables */
286 struct pte ptes[MAXIMUM_PARTS];
288 /* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
289 #define G (*ptr_to_globals)
291 #define line_ptr (G.line_ptr)
292 #define listingbuf (G.listingbuf)
293 #define line_buffer (G.line_buffer)
294 #define partname_buffer (G.partname_buffer)
295 #define MBRbuffer (G.MBRbuffer)
296 #define ptes (G.ptes)
301 #define IS_EXTENDED(i) \
302 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
304 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
306 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
308 #define pt_offset(b, n) \
309 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
311 #define sector(s) ((s) & 0x3f)
313 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
315 #define hsc2sector(h,s,c) \
316 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
318 #define set_hsc(h,s,c,sector) \
320 s = sector % sectors + 1; \
322 h = sector % heads; \
325 s |= (sector >> 2) & 0xc0; \
328 #if ENABLE_FEATURE_FDISK_WRITABLE
329 /* read line; return 0 or first printable char */
331 read_line(const char *prompt)
335 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
337 exit(0); /* Ctrl-D or Ctrl-C */
339 if (line_buffer[sz-1] == '\n')
340 line_buffer[--sz] = '\0';
342 line_ptr = line_buffer;
343 while (*line_ptr && !isgraph(*line_ptr))
350 * return partition name - uses static storage
353 partname(const char *dev, int pno, int lth)
360 bufp = partname_buffer;
361 bufsiz = sizeof(partname_buffer);
366 if (isdigit(dev[w-1]))
369 /* devfs kludge - note: fdisk partition names are not supposed
370 to equal kernel names, so there is no reason to do this */
371 if (strcmp(dev + w - 4, "disc") == 0) {
379 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
380 lth-wp-2, w, dev, p, pno);
382 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
387 #if ENABLE_FEATURE_FDISK_WRITABLE
389 set_all_unchanged(void)
393 for (i = 0; i < MAXIMUM_PARTS; i++)
397 static ATTRIBUTE_ALWAYS_INLINE void
402 #endif /* FEATURE_FDISK_WRITABLE */
404 static ATTRIBUTE_ALWAYS_INLINE struct partition *
405 get_part_table(int i)
407 return ptes[i].part_table;
412 { /* n==1: use singular */
414 return display_in_cyl_units ? "cylinder" : "sector";
415 return display_in_cyl_units ? "cylinders" : "sectors";
419 valid_part_table_flag(const char *mbuffer)
421 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
424 #if ENABLE_FEATURE_FDISK_WRITABLE
425 static ATTRIBUTE_ALWAYS_INLINE void
426 write_part_table_flag(char *b)
433 read_nonempty(const char *mesg)
435 while (!read_line(mesg)) /* repeat */;
440 read_maybe_empty(const char *mesg)
442 if (!read_line(mesg)) {
443 line_ptr = line_buffer;
451 read_hex(const char *const *sys)
455 read_nonempty("Hex code (type L to list codes): ");
456 if (*line_ptr == 'l' || *line_ptr == 'L') {
460 v = bb_strtoul(line_ptr, NULL, 16);
462 /* Bad input also triggers this */
467 #endif /* FEATURE_FDISK_WRITABLE */
469 #include "fdisk_aix.c"
472 unsigned char info[128]; /* Informative text string */
473 unsigned char spare0[14];
475 unsigned char spare1;
477 unsigned char spare2;
480 unsigned char spare1[246]; /* Boot information etc. */
481 unsigned short rspeed; /* Disk rotational speed */
482 unsigned short pcylcount; /* Physical cylinder count */
483 unsigned short sparecyl; /* extra sects per cylinder */
484 unsigned char spare2[4]; /* More magic... */
485 unsigned short ilfact; /* Interleave factor */
486 unsigned short ncyl; /* Data cylinder count */
487 unsigned short nacyl; /* Alt. cylinder count */
488 unsigned short ntrks; /* Tracks per cylinder */
489 unsigned short nsect; /* Sectors per track */
490 unsigned char spare3[4]; /* Even more magic... */
491 struct sun_partinfo {
492 uint32_t start_cylinder;
493 uint32_t num_sectors;
495 unsigned short magic; /* Magic number */
496 unsigned short csum; /* Label xor'd checksum */
498 #define sunlabel ((sun_partition *)MBRbuffer)
499 STATIC_OSF void bsd_select(void);
500 STATIC_OSF void xbsd_print_disklabel(int);
501 #include "fdisk_osf.c"
503 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
505 fdisk_swap16(uint16_t x)
507 return (x << 8) | (x >> 8);
511 fdisk_swap32(uint32_t x)
514 ((x & 0xFF00) << 8) |
515 ((x & 0xFF0000) >> 8) |
520 STATIC_SGI const char *const sgi_sys_types[];
521 STATIC_SGI unsigned sgi_get_num_sectors(int i);
522 STATIC_SGI int sgi_get_sysid(int i);
523 STATIC_SGI void sgi_delete_partition(int i);
524 STATIC_SGI void sgi_change_sysid(int i, int sys);
525 STATIC_SGI void sgi_list_table(int xtra);
526 #if ENABLE_FEATURE_FDISK_ADVANCED
527 STATIC_SGI void sgi_set_xcyl(void);
529 STATIC_SGI int verify_sgi(int verbose);
530 STATIC_SGI void sgi_add_partition(int n, int sys);
531 STATIC_SGI void sgi_set_swappartition(int i);
532 STATIC_SGI const char *sgi_get_bootfile(void);
533 STATIC_SGI void sgi_set_bootfile(const char* aFile);
534 STATIC_SGI void create_sgiinfo(void);
535 STATIC_SGI void sgi_write_table(void);
536 STATIC_SGI void sgi_set_bootpartition(int i);
537 #include "fdisk_sgi.c"
539 STATIC_SUN const char *const sun_sys_types[];
540 STATIC_SUN void sun_delete_partition(int i);
541 STATIC_SUN void sun_change_sysid(int i, int sys);
542 STATIC_SUN void sun_list_table(int xtra);
543 STATIC_SUN void add_sun_partition(int n, int sys);
544 #if ENABLE_FEATURE_FDISK_ADVANCED
545 STATIC_SUN void sun_set_alt_cyl(void);
546 STATIC_SUN void sun_set_ncyl(int cyl);
547 STATIC_SUN void sun_set_xcyl(void);
548 STATIC_SUN void sun_set_ilfact(void);
549 STATIC_SUN void sun_set_rspeed(void);
550 STATIC_SUN void sun_set_pcylcount(void);
552 STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
553 STATIC_SUN void verify_sun(void);
554 STATIC_SUN void sun_write_table(void);
555 #include "fdisk_sun.c"
557 #if ENABLE_FEATURE_FDISK_WRITABLE
558 /* start_sect and nr_sects are stored little endian on all machines */
559 /* moreover, they are not aligned correctly */
561 store4_little_endian(unsigned char *cp, unsigned val)
568 #endif /* FEATURE_FDISK_WRITABLE */
571 read4_little_endian(const unsigned char *cp)
573 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
576 #if ENABLE_FEATURE_FDISK_WRITABLE
578 set_start_sect(struct partition *p, unsigned start_sect)
580 store4_little_endian(p->start4, start_sect);
585 get_start_sect(const struct partition *p)
587 return read4_little_endian(p->start4);
590 #if ENABLE_FEATURE_FDISK_WRITABLE
592 set_nr_sects(struct partition *p, unsigned nr_sects)
594 store4_little_endian(p->size4, nr_sects);
599 get_nr_sects(const struct partition *p)
601 return read4_little_endian(p->size4);
604 /* normally O_RDWR, -l option gives O_RDONLY */
605 static int type_open = O_RDWR;
608 static int ext_index; /* the prime extended partition */
609 static int listing; /* no aborts for fdisk -l */
610 static int dos_compatible_flag = ~0;
611 #if ENABLE_FEATURE_FDISK_WRITABLE
612 static int dos_changed;
613 static int nowarn; /* no warnings for fdisk -l/-s */
618 static unsigned user_cylinders, user_heads, user_sectors;
619 static unsigned pt_heads, pt_sectors;
620 static unsigned kern_heads, kern_sectors;
622 static off_t extended_offset; /* offset of link pointers */
624 static unsigned long long total_number_of_sectors;
627 static void fdisk_fatal(enum failure why)
633 longjmp(listingbuf, 1);
638 message = "cannot open %s";
641 message = "cannot read from %s";
644 message = "cannot seek on %s";
646 case unable_to_write:
647 message = "cannot write to %s";
650 message = "BLKGETSIZE ioctl failed on %s";
653 message = "fatal error";
656 bb_error_msg_and_die(message, disk_device);
660 seek_sector(off_t secno)
662 off_t offset = secno * sector_size;
663 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
664 fdisk_fatal(unable_to_seek);
667 #if ENABLE_FEATURE_FDISK_WRITABLE
669 write_sector(off_t secno, char *buf)
672 if (write(fd, buf, sector_size) != sector_size)
673 fdisk_fatal(unable_to_write);
677 /* Allocate a buffer and read a partition table sector */
679 read_pte(struct pte *pe, off_t offset)
682 pe->sectorbuffer = xmalloc(sector_size);
684 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
685 fdisk_fatal(unable_to_read);
686 #if ENABLE_FEATURE_FDISK_WRITABLE
689 pe->part_table = pe->ext_pointer = NULL;
693 get_partition_start(const struct pte *pe)
695 return pe->offset + get_start_sect(pe->part_table);
698 #if ENABLE_FEATURE_FDISK_WRITABLE
700 * Avoid warning about DOS partitions when no DOS partition was changed.
701 * Here a heuristic "is probably dos partition".
702 * We might also do the opposite and warn in all cases except
703 * for "is probably nondos partition".
706 is_dos_partition(int t)
708 return (t == 1 || t == 4 || t == 6 ||
709 t == 0x0b || t == 0x0c || t == 0x0e ||
710 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
711 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
712 t == 0xc1 || t == 0xc4 || t == 0xc6);
718 puts("Command Action");
720 puts("a\ttoggle a read only flag"); /* sun */
721 puts("b\tedit bsd disklabel");
722 puts("c\ttoggle the mountable flag"); /* sun */
723 puts("d\tdelete a partition");
724 puts("l\tlist known partition types");
725 puts("n\tadd a new partition");
726 puts("o\tcreate a new empty DOS partition table");
727 puts("p\tprint the partition table");
728 puts("q\tquit without saving changes");
729 puts("s\tcreate a new empty Sun disklabel"); /* sun */
730 puts("t\tchange a partition's system id");
731 puts("u\tchange display/entry units");
732 puts("v\tverify the partition table");
733 puts("w\twrite table to disk and exit");
734 #if ENABLE_FEATURE_FDISK_ADVANCED
735 puts("x\textra functionality (experts only)");
737 } else if (LABEL_IS_SGI) {
738 puts("a\tselect bootable partition"); /* sgi flavour */
739 puts("b\tedit bootfile entry"); /* sgi */
740 puts("c\tselect sgi swap partition"); /* sgi flavour */
741 puts("d\tdelete a partition");
742 puts("l\tlist known partition types");
743 puts("n\tadd a new partition");
744 puts("o\tcreate a new empty DOS partition table");
745 puts("p\tprint the partition table");
746 puts("q\tquit without saving changes");
747 puts("s\tcreate a new empty Sun disklabel"); /* sun */
748 puts("t\tchange a partition's system id");
749 puts("u\tchange display/entry units");
750 puts("v\tverify the partition table");
751 puts("w\twrite table to disk and exit");
752 } else if (LABEL_IS_AIX) {
753 puts("o\tcreate a new empty DOS partition table");
754 puts("q\tquit without saving changes");
755 puts("s\tcreate a new empty Sun disklabel"); /* sun */
757 puts("a\ttoggle a bootable flag");
758 puts("b\tedit bsd disklabel");
759 puts("c\ttoggle the dos compatibility flag");
760 puts("d\tdelete a partition");
761 puts("l\tlist known partition types");
762 puts("n\tadd a new partition");
763 puts("o\tcreate a new empty DOS partition table");
764 puts("p\tprint the partition table");
765 puts("q\tquit without saving changes");
766 puts("s\tcreate a new empty Sun disklabel"); /* sun */
767 puts("t\tchange a partition's system id");
768 puts("u\tchange display/entry units");
769 puts("v\tverify the partition table");
770 puts("w\twrite table to disk and exit");
771 #if ENABLE_FEATURE_FDISK_ADVANCED
772 puts("x\textra functionality (experts only)");
776 #endif /* FEATURE_FDISK_WRITABLE */
779 #if ENABLE_FEATURE_FDISK_ADVANCED
783 puts("Command Action");
785 puts("a\tchange number of alternate cylinders"); /*sun*/
786 puts("c\tchange number of cylinders");
787 puts("d\tprint the raw data in the partition table");
788 puts("e\tchange number of extra sectors per cylinder");/*sun*/
789 puts("h\tchange number of heads");
790 puts("i\tchange interleave factor"); /*sun*/
791 puts("o\tchange rotation speed (rpm)"); /*sun*/
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 puts("y\tchange number of physical cylinders"); /*sun*/
799 } else if (LABEL_IS_SGI) {
800 puts("b\tmove beginning of data in a partition"); /* !sun */
801 puts("c\tchange number of cylinders");
802 puts("d\tprint the raw data in the partition table");
803 puts("e\tlist extended partitions"); /* !sun */
804 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
805 puts("h\tchange number of heads");
806 puts("p\tprint the partition table");
807 puts("q\tquit without saving changes");
808 puts("r\treturn to main menu");
809 puts("s\tchange number of sectors/track");
810 puts("v\tverify the partition table");
811 puts("w\twrite table to disk and exit");
812 } else if (LABEL_IS_AIX) {
813 puts("b\tmove beginning of data in a partition"); /* !sun */
814 puts("c\tchange number of cylinders");
815 puts("d\tprint the raw data in the partition table");
816 puts("e\tlist extended partitions"); /* !sun */
817 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
818 puts("h\tchange number of heads");
819 puts("p\tprint the partition table");
820 puts("q\tquit without saving changes");
821 puts("r\treturn to main menu");
822 puts("s\tchange number of sectors/track");
823 puts("v\tverify the partition table");
824 puts("w\twrite table to disk and exit");
826 puts("b\tmove beginning of data in a partition"); /* !sun */
827 puts("c\tchange number of cylinders");
828 puts("d\tprint the raw data in the partition table");
829 puts("e\tlist extended partitions"); /* !sun */
830 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
831 #if ENABLE_FEATURE_SGI_LABEL
832 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
834 puts("h\tchange number of heads");
835 puts("p\tprint the partition table");
836 puts("q\tquit without saving changes");
837 puts("r\treturn to main menu");
838 puts("s\tchange number of sectors/track");
839 puts("v\tverify the partition table");
840 puts("w\twrite table to disk and exit");
843 #endif /* ADVANCED mode */
845 #if ENABLE_FEATURE_FDISK_WRITABLE
846 static const char *const *
850 LABEL_IS_SUN ? sun_sys_types :
851 LABEL_IS_SGI ? sgi_sys_types :
855 #define get_sys_types() i386_sys_types
856 #endif /* FEATURE_FDISK_WRITABLE */
859 partition_type(unsigned char type)
862 const char *const *types = get_sys_types();
864 for (i = 0; types[i]; i++)
865 if ((unsigned char)types[i][0] == type)
872 #if ENABLE_FEATURE_FDISK_WRITABLE
876 return LABEL_IS_SUN ? sunlabel->infos[i].id :
877 (LABEL_IS_SGI ? sgi_get_sysid(i) :
878 ptes[i].part_table->sys_ind);
882 list_types(const char *const *sys)
887 unsigned done, next, size;
890 for (size = 0; sys[size]; size++) /* */;
893 for (i = COLS-1; i >= 0; i--) {
894 done += (size + i - done) / (i + 1);
895 last[COLS-1 - i] = done;
900 printf("%c%2x %-22.22s", i ? ' ' : '\n',
901 (unsigned char)sys[next][0],
903 next = last[i++] + done;
904 if (i >= COLS || next >= last[i]) {
908 } while (done < last[0]);
911 #endif /* FEATURE_FDISK_WRITABLE */
914 is_cleared_partition(const struct partition *p)
916 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
917 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
918 get_start_sect(p) || get_nr_sects(p));
922 clear_partition(struct partition *p)
926 memset(p, 0, sizeof(struct partition));
929 #if ENABLE_FEATURE_FDISK_WRITABLE
931 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
937 p = ptes[i].ext_pointer;
938 offset = extended_offset;
940 p = ptes[i].part_table;
941 offset = ptes[i].offset;
945 set_start_sect(p, start - offset);
946 set_nr_sects(p, stop - start + 1);
947 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
948 start = heads*sectors*1024 - 1;
949 set_hsc(p->head, p->sector, p->cyl, start);
950 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
951 stop = heads*sectors*1024 - 1;
952 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
960 if (heads && sectors && cylinders)
963 printf("Unknown value(s) for:");
969 printf(" cylinders");
971 #if ENABLE_FEATURE_FDISK_WRITABLE
972 " (settable in the extra functions menu)"
981 int cyl_units = heads * sectors;
983 if (display_in_cyl_units && cyl_units)
984 units_per_sector = cyl_units;
986 units_per_sector = 1; /* in sectors */
989 #if ENABLE_FEATURE_FDISK_WRITABLE
993 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
995 "The number of cylinders for this disk is set to %d.\n"
996 "There is nothing wrong with that, but this is larger than 1024,\n"
997 "and could in certain setups cause problems with:\n"
998 "1) software that runs at boot time (e.g., old versions of LILO)\n"
999 "2) booting and partitioning software from other OSs\n"
1000 " (e.g., DOS FDISK, OS/2 FDISK)\n",
1006 read_extended(int ext)
1010 struct partition *p, *q;
1014 pex->ext_pointer = pex->part_table;
1016 p = pex->part_table;
1017 if (!get_start_sect(p)) {
1018 printf("Bad offset in primary extended partition\n");
1022 while (IS_EXTENDED(p->sys_ind)) {
1023 struct pte *pe = &ptes[partitions];
1025 if (partitions >= MAXIMUM_PARTS) {
1026 /* This is not a Linux restriction, but
1027 this program uses arrays of size MAXIMUM_PARTS.
1028 Do not try to 'improve' this test. */
1029 struct pte *pre = &ptes[partitions-1];
1030 #if ENABLE_FEATURE_FDISK_WRITABLE
1031 printf("Warning: deleting partitions after %d\n",
1035 clear_partition(pre->ext_pointer);
1039 read_pte(pe, extended_offset + get_start_sect(p));
1041 if (!extended_offset)
1042 extended_offset = get_start_sect(p);
1044 q = p = pt_offset(pe->sectorbuffer, 0);
1045 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1046 if (IS_EXTENDED(p->sys_ind)) {
1047 if (pe->ext_pointer)
1048 printf("Warning: extra link "
1049 "pointer in partition table"
1050 " %d\n", partitions + 1);
1052 pe->ext_pointer = p;
1053 } else if (p->sys_ind) {
1055 printf("Warning: ignoring extra "
1056 "data in partition table"
1057 " %d\n", partitions + 1);
1063 /* very strange code here... */
1064 if (!pe->part_table) {
1065 if (q != pe->ext_pointer)
1068 pe->part_table = q + 1;
1070 if (!pe->ext_pointer) {
1071 if (q != pe->part_table)
1072 pe->ext_pointer = q;
1074 pe->ext_pointer = q + 1;
1077 p = pe->ext_pointer;
1081 #if ENABLE_FEATURE_FDISK_WRITABLE
1082 /* remove empty links */
1084 for (i = 4; i < partitions; i++) {
1085 struct pte *pe = &ptes[i];
1087 if (!get_nr_sects(pe->part_table)
1088 && (partitions > 5 || ptes[4].part_table->sys_ind)
1090 printf("Omitting empty partition (%d)\n", i+1);
1091 delete_partition(i);
1092 goto remove; /* numbering changed */
1098 #if ENABLE_FEATURE_FDISK_WRITABLE
1100 create_doslabel(void)
1104 printf(msg_building_new_label, "DOS disklabel");
1106 current_label_type = label_dos;
1108 #if ENABLE_FEATURE_OSF_LABEL
1109 possibly_osf_label = 0;
1113 for (i = 510-64; i < 510; i++)
1115 write_part_table_flag(MBRbuffer);
1116 extended_offset = 0;
1117 set_all_unchanged();
1119 get_boot(create_empty_dos);
1121 #endif /* FEATURE_FDISK_WRITABLE */
1124 get_sectorsize(void)
1126 if (!user_set_sector_size) {
1128 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1130 if (sector_size != DEFAULT_SECTOR_SIZE)
1131 printf("Note: sector size is %d (not %d)\n",
1132 sector_size, DEFAULT_SECTOR_SIZE);
1137 get_kernel_geometry(void)
1139 struct hd_geometry geometry;
1141 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1142 kern_heads = geometry.heads;
1143 kern_sectors = geometry.sectors;
1144 /* never use geometry.cylinders - it is truncated */
1149 get_partition_table_geometry(void)
1151 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1152 struct partition *p;
1153 int i, h, s, hh, ss;
1157 if (!(valid_part_table_flag((char*)bufp)))
1161 for (i = 0; i < 4; i++) {
1162 p = pt_offset(bufp, i);
1163 if (p->sys_ind != 0) {
1164 h = p->end_head + 1;
1165 s = (p->end_sector & 077);
1170 } else if (hh != h || ss != s)
1175 if (!first && !bad) {
1185 unsigned long long bytes; /* really u64 */
1188 sec_fac = sector_size / 512;
1189 #if ENABLE_FEATURE_SUN_LABEL
1190 guess_device_type();
1192 heads = cylinders = sectors = 0;
1193 kern_heads = kern_sectors = 0;
1194 pt_heads = pt_sectors = 0;
1196 get_kernel_geometry();
1197 get_partition_table_geometry();
1199 heads = user_heads ? user_heads :
1200 pt_heads ? pt_heads :
1201 kern_heads ? kern_heads : 255;
1202 sectors = user_sectors ? user_sectors :
1203 pt_sectors ? pt_sectors :
1204 kern_sectors ? kern_sectors : 63;
1205 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
1208 unsigned long longsectors;
1210 if (ioctl(fd, BLKGETSIZE, &longsectors))
1212 bytes = ((unsigned long long) longsectors) << 9;
1215 total_number_of_sectors = (bytes >> 9);
1218 if (dos_compatible_flag)
1219 sector_offset = sectors;
1221 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
1223 cylinders = user_cylinders;
1227 * Read MBR. Returns:
1228 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1229 * 0: found or created label
1233 get_boot(enum action what)
1239 for (i = 0; i < 4; i++) {
1240 struct pte *pe = &ptes[i];
1242 pe->part_table = pt_offset(MBRbuffer, i);
1243 pe->ext_pointer = NULL;
1245 pe->sectorbuffer = MBRbuffer;
1246 #if ENABLE_FEATURE_FDISK_WRITABLE
1247 pe->changed = (what == create_empty_dos);
1251 #if ENABLE_FEATURE_SUN_LABEL
1252 if (what == create_empty_sun && check_sun_label())
1256 memset(MBRbuffer, 0, 512);
1258 #if ENABLE_FEATURE_FDISK_WRITABLE
1259 if (what == create_empty_dos)
1260 goto got_dos_table; /* skip reading disk */
1262 fd = open(disk_device, type_open);
1264 fd = open(disk_device, O_RDONLY);
1266 if (what == try_only)
1268 fdisk_fatal(unable_to_open);
1270 printf("You will not be able to write "
1271 "the partition table\n");
1274 if (512 != read(fd, MBRbuffer, 512)) {
1275 if (what == try_only)
1277 fdisk_fatal(unable_to_read);
1280 fd = open(disk_device, O_RDONLY);
1283 if (512 != read(fd, MBRbuffer, 512))
1291 #if ENABLE_FEATURE_SUN_LABEL
1292 if (check_sun_label())
1296 #if ENABLE_FEATURE_SGI_LABEL
1297 if (check_sgi_label())
1301 #if ENABLE_FEATURE_AIX_LABEL
1302 if (check_aix_label())
1306 #if ENABLE_FEATURE_OSF_LABEL
1307 if (check_osf_label()) {
1308 possibly_osf_label = 1;
1309 if (!valid_part_table_flag(MBRbuffer)) {
1310 current_label_type = label_osf;
1313 printf("This disk has both DOS and BSD magic.\n"
1314 "Give the 'b' command to go to BSD mode.\n");
1318 #if ENABLE_FEATURE_FDISK_WRITABLE
1322 if (!valid_part_table_flag(MBRbuffer)) {
1323 #if !ENABLE_FEATURE_FDISK_WRITABLE
1328 printf("Device contains neither a valid DOS "
1329 "partition table, nor Sun, SGI or OSF "
1332 #if ENABLE_FEATURE_SUN_LABEL
1341 case create_empty_dos:
1342 #if ENABLE_FEATURE_SUN_LABEL
1343 case create_empty_sun:
1347 bb_error_msg_and_die("internal error");
1349 #endif /* FEATURE_FDISK_WRITABLE */
1352 #if ENABLE_FEATURE_FDISK_WRITABLE
1357 for (i = 0; i < 4; i++) {
1358 struct pte *pe = &ptes[i];
1360 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1361 if (partitions != 4)
1362 printf("Ignoring extra extended "
1363 "partition %d\n", i + 1);
1369 for (i = 3; i < partitions; i++) {
1370 struct pte *pe = &ptes[i];
1372 if (!valid_part_table_flag(pe->sectorbuffer)) {
1373 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1374 "table %d will be corrected by w(rite)\n",
1375 pe->sectorbuffer[510],
1376 pe->sectorbuffer[511],
1378 #if ENABLE_FEATURE_FDISK_WRITABLE
1387 #if ENABLE_FEATURE_FDISK_WRITABLE
1389 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1390 * If the user hits Enter, DFLT is returned.
1391 * Answers like +10 are interpreted as offsets from BASE.
1393 * There is no default if DFLT is not between LOW and HIGH.
1396 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1400 const char *fmt = "%s (%u-%u, default %u): ";
1402 if (dflt < low || dflt > high) {
1403 fmt = "%s (%u-%u): ";
1408 int use_default = default_ok;
1410 /* ask question and read answer */
1412 printf(fmt, mesg, low, high, dflt);
1413 read_maybe_empty("");
1414 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1415 && *line_ptr != '-' && *line_ptr != '+');
1417 if (*line_ptr == '+' || *line_ptr == '-') {
1418 int minus = (*line_ptr == '-');
1421 i = atoi(line_ptr + 1);
1423 while (isdigit(*++line_ptr))
1426 switch (*line_ptr) {
1429 if (!display_in_cyl_units)
1430 i *= heads * sectors;
1444 absolute = 1000000000;
1450 unsigned long long bytes;
1453 bytes = (unsigned long long) i * absolute;
1454 unit = sector_size * units_per_sector;
1455 bytes += unit/2; /* round */
1464 while (isdigit(*line_ptr)) {
1471 printf("Using default value %u\n", i);
1473 if (i >= low && i <= high)
1475 printf("Value is out of range\n");
1481 get_partition(int warn, int max)
1486 i = read_int(1, 0, max, 0, "Partition number") - 1;
1490 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1491 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1492 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1494 printf("Warning: partition %d has empty type\n", i+1);
1501 get_existing_partition(int warn, int max)
1506 for (i = 0; i < max; i++) {
1507 struct pte *pe = &ptes[i];
1508 struct partition *p = pe->part_table;
1510 if (p && !is_cleared_partition(p)) {
1517 printf("Selected partition %d\n", pno+1);
1520 printf("No partition is defined yet!\n");
1524 return get_partition(warn, max);
1528 get_nonexisting_partition(int warn, int max)
1533 for (i = 0; i < max; i++) {
1534 struct pte *pe = &ptes[i];
1535 struct partition *p = pe->part_table;
1537 if (p && is_cleared_partition(p)) {
1544 printf("Selected partition %d\n", pno+1);
1547 printf("All primary partitions have been defined already!\n");
1551 return get_partition(warn, max);
1558 display_in_cyl_units = !display_in_cyl_units;
1560 printf("Changing display/entry units to %s\n",
1565 toggle_active(int i)
1567 struct pte *pe = &ptes[i];
1568 struct partition *p = pe->part_table;
1570 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1571 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1572 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1577 toggle_dos_compatibility_flag(void)
1579 dos_compatible_flag = ~dos_compatible_flag;
1580 if (dos_compatible_flag) {
1581 sector_offset = sectors;
1582 printf("DOS Compatibility flag is set\n");
1585 printf("DOS Compatibility flag is not set\n");
1590 delete_partition(int i)
1592 struct pte *pe = &ptes[i];
1593 struct partition *p = pe->part_table;
1594 struct partition *q = pe->ext_pointer;
1596 /* Note that for the fifth partition (i == 4) we don't actually
1597 * decrement partitions.
1600 if (warn_geometry())
1601 return; /* C/H/S not set */
1605 sun_delete_partition(i);
1609 sgi_delete_partition(i);
1614 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1616 ptes[ext_index].ext_pointer = NULL;
1617 extended_offset = 0;
1623 if (!q->sys_ind && i > 4) {
1624 /* the last one in the chain - just delete */
1627 clear_partition(ptes[i].ext_pointer);
1628 ptes[i].changed = 1;
1630 /* not the last one - further ones will be moved down */
1632 /* delete this link in the chain */
1633 p = ptes[i-1].ext_pointer;
1635 set_start_sect(p, get_start_sect(q));
1636 set_nr_sects(p, get_nr_sects(q));
1637 ptes[i-1].changed = 1;
1638 } else if (partitions > 5) { /* 5 will be moved to 4 */
1639 /* the first logical in a longer chain */
1642 if (pe->part_table) /* prevent SEGFAULT */
1643 set_start_sect(pe->part_table,
1644 get_partition_start(pe) -
1646 pe->offset = extended_offset;
1650 if (partitions > 5) {
1652 while (i < partitions) {
1653 ptes[i] = ptes[i+1];
1657 /* the only logical: clear only */
1658 clear_partition(ptes[i].part_table);
1665 int i, sys, origsys;
1666 struct partition *p;
1668 /* If sgi_label then don't use get_existing_partition,
1669 let the user select a partition, since get_existing_partition()
1670 only works for Linux like partition tables. */
1671 if (!LABEL_IS_SGI) {
1672 i = get_existing_partition(0, partitions);
1674 i = get_partition(0, partitions);
1678 p = ptes[i].part_table;
1679 origsys = sys = get_sysid(i);
1681 /* if changing types T to 0 is allowed, then
1682 the reverse change must be allowed, too */
1683 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1684 printf("Partition %d does not exist yet!\n", i + 1);
1688 sys = read_hex(get_sys_types());
1690 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1691 printf("Type 0 means free space to many systems\n"
1692 "(but not to Linux). Having partitions of\n"
1693 "type 0 is probably unwise.\n");
1697 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1698 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1699 printf("You cannot change a partition into"
1700 " an extended one or vice versa\n");
1706 #if ENABLE_FEATURE_SUN_LABEL
1707 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1708 printf("Consider leaving partition 3 "
1709 "as Whole disk (5),\n"
1710 "as SunOS/Solaris expects it and "
1711 "even Linux likes it\n\n");
1713 #if ENABLE_FEATURE_SGI_LABEL
1716 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1717 (i == 8 && sys != 0)
1720 printf("Consider leaving partition 9 "
1721 "as volume header (0),\nand "
1722 "partition 11 as entire volume (6)"
1723 "as IRIX expects it\n\n");
1729 sun_change_sysid(i, sys);
1730 } else if (LABEL_IS_SGI) {
1731 sgi_change_sysid(i, sys);
1735 printf("Changed system type of partition %d "
1736 "to %x (%s)\n", i + 1, sys,
1737 partition_type(sys));
1738 ptes[i].changed = 1;
1739 if (is_dos_partition(origsys) ||
1740 is_dos_partition(sys))
1746 #endif /* FEATURE_FDISK_WRITABLE */
1749 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1750 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1751 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1752 * Lubkin Oct. 1991). */
1755 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1757 int spc = heads * sectors;
1762 *s = ls % sectors + 1; /* sectors count from 1 */
1766 check_consistency(const struct partition *p, int partition)
1768 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1769 unsigned pec, peh, pes; /* physical ending c, h, s */
1770 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1771 unsigned lec, leh, les; /* logical ending c, h, s */
1773 if (!heads || !sectors || (partition >= 4))
1774 return; /* do not check extended partitions */
1776 /* physical beginning c, h, s */
1777 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1779 pbs = p->sector & 0x3f;
1781 /* physical ending c, h, s */
1782 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1784 pes = p->end_sector & 0x3f;
1786 /* compute logical beginning (c, h, s) */
1787 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1789 /* compute logical ending (c, h, s) */
1790 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1792 /* Same physical / logical beginning? */
1793 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1794 printf("Partition %d has different physical/logical "
1795 "beginnings (non-Linux?):\n", partition + 1);
1796 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1797 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1800 /* Same physical / logical ending? */
1801 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1802 printf("Partition %d has different physical/logical "
1803 "endings:\n", partition + 1);
1804 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1805 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1808 /* Ending on cylinder boundary? */
1809 if (peh != (heads - 1) || pes != sectors) {
1810 printf("Partition %i does not end on cylinder boundary\n",
1816 list_disk_geometry(void)
1818 long long bytes = (total_number_of_sectors << 9);
1819 long megabytes = bytes/1000000;
1821 if (megabytes < 10000)
1822 printf("\nDisk %s: %ld MB, %lld bytes\n",
1823 disk_device, megabytes, bytes);
1825 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1826 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1827 printf("%d heads, %d sectors/track, %d cylinders",
1828 heads, sectors, cylinders);
1829 if (units_per_sector == 1)
1830 printf(", total %llu sectors",
1831 total_number_of_sectors / (sector_size/512));
1832 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1834 units_per_sector, sector_size, units_per_sector * sector_size);
1838 * Check whether partition entries are ordered by their starting positions.
1839 * Return 0 if OK. Return i if partition i should have been earlier.
1840 * Two separate checks: primary and logical partitions.
1843 wrong_p_order(int *prev)
1845 const struct pte *pe;
1846 const struct partition *p;
1847 off_t last_p_start_pos = 0, p_start_pos;
1850 for (i = 0 ; i < partitions; i++) {
1853 last_p_start_pos = 0;
1856 if ((p = pe->part_table)->sys_ind) {
1857 p_start_pos = get_partition_start(pe);
1859 if (last_p_start_pos > p_start_pos) {
1865 last_p_start_pos = p_start_pos;
1872 #if ENABLE_FEATURE_FDISK_ADVANCED
1874 * Fix the chain of logicals.
1875 * extended_offset is unchanged, the set of sectors used is unchanged
1876 * The chain is sorted so that sectors increase, and so that
1877 * starting sectors increase.
1879 * After this it may still be that cfdisk doesnt like the table.
1880 * (This is because cfdisk considers expanded parts, from link to
1881 * end of partition, and these may still overlap.)
1883 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1887 fix_chain_of_logicals(void)
1889 int j, oj, ojj, sj, sjj;
1890 struct partition *pj,*pjj,tmp;
1892 /* Stage 1: sort sectors but leave sector of part 4 */
1893 /* (Its sector is the global extended_offset.) */
1895 for (j = 5; j < partitions-1; j++) {
1896 oj = ptes[j].offset;
1897 ojj = ptes[j+1].offset;
1899 ptes[j].offset = ojj;
1900 ptes[j+1].offset = oj;
1901 pj = ptes[j].part_table;
1902 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1903 pjj = ptes[j+1].part_table;
1904 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1905 set_start_sect(ptes[j-1].ext_pointer,
1906 ojj-extended_offset);
1907 set_start_sect(ptes[j].ext_pointer,
1908 oj-extended_offset);
1913 /* Stage 2: sort starting sectors */
1915 for (j = 4; j < partitions-1; j++) {
1916 pj = ptes[j].part_table;
1917 pjj = ptes[j+1].part_table;
1918 sj = get_start_sect(pj);
1919 sjj = get_start_sect(pjj);
1920 oj = ptes[j].offset;
1921 ojj = ptes[j+1].offset;
1922 if (oj+sj > ojj+sjj) {
1926 set_start_sect(pj, ojj+sjj-oj);
1927 set_start_sect(pjj, oj+sj-ojj);
1932 /* Probably something was changed */
1933 for (j = 4; j < partitions; j++)
1934 ptes[j].changed = 1;
1939 fix_partition_table_order(void)
1941 struct pte *pei, *pek;
1944 if (!wrong_p_order(NULL)) {
1945 printf("Ordering is already correct\n\n");
1949 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1950 /* partition i should have come earlier, move it */
1951 /* We have to move data in the MBR */
1952 struct partition *pi, *pk, *pe, pbuf;
1956 pe = pei->ext_pointer;
1957 pei->ext_pointer = pek->ext_pointer;
1958 pek->ext_pointer = pe;
1960 pi = pei->part_table;
1961 pk = pek->part_table;
1963 memmove(&pbuf, pi, sizeof(struct partition));
1964 memmove(pi, pk, sizeof(struct partition));
1965 memmove(pk, &pbuf, sizeof(struct partition));
1967 pei->changed = pek->changed = 1;
1971 fix_chain_of_logicals();
1979 list_table(int xtra)
1981 const struct partition *p;
1985 sun_list_table(xtra);
1989 sgi_list_table(xtra);
1993 list_disk_geometry();
1996 xbsd_print_disklabel(xtra);
2000 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
2001 but if the device name ends in a digit, say /dev/foo1,
2002 then the partition is called /dev/foo1p3. */
2003 w = strlen(disk_device);
2004 if (w && isdigit(disk_device[w-1]))
2009 // 1 12345678901 12345678901 12345678901 12
2010 printf("%*s Boot Start End Blocks Id System\n",
2013 for (i = 0; i < partitions; i++) {
2014 const struct pte *pe = &ptes[i];
2020 if (!p || is_cleared_partition(p))
2023 psects = get_nr_sects(p);
2027 if (sector_size < 1024) {
2028 pblocks /= (1024 / sector_size);
2029 podd = psects % (1024 / sector_size);
2031 if (sector_size > 1024)
2032 pblocks *= (sector_size / 1024);
2034 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2035 partname(disk_device, i+1, w+2),
2036 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2038 (unsigned long long) cround(get_partition_start(pe)), /* start */
2039 (unsigned long long) cround(get_partition_start(pe) + psects /* end */
2040 - (psects ? 1 : 0)),
2041 (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */
2042 p->sys_ind, /* type id */
2043 partition_type(p->sys_ind)); /* type name */
2045 check_consistency(p, i);
2048 /* Is partition table in disk order? It need not be, but... */
2049 /* partition table entries are not checked for correct order if this
2050 is a sgi, sun or aix labeled disk... */
2051 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2053 printf("\nPartition table entries are not in disk order\n");
2057 #if ENABLE_FEATURE_FDISK_ADVANCED
2059 x_list_table(int extend)
2061 const struct pte *pe;
2062 const struct partition *p;
2065 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2066 disk_device, heads, sectors, cylinders);
2067 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2068 for (i = 0 ; i < partitions; i++) {
2070 p = (extend ? pe->ext_pointer : pe->part_table);
2072 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2073 i + 1, p->boot_ind, p->head,
2075 cylinder(p->sector, p->cyl), p->end_head,
2076 sector(p->end_sector),
2077 cylinder(p->end_sector, p->end_cyl),
2078 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2080 check_consistency(p, i);
2086 #if ENABLE_FEATURE_FDISK_WRITABLE
2088 fill_bounds(off_t *first, off_t *last)
2091 const struct pte *pe = &ptes[0];
2092 const struct partition *p;
2094 for (i = 0; i < partitions; pe++,i++) {
2096 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2097 first[i] = 0xffffffff;
2100 first[i] = get_partition_start(pe);
2101 last[i] = first[i] + get_nr_sects(p) - 1;
2107 check(int n, unsigned h, unsigned s, unsigned c, off_t start)
2109 off_t total, real_s, real_c;
2111 real_s = sector(s) - 1;
2112 real_c = cylinder(s, c);
2113 total = (real_c * sectors + real_s) * heads + h;
2115 printf("Partition %d contains sector 0\n", n);
2117 printf("Partition %d: head %d greater than maximum %d\n",
2119 if (real_s >= sectors)
2120 printf("Partition %d: sector %d greater than "
2121 "maximum %d\n", n, s, sectors);
2122 if (real_c >= cylinders)
2123 printf("Partition %d: cylinder %"OFF_FMT"u greater than "
2124 "maximum %d\n", n, real_c + 1, cylinders);
2125 if (cylinders <= 1024 && start != total)
2126 printf("Partition %d: previous sectors %"OFF_FMT"u disagrees with "
2127 "total %"OFF_FMT"u\n", n, start, total);
2135 off_t first[partitions], last[partitions];
2136 struct partition *p;
2138 if (warn_geometry())
2150 fill_bounds(first, last);
2151 for (i = 0; i < partitions; i++) {
2152 struct pte *pe = &ptes[i];
2155 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2156 check_consistency(p, i);
2157 if (get_partition_start(pe) < first[i])
2158 printf("Warning: bad start-of-data in "
2159 "partition %d\n", i + 1);
2160 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2162 total += last[i] + 1 - first[i];
2163 for (j = 0; j < i; j++) {
2164 if ((first[i] >= first[j] && first[i] <= last[j])
2165 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2166 printf("Warning: partition %d overlaps "
2167 "partition %d\n", j + 1, i + 1);
2168 total += first[i] >= first[j] ?
2169 first[i] : first[j];
2170 total -= last[i] <= last[j] ?
2177 if (extended_offset) {
2178 struct pte *pex = &ptes[ext_index];
2179 off_t e_last = get_start_sect(pex->part_table) +
2180 get_nr_sects(pex->part_table) - 1;
2182 for (i = 4; i < partitions; i++) {
2184 p = ptes[i].part_table;
2186 if (i != 4 || i + 1 < partitions)
2187 printf("Warning: partition %d "
2188 "is empty\n", i + 1);
2189 } else if (first[i] < extended_offset || last[i] > e_last) {
2190 printf("Logical partition %d not entirely in "
2191 "partition %d\n", i + 1, ext_index + 1);
2196 if (total > heads * sectors * cylinders)
2197 printf("Total allocated sectors %d greater than the maximum "
2198 "%d\n", total, heads * sectors * cylinders);
2200 total = heads * sectors * cylinders - total;
2202 printf("%d unallocated sectors\n", total);
2207 add_partition(int n, int sys)
2209 char mesg[256]; /* 48 does not suffice in Japanese */
2210 int i, num_read = 0;
2211 struct partition *p = ptes[n].part_table;
2212 struct partition *q = ptes[ext_index].part_table;
2214 off_t start, stop = 0, limit, temp,
2215 first[partitions], last[partitions];
2217 if (p && p->sys_ind) {
2218 printf(msg_part_already_defined, n + 1);
2221 fill_bounds(first, last);
2223 start = sector_offset;
2224 if (display_in_cyl_units || !total_number_of_sectors)
2225 llimit = heads * sectors * cylinders - 1;
2227 llimit = total_number_of_sectors - 1;
2229 if (limit != llimit)
2231 if (extended_offset) {
2232 first[ext_index] = extended_offset;
2233 last[ext_index] = get_start_sect(q) +
2234 get_nr_sects(q) - 1;
2237 start = extended_offset + sector_offset;
2238 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2240 if (display_in_cyl_units)
2241 for (i = 0; i < partitions; i++)
2242 first[i] = (cround(first[i]) - 1) * units_per_sector;
2244 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2247 for (i = 0; i < partitions; i++) {
2250 if (start == ptes[i].offset)
2251 start += sector_offset;
2252 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2253 if (start >= first[i] && start <= lastplusoff)
2254 start = lastplusoff + 1;
2258 if (start >= temp+units_per_sector && num_read) {
2259 printf("Sector %"OFF_FMT"d is already allocated\n", temp);
2263 if (!num_read && start == temp) {
2266 saved_start = start;
2267 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2269 if (display_in_cyl_units) {
2270 start = (start - 1) * units_per_sector;
2271 if (start < saved_start) start = saved_start;
2275 } while (start != temp || !num_read);
2276 if (n > 4) { /* NOT for fifth partition */
2277 struct pte *pe = &ptes[n];
2279 pe->offset = start - sector_offset;
2280 if (pe->offset == extended_offset) { /* must be corrected */
2282 if (sector_offset == 1)
2287 for (i = 0; i < partitions; i++) {
2288 struct pte *pe = &ptes[i];
2290 if (start < pe->offset && limit >= pe->offset)
2291 limit = pe->offset - 1;
2292 if (start < first[i] && limit >= first[i])
2293 limit = first[i] - 1;
2295 if (start > limit) {
2296 printf("No free sectors available\n");
2301 if (cround(start) == cround(limit)) {
2304 snprintf(mesg, sizeof(mesg),
2305 "Last %s or +size or +sizeM or +sizeK",
2306 str_units(SINGULAR));
2307 stop = read_int(cround(start), cround(limit), cround(limit),
2308 cround(start), mesg);
2309 if (display_in_cyl_units) {
2310 stop = stop * units_per_sector - 1;
2316 set_partition(n, 0, start, stop, sys);
2318 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2320 if (IS_EXTENDED(sys)) {
2321 struct pte *pe4 = &ptes[4];
2322 struct pte *pen = &ptes[n];
2325 pen->ext_pointer = p;
2326 pe4->offset = extended_offset = start;
2327 pe4->sectorbuffer = xzalloc(sector_size);
2328 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2329 pe4->ext_pointer = pe4->part_table + 1;
2338 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2339 struct pte *pe = &ptes[partitions];
2341 pe->sectorbuffer = xzalloc(sector_size);
2342 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2343 pe->ext_pointer = pe->part_table + 1;
2348 add_partition(partitions - 1, LINUX_NATIVE);
2354 int i, free_primary = 0;
2356 if (warn_geometry())
2360 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2364 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2368 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2369 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2370 "table first (use 'o'). This will destroy the present disk contents.\n");
2374 for (i = 0; i < 4; i++)
2375 free_primary += !ptes[i].part_table->sys_ind;
2377 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2378 printf("The maximum number of partitions has been created\n");
2382 if (!free_primary) {
2383 if (extended_offset)
2386 printf("You must delete some partition and add "
2387 "an extended partition first\n");
2390 snprintf(line, sizeof(line),
2393 " p primary partition (1-4)\n",
2395 "l logical (5 or over)" : "e extended"));
2397 c = read_nonempty(line);
2398 if (c == 'p' || c == 'P') {
2399 i = get_nonexisting_partition(0, 4);
2401 add_partition(i, LINUX_NATIVE);
2404 if (c == 'l' && extended_offset) {
2408 if (c == 'e' && !extended_offset) {
2409 i = get_nonexisting_partition(0, 4);
2411 add_partition(i, EXTENDED);
2414 printf("Invalid partition number "
2415 "for type '%c'\n", c);
2426 for (i = 0; i < 3; i++)
2427 if (ptes[i].changed)
2428 ptes[3].changed = 1;
2429 for (i = 3; i < partitions; i++) {
2430 struct pte *pe = &ptes[i];
2433 write_part_table_flag(pe->sectorbuffer);
2434 write_sector(pe->offset, pe->sectorbuffer);
2438 else if (LABEL_IS_SGI) {
2439 /* no test on change? the printf below might be mistaken */
2442 else if (LABEL_IS_SUN) {
2445 for (i = 0; i < 8; i++)
2446 if (ptes[i].changed)
2452 printf("The partition table has been altered!\n\n");
2453 reread_partition_table(1);
2457 reread_partition_table(int leave)
2461 printf("Calling ioctl() to re-read partition table\n");
2463 /* sleep(2); Huh? */
2464 i = ioctl(fd, BLKRRPART);
2467 /* some kernel versions (1.2.x) seem to have trouble
2468 rereading the partition table, but if asked to do it
2469 twice, the second time works. - biro@yggdrasil.com */
2472 i = ioctl(fd, BLKRRPART);
2477 bb_perror_msg("WARNING: rereading partition table "
2478 "failed, kernel still uses old table");
2484 "\nWARNING: If you have created or modified any DOS 6.x\n"
2485 "partitions, please see the fdisk manual page for additional\n"
2490 if (ENABLE_FEATURE_CLEAN_UP)
2495 #endif /* FEATURE_FDISK_WRITABLE */
2497 #if ENABLE_FEATURE_FDISK_ADVANCED
2498 #define MAX_PER_LINE 16
2500 print_buffer(char *pbuffer)
2504 for (i = 0, l = 0; i < sector_size; i++, l++) {
2506 printf("0x%03X:", i);
2507 printf(" %02X", (unsigned char) pbuffer[i]);
2508 if (l == MAX_PER_LINE - 1) {
2523 printf("Device: %s\n", disk_device);
2524 if (LABEL_IS_SGI || LABEL_IS_SUN)
2525 print_buffer(MBRbuffer);
2527 for (i = 3; i < partitions; i++)
2528 print_buffer(ptes[i].sectorbuffer);
2535 struct pte *pe = &ptes[i];
2536 struct partition *p = pe->part_table;
2539 if (warn_geometry())
2541 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2542 printf("Partition %d has no data area\n", i + 1);
2545 first = get_partition_start(pe);
2546 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2547 "New beginning of data") - pe->offset;
2549 if (new != get_nr_sects(p)) {
2550 first = get_nr_sects(p) + get_start_sect(p) - new;
2551 set_nr_sects(p, first);
2552 set_start_sect(p, new);
2564 c = tolower(read_nonempty("Expert command (m for help): "));
2572 move_begin(get_partition(0, partitions));
2575 user_cylinders = cylinders =
2576 read_int(1, cylinders, 1048576, 0,
2577 "Number of cylinders");
2579 sun_set_ncyl(cylinders);
2589 else if (LABEL_IS_SUN)
2591 else if (LABEL_IS_DOS)
2596 fix_partition_table_order();
2599 #if ENABLE_FEATURE_SGI_LABEL
2604 user_heads = heads = read_int(1, heads, 256, 0,
2629 user_sectors = sectors = read_int(1, sectors, 63, 0,
2630 "Number of sectors");
2631 if (dos_compatible_flag) {
2632 sector_offset = sectors;
2633 printf("Warning: setting sector offset for DOS "
2642 write_table(); /* does not return */
2646 sun_set_pcylcount();
2653 #endif /* ADVANCED mode */
2656 is_ide_cdrom_or_tape(const char *device)
2660 struct stat statbuf;
2663 /* No device was given explicitly, and we are trying some
2664 likely things. But opening /dev/hdc may produce errors like
2665 "hdc: tray open or drive not ready"
2666 if it happens to be a CD-ROM drive. It even happens that
2667 the process hangs on the attempt to read a music CD.
2668 So try to be careful. This only works since 2.1.73. */
2670 if (strncmp("/dev/hd", device, 7))
2673 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2674 procf = fopen(buf, "r");
2675 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2676 is_ide = (!strncmp(buf, "cdrom", 5) ||
2677 !strncmp(buf, "tape", 4));
2679 /* Now when this proc file does not exist, skip the
2680 device when it is read-only. */
2681 if (stat(device, &statbuf) == 0)
2682 is_ide = ((statbuf.st_mode & 0222) == 0);
2691 trydev(const char *device, int user_specified)
2695 disk_device = device;
2696 if (setjmp(listingbuf))
2698 if (!user_specified)
2699 if (is_ide_cdrom_or_tape(device))
2701 fd = open(disk_device, type_open);
2703 gb = get_boot(try_only);
2704 if (gb > 0) { /* I/O error */
2706 } else if (gb < 0) { /* no DOS signature */
2707 list_disk_geometry();
2711 #if ENABLE_FEATURE_OSF_LABEL
2712 if (bsd_trydev(device) < 0)
2714 printf("Disk %s doesn't contain a valid "
2715 "partition table\n", device);
2720 #if ENABLE_FEATURE_FDISK_WRITABLE
2721 if (!LABEL_IS_SUN && partitions > 4){
2722 delete_partition(ext_index);
2727 /* Ignore other errors, since we try IDE
2728 and SCSI hard disks which may not be
2729 installed on the system. */
2730 if (errno == EACCES) {
2731 printf("Cannot open %s\n", device);
2737 /* for fdisk -l: try all things in /proc/partitions
2738 that look like a partition name (do not end in a digit) */
2743 char line[100], ptname[100], devname[120], *s;
2746 procpt = fopen_or_warn("/proc/partitions", "r");
2748 while (fgets(line, sizeof(line), procpt)) {
2749 if (sscanf(line, " %d %d %d %[^\n ]",
2750 &ma, &mi, &sz, ptname) != 4)
2752 for (s = ptname; *s; s++);
2755 sprintf(devname, "/dev/%s", ptname);
2758 #if ENABLE_FEATURE_CLEAN_UP
2763 #if ENABLE_FEATURE_FDISK_WRITABLE
2765 unknown_command(int c)
2767 printf("%c: unknown command\n", c);
2771 int fdisk_main(int argc, char **argv);
2772 int fdisk_main(int argc, char **argv)
2774 char *str_b, *str_C, *str_H, *str_S;
2778 * fdisk -l [-b sectorsize] [-u] device ...
2779 * fdisk -s [partition] ...
2780 * fdisk [-b sectorsize] [-u] device
2782 * Options -C, -H, -S set the geometry.
2791 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2794 PTR_TO_GLOBALS = xzalloc(sizeof(G));
2796 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2797 &str_b, &str_C, &str_H, &str_S);
2800 if (opt & OPT_b) { // -b
2801 /* Ugly: this sector size is really per device,
2802 so cannot be combined with multiple disks,
2803 and the same goes for the C/H/S options.
2805 sector_size = xatoi_u(str_b);
2806 if (sector_size != 512 && sector_size != 1024 &&
2807 sector_size != 2048)
2810 user_set_sector_size = 1;
2812 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2813 if (opt & OPT_H) { // -H
2814 user_heads = xatoi_u(str_H);
2815 if (user_heads <= 0 || user_heads >= 256)
2818 //if (opt & OPT_l) // -l
2819 if (opt & OPT_S) { // -S
2820 user_sectors = xatoi_u(str_S);
2821 if (user_sectors <= 0 || user_sectors >= 64)
2824 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2825 //if (opt & OPT_s) // -s
2827 if (user_set_sector_size && argc != 1)
2828 printf("Warning: the -b (set sector size) option should"
2829 " be used with one specified device\n");
2831 #if ENABLE_FEATURE_FDISK_WRITABLE
2835 type_open = O_RDONLY;
2838 #if defined(__GNUC__)
2839 /* avoid gcc warning:
2840 variable `k' might be clobbered by `longjmp' */
2844 for (k = 0; k < argc; k++)
2847 /* we no longer have default device names */
2848 /* but, we can use /proc/partitions instead */
2852 #if ENABLE_FEATURE_FDISK_WRITABLE
2856 #if ENABLE_FEATURE_FDISK_BLKSIZE
2862 type_open = O_RDONLY;
2867 for (j = 0; j < argc; j++) {
2868 disk_device = argv[j];
2869 fd = open(disk_device, type_open);
2871 fdisk_fatal(unable_to_open);
2872 if (ioctl(fd, BLKGETSIZE, &size))
2873 fdisk_fatal(ioctl_error);
2876 printf("%ld\n", size/2);
2878 printf("%s: %ld\n", argv[j], size/2);
2884 #if ENABLE_FEATURE_FDISK_WRITABLE
2888 disk_device = argv[0];
2892 /* OSF label, and no DOS label */
2893 printf("Detected an OSF/1 disklabel on %s, entering "
2894 "disklabel mode\n", disk_device);
2896 /*Why do we do this? It seems to be counter-intuitive*/
2897 current_label_type = label_dos;
2898 /* If we return we may want to make an empty DOS label? */
2904 c = tolower(read_nonempty("Command (m for help): "));
2908 toggle_active(get_partition(1, partitions));
2909 else if (LABEL_IS_SUN)
2910 toggle_sunflags(get_partition(1, partitions),
2912 else if (LABEL_IS_SGI)
2913 sgi_set_bootpartition(
2914 get_partition(1, partitions));
2920 printf("\nThe current boot file is: %s\n",
2921 sgi_get_bootfile());
2922 if (read_maybe_empty("Please enter the name of the "
2923 "new boot file: ") == '\n')
2924 printf("Boot file unchanged\n");
2926 sgi_set_bootfile(line_ptr);
2928 #if ENABLE_FEATURE_OSF_LABEL
2935 toggle_dos_compatibility_flag();
2936 else if (LABEL_IS_SUN)
2937 toggle_sunflags(get_partition(1, partitions),
2939 else if (LABEL_IS_SGI)
2940 sgi_set_swappartition(
2941 get_partition(1, partitions));
2948 /* If sgi_label then don't use get_existing_partition,
2949 let the user select a partition, since
2950 get_existing_partition() only works for Linux-like
2952 if (!LABEL_IS_SGI) {
2953 j = get_existing_partition(1, partitions);
2955 j = get_partition(1, partitions);
2958 delete_partition(j);
2967 list_types(get_sys_types());
2986 #if ENABLE_FEATURE_SUN_LABEL
3000 write_table(); /* does not return */
3002 #if ENABLE_FEATURE_FDISK_ADVANCED
3005 printf("\n\tSorry, no experts menu for SGI "
3006 "partition tables available\n\n");
3017 #endif /* FEATURE_FDISK_WRITABLE */