]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libfdisk: add ASKTYPE_MENU and context last_lba
authorKarel Zak <kzak@redhat.com>
Wed, 29 Jan 2014 13:15:30 +0000 (14:15 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 11 Mar 2014 10:35:13 +0000 (11:35 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libfdisk/src/ask.c
libfdisk/src/dos.c
libfdisk/src/fdiskP.h
libfdisk/src/libfdisk.h

index 23e6263c6fba6056a2957ba9f8624226bad1bfa2..8647817afdef5ccf401854cb4aa71f8e314035b3 100644 (file)
@@ -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)
index 1beeb6573df1851d2f858990da64bf7e88b2b103..01e203268377cf9479e53471f5d6d77f102a7dd4 100644 (file)
@@ -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);
index 1db19b648bf2924cad4adeb7bae5b635a84e2a44..eb8b90bc9bbb860285c1159133fb9eb88990e70f 100644 (file)
@@ -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 */
index 8a9cc926ec5ebc6c9d23380c9db6dbc2c62b506b..fe1d290aaca8aae0aae93335b6574f8b3e9a3750 100644 (file)
@@ -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