]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: extend API to provide label specific geometry ranges
authorKarel Zak <kzak@redhat.com>
Tue, 2 Jan 2018 15:43:22 +0000 (16:43 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 2 Jan 2018 15:43:22 +0000 (16:43 +0100)
Now fdisk provides DOS specific geometry ranges in expert menu.

Addresses: https://github.com/karelzak/util-linux/issues/556
Signed-off-by: Karel Zak <kzak@redhat.com>
disk-utils/fdisk-menu.c
libfdisk/src/dos.c
libfdisk/src/fdiskP.h
libfdisk/src/label.c
libfdisk/src/libfdisk.h.in
libfdisk/src/libfdisk.sym
libfdisk/src/sun.c

index 8220d6586e1b4bd4bd8bbb81561e36b1abd4de77..b8a2e6003204f93e7f1ef430faa012aa855922bb 100644 (file)
@@ -151,7 +151,7 @@ static const struct menu menu_geo = {
        .callback = geo_menu_cb,
        .exclude = FDISK_DISKLABEL_GPT | FDISK_DISKLABEL_BSD,
        .entries = {
-               MENU_XSEP(N_("Geometry")),
+               MENU_XSEP(N_("Geometry (for the current label)")),
                MENU_XENT('c', N_("change number of cylinders")),
                MENU_XENT('h', N_("change number of heads")),
                MENU_XENT('s', N_("change number of sectors/track")),
@@ -1004,32 +1004,50 @@ static int bsd_menu_cb(struct fdisk_context **cxt0,
        return rc;
 }
 
-/* C/H/S commands */
+/* C/H/S commands
+ *
+ * The geometry setting from this dialog is not persistent and maybe reseted by
+ * fdisk_reset_device_properties() (for example when you create a new disk
+ * label). Note that on command line specified -C/-H/-S setting is persistent
+ * as it's based on fdisk_save_user_geometry().
+ */
 static int geo_menu_cb(struct fdisk_context **cxt0,
                       const struct menu *menu __attribute__((__unused__)),
                       const struct menu_entry *ent)
 {
        struct fdisk_context *cxt = *cxt0;
+       struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
        int rc = -EINVAL;
        uintmax_t c = 0, h = 0, s = 0;
+       fdisk_sector_t mi, ma;
 
        DBG(MENU, ul_debug("enter GEO menu"));
 
        assert(cxt);
        assert(ent);
 
+       /* default */
+       if (!lb)
+               lb = fdisk_get_label(cxt, "dos");
+
        switch (ent->key) {
        case 'c':
-               rc =  fdisk_ask_number(cxt, 1, fdisk_get_geom_cylinders(cxt),
-                               1048576, _("Number of cylinders"), &c);
+               fdisk_label_get_geomrange_cylinders(lb, &mi, &ma);
+               rc =  fdisk_ask_number(cxt, mi, fdisk_get_geom_cylinders(cxt),
+                               ma, _("Number of cylinders"), &c);
                break;
        case 'h':
-               rc =  fdisk_ask_number(cxt, 1, fdisk_get_geom_heads(cxt),
-                               256, _("Number of heads"), &h);
+       {
+               unsigned int i, a;
+               fdisk_label_get_geomrange_heads(lb, &i, &a);
+               rc =  fdisk_ask_number(cxt, i, fdisk_get_geom_heads(cxt),
+                               a, _("Number of heads"), &h);
                break;
+       }
        case 's':
-               rc =  fdisk_ask_number(cxt, 1, fdisk_get_geom_sectors(cxt),
-                               63, _("Number of sectors"), &s);
+               fdisk_label_get_geomrange_sectors(lb, &mi, &ma);
+               rc =  fdisk_ask_number(cxt, mi, fdisk_get_geom_sectors(cxt),
+                               ma, _("Number of sectors"), &s);
                break;
        }
 
index 9759ce2e0abac54781a1659fed028b0e589fb32f..fd6e2cbb53c584350d5aed80eeafa7f926b915e0 100644 (file)
@@ -2485,6 +2485,14 @@ struct fdisk_label *fdisk_new_dos_label(struct fdisk_context *cxt)
        lb->fields = dos_fields;
        lb->nfields = ARRAY_SIZE(dos_fields);
 
+       lb->geom_min.sectors = 1;
+       lb->geom_min.heads = 1;
+       lb->geom_min.cylinders = 1;
+
+       lb->geom_max.sectors = 63;
+       lb->geom_max.heads = 256;
+       lb->geom_max.cylinders = 1048576;
+
        return lb;
 }
 
index b81d6fc7a2349562aae7be42b1a9f4c9edae25f0..0b9d4341320994d1cb4e3912104fbc59c69f4652 100644 (file)
@@ -279,6 +279,9 @@ struct fdisk_label {
 
        int                     flags;          /* FDISK_LABEL_FL_* flags */
 
+       struct fdisk_geometry   geom_min;       /* minimal geometry */
+       struct fdisk_geometry   geom_max;       /* maximal geometry */
+
        unsigned int            changed:1,      /* label has been modified */
                                disabled:1;     /* this driver is disabled at all */
 
index c1afdf1b9779c519833c8b886d1db1c6300e89e0..304ea34e4ba6a9717bfcb0c319a6c8588477e9f6 100644 (file)
@@ -628,3 +628,73 @@ int fdisk_label_is_disabled(const struct fdisk_label *lb)
        assert(lb);
        return lb ? lb->disabled : 0;
 }
+
+/**
+ * fdisk_label_get_geomrange_sectors:
+ * @lb: label
+ * @mi: minimal number
+ * @ma: maximal number
+ *
+ * The function provides minimal and maximal geometry supported for the label,
+ * if no range defined by library than returns -ENOSYS.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_label_get_geomrange_sectors(const struct fdisk_label *lb,
+                                       fdisk_sector_t *mi, fdisk_sector_t *ma)
+{
+       if (!lb || lb->geom_min.sectors == 0)
+               return -ENOSYS;
+       if (mi)
+               *mi = lb->geom_min.sectors;
+       if (ma)
+               *ma = lb->geom_max.sectors;
+       return 0;
+}
+
+/**
+ * fdisk_label_get_geomrange_heads:
+ * @lb: label
+ * @mi: minimal number
+ * @ma: maximal number
+ *
+ * The function provides minimal and maximal geometry supported for the label,
+ * if no range defined by library than returns -ENOSYS.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_label_get_geomrange_heads(const struct fdisk_label *lb,
+                                       unsigned int *mi, unsigned int *ma)
+{
+       if (!lb || lb->geom_min.heads == 0)
+               return -ENOSYS;
+       if (mi)
+               *mi = lb->geom_min.heads;
+       if (ma)
+               *ma = lb->geom_max.heads;
+       return 0;
+}
+
+/**
+ * fdisk_label_get_geomrange_cylinders:
+ * @lb: label
+ * @mi: minimal number
+ * @ma: maximal number
+ *
+ * The function provides minimal and maximal geometry supported for the label,
+ * if no range defined by library than returns -ENOSYS.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_label_get_geomrange_cylinders(const struct fdisk_label *lb,
+                                       fdisk_sector_t *mi, fdisk_sector_t *ma)
+{
+       if (!lb || lb->geom_min.cylinders == 0)
+               return -ENOSYS;
+       if (mi)
+               *mi = lb->geom_min.cylinders;
+       if (ma)
+               *ma = lb->geom_max.cylinders;
+       return 0;
+}
+
index 3586d66267f1bfb22634e13ad43b06985d09ae13..ddf4a91e67012d634533d9b52b88bb5a3c010cfc 100644 (file)
@@ -321,6 +321,13 @@ extern int fdisk_locate_disklabel(struct fdisk_context *cxt, int n,
                                  uint64_t *offset,
                                  size_t *size);
 
+extern int fdisk_label_get_geomrange_cylinders(const struct fdisk_label *lb,
+                       fdisk_sector_t *mi, fdisk_sector_t *ma);
+extern int fdisk_label_get_geomrange_heads(const struct fdisk_label *lb,
+                        unsigned int *mi, unsigned int *ma);
+extern int fdisk_label_get_geomrange_sectors(const struct fdisk_label *lb,
+                        fdisk_sector_t *mi, fdisk_sector_t *ma);
+
 /**
  * fdisk_labelitem_gen:
  *
index 2c892a0c394eaec67a1f7ba823ff2cad809d7855..8d38332b9aa51827ed3fce811a256fea03ee69d0 100644 (file)
@@ -291,3 +291,9 @@ FDISK_2.31 {
        fdisk_has_dialogs;
        fdisk_save_user_grain;
 } FDISK_2.30;
+
+FDISK_2.32 {
+       fdisk_label_get_geomrange_sectors;
+       fdisk_label_get_geomrange_heads;
+       fdisk_label_get_geomrange_cylinders;
+} FDISK_2.31;
index 923b73e326cdd2be8baeda5e082bf98ae57466be..0be4d8df68933a665841665a568e9367eb2a5bc8 100644 (file)
@@ -182,11 +182,19 @@ static void ask_geom(struct fdisk_context *cxt)
 
        assert(cxt);
 
-       if (fdisk_ask_number(cxt, 1, 1, 1024, _("Heads"), &res) == 0)
+       if (fdisk_ask_number(cxt, cxt->label->geom_min.heads, 1,
+                                 cxt->label->geom_max.heads,
+                                 _("Heads"), &res) == 0)
                cxt->geom.heads = res;
-       if (fdisk_ask_number(cxt, 1, 1, 1024, _("Sectors/track"), &res) == 0)
+
+       if (fdisk_ask_number(cxt, cxt->label->geom_min.sectors, 1,
+                                 cxt->label->geom_max.sectors,
+                                 _("Sectors/track"), &res) == 0)
                cxt->geom.sectors = res;
-       if (fdisk_ask_number(cxt, 1, 1, USHRT_MAX, _("Cylinders"), &res) == 0)
+
+       if (fdisk_ask_number(cxt, cxt->label->geom_min.cylinders, 1,
+                                 cxt->label->geom_max.cylinders,
+                                 _("Cylinders"), &res) == 0)
                cxt->geom.cylinders = res;
 }
 
@@ -1154,5 +1162,12 @@ struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt)
        lb->nfields = ARRAY_SIZE(sun_fields);
        lb->flags |= FDISK_LABEL_FL_REQUIRE_GEOMETRY;
 
+       lb->geom_min.sectors = 1;
+       lb->geom_min.heads = 1;
+       lb->geom_min.cylinders = 1;
+
+       lb->geom_max.sectors = 1024;
+       lb->geom_max.heads = 1024;
+       lb->geom_max.cylinders = USHRT_MAX;
        return lb;
 }