aboutsummaryrefslogtreecommitdiff
path: root/util-linux/fdisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'util-linux/fdisk.c')
-rw-r--r--util-linux/fdisk.c131
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 */
171typedef uint32_t sector_t; 171typedef 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 */
643static int
644read_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
661static void 641static void
662set_all_unchanged(void) 642set_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 */
664static int
665read_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
683static char 682static char
684read_nonempty(const char *mesg) 683read_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
1727static int 1747static int
1728get_nonexisting_partition(int warn, unsigned max) 1748get_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;