summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorKarel Zak2014-01-29 14:15:30 +0100
committerKarel Zak2014-03-11 11:35:13 +0100
commit20f878fee3ff40d0678e3cddfda06788c5ea87c9 (patch)
treedc65fe2c5e30e2675e96c13e96e98057f4e67237 /libfdisk
parentlib/mbalign: add mbs_safe_width() from tt.c (diff)
downloadkernel-qcow2-util-linux-20f878fee3ff40d0678e3cddfda06788c5ea87c9.tar.gz
kernel-qcow2-util-linux-20f878fee3ff40d0678e3cddfda06788c5ea87c9.tar.xz
kernel-qcow2-util-linux-20f878fee3ff40d0678e3cddfda06788c5ea87c9.zip
libfdisk: add ASKTYPE_MENU and context last_lba
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/src/ask.c130
-rw-r--r--libfdisk/src/dos.c61
-rw-r--r--libfdisk/src/fdiskP.h15
-rw-r--r--libfdisk/src/libfdisk.h19
4 files changed, 197 insertions, 28 deletions
diff --git a/libfdisk/src/ask.c b/libfdisk/src/ask.c
index 23e6263c6..8647817af 100644
--- a/libfdisk/src/ask.c
+++ b/libfdisk/src/ask.c
@@ -3,6 +3,9 @@
#include "fdiskP.h"
+static void fdisk_ask_menu_reset_items(struct fdisk_ask *ask);
+
+
struct fdisk_ask *fdisk_new_ask(void)
{
return calloc(1, sizeof(struct fdisk_ask));
@@ -13,6 +16,9 @@ void fdisk_reset_ask(struct fdisk_ask *ask)
assert(ask);
free(ask->query);
+ if (fdisk_is_ask(ask, MENU))
+ fdisk_ask_menu_reset_items(ask);
+
memset(ask, 0, sizeof(*ask));
}
@@ -490,6 +496,130 @@ int fdisk_ask_yesno_set_result(struct fdisk_ask *ask, uint64_t result)
return 0;
}
+/*
+ * menu
+ */
+int fdisk_ask_menu_set_default(struct fdisk_ask *ask, int dfl)
+{
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+ ask->data.menu.dfl = dfl;
+ return 0;
+}
+
+int fdisk_ask_menu_get_default(struct fdisk_ask *ask)
+{
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+ return ask->data.menu.dfl;
+}
+
+int fdisk_ask_menu_set_result(struct fdisk_ask *ask, int key)
+{
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+ ask->data.menu.result = key;
+ DBG(ASK, dbgprint("menu result: %c\n", key));
+ return 0;
+
+}
+
+int fdisk_ask_menu_get_result(struct fdisk_ask *ask, int *key)
+{
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+ if (key)
+ *key = ask->data.menu.result;
+ return 0;
+}
+
+/* returns: 0 = success, <0 = error, >0 = idx out-of-range */
+int fdisk_ask_menu_get_item(struct fdisk_ask *ask, size_t idx, int *key,
+ const char **name, const char **desc)
+{
+ size_t i;
+ struct ask_menuitem *mi;
+
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+
+ for (i = 0, mi = ask->data.menu.first; mi; mi = mi->next, i++) {
+ if (i == idx)
+ break;
+ }
+
+ if (!mi)
+ return 1; /* no more items */
+ if (key)
+ *key = mi->key;
+ if (name)
+ *name = mi->name;
+ if (desc)
+ *desc = mi->desc;
+ return 0;
+}
+
+static void fdisk_ask_menu_reset_items(struct fdisk_ask *ask)
+{
+ struct ask_menuitem *mi;
+
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+
+ for (mi = ask->data.menu.first; mi; ) {
+ struct ask_menuitem *next = mi->next;
+ free(mi);
+ mi = next;
+ }
+}
+
+size_t fdisk_ask_menu_get_nitems(struct fdisk_ask *ask)
+{
+ struct ask_menuitem *mi;
+ size_t n;
+
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+
+ for (n = 0, mi = ask->data.menu.first; mi; mi = mi->next, n++);
+
+ return n;
+}
+
+int fdisk_ask_menu_add_item(struct fdisk_ask *ask, int key,
+ const char *name, const char *desc)
+{
+ struct ask_menuitem *mi;
+
+ assert(ask);
+ assert(fdisk_is_ask(ask, MENU));
+
+ mi = calloc(1, sizeof(*mi));
+ if (!mi)
+ return -ENOMEM;
+ mi->key = key;
+ mi->name = name;
+ mi->desc = desc;
+
+ if (!ask->data.menu.first)
+ ask->data.menu.first = mi;
+ else {
+ struct ask_menuitem *last = ask->data.menu.first;
+
+ while (last->next)
+ last = last->next;
+ last->next = mi;
+ }
+
+ DBG(ASK, dbgprint("new menu item: %c, \"%s\" (%s)\n", mi->key, mi->name, mi->desc));
+ return 0;
+}
+
+
+/*
+ * print-like
+ */
+
#define is_print_ask(a) (fdisk_is_ask(a, WARN) || fdisk_is_ask(a, WARNX) || fdisk_is_ask(a, INFO))
int fdisk_ask_print_get_errno(struct fdisk_ask *ask)
diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c
index 1beeb6573..01e203268 100644
--- a/libfdisk/src/dos.c
+++ b/libfdisk/src/dos.c
@@ -826,9 +826,13 @@ static int get_start_from_user( struct fdisk_context *cxt,
*start = dflt;
else if (pa && pa->start) {
+ DBG(LABEL, dbgprint("DOS: start: wanted=%ju, low=%ju, limit=%ju",
+ (uintmax_t) pa->start, (uintmax_t) low, (uintmax_t) limit));
*start = pa->start;
- if (*start < low || *start > limit)
+ if (*start < low || *start > limit) {
+ fdisk_warnx(cxt, _("Start sector out of range."));
return -ERANGE;
+ }
} else {
/* ask user by dialog */
struct fdisk_ask *ask = fdisk_new_ask();
@@ -875,7 +879,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
DBG(LABEL, dbgprint("DOS: adding partition %zu", n));
- sys = pa ? pa->type->type : MBR_LINUX_DATA_PARTITION;
+ sys = pa && pa->type ? pa->type->type : MBR_LINUX_DATA_PARTITION;
if (is_used_partition(p)) {
fdisk_warnx(cxt, _("Partition %zu is already defined. "
@@ -984,8 +988,6 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
stop = limit;
else if (pa && pa->size) {
stop = start + pa->size;
- if (stop > limit)
- return -ERANGE;
isrel = 1;
} else {
/* ask user by dialog */
@@ -1296,6 +1298,8 @@ static int dos_add_partition(struct fdisk_context *cxt,
assert(cxt->label);
assert(fdisk_is_disklabel(cxt, DOS));
+ /* TODO: use pa->type */
+
for (i = 0; i < 4; i++) {
struct dos_partition *p = self_partition(cxt, i);
free_primary += !is_used_partition(p);
@@ -1327,31 +1331,34 @@ static int dos_add_partition(struct fdisk_context *cxt,
if (j >= 0)
rc = add_partition(cxt, j, pa);
} else {
- char *buf;
- char c, prompt[BUFSIZ];
- int dflt;
-
- dflt = (free_primary == 1 && !l->ext_offset) ? 'e' : 'p';
-
- snprintf(prompt, sizeof(prompt),
- _("Partition type:\n"
- " p primary (%zu primary, %d extended, %zu free)\n"
- "%s\n"
- "Select (default %c)"),
- 4 - (l->ext_offset ? 1 : 0) - free_primary,
- l->ext_offset ? 1 : 0, free_primary,
- l->ext_offset ? _(" l logical (numbered from 5)") : _(" e extended"),
- dflt);
-
- rc = fdisk_ask_string(cxt, prompt, &buf);
+ char hint[BUFSIZ];
+ struct fdisk_ask *ask;
+ int c;
+
+ ask = fdisk_new_ask();
+ if (!ask)
+ return -ENOMEM;
+ fdisk_ask_set_type(ask, FDISK_ASKTYPE_MENU);
+ fdisk_ask_set_query(ask, _("Partition type"));
+ fdisk_ask_menu_set_default(ask, free_primary == 1
+ && !l->ext_offset ? 'e' : 'p');
+ snprintf(hint, sizeof(hint),
+ _("%zu primary, %d extended, %zu free"),
+ 4 - (l->ext_offset ? 1 : 0) - free_primary,
+ l->ext_offset ? 1 : 0,
+ free_primary);
+
+ fdisk_ask_menu_add_item(ask, 'p', _("primary"), hint);
+ if (!l->ext_offset)
+ fdisk_ask_menu_add_item(ask, 'e', _("extended"), _("container for logical partitions"));
+ else
+ fdisk_ask_menu_add_item(ask, 'l', _("logical"), _("numbered from 5"));
+
+ rc = fdisk_do_ask(cxt, ask);
if (rc)
return rc;
- if (!buf[0]) {
- c = dflt;
- fdisk_info(cxt, _("Using default response %c."), c);
- } else
- c = tolower(buf[0]);
- free(buf);
+ fdisk_ask_menu_get_result(ask, &c);
+ fdisk_free_ask(ask);
if (c == 'p') {
int j = get_partition_unused_primary(cxt, pa);
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index 1db19b648..eb8b90bc9 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -322,6 +322,14 @@ extern struct fdisk_label *fdisk_new_sgi_label(struct fdisk_context *cxt);
extern struct fdisk_label *fdisk_new_sun_label(struct fdisk_context *cxt);
+struct ask_menuitem {
+ char key;
+ const char *name;
+ const char *desc;
+
+ struct ask_menuitem *next;
+};
+
/* fdisk dialog -- note that nothing from this stuff will be directly exported,
* we will have get/set() function for everything.
*/
@@ -356,6 +364,12 @@ struct fdisk_ask {
struct ask_string {
char *result; /* allocated */
} str;
+ /* FDISK_ASKTYPE_MENU */
+ struct ask_menu {
+ int dfl; /* default meni item */
+ int result;
+ struct ask_menuitem *first;
+ } menu;
} data;
};
@@ -380,6 +394,7 @@ struct fdisk_context {
/* alignment */
unsigned long grain; /* alignment unit */
sector_t first_lba; /* recommended begin of the first partition */
+ sector_t last_lba; /* recomennded end of last partition */
/* geometry */
sector_t total_sectors; /* in logical sectors */
diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h
index 8a9cc926e..fe1d290aa 100644
--- a/libfdisk/src/libfdisk.h
+++ b/libfdisk/src/libfdisk.h
@@ -55,7 +55,8 @@ enum {
FDISK_ASKTYPE_WARNX,
FDISK_ASKTYPE_INFO,
FDISK_ASKTYPE_YESNO,
- FDISK_ASKTYPE_STRING
+ FDISK_ASKTYPE_STRING,
+ FDISK_ASKTYPE_MENU
};
/* extra flags for info massages (see fdisk_sinfo() */
@@ -209,6 +210,10 @@ extern int fdisk_partition_next_partno(struct fdisk_partition *pa,
struct fdisk_context *cxt,
size_t *n);
+extern int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable);
+extern int fdisk_partition_start_follow_default(struct fdisk_partition *pa, int enable);
+extern int fdisk_partition_end_follow_default(struct fdisk_partition *pa, int enable);
+
/* table.c */
extern struct fdisk_table *fdisk_new_table(void);
extern int fdisk_reset_table(struct fdisk_table *tb);
@@ -374,6 +379,18 @@ extern int fdisk_ask_print_set_errno(struct fdisk_ask *ask, int errnum);
extern const char *fdisk_ask_print_get_mesg(struct fdisk_ask *ask);
extern int fdisk_ask_print_set_mesg(struct fdisk_ask *ask, const char *mesg);
+
+extern size_t fdisk_ask_menu_get_nitems(struct fdisk_ask *ask);
+extern int fdisk_ask_menu_set_default(struct fdisk_ask *ask, int dfl);
+extern int fdisk_ask_menu_get_default(struct fdisk_ask *ask);
+extern int fdisk_ask_menu_set_result(struct fdisk_ask *ask, int key);
+extern int fdisk_ask_menu_get_result(struct fdisk_ask *ask, int *key);
+extern int fdisk_ask_menu_get_item(struct fdisk_ask *ask, size_t idx, int *key,
+ const char **name, const char **desc);
+extern int fdisk_ask_menu_add_item(struct fdisk_ask *ask, int key,
+ const char *name, const char *desc);
+
+
#ifdef __cplusplus
}
#endif