From d6b3ba417b043b76d651fa7e05f6209f12f5135b Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 10 Mar 2014 13:55:43 +0100 Subject: fdisk: merge fdisk-ask.c to fdisk.c Signed-off-by: Karel Zak --- fdisks/fdisk.c | 361 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) (limited to 'fdisks/fdisk.c') diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c index d2494ef9f..e003baf64 100644 --- a/fdisks/fdisk.c +++ b/fdisks/fdisk.c @@ -71,6 +71,367 @@ static void __attribute__ ((__noreturn__)) usage(FILE *out) exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } + + +int get_user_reply(struct fdisk_context *cxt, const 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, _("\nDo 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_menu(struct fdisk_context *cxt, struct fdisk_ask *ask, + char *buf, size_t bufsz) + +{ + const char *q = fdisk_ask_get_query(ask); + int dft = fdisk_ask_menu_get_default(ask); + + if (q) { + fputs(q, stdout); /* print header */ + fputc('\n', stdout); + } + + do { + char prompt[128]; + int key, c; + const char *name, *desc; + size_t i = 0; + + /* print menu items */ + while (fdisk_ask_menu_get_item(ask, i++, &key, &name, &desc) == 0) + fprintf(stdout, " %c %s (%s)\n", key, name, desc); + + /* ask for key */ + snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft); + get_user_reply(cxt, prompt, buf, bufsz); + if (!*buf) { + fdisk_info(cxt, _("Using default response %c."), dft); + c = dft; + } else + c = tolower(buf[0]); + + /* check result */ + i = 0; + while (fdisk_ask_menu_get_item(ask, i++, &key, NULL, NULL) == 0) { + if (c == key) { + fdisk_ask_menu_set_result(ask, c); + return 0; /* success */ + } + } + fdisk_warnx(cxt, _("Value out of range.")); + } while (1); + + return -EINVAL; +} + + +#define tochar(num) ((int) ('a' + num - 1)) +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_query(ask); + const char *range = fdisk_ask_number_get_range(ask); + + uint64_t dflt = fdisk_ask_number_get_default(ask), + low = fdisk_ask_number_get_low(ask), + high = fdisk_ask_number_get_high(ask); + int inchar = fdisk_ask_number_inchars(ask); + + assert(q); + + DBG(ASK, dbgprint("asking for number " + "['%s', <%ju,%ju>, default=%ju, range: %s]", + q, low, high, dflt, range)); + + if (range && dflt >= low && dflt <= high) { + if (inchar) + snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "), + q, range, tochar(dflt)); + else + snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), + q, range, dflt); + + } else if (dflt >= low && dflt <= high) { + if (inchar) + snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "), + q, tochar(low), tochar(high), tochar(dflt)); + else + snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), + q, low, high, dflt); + } else if (inchar) + snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "), + q, tochar(low), tochar(high)); + else + snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), + q, low, high); + + do { + int rc = get_user_reply(cxt, prompt, buf, bufsz); + uint64_t num; + + if (rc) + return rc; + if (!*buf && dflt >= low && dflt <= high) + return fdisk_ask_number_set_result(ask, dflt); + + if (isdigit_string(buf)) { + char *end; + + errno = 0; + num = strtoumax(buf, &end, 10); + if (errno || buf == end || (end && *end)) + continue; + } else if (inchar && isalpha(*buf)) { + num = tolower(*buf) - 'a' + 1; + } else + rc = -EINVAL; + + if (rc == 0 && num >= low && num <= high) + return fdisk_ask_number_set_result(ask, num); + + fdisk_warnx(cxt, _("Value out of range.")); + } while (1); + + return -1; +} + +static int ask_offset(struct fdisk_context *cxt, + struct fdisk_ask *ask, + char *buf, size_t bufsz) +{ + char prompt[128] = { '\0' }; + const char *q = fdisk_ask_get_query(ask); + const char *range = fdisk_ask_number_get_range(ask); + + uint64_t dflt = fdisk_ask_number_get_default(ask), + low = fdisk_ask_number_get_low(ask), + high = fdisk_ask_number_get_high(ask), + base = fdisk_ask_number_get_base(ask); + + assert(q); + + DBG(ASK, dbgprint("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]", + q, low, high, base, dflt, range)); + + if (range && dflt >= low && dflt <= high) + snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt); + else if (dflt >= low && dflt <= high) + snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt); + else + snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high); + + do { + uint64_t num = 0; + char sig = 0, *p; + int pwr = 0; + + int rc = get_user_reply(cxt, prompt, buf, bufsz); + if (rc) + return rc; + if (!*buf && dflt >= low && dflt <= high) + return fdisk_ask_number_set_result(ask, dflt); + + p = buf; + if (*p == '+' || *p == '-') { + sig = *buf; + p++; + } + + rc = parse_size(p, &num, &pwr); + if (rc) + continue; + DBG(ASK, dbgprint("parsed size: %ju", num)); + if (sig && pwr) { + /* +{size}{K,M,...} specified, the "num" is in bytes */ + uint64_t unit = fdisk_ask_number_get_unit(ask); + num += unit/2; /* round */ + num /= unit; + } + if (sig == '+') + num += base; + else if (sig == '-') + num = base - num; + + DBG(ASK, dbgprint("final offset: %ju [sig: %c, power: %d, %s]", + num, sig, pwr, + sig ? "relative" : "absolute")); + if (num >= low && num <= high) { + if (sig) + fdisk_ask_number_set_relative(ask, 1); + return fdisk_ask_number_set_result(ask, num); + } + fdisk_warnx(cxt, _("Value out of range.")); + } while (1); + + return -1; +} + +static unsigned int info_count; + +static void fputs_info(struct fdisk_ask *ask, FILE *out, char *buf, size_t bufsz) +{ + const char *msg; + unsigned int flags; + + assert(ask); + + msg = fdisk_ask_print_get_mesg(ask); + flags = fdisk_ask_get_flags(ask); + + if (!msg) + return; + if (info_count == 1) + fputc('\n', out); + if (flags == 0 || !colors_wanted()) + goto simple; + + if (flags & FDISK_INFO_COLON) { + size_t sz; + char *sep = _(": "); + char *p = strstr(msg, sep); + + if (!p) + goto simple; + + sz = strlen(sep); + strncpy(buf, msg, bufsz); + buf[p - msg + sz] = '\0'; + + color_enable(UL_COLOR_BROWN); + fputs(buf, out); + color_disable(); + fputs(p + sz, out); + + } else if (flags & FDISK_INFO_SUCCESS) { + color_enable(UL_COLOR_BOLD); + fputs(msg, out); + color_disable(); + } else { +simple: + fputs(msg, out); + } + fputc('\n', out); +} + +int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask, + void *data __attribute__((__unused__))) +{ + int rc = 0; + char buf[BUFSIZ]; + + assert(cxt); + assert(ask); + + if (fdisk_ask_get_type(ask) != FDISK_ASKTYPE_INFO) + info_count = 0; + + switch(fdisk_ask_get_type(ask)) { + case FDISK_ASKTYPE_MENU: + return ask_menu(cxt, ask, buf, sizeof(buf)); + case FDISK_ASKTYPE_NUMBER: + return ask_number(cxt, ask, buf, sizeof(buf)); + case FDISK_ASKTYPE_OFFSET: + return ask_offset(cxt, ask, buf, sizeof(buf)); + case FDISK_ASKTYPE_INFO: + info_count++; + fputs_info(ask, stdout, buf, sizeof(buf)); + break; + case FDISK_ASKTYPE_WARNX: + color_fenable(UL_COLOR_RED, stderr); + fputs(fdisk_ask_print_get_mesg(ask), stderr); + color_fdisable(stderr); + fputc('\n', stderr); + break; + case FDISK_ASKTYPE_WARN: + color_fenable(UL_COLOR_RED, stderr); + fputs(fdisk_ask_print_get_mesg(ask), stderr); + errno = fdisk_ask_print_get_errno(ask); + fprintf(stderr, ": %m\n"); + color_fdisable(stderr); + break; + case FDISK_ASKTYPE_YESNO: + fputc('\n', stdout); + fputs(fdisk_ask_get_query(ask), stdout); + rc = get_user_reply(cxt, _(" [Y]es/[N]o: "), buf, sizeof(buf)); + if (rc == 0) + fdisk_ask_yesno_set_result(ask, rpmatch(buf)); + DBG(ASK, dbgprint("yes-no ask: reply '%s' [rc=%d]", buf, rc)); + break; + case FDISK_ASKTYPE_STRING: + { + char prmt[BUFSIZ]; + snprintf(prmt, sizeof(prmt), "%s: ", fdisk_ask_get_query(ask)); + fputc('\n', stdout); + rc = get_user_reply(cxt, prmt, buf, sizeof(buf)); + if (rc == 0) + fdisk_ask_string_set_result(ask, xstrdup(buf)); + DBG(ASK, dbgprint("string ask: reply '%s' [rc=%d]", buf, rc)); + break; + } + default: + warnx(_("internal error: unsupported dialog type %d"), fdisk_ask_get_type(ask)); + return -EINVAL; + } + return rc; +} + +struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt) +{ + const char *q; + + if (!cxt || !cxt->label || !cxt->label->nparttypes) + return NULL; + + q = fdisk_is_parttype_string(cxt) ? + _("Partition type (type L to list all types): ") : + _("Hex code (type L to list all codes): "); + do { + char buf[256]; + int rc = get_user_reply(cxt, q, buf, sizeof(buf)); + + if (rc) + break; + + if (buf[1] == '\0' && toupper(*buf) == 'L') + list_partition_types(cxt); + else if (*buf) + return fdisk_parse_parttype(cxt, buf); + } while (1); + + return NULL; +} + void list_partition_types(struct fdisk_context *cxt) { struct fdisk_parttype *types; -- cgit v1.2.3-55-g7522