1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
29 #include "wholedisk.h"
31 #include "fdisksunlabel.h"
32 #include "fdisksgilabel.h"
33 #include "fdiskaixlabel.h"
34 #include "fdiskmaclabel.h"
36 #ifdef HAVE_LINUX_COMPILER_H
37 #include <linux/compiler.h>
39 #ifdef HAVE_LINUX_BLKPG_H
40 #include <linux/blkpg.h>
45 static void delete_partition(int i);
47 #define hex_val(c) ({ \
49 isdigit(_c) ? _c - '0' : \
50 tolower(_c) + 10 - 'a'; \
54 #define LINE_LENGTH 800
55 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
56 (n) * sizeof(struct partition)))
57 #define sector(s) ((s) & 0x3f)
58 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
60 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
61 ((h) + heads * cylinder(s,c)))
62 #define set_hsc(h,s,c,sector) { \
63 s = sector % sectors + 1; \
68 s |= (sector >> 2) & 0xc0; \
71 /* A valid partition table sector ends in 0x55 0xaa */
73 part_table_flag(unsigned char *b) {
74 return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8);
78 valid_part_table_flag(unsigned char *b) {
79 return (b[510] == 0x55 && b[511] == 0xaa);
83 write_part_table_flag(unsigned char *b) {
88 /* start_sect and nr_sects are stored little endian on all machines */
89 /* moreover, they are not aligned correctly */
91 store4_little_endian(unsigned char *cp, unsigned int val) {
93 cp[1] = ((val >> 8) & 0xff);
94 cp[2] = ((val >> 16) & 0xff);
95 cp[3] = ((val >> 24) & 0xff);
99 read4_little_endian(const unsigned char *cp) {
100 return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8)
101 + ((unsigned int)(cp[2]) << 16)
102 + ((unsigned int)(cp[3]) << 24);
106 set_start_sect(struct partition *p, unsigned int start_sect) {
107 store4_little_endian(p->start4, start_sect);
111 get_start_sect(struct partition *p) {
112 return read4_little_endian(p->start4);
116 set_nr_sects(struct partition *p, unsigned long long nr_sects) {
117 store4_little_endian(p->size4, nr_sects);
121 get_nr_sects(struct partition *p) {
122 return read4_little_endian(p->size4);
126 xread(int fd, void *buf, size_t count) {
132 rv = read(fd, p, count);
134 if (errno == EINTR || errno == EAGAIN)
136 return out ? out : -1; /* Error */
137 } else if (rv == 0) {
138 return out; /* EOF */
150 get_random_id(void) {
156 fd = open("/dev/urandom", O_RDONLY);
158 rv = xread(fd, &v, sizeof v);
165 /* Fallback: sucks, but better than nothing */
166 gettimeofday(&tv, NULL);
167 return (unsigned int)(tv.tv_sec + (tv.tv_usec << 12) + getpid());
170 /* normally O_RDWR, -l option gives O_RDONLY */
171 static int type_open = O_RDWR;
174 * Raw disk label. For DOS-type partition tables the MBR,
175 * with descriptions of the primary partitions.
177 unsigned char MBRbuffer[MAX_SECTOR_SIZE];
180 * per partition table entry data
182 * The four primary partitions have the same sectorbuffer (MBRbuffer)
183 * and have NULL ext_pointer.
184 * Each logical partition table entry has two pointers, one for the
185 * partition and one link to the next one.
188 struct partition *part_table; /* points into sectorbuffer */
189 struct partition *ext_pointer; /* points into sectorbuffer */
190 char changed; /* boolean */
191 unsigned long long offset; /* disk sector number */
192 unsigned char *sectorbuffer; /* disk sector contents */
193 } ptes[MAXIMUM_PARTS];
195 char *disk_device, /* must be specified */
196 *line_ptr, /* interactive input */
197 line_buffer[LINE_LENGTH];
199 int fd, /* the disk */
200 ext_index, /* the prime extended partition */
201 listing = 0, /* no aborts for fdisk -l */
202 nowarn = 0, /* no warnings for fdisk -l/-s */
203 dos_compatible_flag = ~0,
205 partitions = 4; /* maximum partition + 1 */
207 unsigned int user_cylinders, user_heads, user_sectors;
208 unsigned int pt_heads, pt_sectors;
209 unsigned int kern_heads, kern_sectors;
211 unsigned long long sector_offset = 1, extended_offset = 0, sectors;
215 sector_size = DEFAULT_SECTOR_SIZE,
217 user_set_sector_size = 0,
218 units_per_sector = 1,
219 display_in_cyl_units = 1;
221 unsigned long long total_number_of_sectors; /* (!) 512-byte sectors */
223 #define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label)
224 int sun_label = 0; /* looking at sun disklabel */
225 int sgi_label = 0; /* looking at sgi disklabel */
226 int aix_label = 0; /* looking at aix disklabel */
227 int osf_label = 0; /* looking at OSF/1 disklabel */
228 int mac_label = 0; /* looking at mac disklabel */
229 int possibly_osf_label = 0;
233 void fatal(enum failure why) {
234 char error[LINE_LENGTH],
239 longjmp(listingbuf, 1);
243 case usage: message = _(
244 "Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
245 " fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
246 " fdisk -s PARTITION Give partition size(s) in blocks\n"
247 " fdisk -v Give fdisk version\n"
248 "Here DISK is something like /dev/hdb or /dev/sda\n"
249 "and PARTITION is something like /dev/hda7\n"
250 "-u: give Start and End in sector (instead of cylinder) units\n"
251 "-b 2048: (for certain MO disks) use 2048-byte sectors\n");
254 /* msg in cases where fdisk used to probe */
256 "Usage: fdisk [-l] [-b SSZ] [-u] device\n"
257 "E.g.: fdisk /dev/hda (for the first IDE disk)\n"
258 " or: fdisk /dev/sdc (for the third SCSI disk)\n"
259 " or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
260 " or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
264 snprintf(error, sizeof(error),
265 _("Unable to open %s\n"), disk_device);
268 snprintf(error, sizeof(error),
269 _("Unable to read %s\n"), disk_device);
272 snprintf(error, sizeof(error),
273 _("Unable to seek on %s\n"),disk_device);
275 case unable_to_write:
276 snprintf(error, sizeof(error),
277 _("Unable to write %s\n"), disk_device);
280 snprintf(error, sizeof(error),
281 _("BLKGETSIZE ioctl failed on %s\n"),
285 message = _("Unable to allocate any more memory\n");
288 message = _("Fatal error\n");
292 fputs(message, stderr);
297 seek_sector(int fd, unsigned long long secno) {
298 off_t offset = (off_t) secno * sector_size;
299 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
300 fatal(unable_to_seek);
304 read_sector(int fd, unsigned long long secno, unsigned char *buf) {
305 seek_sector(fd, secno);
306 if (read(fd, buf, sector_size) != sector_size)
307 fatal(unable_to_read);
311 write_sector(int fd, unsigned long long secno, unsigned char *buf) {
312 seek_sector(fd, secno);
313 if (write(fd, buf, sector_size) != sector_size)
314 fatal(unable_to_write);
317 /* Allocate a buffer and read a partition table sector */
319 read_pte(int fd, int pno, unsigned long long offset) {
320 struct pte *pe = &ptes[pno];
323 pe->sectorbuffer = malloc(sector_size);
324 if (!pe->sectorbuffer)
325 fatal(out_of_memory);
326 read_sector(fd, offset, pe->sectorbuffer);
328 pe->part_table = pe->ext_pointer = NULL;
331 static unsigned long long
332 get_partition_start(struct pte *pe) {
333 return pe->offset + get_start_sect(pe->part_table);
337 get_part_table(int i) {
338 return ptes[i].part_table;
342 set_all_unchanged(void) {
345 for (i = 0; i < MAXIMUM_PARTS; i++)
355 is_garbage_table(void) {
358 for (i = 0; i < 4; i++) {
359 struct pte *pe = &ptes[i];
360 struct partition *p = pe->part_table;
362 if (p->boot_ind != 0 && p->boot_ind != 0x80)
369 * Avoid warning about DOS partitions when no DOS partition was changed.
370 * Here a heuristic "is probably dos partition".
371 * We might also do the opposite and warn in all cases except
372 * for "is probably nondos partition".
375 is_dos_partition(int t) {
376 return (t == 1 || t == 4 || t == 6 ||
377 t == 0x0b || t == 0x0c || t == 0x0e ||
378 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
379 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
380 t == 0xc1 || t == 0xc4 || t == 0xc6);
386 puts(_("Command action"));
387 puts(_(" a toggle a read only flag")); /* sun */
388 puts(_(" b edit bsd disklabel"));
389 puts(_(" c toggle the mountable flag")); /* sun */
390 puts(_(" d delete a partition"));
391 puts(_(" l list known partition types"));
392 puts(_(" m print this menu"));
393 puts(_(" n add a new partition"));
394 puts(_(" o create a new empty DOS partition table"));
395 puts(_(" p print the partition table"));
396 puts(_(" q quit without saving changes"));
397 puts(_(" s create a new empty Sun disklabel")); /* sun */
398 puts(_(" t change a partition's system id"));
399 puts(_(" u change display/entry units"));
400 puts(_(" v verify the partition table"));
401 puts(_(" w write table to disk and exit"));
402 puts(_(" x extra functionality (experts only)"));
404 else if (sgi_label) {
405 puts(_("Command action"));
406 puts(_(" a select bootable partition")); /* sgi flavour */
407 puts(_(" b edit bootfile entry")); /* sgi */
408 puts(_(" c select sgi swap partition")); /* sgi flavour */
409 puts(_(" d delete a partition"));
410 puts(_(" l list known partition types"));
411 puts(_(" m print this menu"));
412 puts(_(" n add a new partition"));
413 puts(_(" o create a new empty DOS partition table"));
414 puts(_(" p print the partition table"));
415 puts(_(" q quit without saving changes"));
416 puts(_(" s create a new empty Sun disklabel")); /* sun */
417 puts(_(" t change a partition's system id"));
418 puts(_(" u change display/entry units"));
419 puts(_(" v verify the partition table"));
420 puts(_(" w write table to disk and exit"));
422 else if (aix_label || mac_label) {
423 puts(_("Command action"));
424 puts(_(" m print this menu"));
425 puts(_(" o create a new empty DOS partition table"));
426 puts(_(" q quit without saving changes"));
427 puts(_(" s create a new empty Sun disklabel")); /* sun */
430 puts(_("Command action"));
431 puts(_(" a toggle a bootable flag"));
432 puts(_(" b edit bsd disklabel"));
433 puts(_(" c toggle the dos compatibility flag"));
434 puts(_(" d delete a partition"));
435 puts(_(" l list known partition types"));
436 puts(_(" m print this menu"));
437 puts(_(" n add a new partition"));
438 puts(_(" o create a new empty DOS partition table"));
439 puts(_(" p print the partition table"));
440 puts(_(" q quit without saving changes"));
441 puts(_(" s create a new empty Sun disklabel")); /* sun */
442 puts(_(" t change a partition's system id"));
443 puts(_(" u change display/entry units"));
444 puts(_(" v verify the partition table"));
445 puts(_(" w write table to disk and exit"));
446 puts(_(" x extra functionality (experts only)"));
453 puts(_("Command action"));
454 puts(_(" a change number of alternate cylinders")); /*sun*/
455 puts(_(" c change number of cylinders"));
456 puts(_(" d print the raw data in the partition table"));
457 puts(_(" e change number of extra sectors per cylinder"));/*sun*/
458 puts(_(" h change number of heads"));
459 puts(_(" i change interleave factor")); /*sun*/
460 puts(_(" o change rotation speed (rpm)")); /*sun*/
461 puts(_(" m print this menu"));
462 puts(_(" p print the partition table"));
463 puts(_(" q quit without saving changes"));
464 puts(_(" r return to main menu"));
465 puts(_(" s change number of sectors/track"));
466 puts(_(" v verify the partition table"));
467 puts(_(" w write table to disk and exit"));
468 puts(_(" y change number of physical cylinders")); /*sun*/
470 else if (sgi_label) {
471 puts(_("Command action"));
472 puts(_(" b move beginning of data in a partition")); /* !sun */
473 puts(_(" c change number of cylinders"));
474 puts(_(" d print the raw data in the partition table"));
475 puts(_(" e list extended partitions")); /* !sun */
476 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
477 puts(_(" h change number of heads"));
478 puts(_(" m print this menu"));
479 puts(_(" p print the partition table"));
480 puts(_(" q quit without saving changes"));
481 puts(_(" r return to main menu"));
482 puts(_(" s change number of sectors/track"));
483 puts(_(" v verify the partition table"));
484 puts(_(" w write table to disk and exit"));
486 else if (aix_label || mac_label) {
487 puts(_("Command action"));
488 puts(_(" b move beginning of data in a partition")); /* !sun */
489 puts(_(" c change number of cylinders"));
490 puts(_(" d print the raw data in the partition table"));
491 puts(_(" e list extended partitions")); /* !sun */
492 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
493 puts(_(" h change number of heads"));
494 puts(_(" m print this menu"));
495 puts(_(" p print the partition table"));
496 puts(_(" q quit without saving changes"));
497 puts(_(" r return to main menu"));
498 puts(_(" s change number of sectors/track"));
499 puts(_(" v verify the partition table"));
500 puts(_(" w write table to disk and exit"));
503 puts(_("Command action"));
504 puts(_(" b move beginning of data in a partition")); /* !sun */
505 puts(_(" c change number of cylinders"));
506 puts(_(" d print the raw data in the partition table"));
507 puts(_(" e list extended partitions")); /* !sun */
508 puts(_(" f fix partition order")); /* !sun, !aix, !sgi */
509 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
510 puts(_(" h change number of heads"));
511 puts(_(" i change the disk identifier")); /* dos only */
512 puts(_(" m print this menu"));
513 puts(_(" p print the partition table"));
514 puts(_(" q quit without saving changes"));
515 puts(_(" r return to main menu"));
516 puts(_(" s change number of sectors/track"));
517 puts(_(" v verify the partition table"));
518 puts(_(" w write table to disk and exit"));
525 sun_label ? sun_get_sysid(i) :
526 sgi_label ? sgi_get_sysid(i) :
527 ptes[i].part_table->sys_ind);
530 static struct systypes *
531 get_sys_types(void) {
533 sun_label ? sun_sys_types :
534 sgi_label ? sgi_sys_types :
538 char *partition_type(unsigned char type)
541 struct systypes *types = get_sys_types();
543 for (i=0; types[i].name; i++)
544 if (types[i].type == type)
545 return _(types[i].name);
550 void list_types(struct systypes *sys)
552 unsigned int last[4], done = 0, next = 0, size;
555 for (i = 0; sys[i].name; i++);
558 for (i = 3; i >= 0; i--)
559 last[3 - i] = done += (size + i - done) / (i + 1);
563 printf("%c%2x %-15.15s", i ? ' ' : '\n',
564 sys[next].type, _(sys[next].name));
565 next = last[i++] + done;
566 if (i > 3 || next >= last[i]) {
570 } while (done < last[0]);
575 is_cleared_partition(struct partition *p) {
576 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
577 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
578 get_start_sect(p) || get_nr_sects(p));
582 clear_partition(struct partition *p) {
598 set_partition(int i, int doext, unsigned long long start,
599 unsigned long long stop, int sysid) {
601 unsigned long long offset;
604 p = ptes[i].ext_pointer;
605 offset = extended_offset;
607 p = ptes[i].part_table;
608 offset = ptes[i].offset;
612 set_start_sect(p, start - offset);
613 set_nr_sects(p, stop - start + 1);
614 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
615 start = heads*sectors*1024 - 1;
616 set_hsc(p->head, p->sector, p->cyl, start);
617 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
618 stop = heads*sectors*1024 - 1;
619 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
624 test_c(char **m, char *mesg) {
627 fprintf(stderr, _("You must set"));
629 fprintf(stderr, " %s", *m);
637 warn_geometry(void) {
641 if (sgi_label) /* cannot set cylinders etc anyway */
644 prev = test_c(&m, _("heads"));
646 prev = test_c(&m, _("sectors"));
648 prev = test_c(&m, _("cylinders"));
652 _("%s%s.\nYou can do this from the extra functions menu.\n"),
653 prev ? _(" and ") : " ", m);
657 void update_units(void)
659 int cyl_units = heads * sectors;
661 if (display_in_cyl_units && cyl_units)
662 units_per_sector = cyl_units;
664 units_per_sector = 1; /* in sectors */
668 warn_cylinders(void) {
669 if (dos_label && cylinders > 1024 && !nowarn)
670 fprintf(stderr, _("\n"
671 "The number of cylinders for this disk is set to %d.\n"
672 "There is nothing wrong with that, but this is larger than 1024,\n"
673 "and could in certain setups cause problems with:\n"
674 "1) software that runs at boot time (e.g., old versions of LILO)\n"
675 "2) booting and partitioning software from other OSs\n"
676 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
679 if (total_number_of_sectors > UINT_MAX) {
680 int giga = (total_number_of_sectors << 9) / 1000000000;
681 int hectogiga = (giga + 50) / 100;
683 fprintf(stderr, _("\n"
684 "WARNING: The size of this disk is %d.%d TB (%llu bytes).\n"
685 "DOS partition table format can not be used on drives for volumes\n"
686 "larger than (%llu bytes) for %d-byte sectors. Use parted(1) and GUID \n"
687 "partition table format (GPT).\n\n"),
688 hectogiga / 10, hectogiga % 10,
689 total_number_of_sectors << 9,
690 (unsigned long long ) UINT_MAX * sector_size,
696 read_extended(int ext) {
699 struct partition *p, *q;
703 pex->ext_pointer = pex->part_table;
706 if (!get_start_sect(p)) {
708 _("Bad offset in primary extended partition\n"));
712 while (IS_EXTENDED (p->sys_ind)) {
713 struct pte *pe = &ptes[partitions];
715 if (partitions >= MAXIMUM_PARTS) {
716 /* This is not a Linux restriction, but
717 this program uses arrays of size MAXIMUM_PARTS.
718 Do not try to `improve' this test. */
719 struct pte *pre = &ptes[partitions-1];
722 _("Warning: omitting partitions after #%d.\n"
723 "They will be deleted "
724 "if you save this partition table.\n"),
726 clear_partition(pre->ext_pointer);
731 read_pte(fd, partitions, extended_offset + get_start_sect(p));
733 if (!extended_offset)
734 extended_offset = get_start_sect(p);
736 q = p = pt_offset(pe->sectorbuffer, 0);
737 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
738 if (IS_EXTENDED (p->sys_ind)) {
741 _("Warning: extra link "
742 "pointer in partition table"
743 " %d\n"), partitions + 1);
746 } else if (p->sys_ind) {
749 _("Warning: ignoring extra "
750 "data in partition table"
751 " %d\n"), partitions + 1);
757 /* very strange code here... */
758 if (!pe->part_table) {
759 if (q != pe->ext_pointer)
762 pe->part_table = q + 1;
764 if (!pe->ext_pointer) {
765 if (q != pe->part_table)
768 pe->ext_pointer = q + 1;
775 /* remove empty links */
777 for (i = 4; i < partitions; i++) {
778 struct pte *pe = &ptes[i];
780 if (!get_nr_sects(pe->part_table) &&
781 (partitions > 5 || ptes[4].part_table->sys_ind)) {
782 printf(_("omitting empty partition (%d)\n"), i+1);
784 goto remove; /* numbering changed */
790 dos_write_mbr_id(unsigned char *b, unsigned int id) {
791 store4_little_endian(&b[440], id);
795 dos_read_mbr_id(const unsigned char *b) {
796 return read4_little_endian(&b[440]);
800 dos_print_mbr_id(void) {
801 printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer));
805 dos_set_mbr_id(void) {
806 unsigned long new_id;
810 snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "),
811 dos_read_mbr_id(MBRbuffer));
813 if (read_chars(ps) == '\n')
816 new_id = strtoul(line_ptr, &ep, 0);
820 dos_write_mbr_id(MBRbuffer, new_id);
825 create_doslabel(void) {
826 unsigned int id = get_random_id();
829 _("Building a new DOS disklabel with disk identifier 0x%08x.\n"
830 "Changes will remain in memory only, until you decide to write them.\n"
831 "After that, of course, the previous content won't be recoverable.\n\n"),
833 sun_nolabel(); /* otherwise always recognised as sun */
834 sgi_nolabel(); /* otherwise always recognised as sgi */
835 mac_label = aix_label = osf_label = possibly_osf_label = 0;
838 /* Zero out the MBR buffer */
842 get_boot(create_empty_dos);
844 /* Generate an MBR ID for this disk */
845 dos_write_mbr_id(MBRbuffer, id);
847 /* Mark it bootable (unfortunately required) */
848 write_part_table_flag(MBRbuffer);
852 get_sectorsize(int fd) {
855 if (user_set_sector_size)
858 if (blkdev_get_sector_size(fd, &arg) == 0)
860 if (sector_size != DEFAULT_SECTOR_SIZE)
861 printf(_("Note: sector size is %d (not %d)\n"),
862 sector_size, DEFAULT_SECTOR_SIZE);
866 get_kernel_geometry(int fd) {
868 struct hd_geometry geometry;
870 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
871 kern_heads = geometry.heads;
872 kern_sectors = geometry.sectors;
873 /* never use geometry.cylinders - it is truncated */
879 get_partition_table_geometry(void) {
880 unsigned char *bufp = MBRbuffer;
886 if (!(valid_part_table_flag(bufp)))
890 for (i=0; i<4; i++) {
891 p = pt_offset(bufp, i);
892 if (p->sys_ind != 0) {
894 s = (p->end_sector & 077);
899 } else if (hh != h || ss != s)
904 if (!first && !bad) {
911 get_geometry(int fd, struct geom *g) {
912 unsigned long long llcyls;
915 sector_factor = sector_size / 512;
916 guess_device_type(fd);
917 heads = cylinders = sectors = 0;
918 kern_heads = kern_sectors = 0;
919 pt_heads = pt_sectors = 0;
921 get_kernel_geometry(fd);
922 get_partition_table_geometry();
924 heads = user_heads ? user_heads :
925 pt_heads ? pt_heads :
926 kern_heads ? kern_heads : 255;
927 sectors = user_sectors ? user_sectors :
928 pt_sectors ? pt_sectors :
929 kern_sectors ? kern_sectors : 63;
931 if (blkdev_get_sectors(fd, &total_number_of_sectors) == -1)
932 total_number_of_sectors = 0;
935 if (dos_compatible_flag)
936 sector_offset = sectors;
938 llcyls = total_number_of_sectors / (heads * sectors * sector_factor);
940 if (cylinders != llcyls) /* truncated? */
943 cylinders = user_cylinders;
947 g->sectors = sectors;
948 g->cylinders = cylinders;
954 * -1: no 0xaa55 flag present (possibly entire disk BSD)
955 * 0: found or created label
959 get_boot(enum action what) {
966 for (i = 0; i < 4; i++) {
967 struct pte *pe = &ptes[i];
969 pe->part_table = pt_offset(MBRbuffer, i);
970 pe->ext_pointer = NULL;
972 pe->sectorbuffer = MBRbuffer;
973 pe->changed = (what == create_empty_dos);
976 if (what == create_empty_sun && check_sun_label())
979 memset(MBRbuffer, 0, 512);
981 if (what == create_empty_dos)
982 goto got_dos_table; /* skip reading disk */
984 if ((fd = open(disk_device, type_open)) < 0) {
985 if ((fd = open(disk_device, O_RDONLY)) < 0) {
986 if (what == try_only)
988 fatal(unable_to_open);
990 printf(_("You will not be able to write "
991 "the partition table.\n"));
994 if (512 != read(fd, MBRbuffer, 512)) {
995 if (what == try_only)
997 fatal(unable_to_read);
1000 get_geometry(fd, NULL);
1004 if (check_sun_label())
1007 if (check_sgi_label())
1010 if (check_aix_label())
1013 if (check_mac_label())
1016 if (check_osf_label()) {
1017 possibly_osf_label = 1;
1018 if (!valid_part_table_flag(MBRbuffer)) {
1022 printf(_("This disk has both DOS and BSD magic.\n"
1023 "Give the 'b' command to go to BSD mode.\n"));
1028 if (!valid_part_table_flag(MBRbuffer)) {
1032 _("Device contains neither a valid DOS "
1033 "partition table, nor Sun, SGI or OSF "
1045 case create_empty_dos:
1046 case create_empty_sun:
1049 fprintf(stderr, _("Internal error\n"));
1057 for (i = 0; i < 4; i++) {
1058 struct pte *pe = &ptes[i];
1060 if (IS_EXTENDED (pe->part_table->sys_ind)) {
1061 if (partitions != 4)
1062 fprintf(stderr, _("Ignoring extra extended "
1063 "partition %d\n"), i + 1);
1069 for (i = 3; i < partitions; i++) {
1070 struct pte *pe = &ptes[i];
1072 if (!valid_part_table_flag(pe->sectorbuffer)) {
1074 _("Warning: invalid flag 0x%04x of partition "
1075 "table %d will be corrected by w(rite)\n"),
1076 part_table_flag(pe->sectorbuffer), i + 1);
1084 /* read line; return 0 or first char */
1088 static int got_eof = 0;
1090 line_ptr = line_buffer;
1091 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
1093 got_eof++; /* user typed ^D ? */
1096 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
1101 while (*line_ptr && !isgraph(*line_ptr))
1107 read_char(char *mesg)
1110 fputs(mesg, stdout);
1111 fflush (stdout); /* requested by niles@scyld.com */
1112 } while (!read_line());
1117 read_chars(char *mesg)
1119 fputs(mesg, stdout);
1120 fflush (stdout); /* niles@scyld.com */
1129 read_hex(struct systypes *sys)
1135 read_char(_("Hex code (type L to list codes): "));
1136 if (tolower(*line_ptr) == 'l')
1138 else if (isxdigit (*line_ptr))
1142 hex = hex << 4 | hex_val(*line_ptr++);
1143 while (isxdigit(*line_ptr));
1150 * Print the message MESG, then read an integer in LOW..HIGH.
1151 * If the user hits Enter, DFLT is returned, provided that is in LOW..HIGH.
1152 * Answers like +10 are interpreted as offsets from BASE.
1154 * There is no default if DFLT is not between LOW and HIGH.
1157 read_int(unsigned int low, unsigned int dflt, unsigned int high,
1158 unsigned int base, char *mesg)
1162 static char *ms = NULL;
1163 static int mslen = 0;
1165 if (!ms || strlen(mesg)+100 > mslen) {
1166 mslen = strlen(mesg)+200;
1167 if (!(ms = realloc(ms,mslen)))
1168 fatal(out_of_memory);
1171 if (dflt < low || dflt > high)
1175 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
1176 mesg, low, high, dflt);
1178 snprintf(ms, mslen, "%s (%u-%u): ",
1182 int use_default = default_ok;
1184 /* ask question and read answer */
1185 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
1186 && *line_ptr != '-' && *line_ptr != '+')
1189 if (*line_ptr == '+' || *line_ptr == '-') {
1190 int minus = (*line_ptr == '-');
1194 i = atoi(line_ptr+1);
1196 while (isdigit(*++line_ptr))
1199 suflen = strlen(line_ptr) - 1;
1201 while(isspace(*(line_ptr + suflen)))
1202 *(line_ptr + suflen--) = '\0';
1204 if ((*line_ptr == 'C' || *line_ptr == 'c') &&
1205 *(line_ptr + 1) == '\0') {
1209 if (!display_in_cyl_units)
1210 i *= heads * sectors;
1211 } else if (*line_ptr &&
1212 *(line_ptr + 1) == 'B' &&
1213 *(line_ptr + 2) == '\0') {
1217 if (*line_ptr == 'K')
1219 else if (*line_ptr == 'M')
1221 else if (*line_ptr == 'G')
1222 absolute = 1000000000;
1225 } else if (*line_ptr &&
1226 *(line_ptr + 1) == '\0') {
1230 if (*line_ptr == 'K')
1232 else if (*line_ptr == 'M')
1234 else if (*line_ptr == 'G')
1238 } else if (*line_ptr != '\0')
1241 if (absolute == -1) {
1242 printf(_("Unsupported suffix: '%s'.\n"), line_ptr);
1243 printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n"
1244 " 2^N: K (KibiByte), M (MebiByte), G (GibiByte)\n"));
1248 if (absolute && i) {
1249 unsigned long long bytes;
1252 bytes = (unsigned long long) i * absolute;
1253 unit = sector_size * units_per_sector;
1254 bytes += unit/2; /* round */
1263 while (isdigit(*line_ptr)) {
1269 printf(_("Using default value %u\n"), i = dflt);
1270 if (i >= low && i <= high)
1273 printf(_("Value out of range.\n"));
1279 get_partition(int warn, int max) {
1283 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
1287 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
1289 (!sunlabel->partitions[i].num_sectors ||
1290 !sunlabel->part_tags[i].tag))
1291 || (sgi_label && (!sgi_get_num_sectors(i)))
1294 _("Warning: partition %d has empty type\n"),
1301 get_existing_partition(int warn, int max) {
1305 for (i = 0; i < max; i++) {
1306 struct pte *pe = &ptes[i];
1307 struct partition *p = pe->part_table;
1309 if (p && !is_cleared_partition(p)) {
1316 printf(_("Selected partition %d\n"), pno+1);
1319 printf(_("No partition is defined yet!\n"));
1323 return get_partition(warn, max);
1327 get_nonexisting_partition(int warn, int max) {
1331 for (i = 0; i < max; i++) {
1332 struct pte *pe = &ptes[i];
1333 struct partition *p = pe->part_table;
1335 if (p && is_cleared_partition(p)) {
1342 printf(_("Selected partition %d\n"), pno+1);
1345 printf(_("All primary partitions have been defined already!\n"));
1349 return get_partition(warn, max);
1353 str_units(int n) { /* n==1: use singular */
1355 return display_in_cyl_units ? _("cylinder") : _("sector");
1357 return display_in_cyl_units ? _("cylinders") : _("sectors");
1360 void change_units(void)
1362 display_in_cyl_units = !display_in_cyl_units;
1364 printf(_("Changing display/entry units to %s\n"),
1369 toggle_active(int i) {
1370 struct pte *pe = &ptes[i];
1371 struct partition *p = pe->part_table;
1373 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
1375 _("WARNING: Partition %d is an extended partition\n"),
1377 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1382 toggle_dos_compatibility_flag(void) {
1383 dos_compatible_flag = ~dos_compatible_flag;
1384 if (dos_compatible_flag) {
1385 sector_offset = sectors;
1386 printf(_("DOS Compatibility flag is set\n"));
1390 printf(_("DOS Compatibility flag is not set\n"));
1395 delete_partition(int i) {
1396 struct pte *pe = &ptes[i];
1397 struct partition *p = pe->part_table;
1398 struct partition *q = pe->ext_pointer;
1400 /* Note that for the fifth partition (i == 4) we don't actually
1401 * decrement partitions.
1404 if (warn_geometry())
1405 return; /* C/H/S not set */
1409 sun_delete_partition(i);
1414 sgi_delete_partition(i);
1419 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
1421 ptes[ext_index].ext_pointer = NULL;
1422 extended_offset = 0;
1428 if (!q->sys_ind && i > 4) {
1429 /* the last one in the chain - just delete */
1432 clear_partition(ptes[i].ext_pointer);
1433 ptes[i].changed = 1;
1435 /* not the last one - further ones will be moved down */
1437 /* delete this link in the chain */
1438 p = ptes[i-1].ext_pointer;
1440 set_start_sect(p, get_start_sect(q));
1441 set_nr_sects(p, get_nr_sects(q));
1442 ptes[i-1].changed = 1;
1443 } else if (partitions > 5) { /* 5 will be moved to 4 */
1444 /* the first logical in a longer chain */
1445 struct pte *pe = &ptes[5];
1447 if (pe->part_table) /* prevent SEGFAULT */
1448 set_start_sect(pe->part_table,
1449 get_partition_start(pe) -
1451 pe->offset = extended_offset;
1455 if (partitions > 5) {
1457 while (i < partitions) {
1458 ptes[i] = ptes[i+1];
1462 /* the only logical: clear only */
1463 clear_partition(ptes[i].part_table);
1468 change_sysid(void) {
1470 int i, sys, origsys;
1471 struct partition *p;
1473 /* If sgi_label then don't use get_existing_partition,
1474 let the user select a partition, since get_existing_partition()
1475 only works for Linux like partition tables. */
1477 i = get_existing_partition(0, partitions);
1479 i = get_partition(0, partitions);
1484 p = ptes[i].part_table;
1485 origsys = sys = get_sysid(i);
1487 /* if changing types T to 0 is allowed, then
1488 the reverse change must be allowed, too */
1489 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
1490 printf(_("Partition %d does not exist yet!\n"), i + 1);
1492 sys = read_hex (get_sys_types());
1494 if (!sys && !sgi_label && !sun_label) {
1495 printf(_("Type 0 means free space to many systems\n"
1496 "(but not to Linux). Having partitions of\n"
1497 "type 0 is probably unwise. You can delete\n"
1498 "a partition using the `d' command.\n"));
1502 if (!sun_label && !sgi_label) {
1503 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
1504 printf(_("You cannot change a partition into"
1505 " an extended one or vice versa\n"
1506 "Delete it first.\n"));
1512 if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
1513 printf(_("Consider leaving partition 3 "
1514 "as Whole disk (5),\n"
1515 "as SunOS/Solaris expects it and "
1516 "even Linux likes it.\n\n"));
1517 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
1518 || (i == 8 && sys != 0)))
1519 printf(_("Consider leaving partition 9 "
1520 "as volume header (0),\nand "
1521 "partition 11 as entire volume (6), "
1522 "as IRIX expects it.\n\n"));
1526 ptes[i].changed = sun_change_sysid(i, sys);
1529 ptes[i].changed = sgi_change_sysid(i, sys);
1532 ptes[i].changed = 1;
1534 temp = partition_type(sys) ? : _("Unknown");
1535 if (ptes[i].changed)
1536 printf (_("Changed system type of partition %d "
1537 "to %x (%s)\n"), i + 1, sys, temp);
1539 printf (_("System type of partition %d is unchanged: "
1540 "%x (%s)\n"), i + 1, sys, temp);
1541 if (is_dos_partition(origsys) ||
1542 is_dos_partition(sys))
1549 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
1550 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1551 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1552 * Lubkin Oct. 1991). */
1555 long2chs(ulong ls, unsigned int *c, unsigned int *h, unsigned int *s) {
1556 int spc = heads * sectors;
1561 *s = ls % sectors + 1; /* sectors count from 1 */
1564 static void check_consistency(struct partition *p, int partition) {
1565 unsigned int pbc, pbh, pbs; /* physical beginning c, h, s */
1566 unsigned int pec, peh, pes; /* physical ending c, h, s */
1567 unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */
1568 unsigned int lec, leh, les; /* logical ending c, h, s */
1570 if (!heads || !sectors || (partition >= 4))
1571 return; /* do not check extended partitions */
1573 /* physical beginning c, h, s */
1574 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1576 pbs = p->sector & 0x3f;
1578 /* physical ending c, h, s */
1579 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1581 pes = p->end_sector & 0x3f;
1583 /* compute logical beginning (c, h, s) */
1584 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1586 /* compute logical ending (c, h, s) */
1587 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1589 /* Same physical / logical beginning? */
1590 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1591 printf(_("Partition %d has different physical/logical "
1592 "beginnings (non-Linux?):\n"), partition + 1);
1593 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
1594 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
1597 /* Same physical / logical ending? */
1598 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1599 printf(_("Partition %d has different physical/logical "
1600 "endings:\n"), partition + 1);
1601 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
1602 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
1606 /* Beginning on cylinder boundary? */
1607 if (pbh != !pbc || pbs != 1) {
1608 printf(_("Partition %i does not start on cylinder "
1609 "boundary:\n"), partition + 1);
1610 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
1611 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
1615 /* Ending on cylinder boundary? */
1616 if (peh != (heads - 1) || pes != sectors) {
1617 printf(_("Partition %i does not end on cylinder boundary.\n"),
1620 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
1621 printf(_("should be (%d, %d, %d)\n"),
1622 pec, heads - 1, sectors);
1628 list_disk_geometry(void) {
1629 long long bytes = (total_number_of_sectors << 9);
1630 long megabytes = bytes/1000000;
1632 if (megabytes < 10000)
1633 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
1634 disk_device, megabytes, bytes);
1636 long hectomega = (megabytes + 50) / 100;
1637 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
1638 disk_device, hectomega / 10, hectomega % 10, bytes);
1640 printf(_("%d heads, %llu sectors/track, %d cylinders"),
1641 heads, sectors, cylinders);
1642 if (units_per_sector == 1)
1643 printf(_(", total %llu sectors"),
1644 total_number_of_sectors / sector_factor);
1646 printf(_("Units = %s of %d * %d = %d bytes\n"),
1648 units_per_sector, sector_size, units_per_sector * sector_size);
1655 * Check whether partition entries are ordered by their starting positions.
1656 * Return 0 if OK. Return i if partition i should have been earlier.
1657 * Two separate checks: primary and logical partitions.
1660 wrong_p_order(int *prev) {
1662 struct partition *p;
1663 unsigned int last_p_start_pos = 0, p_start_pos;
1666 for (i = 0 ; i < partitions; i++) {
1669 last_p_start_pos = 0;
1672 if ((p = pe->part_table)->sys_ind) {
1673 p_start_pos = get_partition_start(pe);
1675 if (last_p_start_pos > p_start_pos) {
1681 last_p_start_pos = p_start_pos;
1689 * Fix the chain of logicals.
1690 * extended_offset is unchanged, the set of sectors used is unchanged
1691 * The chain is sorted so that sectors increase, and so that
1692 * starting sectors increase.
1694 * After this it may still be that cfdisk doesnt like the table.
1695 * (This is because cfdisk considers expanded parts, from link to
1696 * end of partition, and these may still overlap.)
1698 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1702 fix_chain_of_logicals(void) {
1703 int j, oj, ojj, sj, sjj;
1704 struct partition *pj,*pjj,tmp;
1706 /* Stage 1: sort sectors but leave sector of part 4 */
1707 /* (Its sector is the global extended_offset.) */
1709 for (j = 5; j < partitions-1; j++) {
1710 oj = ptes[j].offset;
1711 ojj = ptes[j+1].offset;
1713 ptes[j].offset = ojj;
1714 ptes[j+1].offset = oj;
1715 pj = ptes[j].part_table;
1716 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1717 pjj = ptes[j+1].part_table;
1718 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1719 set_start_sect(ptes[j-1].ext_pointer,
1720 ojj-extended_offset);
1721 set_start_sect(ptes[j].ext_pointer,
1722 oj-extended_offset);
1727 /* Stage 2: sort starting sectors */
1729 for (j = 4; j < partitions-1; j++) {
1730 pj = ptes[j].part_table;
1731 pjj = ptes[j+1].part_table;
1732 sj = get_start_sect(pj);
1733 sjj = get_start_sect(pjj);
1734 oj = ptes[j].offset;
1735 ojj = ptes[j+1].offset;
1736 if (oj+sj > ojj+sjj) {
1740 set_start_sect(pj, ojj+sjj-oj);
1741 set_start_sect(pjj, oj+sj-ojj);
1746 /* Probably something was changed */
1747 for (j = 4; j < partitions; j++)
1748 ptes[j].changed = 1;
1752 fix_partition_table_order(void) {
1753 struct pte *pei, *pek;
1756 if (!wrong_p_order(NULL)) {
1757 printf(_("Nothing to do. Ordering is correct already.\n\n"));
1761 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1762 /* partition i should have come earlier, move it */
1763 /* We have to move data in the MBR */
1764 struct partition *pi, *pk, *pe, pbuf;
1768 pe = pei->ext_pointer;
1769 pei->ext_pointer = pek->ext_pointer;
1770 pek->ext_pointer = pe;
1772 pi = pei->part_table;
1773 pk = pek->part_table;
1775 memmove(&pbuf, pi, sizeof(struct partition));
1776 memmove(pi, pk, sizeof(struct partition));
1777 memmove(pk, &pbuf, sizeof(struct partition));
1779 pei->changed = pek->changed = 1;
1783 fix_chain_of_logicals();
1785 printf(_("Done.\n"));
1790 list_table(int xtra) {
1791 struct partition *p;
1796 sun_list_table(xtra);
1801 sgi_list_table(xtra);
1805 list_disk_geometry();
1808 xbsd_print_disklabel(xtra);
1812 if (is_garbage_table()) {
1813 printf(_("This doesn't look like a partition table\n"
1814 "Probably you selected the wrong device.\n\n"));
1817 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1818 but if the device name ends in a digit, say /dev/foo1,
1819 then the partition is called /dev/foo1p3. */
1820 w = strlen(disk_device);
1821 if (w && isdigit(disk_device[w-1]))
1826 printf(_("%*s Boot Start End Blocks Id System\n"),
1829 for (i = 0; i < partitions; i++) {
1830 struct pte *pe = &ptes[i];
1833 if (p && !is_cleared_partition(p)) {
1834 unsigned int psects = get_nr_sects(p);
1835 unsigned int pblocks = psects;
1836 unsigned int podd = 0;
1838 if (sector_size < 1024) {
1839 pblocks /= (1024 / sector_size);
1840 podd = psects % (1024 / sector_size);
1842 if (sector_size > 1024)
1843 pblocks *= (sector_size / 1024);
1845 "%s %c %11lu %11lu %11lu%c %2x %s\n",
1846 partname(disk_device, i+1, w+2),
1847 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
1849 /* start */ (unsigned long) cround(get_partition_start(pe)),
1850 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
1851 - (psects ? 1 : 0)),
1852 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
1853 /* type id */ p->sys_ind,
1854 /* type name */ (type = partition_type(p->sys_ind)) ?
1855 type : _("Unknown"));
1856 check_consistency(p, i);
1860 /* Is partition table in disk order? It need not be, but... */
1861 /* partition table entries are not checked for correct order if this
1862 is a sgi, sun or aix labeled disk... */
1863 if (dos_label && wrong_p_order(NULL)) {
1864 printf(_("\nPartition table entries are not in disk order\n"));
1869 x_list_table(int extend) {
1871 struct partition *p;
1874 printf(_("\nDisk %s: %d heads, %llu sectors, %d cylinders\n\n"),
1875 disk_device, heads, sectors, cylinders);
1876 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
1877 for (i = 0 ; i < partitions; i++) {
1879 p = (extend ? pe->ext_pointer : pe->part_table);
1881 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x\n",
1882 i + 1, p->boot_ind, p->head,
1884 cylinder(p->sector, p->cyl), p->end_head,
1885 sector(p->end_sector),
1886 cylinder(p->end_sector, p->end_cyl),
1887 (unsigned long) get_start_sect(p),
1888 (unsigned long) get_nr_sects(p), p->sys_ind);
1890 check_consistency(p, i);
1896 fill_bounds(unsigned long long *first, unsigned long long *last) {
1898 struct pte *pe = &ptes[0];
1899 struct partition *p;
1901 for (i = 0; i < partitions; pe++,i++) {
1903 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
1904 first[i] = 0xffffffff;
1907 first[i] = get_partition_start(pe);
1908 last[i] = first[i] + get_nr_sects(p) - 1;
1914 check(int n, unsigned int h, unsigned int s, unsigned int c,
1915 unsigned int start) {
1916 unsigned int total, real_s, real_c;
1918 real_s = sector(s) - 1;
1919 real_c = cylinder(s, c);
1920 total = (real_c * sectors + real_s) * heads + h;
1922 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
1925 _("Partition %d: head %d greater than maximum %d\n"),
1927 if (real_s >= sectors)
1928 fprintf(stderr, _("Partition %d: sector %d greater than "
1929 "maximum %llu\n"), n, s, sectors);
1930 if (real_c >= cylinders)
1931 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
1932 "maximum %d\n"), n, real_c + 1, cylinders);
1933 if (cylinders <= 1024 && start != total)
1935 _("Partition %d: previous sectors %d disagrees with "
1936 "total %d\n"), n, start, total);
1942 unsigned long long total = 1;
1943 unsigned long long n_sectors = (total_number_of_sectors / sector_factor);
1944 unsigned long long first[partitions], last[partitions];
1945 struct partition *p;
1947 if (warn_geometry())
1960 fill_bounds(first, last);
1961 for (i = 0; i < partitions; i++) {
1962 struct pte *pe = &ptes[i];
1965 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
1966 check_consistency(p, i);
1967 if (get_partition_start(pe) < first[i])
1968 printf(_("Warning: bad start-of-data in "
1969 "partition %d\n"), i + 1);
1970 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
1972 total += last[i] + 1 - first[i];
1973 for (j = 0; j < i; j++)
1974 if ((first[i] >= first[j] && first[i] <= last[j])
1975 || ((last[i] <= last[j] && last[i] >= first[j]))) {
1976 printf(_("Warning: partition %d overlaps "
1977 "partition %d.\n"), j + 1, i + 1);
1978 total += first[i] >= first[j] ?
1979 first[i] : first[j];
1980 total -= last[i] <= last[j] ?
1986 if (extended_offset) {
1987 struct pte *pex = &ptes[ext_index];
1988 unsigned long long e_last = get_start_sect(pex->part_table) +
1989 get_nr_sects(pex->part_table) - 1;
1991 for (i = 4; i < partitions; i++) {
1993 p = ptes[i].part_table;
1995 if (i != 4 || i + 1 < partitions)
1996 printf(_("Warning: partition %d "
1997 "is empty\n"), i + 1);
1999 else if (first[i] < extended_offset ||
2001 printf(_("Logical partition %d not entirely in "
2002 "partition %d\n"), i + 1, ext_index + 1);
2006 if (total > n_sectors)
2007 printf(_("Total allocated sectors %llu greater than the maximum"
2008 " %llu\n"), total, n_sectors);
2009 else if (total < n_sectors)
2010 printf(_("%lld unallocated %d-byte sectors\n"),
2011 n_sectors - total, sector_size);
2015 add_partition(int n, int sys) {
2016 char mesg[256]; /* 48 does not suffice in Japanese */
2018 struct partition *p = ptes[n].part_table;
2019 struct partition *q = ptes[ext_index].part_table;
2021 unsigned long long start, stop = 0, limit, temp,
2022 first[partitions], last[partitions];
2024 if (p && p->sys_ind) {
2025 printf(_("Partition %d is already defined. Delete "
2026 "it before re-adding it.\n"), n + 1);
2029 fill_bounds(first, last);
2031 start = sector_offset;
2032 if (display_in_cyl_units || !total_number_of_sectors)
2033 llimit = heads * sectors * cylinders - 1;
2035 llimit = (total_number_of_sectors / sector_factor) - 1;
2037 if (limit != llimit)
2039 if (extended_offset) {
2040 first[ext_index] = extended_offset;
2041 last[ext_index] = get_start_sect(q) +
2042 get_nr_sects(q) - 1;
2045 start = extended_offset + sector_offset;
2046 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2048 if (display_in_cyl_units)
2049 for (i = 0; i < partitions; i++)
2050 first[i] = (cround(first[i]) - 1) * units_per_sector;
2052 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2055 for (i = 0; i < partitions; i++) {
2056 unsigned long long lastplusoff;
2058 if (start == ptes[i].offset)
2059 start += sector_offset;
2060 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
2061 if (start >= first[i] && start <= lastplusoff)
2062 start = lastplusoff + 1;
2066 if (start >= temp+units_per_sector && read) {
2067 printf(_("Sector %llu is already allocated\n"), temp);
2071 if (!read && start == temp) {
2072 unsigned long long i = start;
2074 start = read_int(cround(i), cround(i), cround(limit),
2076 if (display_in_cyl_units) {
2077 start = (start - 1) * units_per_sector;
2078 if (start < i) start = i;
2082 } while (start != temp || !read);
2083 if (n > 4) { /* NOT for fifth partition */
2084 struct pte *pe = &ptes[n];
2086 pe->offset = start - sector_offset;
2087 if (pe->offset == extended_offset) { /* must be corrected */
2089 if (sector_offset == 1)
2094 for (i = 0; i < partitions; i++) {
2095 struct pte *pe = &ptes[i];
2097 if (start < pe->offset && limit >= pe->offset)
2098 limit = pe->offset - 1;
2099 if (start < first[i] && limit >= first[i])
2100 limit = first[i] - 1;
2102 if (start > limit) {
2103 printf(_("No free sectors available\n"));
2108 if (cround(start) == cround(limit)) {
2111 snprintf(mesg, sizeof(mesg),
2112 _("Last %1$s, +%2$s or +size{K,M,G}"),
2113 str_units(SINGULAR), str_units(PLURAL));
2115 stop = read_int(cround(start), cround(limit), cround(limit),
2116 cround(start), mesg);
2117 if (display_in_cyl_units) {
2118 stop = stop * units_per_sector - 1;
2124 set_partition(n, 0, start, stop, sys);
2126 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2128 if (IS_EXTENDED (sys)) {
2129 struct pte *pe4 = &ptes[4];
2130 struct pte *pen = &ptes[n];
2133 pen->ext_pointer = p;
2134 pe4->offset = extended_offset = start;
2135 if (!(pe4->sectorbuffer = calloc(1, sector_size)))
2136 fatal(out_of_memory);
2137 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2138 pe4->ext_pointer = pe4->part_table + 1;
2146 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2147 struct pte *pe = &ptes[partitions];
2149 if (!(pe->sectorbuffer = calloc(1, sector_size)))
2150 fatal(out_of_memory);
2151 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2152 pe->ext_pointer = pe->part_table + 1;
2157 add_partition(partitions - 1, LINUX_NATIVE);
2161 new_partition(void) {
2162 int i, free_primary = 0;
2164 if (warn_geometry())
2168 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2173 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2178 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
2179 "\n\tIf you want to add DOS-type partitions, create"
2180 "\n\ta new empty DOS partition table first. (Use o.)"
2182 "This will destroy the present disk contents.\n"));
2187 printf(_("\tSorry - this fdisk cannot handle Mac disk labels."
2188 "\n\tIf you want to add DOS-type partitions, create"
2189 "\n\ta new empty DOS partition table first. (Use o.)"
2191 "This will destroy the present disk contents.\n"));
2195 for (i = 0; i < 4; i++)
2196 free_primary += !ptes[i].part_table->sys_ind;
2198 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2199 printf(_("The maximum number of partitions has been created\n"));
2203 if (!free_primary) {
2204 if (extended_offset)
2207 printf(_("You must delete some partition and add "
2208 "an extended partition first\n"));
2209 } else if (partitions >= MAXIMUM_PARTS) {
2210 printf(_("All logical partitions are in use\n"));
2211 printf(_("Adding a primary partition\n"));
2212 add_partition(get_partition(0, 4), LINUX_NATIVE);
2214 char c, line[LINE_LENGTH];
2215 snprintf(line, sizeof(line),
2216 _("Command action\n %s\n p primary "
2217 "partition (1-4)\n"), extended_offset ?
2218 _("l logical (5 or over)") : _("e extended"));
2220 if ((c = tolower(read_char(line))) == 'p') {
2221 int i = get_nonexisting_partition(0, 4);
2223 add_partition(i, LINUX_NATIVE);
2226 else if (c == 'l' && extended_offset) {
2230 else if (c == 'e' && !extended_offset) {
2231 int i = get_nonexisting_partition(0, 4);
2233 add_partition(i, EXTENDED);
2237 printf(_("Invalid partition number "
2238 "for type `%c'\n"), c);
2249 if (ptes[i].changed)
2250 ptes[3].changed = 1;
2251 for (i = 3; i < partitions; i++) {
2252 struct pte *pe = &ptes[i];
2255 write_part_table_flag(pe->sectorbuffer);
2256 write_sector(fd, pe->offset, pe->sectorbuffer);
2260 else if (sgi_label) {
2261 /* no test on change? the printf below might be mistaken */
2263 } else if (sun_label) {
2267 if (ptes[i].changed)
2273 printf(_("The partition table has been altered!\n\n"));
2274 reread_partition_table(1);
2278 reread_partition_table(int leave) {
2280 struct stat statbuf;
2282 i = fstat(fd, &statbuf);
2283 if (i == 0 && S_ISBLK(statbuf.st_mode)) {
2287 printf(_("Calling ioctl() to re-read partition table.\n"));
2288 i = ioctl(fd, BLKRRPART);
2296 printf(_("\nWARNING: Re-reading the partition table failed with error %d: %s.\n"
2297 "The kernel still uses the old table. The new table will be used at\n"
2298 "the next reboot or after you run partprobe(8) or kpartx(8)\n"),
2299 errno, strerror(errno));
2304 _("\nWARNING: If you have created or modified any DOS 6.x\n"
2305 "partitions, please see the fdisk manual page for additional\n"
2309 if (fsync(fd) || close(fd)) {
2310 fprintf(stderr, _("\nError closing file\n"));
2314 printf(_("Syncing disks.\n"));
2316 sleep(4); /* for sync() */
2321 #define MAX_PER_LINE 16
2323 print_buffer(unsigned char pbuffer[]) {
2327 for (i = 0, l = 0; i < sector_size; i++, l++) {
2329 printf("0x%03X:", i);
2330 printf(" %02X", pbuffer[i]);
2331 if (l == MAX_PER_LINE - 1) {
2345 printf(_("Device: %s\n"), disk_device);
2346 if (sun_label || sgi_label)
2347 print_buffer(MBRbuffer);
2348 else for (i = 3; i < partitions; i++)
2349 print_buffer(ptes[i].sectorbuffer);
2354 struct pte *pe = &ptes[i];
2355 struct partition *p = pe->part_table;
2356 unsigned int new, first;
2358 if (warn_geometry())
2360 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
2361 printf(_("Partition %d has no data area\n"), i + 1);
2364 first = get_partition_start(pe);
2365 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2366 _("New beginning of data")) - pe->offset;
2368 if (new != get_nr_sects(p)) {
2369 first = get_nr_sects(p) + get_start_sect(p) - new;
2370 set_nr_sects(p, first);
2371 set_start_sect(p, new);
2382 c = tolower(read_char(_("Expert command (m for help): ")));
2390 move_begin(get_partition(0, partitions));
2393 user_cylinders = cylinders =
2394 read_int(1, cylinders, 1048576, 0,
2395 _("Number of cylinders"));
2397 sun_set_ncyl(cylinders);
2415 fix_partition_table_order();
2421 user_heads = heads = read_int(1, heads, 256, 0,
2422 _("Number of heads"));
2448 user_sectors = sectors = read_int(1, sectors, 63, 0,
2449 _("Number of sectors"));
2450 if (dos_compatible_flag) {
2451 sector_offset = sectors;
2452 fprintf(stderr, _("Warning: setting "
2453 "sector offset for DOS "
2462 write_table(); /* does not return */
2466 sun_set_pcylcount();
2475 is_ide_cdrom_or_tape(char *device) {
2478 struct stat statbuf;
2481 /* No device was given explicitly, and we are trying some
2482 likely things. But opening /dev/hdc may produce errors like
2483 "hdc: tray open or drive not ready"
2484 if it happens to be a CD-ROM drive. It even happens that
2485 the process hangs on the attempt to read a music CD.
2486 So try to be careful. This only works since 2.1.73. */
2488 if (strncmp("/dev/hd", device, 7))
2491 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2492 procf = fopen(buf, "r");
2493 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2494 is_ide = (!strncmp(buf, "cdrom", 5) ||
2495 !strncmp(buf, "tape", 4));
2497 /* Now when this proc file does not exist, skip the
2498 device when it is read-only. */
2499 if (stat(device, &statbuf) == 0)
2500 is_ide = ((statbuf.st_mode & 0222) == 0);
2508 gpt_warning(char *dev)
2510 if (dev && gpt_probe_signature_devname(dev))
2511 fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
2512 "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
2516 try(char *device, int user_specified) {
2519 disk_device = device;
2520 if (setjmp(listingbuf))
2522 if (!user_specified)
2523 if (is_ide_cdrom_or_tape(device))
2525 gpt_warning(device);
2526 if ((fd = open(disk_device, type_open)) >= 0) {
2527 gb = get_boot(try_only);
2528 if (gb > 0) { /* I/O error */
2529 } else if (gb < 0) { /* no DOS signature */
2530 list_disk_geometry();
2531 if (!aix_label && !mac_label && btrydev(device) < 0)
2533 _("Disk %s doesn't contain a valid "
2534 "partition table\n"), device);
2540 /* Ignore other errors, since we try IDE
2541 and SCSI hard disks which may not be
2542 installed on the system. */
2543 if (errno == EACCES) {
2544 fprintf(stderr, _("Cannot open %s\n"), device);
2552 * try all things in /proc/partitions that look like a full disk
2557 char line[128], ptname[128], devname[256];
2559 unsigned long long sz;
2561 procpt = fopen(PROC_PARTITIONS, "r");
2562 if (procpt == NULL) {
2563 fprintf(stderr, _("cannot open %s\n"), PROC_PARTITIONS);
2567 while (fgets(line, sizeof(line), procpt)) {
2568 if (sscanf (line, " %d %d %llu %128[^\n ]",
2569 &ma, &mi, &sz, ptname) != 4)
2571 snprintf(devname, sizeof(devname), "/dev/%s", ptname);
2572 if (is_whole_disk(devname))
2582 unknown_command(int c) {
2583 printf(_("%c: unknown command\n"), c);
2589 main(int argc, char **argv) {
2591 int optl = 0, opts = 0;
2593 setlocale(LC_ALL, "");
2594 bindtextdomain(PACKAGE, LOCALEDIR);
2595 textdomain(PACKAGE);
2600 * fdisk -l [-b sectorsize] [-u] device ...
2601 * fdisk -s [partition] ...
2602 * fdisk [-b sectorsize] [-u] device
2604 * Options -C, -H, -S set the geometry.
2607 while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
2610 /* Ugly: this sector size is really per device,
2611 so cannot be combined with multiple disks,
2612 and te same goes for the C/H/S options.
2614 sector_size = atoi(optarg);
2615 if (sector_size != 512 && sector_size != 1024 &&
2616 sector_size != 2048 && sector_size != 4096)
2619 user_set_sector_size = 1;
2622 user_cylinders = atoi(optarg);
2625 user_heads = atoi(optarg);
2626 if (user_heads <= 0 || user_heads > 256)
2630 user_sectors = atoi(optarg);
2631 if (user_sectors <= 0 || user_sectors >= 64)
2641 display_in_cyl_units = 0;
2645 printf("fdisk (%s)\n", PACKAGE_STRING);
2653 printf(_("This kernel finds the sector size itself - "
2654 "-b option ignored\n"));
2656 if (user_set_sector_size && argc-optind != 1)
2657 printf(_("Warning: the -b (set sector size) option should"
2658 " be used with one specified device\n"));
2663 type_open = O_RDONLY;
2664 if (argc > optind) {
2666 /* avoid gcc warning:
2667 variable `k' might be clobbered by `longjmp' */
2670 for (k = optind; k < argc; k++)
2673 /* we no longer have default device names */
2674 /* but we can use /proc/partitions instead */
2681 unsigned long long size;
2684 type_open = O_RDONLY;
2686 opts = argc - optind;
2690 for (j = optind; j < argc; j++) {
2691 disk_device = argv[j];
2692 if ((fd = open(disk_device, type_open)) < 0)
2693 fatal(unable_to_open);
2694 if (blkdev_get_sectors(fd, &size) == -1)
2698 printf("%llu\n", size/2);
2700 printf("%s: %llu\n", argv[j], size/2);
2705 if (argc-optind == 1)
2706 disk_device = argv[optind];
2707 else if (argc-optind != 0)
2712 gpt_warning(disk_device);
2716 /* OSF label, and no DOS label */
2717 printf(_("Detected an OSF/1 disklabel on %s, entering "
2718 "disklabel mode.\n"),
2722 /* If we return we may want to make an empty DOS label? */
2727 c = tolower(read_char(_("Command (m for help): ")));
2731 toggle_active(get_partition(1, partitions));
2733 toggle_sunflags(get_partition(1, partitions),
2736 sgi_set_bootpartition(
2737 get_partition(1, partitions));
2743 printf(_("\nThe current boot file is: %s\n"),
2744 sgi_get_bootfile());
2745 if (read_chars(_("Please enter the name of the "
2746 "new boot file: ")) == '\n')
2747 printf(_("Boot file unchanged\n"));
2749 sgi_set_bootfile(line_ptr);
2755 toggle_dos_compatibility_flag();
2757 toggle_sunflags(get_partition(1, partitions),
2760 sgi_set_swappartition(
2761 get_partition(1, partitions));
2766 /* If sgi_label then don't use get_existing_partition,
2767 let the user select a partition, since
2768 get_existing_partition() only works for Linux-like
2771 j = get_existing_partition(1, partitions);
2773 j = get_partition(1, partitions);
2776 delete_partition(j);
2784 list_types(get_sys_types());
2815 write_table(); /* does not return */
2820 _("\n\tSorry, no experts menu for SGI "
2821 "partition tables available.\n\n"));