]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fdisk: add callback for ask-numbers API
authorKarel Zak <kzak@redhat.com>
Mon, 28 Jan 2013 15:16:11 +0000 (16:16 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 11 Mar 2013 12:00:54 +0000 (13:00 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/Makemodule.am
fdisks/fdisk-ask.c [new file with mode: 0644]
fdisks/fdisk.c
fdisks/fdisk.h
include/strutils.h
lib/strutils.c

index dcb48e52f0241282b183824299f535371b2c56fe..f9488c2211e89efb1f5bdbbe824fd41685b036d2 100644 (file)
@@ -7,6 +7,7 @@ fdisk_SOURCES = \
        fdisks/dos_part_types.h \
        fdisks/fdisk.c \
        fdisks/fdisk.h \
+       fdisks/fdisk-ask.c \
        fdisks/fdiskaixlabel.c \
        fdisks/fdiskaixlabel.h \
        fdisks/fdiskbsdlabel.c \
diff --git a/fdisks/fdisk-ask.c b/fdisks/fdisk-ask.c
new file mode 100644 (file)
index 0000000..ebfb404
--- /dev/null
@@ -0,0 +1,111 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "c.h"
+#include "strutils.h"
+#include "rpmatch.h"
+
+#include "fdisk.h"
+
+static int get_user_reply(struct fdisk_context *cxt, char *prompt,
+                         char *buf, size_t bufsz)
+{
+       char *p;
+       size_t sz;
+
+       do {
+               fputs(prompt, stdout);
+               fflush(stdout);
+
+               if (!fgets(buf, bufsz, stdin)) {
+                       if (fdisk_label_is_changed(cxt->label)) {
+                               fprintf(stderr, _("Do you really want to quit? "));
+
+                               if (fgets(buf, bufsz, stdin) && !rpmatch(buf))
+                                       continue;
+                       }
+                       fdisk_free_context(cxt);
+                       exit(EXIT_FAILURE);
+               } else
+                       break;
+       } while (1);
+
+       for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */
+
+       if (p > buf)
+               memmove(buf, p, p - buf);               /* remove blank space */
+       sz = strlen(buf);
+       if (sz && *(buf + sz - 1) == '\n')
+               *(buf + sz - 1) = '\0';
+
+       DBG(ASK, dbgprint("user's reply: >>>%s<<<", buf));
+       return 0;
+}
+
+static int ask_number(struct fdisk_context *cxt,
+                     struct fdisk_ask *ask,
+                     char *buf, size_t bufsz)
+{
+       char prompt[128] = { '\0' };
+       const char *q = fdisk_ask_get_question(ask);
+       const char *range = fdisk_ask_number_get_range(ask);
+
+       uint64_t dfl = fdisk_ask_number_get_default(ask),
+                low = fdisk_ask_number_get_low(ask),
+                hig = fdisk_ask_number_get_high(ask);
+
+       assert(q);
+
+       DBG(ASK, dbgprint("asking for number ['%s', <%jd,%jd>, default: %jd, range: %s]",
+                               q, low, hig, dfl, range));
+
+       if (range && dfl)
+               snprintf(prompt, sizeof(prompt), _("%s (%s, default %jd): "), q, range, dfl);
+       else if (dfl)
+               snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd, default %jd): "), q, low, hig, dfl);
+       else
+               snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd): "), q, low, hig);
+
+       do {
+               uint64_t num;
+               int rc = get_user_reply(cxt, prompt, buf, bufsz);
+               if (rc)
+                       return rc;
+
+               if (!*buf && dfl)
+                       return fdisk_ask_number_set_result(ask, dfl);
+               else if (isdigit_string(buf)) {
+                       char *end;
+                       errno = 0;
+                       num = strtoumax(buf, &end, 10);
+                       if (errno || buf == end || (end && *end))
+                               continue;
+                       if (num >= low && num <= hig)
+                               return fdisk_ask_number_set_result(ask, num);
+                       printf(_("Value out of range.\n"));
+               }
+       } while (1);
+
+       return -1;
+}
+
+int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
+                   void *data __attribute__((__unused__)))
+{
+       char buf[BUFSIZ];
+
+       assert(cxt);
+       assert(ask);
+
+       switch(fdisk_ask_get_type(ask)) {
+       case FDISK_ASKTYPE_NUMBER:
+               return ask_number(cxt, ask, buf, sizeof(buf));
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
index 094b7e0f6056ebc65ecccd3e2fdaf9047088f74b..453583ee190d51123e31fa7d51c7bc9f3b953769 100644 (file)
@@ -752,19 +752,13 @@ void print_partition_size(struct fdisk_context *cxt,
 
 static void new_partition(struct fdisk_context *cxt)
 {
-       int partnum = 0;
-
        assert(cxt);
        assert(cxt->label);
 
        if (warn_geometry(cxt))
                return;
 
-       if (!(cxt->label->flags & FDISK_LABEL_FL_ADDPART_NOPARTNO))
-               partnum = get_partition_dflt(cxt, 0, cxt->label->nparts_max,
-                               cxt->label->nparts_cur + 1);
-
-       fdisk_add_partition(cxt, partnum, NULL);
+       fdisk_add_partition(cxt, NULL);
 }
 
 static void write_table(struct fdisk_context *cxt)
@@ -1197,6 +1191,8 @@ int main(int argc, char **argv)
        if (!cxt)
                err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
 
+       fdisk_context_set_ask(cxt, ask_callback, NULL);
+
        while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) {
                switch (c) {
                case 'b':
index e337aefd2645a442d6b5c0acbcfde6ae8ed07774..627b0d91fdfe1289606d5cc74146273043dd61b2 100644 (file)
@@ -60,6 +60,10 @@ enum failure {
        unable_to_write
 };
 
+
+extern int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
+                   void *data __attribute__((__unused__)));
+
 /* prototypes for fdisk.c */
 extern char *line_ptr;
 extern unsigned int display_in_cyl_units, units_per_sector;
index 00598cf622d97424bb61c7efe774d91b49c96d23..38eb1ce6a6df3de6eee751af37e001b69412fa1b 100644 (file)
@@ -28,6 +28,8 @@ extern double strtod_or_err(const char *str, const char *errmesg);
 extern long strtol_or_err(const char *str, const char *errmesg);
 extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
 
+extern int isdigit_string(const char *str);
+
 #ifndef HAVE_MEMPCPY
 extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
 #endif
index 2337b07b96d03c77c5959216420074de016f8b85..8e8ab2f3709e0a5a8ef53cd6b038cc587a21c35b 100644 (file)
@@ -132,6 +132,16 @@ err:
        return -1;
 }
 
+int isdigit_string(const char *str)
+{
+       const char *p;
+
+       for (p = str; p && *p && isdigit((unsigned char) *p); p++);
+
+       return p && p > str && !*p;
+}
+
+
 #ifndef HAVE_MEMPCPY
 void *mempcpy(void *restrict dest, const void *restrict src, size_t n)
 {