summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fdisks/fdisk-menu.c53
-rw-r--r--fdisks/fdisk.c12
-rw-r--r--fdisks/fdisk.h2
3 files changed, 47 insertions, 20 deletions
diff --git a/fdisks/fdisk-menu.c b/fdisks/fdisk-menu.c
index c7f92b0c0..7bbca6f49 100644
--- a/fdisks/fdisk-menu.c
+++ b/fdisks/fdisk-menu.c
@@ -31,7 +31,7 @@ struct menu {
enum fdisk_labeltype label; /* only for this label */
enum fdisk_labeltype exclude; /* all labels except this */
- int (*callback)(struct fdisk_context *,
+ int (*callback)(struct fdisk_context **,
const struct menu *,
const struct menu_entry *);
@@ -45,7 +45,7 @@ struct menu_context {
#define MENU_CXT_EMPTY { 0, 0 }
#define DECLARE_MENU_CB(x) \
- static int x(struct fdisk_context *, \
+ static int x(struct fdisk_context **, \
const struct menu *, \
const struct menu_entry *)
@@ -199,7 +199,7 @@ struct menu menu_dos = {
};
struct menu menu_bsd = {
-/* .callback = bsd_menu_cb, */
+/* .callback = bsd_menu_cb,*/
.label = FDISK_DISKLABEL_OSF,
.entries = {
MENU_SEP(N_("BSD")),
@@ -339,12 +339,16 @@ int print_fdisk_menu(struct fdisk_context *cxt)
* returns the command key if no callback for the command is
* implemented.
*
+ * Note that this function might exchange the context pointer to
+ * switch to another (nested) context.
+ *
* Returns: <0 on error
* 0 on success (the command performed)
* >0 if no callback (then returns the key)
*/
-int process_fdisk_menu(struct fdisk_context *cxt)
+int process_fdisk_menu(struct fdisk_context **cxt0)
{
+ struct fdisk_context *cxt = *cxt0;
const struct menu_entry *ent;
const struct menu *menu;
int key, rc;
@@ -368,19 +372,23 @@ int process_fdisk_menu(struct fdisk_context *cxt)
return -EINVAL;
}
+ rc = 0;
DBG(FRONTEND, dbgprint("selected: key=%c, entry='%s'",
key, ent->title));
/* hardcoded help */
- if (key == 'm') {
+ if (key == 'm')
print_fdisk_menu(cxt);
- return 0;
/* menu has implemented callback, use it */
- } else if (menu->callback)
- return menu->callback(cxt, menu, ent);
+ else if (menu->callback)
+ rc = menu->callback(cxt0, menu, ent);
+ else {
+ DBG(FRONTEND, dbgprint("no callback, return key '%c'", key));
+ return key;
+ }
- /* no callback, return the key */
- return key;
+ DBG(FRONTEND, dbgprint("process menu done [rc=%d]", rc));
+ return rc;
}
@@ -388,10 +396,11 @@ int process_fdisk_menu(struct fdisk_context *cxt)
* This is fdisk frontend for GPT specific libfdisk functions that
* are not expported by generic libfdisk API.
*/
-static int gpt_menu_cb(struct fdisk_context *cxt,
+static int gpt_menu_cb(struct fdisk_context **cxt0,
const struct menu *menu __attribute__((__unused__)),
const struct menu_entry *ent)
{
+ struct fdisk_context *cxt = *cxt0;
size_t n;
int rc;
@@ -424,12 +433,15 @@ static int gpt_menu_cb(struct fdisk_context *cxt,
* This is fdisk frontend for MBR specific libfdisk functions that
* are not expported by generic libfdisk API.
*/
-static int dos_menu_cb(struct fdisk_context *cxt,
+static int dos_menu_cb(struct fdisk_context **cxt0,
const struct menu *menu __attribute__((__unused__)),
const struct menu_entry *ent)
{
+ struct fdisk_context *cxt = *cxt0;
int rc = 0;
+ DBG(FRONTEND, dbgprint("enter DOS menu"));
+
if (!ent->expert) {
switch (ent->key) {
case 'a':
@@ -448,9 +460,10 @@ static int dos_menu_cb(struct fdisk_context *cxt,
return -ENOMEM;
if (!fdisk_dev_has_disklabel(bsd))
rc = fdisk_create_disklabel(bsd, "bsd");
- if (!rc)
- bsd_command_prompt(bsd);
- fdisk_free_context(bsd);
+ if (rc)
+ fdisk_free_context(bsd);
+ else
+ *cxt0 = cxt = bsd;
break;
}
case 'c':
@@ -483,12 +496,15 @@ static int dos_menu_cb(struct fdisk_context *cxt,
return rc;
}
-static int sun_menu_cb(struct fdisk_context *cxt,
+static int sun_menu_cb(struct fdisk_context **cxt0,
const struct menu *menu __attribute__((__unused__)),
const struct menu_entry *ent)
{
+ struct fdisk_context *cxt = *cxt0;
int rc = 0;
+ DBG(FRONTEND, dbgprint("enter SUN menu"));
+
assert(cxt);
assert(ent);
assert(fdisk_is_disklabel(cxt, SUN));
@@ -535,13 +551,16 @@ static int sun_menu_cb(struct fdisk_context *cxt,
}
/* C/H/S commands */
-static int geo_menu_cb(struct fdisk_context *cxt,
+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;
int rc = -EINVAL;
uintmax_t c = 0, h = 0, s = 0;
+ DBG(FRONTEND, dbgprint("enter GEO menu"));
+
assert(cxt);
assert(ent);
diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c
index 0ca888943..f95266bd1 100644
--- a/fdisks/fdisk.c
+++ b/fdisks/fdisk.c
@@ -381,7 +381,7 @@ expert_command_prompt(struct fdisk_context *cxt)
while(1) {
assert(cxt->label);
- c = process_fdisk_menu(cxt);
+ c = process_fdisk_menu(&cxt);
if (c <= 0)
continue;
@@ -512,7 +512,7 @@ static void command_prompt(struct fdisk_context *cxt)
while (1) {
assert(cxt->label);
- c = process_fdisk_menu(cxt);
+ c = process_fdisk_menu(&cxt);
if (c <= 0)
continue;
@@ -588,6 +588,14 @@ static void command_prompt(struct fdisk_context *cxt)
case 'x':
expert_command_prompt(cxt);
break;
+ case 'r':
+ if (cxt->parent) {
+ struct fdisk_context *tmp = cxt->parent;
+
+ fdisk_free_context(cxt);
+ cxt = tmp;
+ }
+ break;
default:
unknown_command(c);
}
diff --git a/fdisks/fdisk.h b/fdisks/fdisk.h
index 9c40d314b..05721bbd8 100644
--- a/fdisks/fdisk.h
+++ b/fdisks/fdisk.h
@@ -25,7 +25,7 @@ extern int get_user_reply(struct fdisk_context *cxt,
const char *prompt,
char *buf, size_t bufsz);
extern int print_fdisk_menu(struct fdisk_context *cxt);
-extern int process_fdisk_menu(struct fdisk_context *cxt);
+extern int process_fdisk_menu(struct fdisk_context **cxt);
extern int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
void *data __attribute__((__unused__)));