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>
.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")),
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;
}
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;
}
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 */
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;
+}
+
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:
*
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;
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;
}
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;
}