summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2018-01-02 16:43:22 +0100
committerKarel Zak2018-01-02 16:43:22 +0100
commit2dd2880f12f402e137cbfab774fde8ceef1c71a0 (patch)
treeb36ea02fbfc783f55f6f77e3eb201c0102b997a8
parentrtcwake: wait stdin to settle down before entering a system sleep (diff)
downloadkernel-qcow2-util-linux-2dd2880f12f402e137cbfab774fde8ceef1c71a0.tar.gz
kernel-qcow2-util-linux-2dd2880f12f402e137cbfab774fde8ceef1c71a0.tar.xz
kernel-qcow2-util-linux-2dd2880f12f402e137cbfab774fde8ceef1c71a0.zip
libfdisk: extend API to provide label specific geometry ranges
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>
-rw-r--r--disk-utils/fdisk-menu.c34
-rw-r--r--libfdisk/src/dos.c8
-rw-r--r--libfdisk/src/fdiskP.h3
-rw-r--r--libfdisk/src/label.c70
-rw-r--r--libfdisk/src/libfdisk.h.in7
-rw-r--r--libfdisk/src/libfdisk.sym6
-rw-r--r--libfdisk/src/sun.c21
7 files changed, 138 insertions, 11 deletions
diff --git a/disk-utils/fdisk-menu.c b/disk-utils/fdisk-menu.c
index 8220d6586..b8a2e6003 100644
--- a/disk-utils/fdisk-menu.c
+++ b/disk-utils/fdisk-menu.c
@@ -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;
}
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 9759ce2e0..fd6e2cbb5 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -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;
}
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index b81d6fc7a..0b9d43413 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -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 */
diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c
index c1afdf1b9..304ea34e4 100644
--- a/libfdisk/src/label.c
+++ b/libfdisk/src/label.c
@@ -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;
+}
+
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index 3586d6626..ddf4a91e6 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -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:
*
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index 2c892a0c3..8d38332b9 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -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;
diff --git a/libfdisk/src/sun.c b/libfdisk/src/sun.c
index 923b73e32..0be4d8df6 100644
--- a/libfdisk/src/sun.c
+++ b/libfdisk/src/sun.c
@@ -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;
}