diff options
Diffstat (limited to 'util-linux/fdisk.c')
-rw-r--r-- | util-linux/fdisk.c | 131 |
1 files changed, 77 insertions, 54 deletions
diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index cdcba0a03..288b9235f 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c | |||
@@ -169,9 +169,9 @@ typedef unsigned long long ullong; | |||
169 | * do not support more than 2^32 sectors | 169 | * do not support more than 2^32 sectors |
170 | */ | 170 | */ |
171 | typedef uint32_t sector_t; | 171 | typedef uint32_t sector_t; |
172 | #if UINT_MAX == 4294967295 | 172 | #if UINT_MAX == 0xffffffff |
173 | # define SECT_FMT "" | 173 | # define SECT_FMT "" |
174 | #elif ULONG_MAX == 4294967295 | 174 | #elif ULONG_MAX == 0xffffffff |
175 | # define SECT_FMT "l" | 175 | # define SECT_FMT "l" |
176 | #else | 176 | #else |
177 | # error Cant detect sizeof(uint32_t) | 177 | # error Cant detect sizeof(uint32_t) |
@@ -426,7 +426,7 @@ struct globals { | |||
426 | unsigned sector_offset; // = 1; | 426 | unsigned sector_offset; // = 1; |
427 | unsigned g_heads, g_sectors, g_cylinders; | 427 | unsigned g_heads, g_sectors, g_cylinders; |
428 | smallint /* enum label_type */ current_label_type; | 428 | smallint /* enum label_type */ current_label_type; |
429 | smallint display_in_cyl_units; // = 1; | 429 | smallint display_in_cyl_units; |
430 | #if ENABLE_FEATURE_OSF_LABEL | 430 | #if ENABLE_FEATURE_OSF_LABEL |
431 | smallint possibly_osf_label; | 431 | smallint possibly_osf_label; |
432 | #endif | 432 | #endif |
@@ -488,7 +488,6 @@ struct globals { | |||
488 | sector_size = DEFAULT_SECTOR_SIZE; \ | 488 | sector_size = DEFAULT_SECTOR_SIZE; \ |
489 | sector_offset = 1; \ | 489 | sector_offset = 1; \ |
490 | g_partitions = 4; \ | 490 | g_partitions = 4; \ |
491 | display_in_cyl_units = 1; \ | ||
492 | units_per_sector = 1; \ | 491 | units_per_sector = 1; \ |
493 | dos_compatible_flag = 1; \ | 492 | dos_compatible_flag = 1; \ |
494 | } while (0) | 493 | } while (0) |
@@ -639,25 +638,6 @@ seek_sector(sector_t secno) | |||
639 | } | 638 | } |
640 | 639 | ||
641 | #if ENABLE_FEATURE_FDISK_WRITABLE | 640 | #if ENABLE_FEATURE_FDISK_WRITABLE |
642 | /* Read line; return 0 or first printable char */ | ||
643 | static int | ||
644 | read_line(const char *prompt) | ||
645 | { | ||
646 | int sz; | ||
647 | |||
648 | sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer)); | ||
649 | if (sz <= 0) | ||
650 | exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ | ||
651 | |||
652 | if (line_buffer[sz-1] == '\n') | ||
653 | line_buffer[--sz] = '\0'; | ||
654 | |||
655 | line_ptr = line_buffer; | ||
656 | while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ') | ||
657 | line_ptr++; | ||
658 | return *line_ptr; | ||
659 | } | ||
660 | |||
661 | static void | 641 | static void |
662 | set_all_unchanged(void) | 642 | set_all_unchanged(void) |
663 | { | 643 | { |
@@ -680,6 +660,25 @@ write_part_table_flag(char *b) | |||
680 | b[511] = 0xaa; | 660 | b[511] = 0xaa; |
681 | } | 661 | } |
682 | 662 | ||
663 | /* Read line; return 0 or first printable non-space char */ | ||
664 | static int | ||
665 | read_line(const char *prompt) | ||
666 | { | ||
667 | int sz; | ||
668 | |||
669 | sz = read_line_input(NULL, prompt, line_buffer, sizeof(line_buffer)); | ||
670 | if (sz <= 0) | ||
671 | exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */ | ||
672 | |||
673 | if (line_buffer[sz-1] == '\n') | ||
674 | line_buffer[--sz] = '\0'; | ||
675 | |||
676 | line_ptr = line_buffer; | ||
677 | while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ') | ||
678 | line_ptr++; | ||
679 | return *line_ptr; | ||
680 | } | ||
681 | |||
683 | static char | 682 | static char |
684 | read_nonempty(const char *mesg) | 683 | read_nonempty(const char *mesg) |
685 | { | 684 | { |
@@ -1614,53 +1613,74 @@ read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char * | |||
1614 | 1613 | ||
1615 | if (*line_ptr == '+' || *line_ptr == '-') { | 1614 | if (*line_ptr == '+' || *line_ptr == '-') { |
1616 | int minus = (*line_ptr == '-'); | 1615 | int minus = (*line_ptr == '-'); |
1617 | int absolute = 0; | 1616 | unsigned scale_shift; |
1618 | 1617 | ||
1619 | value = atoi(line_ptr + 1); | 1618 | if (sizeof(value) <= sizeof(long)) |
1619 | value = strtoul(line_ptr + 1, NULL, 10); | ||
1620 | else | ||
1621 | value = strtoull(line_ptr + 1, NULL, 10); | ||
1620 | 1622 | ||
1621 | /* (1) if 2nd char is digit, use_default = 0. | 1623 | /* (1) if 2nd char is digit, use_default = 0. |
1622 | * (2) move line_ptr to first non-digit. */ | 1624 | * (2) move line_ptr to first non-digit. |
1625 | */ | ||
1623 | while (isdigit(*++line_ptr)) | 1626 | while (isdigit(*++line_ptr)) |
1624 | use_default = 0; | 1627 | use_default = 0; |
1625 | 1628 | ||
1626 | switch (*line_ptr) { | 1629 | scale_shift = 0; |
1627 | case 'c': | 1630 | switch (*line_ptr | 0x20) { |
1628 | case 'C': | ||
1629 | if (!display_in_cyl_units) | ||
1630 | value *= g_heads * g_sectors; | ||
1631 | break; | ||
1632 | case 'K': | ||
1633 | absolute = 1024; | ||
1634 | break; | ||
1635 | case 'k': | 1631 | case 'k': |
1636 | absolute = 1000; | 1632 | scale_shift = 10; /* 1024 */ |
1637 | break; | 1633 | break; |
1634 | /* | ||
1635 | * fdisk from util-linux 2.31 seems to round '+NNNk' and '+NNNK' to megabytes, | ||
1636 | * (512-byte) sector count of the partition does not equal NNN*2: | ||
1637 | * | ||
1638 | * Last sector, +sectors or +size{K,M,G,T,P} (1953792-1000215215, default 1000215215): +9727k | ||
1639 | * Device Boot Start End Sectors Size Id Type | ||
1640 | * /dev/sdaN 1953792 1972223 18432 9M 83 Linux <-- size exactly 9*1024*1024 bytes | ||
1641 | * | ||
1642 | * Last sector, +sectors or +size{K,M,G,T,P} (1953792-1000215215, default 1000215215): +9728k | ||
1643 | * /dev/sdaN 1953792 1974271 20480 10M 83 Linux <-- size exactly 10*1024*1024 bytes | ||
1644 | * | ||
1645 | * If 'k' means 1000 bytes (not 1024), then 9728k = 9728*1000 = 9500*1024, | ||
1646 | * exactly halfway from 9000 to 10000, which explains why it jumps to next mbyte | ||
1647 | * at this value. | ||
1648 | * | ||
1649 | * 'm' does not seem to behave this way: it means 1024*1024 bytes. | ||
1650 | * | ||
1651 | * Not sure we want to copy this. If user says he wants 1234kbyte partition, | ||
1652 | * we do _exactly that_: 1234kbytes = 2468 sectors. | ||
1653 | */ | ||
1638 | case 'm': | 1654 | case 'm': |
1639 | case 'M': | 1655 | scale_shift = 20; /* 1024*1024 */ |
1640 | absolute = 1000000; | ||
1641 | break; | 1656 | break; |
1642 | case 'g': | 1657 | case 'g': |
1643 | case 'G': | 1658 | scale_shift = 30; /* 1024*1024*1024 */ |
1644 | absolute = 1000000000; | 1659 | break; |
1660 | case 't': | ||
1661 | scale_shift = 40; /* 1024*1024*1024*1024 */ | ||
1645 | break; | 1662 | break; |
1646 | default: | 1663 | default: |
1647 | break; | 1664 | break; |
1648 | } | 1665 | } |
1649 | if (absolute) { | 1666 | if (scale_shift) { |
1650 | ullong bytes; | 1667 | ullong bytes; |
1651 | unsigned long unit; | 1668 | unsigned long unit; |
1652 | 1669 | ||
1653 | bytes = (ullong) value * absolute; | 1670 | bytes = (ullong) value << scale_shift; |
1654 | unit = sector_size * units_per_sector; | 1671 | unit = sector_size * units_per_sector; |
1655 | bytes += unit/2; /* round */ | 1672 | bytes += unit/2; /* round */ |
1656 | bytes /= unit; | 1673 | bytes /= unit; |
1657 | value = bytes; | 1674 | value = (bytes != 0 ? bytes - 1 : 0); |
1658 | } | 1675 | } |
1659 | if (minus) | 1676 | if (minus) |
1660 | value = -value; | 1677 | value = -value; |
1661 | value += base; | 1678 | value += base; |
1662 | } else { | 1679 | } else { |
1663 | value = atoi(line_ptr); | 1680 | if (sizeof(value) <= sizeof(long)) |
1681 | value = strtoul(line_ptr, NULL, 10); | ||
1682 | else | ||
1683 | value = strtoull(line_ptr, NULL, 10); | ||
1664 | while (isdigit(*line_ptr)) { | 1684 | while (isdigit(*line_ptr)) { |
1665 | line_ptr++; | 1685 | line_ptr++; |
1666 | use_default = 0; | 1686 | use_default = 0; |
@@ -1725,8 +1745,9 @@ get_existing_partition(int warn, unsigned max) | |||
1725 | } | 1745 | } |
1726 | 1746 | ||
1727 | static int | 1747 | static int |
1728 | get_nonexisting_partition(int warn, unsigned max) | 1748 | get_nonexisting_partition(void) |
1729 | { | 1749 | { |
1750 | const int max = 4; | ||
1730 | int pno = -1; | 1751 | int pno = -1; |
1731 | unsigned i; | 1752 | unsigned i; |
1732 | 1753 | ||
@@ -1748,7 +1769,7 @@ get_nonexisting_partition(int warn, unsigned max) | |||
1748 | return -1; | 1769 | return -1; |
1749 | 1770 | ||
1750 | not_unique: | 1771 | not_unique: |
1751 | return get_partition(warn, max); | 1772 | return get_partition(/*warn*/ 0, max); |
1752 | } | 1773 | } |
1753 | 1774 | ||
1754 | 1775 | ||
@@ -2526,8 +2547,9 @@ add_partition(int n, int sys) | |||
2526 | stop = limit; | 2547 | stop = limit; |
2527 | } else { | 2548 | } else { |
2528 | snprintf(mesg, sizeof(mesg), | 2549 | snprintf(mesg, sizeof(mesg), |
2529 | "Last %s or +size or +sizeM or +sizeK", | 2550 | "Last %s or +size{,K,M,G,T}", |
2530 | str_units(SINGULAR)); | 2551 | str_units(SINGULAR) |
2552 | ); | ||
2531 | stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg); | 2553 | stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg); |
2532 | if (display_in_cyl_units) { | 2554 | if (display_in_cyl_units) { |
2533 | stop = stop * units_per_sector - 1; | 2555 | stop = stop * units_per_sector - 1; |
@@ -2611,15 +2633,16 @@ new_partition(void) | |||
2611 | } else { | 2633 | } else { |
2612 | char c, line[80]; | 2634 | char c, line[80]; |
2613 | snprintf(line, sizeof(line), | 2635 | snprintf(line, sizeof(line), |
2614 | "Command action\n" | 2636 | "Partition type\n" |
2615 | " %s\n" | 2637 | " p primary partition (1-4)\n" |
2616 | " p primary partition (1-4)\n", | 2638 | " %s\n", |
2617 | (extended_offset ? | 2639 | (extended_offset ? |
2618 | "l logical (5 or over)" : "e extended")); | 2640 | "l logical (5 or over)" : "e extended")); |
2619 | while (1) { | 2641 | while (1) { |
2620 | c = read_nonempty(line); | 2642 | c = read_nonempty(line); |
2621 | if ((c | 0x20) == 'p') { | 2643 | c |= 0x20; /* lowercase */ |
2622 | i = get_nonexisting_partition(0, 4); | 2644 | if (c == 'p') { |
2645 | i = get_nonexisting_partition(); | ||
2623 | if (i >= 0) | 2646 | if (i >= 0) |
2624 | add_partition(i, LINUX_NATIVE); | 2647 | add_partition(i, LINUX_NATIVE); |
2625 | return; | 2648 | return; |
@@ -2629,7 +2652,7 @@ new_partition(void) | |||
2629 | return; | 2652 | return; |
2630 | } | 2653 | } |
2631 | if (c == 'e' && !extended_offset) { | 2654 | if (c == 'e' && !extended_offset) { |
2632 | i = get_nonexisting_partition(0, 4); | 2655 | i = get_nonexisting_partition(); |
2633 | if (i >= 0) | 2656 | if (i >= 0) |
2634 | add_partition(i, EXTENDED); | 2657 | add_partition(i, EXTENDED); |
2635 | return; | 2658 | return; |