]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: allow to exchange context pointer in menu callbacks
authorKarel Zak <kzak@redhat.com>
Wed, 10 Jul 2013 12:17:58 +0000 (14:17 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 16 Sep 2013 14:47:06 +0000 (16:47 +0200)
... to make it possible to switch to nested contexts (nested partition
tables).

Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/fdisk-menu.c
fdisks/fdisk.c
fdisks/fdisk.h

index c7f92b0c0fa11673f439618be54edd1864081e41..7bbca6f494c919306a4f4fa68d8ca471c83daa5e 100644 (file)
@@ -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);
 
index 0ca88894371993dd69514cb4b17de155e834f10e..f95266bd11622eb40ec6aefaece524d468a915d5 100644 (file)
@@ -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);
                }
index 9c40d314bfef7e777c80be2c77616fb85a5d06d6..05721bbd843ff4f1b0d4589480bd4896bbd88919 100644 (file)
@@ -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__)));