[parted-devel] [PATCH 1/2] parted: mkpart: subtract one sector fron end if IEC unit is used

Petr Uzel petr.uzel at suse.cz
Sat Oct 22 13:22:09 UTC 2011


Before, if the user specified start and end in mkpart command using
IEC units, parted created a partition that starts and ends exactly on
these positions. With such behavior, it is impossible to create
partitions as follows: 1MiB-2MiB, 2MiB-3MiB - parted would complain
that it cannot create the second partition, because the first one
occupied sectors 2048-4096 and the second one sectors 4096-3072,
so they would overlap at sector 4096.

With this patch, if the user uses IEC units to specify end of the
partition, parted creates the partition which ends one sector before
the specified position.

See also
https://lists.gnu.org/archive/html/bug-parted/2011-10/msg00009.html

* parted/ui.c (command_line_get_sector): Add parameter to retrieve
raw input from user.
* parted/ui.h (command_line_get_sector): Adjust prototype of function.
* parted/parted.c (_adjust_end_if_iec): New function.
(_rstrip_string): New function.
(_string_ends_with_iec_unit): New function.
(do_mkpart): Call _adjust_end_if_iec(). Use new parameter of
command_line_get_sector function.
(do_rescue): Adjust call to command_line_get_sector.
* NEWS: Mention the changed behavior.
---
 NEWS            |    6 ++++
 parted/parted.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 parted/ui.c     |    7 +++-
 parted/ui.h     |    2 +-
 4 files changed, 82 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index b7fb56b..bc5152b 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,12 @@ GNU parted NEWS                                    -*- outline -*-
   cause an MSDOS partition table to be mistakenly identified as pc98.
   [bug present since the beginning]
 
+** Changes in behavior
+
+  parted: mkpart command has changed semantics with regard to specifying end
+  of the partition. If the end is specified using MiB, GiB, etc. unit, parted
+  subtracts one sector from the specified value. With this change, it is now
+  possible to create partitions like 1MiB-2MiB, 2MiB-3MiB and so on.
 
 * Noteworthy changes in release 3.0 (2011-05-30) [stable]
 
diff --git a/parted/parted.c b/parted/parted.c
index 87f30eb..6f90cab 100644
--- a/parted/parted.c
+++ b/parted/parted.c
@@ -523,6 +523,68 @@ error:
         return 0;
 }
 
+/* Strip whitespace character from end of the string, in place */
+void _rstrip_string(char* str)
+{
+        if (!str)
+                return;
+
+        int i;
+        for (i = strlen(str) - 1; i; i--)
+                if (isspace(str[i]))
+                    str[i]='\0';
+        else
+                break;
+}
+
+/* Return true, if str ends with [kMGT]iB, i.e. the IEC unit */
+static bool
+_string_ends_with_iec_unit(const char* str)
+{
+        /* 3 characters for the IEC unit and at least 1 digit */
+        if (!str || strlen(str) < 4)
+                return false;
+
+        char *last3 = str + strlen(str) - 3;
+        if (!strcmp(last3, "kiB") || !strcmp(last3, "MiB") ||
+            !strcmp(last3, "GiB") || !strcmp(last3, "TiB"))
+                return true;
+
+        return false;
+}
+
+/* If the selected unit is one of kiB, MiB, GiB or TiB and the partition is not
+ * only 1 sector long, then adjust the end so that it is one sector before the
+ * given position. Also adjust range_end accordingly. Thus next partition can
+ * start immediately after this one.
+ *
+ * To be called after end sector is read from the user.
+ *
+ * https://lists.gnu.org/archive/html/bug-parted/2011-10/msg00009.html
+ */
+static void
+_adjust_end_if_iec (PedSector* start, PedSector* end,
+                    PedGeometry* range_end, char* end_input)
+{
+        PED_ASSERT(start);
+        PED_ASSERT(end);
+        PED_ASSERT(range_end);
+
+        /* 1s partition - do not move the end */
+        if (*start == *end)
+                return;
+
+        _rstrip_string(end_input);
+        PedUnit unit = ped_unit_get_default();
+        if (_string_ends_with_iec_unit(end_input) ||
+            (unit == PED_UNIT_KIBIBYTE) || (unit == PED_UNIT_MEBIBYTE) ||
+            (unit == PED_UNIT_GIBIBYTE) || (unit == PED_UNIT_TEBIBYTE)) {
+                *end -= 1;
+                range_end->start -= 1;
+                range_end->end -= 1;
+        }
+}
+
 static int
 do_mkpart (PedDevice** dev)
 {
@@ -584,11 +646,15 @@ do_mkpart (PedDevice** dev)
         }
         free (peek_word);
 
-        if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start))
+        if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start, NULL))
                 goto error_destroy_disk;
-        if (!command_line_get_sector (_("End?"), *dev, &end, &range_end))
+        char *end_input;
+        if (!command_line_get_sector (_("End?"), *dev, &end, &range_end, &end_input))
                 goto error_destroy_disk;
 
+        _adjust_end_if_iec(&start, &end, range_end, end_input);
+        free(end_input);
+
         /* processing starts here */
         part = ped_partition_new (disk, part_type, fs_type, start, end);
         if (!part)
@@ -1336,9 +1402,9 @@ do_rescue (PedDevice** dev)
         if (!disk)
                 goto error;
 
-        if (!command_line_get_sector (_("Start?"), *dev, &start, NULL))
+        if (!command_line_get_sector (_("Start?"), *dev, &start, NULL, NULL))
                 goto error_destroy_disk;
-        if (!command_line_get_sector (_("End?"), *dev, &end, NULL))
+        if (!command_line_get_sector (_("End?"), *dev, &end, NULL, NULL))
                 goto error_destroy_disk;
 
         fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)),
diff --git a/parted/ui.c b/parted/ui.c
index 77bb24c..1def754 100644
--- a/parted/ui.c
+++ b/parted/ui.c
@@ -924,7 +924,7 @@ command_line_get_integer (const char* prompt, int* value)
 
 int
 command_line_get_sector (const char* prompt, PedDevice* dev, PedSector* value,
-                         PedGeometry** range)
+                         PedGeometry** range, char** raw_input)
 {
         char*    def_str;
         char*    input;
@@ -960,7 +960,10 @@ command_line_get_sector (const char* prompt, PedDevice* dev, PedSector* value,
 
         valid = ped_unit_parse (input, dev, value, range);
 
-        free (input);
+        if (raw_input)
+            *raw_input = input;
+        else
+            free (input);
         return valid;
 }
 
diff --git a/parted/ui.h b/parted/ui.h
index 44b521a..14ba380 100644
--- a/parted/ui.h
+++ b/parted/ui.h
@@ -52,7 +52,7 @@ extern char* command_line_get_word (const char* prompt, const char* def,
 				    int multi_word);
 extern int command_line_get_integer (const char* prompt, int* value);
 extern int command_line_get_sector (const char* prompt, PedDevice* dev,
-				    PedSector* value, PedGeometry** range);
+				    PedSector* value, PedGeometry** range, char** raw_input);
 extern int command_line_get_state (const char* prompt, int* value);
 extern int command_line_get_device (const char* prompt, PedDevice** value);
 extern int command_line_get_disk (const char* prompt, PedDisk** value)
-- 
1.7.3.4




More information about the parted-devel mailing list