[Parted-commits] GNU Parted Official Repository: Changes to 'master'

Jim Meyering meyering at alioth.debian.org
Wed Nov 2 16:28:18 UTC 2011


 NEWS                               |    6 ++
 bootstrap.conf                     |    2 
 parted/parted.c                    |   86 +++++++++++++++++++++++++++++++++++--
 parted/ui.c                        |    7 ++-
 parted/ui.h                        |    2 
 tests/Makefile.am                  |    1 
 tests/t0207-IEC-binary-notation.sh |    2 
 tests/t0208-mkpart-end-in-IEC.sh   |   61 ++++++++++++++++++++++++++
 8 files changed, 159 insertions(+), 8 deletions(-)

New commits:
commit 31065fb2aa4395b5cfbfe078270eeb95bdfb1420
Author: Petr Uzel <petr.uzel at suse.cz>
Date:   Sat Oct 22 15:22:09 2011 +0200

    tests: exercise the new feature
    
    * tests/t0208-mkpart-end-in-IEC.sh: New file.
    * tests/Makefile.am: Add it.

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5a8a539..63bcd31 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -18,6 +18,7 @@ TESTS = \
   t0205-gpt-list-clobbers-pmbr.sh \
   t0206-gpt-print-with-corrupt-primary-clobbers-pmbr.sh \
   t0207-IEC-binary-notation.sh \
+  t0208-mkpart-end-in-IEC.sh \
   t0220-gpt-msftres.sh \
   t0250-gpt.sh \
   t0280-gpt-corrupt.sh \
diff --git a/tests/t0208-mkpart-end-in-IEC.sh b/tests/t0208-mkpart-end-in-IEC.sh
new file mode 100644
index 0000000..475190b
--- /dev/null
+++ b/tests/t0208-mkpart-end-in-IEC.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+# Make sure parted mkpart ends the partition one sector before the specified
+# value if end is specified with IEC units.
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../parted
+
+require_512_byte_sector_size_
+n_mbs=8
+dev=dev-file
+
+dd if=/dev/null of=$dev bs=1M seek=$n_mbs || fail=1
+# create 1st partition
+parted --align=none -s $dev mklabel gpt mkpart p1 1MiB 2MiB > err 2>&1 || fail=1
+compare err /dev/null || fail=1  # expect no output
+#parted -m -s $dev u s p > exp || fail=1
+
+# create 2nd partition - they should not overlap
+# this time specify default unit
+parted --align=none -s $dev unit MiB mkpart p2 2 3 > err 2>&1 || fail=1
+compare err /dev/null || fail=1  # expect no output
+
+# create 3rd partition - expect no overlap
+# specify default unit, but explicitly override it
+parted --align=none -s $dev unit TB mkpart p3 3MiB 4MiB > err 2>&1 || fail=1
+compare err /dev/null || fail=1  # expect no output
+
+# Specify default unit of MiB, yet use explicit ending sector number.
+parted --align=none -s $dev unit MiB mkpart p4 4MiB 10239s > err 2>&1 || fail=1
+compare err /dev/null || fail=1  # expect no output
+
+# check boundaries of the partitions
+parted -m -s $dev u s p > out || fail=1
+
+# prepare expected output
+cat <<EOF > exp || framework_failure
+1:2048s:4095s:2048s::p1:;
+2:4096s:6143s:2048s::p2:;
+3:6144s:8191s:2048s::p3:;
+4:8192s:10239s:2048s::p4:;
+EOF
+
+# compare expected and actual outputs
+sed -e "1,2d" out > k; mv k out
+compare out exp || fail=1
+
+Exit $fail

commit 961abca12d1766264651dbe08284aeec3c0396c6
Author: Petr Uzel <petr.uzel at suse.cz>
Date:   Sat Oct 22 15:22:09 2011 +0200

    parted: mkpart: DWIM for IEC ending sector numbers like 2MiB and 9GiB
    
    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.
    (_strip_trailing_spaces): 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.
    * bootstrap.conf (gnulib_modules): Add these: c-ctype, c-strcase.
    * tests/t0207-IEC-binary-notation.sh: Adjust to new semantics.
    * NEWS: Mention the changed behavior.
    
    Notable adjustments:
    - s/isspace/c_isblank/ so that parsing is locale-independent
    - avoid an array-bounds error:
      * parted/parted.c (_strip_trailing_spaces): Don't deref str[-1]
      for an empty string.

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/bootstrap.conf b/bootstrap.conf
index 7c79d50..14123a2 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -28,6 +28,8 @@ gnulib_modules="
   announce-gen
   argmatch
   assert
+  c-ctype
+  c-strcase
   calloc-gnu
   canonicalize-lgpl
   close
diff --git a/parted/parted.c b/parted/parted.c
index 87f30eb..b6f89aa 100644
--- a/parted/parted.c
+++ b/parted/parted.c
@@ -53,6 +53,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <limits.h>
+#include "c-ctype.h"
+#include "c-strcase.h"
 #include "xalloc.h"
 
 #ifdef ENABLE_MTRACE
@@ -523,6 +525,78 @@ error:
         return 0;
 }
 
+/* Strip blanks from the end of string STR, in place.  */
+void _strip_trailing_spaces(char *str)
+{
+        if (!str)
+                return;
+        size_t i = strlen(str);
+        while (i && c_isblank(str[--i]))
+                str[i]='\0';
+}
+
+/* Return true, if str ends with [kMGTPEZY]iB, i.e. IEC units.  */
+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 const *p = str + strlen(str) - 3;
+        return strchr ("kMGTPEZY", *p) && c_strcasecmp (p+1, "iB") == 0;
+}
+
+/* Return true if str ends with explicit unit identifier.
+ * Do not parse the unit, just check if the unit is specified.
+ * This function expects trailing spaces to be already stripped.
+ */
+static bool
+_string_has_unit_suffix(const char *str)
+{
+        /* At least 1 digit and 1 character to meet the condition */
+        if (!str || strlen(str) < 2)
+                return false;
+
+        if (!isdigit(str[strlen(str) - 1]))
+                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;
+
+        _strip_trailing_spaces(end_input);
+        PedUnit unit = ped_unit_get_default();
+        if (_string_ends_with_iec_unit(end_input) ||
+            (!_string_has_unit_suffix(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 +658,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 +1414,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)
diff --git a/tests/t0207-IEC-binary-notation.sh b/tests/t0207-IEC-binary-notation.sh
index 2228ce1..343b8c1 100644
--- a/tests/t0207-IEC-binary-notation.sh
+++ b/tests/t0207-IEC-binary-notation.sh
@@ -23,7 +23,7 @@ n_sectors=3000
 dev=dev-file
 
 dd if=/dev/null of=$dev bs=$ss seek=$n_sectors || fail=1
-parted --align=none -s $dev mklabel gpt mkpart p1 $((64*1024))B $((1024*1024))B \
+parted --align=none -s $dev mklabel gpt mkpart p1 $((64*1024))B $((1024*1024-$ss))B \
     > err 2>&1 || fail=1
 compare err /dev/null || fail=1
 parted -m -s $dev u s p > exp || fail=1



More information about the Parted-commits mailing list