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 DEFAULT_SECTOR_SIZE 512
20 #define MAX_SECTOR_SIZE 2048
21 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
22 #define MAXIMUM_PARTS 60
24 #define ACTIVE_FLAG 0x80
27 #define WIN98_EXTENDED 0x0f
28 #define LINUX_PARTITION 0x81
29 #define LINUX_SWAP 0x82
30 #define LINUX_NATIVE 0x83
31 #define LINUX_EXTENDED 0x85
32 #define LINUX_LVM 0x8e
33 #define LINUX_RAID 0xfd
35 #define IS_EXTENDED(i) \
36 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
38 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
40 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
41 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
45 unsigned char sectors;
46 unsigned short cylinders;
50 #define HDIO_GETGEO 0x0301 /* get device geometry */
52 static const char msg_building_new_label[] =
53 "Building a new %s. Changes will remain in memory only,\n"
54 "until you decide to write them. After that the previous content\n"
55 "won't be recoverable.\n\n";
57 static const char msg_part_already_defined[] =
58 "Partition %d is already defined, delete it before re-adding\n";
61 static unsigned sector_size = DEFAULT_SECTOR_SIZE;
62 static unsigned user_set_sector_size;
63 static unsigned sector_offset = 1;
65 #if ENABLE_FEATURE_OSF_LABEL
66 static int possibly_osf_label;
69 static unsigned heads, sectors, cylinders;
70 static void update_units(void);
74 unsigned char boot_ind; /* 0x80 - active */
75 unsigned char head; /* starting head */
76 unsigned char sector; /* starting sector */
77 unsigned char cyl; /* starting cylinder */
78 unsigned char sys_ind; /* What partition type */
79 unsigned char end_head; /* end head */
80 unsigned char end_sector; /* end sector */
81 unsigned char end_cyl; /* end cylinder */
82 unsigned char start4[4]; /* starting sector counting from 0 */
83 unsigned char size4[4]; /* nr of sectors in partition */
87 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
92 label_dos, label_sun, label_sgi, label_aix, label_osf
94 #define LABEL_IS_DOS (label_dos == current_label_type)
96 #if ENABLE_FEATURE_SUN_LABEL
97 #define LABEL_IS_SUN (label_sun == current_label_type)
98 #define STATIC_SUN static
100 #define LABEL_IS_SUN 0
101 #define STATIC_SUN extern
104 #if ENABLE_FEATURE_SGI_LABEL
105 #define LABEL_IS_SGI (label_sgi == current_label_type)
106 #define STATIC_SGI static
108 #define LABEL_IS_SGI 0
109 #define STATIC_SGI extern
112 #if ENABLE_FEATURE_AIX_LABEL
113 #define LABEL_IS_AIX (label_aix == current_label_type)
114 #define STATIC_AIX static
116 #define LABEL_IS_AIX 0
117 #define STATIC_AIX extern
120 #if ENABLE_FEATURE_OSF_LABEL
121 #define LABEL_IS_OSF (label_osf == current_label_type)
122 #define STATIC_OSF static
124 #define LABEL_IS_OSF 0
125 #define STATIC_OSF extern
128 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
130 static enum label_type current_label_type;
132 static const char *disk_device;
133 static int fd; /* the disk */
134 static int partitions = 4; /* maximum partition + 1 */
135 static int display_in_cyl_units = 1;
136 static unsigned units_per_sector = 1;
137 #if ENABLE_FEATURE_FDISK_WRITABLE
138 static void change_units(void);
139 static void reread_partition_table(int leave);
140 static void delete_partition(int i);
141 static int get_partition(int warn, int max);
142 static void list_types(const char *const *sys);
143 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
145 static const char *partition_type(unsigned char type);
146 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
147 static void get_geometry(void);
148 static int get_boot(enum action what);
153 #define hex_val(c) ({ \
155 isdigit(_c) ? _c - '0' : \
156 tolower(_c) + 10 - 'a'; \
159 #define LINE_LENGTH 80
160 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
161 (n) * sizeof(struct partition)))
162 #define sector(s) ((s) & 0x3f)
163 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
165 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
166 ((h) + heads * cylinder(s,c)))
167 #define set_hsc(h,s,c,sector) \
169 s = sector % sectors + 1; \
171 h = sector % heads; \
174 s |= (sector >> 2) & 0xc0; \
177 static unsigned get_start_sect(const struct partition *p);
178 static unsigned get_nr_sects(const struct partition *p);
181 * per partition table entry data
183 * The four primary partitions have the same sectorbuffer (MBRbuffer)
184 * and have NULL ext_pointer.
185 * Each logical partition table entry has two pointers, one for the
186 * partition and one link to the next one.
189 struct partition *part_table; /* points into sectorbuffer */
190 struct partition *ext_pointer; /* points into sectorbuffer */
191 #if ENABLE_FEATURE_FDISK_WRITABLE
192 char changed; /* boolean */
194 off_t offset; /* disk sector number */
195 char *sectorbuffer; /* disk sector contents */
199 /* Raw disk label. For DOS-type partition tables the MBR,
200 * with descriptions of the primary partitions. */
201 char MBRbuffer[MAX_SECTOR_SIZE];
202 /* Partition tables */
203 struct pte ptes[MAXIMUM_PARTS];
206 #define G (*(struct globals*)bb_common_bufsiz1)
207 #define MBRbuffer (G.MBRbuffer)
208 #define ptes (G.ptes)
212 * return partition name - uses static storage
215 partname(const char *dev, int pno, int lth)
217 static char buffer[80];
224 bufsiz = sizeof(buffer);
229 if (isdigit(dev[w-1]))
232 /* devfs kludge - note: fdisk partition names are not supposed
233 to equal kernel names, so there is no reason to do this */
234 if (strcmp(dev + w - 4, "disc") == 0) {
242 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
243 lth-wp-2, w, dev, p, pno);
245 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
250 #if ENABLE_FEATURE_FDISK_WRITABLE
252 set_all_unchanged(void)
256 for (i = 0; i < MAXIMUM_PARTS; i++)
260 static ATTRIBUTE_ALWAYS_INLINE void
265 #endif /* FEATURE_FDISK_WRITABLE */
267 static ATTRIBUTE_ALWAYS_INLINE struct partition *
268 get_part_table(int i)
270 return ptes[i].part_table;
275 { /* n==1: use singular */
277 return display_in_cyl_units ? "cylinder" : "sector";
278 return display_in_cyl_units ? "cylinders" : "sectors";
282 valid_part_table_flag(const char *mbuffer)
284 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
287 #if ENABLE_FEATURE_FDISK_WRITABLE
288 static ATTRIBUTE_ALWAYS_INLINE void
289 write_part_table_flag(char *b)
295 static char line_buffer[LINE_LENGTH];
296 static char *line_ptr;
298 /* read line; return 0 or first printable char */
300 read_line(const char *prompt)
304 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
306 exit(0); /* Ctrl-D or Ctrl-C */
308 if (line_buffer[sz-1] == '\n')
309 line_buffer[--sz] = '\0';
311 line_ptr = line_buffer;
312 while (*line_ptr && !isgraph(*line_ptr))
318 read_nonempty(const char *mesg)
320 while (!read_line(mesg)) /* repeat */;
325 read_maybe_empty(const char *mesg)
327 if (!read_line(mesg)) {
328 line_ptr = line_buffer;
336 read_hex(const char *const *sys)
340 read_nonempty("Hex code (type L to list codes): ");
341 if (*line_ptr == 'l' || *line_ptr == 'L') {
345 v = bb_strtoul(line_ptr, NULL, 16);
347 /* Bad input also triggers this */
352 #endif /* FEATURE_FDISK_WRITABLE */
354 #include "fdisk_aix.c"
357 unsigned char info[128]; /* Informative text string */
358 unsigned char spare0[14];
360 unsigned char spare1;
362 unsigned char spare2;
365 unsigned char spare1[246]; /* Boot information etc. */
366 unsigned short rspeed; /* Disk rotational speed */
367 unsigned short pcylcount; /* Physical cylinder count */
368 unsigned short sparecyl; /* extra sects per cylinder */
369 unsigned char spare2[4]; /* More magic... */
370 unsigned short ilfact; /* Interleave factor */
371 unsigned short ncyl; /* Data cylinder count */
372 unsigned short nacyl; /* Alt. cylinder count */
373 unsigned short ntrks; /* Tracks per cylinder */
374 unsigned short nsect; /* Sectors per track */
375 unsigned char spare3[4]; /* Even more magic... */
376 struct sun_partinfo {
377 uint32_t start_cylinder;
378 uint32_t num_sectors;
380 unsigned short magic; /* Magic number */
381 unsigned short csum; /* Label xor'd checksum */
383 #define sunlabel ((sun_partition *)MBRbuffer)
384 STATIC_OSF void bsd_select(void);
385 STATIC_OSF void xbsd_print_disklabel(int);
386 #include "fdisk_osf.c"
388 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
390 fdisk_swap16(uint16_t x)
392 return (x << 8) | (x >> 8);
396 fdisk_swap32(uint32_t x)
399 ((x & 0xFF00) << 8) |
400 ((x & 0xFF0000) >> 8) |
405 STATIC_SGI const char *const sgi_sys_types[];
406 STATIC_SGI unsigned sgi_get_num_sectors(int i);
407 STATIC_SGI int sgi_get_sysid(int i);
408 STATIC_SGI void sgi_delete_partition(int i);
409 STATIC_SGI void sgi_change_sysid(int i, int sys);
410 STATIC_SGI void sgi_list_table(int xtra);
411 #if ENABLE_FEATURE_FDISK_ADVANCED
412 STATIC_SGI void sgi_set_xcyl(void);
414 STATIC_SGI int verify_sgi(int verbose);
415 STATIC_SGI void sgi_add_partition(int n, int sys);
416 STATIC_SGI void sgi_set_swappartition(int i);
417 STATIC_SGI const char *sgi_get_bootfile(void);
418 STATIC_SGI void sgi_set_bootfile(const char* aFile);
419 STATIC_SGI void create_sgiinfo(void);
420 STATIC_SGI void sgi_write_table(void);
421 STATIC_SGI void sgi_set_bootpartition(int i);
422 #include "fdisk_sgi.c"
424 STATIC_SUN const char *const sun_sys_types[];
425 STATIC_SUN void sun_delete_partition(int i);
426 STATIC_SUN void sun_change_sysid(int i, int sys);
427 STATIC_SUN void sun_list_table(int xtra);
428 STATIC_SUN void add_sun_partition(int n, int sys);
429 #if ENABLE_FEATURE_FDISK_ADVANCED
430 STATIC_SUN void sun_set_alt_cyl(void);
431 STATIC_SUN void sun_set_ncyl(int cyl);
432 STATIC_SUN void sun_set_xcyl(void);
433 STATIC_SUN void sun_set_ilfact(void);
434 STATIC_SUN void sun_set_rspeed(void);
435 STATIC_SUN void sun_set_pcylcount(void);
437 STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
438 STATIC_SUN void verify_sun(void);
439 STATIC_SUN void sun_write_table(void);
440 #include "fdisk_sun.c"
442 /* DOS partition types */
444 static const char *const i386_sys_types[] = {
448 "\x05" "Extended", /* DOS 3.3+ extended partition */
449 "\x06" "FAT16", /* DOS 16-bit >=32M */
450 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
451 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
452 "\x0b" "Win95 FAT32",
453 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
454 "\x0e" "Win95 FAT16 (LBA)",
455 "\x0f" "Win95 Ext'd (LBA)",
456 "\x11" "Hidden FAT12",
457 "\x12" "Compaq diagnostics",
458 "\x14" "Hidden FAT16 <32M",
459 "\x16" "Hidden FAT16",
460 "\x17" "Hidden HPFS/NTFS",
461 "\x1b" "Hidden Win95 FAT32",
462 "\x1c" "Hidden W95 FAT32 (LBA)",
463 "\x1e" "Hidden W95 FAT16 (LBA)",
464 "\x3c" "Part.Magic recovery",
465 "\x41" "PPC PReP Boot",
467 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
468 "\x80" "Old Minix", /* Minix 1.4a and earlier */
469 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
470 "\x82" "Linux swap", /* also Solaris */
472 "\x84" "OS/2 hidden C: drive",
473 "\x85" "Linux extended",
474 "\x86" "NTFS volume set",
475 "\x87" "NTFS volume set",
477 "\x9f" "BSD/OS", /* BSDI */
478 "\xa0" "Thinkpad hibernation",
479 "\xa5" "FreeBSD", /* various BSD flavours */
483 "\xab" "Darwin boot",
486 "\xbe" "Solaris boot",
488 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
489 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
490 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
491 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
492 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
493 autodetect using persistent
495 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
498 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
499 "\x09" "AIX bootable", /* AIX data or Coherent */
501 "\x18" "AST SmartSleep",
504 "\x40" "Venix 80286",
506 "\x4e" "QNX4.x 2nd part",
507 "\x4f" "QNX4.x 3rd part",
509 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
510 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
511 "\x53" "OnTrack DM6 Aux3",
515 "\x5c" "Priam Edisk",
517 "\x64" "Novell Netware 286",
518 "\x65" "Novell Netware 386",
519 "\x70" "DiskSecure Multi-Boot",
522 "\x94" "Amoeba BBT", /* (bad block table) */
524 "\xbb" "Boot Wizard hidden",
525 "\xc1" "DRDOS/sec (FAT-12)",
526 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
527 "\xc6" "DRDOS/sec (FAT-16)",
529 "\xda" "Non-FS data",
530 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
531 Concurrent DOS or CTOS */
532 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
533 "\xdf" "BootIt", /* BootIt EMBRM */
534 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
535 extended partition */
536 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
537 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
538 partition < 1024 cyl. */
540 "\xf4" "SpeedStor", /* SpeedStor large partition */
541 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
542 "\xff" "BBT", /* Xenix Bad Block Table */
548 #if ENABLE_FEATURE_FDISK_WRITABLE
549 /* start_sect and nr_sects are stored little endian on all machines */
550 /* moreover, they are not aligned correctly */
552 store4_little_endian(unsigned char *cp, unsigned val)
559 #endif /* FEATURE_FDISK_WRITABLE */
562 read4_little_endian(const unsigned char *cp)
564 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
567 #if ENABLE_FEATURE_FDISK_WRITABLE
569 set_start_sect(struct partition *p, unsigned start_sect)
571 store4_little_endian(p->start4, start_sect);
576 get_start_sect(const struct partition *p)
578 return read4_little_endian(p->start4);
581 #if ENABLE_FEATURE_FDISK_WRITABLE
583 set_nr_sects(struct partition *p, unsigned nr_sects)
585 store4_little_endian(p->size4, nr_sects);
590 get_nr_sects(const struct partition *p)
592 return read4_little_endian(p->size4);
595 /* normally O_RDWR, -l option gives O_RDONLY */
596 static int type_open = O_RDWR;
599 static int ext_index; /* the prime extended partition */
600 static int listing; /* no aborts for fdisk -l */
601 static int dos_compatible_flag = ~0;
602 #if ENABLE_FEATURE_FDISK_WRITABLE
603 static int dos_changed;
604 static int nowarn; /* no warnings for fdisk -l/-s */
609 static unsigned user_cylinders, user_heads, user_sectors;
610 static unsigned pt_heads, pt_sectors;
611 static unsigned kern_heads, kern_sectors;
613 static off_t extended_offset; /* offset of link pointers */
615 static unsigned long long total_number_of_sectors;
618 static jmp_buf listingbuf;
620 static void fdisk_fatal(enum failure why)
626 longjmp(listingbuf, 1);
631 message = "cannot open %s";
634 message = "cannot read from %s";
637 message = "cannot seek on %s";
639 case unable_to_write:
640 message = "cannot write to %s";
643 message = "BLKGETSIZE ioctl failed on %s";
646 message = "fatal error";
649 bb_error_msg_and_die(message, disk_device);
653 seek_sector(off_t secno)
655 off_t offset = secno * sector_size;
656 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
657 fdisk_fatal(unable_to_seek);
660 #if ENABLE_FEATURE_FDISK_WRITABLE
662 write_sector(off_t secno, char *buf)
665 if (write(fd, buf, sector_size) != sector_size)
666 fdisk_fatal(unable_to_write);
670 /* Allocate a buffer and read a partition table sector */
672 read_pte(struct pte *pe, off_t offset)
675 pe->sectorbuffer = xmalloc(sector_size);
677 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
678 fdisk_fatal(unable_to_read);
679 #if ENABLE_FEATURE_FDISK_WRITABLE
682 pe->part_table = pe->ext_pointer = NULL;
686 get_partition_start(const struct pte *pe)
688 return pe->offset + get_start_sect(pe->part_table);
691 #if ENABLE_FEATURE_FDISK_WRITABLE
693 * Avoid warning about DOS partitions when no DOS partition was changed.
694 * Here a heuristic "is probably dos partition".
695 * We might also do the opposite and warn in all cases except
696 * for "is probably nondos partition".
699 is_dos_partition(int t)
701 return (t == 1 || t == 4 || t == 6 ||
702 t == 0x0b || t == 0x0c || t == 0x0e ||
703 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
704 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
705 t == 0xc1 || t == 0xc4 || t == 0xc6);
711 puts("Command Action");
713 puts("a\ttoggle a read only flag"); /* sun */
714 puts("b\tedit bsd disklabel");
715 puts("c\ttoggle the mountable flag"); /* sun */
716 puts("d\tdelete a partition");
717 puts("l\tlist known partition types");
718 puts("n\tadd a new partition");
719 puts("o\tcreate a new empty DOS partition table");
720 puts("p\tprint the partition table");
721 puts("q\tquit without saving changes");
722 puts("s\tcreate a new empty Sun disklabel"); /* sun */
723 puts("t\tchange a partition's system id");
724 puts("u\tchange display/entry units");
725 puts("v\tverify the partition table");
726 puts("w\twrite table to disk and exit");
727 #if ENABLE_FEATURE_FDISK_ADVANCED
728 puts("x\textra functionality (experts only)");
730 } else if (LABEL_IS_SGI) {
731 puts("a\tselect bootable partition"); /* sgi flavour */
732 puts("b\tedit bootfile entry"); /* sgi */
733 puts("c\tselect sgi swap partition"); /* sgi flavour */
734 puts("d\tdelete a partition");
735 puts("l\tlist known partition types");
736 puts("n\tadd a new partition");
737 puts("o\tcreate a new empty DOS partition table");
738 puts("p\tprint the partition table");
739 puts("q\tquit without saving changes");
740 puts("s\tcreate a new empty Sun disklabel"); /* sun */
741 puts("t\tchange a partition's system id");
742 puts("u\tchange display/entry units");
743 puts("v\tverify the partition table");
744 puts("w\twrite table to disk and exit");
745 } else if (LABEL_IS_AIX) {
746 puts("o\tcreate a new empty DOS partition table");
747 puts("q\tquit without saving changes");
748 puts("s\tcreate a new empty Sun disklabel"); /* sun */
750 puts("a\ttoggle a bootable flag");
751 puts("b\tedit bsd disklabel");
752 puts("c\ttoggle the dos compatibility flag");
753 puts("d\tdelete a partition");
754 puts("l\tlist known partition types");
755 puts("n\tadd a new partition");
756 puts("o\tcreate a new empty DOS partition table");
757 puts("p\tprint the partition table");
758 puts("q\tquit without saving changes");
759 puts("s\tcreate a new empty Sun disklabel"); /* sun */
760 puts("t\tchange a partition's system id");
761 puts("u\tchange display/entry units");
762 puts("v\tverify the partition table");
763 puts("w\twrite table to disk and exit");
764 #if ENABLE_FEATURE_FDISK_ADVANCED
765 puts("x\textra functionality (experts only)");
769 #endif /* FEATURE_FDISK_WRITABLE */
772 #if ENABLE_FEATURE_FDISK_ADVANCED
776 puts("Command Action");
778 puts("a\tchange number of alternate cylinders"); /*sun*/
779 puts("c\tchange number of cylinders");
780 puts("d\tprint the raw data in the partition table");
781 puts("e\tchange number of extra sectors per cylinder");/*sun*/
782 puts("h\tchange number of heads");
783 puts("i\tchange interleave factor"); /*sun*/
784 puts("o\tchange rotation speed (rpm)"); /*sun*/
785 puts("p\tprint the partition table");
786 puts("q\tquit without saving changes");
787 puts("r\treturn to main menu");
788 puts("s\tchange number of sectors/track");
789 puts("v\tverify the partition table");
790 puts("w\twrite table to disk and exit");
791 puts("y\tchange number of physical cylinders"); /*sun*/
792 } else if (LABEL_IS_SGI) {
793 puts("b\tmove beginning of data in a partition"); /* !sun */
794 puts("c\tchange number of cylinders");
795 puts("d\tprint the raw data in the partition table");
796 puts("e\tlist extended partitions"); /* !sun */
797 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
798 puts("h\tchange number of heads");
799 puts("p\tprint the partition table");
800 puts("q\tquit without saving changes");
801 puts("r\treturn to main menu");
802 puts("s\tchange number of sectors/track");
803 puts("v\tverify the partition table");
804 puts("w\twrite table to disk and exit");
805 } else if (LABEL_IS_AIX) {
806 puts("b\tmove beginning of data in a partition"); /* !sun */
807 puts("c\tchange number of cylinders");
808 puts("d\tprint the raw data in the partition table");
809 puts("e\tlist extended partitions"); /* !sun */
810 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
811 puts("h\tchange number of heads");
812 puts("p\tprint the partition table");
813 puts("q\tquit without saving changes");
814 puts("r\treturn to main menu");
815 puts("s\tchange number of sectors/track");
816 puts("v\tverify the partition table");
817 puts("w\twrite table to disk and exit");
819 puts("b\tmove beginning of data in a partition"); /* !sun */
820 puts("c\tchange number of cylinders");
821 puts("d\tprint the raw data in the partition table");
822 puts("e\tlist extended partitions"); /* !sun */
823 puts("f\tfix partition order"); /* !sun, !aix, !sgi */
824 #if ENABLE_FEATURE_SGI_LABEL
825 puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
827 puts("h\tchange number of heads");
828 puts("p\tprint the partition table");
829 puts("q\tquit without saving changes");
830 puts("r\treturn to main menu");
831 puts("s\tchange number of sectors/track");
832 puts("v\tverify the partition table");
833 puts("w\twrite table to disk and exit");
836 #endif /* ADVANCED mode */
838 #if ENABLE_FEATURE_FDISK_WRITABLE
839 static const char *const *
843 LABEL_IS_SUN ? sun_sys_types :
844 LABEL_IS_SGI ? sgi_sys_types :
848 #define get_sys_types() i386_sys_types
849 #endif /* FEATURE_FDISK_WRITABLE */
852 partition_type(unsigned char type)
855 const char *const *types = get_sys_types();
857 for (i = 0; types[i]; i++)
858 if ((unsigned char)types[i][0] == type)
865 #if ENABLE_FEATURE_FDISK_WRITABLE
869 return LABEL_IS_SUN ? sunlabel->infos[i].id :
870 (LABEL_IS_SGI ? sgi_get_sysid(i) :
871 ptes[i].part_table->sys_ind);
875 list_types(const char *const *sys)
880 unsigned done, next, size;
883 for (size = 0; sys[size]; size++) /* */;
886 for (i = COLS-1; i >= 0; i--) {
887 done += (size + i - done) / (i + 1);
888 last[COLS-1 - i] = done;
893 printf("%c%2x %-22.22s", i ? ' ' : '\n',
894 (unsigned char)sys[next][0],
896 next = last[i++] + done;
897 if (i >= COLS || next >= last[i]) {
901 } while (done < last[0]);
904 #endif /* FEATURE_FDISK_WRITABLE */
907 is_cleared_partition(const struct partition *p)
909 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
910 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
911 get_start_sect(p) || get_nr_sects(p));
915 clear_partition(struct partition *p)
919 memset(p, 0, sizeof(struct partition));
922 #if ENABLE_FEATURE_FDISK_WRITABLE
924 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
930 p = ptes[i].ext_pointer;
931 offset = extended_offset;
933 p = ptes[i].part_table;
934 offset = ptes[i].offset;
938 set_start_sect(p, start - offset);
939 set_nr_sects(p, stop - start + 1);
940 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
941 start = heads*sectors*1024 - 1;
942 set_hsc(p->head, p->sector, p->cyl, start);
943 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
944 stop = heads*sectors*1024 - 1;
945 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
953 if (heads && sectors && cylinders)
956 printf("Unknown value(s) for:");
962 printf(" cylinders");
964 #if ENABLE_FEATURE_FDISK_WRITABLE
965 " (settable in the extra functions menu)"
974 int cyl_units = heads * sectors;
976 if (display_in_cyl_units && cyl_units)
977 units_per_sector = cyl_units;
979 units_per_sector = 1; /* in sectors */
982 #if ENABLE_FEATURE_FDISK_WRITABLE
986 if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
988 "The number of cylinders for this disk is set to %d.\n"
989 "There is nothing wrong with that, but this is larger than 1024,\n"
990 "and could in certain setups cause problems with:\n"
991 "1) software that runs at boot time (e.g., old versions of LILO)\n"
992 "2) booting and partitioning software from other OSs\n"
993 " (e.g., DOS FDISK, OS/2 FDISK)\n",
999 read_extended(int ext)
1003 struct partition *p, *q;
1007 pex->ext_pointer = pex->part_table;
1009 p = pex->part_table;
1010 if (!get_start_sect(p)) {
1011 printf("Bad offset in primary extended partition\n");
1015 while (IS_EXTENDED(p->sys_ind)) {
1016 struct pte *pe = &ptes[partitions];
1018 if (partitions >= MAXIMUM_PARTS) {
1019 /* This is not a Linux restriction, but
1020 this program uses arrays of size MAXIMUM_PARTS.
1021 Do not try to 'improve' this test. */
1022 struct pte *pre = &ptes[partitions-1];
1023 #if ENABLE_FEATURE_FDISK_WRITABLE
1024 printf("Warning: deleting partitions after %d\n",
1028 clear_partition(pre->ext_pointer);
1032 read_pte(pe, extended_offset + get_start_sect(p));
1034 if (!extended_offset)
1035 extended_offset = get_start_sect(p);
1037 q = p = pt_offset(pe->sectorbuffer, 0);
1038 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
1039 if (IS_EXTENDED(p->sys_ind)) {
1040 if (pe->ext_pointer)
1041 printf("Warning: extra link "
1042 "pointer in partition table"
1043 " %d\n", partitions + 1);
1045 pe->ext_pointer = p;
1046 } else if (p->sys_ind) {
1048 printf("Warning: ignoring extra "
1049 "data in partition table"
1050 " %d\n", partitions + 1);
1056 /* very strange code here... */
1057 if (!pe->part_table) {
1058 if (q != pe->ext_pointer)
1061 pe->part_table = q + 1;
1063 if (!pe->ext_pointer) {
1064 if (q != pe->part_table)
1065 pe->ext_pointer = q;
1067 pe->ext_pointer = q + 1;
1070 p = pe->ext_pointer;
1074 #if ENABLE_FEATURE_FDISK_WRITABLE
1075 /* remove empty links */
1077 for (i = 4; i < partitions; i++) {
1078 struct pte *pe = &ptes[i];
1080 if (!get_nr_sects(pe->part_table)
1081 && (partitions > 5 || ptes[4].part_table->sys_ind)
1083 printf("Omitting empty partition (%d)\n", i+1);
1084 delete_partition(i);
1085 goto remove; /* numbering changed */
1091 #if ENABLE_FEATURE_FDISK_WRITABLE
1093 create_doslabel(void)
1097 printf(msg_building_new_label, "DOS disklabel");
1099 current_label_type = label_dos;
1101 #if ENABLE_FEATURE_OSF_LABEL
1102 possibly_osf_label = 0;
1106 for (i = 510-64; i < 510; i++)
1108 write_part_table_flag(MBRbuffer);
1109 extended_offset = 0;
1110 set_all_unchanged();
1112 get_boot(create_empty_dos);
1114 #endif /* FEATURE_FDISK_WRITABLE */
1117 get_sectorsize(void)
1119 if (!user_set_sector_size) {
1121 if (ioctl(fd, BLKSSZGET, &arg) == 0)
1123 if (sector_size != DEFAULT_SECTOR_SIZE)
1124 printf("Note: sector size is %d (not %d)\n",
1125 sector_size, DEFAULT_SECTOR_SIZE);
1130 get_kernel_geometry(void)
1132 struct hd_geometry geometry;
1134 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
1135 kern_heads = geometry.heads;
1136 kern_sectors = geometry.sectors;
1137 /* never use geometry.cylinders - it is truncated */
1142 get_partition_table_geometry(void)
1144 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
1145 struct partition *p;
1146 int i, h, s, hh, ss;
1150 if (!(valid_part_table_flag((char*)bufp)))
1154 for (i = 0; i < 4; i++) {
1155 p = pt_offset(bufp, i);
1156 if (p->sys_ind != 0) {
1157 h = p->end_head + 1;
1158 s = (p->end_sector & 077);
1163 } else if (hh != h || ss != s)
1168 if (!first && !bad) {
1178 unsigned long long bytes; /* really u64 */
1181 sec_fac = sector_size / 512;
1182 #if ENABLE_FEATURE_SUN_LABEL
1183 guess_device_type();
1185 heads = cylinders = sectors = 0;
1186 kern_heads = kern_sectors = 0;
1187 pt_heads = pt_sectors = 0;
1189 get_kernel_geometry();
1190 get_partition_table_geometry();
1192 heads = user_heads ? user_heads :
1193 pt_heads ? pt_heads :
1194 kern_heads ? kern_heads : 255;
1195 sectors = user_sectors ? user_sectors :
1196 pt_sectors ? pt_sectors :
1197 kern_sectors ? kern_sectors : 63;
1198 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
1201 unsigned long longsectors;
1203 if (ioctl(fd, BLKGETSIZE, &longsectors))
1205 bytes = ((unsigned long long) longsectors) << 9;
1208 total_number_of_sectors = (bytes >> 9);
1211 if (dos_compatible_flag)
1212 sector_offset = sectors;
1214 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
1216 cylinders = user_cylinders;
1220 * Read MBR. Returns:
1221 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1222 * 0: found or created label
1226 get_boot(enum action what)
1232 for (i = 0; i < 4; i++) {
1233 struct pte *pe = &ptes[i];
1235 pe->part_table = pt_offset(MBRbuffer, i);
1236 pe->ext_pointer = NULL;
1238 pe->sectorbuffer = MBRbuffer;
1239 #if ENABLE_FEATURE_FDISK_WRITABLE
1240 pe->changed = (what == create_empty_dos);
1244 #if ENABLE_FEATURE_SUN_LABEL
1245 if (what == create_empty_sun && check_sun_label())
1249 memset(MBRbuffer, 0, 512);
1251 #if ENABLE_FEATURE_FDISK_WRITABLE
1252 if (what == create_empty_dos)
1253 goto got_dos_table; /* skip reading disk */
1255 fd = open(disk_device, type_open);
1257 fd = open(disk_device, O_RDONLY);
1259 if (what == try_only)
1261 fdisk_fatal(unable_to_open);
1263 printf("You will not be able to write "
1264 "the partition table\n");
1267 if (512 != read(fd, MBRbuffer, 512)) {
1268 if (what == try_only)
1270 fdisk_fatal(unable_to_read);
1273 fd = open(disk_device, O_RDONLY);
1276 if (512 != read(fd, MBRbuffer, 512))
1284 #if ENABLE_FEATURE_SUN_LABEL
1285 if (check_sun_label())
1289 #if ENABLE_FEATURE_SGI_LABEL
1290 if (check_sgi_label())
1294 #if ENABLE_FEATURE_AIX_LABEL
1295 if (check_aix_label())
1299 #if ENABLE_FEATURE_OSF_LABEL
1300 if (check_osf_label()) {
1301 possibly_osf_label = 1;
1302 if (!valid_part_table_flag(MBRbuffer)) {
1303 current_label_type = label_osf;
1306 printf("This disk has both DOS and BSD magic.\n"
1307 "Give the 'b' command to go to BSD mode.\n");
1311 #if ENABLE_FEATURE_FDISK_WRITABLE
1315 if (!valid_part_table_flag(MBRbuffer)) {
1316 #if !ENABLE_FEATURE_FDISK_WRITABLE
1321 printf("Device contains neither a valid DOS "
1322 "partition table, nor Sun, SGI or OSF "
1325 #if ENABLE_FEATURE_SUN_LABEL
1334 case create_empty_dos:
1335 #if ENABLE_FEATURE_SUN_LABEL
1336 case create_empty_sun:
1340 bb_error_msg_and_die("internal error");
1342 #endif /* FEATURE_FDISK_WRITABLE */
1345 #if ENABLE_FEATURE_FDISK_WRITABLE
1350 for (i = 0; i < 4; i++) {
1351 struct pte *pe = &ptes[i];
1353 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1354 if (partitions != 4)
1355 printf("Ignoring extra extended "
1356 "partition %d\n", i + 1);
1362 for (i = 3; i < partitions; i++) {
1363 struct pte *pe = &ptes[i];
1365 if (!valid_part_table_flag(pe->sectorbuffer)) {
1366 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1367 "table %d will be corrected by w(rite)\n",
1368 pe->sectorbuffer[510],
1369 pe->sectorbuffer[511],
1371 #if ENABLE_FEATURE_FDISK_WRITABLE
1380 #if ENABLE_FEATURE_FDISK_WRITABLE
1382 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1383 * If the user hits Enter, DFLT is returned.
1384 * Answers like +10 are interpreted as offsets from BASE.
1386 * There is no default if DFLT is not between LOW and HIGH.
1389 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1393 const char *fmt = "%s (%u-%u, default %u): ";
1395 if (dflt < low || dflt > high) {
1396 fmt = "%s (%u-%u): ";
1401 int use_default = default_ok;
1403 /* ask question and read answer */
1405 printf(fmt, mesg, low, high, dflt);
1406 read_maybe_empty("");
1407 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1408 && *line_ptr != '-' && *line_ptr != '+');
1410 if (*line_ptr == '+' || *line_ptr == '-') {
1411 int minus = (*line_ptr == '-');
1414 i = atoi(line_ptr + 1);
1416 while (isdigit(*++line_ptr))
1419 switch (*line_ptr) {
1422 if (!display_in_cyl_units)
1423 i *= heads * sectors;
1437 absolute = 1000000000;
1443 unsigned long long bytes;
1446 bytes = (unsigned long long) i * absolute;
1447 unit = sector_size * units_per_sector;
1448 bytes += unit/2; /* round */
1457 while (isdigit(*line_ptr)) {
1464 printf("Using default value %u\n", i);
1466 if (i >= low && i <= high)
1468 printf("Value is out of range\n");
1474 get_partition(int warn, int max)
1479 i = read_int(1, 0, max, 0, "Partition number") - 1;
1483 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1484 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1485 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1487 printf("Warning: partition %d has empty type\n", i+1);
1494 get_existing_partition(int warn, int max)
1499 for (i = 0; i < max; i++) {
1500 struct pte *pe = &ptes[i];
1501 struct partition *p = pe->part_table;
1503 if (p && !is_cleared_partition(p)) {
1510 printf("Selected partition %d\n", pno+1);
1513 printf("No partition is defined yet!\n");
1517 return get_partition(warn, max);
1521 get_nonexisting_partition(int warn, int max)
1526 for (i = 0; i < max; i++) {
1527 struct pte *pe = &ptes[i];
1528 struct partition *p = pe->part_table;
1530 if (p && is_cleared_partition(p)) {
1537 printf("Selected partition %d\n", pno+1);
1540 printf("All primary partitions have been defined already!\n");
1544 return get_partition(warn, max);
1551 display_in_cyl_units = !display_in_cyl_units;
1553 printf("Changing display/entry units to %s\n",
1558 toggle_active(int i)
1560 struct pte *pe = &ptes[i];
1561 struct partition *p = pe->part_table;
1563 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1564 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1565 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1570 toggle_dos_compatibility_flag(void)
1572 dos_compatible_flag = ~dos_compatible_flag;
1573 if (dos_compatible_flag) {
1574 sector_offset = sectors;
1575 printf("DOS Compatibility flag is set\n");
1578 printf("DOS Compatibility flag is not set\n");
1583 delete_partition(int i)
1585 struct pte *pe = &ptes[i];
1586 struct partition *p = pe->part_table;
1587 struct partition *q = pe->ext_pointer;
1589 /* Note that for the fifth partition (i == 4) we don't actually
1590 * decrement partitions.
1593 if (warn_geometry())
1594 return; /* C/H/S not set */
1598 sun_delete_partition(i);
1602 sgi_delete_partition(i);
1607 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1609 ptes[ext_index].ext_pointer = NULL;
1610 extended_offset = 0;
1616 if (!q->sys_ind && i > 4) {
1617 /* the last one in the chain - just delete */
1620 clear_partition(ptes[i].ext_pointer);
1621 ptes[i].changed = 1;
1623 /* not the last one - further ones will be moved down */
1625 /* delete this link in the chain */
1626 p = ptes[i-1].ext_pointer;
1628 set_start_sect(p, get_start_sect(q));
1629 set_nr_sects(p, get_nr_sects(q));
1630 ptes[i-1].changed = 1;
1631 } else if (partitions > 5) { /* 5 will be moved to 4 */
1632 /* the first logical in a longer chain */
1635 if (pe->part_table) /* prevent SEGFAULT */
1636 set_start_sect(pe->part_table,
1637 get_partition_start(pe) -
1639 pe->offset = extended_offset;
1643 if (partitions > 5) {
1645 while (i < partitions) {
1646 ptes[i] = ptes[i+1];
1650 /* the only logical: clear only */
1651 clear_partition(ptes[i].part_table);
1658 int i, sys, origsys;
1659 struct partition *p;
1661 /* If sgi_label then don't use get_existing_partition,
1662 let the user select a partition, since get_existing_partition()
1663 only works for Linux like partition tables. */
1664 if (!LABEL_IS_SGI) {
1665 i = get_existing_partition(0, partitions);
1667 i = get_partition(0, partitions);
1671 p = ptes[i].part_table;
1672 origsys = sys = get_sysid(i);
1674 /* if changing types T to 0 is allowed, then
1675 the reverse change must be allowed, too */
1676 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1677 printf("Partition %d does not exist yet!\n", i + 1);
1681 sys = read_hex(get_sys_types());
1683 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1684 printf("Type 0 means free space to many systems\n"
1685 "(but not to Linux). Having partitions of\n"
1686 "type 0 is probably unwise.\n");
1690 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1691 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1692 printf("You cannot change a partition into"
1693 " an extended one or vice versa\n");
1699 #if ENABLE_FEATURE_SUN_LABEL
1700 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1701 printf("Consider leaving partition 3 "
1702 "as Whole disk (5),\n"
1703 "as SunOS/Solaris expects it and "
1704 "even Linux likes it\n\n");
1706 #if ENABLE_FEATURE_SGI_LABEL
1709 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1710 (i == 8 && sys != 0)
1713 printf("Consider leaving partition 9 "
1714 "as volume header (0),\nand "
1715 "partition 11 as entire volume (6)"
1716 "as IRIX expects it\n\n");
1722 sun_change_sysid(i, sys);
1723 } else if (LABEL_IS_SGI) {
1724 sgi_change_sysid(i, sys);
1728 printf("Changed system type of partition %d "
1729 "to %x (%s)\n", i + 1, sys,
1730 partition_type(sys));
1731 ptes[i].changed = 1;
1732 if (is_dos_partition(origsys) ||
1733 is_dos_partition(sys))
1739 #endif /* FEATURE_FDISK_WRITABLE */
1742 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1743 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1744 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1745 * Lubkin Oct. 1991). */
1748 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1750 int spc = heads * sectors;
1755 *s = ls % sectors + 1; /* sectors count from 1 */
1759 check_consistency(const struct partition *p, int partition)
1761 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1762 unsigned pec, peh, pes; /* physical ending c, h, s */
1763 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1764 unsigned lec, leh, les; /* logical ending c, h, s */
1766 if (!heads || !sectors || (partition >= 4))
1767 return; /* do not check extended partitions */
1769 /* physical beginning c, h, s */
1770 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1772 pbs = p->sector & 0x3f;
1774 /* physical ending c, h, s */
1775 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1777 pes = p->end_sector & 0x3f;
1779 /* compute logical beginning (c, h, s) */
1780 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1782 /* compute logical ending (c, h, s) */
1783 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1785 /* Same physical / logical beginning? */
1786 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1787 printf("Partition %d has different physical/logical "
1788 "beginnings (non-Linux?):\n", partition + 1);
1789 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1790 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1793 /* Same physical / logical ending? */
1794 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1795 printf("Partition %d has different physical/logical "
1796 "endings:\n", partition + 1);
1797 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1798 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1801 /* Ending on cylinder boundary? */
1802 if (peh != (heads - 1) || pes != sectors) {
1803 printf("Partition %i does not end on cylinder boundary\n",
1809 list_disk_geometry(void)
1811 long long bytes = (total_number_of_sectors << 9);
1812 long megabytes = bytes/1000000;
1814 if (megabytes < 10000)
1815 printf("\nDisk %s: %ld MB, %lld bytes\n",
1816 disk_device, megabytes, bytes);
1818 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1819 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1820 printf("%d heads, %d sectors/track, %d cylinders",
1821 heads, sectors, cylinders);
1822 if (units_per_sector == 1)
1823 printf(", total %llu sectors",
1824 total_number_of_sectors / (sector_size/512));
1825 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1827 units_per_sector, sector_size, units_per_sector * sector_size);
1831 * Check whether partition entries are ordered by their starting positions.
1832 * Return 0 if OK. Return i if partition i should have been earlier.
1833 * Two separate checks: primary and logical partitions.
1836 wrong_p_order(int *prev)
1838 const struct pte *pe;
1839 const struct partition *p;
1840 off_t last_p_start_pos = 0, p_start_pos;
1843 for (i = 0 ; i < partitions; i++) {
1846 last_p_start_pos = 0;
1849 if ((p = pe->part_table)->sys_ind) {
1850 p_start_pos = get_partition_start(pe);
1852 if (last_p_start_pos > p_start_pos) {
1858 last_p_start_pos = p_start_pos;
1865 #if ENABLE_FEATURE_FDISK_ADVANCED
1867 * Fix the chain of logicals.
1868 * extended_offset is unchanged, the set of sectors used is unchanged
1869 * The chain is sorted so that sectors increase, and so that
1870 * starting sectors increase.
1872 * After this it may still be that cfdisk doesnt like the table.
1873 * (This is because cfdisk considers expanded parts, from link to
1874 * end of partition, and these may still overlap.)
1876 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1880 fix_chain_of_logicals(void)
1882 int j, oj, ojj, sj, sjj;
1883 struct partition *pj,*pjj,tmp;
1885 /* Stage 1: sort sectors but leave sector of part 4 */
1886 /* (Its sector is the global extended_offset.) */
1888 for (j = 5; j < partitions-1; j++) {
1889 oj = ptes[j].offset;
1890 ojj = ptes[j+1].offset;
1892 ptes[j].offset = ojj;
1893 ptes[j+1].offset = oj;
1894 pj = ptes[j].part_table;
1895 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1896 pjj = ptes[j+1].part_table;
1897 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1898 set_start_sect(ptes[j-1].ext_pointer,
1899 ojj-extended_offset);
1900 set_start_sect(ptes[j].ext_pointer,
1901 oj-extended_offset);
1906 /* Stage 2: sort starting sectors */
1908 for (j = 4; j < partitions-1; j++) {
1909 pj = ptes[j].part_table;
1910 pjj = ptes[j+1].part_table;
1911 sj = get_start_sect(pj);
1912 sjj = get_start_sect(pjj);
1913 oj = ptes[j].offset;
1914 ojj = ptes[j+1].offset;
1915 if (oj+sj > ojj+sjj) {
1919 set_start_sect(pj, ojj+sjj-oj);
1920 set_start_sect(pjj, oj+sj-ojj);
1925 /* Probably something was changed */
1926 for (j = 4; j < partitions; j++)
1927 ptes[j].changed = 1;
1932 fix_partition_table_order(void)
1934 struct pte *pei, *pek;
1937 if (!wrong_p_order(NULL)) {
1938 printf("Ordering is already correct\n\n");
1942 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1943 /* partition i should have come earlier, move it */
1944 /* We have to move data in the MBR */
1945 struct partition *pi, *pk, *pe, pbuf;
1949 pe = pei->ext_pointer;
1950 pei->ext_pointer = pek->ext_pointer;
1951 pek->ext_pointer = pe;
1953 pi = pei->part_table;
1954 pk = pek->part_table;
1956 memmove(&pbuf, pi, sizeof(struct partition));
1957 memmove(pi, pk, sizeof(struct partition));
1958 memmove(pk, &pbuf, sizeof(struct partition));
1960 pei->changed = pek->changed = 1;
1964 fix_chain_of_logicals();
1972 list_table(int xtra)
1974 const struct partition *p;
1978 sun_list_table(xtra);
1982 sgi_list_table(xtra);
1986 list_disk_geometry();
1989 xbsd_print_disklabel(xtra);
1993 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1994 but if the device name ends in a digit, say /dev/foo1,
1995 then the partition is called /dev/foo1p3. */
1996 w = strlen(disk_device);
1997 if (w && isdigit(disk_device[w-1]))
2002 // 1 12345678901 12345678901 12345678901 12
2003 printf("%*s Boot Start End Blocks Id System\n",
2006 for (i = 0; i < partitions; i++) {
2007 const struct pte *pe = &ptes[i];
2013 if (!p || is_cleared_partition(p))
2016 psects = get_nr_sects(p);
2020 if (sector_size < 1024) {
2021 pblocks /= (1024 / sector_size);
2022 podd = psects % (1024 / sector_size);
2024 if (sector_size > 1024)
2025 pblocks *= (sector_size / 1024);
2027 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2028 partname(disk_device, i+1, w+2),
2029 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2031 (unsigned long long) cround(get_partition_start(pe)), /* start */
2032 (unsigned long long) cround(get_partition_start(pe) + psects /* end */
2033 - (psects ? 1 : 0)),
2034 (unsigned long long) pblocks, podd ? '+' : ' ', /* odd flag on end */
2035 p->sys_ind, /* type id */
2036 partition_type(p->sys_ind)); /* type name */
2038 check_consistency(p, i);
2041 /* Is partition table in disk order? It need not be, but... */
2042 /* partition table entries are not checked for correct order if this
2043 is a sgi, sun or aix labeled disk... */
2044 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2046 printf("\nPartition table entries are not in disk order\n");
2050 #if ENABLE_FEATURE_FDISK_ADVANCED
2052 x_list_table(int extend)
2054 const struct pte *pe;
2055 const struct partition *p;
2058 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2059 disk_device, heads, sectors, cylinders);
2060 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2061 for (i = 0 ; i < partitions; i++) {
2063 p = (extend ? pe->ext_pointer : pe->part_table);
2065 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2066 i + 1, p->boot_ind, p->head,
2068 cylinder(p->sector, p->cyl), p->end_head,
2069 sector(p->end_sector),
2070 cylinder(p->end_sector, p->end_cyl),
2071 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2073 check_consistency(p, i);
2079 #if ENABLE_FEATURE_FDISK_WRITABLE
2081 fill_bounds(off_t *first, off_t *last)
2084 const struct pte *pe = &ptes[0];
2085 const struct partition *p;
2087 for (i = 0; i < partitions; pe++,i++) {
2089 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2090 first[i] = 0xffffffff;
2093 first[i] = get_partition_start(pe);
2094 last[i] = first[i] + get_nr_sects(p) - 1;
2100 check(int n, unsigned h, unsigned s, unsigned c, off_t start)
2102 off_t total, real_s, real_c;
2104 real_s = sector(s) - 1;
2105 real_c = cylinder(s, c);
2106 total = (real_c * sectors + real_s) * heads + h;
2108 printf("Partition %d contains sector 0\n", n);
2110 printf("Partition %d: head %d greater than maximum %d\n",
2112 if (real_s >= sectors)
2113 printf("Partition %d: sector %d greater than "
2114 "maximum %d\n", n, s, sectors);
2115 if (real_c >= cylinders)
2116 printf("Partition %d: cylinder %"OFF_FMT"u greater than "
2117 "maximum %d\n", n, real_c + 1, cylinders);
2118 if (cylinders <= 1024 && start != total)
2119 printf("Partition %d: previous sectors %"OFF_FMT"u disagrees with "
2120 "total %"OFF_FMT"u\n", n, start, total);
2128 off_t first[partitions], last[partitions];
2129 struct partition *p;
2131 if (warn_geometry())
2143 fill_bounds(first, last);
2144 for (i = 0; i < partitions; i++) {
2145 struct pte *pe = &ptes[i];
2148 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2149 check_consistency(p, i);
2150 if (get_partition_start(pe) < first[i])
2151 printf("Warning: bad start-of-data in "
2152 "partition %d\n", i + 1);
2153 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2155 total += last[i] + 1 - first[i];
2156 for (j = 0; j < i; j++) {
2157 if ((first[i] >= first[j] && first[i] <= last[j])
2158 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2159 printf("Warning: partition %d overlaps "
2160 "partition %d\n", j + 1, i + 1);
2161 total += first[i] >= first[j] ?
2162 first[i] : first[j];
2163 total -= last[i] <= last[j] ?
2170 if (extended_offset) {
2171 struct pte *pex = &ptes[ext_index];
2172 off_t e_last = get_start_sect(pex->part_table) +
2173 get_nr_sects(pex->part_table) - 1;
2175 for (i = 4; i < partitions; i++) {
2177 p = ptes[i].part_table;
2179 if (i != 4 || i + 1 < partitions)
2180 printf("Warning: partition %d "
2181 "is empty\n", i + 1);
2182 } else if (first[i] < extended_offset || last[i] > e_last) {
2183 printf("Logical partition %d not entirely in "
2184 "partition %d\n", i + 1, ext_index + 1);
2189 if (total > heads * sectors * cylinders)
2190 printf("Total allocated sectors %d greater than the maximum "
2191 "%d\n", total, heads * sectors * cylinders);
2193 total = heads * sectors * cylinders - total;
2195 printf("%d unallocated sectors\n", total);
2200 add_partition(int n, int sys)
2202 char mesg[256]; /* 48 does not suffice in Japanese */
2203 int i, num_read = 0;
2204 struct partition *p = ptes[n].part_table;
2205 struct partition *q = ptes[ext_index].part_table;
2207 off_t start, stop = 0, limit, temp,
2208 first[partitions], last[partitions];
2210 if (p && p->sys_ind) {
2211 printf(msg_part_already_defined, n + 1);
2214 fill_bounds(first, last);
2216 start = sector_offset;
2217 if (display_in_cyl_units || !total_number_of_sectors)
2218 llimit = heads * sectors * cylinders - 1;
2220 llimit = total_number_of_sectors - 1;
2222 if (limit != llimit)
2224 if (extended_offset) {
2225 first[ext_index] = extended_offset;
2226 last[ext_index] = get_start_sect(q) +
2227 get_nr_sects(q) - 1;
2230 start = extended_offset + sector_offset;
2231 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2233 if (display_in_cyl_units)
2234 for (i = 0; i < partitions; i++)
2235 first[i] = (cround(first[i]) - 1) * units_per_sector;
2237 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2240 for (i = 0; i < partitions; i++) {
2243 if (start == ptes[i].offset)
2244 start += sector_offset;
2245 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2246 if (start >= first[i] && start <= lastplusoff)
2247 start = lastplusoff + 1;
2251 if (start >= temp+units_per_sector && num_read) {
2252 printf("Sector %"OFF_FMT"d is already allocated\n", temp);
2256 if (!num_read && start == temp) {
2259 saved_start = start;
2260 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2262 if (display_in_cyl_units) {
2263 start = (start - 1) * units_per_sector;
2264 if (start < saved_start) start = saved_start;
2268 } while (start != temp || !num_read);
2269 if (n > 4) { /* NOT for fifth partition */
2270 struct pte *pe = &ptes[n];
2272 pe->offset = start - sector_offset;
2273 if (pe->offset == extended_offset) { /* must be corrected */
2275 if (sector_offset == 1)
2280 for (i = 0; i < partitions; i++) {
2281 struct pte *pe = &ptes[i];
2283 if (start < pe->offset && limit >= pe->offset)
2284 limit = pe->offset - 1;
2285 if (start < first[i] && limit >= first[i])
2286 limit = first[i] - 1;
2288 if (start > limit) {
2289 printf("No free sectors available\n");
2294 if (cround(start) == cround(limit)) {
2297 snprintf(mesg, sizeof(mesg),
2298 "Last %s or +size or +sizeM or +sizeK",
2299 str_units(SINGULAR));
2300 stop = read_int(cround(start), cround(limit), cround(limit),
2301 cround(start), mesg);
2302 if (display_in_cyl_units) {
2303 stop = stop * units_per_sector - 1;
2309 set_partition(n, 0, start, stop, sys);
2311 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2313 if (IS_EXTENDED(sys)) {
2314 struct pte *pe4 = &ptes[4];
2315 struct pte *pen = &ptes[n];
2318 pen->ext_pointer = p;
2319 pe4->offset = extended_offset = start;
2320 pe4->sectorbuffer = xzalloc(sector_size);
2321 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2322 pe4->ext_pointer = pe4->part_table + 1;
2331 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2332 struct pte *pe = &ptes[partitions];
2334 pe->sectorbuffer = xzalloc(sector_size);
2335 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2336 pe->ext_pointer = pe->part_table + 1;
2341 add_partition(partitions - 1, LINUX_NATIVE);
2347 int i, free_primary = 0;
2349 if (warn_geometry())
2353 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2357 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2361 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2362 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2363 "table first (use 'o'). This will destroy the present disk contents.\n");
2367 for (i = 0; i < 4; i++)
2368 free_primary += !ptes[i].part_table->sys_ind;
2370 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2371 printf("The maximum number of partitions has been created\n");
2375 if (!free_primary) {
2376 if (extended_offset)
2379 printf("You must delete some partition and add "
2380 "an extended partition first\n");
2382 char c, line[LINE_LENGTH];
2383 snprintf(line, sizeof(line),
2386 " p primary partition (1-4)\n",
2388 "l logical (5 or over)" : "e extended"));
2390 c = read_nonempty(line);
2391 if (c == 'p' || c == 'P') {
2392 i = get_nonexisting_partition(0, 4);
2394 add_partition(i, LINUX_NATIVE);
2397 if (c == 'l' && extended_offset) {
2401 if (c == 'e' && !extended_offset) {
2402 i = get_nonexisting_partition(0, 4);
2404 add_partition(i, EXTENDED);
2407 printf("Invalid partition number "
2408 "for type '%c'\n", c);
2419 for (i = 0; i < 3; i++)
2420 if (ptes[i].changed)
2421 ptes[3].changed = 1;
2422 for (i = 3; i < partitions; i++) {
2423 struct pte *pe = &ptes[i];
2426 write_part_table_flag(pe->sectorbuffer);
2427 write_sector(pe->offset, pe->sectorbuffer);
2431 else if (LABEL_IS_SGI) {
2432 /* no test on change? the printf below might be mistaken */
2435 else if (LABEL_IS_SUN) {
2438 for (i = 0; i < 8; i++)
2439 if (ptes[i].changed)
2445 printf("The partition table has been altered!\n\n");
2446 reread_partition_table(1);
2450 reread_partition_table(int leave)
2454 printf("Calling ioctl() to re-read partition table\n");
2456 /* sleep(2); Huh? */
2457 i = ioctl(fd, BLKRRPART);
2460 /* some kernel versions (1.2.x) seem to have trouble
2461 rereading the partition table, but if asked to do it
2462 twice, the second time works. - biro@yggdrasil.com */
2465 i = ioctl(fd, BLKRRPART);
2470 bb_perror_msg("WARNING: rereading partition table "
2471 "failed, kernel still uses old table");
2477 "\nWARNING: If you have created or modified any DOS 6.x\n"
2478 "partitions, please see the fdisk manual page for additional\n"
2483 if (ENABLE_FEATURE_CLEAN_UP)
2488 #endif /* FEATURE_FDISK_WRITABLE */
2490 #if ENABLE_FEATURE_FDISK_ADVANCED
2491 #define MAX_PER_LINE 16
2493 print_buffer(char *pbuffer)
2497 for (i = 0, l = 0; i < sector_size; i++, l++) {
2499 printf("0x%03X:", i);
2500 printf(" %02X", (unsigned char) pbuffer[i]);
2501 if (l == MAX_PER_LINE - 1) {
2516 printf("Device: %s\n", disk_device);
2517 if (LABEL_IS_SGI || LABEL_IS_SUN)
2518 print_buffer(MBRbuffer);
2520 for (i = 3; i < partitions; i++)
2521 print_buffer(ptes[i].sectorbuffer);
2528 struct pte *pe = &ptes[i];
2529 struct partition *p = pe->part_table;
2532 if (warn_geometry())
2534 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2535 printf("Partition %d has no data area\n", i + 1);
2538 first = get_partition_start(pe);
2539 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2540 "New beginning of data") - pe->offset;
2542 if (new != get_nr_sects(p)) {
2543 first = get_nr_sects(p) + get_start_sect(p) - new;
2544 set_nr_sects(p, first);
2545 set_start_sect(p, new);
2557 c = tolower(read_nonempty("Expert command (m for help): "));
2565 move_begin(get_partition(0, partitions));
2568 user_cylinders = cylinders =
2569 read_int(1, cylinders, 1048576, 0,
2570 "Number of cylinders");
2572 sun_set_ncyl(cylinders);
2582 else if (LABEL_IS_SUN)
2584 else if (LABEL_IS_DOS)
2589 fix_partition_table_order();
2592 #if ENABLE_FEATURE_SGI_LABEL
2597 user_heads = heads = read_int(1, heads, 256, 0,
2622 user_sectors = sectors = read_int(1, sectors, 63, 0,
2623 "Number of sectors");
2624 if (dos_compatible_flag) {
2625 sector_offset = sectors;
2626 printf("Warning: setting sector offset for DOS "
2635 write_table(); /* does not return */
2639 sun_set_pcylcount();
2646 #endif /* ADVANCED mode */
2649 is_ide_cdrom_or_tape(const char *device)
2653 struct stat statbuf;
2656 /* No device was given explicitly, and we are trying some
2657 likely things. But opening /dev/hdc may produce errors like
2658 "hdc: tray open or drive not ready"
2659 if it happens to be a CD-ROM drive. It even happens that
2660 the process hangs on the attempt to read a music CD.
2661 So try to be careful. This only works since 2.1.73. */
2663 if (strncmp("/dev/hd", device, 7))
2666 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2667 procf = fopen(buf, "r");
2668 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2669 is_ide = (!strncmp(buf, "cdrom", 5) ||
2670 !strncmp(buf, "tape", 4));
2672 /* Now when this proc file does not exist, skip the
2673 device when it is read-only. */
2674 if (stat(device, &statbuf) == 0)
2675 is_ide = ((statbuf.st_mode & 0222) == 0);
2684 trydev(const char *device, int user_specified)
2688 disk_device = device;
2689 if (setjmp(listingbuf))
2691 if (!user_specified)
2692 if (is_ide_cdrom_or_tape(device))
2694 fd = open(disk_device, type_open);
2696 gb = get_boot(try_only);
2697 if (gb > 0) { /* I/O error */
2699 } else if (gb < 0) { /* no DOS signature */
2700 list_disk_geometry();
2704 #if ENABLE_FEATURE_OSF_LABEL
2705 if (bsd_trydev(device) < 0)
2707 printf("Disk %s doesn't contain a valid "
2708 "partition table\n", device);
2713 #if ENABLE_FEATURE_FDISK_WRITABLE
2714 if (!LABEL_IS_SUN && partitions > 4){
2715 delete_partition(ext_index);
2720 /* Ignore other errors, since we try IDE
2721 and SCSI hard disks which may not be
2722 installed on the system. */
2723 if (errno == EACCES) {
2724 printf("Cannot open %s\n", device);
2730 /* for fdisk -l: try all things in /proc/partitions
2731 that look like a partition name (do not end in a digit) */
2736 char line[100], ptname[100], devname[120], *s;
2739 procpt = fopen_or_warn("/proc/partitions", "r");
2741 while (fgets(line, sizeof(line), procpt)) {
2742 if (sscanf(line, " %d %d %d %[^\n ]",
2743 &ma, &mi, &sz, ptname) != 4)
2745 for (s = ptname; *s; s++);
2748 sprintf(devname, "/dev/%s", ptname);
2751 #if ENABLE_FEATURE_CLEAN_UP
2756 #if ENABLE_FEATURE_FDISK_WRITABLE
2758 unknown_command(int c)
2760 printf("%c: unknown command\n", c);
2764 void BUG_fdisk_globals_overflow(void);
2766 int fdisk_main(int argc, char **argv);
2767 int fdisk_main(int argc, char **argv)
2769 char *str_b, *str_C, *str_H, *str_S;
2773 * fdisk -l [-b sectorsize] [-u] device ...
2774 * fdisk -s [partition] ...
2775 * fdisk [-b sectorsize] [-u] device
2777 * Options -C, -H, -S set the geometry.
2786 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2789 if (sizeof(G) > sizeof(bb_common_bufsiz1))
2790 BUG_fdisk_globals_overflow();
2792 opt = getopt32(argc, argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2793 &str_b, &str_C, &str_H, &str_S);
2796 if (opt & OPT_b) { // -b
2797 /* Ugly: this sector size is really per device,
2798 so cannot be combined with multiple disks,
2799 and the same goes for the C/H/S options.
2801 sector_size = xatoi_u(str_b);
2802 if (sector_size != 512 && sector_size != 1024 &&
2803 sector_size != 2048)
2806 user_set_sector_size = 1;
2808 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2809 if (opt & OPT_H) { // -H
2810 user_heads = xatoi_u(str_H);
2811 if (user_heads <= 0 || user_heads >= 256)
2814 //if (opt & OPT_l) // -l
2815 if (opt & OPT_S) { // -S
2816 user_sectors = xatoi_u(str_S);
2817 if (user_sectors <= 0 || user_sectors >= 64)
2820 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2821 //if (opt & OPT_s) // -s
2823 if (user_set_sector_size && argc != 1)
2824 printf("Warning: the -b (set sector size) option should"
2825 " be used with one specified device\n");
2827 #if ENABLE_FEATURE_FDISK_WRITABLE
2831 type_open = O_RDONLY;
2834 #if defined(__GNUC__)
2835 /* avoid gcc warning:
2836 variable `k' might be clobbered by `longjmp' */
2840 for (k = 0; k < argc; k++)
2843 /* we no longer have default device names */
2844 /* but, we can use /proc/partitions instead */
2848 #if ENABLE_FEATURE_FDISK_WRITABLE
2852 #if ENABLE_FEATURE_FDISK_BLKSIZE
2858 type_open = O_RDONLY;
2863 for (j = 0; j < argc; j++) {
2864 disk_device = argv[j];
2865 fd = open(disk_device, type_open);
2867 fdisk_fatal(unable_to_open);
2868 if (ioctl(fd, BLKGETSIZE, &size))
2869 fdisk_fatal(ioctl_error);
2872 printf("%ld\n", size/2);
2874 printf("%s: %ld\n", argv[j], size/2);
2880 #if ENABLE_FEATURE_FDISK_WRITABLE
2884 disk_device = argv[0];
2888 /* OSF label, and no DOS label */
2889 printf("Detected an OSF/1 disklabel on %s, entering "
2890 "disklabel mode\n", disk_device);
2892 /*Why do we do this? It seems to be counter-intuitive*/
2893 current_label_type = label_dos;
2894 /* If we return we may want to make an empty DOS label? */
2900 c = tolower(read_nonempty("Command (m for help): "));
2904 toggle_active(get_partition(1, partitions));
2905 else if (LABEL_IS_SUN)
2906 toggle_sunflags(get_partition(1, partitions),
2908 else if (LABEL_IS_SGI)
2909 sgi_set_bootpartition(
2910 get_partition(1, partitions));
2916 printf("\nThe current boot file is: %s\n",
2917 sgi_get_bootfile());
2918 if (read_maybe_empty("Please enter the name of the "
2919 "new boot file: ") == '\n')
2920 printf("Boot file unchanged\n");
2922 sgi_set_bootfile(line_ptr);
2924 #if ENABLE_FEATURE_OSF_LABEL
2931 toggle_dos_compatibility_flag();
2932 else if (LABEL_IS_SUN)
2933 toggle_sunflags(get_partition(1, partitions),
2935 else if (LABEL_IS_SGI)
2936 sgi_set_swappartition(
2937 get_partition(1, partitions));
2944 /* If sgi_label then don't use get_existing_partition,
2945 let the user select a partition, since
2946 get_existing_partition() only works for Linux-like
2948 if (!LABEL_IS_SGI) {
2949 j = get_existing_partition(1, partitions);
2951 j = get_partition(1, partitions);
2954 delete_partition(j);
2963 list_types(get_sys_types());
2982 #if ENABLE_FEATURE_SUN_LABEL
2996 write_table(); /* does not return */
2998 #if ENABLE_FEATURE_FDISK_ADVANCED
3001 printf("\n\tSorry, no experts menu for SGI "
3002 "partition tables available\n\n");
3013 #endif /* FEATURE_FDISK_WRITABLE */