diff options
-rw-r--r-- | fdisks/Makemodule.am | 1 | ||||
-rw-r--r-- | fdisks/fdisk-ask.c | 111 | ||||
-rw-r--r-- | fdisks/fdisk.c | 10 | ||||
-rw-r--r-- | fdisks/fdisk.h | 4 | ||||
-rw-r--r-- | include/strutils.h | 2 | ||||
-rw-r--r-- | lib/strutils.c | 10 |
6 files changed, 131 insertions, 7 deletions
diff --git a/fdisks/Makemodule.am b/fdisks/Makemodule.am index dcb48e52f..f9488c221 100644 --- a/fdisks/Makemodule.am +++ b/fdisks/Makemodule.am @@ -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 index 000000000..ebfb404bb --- /dev/null +++ b/fdisks/fdisk-ask.c @@ -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; +} diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c index 094b7e0f6..453583ee1 100644 --- a/fdisks/fdisk.c +++ b/fdisks/fdisk.c @@ -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': diff --git a/fdisks/fdisk.h b/fdisks/fdisk.h index e337aefd2..627b0d91f 100644 --- a/fdisks/fdisk.h +++ b/fdisks/fdisk.h @@ -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; diff --git a/include/strutils.h b/include/strutils.h index 00598cf62..38eb1ce6a 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -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 diff --git a/lib/strutils.c b/lib/strutils.c index 2337b07b9..8e8ab2f37 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -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) { |