bug-parted
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#61582: Different behaviour for "mkpart" command while using "kiB" an


From: Pavel Iatchenii
Subject: bug#61582: Different behaviour for "mkpart" command while using "kiB" and "KiB" units (case sensitivity)
Date: Fri, 17 Feb 2023 17:10:31 +0000

Introduction

When you open man page or gnu documentation, you may refer to "unit" command and think that "KiB" is a correct interpretation of, whatever its name, 1024 bytes. And it actually works for using this command as well as creating a single partition with "mkpart" command. Then, there is a BIG one: you can’t create adjacent partitions while encountering a weird error:


parted -s /dev/nvme1n1 mkpart primary 128KiB 28692352KiB mkpart primary 28692352KiB 29216640KiB
Error: You requested a partition from 29.4GB to 29.9GB (sectors 7173088..7304160).
The closest location we can manage is 29.4GB to 29.9GB (sectors 7173089..7304160).

However, if you proceed with "unit" command as in documentation and keep the case of "KiB", then partitions are created successfully:

parted -s /dev/nvme1n1 unit KiB mkpart primary 128 28692352 mkpart primary 28692352 29216640

Where could be the catch?

  1. The code of the above-mentioned "unit" command contains a static constant array of units. It looks like this and has "kiB" with lower case “k”, though further down checks names without case sensitivity.
static const char* unit_names[] = {
    "s",
    "B",
    "kB",
    "MB",
    "GB",
    "TB",
    "compact",
    "cyl",
    "chs",
    "%",
    "kiB",
    "MiB",
    "GiB",
    "TiB"
};

  1. There is adjustment to be called whenever the partition is created or resized. It looks like this and also checks for "kiB", though with case sensitivity this time.
/* 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;
}

/* 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.
 *
 */
static void
_adjust_end_if_iec (PedSector* start, PedSector* end,
                    PedGeometry* range_end, char* end_input)
{
        ...
        if (_string_ends_with_iec_unit(end_input) || ...) {
                *end -= 1;
                range_end->start -= 1;
                range_end->end -= 1;
        }
}


Suggestion

Even though units are parsed case-insensitively in most cases, it may be crucial in other cases and lead to the original issue. As such, whether this is a following ICE standard or archaeology, the documentation of "parted" utility could clarify this point and eliminate such problems in the future. Alternatively, both catches could be consistent with each other and treat case sensitivity in the same manner, according to documentation.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]