1 /* vi: set sw=4 ts=4: */
2 /* fdisk.c -- Partition table manipulator for Linux.
4 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
10 #ifndef _LARGEFILE64_SOURCE
12 #define _LARGEFILE64_SOURCE
14 #include <assert.h> /* assert */
17 /* Looks like someone forgot to add this to config system */
18 #ifndef ENABLE_FEATURE_FDISK_BLKSIZE
19 # define ENABLE_FEATURE_FDISK_BLKSIZE 0
20 # define USE_FEATURE_FDISK_BLKSIZE(a)
23 #define DEFAULT_SECTOR_SIZE 512
24 #define MAX_SECTOR_SIZE 2048
25 #define SECTOR_SIZE 512 /* still used in osf/sgi/sun code */
26 #define MAXIMUM_PARTS 60
28 #define ACTIVE_FLAG 0x80
31 #define WIN98_EXTENDED 0x0f
32 #define LINUX_PARTITION 0x81
33 #define LINUX_SWAP 0x82
34 #define LINUX_NATIVE 0x83
35 #define LINUX_EXTENDED 0x85
36 #define LINUX_LVM 0x8e
37 #define LINUX_RAID 0xfd
39 /* Used for sector numbers. Today's disk sizes make it necessary */
40 typedef unsigned long long ullong;
44 unsigned char sectors;
45 unsigned short cylinders;
49 #define HDIO_GETGEO 0x0301 /* get device geometry */
51 static const char msg_building_new_label[] ALIGN1 =
52 "Building a new %s. Changes will remain in memory only,\n"
53 "until you decide to write them. After that the previous content\n"
54 "won't be recoverable.\n\n";
56 static const char msg_part_already_defined[] ALIGN1 =
57 "Partition %d is already defined, delete it before re-adding\n";
61 unsigned char boot_ind; /* 0x80 - active */
62 unsigned char head; /* starting head */
63 unsigned char sector; /* starting sector */
64 unsigned char cyl; /* starting cylinder */
65 unsigned char sys_ind; /* What partition type */
66 unsigned char end_head; /* end head */
67 unsigned char end_sector; /* end sector */
68 unsigned char end_cyl; /* end cylinder */
69 unsigned char start4[4]; /* starting sector counting from 0 */
70 unsigned char size4[4]; /* nr of sectors in partition */
73 static const char unable_to_open[] ALIGN1 = "cannot open %s";
74 static const char unable_to_read[] ALIGN1 = "cannot read from %s";
75 static const char unable_to_seek[] ALIGN1 = "cannot seek on %s";
76 static const char unable_to_write[] ALIGN1 = "cannot write to %s";
77 static const char ioctl_error[] ALIGN1 = "BLKGETSIZE ioctl failed on %s";
78 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
81 label_dos, label_sun, label_sgi, label_aix, label_osf
84 #define LABEL_IS_DOS (label_dos == current_label_type)
86 #if ENABLE_FEATURE_SUN_LABEL
87 #define LABEL_IS_SUN (label_sun == current_label_type)
88 #define STATIC_SUN static
90 #define LABEL_IS_SUN 0
91 #define STATIC_SUN extern
94 #if ENABLE_FEATURE_SGI_LABEL
95 #define LABEL_IS_SGI (label_sgi == current_label_type)
96 #define STATIC_SGI static
98 #define LABEL_IS_SGI 0
99 #define STATIC_SGI extern
102 #if ENABLE_FEATURE_AIX_LABEL
103 #define LABEL_IS_AIX (label_aix == current_label_type)
104 #define STATIC_AIX static
106 #define LABEL_IS_AIX 0
107 #define STATIC_AIX extern
110 #if ENABLE_FEATURE_OSF_LABEL
111 #define LABEL_IS_OSF (label_osf == current_label_type)
112 #define STATIC_OSF static
114 #define LABEL_IS_OSF 0
115 #define STATIC_OSF extern
118 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
120 static void update_units(void);
121 #if ENABLE_FEATURE_FDISK_WRITABLE
122 static void change_units(void);
123 static void reread_partition_table(int leave);
124 static void delete_partition(int i);
125 static int get_partition(int warn, int max);
126 static void list_types(const char *const *sys);
127 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
129 static const char *partition_type(unsigned char type);
130 static void get_geometry(void);
131 static int get_boot(enum action what);
136 static unsigned get_start_sect(const struct partition *p);
137 static unsigned get_nr_sects(const struct partition *p);
140 * per partition table entry data
142 * The four primary partitions have the same sectorbuffer (MBRbuffer)
143 * and have NULL ext_pointer.
144 * Each logical partition table entry has two pointers, one for the
145 * partition and one link to the next one.
148 struct partition *part_table; /* points into sectorbuffer */
149 struct partition *ext_pointer; /* points into sectorbuffer */
150 ullong offset; /* disk sector number */
151 char *sectorbuffer; /* disk sector contents */
152 #if ENABLE_FEATURE_FDISK_WRITABLE
153 char changed; /* boolean */
157 /* DOS partition types */
159 static const char *const i386_sys_types[] = {
163 "\x05" "Extended", /* DOS 3.3+ extended partition */
164 "\x06" "FAT16", /* DOS 16-bit >=32M */
165 "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */
166 "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
167 "\x0b" "Win95 FAT32",
168 "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
169 "\x0e" "Win95 FAT16 (LBA)",
170 "\x0f" "Win95 Ext'd (LBA)",
171 "\x11" "Hidden FAT12",
172 "\x12" "Compaq diagnostics",
173 "\x14" "Hidden FAT16 <32M",
174 "\x16" "Hidden FAT16",
175 "\x17" "Hidden HPFS/NTFS",
176 "\x1b" "Hidden Win95 FAT32",
177 "\x1c" "Hidden W95 FAT32 (LBA)",
178 "\x1e" "Hidden W95 FAT16 (LBA)",
179 "\x3c" "Part.Magic recovery",
180 "\x41" "PPC PReP Boot",
182 "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
183 "\x80" "Old Minix", /* Minix 1.4a and earlier */
184 "\x81" "Minix / old Linux",/* Minix 1.4b and later */
185 "\x82" "Linux swap", /* also Solaris */
187 "\x84" "OS/2 hidden C: drive",
188 "\x85" "Linux extended",
189 "\x86" "NTFS volume set",
190 "\x87" "NTFS volume set",
192 "\x9f" "BSD/OS", /* BSDI */
193 "\xa0" "Thinkpad hibernation",
194 "\xa5" "FreeBSD", /* various BSD flavours */
198 "\xab" "Darwin boot",
201 "\xbe" "Solaris boot",
203 "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */
204 "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */
205 "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */
206 "\xf2" "DOS secondary", /* DOS 3.3+ secondary */
207 "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with
208 autodetect using persistent
210 #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
213 "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */
214 "\x09" "AIX bootable", /* AIX data or Coherent */
216 "\x18" "AST SmartSleep",
219 "\x40" "Venix 80286",
221 "\x4e" "QNX4.x 2nd part",
222 "\x4f" "QNX4.x 3rd part",
224 "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
225 "\x52" "CP/M", /* CP/M or Microport SysV/AT */
226 "\x53" "OnTrack DM6 Aux3",
230 "\x5c" "Priam Edisk",
232 "\x64" "Novell Netware 286",
233 "\x65" "Novell Netware 386",
234 "\x70" "DiskSecure Multi-Boot",
237 "\x94" "Amoeba BBT", /* (bad block table) */
239 "\xbb" "Boot Wizard hidden",
240 "\xc1" "DRDOS/sec (FAT-12)",
241 "\xc4" "DRDOS/sec (FAT-16 < 32M)",
242 "\xc6" "DRDOS/sec (FAT-16)",
244 "\xda" "Non-FS data",
245 "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
246 Concurrent DOS or CTOS */
247 "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */
248 "\xdf" "BootIt", /* BootIt EMBRM */
249 "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT
250 extended partition */
251 "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */
252 "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended
253 partition < 1024 cyl. */
255 "\xf4" "SpeedStor", /* SpeedStor large partition */
256 "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */
257 "\xff" "BBT", /* Xenix Bad Block Table */
268 const char *disk_device;
269 int fd; /* the disk */
270 int g_partitions; // = 4; /* maximum partition + 1 */
271 unsigned units_per_sector; // = 1;
272 unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
273 unsigned user_set_sector_size;
274 unsigned sector_offset; // = 1;
275 unsigned g_heads, g_sectors, g_cylinders;
276 enum label_type current_label_type;
277 smallint display_in_cyl_units; // = 1;
278 #if ENABLE_FEATURE_OSF_LABEL
279 smallint possibly_osf_label;
283 char line_buffer[80];
284 char partname_buffer[80];
285 /* Raw disk label. For DOS-type partition tables the MBR,
286 * with descriptions of the primary partitions. */
287 char MBRbuffer[MAX_SECTOR_SIZE];
288 /* Partition tables */
289 struct pte ptes[MAXIMUM_PARTS];
291 #define G (*ptr_to_globals)
292 #define line_ptr (G.line_ptr)
293 #define disk_device (G.disk_device )
295 #define g_partitions (G.g_partitions )
296 #define units_per_sector (G.units_per_sector )
297 #define sector_size (G.sector_size )
298 #define user_set_sector_size (G.user_set_sector_size)
299 #define sector_offset (G.sector_offset )
300 #define g_heads (G.g_heads )
301 #define g_sectors (G.g_sectors )
302 #define g_cylinders (G.g_cylinders )
303 #define current_label_type (G.current_label_type )
304 #define display_in_cyl_units (G.display_in_cyl_units)
305 #define possibly_osf_label (G.possibly_osf_label )
306 #define listingbuf (G.listingbuf)
307 #define line_buffer (G.line_buffer)
308 #define partname_buffer (G.partname_buffer)
309 #define MBRbuffer (G.MBRbuffer)
310 #define ptes (G.ptes)
311 #define INIT_G() do { \
312 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
313 sector_size = DEFAULT_SECTOR_SIZE; \
316 display_in_cyl_units = 1; \
317 units_per_sector = 1; \
321 #define IS_EXTENDED(i) \
322 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
324 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
326 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
328 #define pt_offset(b, n) \
329 ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
331 #define sector(s) ((s) & 0x3f)
333 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
335 #define hsc2sector(h,s,c) \
336 (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
338 #define set_hsc(h,s,c,sector) \
340 s = sector % g_sectors + 1; \
341 sector /= g_sectors; \
342 h = sector % g_heads; \
345 s |= (sector >> 2) & 0xc0; \
348 #if ENABLE_FEATURE_FDISK_WRITABLE
349 /* read line; return 0 or first printable char */
351 read_line(const char *prompt)
355 sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
357 exit(0); /* Ctrl-D or Ctrl-C */
359 if (line_buffer[sz-1] == '\n')
360 line_buffer[--sz] = '\0';
362 line_ptr = line_buffer;
363 while (*line_ptr && !isgraph(*line_ptr))
370 * return partition name - uses static storage
373 partname(const char *dev, int pno, int lth)
380 bufp = partname_buffer;
381 bufsiz = sizeof(partname_buffer);
386 if (isdigit(dev[w-1]))
389 /* devfs kludge - note: fdisk partition names are not supposed
390 to equal kernel names, so there is no reason to do this */
391 if (strcmp(dev + w - 4, "disc") == 0) {
399 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
400 lth-wp-2, w, dev, p, pno);
402 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
407 #if ENABLE_FEATURE_FDISK_WRITABLE
409 set_all_unchanged(void)
413 for (i = 0; i < MAXIMUM_PARTS; i++)
417 static ALWAYS_INLINE void
422 #endif /* FEATURE_FDISK_WRITABLE */
424 static ALWAYS_INLINE struct partition *
425 get_part_table(int i)
427 return ptes[i].part_table;
432 { /* n==1: use singular */
434 return display_in_cyl_units ? "cylinder" : "sector";
435 return display_in_cyl_units ? "cylinders" : "sectors";
439 valid_part_table_flag(const char *mbuffer)
441 return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
444 #if ENABLE_FEATURE_FDISK_WRITABLE
445 static ALWAYS_INLINE void
446 write_part_table_flag(char *b)
453 read_nonempty(const char *mesg)
455 while (!read_line(mesg)) /* repeat */;
460 read_maybe_empty(const char *mesg)
462 if (!read_line(mesg)) {
463 line_ptr = line_buffer;
471 read_hex(const char *const *sys)
475 read_nonempty("Hex code (type L to list codes): ");
476 if (*line_ptr == 'l' || *line_ptr == 'L') {
480 v = bb_strtoul(line_ptr, NULL, 16);
482 /* Bad input also triggers this */
487 #endif /* FEATURE_FDISK_WRITABLE */
489 #include "fdisk_aix.c"
492 unsigned char info[128]; /* Informative text string */
493 unsigned char spare0[14];
495 unsigned char spare1;
497 unsigned char spare2;
500 unsigned char spare1[246]; /* Boot information etc. */
501 unsigned short rspeed; /* Disk rotational speed */
502 unsigned short pcylcount; /* Physical cylinder count */
503 unsigned short sparecyl; /* extra sects per cylinder */
504 unsigned char spare2[4]; /* More magic... */
505 unsigned short ilfact; /* Interleave factor */
506 unsigned short ncyl; /* Data cylinder count */
507 unsigned short nacyl; /* Alt. cylinder count */
508 unsigned short ntrks; /* Tracks per cylinder */
509 unsigned short nsect; /* Sectors per track */
510 unsigned char spare3[4]; /* Even more magic... */
511 struct sun_partinfo {
512 uint32_t start_cylinder;
513 uint32_t num_sectors;
515 unsigned short magic; /* Magic number */
516 unsigned short csum; /* Label xor'd checksum */
518 #define sunlabel ((sun_partition *)MBRbuffer)
519 STATIC_OSF void bsd_select(void);
520 STATIC_OSF void xbsd_print_disklabel(int);
521 #include "fdisk_osf.c"
523 #if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
525 fdisk_swap16(uint16_t x)
527 return (x << 8) | (x >> 8);
531 fdisk_swap32(uint32_t x)
534 ((x & 0xFF00) << 8) |
535 ((x & 0xFF0000) >> 8) |
540 STATIC_SGI const char *const sgi_sys_types[];
541 STATIC_SGI unsigned sgi_get_num_sectors(int i);
542 STATIC_SGI int sgi_get_sysid(int i);
543 STATIC_SGI void sgi_delete_partition(int i);
544 STATIC_SGI void sgi_change_sysid(int i, int sys);
545 STATIC_SGI void sgi_list_table(int xtra);
546 #if ENABLE_FEATURE_FDISK_ADVANCED
547 STATIC_SGI void sgi_set_xcyl(void);
549 STATIC_SGI int verify_sgi(int verbose);
550 STATIC_SGI void sgi_add_partition(int n, int sys);
551 STATIC_SGI void sgi_set_swappartition(int i);
552 STATIC_SGI const char *sgi_get_bootfile(void);
553 STATIC_SGI void sgi_set_bootfile(const char* aFile);
554 STATIC_SGI void create_sgiinfo(void);
555 STATIC_SGI void sgi_write_table(void);
556 STATIC_SGI void sgi_set_bootpartition(int i);
557 #include "fdisk_sgi.c"
559 STATIC_SUN const char *const sun_sys_types[];
560 STATIC_SUN void sun_delete_partition(int i);
561 STATIC_SUN void sun_change_sysid(int i, int sys);
562 STATIC_SUN void sun_list_table(int xtra);
563 STATIC_SUN void add_sun_partition(int n, int sys);
564 #if ENABLE_FEATURE_FDISK_ADVANCED
565 STATIC_SUN void sun_set_alt_cyl(void);
566 STATIC_SUN void sun_set_ncyl(int cyl);
567 STATIC_SUN void sun_set_xcyl(void);
568 STATIC_SUN void sun_set_ilfact(void);
569 STATIC_SUN void sun_set_rspeed(void);
570 STATIC_SUN void sun_set_pcylcount(void);
572 STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
573 STATIC_SUN void verify_sun(void);
574 STATIC_SUN void sun_write_table(void);
575 #include "fdisk_sun.c"
577 #if ENABLE_FEATURE_FDISK_WRITABLE
578 /* start_sect and nr_sects are stored little endian on all machines */
579 /* moreover, they are not aligned correctly */
581 store4_little_endian(unsigned char *cp, unsigned val)
588 #endif /* FEATURE_FDISK_WRITABLE */
591 read4_little_endian(const unsigned char *cp)
593 return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
596 #if ENABLE_FEATURE_FDISK_WRITABLE
598 set_start_sect(struct partition *p, unsigned start_sect)
600 store4_little_endian(p->start4, start_sect);
605 get_start_sect(const struct partition *p)
607 return read4_little_endian(p->start4);
610 #if ENABLE_FEATURE_FDISK_WRITABLE
612 set_nr_sects(struct partition *p, unsigned nr_sects)
614 store4_little_endian(p->size4, nr_sects);
619 get_nr_sects(const struct partition *p)
621 return read4_little_endian(p->size4);
624 /* normally O_RDWR, -l option gives O_RDONLY */
625 static int type_open = O_RDWR;
627 static int ext_index; /* the prime extended partition */
628 static smallint listing; /* no aborts for fdisk -l */
629 static int dos_compatible_flag = ~0;
630 #if ENABLE_FEATURE_FDISK_WRITABLE
631 //static int dos_changed;
632 static smallint nowarn; /* no warnings for fdisk -l/-s */
635 static unsigned user_cylinders, user_heads, user_sectors;
636 static unsigned pt_heads, pt_sectors;
637 static unsigned kern_heads, kern_sectors;
639 static ullong extended_offset; /* offset of link pointers */
640 static ullong total_number_of_sectors;
642 static void fdisk_fatal(const char *why)
646 longjmp(listingbuf, 1);
648 bb_error_msg_and_die(why, disk_device);
652 seek_sector(ullong secno)
654 secno *= sector_size;
655 #if ENABLE_FDISK_SUPPORT_LARGE_DISKS
656 if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
657 fdisk_fatal(unable_to_seek);
659 if (secno > MAXINT(off_t)
660 || lseek(fd, (off_t)secno, SEEK_SET) == (off_t) -1
662 fdisk_fatal(unable_to_seek);
667 #if ENABLE_FEATURE_FDISK_WRITABLE
669 write_sector(ullong 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, ullong 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, ullong start, ullong 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 / (g_sectors * g_heads) > 1023))
948 start = g_heads * g_sectors * 1024 - 1;
949 set_hsc(p->head, p->sector, p->cyl, start);
950 if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
951 stop = g_heads * g_sectors * 1024 - 1;
952 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
960 if (g_heads && g_sectors && g_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 = g_heads * g_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 && g_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[g_partitions];
1025 if (g_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[g_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", g_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", g_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 < g_partitions; i++) {
1085 struct pte *pe = &ptes[i];
1087 if (!get_nr_sects(pe->part_table)
1088 && (g_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) {
1188 sec_fac = sector_size / 512;
1189 #if ENABLE_FEATURE_SUN_LABEL
1190 guess_device_type();
1192 g_heads = g_cylinders = g_sectors = 0;
1193 kern_heads = kern_sectors = 0;
1194 pt_heads = pt_sectors = 0;
1196 get_kernel_geometry();
1197 get_partition_table_geometry();
1199 g_heads = user_heads ? user_heads :
1200 pt_heads ? pt_heads :
1201 kern_heads ? kern_heads : 255;
1202 g_sectors = user_sectors ? user_sectors :
1203 pt_sectors ? pt_sectors :
1204 kern_sectors ? kern_sectors : 63;
1205 if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
1206 /* got bytes, convert to 512 byte sectors */
1207 total_number_of_sectors = (v64 >> 9);
1209 unsigned long longsectors; /* need temp of type long */
1210 if (ioctl(fd, BLKGETSIZE, &longsectors))
1212 total_number_of_sectors = longsectors;
1216 if (dos_compatible_flag)
1217 sector_offset = g_sectors;
1219 g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
1221 g_cylinders = user_cylinders;
1225 * Read MBR. Returns:
1226 * -1: no 0xaa55 flag present (possibly entire disk BSD)
1227 * 0: found or created label
1231 get_boot(enum action what)
1237 for (i = 0; i < 4; i++) {
1238 struct pte *pe = &ptes[i];
1240 pe->part_table = pt_offset(MBRbuffer, i);
1241 pe->ext_pointer = NULL;
1243 pe->sectorbuffer = MBRbuffer;
1244 #if ENABLE_FEATURE_FDISK_WRITABLE
1245 pe->changed = (what == create_empty_dos);
1249 #if ENABLE_FEATURE_SUN_LABEL
1250 if (what == create_empty_sun && check_sun_label())
1254 memset(MBRbuffer, 0, 512);
1256 #if ENABLE_FEATURE_FDISK_WRITABLE
1257 if (what == create_empty_dos)
1258 goto got_dos_table; /* skip reading disk */
1260 fd = open(disk_device, type_open);
1262 fd = open(disk_device, O_RDONLY);
1264 if (what == try_only)
1266 fdisk_fatal(unable_to_open);
1268 printf("You will not be able to write "
1269 "the partition table\n");
1272 if (512 != read(fd, MBRbuffer, 512)) {
1273 if (what == try_only)
1275 fdisk_fatal(unable_to_read);
1278 fd = open(disk_device, O_RDONLY);
1281 if (512 != read(fd, MBRbuffer, 512))
1289 #if ENABLE_FEATURE_SUN_LABEL
1290 if (check_sun_label())
1294 #if ENABLE_FEATURE_SGI_LABEL
1295 if (check_sgi_label())
1299 #if ENABLE_FEATURE_AIX_LABEL
1300 if (check_aix_label())
1304 #if ENABLE_FEATURE_OSF_LABEL
1305 if (check_osf_label()) {
1306 possibly_osf_label = 1;
1307 if (!valid_part_table_flag(MBRbuffer)) {
1308 current_label_type = label_osf;
1311 printf("This disk has both DOS and BSD magic.\n"
1312 "Give the 'b' command to go to BSD mode.\n");
1316 #if ENABLE_FEATURE_FDISK_WRITABLE
1320 if (!valid_part_table_flag(MBRbuffer)) {
1321 #if !ENABLE_FEATURE_FDISK_WRITABLE
1326 printf("Device contains neither a valid DOS "
1327 "partition table, nor Sun, SGI or OSF "
1330 #if ENABLE_FEATURE_SUN_LABEL
1339 case create_empty_dos:
1340 #if ENABLE_FEATURE_SUN_LABEL
1341 case create_empty_sun:
1345 bb_error_msg_and_die("internal error");
1347 #endif /* FEATURE_FDISK_WRITABLE */
1350 #if ENABLE_FEATURE_FDISK_WRITABLE
1355 for (i = 0; i < 4; i++) {
1356 struct pte *pe = &ptes[i];
1358 if (IS_EXTENDED(pe->part_table->sys_ind)) {
1359 if (g_partitions != 4)
1360 printf("Ignoring extra extended "
1361 "partition %d\n", i + 1);
1367 for (i = 3; i < g_partitions; i++) {
1368 struct pte *pe = &ptes[i];
1370 if (!valid_part_table_flag(pe->sectorbuffer)) {
1371 printf("Warning: invalid flag 0x%02x,0x%02x of partition "
1372 "table %d will be corrected by w(rite)\n",
1373 pe->sectorbuffer[510],
1374 pe->sectorbuffer[511],
1376 #if ENABLE_FEATURE_FDISK_WRITABLE
1385 #if ENABLE_FEATURE_FDISK_WRITABLE
1387 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1388 * If the user hits Enter, DFLT is returned.
1389 * Answers like +10 are interpreted as offsets from BASE.
1391 * There is no default if DFLT is not between LOW and HIGH.
1394 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
1398 const char *fmt = "%s (%u-%u, default %u): ";
1400 if (dflt < low || dflt > high) {
1401 fmt = "%s (%u-%u): ";
1406 int use_default = default_ok;
1408 /* ask question and read answer */
1410 printf(fmt, mesg, low, high, dflt);
1411 read_maybe_empty("");
1412 } while (*line_ptr != '\n' && !isdigit(*line_ptr)
1413 && *line_ptr != '-' && *line_ptr != '+');
1415 if (*line_ptr == '+' || *line_ptr == '-') {
1416 int minus = (*line_ptr == '-');
1419 i = atoi(line_ptr + 1);
1421 while (isdigit(*++line_ptr))
1424 switch (*line_ptr) {
1427 if (!display_in_cyl_units)
1428 i *= g_heads * g_sectors;
1442 absolute = 1000000000;
1451 bytes = (ullong) i * absolute;
1452 unit = sector_size * units_per_sector;
1453 bytes += unit/2; /* round */
1462 while (isdigit(*line_ptr)) {
1469 printf("Using default value %u\n", i);
1471 if (i >= low && i <= high)
1473 printf("Value is out of range\n");
1479 get_partition(int warn, int max)
1484 i = read_int(1, 0, max, 0, "Partition number") - 1;
1488 if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
1489 || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
1490 || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
1492 printf("Warning: partition %d has empty type\n", i+1);
1499 get_existing_partition(int warn, int max)
1504 for (i = 0; i < max; i++) {
1505 struct pte *pe = &ptes[i];
1506 struct partition *p = pe->part_table;
1508 if (p && !is_cleared_partition(p)) {
1515 printf("Selected partition %d\n", pno+1);
1518 printf("No partition is defined yet!\n");
1522 return get_partition(warn, max);
1526 get_nonexisting_partition(int warn, int max)
1531 for (i = 0; i < max; i++) {
1532 struct pte *pe = &ptes[i];
1533 struct partition *p = pe->part_table;
1535 if (p && is_cleared_partition(p)) {
1542 printf("Selected partition %d\n", pno+1);
1545 printf("All primary partitions have been defined already!\n");
1549 return get_partition(warn, max);
1556 display_in_cyl_units = !display_in_cyl_units;
1558 printf("Changing display/entry units to %s\n",
1563 toggle_active(int i)
1565 struct pte *pe = &ptes[i];
1566 struct partition *p = pe->part_table;
1568 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
1569 printf("WARNING: Partition %d is an extended partition\n", i + 1);
1570 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1575 toggle_dos_compatibility_flag(void)
1577 dos_compatible_flag = ~dos_compatible_flag;
1578 if (dos_compatible_flag) {
1579 sector_offset = g_sectors;
1580 printf("DOS Compatibility flag is set\n");
1583 printf("DOS Compatibility flag is not set\n");
1588 delete_partition(int i)
1590 struct pte *pe = &ptes[i];
1591 struct partition *p = pe->part_table;
1592 struct partition *q = pe->ext_pointer;
1594 /* Note that for the fifth partition (i == 4) we don't actually
1595 * decrement partitions.
1598 if (warn_geometry())
1599 return; /* C/H/S not set */
1603 sun_delete_partition(i);
1607 sgi_delete_partition(i);
1612 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
1614 ptes[ext_index].ext_pointer = NULL;
1615 extended_offset = 0;
1621 if (!q->sys_ind && i > 4) {
1622 /* the last one in the chain - just delete */
1625 clear_partition(ptes[i].ext_pointer);
1626 ptes[i].changed = 1;
1628 /* not the last one - further ones will be moved down */
1630 /* delete this link in the chain */
1631 p = ptes[i-1].ext_pointer;
1633 set_start_sect(p, get_start_sect(q));
1634 set_nr_sects(p, get_nr_sects(q));
1635 ptes[i-1].changed = 1;
1636 } else if (g_partitions > 5) { /* 5 will be moved to 4 */
1637 /* the first logical in a longer chain */
1640 if (pe->part_table) /* prevent SEGFAULT */
1641 set_start_sect(pe->part_table,
1642 get_partition_start(pe) -
1644 pe->offset = extended_offset;
1648 if (g_partitions > 5) {
1650 while (i < g_partitions) {
1651 ptes[i] = ptes[i+1];
1655 /* the only logical: clear only */
1656 clear_partition(ptes[i].part_table);
1663 int i, sys, origsys;
1664 struct partition *p;
1666 /* If sgi_label then don't use get_existing_partition,
1667 let the user select a partition, since get_existing_partition()
1668 only works for Linux like partition tables. */
1669 if (!LABEL_IS_SGI) {
1670 i = get_existing_partition(0, g_partitions);
1672 i = get_partition(0, g_partitions);
1676 p = ptes[i].part_table;
1677 origsys = sys = get_sysid(i);
1679 /* if changing types T to 0 is allowed, then
1680 the reverse change must be allowed, too */
1681 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
1682 printf("Partition %d does not exist yet!\n", i + 1);
1686 sys = read_hex(get_sys_types());
1688 if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
1689 printf("Type 0 means free space to many systems\n"
1690 "(but not to Linux). Having partitions of\n"
1691 "type 0 is probably unwise.\n");
1695 if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
1696 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
1697 printf("You cannot change a partition into"
1698 " an extended one or vice versa\n");
1704 #if ENABLE_FEATURE_SUN_LABEL
1705 if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
1706 printf("Consider leaving partition 3 "
1707 "as Whole disk (5),\n"
1708 "as SunOS/Solaris expects it and "
1709 "even Linux likes it\n\n");
1711 #if ENABLE_FEATURE_SGI_LABEL
1714 (i == 10 && sys != SGI_ENTIRE_DISK) ||
1715 (i == 8 && sys != 0)
1718 printf("Consider leaving partition 9 "
1719 "as volume header (0),\nand "
1720 "partition 11 as entire volume (6)"
1721 "as IRIX expects it\n\n");
1727 sun_change_sysid(i, sys);
1728 } else if (LABEL_IS_SGI) {
1729 sgi_change_sysid(i, sys);
1733 printf("Changed system type of partition %d "
1734 "to %x (%s)\n", i + 1, sys,
1735 partition_type(sys));
1736 ptes[i].changed = 1;
1737 //if (is_dos_partition(origsys) || is_dos_partition(sys))
1743 #endif /* FEATURE_FDISK_WRITABLE */
1746 /* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
1747 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1748 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1749 * Lubkin Oct. 1991). */
1752 linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
1754 int spc = g_heads * g_sectors;
1758 *h = ls / g_sectors;
1759 *s = ls % g_sectors + 1; /* sectors count from 1 */
1763 check_consistency(const struct partition *p, int partition)
1765 unsigned pbc, pbh, pbs; /* physical beginning c, h, s */
1766 unsigned pec, peh, pes; /* physical ending c, h, s */
1767 unsigned lbc, lbh, lbs; /* logical beginning c, h, s */
1768 unsigned lec, leh, les; /* logical ending c, h, s */
1770 if (!g_heads || !g_sectors || (partition >= 4))
1771 return; /* do not check extended partitions */
1773 /* physical beginning c, h, s */
1774 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1776 pbs = p->sector & 0x3f;
1778 /* physical ending c, h, s */
1779 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1781 pes = p->end_sector & 0x3f;
1783 /* compute logical beginning (c, h, s) */
1784 linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1786 /* compute logical ending (c, h, s) */
1787 linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1789 /* Same physical / logical beginning? */
1790 if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1791 printf("Partition %d has different physical/logical "
1792 "beginnings (non-Linux?):\n", partition + 1);
1793 printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
1794 printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
1797 /* Same physical / logical ending? */
1798 if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1799 printf("Partition %d has different physical/logical "
1800 "endings:\n", partition + 1);
1801 printf(" phys=(%d, %d, %d) ", pec, peh, pes);
1802 printf("logical=(%d, %d, %d)\n", lec, leh, les);
1805 /* Ending on cylinder boundary? */
1806 if (peh != (g_heads - 1) || pes != g_sectors) {
1807 printf("Partition %i does not end on cylinder boundary\n",
1813 list_disk_geometry(void)
1815 long long bytes = (total_number_of_sectors << 9);
1816 long megabytes = bytes/1000000;
1818 if (megabytes < 10000)
1819 printf("\nDisk %s: %ld MB, %lld bytes\n",
1820 disk_device, megabytes, bytes);
1822 printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
1823 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
1824 printf("%d heads, %d sectors/track, %d cylinders",
1825 g_heads, g_sectors, g_cylinders);
1826 if (units_per_sector == 1)
1827 printf(", total %llu sectors",
1828 total_number_of_sectors / (sector_size/512));
1829 printf("\nUnits = %s of %d * %d = %d bytes\n\n",
1831 units_per_sector, sector_size, units_per_sector * sector_size);
1835 * Check whether partition entries are ordered by their starting positions.
1836 * Return 0 if OK. Return i if partition i should have been earlier.
1837 * Two separate checks: primary and logical partitions.
1840 wrong_p_order(int *prev)
1842 const struct pte *pe;
1843 const struct partition *p;
1844 ullong last_p_start_pos = 0, p_start_pos;
1847 for (i = 0; i < g_partitions; i++) {
1850 last_p_start_pos = 0;
1855 p_start_pos = get_partition_start(pe);
1857 if (last_p_start_pos > p_start_pos) {
1863 last_p_start_pos = p_start_pos;
1870 #if ENABLE_FEATURE_FDISK_ADVANCED
1872 * Fix the chain of logicals.
1873 * extended_offset is unchanged, the set of sectors used is unchanged
1874 * The chain is sorted so that sectors increase, and so that
1875 * starting sectors increase.
1877 * After this it may still be that cfdisk doesnt like the table.
1878 * (This is because cfdisk considers expanded parts, from link to
1879 * end of partition, and these may still overlap.)
1881 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1885 fix_chain_of_logicals(void)
1887 int j, oj, ojj, sj, sjj;
1888 struct partition *pj,*pjj,tmp;
1890 /* Stage 1: sort sectors but leave sector of part 4 */
1891 /* (Its sector is the global extended_offset.) */
1893 for (j = 5; j < g_partitions - 1; j++) {
1894 oj = ptes[j].offset;
1895 ojj = ptes[j+1].offset;
1897 ptes[j].offset = ojj;
1898 ptes[j+1].offset = oj;
1899 pj = ptes[j].part_table;
1900 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1901 pjj = ptes[j+1].part_table;
1902 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1903 set_start_sect(ptes[j-1].ext_pointer,
1904 ojj-extended_offset);
1905 set_start_sect(ptes[j].ext_pointer,
1906 oj-extended_offset);
1911 /* Stage 2: sort starting sectors */
1913 for (j = 4; j < g_partitions - 1; j++) {
1914 pj = ptes[j].part_table;
1915 pjj = ptes[j+1].part_table;
1916 sj = get_start_sect(pj);
1917 sjj = get_start_sect(pjj);
1918 oj = ptes[j].offset;
1919 ojj = ptes[j+1].offset;
1920 if (oj+sj > ojj+sjj) {
1924 set_start_sect(pj, ojj+sjj-oj);
1925 set_start_sect(pjj, oj+sj-ojj);
1930 /* Probably something was changed */
1931 for (j = 4; j < g_partitions; j++)
1932 ptes[j].changed = 1;
1937 fix_partition_table_order(void)
1939 struct pte *pei, *pek;
1942 if (!wrong_p_order(NULL)) {
1943 printf("Ordering is already correct\n\n");
1947 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1948 /* partition i should have come earlier, move it */
1949 /* We have to move data in the MBR */
1950 struct partition *pi, *pk, *pe, pbuf;
1954 pe = pei->ext_pointer;
1955 pei->ext_pointer = pek->ext_pointer;
1956 pek->ext_pointer = pe;
1958 pi = pei->part_table;
1959 pk = pek->part_table;
1961 memmove(&pbuf, pi, sizeof(struct partition));
1962 memmove(pi, pk, sizeof(struct partition));
1963 memmove(pk, &pbuf, sizeof(struct partition));
1965 pei->changed = pek->changed = 1;
1969 fix_chain_of_logicals();
1977 list_table(int xtra)
1979 const struct partition *p;
1983 sun_list_table(xtra);
1987 sgi_list_table(xtra);
1991 list_disk_geometry();
1994 xbsd_print_disklabel(xtra);
1998 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1999 but if the device name ends in a digit, say /dev/foo1,
2000 then the partition is called /dev/foo1p3. */
2001 w = strlen(disk_device);
2002 if (w && isdigit(disk_device[w-1]))
2007 // 1 12345678901 12345678901 12345678901 12
2008 printf("%*s Boot Start End Blocks Id System\n",
2011 for (i = 0; i < g_partitions; i++) {
2012 const struct pte *pe = &ptes[i];
2018 if (!p || is_cleared_partition(p))
2021 psects = get_nr_sects(p);
2025 if (sector_size < 1024) {
2026 pblocks /= (1024 / sector_size);
2027 podd = psects % (1024 / sector_size);
2029 if (sector_size > 1024)
2030 pblocks *= (sector_size / 1024);
2032 printf("%s %c %11llu %11llu %11llu%c %2x %s\n",
2033 partname(disk_device, i+1, w+2),
2034 !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
2036 (ullong) cround(get_partition_start(pe)), /* start */
2037 (ullong) cround(get_partition_start(pe) + psects /* end */
2038 - (psects ? 1 : 0)),
2039 (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
2040 p->sys_ind, /* type id */
2041 partition_type(p->sys_ind)); /* type name */
2043 check_consistency(p, i);
2046 /* Is partition table in disk order? It need not be, but... */
2047 /* partition table entries are not checked for correct order if this
2048 is a sgi, sun or aix labeled disk... */
2049 if (LABEL_IS_DOS && wrong_p_order(NULL)) {
2051 printf("\nPartition table entries are not in disk order\n");
2055 #if ENABLE_FEATURE_FDISK_ADVANCED
2057 x_list_table(int extend)
2059 const struct pte *pe;
2060 const struct partition *p;
2063 printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
2064 disk_device, g_heads, g_sectors, g_cylinders);
2065 printf("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n");
2066 for (i = 0; i < g_partitions; i++) {
2068 p = (extend ? pe->ext_pointer : pe->part_table);
2070 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
2071 i + 1, p->boot_ind, p->head,
2073 cylinder(p->sector, p->cyl), p->end_head,
2074 sector(p->end_sector),
2075 cylinder(p->end_sector, p->end_cyl),
2076 get_start_sect(p), get_nr_sects(p), p->sys_ind);
2078 check_consistency(p, i);
2084 #if ENABLE_FEATURE_FDISK_WRITABLE
2086 fill_bounds(ullong *first, ullong *last)
2089 const struct pte *pe = &ptes[0];
2090 const struct partition *p;
2092 for (i = 0; i < g_partitions; pe++,i++) {
2094 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
2095 first[i] = 0xffffffff;
2098 first[i] = get_partition_start(pe);
2099 last[i] = first[i] + get_nr_sects(p) - 1;
2105 check(int n, unsigned h, unsigned s, unsigned c, ullong start)
2107 ullong total, real_s, real_c;
2109 real_s = sector(s) - 1;
2110 real_c = cylinder(s, c);
2111 total = (real_c * g_sectors + real_s) * g_heads + h;
2113 printf("Partition %d contains sector 0\n", n);
2115 printf("Partition %d: head %d greater than maximum %d\n",
2117 if (real_s >= g_sectors)
2118 printf("Partition %d: sector %d greater than "
2119 "maximum %d\n", n, s, g_sectors);
2120 if (real_c >= g_cylinders)
2121 printf("Partition %d: cylinder %llu greater than "
2122 "maximum %d\n", n, real_c + 1, g_cylinders);
2123 if (g_cylinders <= 1024 && start != total)
2124 printf("Partition %d: previous sectors %llu disagrees with "
2125 "total %llu\n", n, start, total);
2133 ullong first[g_partitions], last[g_partitions];
2134 struct partition *p;
2136 if (warn_geometry())
2148 fill_bounds(first, last);
2149 for (i = 0; i < g_partitions; i++) {
2150 struct pte *pe = &ptes[i];
2153 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
2154 check_consistency(p, i);
2155 if (get_partition_start(pe) < first[i])
2156 printf("Warning: bad start-of-data in "
2157 "partition %d\n", i + 1);
2158 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
2160 total += last[i] + 1 - first[i];
2161 for (j = 0; j < i; j++) {
2162 if ((first[i] >= first[j] && first[i] <= last[j])
2163 || ((last[i] <= last[j] && last[i] >= first[j]))) {
2164 printf("Warning: partition %d overlaps "
2165 "partition %d\n", j + 1, i + 1);
2166 total += first[i] >= first[j] ?
2167 first[i] : first[j];
2168 total -= last[i] <= last[j] ?
2175 if (extended_offset) {
2176 struct pte *pex = &ptes[ext_index];
2177 ullong e_last = get_start_sect(pex->part_table) +
2178 get_nr_sects(pex->part_table) - 1;
2180 for (i = 4; i < g_partitions; i++) {
2182 p = ptes[i].part_table;
2184 if (i != 4 || i + 1 < g_partitions)
2185 printf("Warning: partition %d "
2186 "is empty\n", i + 1);
2187 } else if (first[i] < extended_offset || last[i] > e_last) {
2188 printf("Logical partition %d not entirely in "
2189 "partition %d\n", i + 1, ext_index + 1);
2194 if (total > g_heads * g_sectors * g_cylinders)
2195 printf("Total allocated sectors %d greater than the maximum "
2196 "%d\n", total, g_heads * g_sectors * g_cylinders);
2198 total = g_heads * g_sectors * g_cylinders - total;
2200 printf("%d unallocated sectors\n", total);
2205 add_partition(int n, int sys)
2207 char mesg[256]; /* 48 does not suffice in Japanese */
2208 int i, num_read = 0;
2209 struct partition *p = ptes[n].part_table;
2210 struct partition *q = ptes[ext_index].part_table;
2212 ullong start, stop = 0;
2213 ullong first[g_partitions], last[g_partitions];
2215 if (p && p->sys_ind) {
2216 printf(msg_part_already_defined, n + 1);
2219 fill_bounds(first, last);
2221 start = sector_offset;
2222 if (display_in_cyl_units || !total_number_of_sectors)
2223 limit = (ullong) g_heads * g_sectors * g_cylinders - 1;
2225 limit = total_number_of_sectors - 1;
2226 if (extended_offset) {
2227 first[ext_index] = extended_offset;
2228 last[ext_index] = get_start_sect(q) +
2229 get_nr_sects(q) - 1;
2232 start = extended_offset + sector_offset;
2233 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2235 if (display_in_cyl_units)
2236 for (i = 0; i < g_partitions; i++)
2237 first[i] = (cround(first[i]) - 1) * units_per_sector;
2239 snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
2242 for (i = 0; i < g_partitions; i++) {
2245 if (start == ptes[i].offset)
2246 start += sector_offset;
2247 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
2248 if (start >= first[i] && start <= lastplusoff)
2249 start = lastplusoff + 1;
2253 if (start >= temp+units_per_sector && num_read) {
2254 printf("Sector %lld is already allocated\n", temp);
2258 if (!num_read && start == temp) {
2261 saved_start = start;
2262 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
2264 if (display_in_cyl_units) {
2265 start = (start - 1) * units_per_sector;
2266 if (start < saved_start) start = saved_start;
2270 } while (start != temp || !num_read);
2271 if (n > 4) { /* NOT for fifth partition */
2272 struct pte *pe = &ptes[n];
2274 pe->offset = start - sector_offset;
2275 if (pe->offset == extended_offset) { /* must be corrected */
2277 if (sector_offset == 1)
2282 for (i = 0; i < g_partitions; i++) {
2283 struct pte *pe = &ptes[i];
2285 if (start < pe->offset && limit >= pe->offset)
2286 limit = pe->offset - 1;
2287 if (start < first[i] && limit >= first[i])
2288 limit = first[i] - 1;
2290 if (start > limit) {
2291 printf("No free sectors available\n");
2296 if (cround(start) == cround(limit)) {
2299 snprintf(mesg, sizeof(mesg),
2300 "Last %s or +size or +sizeM or +sizeK",
2301 str_units(SINGULAR));
2302 stop = read_int(cround(start), cround(limit), cround(limit),
2303 cround(start), mesg);
2304 if (display_in_cyl_units) {
2305 stop = stop * units_per_sector - 1;
2311 set_partition(n, 0, start, stop, sys);
2313 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2315 if (IS_EXTENDED(sys)) {
2316 struct pte *pe4 = &ptes[4];
2317 struct pte *pen = &ptes[n];
2320 pen->ext_pointer = p;
2321 pe4->offset = extended_offset = start;
2322 pe4->sectorbuffer = xzalloc(sector_size);
2323 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2324 pe4->ext_pointer = pe4->part_table + 1;
2333 if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
2334 struct pte *pe = &ptes[g_partitions];
2336 pe->sectorbuffer = xzalloc(sector_size);
2337 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2338 pe->ext_pointer = pe->part_table + 1;
2343 add_partition(g_partitions - 1, LINUX_NATIVE);
2349 int i, free_primary = 0;
2351 if (warn_geometry())
2355 add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2359 sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
2363 printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
2364 "If you want to add DOS-type partitions, create a new empty DOS partition\n"
2365 "table first (use 'o'). This will destroy the present disk contents.\n");
2369 for (i = 0; i < 4; i++)
2370 free_primary += !ptes[i].part_table->sys_ind;
2372 if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
2373 printf("The maximum number of partitions has been created\n");
2377 if (!free_primary) {
2378 if (extended_offset)
2381 printf("You must delete some partition and add "
2382 "an extended partition first\n");
2385 snprintf(line, sizeof(line),
2388 " p primary partition (1-4)\n",
2390 "l logical (5 or over)" : "e extended"));
2392 c = read_nonempty(line);
2393 if (c == 'p' || c == 'P') {
2394 i = get_nonexisting_partition(0, 4);
2396 add_partition(i, LINUX_NATIVE);
2399 if (c == 'l' && extended_offset) {
2403 if (c == 'e' && !extended_offset) {
2404 i = get_nonexisting_partition(0, 4);
2406 add_partition(i, EXTENDED);
2409 printf("Invalid partition number "
2410 "for type '%c'\n", c);
2421 for (i = 0; i < 3; i++)
2422 if (ptes[i].changed)
2423 ptes[3].changed = 1;
2424 for (i = 3; i < g_partitions; i++) {
2425 struct pte *pe = &ptes[i];
2428 write_part_table_flag(pe->sectorbuffer);
2429 write_sector(pe->offset, pe->sectorbuffer);
2433 else if (LABEL_IS_SGI) {
2434 /* no test on change? the printf below might be mistaken */
2437 else if (LABEL_IS_SUN) {
2440 for (i = 0; i < 8; i++)
2441 if (ptes[i].changed)
2447 printf("The partition table has been altered!\n\n");
2448 reread_partition_table(1);
2452 reread_partition_table(int leave)
2456 printf("Calling ioctl() to re-read partition table\n");
2458 /* sleep(2); Huh? */
2459 i = ioctl_or_perror(fd, BLKRRPART, NULL,
2460 "WARNING: rereading partition table "
2461 "failed, kernel still uses old table");
2465 "\nWARNING: If you have created or modified any DOS 6.x\n"
2466 "partitions, please see the fdisk manual page for additional\n"
2471 if (ENABLE_FEATURE_CLEAN_UP)
2476 #endif /* FEATURE_FDISK_WRITABLE */
2478 #if ENABLE_FEATURE_FDISK_ADVANCED
2479 #define MAX_PER_LINE 16
2481 print_buffer(char *pbuffer)
2485 for (i = 0, l = 0; i < sector_size; i++, l++) {
2487 printf("0x%03X:", i);
2488 printf(" %02X", (unsigned char) pbuffer[i]);
2489 if (l == MAX_PER_LINE - 1) {
2504 printf("Device: %s\n", disk_device);
2505 if (LABEL_IS_SGI || LABEL_IS_SUN)
2506 print_buffer(MBRbuffer);
2508 for (i = 3; i < g_partitions; i++)
2509 print_buffer(ptes[i].sectorbuffer);
2516 struct pte *pe = &ptes[i];
2517 struct partition *p = pe->part_table;
2520 if (warn_geometry())
2522 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
2523 printf("Partition %d has no data area\n", i + 1);
2526 first = get_partition_start(pe);
2527 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2528 "New beginning of data") - pe->offset;
2530 if (new != get_nr_sects(p)) {
2531 first = get_nr_sects(p) + get_start_sect(p) - new;
2532 set_nr_sects(p, first);
2533 set_start_sect(p, new);
2545 c = tolower(read_nonempty("Expert command (m for help): "));
2553 move_begin(get_partition(0, g_partitions));
2556 user_cylinders = g_cylinders =
2557 read_int(1, g_cylinders, 1048576, 0,
2558 "Number of cylinders");
2560 sun_set_ncyl(g_cylinders);
2570 else if (LABEL_IS_SUN)
2572 else if (LABEL_IS_DOS)
2577 fix_partition_table_order();
2580 #if ENABLE_FEATURE_SGI_LABEL
2585 user_heads = g_heads = read_int(1, g_heads, 256, 0,
2610 user_sectors = g_sectors = read_int(1, g_sectors, 63, 0,
2611 "Number of sectors");
2612 if (dos_compatible_flag) {
2613 sector_offset = g_sectors;
2614 printf("Warning: setting sector offset for DOS "
2623 write_table(); /* does not return */
2627 sun_set_pcylcount();
2634 #endif /* ADVANCED mode */
2637 is_ide_cdrom_or_tape(const char *device)
2641 struct stat statbuf;
2644 /* No device was given explicitly, and we are trying some
2645 likely things. But opening /dev/hdc may produce errors like
2646 "hdc: tray open or drive not ready"
2647 if it happens to be a CD-ROM drive. It even happens that
2648 the process hangs on the attempt to read a music CD.
2649 So try to be careful. This only works since 2.1.73. */
2651 if (strncmp("/dev/hd", device, 7))
2654 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2655 procf = fopen(buf, "r");
2656 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2657 is_ide = (!strncmp(buf, "cdrom", 5) ||
2658 !strncmp(buf, "tape", 4));
2660 /* Now when this proc file does not exist, skip the
2661 device when it is read-only. */
2662 if (stat(device, &statbuf) == 0)
2663 is_ide = ((statbuf.st_mode & 0222) == 0);
2672 trydev(const char *device, int user_specified)
2676 disk_device = device;
2677 if (setjmp(listingbuf))
2679 if (!user_specified)
2680 if (is_ide_cdrom_or_tape(device))
2682 fd = open(disk_device, type_open);
2684 gb = get_boot(try_only);
2685 if (gb > 0) { /* I/O error */
2687 } else if (gb < 0) { /* no DOS signature */
2688 list_disk_geometry();
2692 #if ENABLE_FEATURE_OSF_LABEL
2693 if (bsd_trydev(device) < 0)
2695 printf("Disk %s doesn't contain a valid "
2696 "partition table\n", device);
2701 #if ENABLE_FEATURE_FDISK_WRITABLE
2702 if (!LABEL_IS_SUN && g_partitions > 4){
2703 delete_partition(ext_index);
2708 /* Ignore other errors, since we try IDE
2709 and SCSI hard disks which may not be
2710 installed on the system. */
2711 if (errno == EACCES) {
2712 printf("Cannot open %s\n", device);
2718 /* for fdisk -l: try all things in /proc/partitions
2719 that look like a partition name (do not end in a digit) */
2724 char line[100], ptname[100], devname[120], *s;
2727 procpt = fopen_or_warn("/proc/partitions", "r");
2729 while (fgets(line, sizeof(line), procpt)) {
2730 if (sscanf(line, " %d %d %d %[^\n ]",
2731 &ma, &mi, &sz, ptname) != 4)
2733 for (s = ptname; *s; s++);
2736 sprintf(devname, "/dev/%s", ptname);
2739 #if ENABLE_FEATURE_CLEAN_UP
2744 #if ENABLE_FEATURE_FDISK_WRITABLE
2746 unknown_command(int c)
2748 printf("%c: unknown command\n", c);
2752 int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2753 int fdisk_main(int argc, char **argv)
2755 char *str_b, *str_C, *str_H, *str_S;
2759 * fdisk -l [-b sectorsize] [-u] device ...
2760 * fdisk -s [partition] ...
2761 * fdisk [-b sectorsize] [-u] device
2763 * Options -C, -H, -S set the geometry.
2772 OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
2777 opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
2778 &str_b, &str_C, &str_H, &str_S);
2781 if (opt & OPT_b) { // -b
2782 /* Ugly: this sector size is really per device,
2783 so cannot be combined with multiple disks,
2784 and the same goes for the C/H/S options.
2786 sector_size = xatoi_u(str_b);
2787 if (sector_size != 512 && sector_size != 1024 &&
2788 sector_size != 2048)
2791 user_set_sector_size = 1;
2793 if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
2794 if (opt & OPT_H) { // -H
2795 user_heads = xatoi_u(str_H);
2796 if (user_heads <= 0 || user_heads >= 256)
2799 //if (opt & OPT_l) // -l
2800 if (opt & OPT_S) { // -S
2801 user_sectors = xatoi_u(str_S);
2802 if (user_sectors <= 0 || user_sectors >= 64)
2805 if (opt & OPT_u) display_in_cyl_units = 0; // -u
2806 //if (opt & OPT_s) // -s
2808 if (user_set_sector_size && argc != 1)
2809 printf("Warning: the -b (set sector size) option should"
2810 " be used with one specified device\n");
2812 #if ENABLE_FEATURE_FDISK_WRITABLE
2816 type_open = O_RDONLY;
2819 #if defined(__GNUC__)
2820 /* avoid gcc warning:
2821 variable `k' might be clobbered by `longjmp' */
2825 for (k = 0; k < argc; k++)
2828 /* we no longer have default device names */
2829 /* but, we can use /proc/partitions instead */
2833 #if ENABLE_FEATURE_FDISK_WRITABLE
2837 #if ENABLE_FEATURE_FDISK_BLKSIZE
2843 type_open = O_RDONLY;
2848 for (j = 0; j < argc; j++) {
2849 disk_device = argv[j];
2850 fd = open(disk_device, type_open);
2852 fdisk_fatal(unable_to_open);
2853 if (ioctl(fd, BLKGETSIZE, &size))
2854 fdisk_fatal(ioctl_error);
2857 printf("%ld\n", size/2);
2859 printf("%s: %ld\n", argv[j], size/2);
2865 #if ENABLE_FEATURE_FDISK_WRITABLE
2869 disk_device = argv[0];
2873 /* OSF label, and no DOS label */
2874 printf("Detected an OSF/1 disklabel on %s, entering "
2875 "disklabel mode\n", disk_device);
2877 /*Why do we do this? It seems to be counter-intuitive*/
2878 current_label_type = label_dos;
2879 /* If we return we may want to make an empty DOS label? */
2885 c = tolower(read_nonempty("Command (m for help): "));
2889 toggle_active(get_partition(1, g_partitions));
2890 else if (LABEL_IS_SUN)
2891 toggle_sunflags(get_partition(1, g_partitions),
2893 else if (LABEL_IS_SGI)
2894 sgi_set_bootpartition(
2895 get_partition(1, g_partitions));
2901 printf("\nThe current boot file is: %s\n",
2902 sgi_get_bootfile());
2903 if (read_maybe_empty("Please enter the name of the "
2904 "new boot file: ") == '\n')
2905 printf("Boot file unchanged\n");
2907 sgi_set_bootfile(line_ptr);
2909 #if ENABLE_FEATURE_OSF_LABEL
2916 toggle_dos_compatibility_flag();
2917 else if (LABEL_IS_SUN)
2918 toggle_sunflags(get_partition(1, g_partitions),
2920 else if (LABEL_IS_SGI)
2921 sgi_set_swappartition(
2922 get_partition(1, g_partitions));
2929 /* If sgi_label then don't use get_existing_partition,
2930 let the user select a partition, since
2931 get_existing_partition() only works for Linux-like
2933 if (!LABEL_IS_SGI) {
2934 j = get_existing_partition(1, g_partitions);
2936 j = get_partition(1, g_partitions);
2939 delete_partition(j);
2948 list_types(get_sys_types());
2967 #if ENABLE_FEATURE_SUN_LABEL
2981 write_table(); /* does not return */
2983 #if ENABLE_FEATURE_FDISK_ADVANCED
2986 printf("\n\tSorry, no experts menu for SGI "
2987 "partition tables available\n\n");
2998 #endif /* FEATURE_FDISK_WRITABLE */